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