]> git.sur5r.net Git - openldap/commitdiff
The new&improved Sockbuf. This adds the infrastructure on which
authorBart Hartgers <bart@openldap.org>
Tue, 2 Mar 1999 20:23:14 +0000 (20:23 +0000)
committerBart Hartgers <bart@openldap.org>
Tue, 2 Mar 1999 20:23:14 +0000 (20:23 +0000)
support for TLS and SASL will be build.

Please inform me of any problems.

27 files changed:
include/lber.h
include/ldap.h
libraries/liblber/Makefile.in
libraries/liblber/dtest.c
libraries/liblber/etest.c
libraries/liblber/io.c
libraries/liblber/lber-int.h
libraries/liblber/sockbuf.c [new file with mode: 0644]
libraries/libldap/abandon.c
libraries/libldap/cldap.c
libraries/libldap/ldap-int.h
libraries/libldap/open.c
libraries/libldap/options.c
libraries/libldap/os-ip.c
libraries/libldap/request.c
libraries/libldap/result.c
libraries/libldap/search.c
libraries/libldap/unbind.c
servers/ldapd/main.c
servers/ldapd/request.c
servers/ldapd/result.c
servers/ldapd/search.c
servers/slapd/connection.c
servers/slapd/daemon.c
servers/slapd/main.c
servers/slapd/monitor.c
servers/slapd/result.c

index c82a8c7614c1e8533bacfe8e7b5f1bbcb9fe1966..5af98579ae425e03a13b66da915d69f6caffcc31 100644 (file)
@@ -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
 
index 56927161e6a20bafd0aec408cc8a81443ac5fa02..c2d67314fcfa8bc1cf88ba10fc2db487b7257a8e 100644 (file)
@@ -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
  */
index ef1f8a02c933fa1388538fb4372ebda782725654..9a17b3335bbb835090efc4c09c7aabac85f5611e 100644 (file)
@@ -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
index 93b1966894b922f106eaeb0cb13c986a3ecdd1f2..df683a0ec7d287efda8ce71e7abd49871ed31fa1 100644 (file)
@@ -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 );
 }
index 1155300092988d4dccac51127815b048c6dafe24..3e8ff55ced81b6f1540e07b81d9be23b86813e92 100644 (file)
@@ -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 );
 }
index fc881b9d445ef1ee7efc4105a517809a10e2f3c3..dd8bc5f14f753272f05faf2a9f5dea98340526b8 100644 (file)
 
 #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), (l<MAX_WRITE)? l : MAX_WRITE )
-#else /* MACOS */
-#ifdef DOS
-#ifdef PCNFS
-/*
- * PCNFS (under DOS)
- */
-#define read( s, b, l ) recv( s, b, l, 0 )
-#define BerWrite( s, b, l ) send( s->sb_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, (l<MAX_WRITE)? l : MAX_WRITE)
-#else /* VMS */
-/*
- * everything else (Unix/BSD 4.3 socket API)
- */
-#define BerWrite( sb, b, l )   write( sb->sb_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;
 }
index 37db2a986b04661c864ad31d14559eb2f4c09518..aeab66b2ba5c73c09e571021f8971b8f9f3d4511 100644 (file)
@@ -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 (file)
index 0000000..8902af1
--- /dev/null
@@ -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 <stdio.h>
+#include <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_SYS_FILIO_H )
+#include <sys/filio.h>
+#elif defined( HAVE_SYS_IOCTL_H )
+#include <sys/ioctl.h>
+#endif
+
+#include "lber-int.h"
+
+#ifdef LDAP_DEBUG
+#include <assert.h>
+#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_size<minsize) {
+      if ((buf->buf_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 (rlen<len) {
+        len-=rlen;
+        buf+=rlen;
+      } else {
+        sb->sb_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 (ptr<end) {
+      /* copy back to beginning of buffer. */
+      SAFEMEMCPY( sb->sb_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 = (blen<len) ? blen : len;
+      memcpy( *buf, sb->sb_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 (ret<to_go) /* not enough data, so pretend no data was sent. */
+     return -1;
+   return ret;
+}
+#endif
+
+long lber_pvt_sb_write( Sockbuf *sb, void *buf, long len_arg )
+{
+   long ret;
+   long len = len_arg;
+   assert( status_is_ok(sb) );
+#if 0
+   /* unfortunately breaks slapd */
+   assert( lber_pvt_sb_in_use( sb ) );
+#endif   
+#ifdef USE_SASL
+   if (sb->sb_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), 
+                   (len<MAX_WRITE)? len : MAX_WRITE );
+#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 send( lber_pvt_sb_get_desc(sb), buf, len, 0 );
+#elif defined(NCSA)
+   return netwrite( lber_pvt_sb_get_desc(sb), buf, len );
+#elif defined(VMS)
+/*
+ * VMS -- each write must be 64K or smaller
+ */
+#define MAX_WRITE 65535
+   return write( lber_pvt_sb_get_desc(sb), buf, 
+                (len<MAX_WRITE)? len : MAX_WRITE);
+#else
+   return write( lber_pvt_sb_get_desc(sb), buf, len );
+#endif   
+}   
+   
+static int 
+stream_close( Sockbuf *sb )
+{
+   tcp_close( lber_pvt_sb_get_desc( sb ) );
+   return 0;
+}
+
+Sockbuf_IO lber_pvt_sb_io_tcp=
+{
+       NULL,   /* sbi_setup */
+       NULL,   /* sbi_release */
+       stream_read,    /* sbi_read */
+       stream_write,   /* sbi_write */
+       stream_close,   /* sbi_close */
+};
+
+/*
+ * Support for UDP (CLDAP)
+ */
+
+struct dgram_data
+{
+       struct sockaddr dst;
+       struct sockaddr src;
+};
+
+static int 
+dgram_setup( Sockbuf *sb, void *arg )
+{
+   sb->sb_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;
+}
index a41199a5813c056eb0b3c8d6b258c87643ac6097..2fac95f770c667226d2e36a93ae5522c8e5a659c 100644 (file)
@@ -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 );
index d5ca787bd3eee1750ed26bed7a507060d4ff1b4d..55f1be4fb9faac15ff96755cd9e1ea60ea09f8eb 100644 (file)
@@ -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 );
        }
     }
index 1369f877c54a7842109d71a3eb79c867eb01e839..474807582efa7d4d85881be5a2d04f94cba938dd 100644 (file)
@@ -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;
index 259bf8a43867b462ad81129995e64f80954948cf..a1db516cbb49b2ca5999d1f76e073b33fb680eb3 100644 (file)
@@ -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
index 0d0400a6b65d6331891b8fb9a4a7e965835dcbaf..7bc03b141dcc389ff7db875906e0a5221cc204b8 100644 (file)
@@ -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:
index 6d501565a9ef759a4b3496509bc0cd0e50683fc1..41f3dd1787bff5a759b66935c92c1f549ecb247c 100644 (file)
@@ -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 ));
 }
 
 
index 6dfa9d1718cc9a7c70e168675e4ce0e097aa2e57..a9f7dbf0faae882ed3e181caf4ae59f6ae67f0ee 100644 (file)
@@ -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",
index ef3a86fad3b4ba7b29d235650c5ecb08f3b2809a..df532f08f6fbfac30330be985e08ee627bd5039f 100644 (file)
@@ -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 :
index 171641e30f928dd2e239eeb62c7ed5dbd4fdecda..117d5f4d2ee1f7b9db238d6ca25502433bee531a 100644 (file)
@@ -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 );
index 63237ba8e236a16ec555a228c1bd9fcdca5b4b50..a1c91e5e7122ef4fe4779b08a46f27e7675c0dbd 100644 (file)
@@ -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 );
index 85f9b5d71f46cf53c34b1557c7a4a673a909ef4f..95430ea99aab2e2df8cc36ab98d861c5387a6350 100644 (file)
@@ -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 {
index 28dae68661e5e94060ce14ab2bf2e6ef5c85de14..222500b6f9ba59ee03cc59ad548434196476a4cb 100644 (file)
@@ -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
index 498ef4a7013862e29b7762477030abb089c58b94..777aec2e68a6da5459f40fb949c957e6dcc324ca 100644 (file)
@@ -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 );
index cd413856c48e0c17b1772bcbe71b6d287d89b75d..33afd35713e14984af4c47644dbdb5e20c75c970 100644 (file)
@@ -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" );
index 4a8ed5462f5ee398de2ee0819973928feec514bc..249f1b82cb954099fee6b4ab2e21c7af90f94181 100644 (file)
@@ -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),
index 230d672edbe5289779a9fc76c741cf564dcbd8c0..25ff2c1cacf1648fbd99bbd266e525a770f75ad4 100644 (file)
 #include <sys/ioctl.h>
 #endif
 
+#ifdef LDAP_DEBUG
+#include <assert.h>
+#else
+#define assert( cond )
+#endif
+
 #ifdef HAVE_TCPD
 #include <tcpd.h>
 
@@ -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 );
 
index f8b3d871b2970eb725fb6c1e603c3f73a3efc334..08b243fdd21fec7ac894bf9a154f1607ed992989 100644 (file)
@@ -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;
                        }
 
index 4c21dfb273339d55d292252b8594bdffa89b287d..62effcda9ecac32aaafb86dd702748d07e20d980 100644 (file)
@@ -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++;
index 1e9384f51ff2e45449568840f0770207aa58f98f..35b1921e1c475505f9ce892a3d81ba556919f8d8 100644 (file)
@@ -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;
        }