include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / libs / ldap / liblber / sockbuf.c
blob915941a5d090f1ea08ca5f76281ff13df04e5a31
1 /* sockbuf.c - i/o routines with support for adding i/o layers. */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2022 The OpenLDAP Foundation.
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 #include "portable.h"
19 #include <stdio.h>
21 #include <ac/stdlib.h>
23 #include <ac/ctype.h>
24 #include <ac/errno.h>
25 #include <ac/socket.h>
26 #include <ac/string.h>
27 #include <ac/unistd.h>
29 #ifdef HAVE_IO_H
30 #include <io.h>
31 #endif /* HAVE_IO_H */
33 #if defined( HAVE_FCNTL_H )
34 #include <fcntl.h>
35 #endif
37 #if defined( HAVE_SYS_FILIO_H )
38 #include <sys/filio.h>
39 #elif defined( HAVE_SYS_IOCTL_H )
40 #include <sys/ioctl.h>
41 #endif
43 #include "lber-int.h"
45 #ifndef LBER_MIN_BUFF_SIZE
46 #define LBER_MIN_BUFF_SIZE 4096
47 #endif
48 #ifndef LBER_MAX_BUFF_SIZE
49 #define LBER_MAX_BUFF_SIZE (65536*256)
50 #endif
51 #ifndef LBER_DEFAULT_READAHEAD
52 #define LBER_DEFAULT_READAHEAD 16384
53 #endif
55 Sockbuf *
56 ber_sockbuf_alloc( void )
58 Sockbuf *sb;
60 sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
62 if( sb == NULL ) return NULL;
64 ber_int_sb_init( sb );
65 return sb;
68 void
69 ber_sockbuf_free( Sockbuf *sb )
71 assert( sb != NULL );
72 assert( SOCKBUF_VALID( sb ) );
74 ber_int_sb_close( sb );
75 ber_int_sb_destroy( sb );
76 LBER_FREE( sb );
79 /* Return values: -1: error, 0: no operation performed or the answer is false,
80 * 1: successful operation or the answer is true
82 int
83 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
85 Sockbuf_IO_Desc *p;
86 int ret = 0;
88 assert( sb != NULL );
89 assert( SOCKBUF_VALID( sb ) );
91 switch ( opt ) {
92 case LBER_SB_OPT_HAS_IO:
93 p = sb->sb_iod;
94 while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
95 p = p->sbiod_next;
98 if ( p ) {
99 ret = 1;
101 break;
103 case LBER_SB_OPT_GET_FD:
104 if ( arg != NULL ) {
105 *((ber_socket_t *)arg) = sb->sb_fd;
107 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
108 break;
110 case LBER_SB_OPT_SET_FD:
111 sb->sb_fd = *((ber_socket_t *)arg);
112 ret = 1;
113 break;
115 case LBER_SB_OPT_SET_NONBLOCK:
116 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
117 ? -1 : 1;
118 break;
120 case LBER_SB_OPT_DRAIN: {
121 /* Drain the data source to enable possible errors (e.g.
122 * TLS) to be propagated to the upper layers
124 char buf[LBER_MIN_BUFF_SIZE];
126 do {
127 ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
128 } while ( ret == sizeof( buf ) );
130 ret = 1;
131 } break;
133 case LBER_SB_OPT_NEEDS_READ:
134 ret = ( sb->sb_trans_needs_read ? 1 : 0 );
135 break;
137 case LBER_SB_OPT_NEEDS_WRITE:
138 ret = ( sb->sb_trans_needs_write ? 1 : 0 );
139 break;
141 case LBER_SB_OPT_GET_MAX_INCOMING:
142 if ( arg != NULL ) {
143 *((ber_len_t *)arg) = sb->sb_max_incoming;
145 ret = 1;
146 break;
148 case LBER_SB_OPT_SET_MAX_INCOMING:
149 sb->sb_max_incoming = *((ber_len_t *)arg);
150 ret = 1;
151 break;
153 case LBER_SB_OPT_UNGET_BUF:
154 #ifdef LDAP_PF_LOCAL_SENDMSG
155 sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
156 if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
157 AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
158 sb->sb_ungetlen );
159 ret = 1;
160 } else {
161 sb->sb_ungetlen = 0;
162 ret = -1;
164 #endif
165 break;
167 default:
168 ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
169 break;
172 return ret;
176 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
178 Sockbuf_IO_Desc *d, *p, **q;
180 assert( sb != NULL );
181 assert( SOCKBUF_VALID( sb ) );
183 if ( sbio == NULL ) {
184 return -1;
187 q = &sb->sb_iod;
188 p = *q;
189 while ( p && p->sbiod_level > layer ) {
190 q = &p->sbiod_next;
191 p = *q;
194 d = LBER_MALLOC( sizeof( *d ) );
195 if ( d == NULL ) {
196 return -1;
199 d->sbiod_level = layer;
200 d->sbiod_sb = sb;
201 d->sbiod_io = sbio;
202 memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
203 d->sbiod_next = p;
204 *q = d;
206 if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
207 return -1;
210 return 0;
214 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
216 Sockbuf_IO_Desc *p, **q;
218 assert( sb != NULL );
219 assert( SOCKBUF_VALID( sb ) );
221 if ( sb->sb_iod == NULL ) {
222 return -1;
225 q = &sb->sb_iod;
226 while ( *q != NULL ) {
227 p = *q;
228 if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
229 if ( p->sbiod_io->sbi_remove != NULL &&
230 p->sbiod_io->sbi_remove( p ) < 0 )
232 return -1;
234 *q = p->sbiod_next;
235 LBER_FREE( p );
236 break;
238 q = &p->sbiod_next;
241 return 0;
244 void
245 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
247 buf->buf_base = NULL;
248 buf->buf_ptr = 0;
249 buf->buf_end = 0;
250 buf->buf_size = 0;
253 void
254 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
256 assert( buf != NULL);
258 if (buf->buf_base) {
259 LBER_FREE( buf->buf_base );
261 ber_pvt_sb_buf_init( buf );
265 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
267 ber_len_t pw;
268 char *p;
270 assert( buf != NULL );
272 for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
273 if (pw > LBER_MAX_BUFF_SIZE) return -1;
276 if ( buf->buf_size < pw ) {
277 p = LBER_REALLOC( buf->buf_base, pw );
278 if ( p == NULL ) return -1;
279 buf->buf_base = p;
280 buf->buf_size = pw;
282 return 0;
285 ber_len_t
286 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
288 ber_len_t max;
290 assert( buf != NULL );
291 assert( sbb != NULL );
292 #if 0
293 assert( sbb->buf_size > 0 );
294 #endif
296 max = sbb->buf_end - sbb->buf_ptr;
297 max = ( max < len) ? max : len;
298 if ( max ) {
299 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
300 sbb->buf_ptr += max;
301 if ( sbb->buf_ptr >= sbb->buf_end ) {
302 sbb->buf_ptr = sbb->buf_end = 0;
305 return max;
308 ber_slen_t
309 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
311 ber_len_t to_go;
312 ber_slen_t ret;
314 assert( sbiod != NULL );
315 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
317 to_go = buf_out->buf_end - buf_out->buf_ptr;
318 assert( to_go > 0 );
320 for(;;) {
321 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
322 buf_out->buf_ptr, to_go );
323 #ifdef EINTR
324 if ((ret<0) && (errno==EINTR)) continue;
325 #endif
326 break;
329 if ( ret <= 0 ) return ret;
331 buf_out->buf_ptr += ret;
332 if (buf_out->buf_ptr == buf_out->buf_end) {
333 buf_out->buf_end = buf_out->buf_ptr = 0;
336 return ret;
340 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
342 #ifdef HAVE_FCNTL
343 int flags = fcntl( sd, F_GETFL);
344 if( nb ) {
345 flags |= O_NONBLOCK;
346 } else {
347 flags &= ~O_NONBLOCK;
349 return fcntl( sd, F_SETFL, flags );
351 #elif defined( FIONBIO )
352 ioctl_t status = nb ? 1 : 0;
353 return ioctl( sd, FIONBIO, &status );
354 #endif
358 ber_int_sb_init( Sockbuf *sb )
360 assert( sb != NULL);
362 sb->sb_valid=LBER_VALID_SOCKBUF;
363 sb->sb_options = 0;
364 sb->sb_debug = ber_int_debug;
365 sb->sb_fd = AC_SOCKET_INVALID;
366 sb->sb_iod = NULL;
367 sb->sb_trans_needs_read = 0;
368 sb->sb_trans_needs_write = 0;
370 assert( SOCKBUF_VALID( sb ) );
371 return 0;
375 ber_int_sb_close( Sockbuf *sb )
377 Sockbuf_IO_Desc *p;
379 assert( sb != NULL);
381 p = sb->sb_iod;
382 while ( p ) {
383 if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) {
384 return -1;
386 p = p->sbiod_next;
389 sb->sb_fd = AC_SOCKET_INVALID;
391 return 0;
395 ber_int_sb_destroy( Sockbuf *sb )
397 Sockbuf_IO_Desc *p;
399 assert( sb != NULL);
400 assert( SOCKBUF_VALID( sb ) );
402 while ( sb->sb_iod ) {
403 p = sb->sb_iod->sbiod_next;
404 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
405 sb->sb_iod->sbiod_level );
406 sb->sb_iod = p;
409 return ber_int_sb_init( sb );
412 ber_slen_t
413 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
415 ber_slen_t ret;
417 assert( buf != NULL );
418 assert( sb != NULL);
419 assert( sb->sb_iod != NULL );
420 assert( SOCKBUF_VALID( sb ) );
422 for (;;) {
423 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
425 #ifdef EINTR
426 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
427 #endif
428 break;
431 return ret;
434 ber_slen_t
435 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
437 ber_slen_t ret;
439 assert( buf != NULL );
440 assert( sb != NULL);
441 assert( sb->sb_iod != NULL );
442 assert( SOCKBUF_VALID( sb ) );
444 for (;;) {
445 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
447 #ifdef EINTR
448 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
449 #endif
450 break;
453 return ret;
457 * Support for TCP
460 static ber_slen_t
461 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
463 assert( sbiod != NULL);
464 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
466 #if defined(MACOS)
468 * MacTCP/OpenTransport
470 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
471 len, NULL );
473 #elif defined( HAVE_PCNFS ) || \
474 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
476 * PCNFS (under DOS)
479 * Windows Socket API (under DOS/Windows 3.x)
482 * 32-bit Windows Socket API (under Windows NT or Windows 95)
484 return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
486 #elif defined( HAVE_NCSA )
488 * NCSA Telnet TCP/IP stack (under DOS)
490 return nread( sbiod->sbiod_sb->sb_fd, buf, len );
492 #else
493 return read( sbiod->sbiod_sb->sb_fd, buf, len );
494 #endif
497 static ber_slen_t
498 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
500 assert( sbiod != NULL);
501 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
503 #if defined(MACOS)
505 * MacTCP/OpenTransport
507 #define MAX_WRITE 65535
508 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
509 (len<MAX_WRITE) ? len : MAX_WRITE );
511 #elif defined( HAVE_PCNFS) \
512 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
514 * PCNFS (under DOS)
517 * Windows Socket API (under DOS/Windows 3.x)
520 * 32-bit Windows Socket API (under Windows NT or Windows 95)
522 return send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
524 #elif defined(HAVE_NCSA)
525 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
527 #elif defined(VMS)
529 * VMS -- each write must be 64K or smaller
531 #define MAX_WRITE 65535
532 return write( sbiod->sbiod_sb->sb_fd, buf,
533 (len<MAX_WRITE) ? len : MAX_WRITE);
534 #else
535 return write( sbiod->sbiod_sb->sb_fd, buf, len );
536 #endif
539 static int
540 sb_stream_close( Sockbuf_IO_Desc *sbiod )
542 assert( sbiod != NULL );
543 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
544 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
545 tcp_close( sbiod->sbiod_sb->sb_fd );
546 return 0;
549 /* The argument is a pointer to the socket descriptor */
550 static int
551 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
552 assert( sbiod != NULL );
554 if ( arg != NULL ) {
555 sbiod->sbiod_sb->sb_fd = *((int *)arg);
557 return 0;
560 static int
561 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
562 /* This is an end IO descriptor */
563 return 0;
566 Sockbuf_IO ber_sockbuf_io_tcp = {
567 sb_stream_setup, /* sbi_setup */
568 NULL, /* sbi_remove */
569 sb_stream_ctrl, /* sbi_ctrl */
570 sb_stream_read, /* sbi_read */
571 sb_stream_write, /* sbi_write */
572 sb_stream_close /* sbi_close */
577 * Support for readahead (UDP needs it)
580 static int
581 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
583 Sockbuf_Buf *p;
585 assert( sbiod != NULL );
587 p = LBER_MALLOC( sizeof( *p ) );
588 if ( p == NULL ) return -1;
590 ber_pvt_sb_buf_init( p );
592 if ( arg == NULL ) {
593 ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD );
594 } else {
595 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
598 sbiod->sbiod_pvt = p;
599 return 0;
602 static int
603 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
605 Sockbuf_Buf *p;
607 assert( sbiod != NULL );
609 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
611 if ( p->buf_ptr != p->buf_end ) return -1;
613 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
614 LBER_FREE( sbiod->sbiod_pvt );
615 sbiod->sbiod_pvt = NULL;
617 return 0;
620 static ber_slen_t
621 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
623 Sockbuf_Buf *p;
624 ber_slen_t bufptr = 0, ret, max;
626 assert( sbiod != NULL );
627 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
628 assert( sbiod->sbiod_next != NULL );
630 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
632 assert( p->buf_size > 0 );
634 /* Are there anything left in the buffer? */
635 ret = ber_pvt_sb_copy_out( p, buf, len );
636 bufptr += ret;
637 len -= ret;
639 if ( len == 0 ) return bufptr;
641 max = p->buf_size - p->buf_end;
642 ret = 0;
643 while ( max > 0 ) {
644 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
645 max );
646 #ifdef EINTR
647 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
648 #endif
649 break;
652 if ( ret < 0 ) {
653 return ( bufptr ? bufptr : ret );
656 p->buf_end += ret;
657 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
658 return bufptr;
661 static ber_slen_t
662 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
664 assert( sbiod != NULL );
665 assert( sbiod->sbiod_next != NULL );
667 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
670 static int
671 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
673 assert( sbiod != NULL );
675 /* Just erase the buffer */
676 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
677 return 0;
680 static int
681 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
683 Sockbuf_Buf *p;
685 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
687 if ( opt == LBER_SB_OPT_DATA_READY ) {
688 if ( p->buf_ptr != p->buf_end ) {
689 return 1;
692 } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
693 if ( p->buf_size >= *((ber_len_t *)arg) ) {
694 return 0;
696 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
697 -1 : 1 );
700 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
703 Sockbuf_IO ber_sockbuf_io_readahead = {
704 sb_rdahead_setup, /* sbi_setup */
705 sb_rdahead_remove, /* sbi_remove */
706 sb_rdahead_ctrl, /* sbi_ctrl */
707 sb_rdahead_read, /* sbi_read */
708 sb_rdahead_write, /* sbi_write */
709 sb_rdahead_close /* sbi_close */
713 * Support for simple file IO
716 static ber_slen_t
717 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
719 assert( sbiod != NULL);
720 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
722 #ifdef LDAP_PF_LOCAL_SENDMSG
723 if ( sbiod->sbiod_sb->sb_ungetlen ) {
724 ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
725 if ( blen > len )
726 blen = len;
727 AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
728 buf = (char *) buf + blen;
729 len -= blen;
730 sbiod->sbiod_sb->sb_ungetlen -= blen;
731 if ( sbiod->sbiod_sb->sb_ungetlen ) {
732 AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
733 sbiod->sbiod_sb->sb_ungetbuf+blen,
734 sbiod->sbiod_sb->sb_ungetlen );
736 if ( len == 0 )
737 return blen;
739 #endif
740 return read( sbiod->sbiod_sb->sb_fd, buf, len );
743 static ber_slen_t
744 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
746 assert( sbiod != NULL);
747 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
749 return write( sbiod->sbiod_sb->sb_fd, buf, len );
752 static int
753 sb_fd_close( Sockbuf_IO_Desc *sbiod )
755 assert( sbiod != NULL );
756 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
758 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
759 close( sbiod->sbiod_sb->sb_fd );
760 return 0;
763 /* The argument is a pointer to the file descriptor */
764 static int
765 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
766 assert( sbiod != NULL );
768 if ( arg != NULL )
769 sbiod->sbiod_sb->sb_fd = *((int *)arg);
770 return 0;
773 static int
774 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
775 /* This is an end IO descriptor */
776 return 0;
779 Sockbuf_IO ber_sockbuf_io_fd = {
780 sb_fd_setup, /* sbi_setup */
781 NULL, /* sbi_remove */
782 sb_fd_ctrl, /* sbi_ctrl */
783 sb_fd_read, /* sbi_read */
784 sb_fd_write, /* sbi_write */
785 sb_fd_close /* sbi_close */
789 * Debugging layer
792 static int
793 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
795 assert( sbiod != NULL );
797 if ( arg == NULL ) arg = "sockbuf_";
799 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
800 if ( sbiod->sbiod_pvt == NULL ) return -1;
802 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
803 return 0;
806 static int
807 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
809 assert( sbiod != NULL );
810 assert( sbiod->sbiod_pvt != NULL );
812 LBER_FREE( sbiod->sbiod_pvt );
813 sbiod->sbiod_pvt = NULL;
814 return 0;
817 static int
818 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
820 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
823 static ber_slen_t
824 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
826 ber_slen_t ret;
827 char ebuf[128];
829 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
830 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
831 int err = sock_errno();
832 if ( ret < 0 ) {
833 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
834 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
835 (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
836 } else {
837 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
838 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
839 (long)len, (long)ret );
840 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
841 (const char *)buf, ret );
843 sock_errset(err);
845 return ret;
848 static ber_slen_t
849 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
851 ber_slen_t ret;
852 char ebuf[128];
854 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
855 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
856 int err = sock_errno();
857 if ( ret < 0 ) {
858 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
859 "%swrite: want=%ld error=%s\n",
860 (char *)sbiod->sbiod_pvt, (long)len,
861 AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
862 } else {
863 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
864 "%swrite: want=%ld, written=%ld\n",
865 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
866 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
867 (const char *)buf, ret );
869 sock_errset(err);
872 return ret;
875 Sockbuf_IO ber_sockbuf_io_debug = {
876 sb_debug_setup, /* sbi_setup */
877 sb_debug_remove, /* sbi_remove */
878 sb_debug_ctrl, /* sbi_ctrl */
879 sb_debug_read, /* sbi_read */
880 sb_debug_write, /* sbi_write */
881 NULL /* sbi_close */
884 #ifdef LDAP_CONNECTIONLESS
887 * Support for UDP (CLDAP)
889 * All I/O at this level must be atomic. For ease of use, the sb_readahead
890 * must be used above this module. All data reads and writes are prefixed
891 * with a sockaddr_storage containing the address of the remote entity. Upper levels
892 * must read and write this sockaddr_storage before doing the usual ber_printf/scanf
893 * operations on LDAP messages.
896 static int
897 sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
899 assert( sbiod != NULL);
900 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
902 if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg);
903 return 0;
906 static ber_slen_t
907 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
909 ber_slen_t rc;
910 ber_socklen_t addrlen;
911 struct sockaddr *src;
913 assert( sbiod != NULL );
914 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
915 assert( buf != NULL );
917 addrlen = sizeof( struct sockaddr_storage );
918 src = buf;
919 buf = (char *) buf + addrlen;
920 len -= addrlen;
921 rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
923 return rc > 0 ? rc+sizeof(struct sockaddr_storage) : rc;
926 static ber_slen_t
927 sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
929 ber_slen_t rc;
930 struct sockaddr *dst;
931 socklen_t dstsize;
933 assert( sbiod != NULL );
934 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
935 assert( buf != NULL );
937 dst = buf;
938 buf = (char *) buf + sizeof( struct sockaddr_storage );
939 len -= sizeof( struct sockaddr_storage );
940 dstsize = dst->sa_family == AF_INET ? sizeof( struct sockaddr_in )
941 #ifdef LDAP_PF_INET6
942 : dst->sa_family == AF_INET6 ? sizeof( struct sockaddr_in6 )
943 #endif
944 : sizeof( struct sockaddr_storage );
945 rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst, dstsize );
947 if ( rc < 0 ) return -1;
949 /* fake error if write was not atomic */
950 if (rc < len) {
951 # ifdef EMSGSIZE
952 errno = EMSGSIZE;
953 # endif
954 return -1;
956 rc = len + sizeof(struct sockaddr_storage);
957 return rc;
960 static int
961 sb_dgram_close( Sockbuf_IO_Desc *sbiod )
963 assert( sbiod != NULL );
964 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
966 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
967 tcp_close( sbiod->sbiod_sb->sb_fd );
968 return 0;
971 static int
972 sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
974 /* This is an end IO descriptor */
975 return 0;
978 Sockbuf_IO ber_sockbuf_io_udp =
980 sb_dgram_setup, /* sbi_setup */
981 NULL, /* sbi_remove */
982 sb_dgram_ctrl, /* sbi_ctrl */
983 sb_dgram_read, /* sbi_read */
984 sb_dgram_write, /* sbi_write */
985 sb_dgram_close /* sbi_close */
988 #endif /* LDAP_CONNECTIONLESS */