sockbuf.c revision 1.1.1.3.12.1 1 /* $NetBSD: sockbuf.c,v 1.1.1.3.12.1 2014/08/19 23:51:59 tls Exp $ */
2
3 /* sockbuf.c - i/o routines with support for adding i/o layers. */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 1998-2014 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18
19 #include "portable.h"
20
21 #include <stdio.h>
22
23 #include <ac/stdlib.h>
24
25 #include <ac/ctype.h>
26 #include <ac/errno.h>
27 #include <ac/socket.h>
28 #include <ac/string.h>
29 #include <ac/unistd.h>
30
31 #ifdef HAVE_IO_H
32 #include <io.h>
33 #endif /* HAVE_IO_H */
34
35 #if defined( HAVE_FCNTL_H )
36 #include <fcntl.h>
37 #endif
38
39 #if defined( HAVE_SYS_FILIO_H )
40 #include <sys/filio.h>
41 #elif defined( HAVE_SYS_IOCTL_H )
42 #include <sys/ioctl.h>
43 #endif
44
45 #include "lber-int.h"
46
47 #ifndef LBER_MIN_BUFF_SIZE
48 #define LBER_MIN_BUFF_SIZE 4096
49 #endif
50 #ifndef LBER_MAX_BUFF_SIZE
51 #define LBER_MAX_BUFF_SIZE (65536*256)
52 #endif
53 #ifndef LBER_DEFAULT_READAHEAD
54 #define LBER_DEFAULT_READAHEAD 16384
55 #endif
56
57 Sockbuf *
58 ber_sockbuf_alloc( void )
59 {
60 Sockbuf *sb;
61
62 sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
63
64 if( sb == NULL ) return NULL;
65
66 ber_int_sb_init( sb );
67 return sb;
68 }
69
70 void
71 ber_sockbuf_free( Sockbuf *sb )
72 {
73 assert( sb != NULL );
74 assert( SOCKBUF_VALID( sb ) );
75
76 ber_int_sb_close( sb );
77 ber_int_sb_destroy( sb );
78 LBER_FREE( sb );
79 }
80
81 /* Return values: -1: error, 0: no operation performed or the answer is false,
82 * 1: successful operation or the answer is true
83 */
84 int
85 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
86 {
87 Sockbuf_IO_Desc *p;
88 int ret = 0;
89
90 assert( sb != NULL );
91 assert( SOCKBUF_VALID( sb ) );
92
93 switch ( opt ) {
94 case LBER_SB_OPT_HAS_IO:
95 p = sb->sb_iod;
96 while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
97 p = p->sbiod_next;
98 }
99
100 if ( p ) {
101 ret = 1;
102 }
103 break;
104
105 case LBER_SB_OPT_GET_FD:
106 if ( arg != NULL ) {
107 *((ber_socket_t *)arg) = sb->sb_fd;
108 }
109 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
110 break;
111
112 case LBER_SB_OPT_SET_FD:
113 sb->sb_fd = *((ber_socket_t *)arg);
114 ret = 1;
115 break;
116
117 case LBER_SB_OPT_SET_NONBLOCK:
118 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
119 ? -1 : 1;
120 break;
121
122 case LBER_SB_OPT_DRAIN: {
123 /* Drain the data source to enable possible errors (e.g.
124 * TLS) to be propagated to the upper layers
125 */
126 char buf[LBER_MIN_BUFF_SIZE];
127
128 do {
129 ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
130 } while ( ret == sizeof( buf ) );
131
132 ret = 1;
133 } break;
134
135 case LBER_SB_OPT_NEEDS_READ:
136 ret = ( sb->sb_trans_needs_read ? 1 : 0 );
137 break;
138
139 case LBER_SB_OPT_NEEDS_WRITE:
140 ret = ( sb->sb_trans_needs_write ? 1 : 0 );
141 break;
142
143 case LBER_SB_OPT_GET_MAX_INCOMING:
144 if ( arg != NULL ) {
145 *((ber_len_t *)arg) = sb->sb_max_incoming;
146 }
147 ret = 1;
148 break;
149
150 case LBER_SB_OPT_SET_MAX_INCOMING:
151 sb->sb_max_incoming = *((ber_len_t *)arg);
152 ret = 1;
153 break;
154
155 case LBER_SB_OPT_UNGET_BUF:
156 #ifdef LDAP_PF_LOCAL_SENDMSG
157 sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
158 if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
159 AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
160 sb->sb_ungetlen );
161 ret = 1;
162 } else {
163 sb->sb_ungetlen = 0;
164 ret = -1;
165 }
166 #endif
167 break;
168
169 default:
170 ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
171 break;
172 }
173
174 return ret;
175 }
176
177 int
178 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
179 {
180 Sockbuf_IO_Desc *d, *p, **q;
181
182 assert( sb != NULL );
183 assert( SOCKBUF_VALID( sb ) );
184
185 if ( sbio == NULL ) {
186 return -1;
187 }
188
189 q = &sb->sb_iod;
190 p = *q;
191 while ( p && p->sbiod_level > layer ) {
192 q = &p->sbiod_next;
193 p = *q;
194 }
195
196 d = LBER_MALLOC( sizeof( *d ) );
197 if ( d == NULL ) {
198 return -1;
199 }
200
201 d->sbiod_level = layer;
202 d->sbiod_sb = sb;
203 d->sbiod_io = sbio;
204 memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
205 d->sbiod_next = p;
206 *q = d;
207
208 if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
209 return -1;
210 }
211
212 return 0;
213 }
214
215 int
216 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
217 {
218 Sockbuf_IO_Desc *p, **q;
219
220 assert( sb != NULL );
221 assert( SOCKBUF_VALID( sb ) );
222
223 if ( sb->sb_iod == NULL ) {
224 return -1;
225 }
226
227 q = &sb->sb_iod;
228 while ( *q != NULL ) {
229 p = *q;
230 if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
231 if ( p->sbiod_io->sbi_remove != NULL &&
232 p->sbiod_io->sbi_remove( p ) < 0 )
233 {
234 return -1;
235 }
236 *q = p->sbiod_next;
237 LBER_FREE( p );
238 break;
239 }
240 q = &p->sbiod_next;
241 }
242
243 return 0;
244 }
245
246 void
247 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
248 {
249 buf->buf_base = NULL;
250 buf->buf_ptr = 0;
251 buf->buf_end = 0;
252 buf->buf_size = 0;
253 }
254
255 void
256 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
257 {
258 assert( buf != NULL);
259
260 if (buf->buf_base) {
261 LBER_FREE( buf->buf_base );
262 }
263 ber_pvt_sb_buf_init( buf );
264 }
265
266 int
267 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
268 {
269 ber_len_t pw;
270 char *p;
271
272 assert( buf != NULL );
273
274 for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
275 if (pw > LBER_MAX_BUFF_SIZE) return -1;
276 }
277
278 if ( buf->buf_size < pw ) {
279 p = LBER_REALLOC( buf->buf_base, pw );
280 if ( p == NULL ) return -1;
281 buf->buf_base = p;
282 buf->buf_size = pw;
283 }
284 return 0;
285 }
286
287 ber_len_t
288 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
289 {
290 ber_len_t max;
291
292 assert( buf != NULL );
293 assert( sbb != NULL );
294 #if 0
295 assert( sbb->buf_size > 0 );
296 #endif
297
298 max = sbb->buf_end - sbb->buf_ptr;
299 max = ( max < len) ? max : len;
300 if ( max ) {
301 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
302 sbb->buf_ptr += max;
303 if ( sbb->buf_ptr >= sbb->buf_end ) {
304 sbb->buf_ptr = sbb->buf_end = 0;
305 }
306 }
307 return max;
308 }
309
310 ber_slen_t
311 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
312 {
313 ber_len_t to_go;
314 ber_slen_t ret;
315
316 assert( sbiod != NULL );
317 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
318
319 to_go = buf_out->buf_end - buf_out->buf_ptr;
320 assert( to_go > 0 );
321
322 for(;;) {
323 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
324 buf_out->buf_ptr, to_go );
325 #ifdef EINTR
326 if ((ret<0) && (errno==EINTR)) continue;
327 #endif
328 break;
329 }
330
331 if ( ret <= 0 ) return ret;
332
333 buf_out->buf_ptr += ret;
334 if (buf_out->buf_ptr == buf_out->buf_end) {
335 buf_out->buf_end = buf_out->buf_ptr = 0;
336 }
337
338 return ret;
339 }
340
341 int
342 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
343 {
344 #ifdef HAVE_FCNTL
345 int flags = fcntl( sd, F_GETFL);
346 if( nb ) {
347 flags |= O_NONBLOCK;
348 } else {
349 flags &= ~O_NONBLOCK;
350 }
351 return fcntl( sd, F_SETFL, flags );
352
353 #elif defined( FIONBIO )
354 ioctl_t status = nb ? 1 : 0;
355 return ioctl( sd, FIONBIO, &status );
356 #endif
357 }
358
359 int
360 ber_int_sb_init( Sockbuf *sb )
361 {
362 assert( sb != NULL);
363
364 sb->sb_valid=LBER_VALID_SOCKBUF;
365 sb->sb_options = 0;
366 sb->sb_debug = ber_int_debug;
367 sb->sb_fd = AC_SOCKET_INVALID;
368 sb->sb_iod = NULL;
369 sb->sb_trans_needs_read = 0;
370 sb->sb_trans_needs_write = 0;
371
372 assert( SOCKBUF_VALID( sb ) );
373 return 0;
374 }
375
376 int
377 ber_int_sb_close( Sockbuf *sb )
378 {
379 Sockbuf_IO_Desc *p;
380
381 assert( sb != NULL);
382
383 p = sb->sb_iod;
384 while ( p ) {
385 if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) {
386 return -1;
387 }
388 p = p->sbiod_next;
389 }
390
391 sb->sb_fd = AC_SOCKET_INVALID;
392
393 return 0;
394 }
395
396 int
397 ber_int_sb_destroy( Sockbuf *sb )
398 {
399 Sockbuf_IO_Desc *p;
400
401 assert( sb != NULL);
402 assert( SOCKBUF_VALID( sb ) );
403
404 while ( sb->sb_iod ) {
405 p = sb->sb_iod->sbiod_next;
406 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
407 sb->sb_iod->sbiod_level );
408 sb->sb_iod = p;
409 }
410
411 return ber_int_sb_init( sb );
412 }
413
414 ber_slen_t
415 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
416 {
417 ber_slen_t ret;
418
419 assert( buf != NULL );
420 assert( sb != NULL);
421 assert( sb->sb_iod != NULL );
422 assert( SOCKBUF_VALID( sb ) );
423
424 for (;;) {
425 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
426
427 #ifdef EINTR
428 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
429 #endif
430 break;
431 }
432
433 return ret;
434 }
435
436 ber_slen_t
437 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
438 {
439 ber_slen_t ret;
440
441 assert( buf != NULL );
442 assert( sb != NULL);
443 assert( sb->sb_iod != NULL );
444 assert( SOCKBUF_VALID( sb ) );
445
446 for (;;) {
447 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
448
449 #ifdef EINTR
450 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
451 #endif
452 break;
453 }
454
455 return ret;
456 }
457
458 /*
459 * Support for TCP
460 */
461
462 static ber_slen_t
463 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
464 {
465 assert( sbiod != NULL);
466 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
467
468 #if defined(MACOS)
469 /*
470 * MacTCP/OpenTransport
471 */
472 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
473 len, NULL );
474
475 #elif defined( HAVE_PCNFS ) || \
476 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
477 /*
478 * PCNFS (under DOS)
479 */
480 /*
481 * Windows Socket API (under DOS/Windows 3.x)
482 */
483 /*
484 * 32-bit Windows Socket API (under Windows NT or Windows 95)
485 */
486 return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
487
488 #elif defined( HAVE_NCSA )
489 /*
490 * NCSA Telnet TCP/IP stack (under DOS)
491 */
492 return nread( sbiod->sbiod_sb->sb_fd, buf, len );
493
494 #else
495 return read( sbiod->sbiod_sb->sb_fd, buf, len );
496 #endif
497 }
498
499 static ber_slen_t
500 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
501 {
502 assert( sbiod != NULL);
503 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
504
505 #if defined(MACOS)
506 /*
507 * MacTCP/OpenTransport
508 */
509 #define MAX_WRITE 65535
510 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
511 (len<MAX_WRITE) ? len : MAX_WRITE );
512
513 #elif defined( HAVE_PCNFS) \
514 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
515 /*
516 * PCNFS (under DOS)
517 */
518 /*
519 * Windows Socket API (under DOS/Windows 3.x)
520 */
521 /*
522 * 32-bit Windows Socket API (under Windows NT or Windows 95)
523 */
524 return send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
525
526 #elif defined(HAVE_NCSA)
527 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
528
529 #elif defined(VMS)
530 /*
531 * VMS -- each write must be 64K or smaller
532 */
533 #define MAX_WRITE 65535
534 return write( sbiod->sbiod_sb->sb_fd, buf,
535 (len<MAX_WRITE) ? len : MAX_WRITE);
536 #else
537 return write( sbiod->sbiod_sb->sb_fd, buf, len );
538 #endif
539 }
540
541 static int
542 sb_stream_close( Sockbuf_IO_Desc *sbiod )
543 {
544 assert( sbiod != NULL );
545 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
546 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
547 tcp_close( sbiod->sbiod_sb->sb_fd );
548 return 0;
549 }
550
551 /* The argument is a pointer to the socket descriptor */
552 static int
553 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
554 assert( sbiod != NULL );
555
556 if ( arg != NULL ) {
557 sbiod->sbiod_sb->sb_fd = *((int *)arg);
558 }
559 return 0;
560 }
561
562 static int
563 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
564 /* This is an end IO descriptor */
565 return 0;
566 }
567
568 Sockbuf_IO ber_sockbuf_io_tcp = {
569 sb_stream_setup, /* sbi_setup */
570 NULL, /* sbi_remove */
571 sb_stream_ctrl, /* sbi_ctrl */
572 sb_stream_read, /* sbi_read */
573 sb_stream_write, /* sbi_write */
574 sb_stream_close /* sbi_close */
575 };
576
577
578 /*
579 * Support for readahead (UDP needs it)
580 */
581
582 static int
583 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
584 {
585 Sockbuf_Buf *p;
586
587 assert( sbiod != NULL );
588
589 p = LBER_MALLOC( sizeof( *p ) );
590 if ( p == NULL ) return -1;
591
592 ber_pvt_sb_buf_init( p );
593
594 if ( arg == NULL ) {
595 ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD );
596 } else {
597 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
598 }
599
600 sbiod->sbiod_pvt = p;
601 return 0;
602 }
603
604 static int
605 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
606 {
607 Sockbuf_Buf *p;
608
609 assert( sbiod != NULL );
610
611 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
612
613 if ( p->buf_ptr != p->buf_end ) return -1;
614
615 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
616 LBER_FREE( sbiod->sbiod_pvt );
617 sbiod->sbiod_pvt = NULL;
618
619 return 0;
620 }
621
622 static ber_slen_t
623 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
624 {
625 Sockbuf_Buf *p;
626 ber_slen_t bufptr = 0, ret, max;
627
628 assert( sbiod != NULL );
629 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
630 assert( sbiod->sbiod_next != NULL );
631
632 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
633
634 assert( p->buf_size > 0 );
635
636 /* Are there anything left in the buffer? */
637 ret = ber_pvt_sb_copy_out( p, buf, len );
638 bufptr += ret;
639 len -= ret;
640
641 if ( len == 0 ) return bufptr;
642
643 max = p->buf_size - p->buf_end;
644 ret = 0;
645 while ( max > 0 ) {
646 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
647 max );
648 #ifdef EINTR
649 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
650 #endif
651 break;
652 }
653
654 if ( ret < 0 ) {
655 return ( bufptr ? bufptr : ret );
656 }
657
658 p->buf_end += ret;
659 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
660 return bufptr;
661 }
662
663 static ber_slen_t
664 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
665 {
666 assert( sbiod != NULL );
667 assert( sbiod->sbiod_next != NULL );
668
669 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
670 }
671
672 static int
673 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
674 {
675 assert( sbiod != NULL );
676
677 /* Just erase the buffer */
678 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
679 return 0;
680 }
681
682 static int
683 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
684 {
685 Sockbuf_Buf *p;
686
687 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
688
689 if ( opt == LBER_SB_OPT_DATA_READY ) {
690 if ( p->buf_ptr != p->buf_end ) {
691 return 1;
692 }
693
694 } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
695 if ( p->buf_size >= *((ber_len_t *)arg) ) {
696 return 0;
697 }
698 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
699 -1 : 1 );
700 }
701
702 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
703 }
704
705 Sockbuf_IO ber_sockbuf_io_readahead = {
706 sb_rdahead_setup, /* sbi_setup */
707 sb_rdahead_remove, /* sbi_remove */
708 sb_rdahead_ctrl, /* sbi_ctrl */
709 sb_rdahead_read, /* sbi_read */
710 sb_rdahead_write, /* sbi_write */
711 sb_rdahead_close /* sbi_close */
712 };
713
714 /*
715 * Support for simple file IO
716 */
717
718 static ber_slen_t
719 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
720 {
721 assert( sbiod != NULL);
722 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
723
724 #ifdef LDAP_PF_LOCAL_SENDMSG
725 if ( sbiod->sbiod_sb->sb_ungetlen ) {
726 ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
727 if ( blen > len )
728 blen = len;
729 AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
730 buf = (char *) buf + blen;
731 len -= blen;
732 sbiod->sbiod_sb->sb_ungetlen -= blen;
733 if ( sbiod->sbiod_sb->sb_ungetlen ) {
734 AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
735 sbiod->sbiod_sb->sb_ungetbuf+blen,
736 sbiod->sbiod_sb->sb_ungetlen );
737 }
738 if ( len == 0 )
739 return blen;
740 }
741 #endif
742 return read( sbiod->sbiod_sb->sb_fd, buf, len );
743 }
744
745 static ber_slen_t
746 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
747 {
748 assert( sbiod != NULL);
749 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
750
751 return write( sbiod->sbiod_sb->sb_fd, buf, len );
752 }
753
754 static int
755 sb_fd_close( Sockbuf_IO_Desc *sbiod )
756 {
757 assert( sbiod != NULL );
758 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
759
760 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
761 close( sbiod->sbiod_sb->sb_fd );
762 return 0;
763 }
764
765 /* The argument is a pointer to the file descriptor */
766 static int
767 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
768 assert( sbiod != NULL );
769
770 if ( arg != NULL )
771 sbiod->sbiod_sb->sb_fd = *((int *)arg);
772 return 0;
773 }
774
775 static int
776 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
777 /* This is an end IO descriptor */
778 return 0;
779 }
780
781 Sockbuf_IO ber_sockbuf_io_fd = {
782 sb_fd_setup, /* sbi_setup */
783 NULL, /* sbi_remove */
784 sb_fd_ctrl, /* sbi_ctrl */
785 sb_fd_read, /* sbi_read */
786 sb_fd_write, /* sbi_write */
787 sb_fd_close /* sbi_close */
788 };
789
790 /*
791 * Debugging layer
792 */
793
794 static int
795 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
796 {
797 assert( sbiod != NULL );
798
799 if ( arg == NULL ) arg = "sockbuf_";
800
801 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
802 if ( sbiod->sbiod_pvt == NULL ) return -1;
803
804 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
805 return 0;
806 }
807
808 static int
809 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
810 {
811 assert( sbiod != NULL );
812 assert( sbiod->sbiod_pvt != NULL );
813
814 LBER_FREE( sbiod->sbiod_pvt );
815 sbiod->sbiod_pvt = NULL;
816 return 0;
817 }
818
819 static int
820 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
821 {
822 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
823 }
824
825 static ber_slen_t
826 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
827 {
828 ber_slen_t ret;
829 char ebuf[128];
830
831 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
832 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
833 int err = sock_errno();
834 if ( ret < 0 ) {
835 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
836 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
837 (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
838 } else {
839 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
840 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
841 (long)len, (long)ret );
842 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
843 (const char *)buf, ret );
844 }
845 sock_errset(err);
846 }
847 return ret;
848 }
849
850 static ber_slen_t
851 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
852 {
853 ber_slen_t ret;
854 char ebuf[128];
855
856 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
857 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
858 int err = sock_errno();
859 if ( ret < 0 ) {
860 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
861 "%swrite: want=%ld error=%s\n",
862 (char *)sbiod->sbiod_pvt, (long)len,
863 AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
864 } else {
865 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
866 "%swrite: want=%ld, written=%ld\n",
867 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
868 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
869 (const char *)buf, ret );
870 }
871 sock_errset(err);
872 }
873
874 return ret;
875 }
876
877 Sockbuf_IO ber_sockbuf_io_debug = {
878 sb_debug_setup, /* sbi_setup */
879 sb_debug_remove, /* sbi_remove */
880 sb_debug_ctrl, /* sbi_ctrl */
881 sb_debug_read, /* sbi_read */
882 sb_debug_write, /* sbi_write */
883 NULL /* sbi_close */
884 };
885
886 #ifdef LDAP_CONNECTIONLESS
887
888 /*
889 * Support for UDP (CLDAP)
890 *
891 * All I/O at this level must be atomic. For ease of use, the sb_readahead
892 * must be used above this module. All data reads and writes are prefixed
893 * with a sockaddr_storage containing the address of the remote entity. Upper levels
894 * must read and write this sockaddr_storage before doing the usual ber_printf/scanf
895 * operations on LDAP messages.
896 */
897
898 static int
899 sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
900 {
901 assert( sbiod != NULL);
902 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
903
904 if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg);
905 return 0;
906 }
907
908 static ber_slen_t
909 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
910 {
911 ber_slen_t rc;
912 ber_socklen_t addrlen;
913 struct sockaddr *src;
914
915 assert( sbiod != NULL );
916 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
917 assert( buf != NULL );
918
919 addrlen = sizeof( struct sockaddr_storage );
920 src = buf;
921 buf = (char *) buf + addrlen;
922 len -= addrlen;
923 rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
924
925 return rc > 0 ? rc+sizeof(struct sockaddr_storage) : rc;
926 }
927
928 static ber_slen_t
929 sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
930 {
931 ber_slen_t rc;
932 struct sockaddr *dst;
933
934 assert( sbiod != NULL );
935 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
936 assert( buf != NULL );
937
938 dst = buf;
939 buf = (char *) buf + sizeof( struct sockaddr_storage );
940 len -= sizeof( struct sockaddr_storage );
941
942 rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
943 sizeof( struct sockaddr_storage ) );
944
945 if ( rc < 0 ) return -1;
946
947 /* fake error if write was not atomic */
948 if (rc < len) {
949 # ifdef EMSGSIZE
950 errno = EMSGSIZE;
951 # endif
952 return -1;
953 }
954 rc = len + sizeof(struct sockaddr_storage);
955 return rc;
956 }
957
958 static int
959 sb_dgram_close( Sockbuf_IO_Desc *sbiod )
960 {
961 assert( sbiod != NULL );
962 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
963
964 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
965 tcp_close( sbiod->sbiod_sb->sb_fd );
966 return 0;
967 }
968
969 static int
970 sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
971 {
972 /* This is an end IO descriptor */
973 return 0;
974 }
975
976 Sockbuf_IO ber_sockbuf_io_udp =
977 {
978 sb_dgram_setup, /* sbi_setup */
979 NULL, /* sbi_remove */
980 sb_dgram_ctrl, /* sbi_ctrl */
981 sb_dgram_read, /* sbi_read */
982 sb_dgram_write, /* sbi_write */
983 sb_dgram_close /* sbi_close */
984 };
985
986 #endif /* LDAP_CONNECTIONLESS */
987