From 8153a4039b9049da4fc324cd0807d3dc964596ab Mon Sep 17 00:00:00 2001 From: Bart Hartgers Date: Tue, 2 Mar 1999 20:23:14 +0000 Subject: [PATCH] The new&improved Sockbuf. This adds the infrastructure on which support for TLS and SASL will be build. Please inform me of any problems. --- include/lber.h | 6 +- include/ldap.h | 7 - libraries/liblber/Makefile.in | 4 +- libraries/liblber/dtest.c | 4 +- libraries/liblber/etest.c | 4 +- libraries/liblber/io.c | 193 +------ libraries/liblber/lber-int.h | 105 +++- libraries/liblber/sockbuf.c | 916 ++++++++++++++++++++++++++++++++++ libraries/libldap/abandon.c | 2 +- libraries/libldap/cldap.c | 67 +-- libraries/libldap/ldap-int.h | 12 +- libraries/libldap/open.c | 8 +- libraries/libldap/options.c | 2 +- libraries/libldap/os-ip.c | 31 +- libraries/libldap/request.c | 13 +- libraries/libldap/result.c | 9 +- libraries/libldap/search.c | 2 +- libraries/libldap/unbind.c | 17 +- servers/ldapd/main.c | 20 +- servers/ldapd/request.c | 20 +- servers/ldapd/result.c | 10 +- servers/ldapd/search.c | 4 +- servers/slapd/connection.c | 2 +- servers/slapd/daemon.c | 48 +- servers/slapd/main.c | 18 +- servers/slapd/monitor.c | 2 +- servers/slapd/result.c | 15 +- 27 files changed, 1209 insertions(+), 332 deletions(-) create mode 100644 libraries/liblber/sockbuf.c diff --git a/include/lber.h b/include/lber.h index c82a8c7614..5af98579ae 100644 --- a/include/lber.h +++ b/include/lber.h @@ -205,9 +205,9 @@ lber_set_option LDAP_P((void *item, int option, void *invalue)); /* * LBER Sockbuf functions */ -LDAP_F Sockbuf *lber_sockbuf_alloc LDAP_P((void)); -LDAP_F Sockbuf *lber_sockbuf_alloc_fd LDAP_P((int fd)); -LDAP_F void lber_sockbuf_free LDAP_P((Sockbuf *sb)); +LDAP_F Sockbuf *lber_pvt_sockbuf_alloc LDAP_P((void)); +LDAP_F Sockbuf *lber_pvt_sockbuf_alloc_fd LDAP_P((int fd)); +LDAP_F void lber_pvt_sockbuf_free LDAP_P((Sockbuf *sb)); LDAP_END_DECL diff --git a/include/ldap.h b/include/ldap.h index 56927161e6..c2d67314fc 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -443,13 +443,6 @@ typedef struct ldap_friendly { char *lf_friendly; } LDAPFriendlyMap; - -/* - * handy macro to check whether LDAP struct is set up for CLDAP or not - */ -#define LDAP_IS_CLDAP( ld ) ( (ld)->ld_sb.sb_naddr > 0 ) - - /* * types for ldap URL handling */ diff --git a/libraries/liblber/Makefile.in b/libraries/liblber/Makefile.in index ef1f8a02c9..9a17b3335b 100644 --- a/libraries/liblber/Makefile.in +++ b/libraries/liblber/Makefile.in @@ -7,8 +7,8 @@ LIBRARY = liblber.la XLIBRARY = ../liblber.a -SRCS= decode.c encode.c io.c bprint.c options.c -OBJS= decode.lo encode.lo io.lo bprint.lo options.lo +SRCS= decode.c encode.c io.c bprint.c options.c sockbuf.c +OBJS= decode.lo encode.lo io.lo bprint.lo options.lo sockbuf.lo XSRCS= version.c PROGRAMS= dtest etest idtest diff --git a/libraries/liblber/dtest.c b/libraries/liblber/dtest.c index 93b1966894..df683a0ec7 100644 --- a/libraries/liblber/dtest.c +++ b/libraries/liblber/dtest.c @@ -49,7 +49,7 @@ main( int argc, char **argv ) cshow( stdout ); #endif /* MACOS */ - sb = lber_sockbuf_alloc_fd( fileno(stdin) ); + sb = lber_pvt_sb_alloc_fd( fileno(stdin) ); if( (ber = ber_alloc_t(LBER_USE_DER)) == NULL ) { perror( "ber_alloc_t" ); @@ -68,6 +68,6 @@ main( int argc, char **argv ) } printf( "got int %ld\n", i ); - lber_sockbuf_free( sb ); + lber_pvt_sb_free( sb ); return( 0 ); } diff --git a/libraries/liblber/etest.c b/libraries/liblber/etest.c index 1155300092..3e8ff55ced 100644 --- a/libraries/liblber/etest.c +++ b/libraries/liblber/etest.c @@ -58,7 +58,7 @@ main( int argc, char **argv ) fd = fileno(stdout); #endif /* MACOS */ - sb = lber_sockbuf_alloc_fd( fd ); + sb = lber_pvt_sb_alloc_fd( fd ); if ( (ber = ber_alloc()) == NULLBER ) { perror( "ber_alloc" ); @@ -171,6 +171,6 @@ main( int argc, char **argv ) #endif - lber_sockbuf_free( sb ); + lber_pvt_sb_free( sb ); return( 0 ); } diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c index fc881b9d44..dd8bc5f14f 100644 --- a/libraries/liblber/io.c +++ b/libraries/liblber/io.c @@ -32,130 +32,11 @@ #include "lber-int.h" -static int ber_realloc LDAP_P(( BerElement *ber, unsigned long len )); -static int ber_filbuf LDAP_P(( Sockbuf *sb, long len )); static long BerRead LDAP_P(( Sockbuf *sb, char *buf, long len )); -#ifdef PCNFS -static int BerWrite LDAP_P(( Sockbuf *sb, char *buf, long len )); -#endif /* PCNFS */ - -#define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \ - (unsigned char)*sb->sb_ber.ber_ptr++ : \ - ber_filbuf( sb, len )) - -#ifdef MACOS -/* - * MacTCP/OpenTransport - */ -#define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL ) -#define MAX_WRITE 65535 -#define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (lsb_sd, b, (int) l, 0 ) -#endif /* PCNFS */ -#ifdef NCSA -/* - * NCSA Telnet TCP/IP stack (under DOS) - */ -#define read( s, b, l ) nread( s, b, l ) -#define BerWrite( s, b, l ) netwrite( s->sb_sd, b, l ) -#endif /* NCSA */ -#ifdef WINSOCK -/* - * Windows Socket API (under DOS/Windows 3.x) - */ -#define read( s, b, l ) recv( s, b, l, 0 ) -#define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 ) -#endif /* WINSOCK */ -#else /* DOS */ -#ifdef _WIN32 -/* - * 32-bit Windows Socket API (under Windows NT or Windows 95) - */ -#define read( s, b, l ) recv( s, b, l, 0 ) -#define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 ) -#else /* _WIN32 */ -#ifdef VMS -/* - * VMS -- each write must be 64K or smaller - */ -#define MAX_WRITE 65535 -#define BerWrite( sb, b, l ) write( sb->sb_sd, b, (lsb_sd, b, l ) -#endif /* VMS */ -#define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \ - (struct sockaddr *)sb->sb_fromaddr, \ - (al = sizeof(struct sockaddr), &al)) -#define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \ - (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr)) -#endif /* _WIN32 */ -#endif /* DOS */ -#endif /* MACOS */ - -#ifndef udp_read -#define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED -#define udp_write( sb, b, l ) CLDAP NOT SUPPORTED -#endif /* udp_read */ +static int ber_realloc LDAP_P(( BerElement *ber, unsigned long len )); #define EXBUFSIZ 1024 -static int -ber_filbuf( Sockbuf *sb, long len ) -{ - short rc; -#ifdef LDAP_CONNECTIONLESS - int addrlen; -#endif /* LDAP_CONNECTIONLESS */ - - if ( sb->sb_ber.ber_buf == NULL ) { - if ( (sb->sb_ber.ber_buf = (char *) malloc( READBUFSIZ )) == - NULL ) - return( -1 ); - sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf; - sb->sb_ber.ber_end = sb->sb_ber.ber_buf; - } - - if ( sb->sb_naddr > 0 ) { -#ifdef LDAP_CONNECTIONLESS - rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen ); - - if ( sb->sb_debug ) { - lber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug, - "ber_filbuf udp_read %d bytes\n", - rc ); - if ( rc > 0 ) - lber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug, - sb->sb_ber.ber_buf, rc ); - } -#else /* LDAP_CONNECTIONLESS */ - rc = -1; -#endif /* LDAP_CONNECTIONLESS */ - } else { - rc = read( sb->sb_sd, sb->sb_ber.ber_buf, - ((sb->sb_options & LBER_NO_READ_AHEAD) && (len < READBUFSIZ)) ? - len : READBUFSIZ ); - } - - if ( rc > 0 ) { - sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1; - sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc; - return( (unsigned char)*sb->sb_ber.ber_buf ); - } - - return( -1 ); -} - - static long BerRead( Sockbuf *sb, char *buf, long len ) { @@ -163,20 +44,19 @@ BerRead( Sockbuf *sb, char *buf, long len ) long nread = 0; while ( len > 0 ) { - if ( (c = bergetc( sb, len )) < 0 ) { + if ( (c = lber_pvt_sb_read( sb, buf, len )) <= 0 ) { if ( nread > 0 ) break; return( c ); } - *buf++ = (char) c; - nread++; - len--; + buf+= c; + nread+=c; + len-=c; } return( nread ); } - long ber_read( BerElement *ber, char *buf, unsigned long len ) { @@ -271,7 +151,7 @@ ber_free( BerElement *ber, int freebuf ) int ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) { - long nwritten, towrite, rc; + long nwritten, towrite, rc; if ( ber->ber_rwptr == NULL ) { ber->ber_rwptr = ber->ber_buf; @@ -289,37 +169,18 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) #if !defined(MACOS) && !defined(DOS) if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) { - rc = write( sb->sb_fd, ber->ber_buf, towrite ); + rc = write( sb->sb_fd, ber->ber_rwptr, towrite ); if ( sb->sb_options & LBER_TO_FILE_ONLY ) { return( (int)rc ); } } #endif - + nwritten = 0; do { - if (sb->sb_naddr > 0) { -#ifdef LDAP_CONNECTIONLESS - rc = udp_write( sb, ber->ber_buf + nwritten, - (size_t)towrite ); -#else /* LDAP_CONNECTIONLESS */ - rc = -1; -#endif /* LDAP_CONNECTIONLESS */ - if ( rc <= 0 ) - return( -1 ); - - /* fake error if write was not atomic */ - if (rc < towrite) { -#ifdef EMSGSIZE - errno = EMSGSIZE; -#endif - return( -1 ); - } - } else { - if ( (rc = BerWrite( sb, ber->ber_rwptr, - (size_t) towrite )) <= 0 ) { - return( -1 ); - } + rc = lber_pvt_sb_write( sb, ber->ber_rwptr, towrite ); + if (rc<=0) { + return -1; } towrite -= rc; nwritten += rc; @@ -477,7 +338,7 @@ get_tag( Sockbuf *sb ) char *tagp; unsigned int i; - if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 ) + if ( lber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 ) return( LBER_DEFAULT ); if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) @@ -486,7 +347,7 @@ get_tag( Sockbuf *sb ) tagp = (char *) &tag; tagp[0] = xbyte; for ( i = 1; i < sizeof(long); i++ ) { - if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 ) + if ( lber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 ) return( LBER_DEFAULT ); tagp[i] = xbyte; @@ -553,7 +414,7 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber ) */ *len = netlen = 0; - if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) { + if ( lber_pvt_sb_read( sb, (char *) &lc, 1 ) != 1 ) { return( LBER_DEFAULT ); } if ( lc & 0x80 ) { @@ -582,12 +443,12 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber ) return( LBER_DEFAULT ); } #endif /* DOS && !_WIN32 */ - +#ifdef DEADWOOD if ( ( sb->sb_options & LBER_MAX_INCOMING_SIZE ) && *len > (unsigned long) sb->sb_max_incoming ) { return( LBER_DEFAULT ); } - +#endif if ( (ber->ber_buf = (char *) malloc( (size_t)*len )) == NULL ) { return( LBER_DEFAULT ); } @@ -598,7 +459,7 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber ) toread = (unsigned long)ber->ber_end - (unsigned long)ber->ber_rwptr; do { - if ( (rc = BerRead( sb, ber->ber_rwptr, (long)toread )) <= 0 ) { + if ( (rc = lber_pvt_sb_read( sb, ber->ber_rwptr, (long)toread )) <= 0 ) { return( LBER_DEFAULT ); } @@ -619,34 +480,34 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber ) return( ber->ber_tag ); } -Sockbuf *lber_sockbuf_alloc( void ) +Sockbuf *lber_pvt_sb_alloc( void ) { Sockbuf *sb = calloc(1, sizeof(Sockbuf)); - sb->sb_debug = lber_int_debug; + lber_pvt_sb_init( sb ); return sb; } -Sockbuf *lber_sockbuf_alloc_fd( int fd ) +Sockbuf *lber_pvt_sb_alloc_fd( int fd ) { - Sockbuf *sb = lber_sockbuf_alloc(); - sb->sb_sd = fd; - + Sockbuf *sb = lber_pvt_sb_alloc(); + lber_pvt_sb_set_desc( sb, fd ); + lber_pvt_sb_set_io( sb, &lber_pvt_sb_io_tcp, NULL ); return sb; } -void lber_sockbuf_free( Sockbuf *sb ) +void lber_pvt_sb_free( Sockbuf *sb ) { if(sb == NULL) return; - + lber_pvt_sb_destroy( sb ); free(sb); } -int lber_sockbuf_get_option( Sockbuf *sb, int opt, void *outvalue ) +int lber_pvt_sb_get_option( Sockbuf *sb, int opt, void *outvalue ) { return LBER_OPT_ERROR; } -int lber_sockbuf_set_option( Sockbuf *sb, int opt, void *invalue ) +int lber_pvt_sb_set_option( Sockbuf *sb, int opt, void *invalue ) { return LBER_OPT_ERROR; } diff --git a/libraries/liblber/lber-int.h b/libraries/liblber/lber-int.h index 37db2a986b..aeab66b2ba 100644 --- a/libraries/liblber/lber-int.h +++ b/libraries/liblber/lber-int.h @@ -50,28 +50,90 @@ struct berelement { }; #define NULLBER ((BerElement *) 0) +struct sockbuf; + +struct sockbuf_io { + int (*sbi_setup)( struct sockbuf * sb, void *arg ); + int (*sbi_remove)( struct sockbuf *sb ); + + long (*sbi_read)( struct sockbuf *sb, void *buf, long len ); + long (*sbi_write)( struct sockbuf *sb, void *buf, long len ); + int (*sbi_close)( struct sockbuf *sb ); +}; + +struct sockbuf_sec +{ + int (*sbs_setup)( struct sockbuf * sb, void *arg ); + int (*sbs_remove)( struct sockbuf *sb ); + + long (*sbs_protect)( struct sockbuf *sb, char *in, long *ilen, + char *out, long olen ); + long (*sbs_release)( struct sockbuf *sb, char *in, long ilen, + char *out0, long olen0, char *out1, long olen1 ); +}; + +struct sockbuf_buf +{ + long buf_size; + long buf_ptr; + long buf_end; + char *buf_base; +}; + +typedef struct sockbuf_io Sockbuf_IO; +typedef struct sockbuf_sec Sockbuf_Sec; +typedef struct sockbuf_buf Sockbuf_Buf; + +#define lber_pvt_sb_get_desc( sb ) ((sb)->sb_sd) +#define lber_pvt_sb_set_desc( sb, val ) ((sb)->sb_sd =(val)) +#define lber_pvt_sb_in_use( sb ) ((sb)->sb_sd!=-1) + +#ifdef USE_SASL +#define lber_pvt_sb_data_ready( sb ) \ +(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready) || ((sb)->sb_sec_ready)) +#else +#define lber_pvt_sb_data_ready( sb ) \ +(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready)) +#endif + struct sockbuf { short sb_item_type; /* always LBER_ITEM_SOCKBUF */ short sb_options; /* to support copying ber elements */ - int sb_debug; - int sb_fd; + int sb_debug:1; + int sb_non_block:1; + int sb_read_ahead:1; + + int sb_buf_ready:1; + int sb_trans_ready:1; + int sb_sec_ready:1; + + int sb_fd; + + void *sb_iodata; /* transport-layer data pointer */ + Sockbuf_IO *sb_io; /* I/O functions */ + +#ifdef LDAP_SASL + void *sb_sdata; /* security-layer data pointer */ + Sockbuf_Sec *sb_sec; +#endif + #ifndef MACOS int sb_sd; #else /* MACOS */ void *sb_sd; #endif /* MACOS */ - +#ifdef DEADWOOD long sb_max_incoming; - - BerElement sb_ber; - - int sb_naddr; /* > 0 implies using CLDAP (UDP) */ - void *sb_useaddr; /* pointer to sockaddr to use next */ - void *sb_fromaddr; /* pointer to message source sockaddr */ - void **sb_addrs; /* actually an array of pointers to - sockaddrs */ +#endif + Sockbuf_Buf sb_buf; +#ifdef LDAP_SASL + Sockbuf_Buf sb_sec_buf_in; + Sockbuf_Buf sb_sec_buf_out; + long sb_sec_prev_len; +#endif }; + #define READBUFSIZ 8192 struct seqorset { @@ -104,4 +166,25 @@ LDAP_F int lber_log_sos_dump LDAP_P(( int loglvl, Seqorset *sos )); +/* sockbuf.c */ + +LDAP_F int lber_pvt_sb_init LDAP_P(( Sockbuf *sb )); +LDAP_F int lber_pvt_sb_destroy LDAP_P(( Sockbuf *sb )); +#ifdef USE_SASL +LDAP_F int lber_pvt_sb_set_sec LDAP_P(( Sockbuf *sb, Sockbuf_Sec *sec, void *arg )); +LDAP_F int lber_pvt_sb_clear_sec LDAP_P(( Sockbuf *sb )); +#endif +LDAP_F int lber_pvt_sb_set_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *layer, void *arg )); +LDAP_F int lber_pvt_sb_clear_io LDAP_P(( Sockbuf *sb )); +LDAP_F int lber_pvt_sb_close LDAP_P((Sockbuf *sb )); +LDAP_F int lber_pvt_sb_set_nonblock LDAP_P(( Sockbuf *sb, int nb )); +LDAP_F int lber_pvt_sb_set_readahead LDAP_P(( Sockbuf *sb, int rh )); +LDAP_F long lber_pvt_sb_read LDAP_P(( Sockbuf *sb, void *buf, long len )); +LDAP_F long lber_pvt_sb_write LDAP_P(( Sockbuf *sb, void *buf, long len )); +LDAP_F int lber_pvt_sb_udp_set_dst LDAP_P((Sockbuf *sb, void *addr )); +LDAP_F void *lber_pvt_sb_udp_get_src LDAP_P((Sockbuf *sb )); + +extern Sockbuf_IO lber_pvt_sb_io_tcp; +extern Sockbuf_IO lber_pvt_sb_io_udp; + #endif /* _LBER_INT_H */ diff --git a/libraries/liblber/sockbuf.c b/libraries/liblber/sockbuf.c new file mode 100644 index 0000000000..8902af162d --- /dev/null +++ b/libraries/liblber/sockbuf.c @@ -0,0 +1,916 @@ +/* sockbuf.c - i/o routines with support for adding i/o layers. */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_IO_H +#include +#endif /* HAVE_IO_H */ + +#if defined( HAVE_SYS_FILIO_H ) +#include +#elif defined( HAVE_SYS_IOCTL_H ) +#include +#endif + +#include "lber-int.h" + +#ifdef LDAP_DEBUG +#include +#else +#define assert( cond ) +#endif + +#define MAX_BUF_SIZE 65535 +#define MIN_BUF_SIZE 4096 + +#define sockbuf_io_write( sb, buf, len ) \ +((sb)->sb_io->sbi_write( (sb), (buf), (len) )) + +#define sockbuf_io_read( sb, buf, len ) \ +((sb)->sb_io->sbi_read( (sb), (buf), (len) )) + +static long have_no_read( Sockbuf *sb, void *buf, long len ); +static long have_no_write( Sockbuf *sb, void *buf, long len ); +static int have_no_close( Sockbuf *sb ); + +static Sockbuf_IO lber_pvt_sb_IO_None= +{ + NULL, /* sbi_setup */ + NULL, /* sbi_release */ + have_no_read, /* sbi_read */ + have_no_write, /* sbi_write */ + have_no_close /* sbi_close */ +}; + +static void +update_status( Sockbuf *sb ) +{ + sb->sb_buf_ready = (sb->sb_buf.buf_ptr < sb->sb_buf.buf_end); +#ifdef USE_SASL + sb->sb_sec_ready = ((sb->sb_sec_buf_in.buf_end!=0) && + (sb->sb_sec_buf_in.buf_ptr >= + sb->sb_sec_buf_in.buf_end)); +#endif +} + +#ifdef LDAP_DEBUG +static int +status_is_ok( Sockbuf *sb ) +{ + int obr; + int osr; + obr = sb->sb_buf_ready; +#ifdef USE_SASL + osr = sb->sb_sec_ready; +#endif + update_status(sb); + if (obr!=sb->sb_buf_ready) + return 0; +#ifdef USE_SASL + if (osr!=sb->sb_sec_ready) + return 0; +#endif + return 1; +} +#endif + +#ifdef USE_SASL +static long +packet_length( char *buf ) +{ + long size; + size = (((unsigned long)buf[0])<<24)| + (((unsigned long)buf[1])<<16)| + (((unsigned long)buf[2])<<8)| + (((unsigned long)buf[3])); + + if ((size<0) || (size>MAX_BUF_SIZE)) { + /* somebody is trying to mess me up. */ + lber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug, + "SASL: received packet length of %d bytes\n", + size ); + size = 16; /* this should lead to an error. */ + } + + return size + 4; /* include the size !!! */ +} +#endif + +static int +grow_buffer( Sockbuf_Buf * buf, long minsize ) +{ + /* round to nearest 2k */ + if (minsize < MIN_BUF_SIZE) { + minsize = MIN_BUF_SIZE; + } else { + minsize=((minsize-1)|2047)+1; + if (minsize > MAX_BUF_SIZE) { + /* this could mean that somebody is trying to crash us. */ + return -1; + } + } + if (buf->buf_sizebuf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) { + /* empty buffer */ + if (buf->buf_base!=NULL) + free( buf->buf_base ); + assert( buf->buf_ptr==0 ); + assert( buf->buf_end==0 ); + buf->buf_base = malloc( minsize ); + if (buf->buf_base==NULL) + return -1; + } else { + char *nb; + nb = realloc( buf->buf_base, minsize ); + if (nb==NULL) + return -1; + buf->buf_base = nb; + } + buf->buf_size = minsize; + } + return 0; +} + +#ifdef USE_SASL +static long +sockbuf_sec_release( Sockbuf *sb, char *buf, long len ) +{ + /* when this is called: + * sb->sb_sec_buf_in.buf_base points to a packet. + * sb->sb_sec_buf_in.buf_ptr contains the total bytes read. + * sb->sb_sec_end.buf_end contains the packet length. + * + * sb->sb_buf.buf_ptr == sb->sb_buf.buf_end == 0; + */ + long rlen; + long total; + char *ptr; + char *end; + long size; + + assert( sb->sb_sec ); + assert( sb->sb_sec->sbs_release ); + assert( sb->sb_sec_buf_in.sb_ptr >= sb->sb_sec_buf_in.sb_end ); + + assert( sb->sb_buf.sb_ptr == 0 ); + assert( sb->sb_buf.sb_end == 0 ); + + assert( status_is_ok(sb) ); + + total = 0; + + ptr = sb->sb_sec_buf_in.buf_base; + end = ptr+ sb->sb_sec_buf_in.buf_ptr; + size = sb->sb_sec_buf_in.buf_end; + + sb->sb_sec_ready = 1; + + for(;(ptr+size<=end);) { + for(;;) { + rlen = sb->sb_sec->sbs_release( sb, ptr, size, + buf, len, + sb->sb_buf.buf_base, + sb->sb_buf.buf_size ); + if (rlen==0) { + /* this means a security violation. */ + return total; /* total ? total : 0 */ + } + if (rlen<0) { + /* this means that the buffer isn't big enough. */ + if (grow_buffer( &(sb->sb_buf), -rlen )<0) + /* memory violation. */ + return total; /* total ? total : 0 */ + continue; + } + /* if (rlen>0) */ + break; + } + total+=rlen; + + /* move to the next packet... */ + ptr+=size; + + if (ptr+4<=end) + size = packet_length( ptr ); + /* size is always at least 4, so the loop condition is always OK !!*/ + assert( size>=4 ); + + if (rlensb_buf_ready = (sb->sb_buf.buf_end = rlen - len) ? 1 : 0; + break; + } + } + + if (ptr+size>end) + sb->sb_sec_ready = 0; + /* clean up the mess. */ + if (ptrsb_sec_buf_in.buf_base, ptr, end-ptr ); + sb->sb_sec_buf_in.buf_ptr = 0; + sb->sb_sec_buf_in.buf_end -= (ptr - sb->sb_sec_buf_in.buf_base); + } + assert( status_is_ok(sb) ); + return total; +} + +static long +sockbuf_sec_protect( Sockbuf *sb, char *buf, long len ) +{ + long ret; + long blen; + long total; + + assert( sb->sb_sec_out.buf_end == 0 ); + assert( sb->sb_sec_out.buf_ptr == 0 ); + + assert( sb->sb_sec ); + assert( sb->sb_sec->sbs_protect ); + + assert( status_is_ok(sb) ); + + total = 0; + for(;(len);) { + for(;;) { + blen = len; + ret = sb->sb_sec->sbs_protect( sb, buf, &blen, + sb->sb_sec_out.buf_base+ + sb->sb_sec_out.buf_end, + sb->sb_sec_out.buf_size - + sb->sb_sec_out.buf_end ); + if (ret==0) + /* protection error ? */ + return total; + if (ret<0) { + if (grow_buffer( &(sb->sb_sec_out),-ret-sb->sb_sec_out.buf_end )<0) + /* memory error */ + return total; + continue; + } + /* else if (ret>0) */ + break; + } + sb->sb_sec_out.buf_end += ret; + len -= blen; + total += blen; + } + assert( status_is_ok(sb) ); + return total; +} +#endif + +static long +sockbuf_copy_out( Sockbuf *sb, char **buf, long len ) +{ + long blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr ); + assert( status_is_ok(sb) ); + if (blen) { + long rlen = (blensb_buf.buf_base + sb->sb_buf.buf_ptr, rlen ); + sb->sb_buf.buf_ptr+=rlen; + *buf+=rlen; + len -= rlen; + if (sb->sb_buf.buf_ptr >= sb->sb_buf.buf_end) { + sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0; + sb->sb_buf_ready = 0; + } else { + sb->sb_buf_ready = 1; + } + } + assert( status_is_ok(sb) ); + return len; +} + + +long +lber_pvt_sb_read( Sockbuf *sb, void *buf_arg, long len ) +{ + char *buf; + long ret; + + assert( status_is_ok(sb) ); +#if 0 + /* breaks slapd :-) */ + assert( lber_pvt_sb_in_use( sb ) ); +#endif + + buf = (char *) buf_arg; + + len = sockbuf_copy_out( sb, &buf, len ); + + if (len==0) { + return (buf - (char *) buf_arg); + } + +#ifdef USE_SASL + if (sb->sb_sec) { + int max; + assert( sb->sb_sec->sbs_release ); + assert( sb->sb_sec_buf_in.buf_base ); + if (sb->sb_read_ahead) { + max = sb->sb_sec_buf_in.buf_size - sb->sb_sec_buf_in.buf_ptr; + } else { + max = sb->sb_sec_buf_in.buf_end - sb->sb_sec_buf_in.buf_ptr; + if (max<=0) { + /* special situation. This means that we need to read the first + * four bytes for the packet length. + */ + max += 4; + } + } + for(;;) { + /* read from stream into sb_sec_buf_in */ + ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base + + sb->sb_sec_buf_in.buf_ptr, max ); + if (ret<=0) { + /* read error. return */ + goto do_return; + } + sb->sb_sec_buf_in.buf_ptr += ret; + + if (sb->sb_sec_buf_in.buf_ptr < sb->sb_sec_buf_in.buf_end) { + /* did not finish a packet. give up. */ + goto do_return; + } + + if (sb->sb_sec_buf_in.buf_end == 0) { + /* Were trying to read the first four bytes... */ + if (sb->sb_sec_buf_in.buf_ptr < 4) { + /* did not read enough for packet length. give up. */ + goto do_return; + } + /* calculate the packet length. */ + sb->sb_sec_buf_in.buf_end = + packet_length(sb->sb_sec_buf_in.buf_base ); + if ((sb->sb_sec_buf_in.buf_end > sb->sb_sec_buf_in.buf_size) && + (grow_buffer( &(sb->sb_sec_buf_in), sb->sb_sec_buf_in.buf_end)<0)) { + /* buffer has to be to big. exit with error. */ + ret = -1; + goto do_return; + } + if (sb->sb_sec_buf_in.buf_ptr >= sb_sec_buf_in.buf_end) { + /* finished packet. decode it. */ + goto decode_packet; + } + /* did not finish packet yet. try again ? */ + if (sb->sb_read_ahead) { + /* we were trying to read the max anyway. forget it */ + goto do_return; + } + } +decode_packet: + /* we read enough for at least 1 packet */ + ret = sockbuf_sec_release( sb, buf, len ); + if (ret<=0) { + /* something went wrong... */ + goto do_return; + } + buf+=ret; + len-=ret; + /* we are finished !!! */ + if ((len==0) || (ret!=max)) + goto do_return; + } + } else { +#endif + if (sb->sb_read_ahead) { + long max; + max = sb->sb_buf.buf_size - sb->sb_buf.buf_end; + if (max>len) { + ret = sockbuf_io_read( sb, + sb->sb_buf.buf_base + + sb->sb_buf.buf_end, + max ); + if (ret<=0) { + /* some error occured */ + goto do_return; + } + sb->sb_buf.buf_end += ret; + /* move out the data... */ + len = sockbuf_copy_out( sb, &buf, len ); + goto do_return; + } + } + /* no read_ahead, just try to put the data in the buf. */ + ret = sockbuf_io_read( sb, buf, len ); + if (ret>0) { + buf+=ret; + len-=ret; + } + /* we might as well return, since there is nothing to do... */ +#ifdef USE_SASL + } +#endif +do_return: + assert( status_is_ok(sb) ); + if ((ret<=0) && (buf==buf_arg)) { + /* there was an error. */ + return ret; + } + return (buf - ((char *) buf_arg)); +} + +#ifdef USE_SASL +long sockbuf_do_write( Sockbuf *sb ) +{ + long to_go; + to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr; + assert( to_go > 0 ); + /* there is something left of the last time... */ + ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+ + sb->sb_sec_out.buf_ptr, to_go ); + if (ret<=0) /* error */ + return ret; + sb->sb_sec_out.buf_ptr += ret; + if (retsb_sec) { + assert( sb->sb_sec_prev_len <= len ); + if (sb->sb_sec_prev_len) { + ret = sockbuf_do_write( sb ); + if (ret<=0) + return ret; + /* finished. */ + len -= sb->sb_sec_prev_len; + sb->sb_sec_prev_len = 0; + sb->sb_sec_out.buf_end = sb->sb_sec_out.buf_ptr = 0; + } + /* now protect the next packet. */ + ret = sockbuf_sec_protect( sb, buf, len ); + if (ret<=0) + return ret; + ret = sockbuf_do_write( sb ); + if (ret<=0) { + sb->sb_sec_prev_len = len; + return ret; + } + return len_arg; + } else { +#endif + return sockbuf_io_write( sb, buf, len ); +#ifdef USE_SASL + } +#endif +} + +int lber_pvt_sb_close( Sockbuf *sb ) +{ + int ret; + assert( sb->sb_io ); + assert( sb->sb_io->sbi_close ); + assert( status_is_ok(sb) ); + assert( lber_pvt_sb_in_use( sb ) ); + + ret = sb->sb_io->sbi_close( sb ); + lber_pvt_sb_set_desc( sb, -1 ); + + return ret; +} + +int lber_pvt_sb_set_readahead( Sockbuf *sb, int rh ) +{ + assert( status_is_ok(sb) ); + sb->sb_read_ahead = (rh!=0); + return 0; +} + +int lber_pvt_sb_set_nonblock( Sockbuf *sb, int nb ) +{ + assert( status_is_ok(sb) ); + if (nb) { + sb->sb_non_block = 1; +#if 0 + sb->sb_read_ahead = 1; +#endif + } else { + sb->sb_non_block = 0; +#if 0 + sb->sb_read_ahead = 0; +#endif + } + if (lber_pvt_sb_in_use(sb)) { + int status = (nb!=0); + if (ioctl( lber_pvt_sb_get_desc(sb), FIONBIO, (caddr_t)&status ) == -1 ) { + return -1; + } + } + return 0; +} + +#define sockbuf_buf_init( bb ) \ +(bb)->buf_base=NULL;\ +(bb)->buf_ptr = 0;\ +(bb)->buf_end = 0;\ +(bb)->buf_size = 0; + +static int +sockbuf_buf_destroy( Sockbuf_Buf *buf ) +{ + if (buf->buf_base) + free( buf->buf_base ); + sockbuf_buf_init( buf ); + return 0; +} + +int lber_pvt_sb_init( Sockbuf *sb ) +{ + sb->sb_item_type=LBER_ITEM_SOCKBUF; + sb->sb_options = 0; + sb->sb_debug = 0; + sb->sb_trans_ready = 0; + sb->sb_buf_ready = 0; +#ifdef USE_SASL + sb->sb_sec_ready = 0; +#endif + sb->sb_read_ahead = 0; + sb->sb_non_block = 0; + sb->sb_fd = -1; + sb->sb_iodata = NULL; + sb->sb_io = &lber_pvt_sb_IO_None; + sb->sb_sd = -1; +#ifdef DEADWOOD + sb->sb_max_incoming = 0; +#endif + sockbuf_buf_init( &(sb->sb_buf) ); +#ifdef USE_SASL + sockbuf_buf_init( &(sb->sb_sec_buf_in) ); + sockbuf_buf_init( &(sb->sb_sec_buf_out) ); + sb->sb_sdata = NULL; + sb->sb_sec = NULL; + sb->sb_sec_prev_len = 0; +#endif + return 0; +} + +int lber_pvt_sb_destroy( Sockbuf *sb ) +{ +#ifdef USE_SASL + lber_pvt_sb_clear_sec(sb); + sockbuf_buf_destroy( &(sb->sb_sec_buf_in) ); + sockbuf_buf_destroy( &(sb->sb_sec_buf_out) ); +#endif + lber_pvt_sb_clear_io(sb); + sockbuf_buf_destroy( &(sb->sb_buf) ); + return lber_pvt_sb_init( sb ); +} + +#ifdef USE_SASL +int lber_pvt_sb_set_sec( Sockbuf *sb, Sockbuf_Sec * sec, void *arg ) +{ + int len; + if ((sb->sb_sec) || (sec==NULL)) + return -1; + + sb->sb_sec = sec; + + if ((sec->sbs_setup) && (sec->sbs_setup( sb, arg)<0)) { + return -1; + } + + len = sb->sb_buf.buf_end - sb->sb_buf.buf_ptr; + + if (len>0) { + /* move this to the security layer. */ + if (grow_buffer( &(sb->sb_sec_buf_in), len )<0) + return -1; + memcpy( sb->sb_sec_buf_in.buf_base, + sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, len ); + sb->sb_sec_buf_in.buf_ptr = len; + sb->sb_sec_buf_in.buf_end = (len>4) ? packet_length( sb->sb_sec_buf_in ) : 0; + sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0; + } + update_status(); + return 0; +} + +int lber_pvt_sb_clear_sec( Sockbuf *sb ) +{ + if (sb->sb_buf.buf_ptr!=0) + return -1; + if (sb->sb_sec==NULL) + return -1; + if ((sb->sb_sec->sbs_remove) && (sb->sb_sec->sbs_remove(sb)<0)) + return -1; + + sb->sb_sec = NULL; + if (sb->sb_sec_buf_in.buf_ptr!=0) { + if (grow_buffer( &(sb->sb_buf), + sb->sb_buf.buf_end + sb->sb_sec_buf_in.buf_ptr)<0) + return -1; + memcpy( sb->sb_buf.buf_base + sb->sb_buf.buf_end, + sb->sb_sec_buf_in.buf_base, sb->sb_sec_buf_in.buf_ptr ); + sb->sb_buf.buf_end += sb->sb_sec_buf_in.buf_ptr; + sb->sb_buf_ready = 1; + } + sockbuf_buf_destroy( &(sb->sb_sec_buf_in) ); + assert( sb->sb_sec_buf.buf_end==0 ); + sockbuf_buf_destroy( &(sb->sb_sec_buf_out) ); + + sb->sb_sec_ready = 0; + + return 0; +} +#endif + +int lber_pvt_sb_set_io( Sockbuf *sb, Sockbuf_IO *trans, void *arg ) +{ + assert( sb->sb_io == &lber_pvt_sb_IO_None ); + + if (trans==NULL) + return -1; + + sb->sb_io = trans; + + if ((trans->sbi_setup) && (trans->sbi_setup( sb, arg)<0)) + return -1; + + return 0; +} + +int lber_pvt_sb_clear_io( Sockbuf *sb ) +{ + if (sb->sb_io==&lber_pvt_sb_IO_None) + return -1; + + if ((sb->sb_io->sbi_remove) && (sb->sb_io->sbi_remove( sb )<0)) + return -1; + + sb->sb_io = &lber_pvt_sb_IO_None; + + sb->sb_trans_ready = 0; + + return 0; +} + +/* + * Support for TCP + */ + +static long +stream_read( Sockbuf *sb, void *buf, long len ) +{ +#if defined(MACOS) +/* + * MacTCP/OpenTransport + */ + return tcpread( lber_pvt_sb_get_desc(sb), 0, (unsigned char *)buf, + len, NULL ); +#elif (defined(DOS) && (defined(PCNFS) || defined( WINSOCK))) \ + || defined( _WIN32) +/* + * PCNFS (under DOS) + */ +/* + * Windows Socket API (under DOS/Windows 3.x) + */ +/* + * 32-bit Windows Socket API (under Windows NT or Windows 95) + */ + return recv( lber_pvt_sb_get_desc(sb), buf, len, 0 ); +#elif (defined(DOS) && defined( NCSA )) +/* + * NCSA Telnet TCP/IP stack (under DOS) + */ + return nread( lber_pvt_sb_get_desc(sb), buf, len ); +#else + return read( lber_pvt_sb_get_desc(sb), buf, len ); +#endif +} + +static long +stream_write( Sockbuf *sb, void *buf, long len ) +{ +#if defined(MACOS) +/* + * MacTCP/OpenTransport + */ +#define MAX_WRITE 65535 + return tcpwrite( lber_pvt_sb_get_desc(sb), + (unsigned char *)(buf), + (lensb_iodata = malloc( sizeof( struct dgram_data ) ); + if (sb->sb_iodata==NULL) + return -1; + sb->sb_read_ahead = 1; /* important since udp is packet based. */ + return 0; +} + +static int +dgram_release( Sockbuf *sb ) +{ + free( sb->sb_iodata ); + return 0; +} + +static long +dgram_read( Sockbuf *sb, void *buf, long len ) +{ +#ifdef LDAP_CONNECTIONLESS + long rc; + int addrlen; + struct dgram_data *dd; + + dd = (struct dgram_data *)(sb->sb_iodata); + +# if !defined( MACOS) && !defined(DOS) && !defined( _WIN32) + addrlen = sizeof( struct sockaddr ); + rc=recvfrom( lber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->src), &addrlen ); +# else + UDP not supported +# endif + + if ( sb->sb_debug ) { + lber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug, + "dgram_read udp_read %d bytes\n", + rc ); + if ( rc > 0 ) + lber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug, + buf, rc ); + } + return rc; +# else /* LDAP_CONNECTIONLESS */ + return -1; +# endif /* LDAP_CONNECTIONLESS */ +} + +static long +dgram_write( Sockbuf *sb, void *buf, long len ) +{ +#ifdef LDAP_CONNECTIONLESS + int rc; + struct dgram_data *dd; + + dd = (struct dgram_data *)(sb->sb_iodata); + +# if !defined( MACOS) && !defined(DOS) && !defined( _WIN32) + rc=sendto( lber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->dst), + sizeof( struct sockaddr ) ); +# else + UDP not supported +# endif + if ( rc <= 0 ) + return( -1 ); + + /* fake error if write was not atomic */ + if (rc < len) { +# ifdef EMSGSIZE + errno = EMSGSIZE; +# endif + return( -1 ); + } + return rc; +#else + return -1; +#endif +} + +static int +dgram_close( Sockbuf *sb ) +{ + tcp_close( lber_pvt_sb_get_desc(sb) ); + return 0; +} + +Sockbuf_IO lber_pvt_sb_io_udp= +{ + dgram_setup, /* sbi_setup */ + dgram_release, /* sbi_release */ + dgram_read, /* sbi_read */ + dgram_write, /* sbi_write */ + dgram_close, /* sbi_close */ +}; + +int lber_pvt_sb_udp_set_dst(Sockbuf *sb, void *addr ) +{ + struct dgram_data *dd; + assert( sb->sb_io == &lber_pvt_sb_io_udp ); + dd = (struct dgram_data *) (sb->sb_iodata); + memcpy( &(dd->dst), addr, sizeof( struct sockaddr ) ); + return 0; +} + +void *lber_pvt_sb_udp_get_src( Sockbuf *sb ) +{ + struct dgram_data *dd; + assert( sb->sb_io == &lber_pvt_sb_io_udp ); + dd = (struct dgram_data *) (sb->sb_iodata); + return &(dd->src); +} + +/* + * debug routines. + * + * BUGS: + * These routines should really call abort, but at the moment that would + * break the servers. + */ + +static long +have_no_read( Sockbuf *sb, void *buf, long len ) +{ + lber_log_printf( LDAP_DEBUG_ANY, lber_int_debug, + "warning: reading from uninitialized sockbuf\n"); + errno = EBADF; + return -1; +} + +static long +have_no_write( Sockbuf *sb, void *buf, long len ) +{ + lber_log_printf( LDAP_DEBUG_ANY, lber_int_debug, + "warning: writing to uninitialized sockbuf\n"); + errno = EBADF; + return -1; +} + +static int +have_no_close( Sockbuf *sb ) +{ + assert( 0 ); + return -1; +} diff --git a/libraries/libldap/abandon.c b/libraries/libldap/abandon.c index a41199a581..2fac95f770 100644 --- a/libraries/libldap/abandon.c +++ b/libraries/libldap/abandon.c @@ -98,7 +98,7 @@ do_abandon( LDAP *ld, int origid, int msgid ) ld->ld_errno = LDAP_NO_MEMORY; } else { #ifdef LDAP_CONNECTIONLESS - if ( ld->ld_sb.sb_naddr > 0 ) { + if ( ld->ld_cldapnaddr > 0 ) { err = ber_printf( ber, "{isti}", ++ld->ld_msgid, ld->ld_cldapdn, LDAP_REQ_ABANDON, msgid ); diff --git a/libraries/libldap/cldap.c b/libraries/libldap/cldap.c index d5ca787bd3..55f1be4fb9 100644 --- a/libraries/libldap/cldap.c +++ b/libraries/libldap/cldap.c @@ -84,19 +84,19 @@ cldap_open( char *host, int port ) close( s ); return( NULL ); } - if (( ld = ldap_init( host, port )) == NULL ) { close( s ); return( NULL ); } - if ( (ld->ld_sb.sb_fromaddr = (void *) calloc( 1, - sizeof( struct sockaddr ))) == NULL ) { + + ld->ld_cldapnaddr = 0; + ld->ld_cldapaddrs = NULL; - ldap_ld_free(ld, 1); - return( NULL ); - } - ld->ld_sb.sb_sd = s; - ld->ld_sb.sb_naddr = 0; + if (lber_pvt_sb_set_io( &(ld->ld_sb), &lber_pvt_sb_io_udp, NULL )<0) { + ldap_ld_free(ld, 1 ); + return NULL; + } + ld->ld_version = LDAP_VERSION; sock.sin_family = AF_INET; @@ -155,7 +155,7 @@ cldap_open( char *host, int port ) } } - if ( ld->ld_sb.sb_addrs == NULL + if ( ld->ld_cldapaddrs == NULL #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS || ( ld->ld_defconn = ldap_new_connection( ld, NULL, 1,0,0 )) == NULL #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ @@ -164,15 +164,16 @@ cldap_open( char *host, int port ) DO_RETURN( NULL ); } - ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ 0 ]; + lber_pvt_sb_udp_set_dst( &ld->ld_sb, ld->ld_cldapaddrs[0] ); + cldap_setretryinfo( ld, 0, 0 ); #ifdef LDAP_DEBUG putchar( '\n' ); - for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) { + for ( i = 0; i < ld->ld_cldapnaddr; ++i ) { Debug( LDAP_DEBUG_TRACE, "end of cldap_open address %d is %s\n", i, inet_ntoa( ((struct sockaddr_in *) - ld->ld_sb.sb_addrs[ i ])->sin_addr ), 0 ); + ld->ld_cldapaddrs[ i ])->sin_addr ), 0 ); } #endif @@ -217,11 +218,13 @@ cldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs, if ( cri.cri_try != 0 ) { --ld->ld_msgid; /* use same id as before */ } - ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ cri.cri_useaddr ]; + + lber_pvt_sb_udp_set_dst( &(ld->ld_sb), + ld->ld_cldapaddrs[ cri.cri_useaddr ] ); Debug( LDAP_DEBUG_TRACE, "cldap_search_s try %d (to %s)\n", cri.cri_try, inet_ntoa( ((struct sockaddr_in *) - ld->ld_sb.sb_useaddr)->sin_addr ), 0 ); + ld->ld_cldapaddrs[ cri.cri_useaddr ])->sin_addr), 0 ); if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly )) == -1 ) { @@ -253,12 +256,12 @@ add_addr( LDAP *ld, struct sockaddr *sap ) ld->ld_errno = LDAP_NO_MEMORY; return( -1 ); } - - if ( ld->ld_sb.sb_naddr == 0 ) { + + if ( ld->ld_cldapnaddr == 0 ) { addrs = (struct sockaddr **)malloc( sizeof(struct sockaddr *)); } else { - addrs = (struct sockaddr **)realloc( ld->ld_sb.sb_addrs, - ( ld->ld_sb.sb_naddr + 1 ) * sizeof(struct sockaddr *)); + addrs = (struct sockaddr **)realloc( ld->ld_cldapaddrs, + ( ld->ld_cldapnaddr + 1 ) * sizeof(struct sockaddr *)); } if ( addrs == NULL ) { @@ -268,8 +271,8 @@ add_addr( LDAP *ld, struct sockaddr *sap ) } SAFEMEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr )); - addrs[ ld->ld_sb.sb_naddr++ ] = newsap; - ld->ld_sb.sb_addrs = (void **)addrs; + addrs[ ld->ld_cldapnaddr++ ] = newsap; + ld->ld_cldapaddrs = (void **)addrs; return( 0 ); } @@ -287,14 +290,14 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res, fromaddr = -1; if ( crip->cri_try == 0 ) { - crip->cri_maxtries = ld->ld_cldaptries * sb->sb_naddr; + crip->cri_maxtries = ld->ld_cldaptries * ld->ld_cldapnaddr; crip->cri_timeout = ld->ld_cldaptimeout; crip->cri_useaddr = 0; Debug( LDAP_DEBUG_TRACE, "cldap_result tries %d timeout %d\n", ld->ld_cldaptries, ld->ld_cldaptimeout, 0 ); } - if ((tv.tv_sec = crip->cri_timeout / sb->sb_naddr) < 1 ) { + if ((tv.tv_sec = crip->cri_timeout / ld->ld_cldapnaddr) < 1 ) { tv.tv_sec = 1; } tv.tv_usec = 0; @@ -319,7 +322,7 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res, ret = LDAP_TIMEOUT; --crip->cri_try; } else { - if ( ++crip->cri_useaddr >= sb->sb_naddr ) { + if ( ++crip->cri_useaddr >= ld->ld_cldapnaddr ) { /* * new round: reset address to first one and * double the timeout @@ -350,14 +353,17 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res, msgid, id, 0 ); ret = -1; /* ignore and keep looking */ } else { + struct sockaddr_in * src; /* * got a result: determine which server it came from * decode into ldap message chain */ - for ( fromaddr = 0; fromaddr < sb->sb_naddr; ++fromaddr ) { + src = (struct sockaddr_in *) lber_pvt_sb_udp_get_src( sb ); + + for ( fromaddr = 0; fromaddr < ld->ld_cldapnaddr; ++fromaddr ) { if ( memcmp( &((struct sockaddr_in *) - sb->sb_addrs[ fromaddr ])->sin_addr, - &((struct sockaddr_in *)sb->sb_fromaddr)->sin_addr, + ld->ld_cldapaddrs[ fromaddr ])->sin_addr, + &(src->sin_addr), sizeof( struct in_addr )) == 0 ) { break; } @@ -380,18 +386,19 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res, */ if ( ret != -1 ) { i = crip->cri_try; - if ( i >= sb->sb_naddr ) { - i = sb->sb_naddr - 1; + if ( i >= ld->ld_cldapnaddr ) { + i = ld->ld_cldapnaddr - 1; } for ( ; i >= 0; --i ) { if ( i == fromaddr ) { continue; } - sb->sb_useaddr = sb->sb_addrs[ i ]; + lber_pvt_sb_udp_set_dst( sb, ld->ld_cldapaddrs[i] ); + Debug( LDAP_DEBUG_TRACE, "cldap_result abandoning id %d (to %s)\n", msgid, inet_ntoa( ((struct sockaddr_in *) - sb->sb_useaddr)->sin_addr ), 0 ); + ld->ld_cldapaddrs[i])->sin_addr ), 0 ); (void) ldap_abandon( ld, msgid ); } } diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 1369f877c5..474807582e 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -173,6 +173,11 @@ typedef struct ldapcache { } LDAPCache; #define NULLLDCACHE ((LDAPCache *)NULL) +/* + * handy macro for checking if handle is connectionless + */ + +#define LDAP_IS_CLDAP(ld) ((ld)->ld_cldapnaddr>0) /* * structure representing an ldap connection @@ -219,8 +224,11 @@ struct ldap { int *ld_abandoned; /* array of abandoned requests */ char ld_attrbuffer[LDAP_MAX_ATTR_LEN]; LDAPCache *ld_cache; /* non-null if cache is initialized */ - char *ld_cldapdn; /* DN used in connectionless search */ - + /* stuff used by connectionless searches. */ + char *ld_cldapdn; /* DN used in connectionless search */ + int ld_cldapnaddr; /* number of addresses */ + void **ld_cldapaddrs;/* addresses to send request to */ + /* do not mess with the rest though */ BERTranslateProc ld_lber_encode_translate_proc; BERTranslateProc ld_lber_decode_translate_proc; diff --git a/libraries/libldap/open.c b/libraries/libldap/open.c index 259bf8a438..a1db516cbb 100644 --- a/libraries/libldap/open.c +++ b/libraries/libldap/open.c @@ -24,6 +24,7 @@ #include "ldap-int.h" + /* * ldap_open - initialize and connect to an ldap server. A magic cookie to * be used for future communication is returned on success, NULL on failure. @@ -143,7 +144,7 @@ ldap_init( char *defhost, int defport ) WSACleanup( ); return( NULL ); } - + /* copy the global options */ memcpy(&ld->ld_options, &openldap_ldap_global_options, sizeof(ld->ld_options)); @@ -198,7 +199,8 @@ ldap_init( char *defhost, int defport ) /* we'll assume we're talking version 2 for now */ ld->ld_version = LDAP_VERSION2; - ld->ld_sb.sb_sd = -1; + lber_pvt_sb_init( &(ld->ld_sb) ); + return( ld ); } @@ -255,6 +257,8 @@ open_ldap_connection( LDAP *ld, Sockbuf *sb, char *host, int defport, if ( rc == -1 ) { return( rc ); } + + lber_pvt_sb_set_io( sb, &lber_pvt_sb_io_tcp, NULL ); if ( krbinstancep != NULL ) { #ifdef HAVE_KERBEROS diff --git a/libraries/libldap/options.c b/libraries/libldap/options.c index 0d0400a6b6..7bc03b141d 100644 --- a/libraries/libldap/options.c +++ b/libraries/libldap/options.c @@ -111,7 +111,7 @@ ldap_get_option( break; } - * (int *) outvalue = ld->ld_sb.sb_sd; + * (int *) outvalue = lber_pvt_sb_get_desc( &(ld->ld_sb) ); return 0; case LDAP_OPT_DEREF: diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 6d501565a9..41f3dd1787 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -140,9 +140,10 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address, } } - sb->sb_sd = s; + lber_pvt_sb_set_desc( sb, s ); if ( connected ) { + #ifdef notyet #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS status = 0; @@ -158,8 +159,6 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address, } DO_RETURN( rc ); - - } #undef DO_RETURN @@ -168,11 +167,11 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address, void ldap_close_connection( Sockbuf *sb ) { - tcp_close( sb->sb_sd ); + lber_pvt_sb_close( sb ); } -#ifdef HAVE_KERBEROS +#if defined( HAVE_KERBEROS ) || defined( HAVE_TLS ) char * ldap_host_connected_to( Sockbuf *sb ) { @@ -189,7 +188,8 @@ ldap_host_connected_to( Sockbuf *sb ) (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in )); len = sizeof( sin ); - if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) { + + if ( getpeername( lber_pvt_sb_get_desc(sb), (struct sockaddr *)&sin, &len ) == -1 ) { return( NULL ); } @@ -204,7 +204,8 @@ ldap_host_connected_to( Sockbuf *sb ) &hp,&local_h_errno ) ==0 ) && (hp != NULL) ) { if ( hp->h_name != NULL ) { - DO_RETURN( strdup( hp->h_name )); + char *host = strdup( hp->h_name ); + DO_RETURN( host ); } } @@ -212,7 +213,7 @@ ldap_host_connected_to( Sockbuf *sb ) } #undef DO_RETURN -#endif /* HAVE_KERBEROS */ +#endif /* HAVE_KERBEROS || HAVE_TLS */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS @@ -231,8 +232,8 @@ ldap_mark_select_write( LDAP *ld, Sockbuf *sb ) struct selectinfo *sip; sip = (struct selectinfo *)ld->ld_selectinfo; - - if ( !FD_ISSET( sb->sb_sd, &sip->si_writefds )) { + + if ( !FD_ISSET( lber_pvt_sb_get_desc(sb), &sip->si_writefds )) { FD_SET( (u_int) sb->sb_sd, &sip->si_writefds ); } } @@ -245,7 +246,7 @@ ldap_mark_select_read( LDAP *ld, Sockbuf *sb ) sip = (struct selectinfo *)ld->ld_selectinfo; - if ( !FD_ISSET( sb->sb_sd, &sip->si_readfds )) { + if ( !FD_ISSET( lber_pvt_sb_get_desc(sb), &sip->si_readfds )) { FD_SET( (u_int) sb->sb_sd, &sip->si_readfds ); } } @@ -258,8 +259,8 @@ ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ) sip = (struct selectinfo *)ld->ld_selectinfo; - FD_CLR( (u_int) sb->sb_sd, &sip->si_writefds ); - FD_CLR( (u_int) sb->sb_sd, &sip->si_readfds ); + FD_CLR( (u_int) lber_pvt_sb_get_desc(sb), &sip->si_writefds ); + FD_CLR( (u_int) lber_pvt_sb_get_desc(sb), &sip->si_readfds ); } @@ -270,7 +271,7 @@ ldap_is_write_ready( LDAP *ld, Sockbuf *sb ) sip = (struct selectinfo *)ld->ld_selectinfo; - return( FD_ISSET( sb->sb_sd, &sip->si_use_writefds )); + return( FD_ISSET( lber_pvt_sb_get_desc(sb), &sip->si_use_writefds )); } @@ -281,7 +282,7 @@ ldap_is_read_ready( LDAP *ld, Sockbuf *sb ) sip = (struct selectinfo *)ld->ld_selectinfo; - return( FD_ISSET( sb->sb_sd, &sip->si_use_readfds )); + return( FD_ISSET( lber_pvt_sb_get_desc(sb), &sip->si_use_readfds )); } diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index 6dfa9d1718..a9f7dbf0fa 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -80,7 +80,7 @@ ldap_send_initial_request( LDAP *ld, unsigned long msgtype, char *dn, Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 ); - if ( ld->ld_sb.sb_sd == -1 ) { + if ( ! lber_pvt_sb_in_use(&ld->ld_sb ) ) { /* not connected yet */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS @@ -296,8 +296,7 @@ ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, * XXX open connection synchronously for now */ if (( lc = (LDAPConn *)calloc( 1, sizeof( LDAPConn ))) == NULL || - ( !use_ldsb && ( sb = (Sockbuf *)calloc( 1, sizeof( Sockbuf ))) - == NULL )) { + ( !use_ldsb && ( (sb = lber_pvt_sb_alloc()) == NULL ))) { if ( lc != NULL ) { free( (char *)lc ); } @@ -321,7 +320,7 @@ ldap_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, if ( srv == NULL ) { if ( !use_ldsb ) { - free( (char *)lc->lconn_sb ); + lber_pvt_sb_free( lc->lconn_sb ); } free( (char *)lc ); ld->ld_errno = LDAP_SERVER_DOWN; @@ -444,9 +443,7 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) ldap_send_unbind( ld, lc->lconn_sb ); } ldap_close_connection( lc->lconn_sb ); - if ( lc->lconn_sb->sb_ber.ber_buf != NULL ) { - free( lc->lconn_sb->sb_ber.ber_buf ); - } + lber_pvt_sb_destroy( lc->lconn_sb ); } prevlc = NULL; for ( tmplc = ld->ld_conns; tmplc != NULL; @@ -466,7 +463,7 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) free( lc->lconn_krbinstance ); } if ( lc->lconn_sb != &ld->ld_sb ) { - free( (char *)lc->lconn_sb ); + lber_pvt_sb_free( lc->lconn_sb ); } free( lc ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: actually freed\n", diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index ef3a86fad3..df532f08f6 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -166,7 +166,7 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, while ( rc == -2 ) { #ifndef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS /* hack attack */ - if ( ld->ld_sb.sb_ber.ber_ptr >= ld->ld_sb.sb_ber.ber_end ) { + if ( ! lber_pvt_sb_data_ready(&ld->ld_sb) ) { rc = ldap_select1( ld, tvp ); if ( rc == 0 || ( rc == -1 && ( @@ -192,8 +192,7 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, } #endif /* LDAP_DEBUG */ for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { - if ( lc->lconn_sb->sb_ber.ber_ptr < - lc->lconn_sb->sb_ber.ber_end ) { + if ( lber_pvt_sb_data_ready(lc->lconn_sb) ) { rc = read1msg( ld, msgid, all, lc->lconn_sb, lc, result ); break; @@ -610,7 +609,7 @@ ldap_select1( LDAP *ld, struct timeval *timeout ) } FD_ZERO( &readfds ); - FD_SET( ld->ld_sb.sb_sd, &readfds ); + FD_SET( lber_pvt_sb_get_desc(&ld->ld_sb), &readfds ); return( select( tblsize, &readfds, 0, 0, timeout ) ); } @@ -732,7 +731,7 @@ cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber ) int rc; unsigned long tag, len; - if ( ld->ld_sb.sb_ber.ber_ptr >= ld->ld_sb.sb_ber.ber_end ) { + if ( ! lber_pvt_sb_data_ready(&ld->ld_sb) ) { rc = ldap_select1( ld, timeout ); if ( rc == -1 || rc == 0 ) { ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c index 171641e30f..117d5f4d2e 100644 --- a/libraries/libldap/search.c +++ b/libraries/libldap/search.c @@ -122,7 +122,7 @@ ldap_build_search_req( LDAP *ld, char *base, int scope, char *filter, } #ifdef LDAP_CONNECTIONLESS - if ( ld->ld_sb.sb_naddr > 0 ) { + if ( ld->ld_cldapnaddr > 0 ) { err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid, ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref, ld->ld_sizelimit, ld->ld_timelimit, attrsonly ); diff --git a/libraries/libldap/unbind.c b/libraries/libldap/unbind.c index 63237ba8e2..a1c91e5e71 100644 --- a/libraries/libldap/unbind.c +++ b/libraries/libldap/unbind.c @@ -39,7 +39,7 @@ ldap_ld_free( LDAP *ld, int close ) LDAPRequest *lr, *nextlr; #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ - if ( ld->ld_sb.sb_naddr == 0 ) { + if ( ld->ld_cldapnaddr == 0 ) { #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS /* free LDAP structure and outstanding requests/responses */ for ( lr = ld->ld_requests; lr != NULL; lr = nextlr ) { @@ -60,11 +60,10 @@ ldap_ld_free( LDAP *ld, int close ) } else { int i; - for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) { - free( ld->ld_sb.sb_addrs[ i ] ); + for ( i = 0; i < ld->ld_cldapnaddr; ++i ) { + free( ld->ld_cldapaddrs[ i ] ); } - free( ld->ld_sb.sb_addrs ); - free( ld->ld_sb.sb_fromaddr ); + free( ld->ld_cldapaddrs ); } for ( lm = ld->ld_responses; lm != NULL; lm = next ) { @@ -86,10 +85,6 @@ ldap_ld_free( LDAP *ld, int close ) free( ld->ld_ufnprefix ); if ( ld->ld_filtd != NULL ) ldap_getfilter_free( ld->ld_filtd ); -#ifndef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS - if ( ld->ld_sb.sb_ber.ber_buf != NULL ) - free( ld->ld_sb.sb_ber.ber_buf ); -#endif /* !LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ if ( ld->ld_abandoned != NULL ) free( ld->ld_abandoned ); @@ -104,8 +99,10 @@ ldap_ld_free( LDAP *ld, int close ) if ( ld->ld_options.ldo_defhost != NULL ) free( ld->ld_options.ldo_defhost ); + lber_pvt_sb_destroy( &(ld->ld_sb) ); + free( (char *) ld ); - + WSACleanup(); return( err ); diff --git a/servers/ldapd/main.c b/servers/ldapd/main.c index 85f9b5d71f..95430ea99a 100644 --- a/servers/ldapd/main.c +++ b/servers/ldapd/main.c @@ -515,18 +515,10 @@ do_queries( conn_init(); } - (void) memset( (void *) &sb, '\0', sizeof( sb ) ); - sb.sb_sd = clientsock; - sb.sb_naddr = ( udp ) ? 1 : 0; -#ifdef LDAP_CONNECTIONLESS - sb.sb_addrs = (void **)saddrlist; - sb.sb_fromaddr = &faddr; - sb.sb_useaddr = saddrlist[ 0 ] = &saddr; -#endif - sb.sb_ber.ber_buf = NULL; - sb.sb_ber.ber_ptr = NULL; - sb.sb_ber.ber_end = NULL; - + lber_pvt_sb_init( &sb ); + lber_pvt_sb_set_desc( &sb, clientsock ); + lber_pvt_sb_set_io( &sb, (udp) ? &lber_pvt_sb_io_udp : + &lber_pvt_sb_io_tcp, NULL ); timeout.tv_sec = idletime; timeout.tv_usec = 0; for ( ;; ) { @@ -555,7 +547,7 @@ do_queries( * already waiting for us on the client sock. */ - if ( sb.sb_ber.ber_ptr >= sb.sb_ber.ber_end ) { + if ( ! lber_pvt_sb_data_ready( &sb ) ) { if ( (rc = select( dtblsize, &readfds, 0, 0, udp ? 0 : &timeout )) < 1 ) { #ifdef LDAP_DEBUG @@ -581,7 +573,7 @@ do_queries( } } - if ( sb.sb_ber.ber_ptr < sb.sb_ber.ber_end || + if ( lber_pvt_sb_data_ready( &sb ) || FD_ISSET( clientsock, &readfds ) ) { client_request( &sb, conns, udp ); } else { diff --git a/servers/ldapd/request.c b/servers/ldapd/request.c index 28dae68661..222500b6f9 100644 --- a/servers/ldapd/request.c +++ b/servers/ldapd/request.c @@ -68,12 +68,15 @@ client_request( BerElement ber, *copyofber; struct msg *m; static int bound; - +#ifdef LDAP_CONNECTIONLESS + struct sockaddr_in *sai; +#endif Debug( LDAP_DEBUG_TRACE, "client_request%s\n", udp ? " udp" : "", 0, 0 ); /* * Get the ldap message, which is a sequence of message id + * and then the actual request choice. */ @@ -85,9 +88,9 @@ client_request( #ifdef LDAP_CONNECTIONLESS if ( udp && dosyslog ) { + sai = (struct sockaddr_in *)lber_pvt_sb_udp_get_src( &clientsb ); syslog( LOG_INFO, "UDP request from unknown (%s)", - inet_ntoa( ((struct sockaddr_in *) - clientsb->sb_fromaddr)->sin_addr )); + inet_ntoa( sai->sin_addr ) ); } #endif @@ -189,16 +192,17 @@ client_request( free( ber.ber_buf ); return; } - + sai = (struct sockaddr_in *) lber_pvt_sb_udp_get_src( &clientsb ); + if ( get_cldap_msg( msgid, tag, - (struct sockaddr *)clientsb->sb_fromaddr ) != NULL ) { + (struct sockaddr *)sai ) != NULL ) { /* * duplicate request: toss this one */ Debug( LDAP_DEBUG_TRACE, "client_request tossing dup request id %ld from %s\n", - msgid, inet_ntoa( ((struct sockaddr_in *) - clientsb->sb_fromaddr)->sin_addr ), 0 ); + msgid, inet_ntoa( sai->sin_addr ), 0 ); + free( ber.ber_buf ); return; } @@ -208,7 +212,7 @@ client_request( m = add_msg( msgid, tag, copyofber, dsaconn, udp, #ifdef LDAP_CONNECTIONLESS - (struct sockaddr *)clientsb->sb_fromaddr ); + (struct sockaddr *)sai ); #else NULL ); #endif diff --git a/servers/ldapd/result.c b/servers/ldapd/result.c index 498ef4a701..777aec2e68 100644 --- a/servers/ldapd/result.c +++ b/servers/ldapd/result.c @@ -280,12 +280,12 @@ send_ldap_msgresult( { #ifdef LDAP_CONNECTIONLESS if ( m->m_cldap ) { - SAFEMEMCPY( (char *)sb->sb_useaddr, &m->m_clientaddr, - sizeof( struct sockaddr )); + lber_pvt_sb_udp_set_dst( &sb, &m->m_clientaddr ); + Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n", inet_ntoa(((struct sockaddr_in *) - sb->sb_useaddr)->sin_addr ), - ((struct sockaddr_in *)sb->sb_useaddr)->sin_port, 0 ); + &m->m_clientaddr)->sin_addr ), + ((struct sockaddr_in *)&m->m_clientaddr)->sin_port, 0 ); } #endif return( send_ldap_result( sb, tag, m->m_msgid, err, matched, text ) ); @@ -305,7 +305,7 @@ send_ldap_result( int rc; #ifdef LDAP_CONNECTIONLESS int cldap; - cldap = ( sb->sb_naddr > 0 ); + cldap = ( sb->sb_io == &lber_pvt_sb_io_udp ); #endif Debug( LDAP_DEBUG_TRACE, "send_ldap_result\n", 0, 0, 0 ); diff --git a/servers/ldapd/search.c b/servers/ldapd/search.c index cd413856c4..33afd35713 100644 --- a/servers/ldapd/search.c +++ b/servers/ldapd/search.c @@ -700,8 +700,8 @@ search_result( LDAP_OPERATIONS_ERROR, NULL, "ber_printf" ); return; } - SAFEMEMCPY( (char *)sb->sb_useaddr, &m->m_clientaddr, - sizeof( struct sockaddr )); + lber_pvt_sb_udp_set_dst( sb, &m->m_clientaddr ); + if ( ber_flush( sb, ber, 1 ) != 0 ) { send_ldap_msgresult( sb, SEARCHRESTAG, m, LDAP_RESULTS_TOO_LARGE, NULL, "ber_flush" ); diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 4a8ed5462f..249f1b82cb 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -133,7 +133,7 @@ connection_activity( != LDAP_TAG_MESSAGE ) { Debug( LDAP_DEBUG_TRACE, "ber_get_next on fd %d failed errno %d (%s)\n", - conn->c_sb.sb_sd, errno, errno > -1 && errno < sys_nerr ? + lber_pvt_sb_get_desc(&conn->c_sb), errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] : "unknown" ); Debug( LDAP_DEBUG_TRACE, "*** got %ld of %lu so far\n", (long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf), diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 230d672edb..25ff2c1cac 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -26,6 +26,12 @@ #include #endif +#ifdef LDAP_DEBUG +#include +#else +#define assert( cond ) +#endif + #ifdef HAVE_TCPD #include @@ -80,12 +86,7 @@ slapd_daemon( c[i].c_addr = NULL; c[i].c_domain = NULL; c[i].c_ops = NULL; - c[i].c_sb.sb_sd = -1; - c[i].c_sb.sb_options = LBER_NO_READ_AHEAD; - c[i].c_sb.sb_naddr = 0; - c[i].c_sb.sb_ber.ber_buf = NULL; - c[i].c_sb.sb_ber.ber_ptr = NULL; - c[i].c_sb.sb_ber.ber_end = NULL; + lber_pvt_sb_init( &c[i].c_sb ); c[i].c_writewaiter = 0; c[i].c_connid = 0; ldap_pvt_thread_mutex_init( &c[i].c_dnmutex ); @@ -150,6 +151,7 @@ slapd_daemon( struct timeval zero; struct timeval *tvp; int len, pid; + int data_ready; char *client_name; char *client_addr; @@ -165,14 +167,19 @@ slapd_daemon( Debug( LDAP_DEBUG_CONNS, "listening for connections on %d, activity on:", tcps, 0, 0 ); + + data_ready = 0; ldap_pvt_thread_mutex_lock( &new_conn_mutex ); for ( i = 0; i < dtblsize; i++ ) { - if ( c[i].c_sb.sb_sd != -1 ) { - FD_SET( c[i].c_sb.sb_sd, &readfds ); - + if ( lber_pvt_sb_in_use( &c[i].c_sb )) { + FD_SET( lber_pvt_sb_get_desc(&c[i].c_sb), + &readfds ); + if (lber_pvt_sb_data_ready(&c[i].c_sb)) + data_ready = 1; if ( c[i].c_writewaiter ) { - FD_SET( c[i].c_sb.sb_sd, &writefds ); + FD_SET( lber_pvt_sb_get_desc(&c[i].c_sb), + &writefds ); } Debug( LDAP_DEBUG_CONNS, " %dr%s", i, c[i].c_writewaiter ? "w" : "", 0 ); @@ -184,9 +191,9 @@ slapd_daemon( Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n", active_threads, 0, 0 ); #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS ) - tvp = NULL; + tvp = (data_ready) ? &zero : NULL; #else - tvp = active_threads ? &zero : NULL; + tvp = (active_threads || data_ready) ? &zero : NULL; #endif ldap_pvt_thread_mutex_unlock( &active_threads_mutex ); @@ -201,7 +208,8 @@ slapd_daemon( case 0: /* timeout - let threads run */ Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n", 0, 0, 0 ); - ldap_pvt_thread_yield(); + if (!data_ready) + ldap_pvt_thread_yield(); continue; default: /* something happened - deal with it */ @@ -225,7 +233,11 @@ slapd_daemon( ldap_pvt_thread_mutex_unlock( &new_conn_mutex ); continue; } - if ( ioctl( ns, FIONBIO, (caddr_t) &on ) == -1 ) { + + lber_pvt_sb_set_desc( &c[ns].c_sb, ns ); + lber_pvt_sb_set_io( &c[ns].c_sb, &lber_pvt_sb_io_tcp, NULL ); + + if (lber_pvt_sb_set_nonblock( &c[ns].c_sb, 1)<0) { Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl on %d failed\n", ns, 0, 0 ); } @@ -279,13 +291,14 @@ slapd_daemon( client_addr == NULL ? "unknown" : client_addr, 0, 0 ); - close(ns); + lber_pvt_sb_close( &c[ns].c_sb ); + lber_pvt_sb_destroy( &c[ns].c_sb ); ldap_pvt_thread_mutex_unlock( &new_conn_mutex ); continue; } #endif /* HAVE_TCPD */ - c[ns].c_sb.sb_sd = ns; + ldap_pvt_thread_mutex_lock( &ops_mutex ); c[ns].c_connid = num_conns++; ldap_pvt_thread_mutex_unlock( &ops_mutex ); @@ -355,7 +368,8 @@ slapd_daemon( ldap_pvt_thread_mutex_unlock( &active_threads_mutex ); } - if ( FD_ISSET( i, &readfds ) ) { + if ( FD_ISSET( i, &readfds ) || + lber_pvt_sb_data_ready( &c[i].c_sb ) ) { Debug( LDAP_DEBUG_CONNS, "read activity on %d\n", i, 0, 0 ); diff --git a/servers/slapd/main.c b/servers/slapd/main.c index f8b3d871b2..08b243fdd2 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -246,12 +246,14 @@ main( int argc, char **argv ) c.c_dn = NULL; c.c_cdn = NULL; c.c_ops = NULL; - c.c_sb.sb_sd = 0; - c.c_sb.sb_options = 0; - c.c_sb.sb_naddr = udp ? 1 : 0; - c.c_sb.sb_ber.ber_buf = NULL; - c.c_sb.sb_ber.ber_ptr = NULL; - c.c_sb.sb_ber.ber_end = NULL; + + lber_pvt_sb_init( &c.c_sb ); + lber_pvt_sb_set_desc( &c.c_sb, 0 ); + lber_pvt_sb_set_io( &c.c_sb, + (udp) ? &lber_pvt_sb_io_udp : &lber_pvt_sb_io_tcp, + NULL ); + /* FIXME: handle udp here */ + ldap_pvt_thread_mutex_init( &c.c_dnmutex ); ldap_pvt_thread_mutex_init( &c.c_opsmutex ); ldap_pvt_thread_mutex_init( &c.c_pdumutex ); @@ -303,8 +305,8 @@ main( int argc, char **argv ) Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0, 0 ); ber_free( &ber, 1 ); - close( c.c_sb.sb_sd ); - c.c_sb.sb_sd = -1; + lber_pvt_sb_close( &c.c_sb ); + lber_pvt_sb_destroy( &c.c_sb ); return 1; } diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c index 4c21dfb273..62effcda9e 100644 --- a/servers/slapd/monitor.c +++ b/servers/slapd/monitor.c @@ -70,7 +70,7 @@ monitor_info( Connection *conn, Operation *op ) ldap_pvt_thread_mutex_lock( &new_conn_mutex ); for ( i = 0; i < dtblsize; i++ ) { - if ( c[i].c_sb.sb_sd != -1 ) { + if ( lber_pvt_sb_in_use(&(c[i].c_sb)) ) { nconns++; if ( c[i].c_writewaiter ) { nwritewaiters++; diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 1e9384f51f..35b1921e1c 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -150,12 +150,11 @@ send_ldap_result( { #ifdef LDAP_CONNECTIONLESS if ( op->o_cldap ) { - SAFEMEMCPY( (char *)conn->c_sb.sb_useaddr, &op->o_clientaddr, - sizeof( struct sockaddr )); + lber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr ); Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n", inet_ntoa(((struct sockaddr_in *) - conn->c_sb.sb_useaddr)->sin_addr ), - ((struct sockaddr_in *) conn->c_sb.sb_useaddr)->sin_port, + &op->o_clientaddr)->sin_addr ), + ((struct sockaddr_in *) &op->o_clientaddr)->sin_port, 0 ); } #endif @@ -448,12 +447,12 @@ void close_connection( Connection *conn, int opconnid, int opid ) { ldap_pvt_thread_mutex_lock( &new_conn_mutex ); - if ( conn->c_sb.sb_sd != -1 && conn->c_connid == opconnid ) { + if ( lber_pvt_sb_in_use(&conn->c_sb) && conn->c_connid == opconnid ) { Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d fd=%d closed errno=%d\n", conn->c_connid, - opid, conn->c_sb.sb_sd, errno, 0 ); - close( conn->c_sb.sb_sd ); - conn->c_sb.sb_sd = -1; + opid, lber_pvt_sb_get_desc(&conn->c_sb), errno, 0 ); + lber_pvt_sb_close( &conn->c_sb ); + lber_pvt_sb_destroy( &conn->c_sb ); conn->c_version = 0; conn->c_protocol = 0; } -- 2.39.5