1 /* sockbuf.c - i/o routines with support for adding i/o layers. */
4 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/stdlib.h>
16 #include <ac/socket.h>
17 #include <ac/string.h>
18 #include <ac/unistd.h>
22 #endif /* HAVE_IO_H */
24 #if defined( HAVE_FCNTL_H )
28 #if defined( HAVE_SYS_FILIO_H )
29 #include <sys/filio.h>
30 #elif defined( HAVE_SYS_IOCTL_H )
31 #include <sys/ioctl.h>
36 #ifndef LBER_MIN_BUFF_SIZE
37 #define LBER_MIN_BUFF_SIZE 4096
39 #ifndef LBER_MAX_BUFF_SIZE
40 #define LBER_MAX_BUFF_SIZE 65536
42 #ifndef LBER_DEFAULT_READAHEAD
43 #define LBER_DEFAULT_READAHEAD 16384
47 ber_sockbuf_alloc( void )
51 ber_int_options.lbo_valid = LBER_INITIALIZED;
53 sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
55 if( sb == NULL ) return NULL;
57 ber_int_sb_init( sb );
62 ber_sockbuf_free( Sockbuf *sb )
65 assert( SOCKBUF_VALID( sb ) );
67 ber_int_sb_close( sb );
68 ber_int_sb_destroy( sb );
72 /* Return values: -1: error, 0: no operation performed or the answer is false,
73 * 1: successful operation or the answer is true
76 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
82 assert( SOCKBUF_VALID( sb ) );
85 case LBER_SB_OPT_HAS_IO:
87 while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
96 case LBER_SB_OPT_GET_FD:
98 *((int *)arg) = sb->sb_fd;
100 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
103 case LBER_SB_OPT_SET_FD:
104 sb->sb_fd = *((int *)arg);
108 case LBER_SB_OPT_SET_NONBLOCK:
109 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
113 case LBER_SB_OPT_DRAIN: {
114 /* Drain the data source to enable possible errors (e.g.
115 * TLS) to be propagated to the upper layers
117 char buf[LBER_MIN_BUFF_SIZE];
120 ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
121 } while ( ret == sizeof( buf ) );
126 case LBER_SB_OPT_NEEDS_READ:
127 ret = ( sb->sb_trans_needs_read ? 1 : 0 );
130 case LBER_SB_OPT_NEEDS_WRITE:
131 ret = ( sb->sb_trans_needs_write ? 1 : 0 );
134 case LBER_SB_OPT_GET_MAX_INCOMING:
136 *((ber_len_t *)arg) = sb->sb_max_incoming;
141 case LBER_SB_OPT_SET_MAX_INCOMING:
142 sb->sb_max_incoming = *((ber_len_t *)arg);
147 ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
156 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
158 Sockbuf_IO_Desc *d, *p, **q;
160 assert( sb != NULL );
161 assert( SOCKBUF_VALID( sb ) );
163 if ( sbio == NULL ) {
169 while ( p && p->sbiod_level > layer ) {
174 d = LBER_MALLOC( sizeof( *d ) );
179 d->sbiod_level = layer;
182 memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
186 if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
194 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
196 Sockbuf_IO_Desc *p, **q;
198 assert( sb != NULL );
199 assert( SOCKBUF_VALID( sb ) );
201 if ( sb->sb_iod == NULL ) {
206 while ( *q != NULL ) {
208 if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
209 if ( p->sbiod_io->sbi_remove != NULL &&
210 p->sbiod_io->sbi_remove( p ) < 0 )
225 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
227 buf->buf_base = NULL;
234 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
236 assert( buf != NULL);
239 LBER_FREE( buf->buf_base );
241 ber_pvt_sb_buf_init( buf );
245 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
250 assert( buf != NULL );
252 for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
253 if (pw > LBER_MAX_BUFF_SIZE) return -1;
256 if ( buf->buf_size < pw ) {
257 p = LBER_REALLOC( buf->buf_base, pw );
258 if ( p == NULL ) return -1;
266 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
270 assert( buf != NULL );
271 assert( sbb != NULL );
273 assert( sbb->buf_size > 0 );
276 max = sbb->buf_end - sbb->buf_ptr;
277 max = ( max < len) ? max : len;
279 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
281 if ( sbb->buf_ptr >= sbb->buf_end ) {
282 sbb->buf_ptr = sbb->buf_end = 0;
289 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
294 assert( sbiod != NULL );
295 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
297 to_go = buf_out->buf_end - buf_out->buf_ptr;
301 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
302 buf_out->buf_ptr, to_go );
304 if ((ret<0) && (errno==EINTR)) continue;
309 if ( ret <= 0 ) return ret;
311 buf_out->buf_ptr += ret;
312 if (buf_out->buf_ptr == buf_out->buf_end) {
313 buf_out->buf_end = buf_out->buf_ptr = 0;
316 if ( (ber_len_t)ret < to_go ) {
317 /* not enough data, so pretend no data was sent. */
325 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
328 int flags = fcntl( sd, F_GETFL);
332 flags &= ~O_NONBLOCK;
334 return fcntl( sd, F_SETFL, flags );
336 #elif defined( FIONBIO )
337 ioctl_t status = nb ? 1 : 0;
338 return ioctl( sd, FIONBIO, &status );
343 ber_int_sb_init( Sockbuf *sb )
347 sb->sb_valid=LBER_VALID_SOCKBUF;
349 sb->sb_debug = ber_int_debug;
350 sb->sb_fd = AC_SOCKET_INVALID;
352 sb->sb_trans_needs_read = 0;
353 sb->sb_trans_needs_write = 0;
355 assert( SOCKBUF_VALID( sb ) );
360 ber_int_sb_close( Sockbuf *sb )
368 if ( p->sbiod_io->sbi_close &&
369 p->sbiod_io->sbi_close( p ) < 0 )
376 sb->sb_fd = AC_SOCKET_INVALID;
382 ber_int_sb_destroy( Sockbuf *sb )
387 assert( SOCKBUF_VALID( sb ) );
389 while ( sb->sb_iod ) {
390 p = sb->sb_iod->sbiod_next;
391 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
392 sb->sb_iod->sbiod_level );
396 return ber_int_sb_init( sb );
400 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
404 assert( buf != NULL );
406 assert( sb->sb_iod != NULL );
407 assert( SOCKBUF_VALID( sb ) );
410 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
413 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
422 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
426 assert( buf != NULL );
428 assert( sb->sb_iod != NULL );
429 assert( SOCKBUF_VALID( sb ) );
432 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
435 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
448 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
450 assert( sbiod != NULL);
451 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
455 * MacTCP/OpenTransport
457 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
460 #elif defined( HAVE_PCNFS ) || \
461 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
466 * Windows Socket API (under DOS/Windows 3.x)
469 * 32-bit Windows Socket API (under Windows NT or Windows 95)
474 rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
480 err = WSAGetLastError();
488 #elif defined( HAVE_NCSA )
490 * NCSA Telnet TCP/IP stack (under DOS)
492 return nread( sbiod->sbiod_sb->sb_fd, buf, len );
495 return read( sbiod->sbiod_sb->sb_fd, buf, len );
500 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
502 assert( sbiod != NULL);
503 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
507 * MacTCP/OpenTransport
509 #define MAX_WRITE 65535
510 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
511 (len<MAX_WRITE) ? len : MAX_WRITE );
513 #elif defined( HAVE_PCNFS) \
514 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
519 * Windows Socket API (under DOS/Windows 3.x)
522 * 32-bit Windows Socket API (under Windows NT or Windows 95)
525 int rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
530 err = WSAGetLastError();
537 #elif defined(HAVE_NCSA)
538 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
542 * VMS -- each write must be 64K or smaller
544 #define MAX_WRITE 65535
545 return write( sbiod->sbiod_sb->sb_fd, buf,
546 (len<MAX_WRITE) ? len : MAX_WRITE);
548 return write( sbiod->sbiod_sb->sb_fd, buf, len );
553 sb_stream_close( Sockbuf_IO_Desc *sbiod )
555 assert( sbiod != NULL );
556 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
557 tcp_close( sbiod->sbiod_sb->sb_fd );
561 /* The argument is a pointer to the socket descriptor */
563 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
564 assert( sbiod != NULL );
567 sbiod->sbiod_sb->sb_fd = *((int *)arg);
573 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
574 /* This is an end IO descriptor */
578 Sockbuf_IO ber_sockbuf_io_tcp = {
579 sb_stream_setup, /* sbi_setup */
580 NULL, /* sbi_remove */
581 sb_stream_ctrl, /* sbi_ctrl */
582 sb_stream_read, /* sbi_read */
583 sb_stream_write, /* sbi_write */
584 sb_stream_close /* sbi_close */
589 * Support for readahead (UDP needs it)
593 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
597 assert( sbiod != NULL );
599 p = LBER_MALLOC( sizeof( *p ) );
600 if ( p == NULL ) return -1;
602 ber_pvt_sb_buf_init( p );
605 ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD );
607 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
610 sbiod->sbiod_pvt = p;
615 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
619 assert( sbiod != NULL );
621 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
623 if ( p->buf_ptr != p->buf_end ) return -1;
625 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
626 LBER_FREE( sbiod->sbiod_pvt );
627 sbiod->sbiod_pvt = NULL;
633 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
636 ber_slen_t bufptr = 0, ret, max;
638 assert( sbiod != NULL );
639 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
640 assert( sbiod->sbiod_next != NULL );
642 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
644 assert( p->buf_size > 0 );
646 /* Are there anything left in the buffer? */
647 ret = ber_pvt_sb_copy_out( p, buf, len );
651 if ( len == 0 ) return bufptr;
653 max = p->buf_size - p->buf_end;
656 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
659 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
665 return ( bufptr ? bufptr : ret );
669 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
674 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
676 assert( sbiod != NULL );
677 assert( sbiod->sbiod_next != NULL );
679 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
683 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
685 assert( sbiod != NULL );
687 /* Just erase the buffer */
688 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
693 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
697 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
699 if ( opt == LBER_SB_OPT_DATA_READY ) {
700 if ( p->buf_ptr != p->buf_end ) {
704 } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
705 if ( p->buf_size >= *((ber_len_t *)arg) ) {
708 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
712 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
715 Sockbuf_IO ber_sockbuf_io_readahead = {
716 sb_rdahead_setup, /* sbi_setup */
717 sb_rdahead_remove, /* sbi_remove */
718 sb_rdahead_ctrl, /* sbi_ctrl */
719 sb_rdahead_read, /* sbi_read */
720 sb_rdahead_write, /* sbi_write */
721 sb_rdahead_close /* sbi_close */
725 * Support for simple file IO
729 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
731 assert( sbiod != NULL);
732 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
734 return read( sbiod->sbiod_sb->sb_fd, buf, len );
738 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
740 assert( sbiod != NULL);
741 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
743 return write( sbiod->sbiod_sb->sb_fd, buf, len );
747 sb_fd_close( Sockbuf_IO_Desc *sbiod )
749 assert( sbiod != NULL );
750 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
752 close( sbiod->sbiod_sb->sb_fd );
756 /* The argument is a pointer to the file descriptor */
758 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
759 assert( sbiod != NULL );
762 sbiod->sbiod_sb->sb_fd = *((int *)arg);
767 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
768 /* This is an end IO descriptor */
772 Sockbuf_IO ber_sockbuf_io_fd = {
773 sb_fd_setup, /* sbi_setup */
774 NULL, /* sbi_remove */
775 sb_fd_ctrl, /* sbi_ctrl */
776 sb_fd_read, /* sbi_read */
777 sb_fd_write, /* sbi_write */
778 sb_fd_close /* sbi_close */
786 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
788 assert( sbiod != NULL );
790 if ( arg == NULL ) arg = "sockbuf_";
792 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
793 if ( sbiod->sbiod_pvt == NULL ) return -1;
795 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
800 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
802 assert( sbiod != NULL );
803 assert( sbiod->sbiod_pvt != NULL );
805 LBER_FREE( sbiod->sbiod_pvt );
806 sbiod->sbiod_pvt = NULL;
811 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
813 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
817 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
821 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
822 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS)
826 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
827 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
828 (long)len, STRERROR( errno ) );
830 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
831 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
832 (long)len, (long)ret );
833 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
834 (const char *)buf, ret );
842 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
846 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
847 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS)
851 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
852 "%swrite: want=%ld error=%s\n",
853 (char *)sbiod->sbiod_pvt, (long)len,
857 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
858 "%swrite: want=%ld, written=%ld\n",
859 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
860 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
861 (const char *)buf, ret );
869 Sockbuf_IO ber_sockbuf_io_debug = {
870 sb_debug_setup, /* sbi_setup */
871 sb_debug_remove, /* sbi_remove */
872 sb_debug_ctrl, /* sbi_ctrl */
873 sb_debug_read, /* sbi_read */
874 sb_debug_write, /* sbi_write */
878 #ifdef LDAP_CONNECTIONLESS
881 * Support for UDP (CLDAP)
883 * All I/O at this level must be atomic. For ease of use, the sb_readahead
884 * must be used above this module. All data reads and writes are prefixed
885 * with a sockaddr containing the address of the remote entity. Upper levels
886 * must read and write this sockaddr before doing the usual ber_printf/scanf
887 * operations on LDAP messages.
891 sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
893 assert( sbiod != NULL);
894 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
897 sbiod->sbiod_sb->sb_fd = *((int *)arg);
902 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
906 struct sockaddr *src;
908 assert( sbiod != NULL );
909 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
910 assert( buf != NULL );
912 addrlen = sizeof( struct sockaddr );
915 rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src,
918 return rc > 0 ? rc+sizeof(struct sockaddr) : rc;
922 sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
925 struct sockaddr *dst;
927 assert( sbiod != NULL );
928 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
929 assert( buf != NULL );
932 buf += sizeof( struct sockaddr );
933 len -= sizeof( struct sockaddr );
935 rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
936 sizeof( struct sockaddr ) );
941 /* fake error if write was not atomic */
948 rc = len + sizeof(struct sockaddr);
953 sb_dgram_close( Sockbuf_IO_Desc *sbiod )
955 assert( sbiod != NULL );
956 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
958 tcp_close( sbiod->sbiod_sb->sb_fd );
963 sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
965 /* This is an end IO descriptor */
969 Sockbuf_IO ber_sockbuf_io_udp =
971 sb_dgram_setup, /* sbi_setup */
972 NULL, /* sbi_remove */
973 sb_dgram_ctrl, /* sbi_ctrl */
974 sb_dgram_read, /* sbi_read */
975 sb_dgram_write, /* sbi_write */
976 sb_dgram_close /* sbi_close */
979 #endif /* LDAP_CONNECTIONLESS */