123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988 |
- /* sockbuf.c - i/o routines with support for adding i/o layers. */
- /* $OpenLDAP$ */
- /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2024 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
- #include "portable.h"
- #include <stdio.h>
- #include <ac/stdlib.h>
- #include <ac/ctype.h>
- #include <ac/errno.h>
- #include <ac/socket.h>
- #include <ac/string.h>
- #include <ac/unistd.h>
- #ifdef HAVE_IO_H
- #include <io.h>
- #endif /* HAVE_IO_H */
- #if defined( HAVE_FCNTL_H )
- #include <fcntl.h>
- #endif
- #if defined( HAVE_SYS_FILIO_H )
- #include <sys/filio.h>
- #elif defined( HAVE_SYS_IOCTL_H )
- #include <sys/ioctl.h>
- #endif
- #include "lber-int.h"
- #ifndef LBER_MIN_BUFF_SIZE
- #define LBER_MIN_BUFF_SIZE 4096
- #endif
- #ifndef LBER_MAX_BUFF_SIZE
- #define LBER_MAX_BUFF_SIZE (65536*256)
- #endif
- #ifndef LBER_DEFAULT_READAHEAD
- #define LBER_DEFAULT_READAHEAD 16384
- #endif
- Sockbuf *
- ber_sockbuf_alloc( void )
- {
- Sockbuf *sb;
- sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
- if( sb == NULL ) return NULL;
- ber_int_sb_init( sb );
- return sb;
- }
- void
- ber_sockbuf_free( Sockbuf *sb )
- {
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- ber_int_sb_close( sb );
- ber_int_sb_destroy( sb );
- LBER_FREE( sb );
- }
- /* Return values: -1: error, 0: no operation performed or the answer is false,
- * 1: successful operation or the answer is true
- */
- int
- ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
- {
- Sockbuf_IO_Desc *p;
- int ret = 0;
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- switch ( opt ) {
- case LBER_SB_OPT_HAS_IO:
- p = sb->sb_iod;
- while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
- p = p->sbiod_next;
- }
-
- if ( p ) {
- ret = 1;
- }
- break;
- case LBER_SB_OPT_GET_FD:
- if ( arg != NULL ) {
- *((ber_socket_t *)arg) = sb->sb_fd;
- }
- ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
- break;
- case LBER_SB_OPT_SET_FD:
- sb->sb_fd = *((ber_socket_t *)arg);
- ret = 1;
- break;
- case LBER_SB_OPT_SET_NONBLOCK:
- ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
- ? -1 : 1;
- break;
- case LBER_SB_OPT_DRAIN: {
- /* Drain the data source to enable possible errors (e.g.
- * TLS) to be propagated to the upper layers
- */
- char buf[LBER_MIN_BUFF_SIZE];
- do {
- ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
- } while ( ret == sizeof( buf ) );
- ret = 1;
- } break;
- case LBER_SB_OPT_NEEDS_READ:
- ret = ( sb->sb_trans_needs_read ? 1 : 0 );
- break;
- case LBER_SB_OPT_NEEDS_WRITE:
- ret = ( sb->sb_trans_needs_write ? 1 : 0 );
- break;
- case LBER_SB_OPT_GET_MAX_INCOMING:
- if ( arg != NULL ) {
- *((ber_len_t *)arg) = sb->sb_max_incoming;
- }
- ret = 1;
- break;
- case LBER_SB_OPT_SET_MAX_INCOMING:
- sb->sb_max_incoming = *((ber_len_t *)arg);
- ret = 1;
- break;
- case LBER_SB_OPT_UNGET_BUF:
- #ifdef LDAP_PF_LOCAL_SENDMSG
- sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
- if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
- AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
- sb->sb_ungetlen );
- ret = 1;
- } else {
- sb->sb_ungetlen = 0;
- ret = -1;
- }
- #endif
- break;
- default:
- ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
- break;
- }
- return ret;
- }
- int
- ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
- {
- Sockbuf_IO_Desc *d, *p, **q;
-
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
-
- if ( sbio == NULL ) {
- return -1;
- }
-
- q = &sb->sb_iod;
- p = *q;
- while ( p && p->sbiod_level > layer ) {
- q = &p->sbiod_next;
- p = *q;
- }
-
- d = LBER_MALLOC( sizeof( *d ) );
- if ( d == NULL ) {
- return -1;
- }
-
- d->sbiod_level = layer;
- d->sbiod_sb = sb;
- d->sbiod_io = sbio;
- memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
- d->sbiod_next = p;
- *q = d;
- if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
- return -1;
- }
- return 0;
- }
-
- int
- ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
- {
- Sockbuf_IO_Desc *p, **q;
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
-
- if ( sb->sb_iod == NULL ) {
- return -1;
- }
-
- q = &sb->sb_iod;
- while ( *q != NULL ) {
- p = *q;
- if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
- if ( p->sbiod_io->sbi_remove != NULL &&
- p->sbiod_io->sbi_remove( p ) < 0 )
- {
- return -1;
- }
- *q = p->sbiod_next;
- LBER_FREE( p );
- break;
- }
- q = &p->sbiod_next;
- }
- return 0;
- }
- void
- ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
- {
- buf->buf_base = NULL;
- buf->buf_ptr = 0;
- buf->buf_end = 0;
- buf->buf_size = 0;
- }
- void
- ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
- {
- assert( buf != NULL);
- if (buf->buf_base) {
- LBER_FREE( buf->buf_base );
- }
- ber_pvt_sb_buf_init( buf );
- }
- int
- ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
- {
- ber_len_t pw;
- char *p;
-
- assert( buf != NULL );
- for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
- if (pw > LBER_MAX_BUFF_SIZE) return -1;
- }
- if ( buf->buf_size < pw ) {
- p = LBER_REALLOC( buf->buf_base, pw );
- if ( p == NULL ) return -1;
- buf->buf_base = p;
- buf->buf_size = pw;
- }
- return 0;
- }
- ber_len_t
- ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
- {
- ber_len_t max;
- assert( buf != NULL );
- assert( sbb != NULL );
- #if 0
- assert( sbb->buf_size > 0 );
- #endif
- max = sbb->buf_end - sbb->buf_ptr;
- max = ( max < len) ? max : len;
- if ( max ) {
- AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
- sbb->buf_ptr += max;
- if ( sbb->buf_ptr >= sbb->buf_end ) {
- sbb->buf_ptr = sbb->buf_end = 0;
- }
- }
- return max;
- }
- ber_slen_t
- ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
- {
- ber_len_t to_go;
- ber_slen_t ret;
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- to_go = buf_out->buf_end - buf_out->buf_ptr;
- assert( to_go > 0 );
-
- for(;;) {
- ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
- buf_out->buf_ptr, to_go );
- #ifdef EINTR
- if ((ret<0) && (errno==EINTR)) continue;
- #endif
- break;
- }
- if ( ret <= 0 ) return ret;
-
- buf_out->buf_ptr += ret;
- if (buf_out->buf_ptr == buf_out->buf_end) {
- buf_out->buf_end = buf_out->buf_ptr = 0;
- }
- return ret;
- }
- int
- ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
- {
- #ifdef HAVE_FCNTL
- int flags = fcntl( sd, F_GETFL);
- if( nb ) {
- flags |= O_NONBLOCK;
- } else {
- flags &= ~O_NONBLOCK;
- }
- return fcntl( sd, F_SETFL, flags );
-
- #elif defined( FIONBIO )
- ioctl_t status = nb ? 1 : 0;
- return ioctl( sd, FIONBIO, &status );
- #endif
- }
- int
- ber_int_sb_init( Sockbuf *sb )
- {
- assert( sb != NULL);
- sb->sb_valid=LBER_VALID_SOCKBUF;
- sb->sb_options = 0;
- sb->sb_debug = ber_int_debug;
- sb->sb_fd = AC_SOCKET_INVALID;
- sb->sb_iod = NULL;
- sb->sb_trans_needs_read = 0;
- sb->sb_trans_needs_write = 0;
-
- assert( SOCKBUF_VALID( sb ) );
- return 0;
- }
-
- int
- ber_int_sb_close( Sockbuf *sb )
- {
- Sockbuf_IO_Desc *p;
- assert( sb != NULL);
-
- p = sb->sb_iod;
- while ( p ) {
- if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) {
- return -1;
- }
- p = p->sbiod_next;
- }
-
- sb->sb_fd = AC_SOCKET_INVALID;
-
- return 0;
- }
- int
- ber_int_sb_destroy( Sockbuf *sb )
- {
- Sockbuf_IO_Desc *p;
- assert( sb != NULL);
- assert( SOCKBUF_VALID( sb ) );
-
- while ( sb->sb_iod ) {
- p = sb->sb_iod->sbiod_next;
- ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
- sb->sb_iod->sbiod_level );
- sb->sb_iod = p;
- }
- return ber_int_sb_init( sb );
- }
- ber_slen_t
- ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
- {
- ber_slen_t ret;
- assert( buf != NULL );
- assert( sb != NULL);
- assert( sb->sb_iod != NULL );
- assert( SOCKBUF_VALID( sb ) );
- for (;;) {
- ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
- #ifdef EINTR
- if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
- #endif
- break;
- }
- return ret;
- }
- ber_slen_t
- ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
- {
- ber_slen_t ret;
- assert( buf != NULL );
- assert( sb != NULL);
- assert( sb->sb_iod != NULL );
- assert( SOCKBUF_VALID( sb ) );
- for (;;) {
- ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
- #ifdef EINTR
- if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
- #endif
- break;
- }
- return ret;
- }
- /*
- * Support for TCP
- */
- static ber_slen_t
- sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- assert( sbiod != NULL);
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- #if defined(MACOS)
- /*
- * MacTCP/OpenTransport
- */
- return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
- len, NULL );
- #elif defined( HAVE_PCNFS ) || \
- defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
- /*
- * PCNFS (under DOS)
- */
- /*
- * Windows Socket API (under DOS/Windows 3.x)
- */
- /*
- * 32-bit Windows Socket API (under Windows NT or Windows 95)
- */
- return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
- #elif defined( HAVE_NCSA )
- /*
- * NCSA Telnet TCP/IP stack (under DOS)
- */
- return nread( sbiod->sbiod_sb->sb_fd, buf, len );
- #else
- return read( sbiod->sbiod_sb->sb_fd, buf, len );
- #endif
- }
- static ber_slen_t
- sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- assert( sbiod != NULL);
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- #if defined(MACOS)
- /*
- * MacTCP/OpenTransport
- */
- #define MAX_WRITE 65535
- return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
- (len<MAX_WRITE) ? len : MAX_WRITE );
- #elif defined( HAVE_PCNFS) \
- || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
- /*
- * PCNFS (under DOS)
- */
- /*
- * Windows Socket API (under DOS/Windows 3.x)
- */
- /*
- * 32-bit Windows Socket API (under Windows NT or Windows 95)
- */
- return send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
- #elif defined(HAVE_NCSA)
- return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
- #elif defined(VMS)
- /*
- * VMS -- each write must be 64K or smaller
- */
- #define MAX_WRITE 65535
- return write( sbiod->sbiod_sb->sb_fd, buf,
- (len<MAX_WRITE) ? len : MAX_WRITE);
- #else
- return write( sbiod->sbiod_sb->sb_fd, buf, len );
- #endif
- }
-
- static int
- sb_stream_close( Sockbuf_IO_Desc *sbiod )
- {
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
- tcp_close( sbiod->sbiod_sb->sb_fd );
- return 0;
- }
- /* The argument is a pointer to the socket descriptor */
- static int
- sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
- assert( sbiod != NULL );
- if ( arg != NULL ) {
- sbiod->sbiod_sb->sb_fd = *((int *)arg);
- }
- return 0;
- }
- static int
- sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
- /* This is an end IO descriptor */
- return 0;
- }
- Sockbuf_IO ber_sockbuf_io_tcp = {
- sb_stream_setup, /* sbi_setup */
- NULL, /* sbi_remove */
- sb_stream_ctrl, /* sbi_ctrl */
- sb_stream_read, /* sbi_read */
- sb_stream_write, /* sbi_write */
- sb_stream_close /* sbi_close */
- };
- /*
- * Support for readahead (UDP needs it)
- */
- static int
- sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
- {
- Sockbuf_Buf *p;
- assert( sbiod != NULL );
- p = LBER_MALLOC( sizeof( *p ) );
- if ( p == NULL ) return -1;
- ber_pvt_sb_buf_init( p );
- if ( arg == NULL ) {
- ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD );
- } else {
- ber_pvt_sb_grow_buffer( p, *((int *)arg) );
- }
- sbiod->sbiod_pvt = p;
- return 0;
- }
- static int
- sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
- {
- Sockbuf_Buf *p;
- assert( sbiod != NULL );
- p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
- if ( p->buf_ptr != p->buf_end ) return -1;
- ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
- LBER_FREE( sbiod->sbiod_pvt );
- sbiod->sbiod_pvt = NULL;
- return 0;
- }
- static ber_slen_t
- sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- Sockbuf_Buf *p;
- ber_slen_t bufptr = 0, ret, max;
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- assert( sbiod->sbiod_next != NULL );
- p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
- assert( p->buf_size > 0 );
- /* Are there anything left in the buffer? */
- ret = ber_pvt_sb_copy_out( p, buf, len );
- bufptr += ret;
- len -= ret;
- if ( len == 0 ) return bufptr;
- max = p->buf_size - p->buf_end;
- ret = 0;
- while ( max > 0 ) {
- ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
- max );
- #ifdef EINTR
- if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
- #endif
- break;
- }
- if ( ret < 0 ) {
- return ( bufptr ? bufptr : ret );
- }
- p->buf_end += ret;
- bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
- return bufptr;
- }
- static ber_slen_t
- sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- assert( sbiod != NULL );
- assert( sbiod->sbiod_next != NULL );
- return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
- }
- static int
- sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
- {
- assert( sbiod != NULL );
- /* Just erase the buffer */
- ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
- return 0;
- }
- static int
- sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
- {
- Sockbuf_Buf *p;
- p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
- if ( opt == LBER_SB_OPT_DATA_READY ) {
- if ( p->buf_ptr != p->buf_end ) {
- return 1;
- }
- } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
- if ( p->buf_size >= *((ber_len_t *)arg) ) {
- return 0;
- }
- return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
- -1 : 1 );
- }
- return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
- }
- Sockbuf_IO ber_sockbuf_io_readahead = {
- sb_rdahead_setup, /* sbi_setup */
- sb_rdahead_remove, /* sbi_remove */
- sb_rdahead_ctrl, /* sbi_ctrl */
- sb_rdahead_read, /* sbi_read */
- sb_rdahead_write, /* sbi_write */
- sb_rdahead_close /* sbi_close */
- };
- /*
- * Support for simple file IO
- */
- static ber_slen_t
- sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- assert( sbiod != NULL);
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- #ifdef LDAP_PF_LOCAL_SENDMSG
- if ( sbiod->sbiod_sb->sb_ungetlen ) {
- ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
- if ( blen > len )
- blen = len;
- AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
- buf = (char *) buf + blen;
- len -= blen;
- sbiod->sbiod_sb->sb_ungetlen -= blen;
- if ( sbiod->sbiod_sb->sb_ungetlen ) {
- AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
- sbiod->sbiod_sb->sb_ungetbuf+blen,
- sbiod->sbiod_sb->sb_ungetlen );
- }
- if ( len == 0 )
- return blen;
- }
- #endif
- return read( sbiod->sbiod_sb->sb_fd, buf, len );
- }
- static ber_slen_t
- sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- assert( sbiod != NULL);
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- return write( sbiod->sbiod_sb->sb_fd, buf, len );
- }
- static int
- sb_fd_close( Sockbuf_IO_Desc *sbiod )
- {
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
- close( sbiod->sbiod_sb->sb_fd );
- return 0;
- }
- /* The argument is a pointer to the file descriptor */
- static int
- sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
- assert( sbiod != NULL );
- if ( arg != NULL )
- sbiod->sbiod_sb->sb_fd = *((int *)arg);
- return 0;
- }
- static int
- sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
- /* This is an end IO descriptor */
- return 0;
- }
- Sockbuf_IO ber_sockbuf_io_fd = {
- sb_fd_setup, /* sbi_setup */
- NULL, /* sbi_remove */
- sb_fd_ctrl, /* sbi_ctrl */
- sb_fd_read, /* sbi_read */
- sb_fd_write, /* sbi_write */
- sb_fd_close /* sbi_close */
- };
- /*
- * Debugging layer
- */
- static int
- sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
- {
- assert( sbiod != NULL );
-
- if ( arg == NULL ) arg = "sockbuf_";
- sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
- if ( sbiod->sbiod_pvt == NULL ) return -1;
- strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
- return 0;
- }
- static int
- sb_debug_remove( Sockbuf_IO_Desc *sbiod )
- {
- assert( sbiod != NULL );
- assert( sbiod->sbiod_pvt != NULL );
- LBER_FREE( sbiod->sbiod_pvt );
- sbiod->sbiod_pvt = NULL;
- return 0;
- }
- static int
- sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
- {
- return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
- }
- static ber_slen_t
- sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- ber_slen_t ret;
- char ebuf[128];
- ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
- if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
- int err = sock_errno();
- if ( ret < 0 ) {
- ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
- "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
- (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
- } else {
- ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
- "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
- (long)len, (long)ret );
- ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
- (const char *)buf, ret );
- }
- sock_errset(err);
- }
- return ret;
- }
- static ber_slen_t
- sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- ber_slen_t ret;
- char ebuf[128];
- ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
- if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
- int err = sock_errno();
- if ( ret < 0 ) {
- ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
- "%swrite: want=%ld error=%s\n",
- (char *)sbiod->sbiod_pvt, (long)len,
- AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
- } else {
- ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
- "%swrite: want=%ld, written=%ld\n",
- (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
- ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
- (const char *)buf, ret );
- }
- sock_errset(err);
- }
- return ret;
- }
- Sockbuf_IO ber_sockbuf_io_debug = {
- sb_debug_setup, /* sbi_setup */
- sb_debug_remove, /* sbi_remove */
- sb_debug_ctrl, /* sbi_ctrl */
- sb_debug_read, /* sbi_read */
- sb_debug_write, /* sbi_write */
- NULL /* sbi_close */
- };
- #ifdef LDAP_CONNECTIONLESS
- /*
- * Support for UDP (CLDAP)
- *
- * All I/O at this level must be atomic. For ease of use, the sb_readahead
- * must be used above this module. All data reads and writes are prefixed
- * with a sockaddr_storage containing the address of the remote entity. Upper levels
- * must read and write this sockaddr_storage before doing the usual ber_printf/scanf
- * operations on LDAP messages.
- */
- static int
- sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
- {
- assert( sbiod != NULL);
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg);
- return 0;
- }
- static ber_slen_t
- sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- ber_slen_t rc;
- ber_socklen_t addrlen;
- struct sockaddr *src;
-
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- assert( buf != NULL );
- addrlen = sizeof( struct sockaddr_storage );
- src = buf;
- buf = (char *) buf + addrlen;
- len -= addrlen;
- rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
- return rc > 0 ? rc+sizeof(struct sockaddr_storage) : rc;
- }
- static ber_slen_t
- sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
- {
- ber_slen_t rc;
- struct sockaddr *dst;
- socklen_t dstsize;
-
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- assert( buf != NULL );
- dst = buf;
- buf = (char *) buf + sizeof( struct sockaddr_storage );
- len -= sizeof( struct sockaddr_storage );
- dstsize = dst->sa_family == AF_INET ? sizeof( struct sockaddr_in )
- #ifdef LDAP_PF_INET6
- : dst->sa_family == AF_INET6 ? sizeof( struct sockaddr_in6 )
- #endif
- : sizeof( struct sockaddr_storage );
- rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst, dstsize );
- if ( rc < 0 ) return -1;
-
- /* fake error if write was not atomic */
- if (rc < len) {
- # ifdef EMSGSIZE
- errno = EMSGSIZE;
- # endif
- return -1;
- }
- rc = len + sizeof(struct sockaddr_storage);
- return rc;
- }
- static int
- sb_dgram_close( Sockbuf_IO_Desc *sbiod )
- {
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-
- if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
- tcp_close( sbiod->sbiod_sb->sb_fd );
- return 0;
- }
- static int
- sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
- {
- /* This is an end IO descriptor */
- return 0;
- }
- Sockbuf_IO ber_sockbuf_io_udp =
- {
- sb_dgram_setup, /* sbi_setup */
- NULL, /* sbi_remove */
- sb_dgram_ctrl, /* sbi_ctrl */
- sb_dgram_read, /* sbi_read */
- sb_dgram_write, /* sbi_write */
- sb_dgram_close /* sbi_close */
- };
- #endif /* LDAP_CONNECTIONLESS */
|