Home | History | Annotate | Line # | Download | only in liblber
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