1 /* sockbuf.c - i/o routines with support for adding i/o layers. */
3 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
14 #include <ac/socket.h>
15 #include <ac/string.h>
16 #include <ac/unistd.h>
20 #endif /* HAVE_IO_H */
22 #if defined( HAVE_SYS_FILIO_H )
23 #include <sys/filio.h>
24 #elif defined( HAVE_SYS_IOCTL_H )
25 #include <sys/ioctl.h>
32 #undef TEST_PARTIAL_READ
33 #undef TEST_PARTIAL_WRITE
35 #define assert( cond )
38 #define MAX_BUF_SIZE 65535
39 #define MIN_BUF_SIZE 4096
41 #define sockbuf_io_write( sb, buf, len ) \
42 ((sb)->sb_io->sbi_write( (sb), (buf), (len) ))
44 #define sockbuf_io_read( sb, buf, len ) \
45 ((sb)->sb_io->sbi_read( (sb), (buf), (len) ))
47 static long have_no_read( Sockbuf *sb, void *buf, long len );
48 static long have_no_write( Sockbuf *sb, void *buf, long len );
49 static int have_no_close( Sockbuf *sb );
51 static Sockbuf_IO lber_pvt_sb_IO_None=
54 NULL, /* sbi_release */
55 have_no_read, /* sbi_read */
56 have_no_write, /* sbi_write */
57 have_no_close /* sbi_close */
61 update_status( Sockbuf *sb )
63 sb->sb_buf_ready = (sb->sb_buf.buf_ptr < sb->sb_buf.buf_end);
65 sb->sb_sec_ready = ((sb->sb_sec_buf_in.buf_end!=0) &&
66 (sb->sb_sec_buf_in.buf_ptr >=
67 sb->sb_sec_buf_in.buf_end));
73 status_is_ok( Sockbuf *sb )
75 int obr = sb->sb_buf_ready;
77 int osr = sb->sb_sec_ready;
81 if (obr!=sb->sb_buf_ready)
85 if (osr!=sb->sb_sec_ready)
95 packet_length( char *buf )
98 size = (((unsigned long)buf[0])<<24)|
99 (((unsigned long)buf[1])<<16)|
100 (((unsigned long)buf[2])<<8)|
101 (((unsigned long)buf[3]));
103 if ((size<0) || (size>MAX_BUF_SIZE)) {
104 /* somebody is trying to mess me up. */
105 lber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug,
106 "SASL: received packet length of %d bytes\n",
108 size = 16; /* this should lead to an error. */
111 return size + 4; /* include the size !!! */
116 grow_buffer( Sockbuf_Buf * buf, long minsize )
118 long pw=MIN_BUF_SIZE;
120 for(;(pw<minsize);pw<<=1) {
121 if (pw > MAX_BUF_SIZE) {
122 /* this could mean that somebody is trying to crash us. */
128 if (buf->buf_size<minsize) {
129 if ((buf->buf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) {
131 if (buf->buf_base!=NULL)
132 free( buf->buf_base );
133 assert( buf->buf_ptr==0 );
134 assert( buf->buf_end==0 );
135 buf->buf_base = malloc( minsize );
136 if (buf->buf_base==NULL)
140 nb = realloc( buf->buf_base, minsize );
145 buf->buf_size = minsize;
152 sockbuf_sec_release( Sockbuf *sb, char *buf, long len )
154 /* when this is called:
155 * sb->sb_sec_buf_in.buf_base points to a packet.
156 * sb->sb_sec_buf_in.buf_ptr contains the total bytes read.
157 * sb->sb_sec_end.buf_end contains the packet length.
159 * sb->sb_buf.buf_ptr == sb->sb_buf.buf_end == 0;
167 assert( sb->sb_sec );
168 assert( sb->sb_sec->sbs_release );
169 assert( sb->sb_sec_buf_in.sb_ptr >= sb->sb_sec_buf_in.sb_end );
171 assert( sb->sb_buf.sb_ptr == 0 );
172 assert( sb->sb_buf.sb_end == 0 );
174 assert( status_is_ok(sb) );
178 ptr = sb->sb_sec_buf_in.buf_base;
179 end = ptr+ sb->sb_sec_buf_in.buf_ptr;
180 size = sb->sb_sec_buf_in.buf_end;
182 sb->sb_sec_ready = 1;
184 for(;(ptr+size<=end);) {
186 rlen = sb->sb_sec->sbs_release( sb, ptr, size,
189 sb->sb_buf.buf_size );
191 /* this means a security violation. */
192 return total; /* total ? total : 0 */
195 /* this means that the buffer isn't big enough. */
196 if (grow_buffer( &(sb->sb_buf), -rlen )<0)
197 /* memory violation. */
198 return total; /* total ? total : 0 */
206 /* move to the next packet... */
210 size = packet_length( ptr );
211 /* size is always at least 4, so the loop condition is always OK !!*/
218 sb->sb_buf_ready = (sb->sb_buf.buf_end = rlen - len) ? 1 : 0;
224 sb->sb_sec_ready = 0;
225 /* clean up the mess. */
227 /* copy back to beginning of buffer. */
228 SAFEMEMCPY( sb->sb_sec_buf_in.buf_base, ptr, end-ptr );
229 sb->sb_sec_buf_in.buf_ptr = 0;
230 sb->sb_sec_buf_in.buf_end -= (ptr - sb->sb_sec_buf_in.buf_base);
232 assert( status_is_ok(sb) );
237 sockbuf_sec_protect( Sockbuf *sb, char *buf, long len )
243 assert( sb->sb_sec_out.buf_end == 0 );
244 assert( sb->sb_sec_out.buf_ptr == 0 );
246 assert( sb->sb_sec );
247 assert( sb->sb_sec->sbs_protect );
249 assert( status_is_ok(sb) );
255 ret = sb->sb_sec->sbs_protect( sb, buf, &blen,
256 sb->sb_sec_out.buf_base+
257 sb->sb_sec_out.buf_end,
258 sb->sb_sec_out.buf_size -
259 sb->sb_sec_out.buf_end );
261 /* protection error ? */
264 if (grow_buffer( &(sb->sb_sec_out),-ret-sb->sb_sec_out.buf_end )<0)
269 /* else if (ret>0) */
272 sb->sb_sec_out.buf_end += ret;
276 assert( status_is_ok(sb) );
282 sockbuf_copy_out( Sockbuf *sb, char **buf, long len )
284 long blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr );
285 assert( status_is_ok(sb) );
287 long rlen = (blen<len) ? blen : len;
288 memcpy( *buf, sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, rlen );
289 sb->sb_buf.buf_ptr+=rlen;
292 if (sb->sb_buf.buf_ptr >= sb->sb_buf.buf_end) {
293 sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
294 sb->sb_buf_ready = 0;
296 sb->sb_buf_ready = 1;
299 assert( status_is_ok(sb) );
305 lber_pvt_sb_read( Sockbuf *sb, void *buf_arg, long len )
310 assert( status_is_ok(sb) );
312 /* breaks slapd :-) */
313 assert( lber_pvt_sb_in_use( sb ) );
316 #ifdef TEST_PARTIAL_READ
317 if ((rand() & 3)==1) { /* 1 out of 4 */
322 len = (rand() % len)+1;
325 buf = (char *) buf_arg;
327 if (sb->sb_buf.buf_ptr!=sb->sb_buf.buf_end) {
328 len = sockbuf_copy_out( sb, &buf, len );
330 return (buf - (char *) buf_arg);
337 assert( sb->sb_sec->sbs_release );
338 assert( sb->sb_sec_buf_in.buf_base );
339 if (sb->sb_read_ahead) {
340 max = sb->sb_sec_buf_in.buf_size - sb->sb_sec_buf_in.buf_ptr;
342 max = sb->sb_sec_buf_in.buf_end - sb->sb_sec_buf_in.buf_ptr;
344 /* special situation. This means that we need to read the first
345 * four bytes for the packet length.
351 /* read from stream into sb_sec_buf_in */
353 ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base +
354 sb->sb_sec_buf_in.buf_ptr, max );
356 if ((ret<0) && (errno==EINTR))
362 /* read error. return */
365 sb->sb_sec_buf_in.buf_ptr += ret;
367 if (sb->sb_sec_buf_in.buf_ptr < sb->sb_sec_buf_in.buf_end) {
368 /* did not finish a packet. give up. */
372 if (sb->sb_sec_buf_in.buf_end == 0) {
373 /* Were trying to read the first four bytes... */
374 if (sb->sb_sec_buf_in.buf_ptr < 4) {
375 /* did not read enough for packet length. give up. */
378 /* calculate the packet length. */
379 sb->sb_sec_buf_in.buf_end =
380 packet_length(sb->sb_sec_buf_in.buf_base );
381 if ((sb->sb_sec_buf_in.buf_end > sb->sb_sec_buf_in.buf_size) &&
382 (grow_buffer( &(sb->sb_sec_buf_in), sb->sb_sec_buf_in.buf_end)<0)) {
383 /* buffer has to be to big. exit with error. */
387 if (sb->sb_sec_buf_in.buf_ptr >= sb_sec_buf_in.buf_end) {
388 /* finished packet. decode it. */
391 /* did not finish packet yet. try again ? */
392 if (sb->sb_read_ahead) {
393 /* we were trying to read the max anyway. forget it */
398 /* we read enough for at least 1 packet */
399 ret = sockbuf_sec_release( sb, buf, len );
401 /* something went wrong... */
406 /* we are finished !!! */
407 if ((len==0) || (ret!=max))
412 if (sb->sb_read_ahead) {
414 max = sb->sb_buf.buf_size - sb->sb_buf.buf_end;
417 ret = sockbuf_io_read( sb,
418 sb->sb_buf.buf_base +
422 if ((ret<0) && (errno==EINTR))
428 /* some error occured */
431 sb->sb_buf.buf_end += ret;
432 /* move out the data... */
433 len = sockbuf_copy_out( sb, &buf, len );
437 /* no read_ahead, just try to put the data in the buf. */
439 ret = sockbuf_io_read( sb, buf, len );
441 if ((ret<0) && (errno==EINTR))
450 /* we might as well return, since there is nothing to do... */
455 assert( status_is_ok(sb) );
456 if ((ret<=0) && (buf==buf_arg)) {
457 /* there was an error. */
460 return (buf - ((char *) buf_arg));
464 long sockbuf_do_write( Sockbuf *sb )
467 to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr;
469 /* there is something left of the last time... */
471 ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+
472 sb->sb_sec_out.buf_ptr, to_go );
474 if ((ret<0) && (errno==EINTR))
479 if (ret<=0) /* error */
481 sb->sb_sec_out.buf_ptr += ret;
482 if (ret<to_go) /* not enough data, so pretend no data was sent. */
488 long lber_pvt_sb_write( Sockbuf *sb, void *buf, long len_arg )
492 assert( status_is_ok(sb) );
494 /* unfortunately breaks slapd */
495 assert( lber_pvt_sb_in_use( sb ) );
497 #ifdef TEST_PARTIAL_WRITE
498 if ((rand() & 3)==1) { /* 1 out of 4 */
503 len_arg = (rand() % len_arg)+1;
509 assert( sb->sb_sec_prev_len <= len );
510 if (sb->sb_sec_prev_len) {
511 ret = sockbuf_do_write( sb );
515 len -= sb->sb_sec_prev_len;
516 sb->sb_sec_prev_len = 0;
517 sb->sb_sec_out.buf_end = sb->sb_sec_out.buf_ptr = 0;
519 /* now protect the next packet. */
520 ret = sockbuf_sec_protect( sb, buf, len );
523 ret = sockbuf_do_write( sb );
525 sb->sb_sec_prev_len = len;
532 ret = sockbuf_io_write( sb, buf, len );
534 if ((ret<0) && (errno==EINTR))
546 int lber_pvt_sb_close( Sockbuf *sb )
550 assert( sb->sb_io->sbi_close );
551 assert( status_is_ok(sb) );
552 assert( lber_pvt_sb_in_use( sb ) );
554 ret = sb->sb_io->sbi_close( sb );
555 lber_pvt_sb_set_desc( sb, -1 );
560 int lber_pvt_sb_set_readahead( Sockbuf *sb, int rh )
562 assert( status_is_ok(sb) );
563 sb->sb_read_ahead = (rh!=0);
569 int lber_pvt_sb_set_nonblock( Sockbuf *sb, int nb )
571 assert( status_is_ok(sb) );
573 sb->sb_non_block = 1;
575 sb->sb_read_ahead = 1;
578 sb->sb_non_block = 0;
580 sb->sb_read_ahead = 0;
583 if (lber_pvt_sb_in_use(sb)) {
584 int status = (nb!=0);
585 if (ioctl( lber_pvt_sb_get_desc(sb), FIONBIO, (caddr_t)&status ) == -1 ) {
593 #define sockbuf_buf_init( bb ) do { \
594 Sockbuf_Buf *sbb = (bb); \
595 sbb->buf_base = NULL; \
602 sockbuf_buf_destroy( Sockbuf_Buf *buf )
605 free( buf->buf_base );
606 sockbuf_buf_init( buf );
610 int lber_pvt_sb_init( Sockbuf *sb )
612 sb->sb_item_type=LBER_ITEM_SOCKBUF;
615 sb->sb_trans_ready = 0;
616 sb->sb_buf_ready = 0;
618 sb->sb_sec_ready = 0;
620 sb->sb_read_ahead = 0;
621 sb->sb_non_block = 0;
623 sb->sb_iodata = NULL;
624 sb->sb_io = &lber_pvt_sb_IO_None;
627 sb->sb_max_incoming = 0;
629 sockbuf_buf_init( &(sb->sb_buf) );
631 sockbuf_buf_init( &(sb->sb_sec_buf_in) );
632 sockbuf_buf_init( &(sb->sb_sec_buf_out) );
635 sb->sb_sec_prev_len = 0;
640 int lber_pvt_sb_destroy( Sockbuf *sb )
643 lber_pvt_sb_clear_sec(sb);
644 sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
645 sockbuf_buf_destroy( &(sb->sb_sec_buf_out) );
647 lber_pvt_sb_clear_io(sb);
648 sockbuf_buf_destroy( &(sb->sb_buf) );
649 return lber_pvt_sb_init( sb );
653 int lber_pvt_sb_set_sec( Sockbuf *sb, Sockbuf_Sec * sec, void *arg )
656 if ((sb->sb_sec) || (sec==NULL))
661 if ((sec->sbs_setup) && (sec->sbs_setup( sb, arg)<0)) {
665 len = sb->sb_buf.buf_end - sb->sb_buf.buf_ptr;
668 /* move this to the security layer. */
669 if (grow_buffer( &(sb->sb_sec_buf_in), len )<0)
671 memcpy( sb->sb_sec_buf_in.buf_base,
672 sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, len );
673 sb->sb_sec_buf_in.buf_ptr = len;
674 sb->sb_sec_buf_in.buf_end = (len>4) ? packet_length( sb->sb_sec_buf_in ) : 0;
675 sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
681 int lber_pvt_sb_clear_sec( Sockbuf *sb )
683 if (sb->sb_buf.buf_ptr!=0)
685 if (sb->sb_sec==NULL)
687 if ((sb->sb_sec->sbs_remove) && (sb->sb_sec->sbs_remove(sb)<0))
691 if (sb->sb_sec_buf_in.buf_ptr!=0) {
692 if (grow_buffer( &(sb->sb_buf),
693 sb->sb_buf.buf_end + sb->sb_sec_buf_in.buf_ptr)<0)
695 memcpy( sb->sb_buf.buf_base + sb->sb_buf.buf_end,
696 sb->sb_sec_buf_in.buf_base, sb->sb_sec_buf_in.buf_ptr );
697 sb->sb_buf.buf_end += sb->sb_sec_buf_in.buf_ptr;
698 sb->sb_buf_ready = 1;
700 sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
701 assert( sb->sb_sec_buf.buf_end==0 );
702 sockbuf_buf_destroy( &(sb->sb_sec_buf_out) );
704 sb->sb_sec_ready = 0;
710 int lber_pvt_sb_set_io( Sockbuf *sb, Sockbuf_IO *trans, void *arg )
712 assert( sb->sb_io == &lber_pvt_sb_IO_None );
719 if ((trans->sbi_setup) && (trans->sbi_setup( sb, arg)<0))
725 int lber_pvt_sb_clear_io( Sockbuf *sb )
727 if (sb->sb_io==&lber_pvt_sb_IO_None)
730 if ((sb->sb_io->sbi_remove) && (sb->sb_io->sbi_remove( sb )<0))
733 sb->sb_io = &lber_pvt_sb_IO_None;
735 sb->sb_trans_ready = 0;
745 stream_read( Sockbuf *sb, void *buf, long len )
749 * MacTCP/OpenTransport
751 return tcpread( lber_pvt_sb_get_desc(sb), 0, (unsigned char *)buf,
753 #elif (defined(DOS) && (defined(PCNFS) || defined( WINSOCK))) \
759 * Windows Socket API (under DOS/Windows 3.x)
762 * 32-bit Windows Socket API (under Windows NT or Windows 95)
764 return recv( lber_pvt_sb_get_desc(sb), buf, len, 0 );
765 #elif (defined(DOS) && defined( NCSA ))
767 * NCSA Telnet TCP/IP stack (under DOS)
769 return nread( lber_pvt_sb_get_desc(sb), buf, len );
771 return read( lber_pvt_sb_get_desc(sb), buf, len );
776 stream_write( Sockbuf *sb, void *buf, long len )
780 * MacTCP/OpenTransport
782 #define MAX_WRITE 65535
783 return tcpwrite( lber_pvt_sb_get_desc(sb),
784 (unsigned char *)(buf),
785 (len<MAX_WRITE)? len : MAX_WRITE );
786 #elif (defined(DOS) && (defined(PCNFS) || defined( WINSOCK))) \
792 * Windows Socket API (under DOS/Windows 3.x)
795 * 32-bit Windows Socket API (under Windows NT or Windows 95)
797 return send( lber_pvt_sb_get_desc(sb), buf, len, 0 );
799 return netwrite( lber_pvt_sb_get_desc(sb), buf, len );
802 * VMS -- each write must be 64K or smaller
804 #define MAX_WRITE 65535
805 return write( lber_pvt_sb_get_desc(sb), buf,
806 (len<MAX_WRITE)? len : MAX_WRITE);
808 return write( lber_pvt_sb_get_desc(sb), buf, len );
813 stream_close( Sockbuf *sb )
815 tcp_close( lber_pvt_sb_get_desc( sb ) );
819 Sockbuf_IO lber_pvt_sb_io_tcp=
821 NULL, /* sbi_setup */
822 NULL, /* sbi_release */
823 stream_read, /* sbi_read */
824 stream_write, /* sbi_write */
825 stream_close, /* sbi_close */
829 * Support for UDP (CLDAP)
839 dgram_setup( Sockbuf *sb, void *arg )
841 sb->sb_iodata = malloc( sizeof( struct dgram_data ) );
842 if (sb->sb_iodata==NULL)
844 sb->sb_read_ahead = 1; /* important since udp is packet based. */
849 dgram_release( Sockbuf *sb )
851 free( sb->sb_iodata );
856 dgram_read( Sockbuf *sb, void *buf, long len )
858 #ifdef LDAP_CONNECTIONLESS
861 struct dgram_data *dd;
863 dd = (struct dgram_data *)(sb->sb_iodata);
865 # if !defined( MACOS) && !defined(DOS) && !defined( _WIN32)
866 addrlen = sizeof( struct sockaddr );
867 rc=recvfrom( lber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->src), &addrlen );
872 if ( sb->sb_debug ) {
873 lber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
874 "dgram_read udp_read %d bytes\n",
877 lber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
881 # else /* LDAP_CONNECTIONLESS */
883 # endif /* LDAP_CONNECTIONLESS */
887 dgram_write( Sockbuf *sb, void *buf, long len )
889 #ifdef LDAP_CONNECTIONLESS
891 struct dgram_data *dd;
893 dd = (struct dgram_data *)(sb->sb_iodata);
895 # if !defined( MACOS) && !defined(DOS) && !defined( _WIN32)
896 rc=sendto( lber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->dst),
897 sizeof( struct sockaddr ) );
904 /* fake error if write was not atomic */
918 dgram_close( Sockbuf *sb )
920 tcp_close( lber_pvt_sb_get_desc(sb) );
924 Sockbuf_IO lber_pvt_sb_io_udp=
926 dgram_setup, /* sbi_setup */
927 dgram_release, /* sbi_release */
928 dgram_read, /* sbi_read */
929 dgram_write, /* sbi_write */
930 dgram_close, /* sbi_close */
933 int lber_pvt_sb_udp_set_dst(Sockbuf *sb, void *addr )
935 struct dgram_data *dd;
936 assert( sb->sb_io == &lber_pvt_sb_io_udp );
937 dd = (struct dgram_data *) (sb->sb_iodata);
938 memcpy( &(dd->dst), addr, sizeof( struct sockaddr ) );
942 void *lber_pvt_sb_udp_get_src( Sockbuf *sb )
944 struct dgram_data *dd;
945 assert( sb->sb_io == &lber_pvt_sb_io_udp );
946 dd = (struct dgram_data *) (sb->sb_iodata);
954 * These routines should really call abort, but at the moment that would
959 have_no_read( Sockbuf *sb, void *buf, long len )
961 lber_log_printf( LDAP_DEBUG_ANY, lber_int_debug,
962 "warning: reading from uninitialized sockbuf\n");
968 have_no_write( Sockbuf *sb, void *buf, long len )
970 lber_log_printf( LDAP_DEBUG_ANY, lber_int_debug,
971 "warning: writing to uninitialized sockbuf\n");
977 have_no_close( Sockbuf *sb )