support for TLS and SASL will be build.
Please inform me of any problems.
/*
* 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
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
*/
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
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" );
}
printf( "got int %ld\n", i );
- lber_sockbuf_free( sb );
+ lber_pvt_sb_free( sb );
return( 0 );
}
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" );
#endif
- lber_sockbuf_free( sb );
+ lber_pvt_sb_free( sb );
return( 0 );
}
#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 )
{
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 )
{
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;
#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;
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 )
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;
*/
*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 ) {
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 );
}
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 );
}
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;
}
};
#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 {
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 */
--- /dev/null
+/* 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;
+}
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 );
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;
}
}
- 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 */
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
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 ) {
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 ) {
}
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 );
}
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;
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
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;
}
*/
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 );
}
}
} 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
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;
#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.
WSACleanup( );
return( NULL );
}
-
+
/* copy the global options */
memcpy(&ld->ld_options, &openldap_ldap_global_options,
sizeof(ld->ld_options));
/* 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 );
}
if ( rc == -1 ) {
return( rc );
}
+
+ lber_pvt_sb_set_io( sb, &lber_pvt_sb_io_tcp, NULL );
if ( krbinstancep != NULL ) {
#ifdef HAVE_KERBEROS
break;
}
- * (int *) outvalue = ld->ld_sb.sb_sd;
+ * (int *) outvalue = lber_pvt_sb_get_desc( &(ld->ld_sb) );
return 0;
case LDAP_OPT_DEREF:
}
}
- 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;
}
DO_RETURN( rc );
-
-
}
#undef DO_RETURN
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 )
{
(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 );
}
&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 );
}
}
}
#undef DO_RETURN
-#endif /* HAVE_KERBEROS */
+#endif /* HAVE_KERBEROS || HAVE_TLS */
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
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 );
}
}
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 );
}
}
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 );
}
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 ));
}
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 ));
}
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
* 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 );
}
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;
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;
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",
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 && (
}
#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;
}
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 ) );
}
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 :
}
#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 );
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 ) {
} 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 ) {
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 );
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 );
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 ( ;; ) {
* 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
}
}
- 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 {
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.
*/
#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
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;
}
m = add_msg( msgid, tag, copyofber, dsaconn, udp,
#ifdef LDAP_CONNECTIONLESS
- (struct sockaddr *)clientsb->sb_fromaddr );
+ (struct sockaddr *)sai );
#else
NULL );
#endif
{
#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 ) );
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 );
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" );
!= 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),
#include <sys/ioctl.h>
#endif
+#ifdef LDAP_DEBUG
+#include <assert.h>
+#else
+#define assert( cond )
+#endif
+
#ifdef HAVE_TCPD
#include <tcpd.h>
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 );
struct timeval zero;
struct timeval *tvp;
int len, pid;
+ int data_ready;
char *client_name;
char *client_addr;
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 );
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 );
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 */
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 );
}
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 );
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 );
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 );
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;
}
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++;
{
#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
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;
}