Copyright 2000 Gábor Gombás. All rights reserved.
This is free software. You may redistribute and use it under the same
terms as OpenLDAP itself.
BER_MEMFREE_FN bmf_free;
} BerMemoryFunctions;
-/* LBER Sockbuf options */
-#define LBER_TO_FILE 0x01 /* to a file referenced by sb_fd */
-#define LBER_TO_FILE_ONLY 0x02 /* only write to file, not network */
-#define LBER_MAX_INCOMING_SIZE 0x04 /* impose limit on incoming stuff */
-#define LBER_NO_READ_AHEAD 0x08 /* read only as much as requested */
+/* LBER Sockbuf_IO options */
+#define LBER_SB_OPT_GET_FD 1
+#define LBER_SB_OPT_SET_FD 2
+#define LBER_SB_OPT_HAS_IO 3
+#define LBER_SB_OPT_SET_NONBLOCK 4
+#define LBER_SB_OPT_UDP_GET_SRC 5
+#define LBER_SB_OPT_UDP_SET_DST 6
+#define LBER_SB_OPT_GET_SSL 7
+#define LBER_SB_OPT_DATA_READY 8
+#define LBER_SB_OPT_SET_READAHEAD 9
+#define LBER_SB_OPT_DRAIN 10
+#define LBER_SB_OPT_NEEDS_READ 11
+#define LBER_SB_OPT_NEEDS_WRITE 12
+/* Largest option used by the library */
+#define LBER_SB_OPT_OPT_MAX 12
+
+/* LBER IO operations stacking levels */
+#define LBER_SBIOD_LEVEL_PROVIDER 10
+#define LBER_SBIOD_LEVEL_TRANSPORT 20
+#define LBER_SBIOD_LEVEL_APPLICATION 30
/* get/set options for Sockbuf */
#define LBER_OPT_SOCKBUF_DESC 0x1000
typedef struct sockbuf Sockbuf;
typedef struct seqorset Seqorset;
+typedef struct sockbuf_io Sockbuf_IO;
+
+/* Structure for LBER IO operarion descriptor */
+typedef struct sockbuf_io_desc {
+ int sbiod_level;
+ Sockbuf *sbiod_sb;
+ Sockbuf_IO *sbiod_io;
+ void *sbiod_pvt;
+ struct sockbuf_io_desc *sbiod_next;
+} Sockbuf_IO_Desc;
+
+/* Structure for LBER IO operation functions */
+struct sockbuf_io {
+ int (*sbi_setup)( Sockbuf_IO_Desc *sbiod, void *arg );
+ int (*sbi_remove)( Sockbuf_IO_Desc *sbiod );
+ int (*sbi_ctrl)( Sockbuf_IO_Desc *sbiod, int opt, void *arg);
+
+ ber_slen_t (*sbi_read)( Sockbuf_IO_Desc *sbiod, void *buf,
+ ber_len_t len );
+ ber_slen_t (*sbi_write)( Sockbuf_IO_Desc *sbiod, void *buf,
+ ber_len_t len );
+
+ int (*sbi_close)( Sockbuf_IO_Desc *sbiod );
+};
+
+/* Helper macros for LBER IO functions */
+#define LBER_SBIOD_READ_NEXT( sbiod, buf, len ) \
+ ( (sbiod)->sbiod_next->sbiod_io->sbi_read( (sbiod)->sbiod_next, \
+ buf, len ) )
+#define LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ) \
+ ( (sbiod)->sbiod_next->sbiod_io->sbi_write( (sbiod)->sbiod_next, \
+ buf, len ) )
+#define LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ) \
+ ( (sbiod)->sbiod_next ? \
+ ( (sbiod)->sbiod_next->sbiod_io->sbi_ctrl( \
+ (sbiod)->sbiod_next, opt, arg ) ) : 0 )
+
/* structure for returning a sequence of octet strings + length */
typedef struct berval {
ber_len_t bv_len;
* LBER sockbuf.c
*/
-LIBLBER_F( Sockbuf * )
-ber_sockbuf_alloc( void );
-
LIBLBER_F( Sockbuf * )
-ber_sockbuf_alloc_fd(
- ber_socket_t fd );
+ber_sockbuf_alloc LDAP_P((
+ void ));
LIBLBER_F( void )
-ber_sockbuf_free(
- Sockbuf *sb );
+ber_sockbuf_free LDAP_P((
+ Sockbuf *sb ));
+
+LIBLBER_F( int )
+ber_sockbuf_add_io LDAP_P((
+ Sockbuf *sb,
+ Sockbuf_IO *sbio,
+ int layer,
+ void *arg ));
+
+LIBLBER_F( int )
+ber_sockbuf_remove_io LDAP_P((
+ Sockbuf *sb,
+ Sockbuf_IO *sbio,
+ int layer ));
+
+LIBLBER_F( int )
+ber_sockbuf_ctrl LDAP_P((
+ Sockbuf *sb,
+ int opt,
+ void *arg ));
+
+LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_tcp;
+LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_udp;
+LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_readahead;
+LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_fd;
+LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_debug;
/*
* LBER memory.c
LDAP_BEGIN_DECL
+typedef struct sockbuf_buf {
+ ber_len_t buf_size;
+ ber_len_t buf_ptr;
+ ber_len_t buf_end;
+ char *buf_base;
+} Sockbuf_Buf;
+
/*
* bprint.c
*/
const char *fmt,
... )) LDAP_GCCATTR((format(printf, 3, 4)));
+/*
+ * sockbuf.c
+ */
+LIBLBER_F( ber_slen_t )
+ber_pvt_sb_do_write LDAP_P(( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out ));
+
+LIBLBER_F( void )
+ber_pvt_sb_buf_init LDAP_P(( Sockbuf_Buf *buf ));
+
+LIBLBER_F( void )
+ber_pvt_sb_buf_destroy LDAP_P(( Sockbuf_Buf *buf ));
+
+LIBLBER_F( int )
+ber_pvt_sb_grow_buffer LDAP_P(( Sockbuf_Buf *buf, ber_len_t minsize ));
+
+LIBLBER_F( ber_len_t )
+ber_pvt_sb_copy_out LDAP_P(( Sockbuf_Buf *sbb, char *buf, ber_len_t len ));
+
+LIBLBER_F( int )
+ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb ));
+
LDAP_END_DECL
#endif
BerElement *ber;
Sockbuf *sb;
+ int fd;
/* enable debugging */
int ival = -1;
cshow( stdout );
#endif
- sb = ber_sockbuf_alloc_fd( fileno(stdin) );
+ sb = ber_sockbuf_alloc();
+ fd = fileno( stdin );
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER,
+ (void *)&fd );
if( (ber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
perror( "ber_alloc_t" );
fd = fileno(stdout);
#endif
- sb = ber_sockbuf_alloc_fd( fd );
+ sb = ber_sockbuf_alloc();
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER,
+ (void *)&fd );
if( sb == NULL ) {
perror( "ber_sockbuf_alloc_fd" );
assert( SOCKBUF_VALID( sb ) );
while ( len > 0 ) {
- if ( (c = ber_pvt_sb_read( sb, buf, len )) <= 0 ) {
+ if ( (c = ber_int_sb_read( sb, buf, len )) <= 0 ) {
if ( nread > 0 )
break;
return( c );
if ( sb->sb_debug ) {
ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
"ber_flush: %ld bytes to sd %ld%s\n", towrite,
- (long) sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)"
- : "" );
+ (long) sb->sb_fd, ber->ber_rwptr != ber->ber_buf ?
+ " (re-flush)" : "" );
ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
ber->ber_rwptr, towrite );
}
-#if HAVE_WRITE
- if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) {
- rc = write( sb->sb_fd, ber->ber_rwptr, towrite );
- if ( sb->sb_options & LBER_TO_FILE_ONLY ) {
- if ( freeit )
- ber_free( ber, 1 );
- return( (int)rc );
- }
- }
-#endif
-
nwritten = 0;
do {
- rc = ber_pvt_sb_write( sb, ber->ber_rwptr, towrite );
+ rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite );
if (rc<=0) {
return -1;
}
assert( sb != NULL );
assert( SOCKBUF_VALID( sb ) );
- if ( ber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
+ if ( ber_int_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(ber_tag_t); i++ ) {
- if ( ber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
+ if ( ber_int_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
return( LBER_DEFAULT );
tagp[i] = xbyte;
if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_tag)) {
if (ber->ber_rwptr == (char *) &ber->ber_tag) {
- if (ber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0)
+ if (ber_int_sb_read( sb, ber->ber_rwptr, 1)<=0)
return LBER_DEFAULT;
if ((ber->ber_rwptr[0] & LBER_BIG_TAG_MASK)
!= LBER_BIG_TAG_MASK) {
}
do {
/* reading the tag... */
- if (ber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0)
+ if (ber_int_sb_read( sb, ber->ber_rwptr, 1)<=0)
return LBER_DEFAULT;
if (! (ber->ber_rwptr[0] & LBER_MORE_TAG_MASK) ) {
ber->ber_tag>>=sizeof(ber->ber_tag) -
get_lenbyte:
if (ber->ber_rwptr==(char *) &ber->ber_usertag) {
unsigned char c;
- if (ber_pvt_sb_read( sb, (char *) &c, 1)<=0)
+ if (ber_int_sb_read( sb, (char *) &c, 1)<=0)
return LBER_DEFAULT;
if (c & 0x80U) {
int len = c & 0x7fU;
to_go = ber->ber_end - ber->ber_rwptr;
assert( to_go > 0 );
- res = ber_pvt_sb_read( sb, ber->ber_rwptr, to_go );
+ res = ber_int_sb_read( sb, ber->ber_rwptr, to_go );
if (res<=0)
return LBER_DEFAULT;
ber->ber_rwptr+=res;
struct lber_options {
short lbo_valid;
+ unsigned short lbo_options;
+ int lbo_debug;
+};
+
#define LBER_UNINITIALIZED 0x0
#define LBER_INITIALIZED 0x1
#define LBER_VALID_BERELEMENT 0x2
#define LBER_VALID_SOCKBUF 0x3
- unsigned short lbo_options;
- int lbo_debug;
-};
-
LIBLBER_F (struct lber_options) ber_int_options;
#define ber_int_debug ber_int_options.lbo_debug
};
#define BER_VALID(ber) ((ber)->ber_valid==LBER_VALID_BERELEMENT)
-
#define ber_pvt_ber_bytes(ber) ((ber)->ber_ptr - (ber)->ber_buf)
#define ber_pvt_ber_remaining(ber) ((ber)->ber_end - (ber)->ber_ptr)
-struct sockbuf;
-
-struct sockbuf_io {
- int (*sbi_setup)( struct sockbuf * sb, void *arg );
- int (*sbi_remove)( struct sockbuf *sb );
-
- ber_slen_t (*sbi_read)( struct sockbuf *sb, void *buf, ber_len_t len );
- ber_slen_t (*sbi_write)( struct sockbuf *sb, void *buf, ber_len_t 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 {
- ber_len_t buf_size;
- ber_len_t buf_ptr;
- ber_len_t buf_end;
- char *buf_base;
-};
-
-typedef struct sockbuf_io Sockbuf_IO;
-typedef struct sockbuf_sec Sockbuf_Sec;
-typedef struct sockbuf_buf Sockbuf_Buf;
-
-LIBLBER_F( Sockbuf_IO ) ber_pvt_sb_io_tcp;
-LIBLBER_F( Sockbuf_IO ) ber_pvt_sb_io_udp;
-
-
struct sockbuf {
struct lber_options sb_opts;
+ Sockbuf_IO_Desc *sb_iod; /* I/O functions */
#define sb_valid sb_opts.lbo_valid
#define sb_options sb_opts.lbo_options
#define sb_debug sb_opts.lbo_debug
-
- 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;
-
- /* these bits indicate if the transport layer
- * needs to read or write
- */
+ ber_socket_t sb_fd;
int sb_trans_needs_read:1;
int sb_trans_needs_write: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
-
- ber_socket_t sb_sd;
-
-#ifdef DEADWOOD
- long sb_max_incoming;
-#endif
- Sockbuf_Buf sb_buf;
-#ifdef LDAP_SASL
- Sockbuf_Buf sb_sec_buf_in;
- Sockbuf_Buf sb_sec_buf_out;
- ber_len_t sb_sec_prev_len;
-#endif
};
-#define SOCKBUF_VALID(ber) ((sb)->sb_valid==LBER_VALID_SOCKBUF)
-/* these should be internal ie: ber_int_* */
-#define ber_pvt_sb_get_desc( sb ) ((sb)->sb_sd)
-#define ber_pvt_sb_set_desc( sb, val ) ((sb)->sb_sd =(val))
-
-#define ber_pvt_sb_in_use( sb ) ((sb)->sb_sd != AC_SOCKET_INVALID)
-
-#ifdef USE_SASL
-#define ber_pvt_sb_data_ready( sb ) \
-(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready) || ((sb)->sb_sec_ready))
-#else
-#define ber_pvt_sb_data_ready( sb ) \
-(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready))
-#endif
-#define ber_pvt_sb_needs_read( sb ) \
-((sb)->sb_trans_needs_read)
-#define ber_pvt_sb_needs_write( sb ) \
-((sb)->sb_trans_needs_write)
+#define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF )
#define READBUFSIZ 8192
/* sockbuf.c */
-/* these should be ber_int*() functions */
-
-LIBLBER_F( int )
-ber_pvt_sb_init LDAP_P(( Sockbuf *sb ));
-
LIBLBER_F( int )
-ber_pvt_sb_destroy LDAP_P(( Sockbuf *sb ));
+ber_int_sb_init LDAP_P(( Sockbuf *sb ));
-#ifdef USE_SASL
LIBLBER_F( int )
-ber_pvt_sb_set_sec LDAP_P(( Sockbuf *sb, Sockbuf_Sec *sec, void *arg ));
-
-LIBLBER_F( int )
-ber_pvt_sb_clear_sec LDAP_P(( Sockbuf *sb ));
-#endif
+ber_int_sb_close LDAP_P(( Sockbuf *sb ));
LIBLBER_F( int )
-ber_pvt_sb_set_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *layer, void *arg ));
-
-LIBLBER_F( int )
-ber_pvt_sb_clear_io LDAP_P(( Sockbuf *sb ));
-
-LIBLBER_F( int )
-ber_pvt_sb_close LDAP_P((Sockbuf *sb ));
-
-LIBLBER_F( int )
-ber_pvt_sb_set_nonblock LDAP_P(( Sockbuf *sb, int nb ));
-
-LIBLBER_F( int )
-ber_pvt_sb_set_readahead LDAP_P(( Sockbuf *sb, int rh ));
+ber_int_sb_destroy LDAP_P(( Sockbuf *sb ));
LIBLBER_F( ber_slen_t )
-ber_pvt_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
+ber_int_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
LIBLBER_F( ber_slen_t )
-ber_pvt_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
-
-LIBLBER_F( int )
-ber_pvt_sb_udp_set_dst LDAP_P((Sockbuf *sb, void *addr ));
-
-LIBLBER_F( void * )
-ber_pvt_sb_udp_get_src LDAP_P((Sockbuf *sb ));
-
-LIBLBER_F( int )
-ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb ));
+ber_int_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
LDAP_END_DECL
#include "lber-int.h"
-#ifdef LDAP_TEST
-#undef TEST_PARTIAL_READ
-#undef TEST_PARTIAL_WRITE
-#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 MIN_BUFF_SIZE 4096
+#define MAX_BUFF_SIZE 65536
+#define DEFAULT_READAHEAD 16384
-#define sockbuf_io_read( sb, buf, len ) \
-((sb)->sb_io->sbi_read( (sb), (buf), (len) ))
+Sockbuf *
+ber_sockbuf_alloc( void )
+{
+ Sockbuf *sb;
-static ber_slen_t have_no_read( Sockbuf *sb, void *buf, ber_len_t len );
-static ber_slen_t have_no_write( Sockbuf *sb, void *buf, ber_len_t len );
-static int have_no_close( Sockbuf *sb );
+ ber_int_options.lbo_valid = LBER_INITIALIZED;
-static Sockbuf_IO sb_IO_None=
-{
- NULL, /* sbi_setup */
- NULL, /* sbi_release */
- have_no_read, /* sbi_read */
- have_no_write, /* sbi_write */
- have_no_close /* sbi_close */
-};
+ sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
-static void
-update_status( Sockbuf *sb )
-{
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
+ if( sb == NULL )
+ return NULL;
- 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
+ ber_int_sb_init( sb );
+ return sb;
}
-#ifdef LDAP_DEBUG
-static int
-status_is_ok( Sockbuf *sb )
+void
+ber_sockbuf_free( Sockbuf *sb )
{
- int obr;
-#ifdef USE_SASL
- int osr;
-#endif
-
assert( sb != NULL );
assert( SOCKBUF_VALID( sb ) );
- 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;
+ ber_int_sb_close( sb );
+ ber_int_sb_destroy( sb );
+ LBER_FREE( sb );
}
-#endif
-#ifdef USE_SASL
-static ber_len_t
-packet_length( Sockbuf *sb, const char *buf )
+/* Return values: -1: error, 0: no operation performed or the answer is false,
+ * 1: successful operation or the answer is true
+ */
+int
+ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
{
- ber_len_t size;
+ Sockbuf_IO_Desc *p;
+ int ret = 0;
+ char buf[4096];
- assert( buf != NULL );
+ assert( sb != NULL );
- size = (((ber_len_t)buf[0])<<24)|
- (((ber_len_t)buf[1])<<16)|
- (((ber_len_t)buf[2])<<8)|
- (((ber_len_t)buf[3]));
-
- if ( size > MAX_BUF_SIZE ) {
- /* somebody is trying to mess me up. */
- ber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug,
- "SASL: received packet length of %lu bytes\n",
- (unsigned long) size );
- size = 16; /* this should lead to an error. */
+ switch ( opt ) {
+ case LBER_SB_OPT_HAS_IO:
+ p = sb->sb_iod;
+
+ while ( p && p->sbiod_io != (Sockbuf_IO *)arg )
+ p = p->sbiod_next;
+
+ if ( p )
+ ret = 1;
+ break;
+ case LBER_SB_OPT_GET_FD:
+ if ( arg != NULL )
+ *((int *)arg) = sb->sb_fd;
+ ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
+ break;
+ case LBER_SB_OPT_SET_FD:
+ sb->sb_fd = *((int *)arg);
+ ret = 1;
+ break;
+ case LBER_SB_OPT_SET_NONBLOCK:
+ ret = ( ber_pvt_socket_set_nonblock( sb->sb_fd,
+ (int)arg ) ? -1 : 1 );
+ break;
+ case LBER_SB_OPT_DRAIN:
+ /* Drain the data source to enable possible errors (e.g.
+ * TLS) to be propagated to the upper layers
+ */
+ do {
+ ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
+ } while ( ret == sizeof( buf ) );
+
+ ret = 1;
+ break;
+ case LBER_SB_OPT_NEEDS_READ:
+ ret = ( sb->sb_trans_needs_read ? 1 : 0 );
+ break;
+ case LBER_SB_OPT_NEEDS_WRITE:
+ ret = ( sb->sb_trans_needs_write ? 1 : 0 );
+ break;
+ default:
+ ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
+ opt, arg );
+ break;
}
-
- return size + 4; /* include the size !!! */
-}
-#endif
-
-static int
-grow_buffer( Sockbuf_Buf * buf, ber_len_t minsize )
-{
- ber_len_t pw;;
-
- assert( buf != NULL );
- for( pw=MIN_BUF_SIZE; pw<minsize; pw<<=1 ) {
- if (pw > MAX_BUF_SIZE) {
- /* this could mean that somebody is trying to crash us. */
- return -1;
- }
- }
- minsize = pw;
-
- 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)
- LBER_FREE( buf->buf_base );
- assert( buf->buf_ptr==0 );
- assert( buf->buf_end==0 );
- buf->buf_base = LBER_MALLOC( minsize );
- if (buf->buf_base==NULL)
- return -1;
- } else {
- char *nb;
- nb = LBER_REALLOC( buf->buf_base, minsize );
- if (nb==NULL)
- return -1;
- buf->buf_base = nb;
- }
- buf->buf_size = minsize;
- }
- return 0;
+ return ret;
}
-#ifdef USE_SASL
-static ber_slen_t
-sockbuf_sec_release( Sockbuf *sb, char *buf, ber_len_t len )
+int
+ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
{
- /* 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;
+ Sockbuf_IO_Desc *d, *p, **q;
- assert( buf != NULL );
assert( sb != NULL );
assert( SOCKBUF_VALID( sb ) );
-
- 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;
+ if ( sbio == NULL )
+ return -1;
- 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;
+ q = &sb->sb_iod;
+ p = *q;
+ while ( p && p->sbiod_level > layer ) {
+ q = &p->sbiod_next;
+ p = *q;
+ }
- sb->sb_sec_ready = 1;
+ d = LBER_MALLOC( sizeof( *d ) );
+ if ( d == NULL )
+ return -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;
+ d->sbiod_level = layer;
+ d->sbiod_sb = sb;
+ d->sbiod_io = sbio;
+ memset( &d->sbiod_pvt, 0, sizeof( d->sbiod_pvt ) );
+ d->sbiod_next = p;
+ *q = d;
- if (ptr+4<=end)
- size = packet_length( sb, ptr );
- /* size is always at least 4, so the loop condition is always OK !!*/
- assert( size>=4 );
+ if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) )
+ return -1;
- if (rlen<len) {
- len-=rlen;
- buf+=rlen;
- } else {
- sb->sb_buf_ready = (sb->sb_buf.buf_end = rlen - len) ? 1 : 0;
- break;
- }
+ return 0;
}
- 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 )
+int
+ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
{
- long ret;
- long blen;
- long total;
-
- assert( buf != NULL );
+ Sockbuf_IO_Desc *p, **q;
assert( sb != NULL );
assert( SOCKBUF_VALID( sb ) );
-
- 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) */
+ if ( sb->sb_iod == NULL )
+ return -1;
+
+ q = &sb->sb_iod;
+ while ( *q != NULL ) {
+ p = *q;
+ if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
+ if ( p->sbiod_io->sbi_remove != NULL &&
+ p->sbiod_io->sbi_remove( p ) < 0 )
+ return -1;
+ *q = p->sbiod_next;
+ LBER_FREE( p );
break;
- }
- sb->sb_sec_out.buf_end += ret;
- len -= blen;
- total += blen;
}
- assert( status_is_ok(sb) );
- return total;
+ q = &p->sbiod_next;
}
-#endif
-
-static ber_len_t
-sockbuf_copy_out( Sockbuf *sb, char **buf, ber_len_t len )
-{
- ber_len_t blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr );
- assert( buf != NULL );
-
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- assert( status_is_ok(sb) );
-
- if (blen) {
- ber_len_t 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;
+ return 0;
}
-Sockbuf *ber_sockbuf_alloc( void )
+void
+ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
{
- Sockbuf *sb;
-
- ber_int_options.lbo_valid = LBER_INITIALIZED;
-
- sb = LBER_CALLOC(1, sizeof(Sockbuf));
-
- if( sb == NULL ) return NULL;
-
- ber_pvt_sb_init( sb );
- return sb;
+ buf->buf_base = NULL;
+ buf->buf_ptr = 0;
+ buf->buf_end = 0;
+ buf->buf_size = 0;
}
-Sockbuf *ber_sockbuf_alloc_fd( ber_socket_t fd )
+void
+ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
{
- Sockbuf *sb = ber_sockbuf_alloc();
-
- if( sb == NULL ) return NULL;
-
- ber_pvt_sb_set_desc( sb, fd );
- ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
- return sb;
-}
+ assert( buf != NULL);
-void ber_sockbuf_free( Sockbuf *sb )
-{
- assert(sb != NULL);
- assert( SOCKBUF_VALID( sb ) );
- ber_pvt_sb_destroy( sb );
- LBER_FREE(sb);
+ if (buf->buf_base)
+ LBER_FREE( buf->buf_base );
+ ber_pvt_sb_buf_init( buf );
}
-ber_slen_t
-ber_pvt_sb_read( Sockbuf *sb, void *buf_arg, ber_len_t len )
+int
+ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
{
- char *buf;
- ber_slen_t ret;
+ ber_len_t pw;
+ char *p;
- assert( buf_arg != NULL );
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- assert( status_is_ok(sb) );
-
- /* slapd might have problems with this */
- assert( ber_pvt_sb_in_use( sb ) );
+ assert( buf != NULL );
-#ifdef TEST_PARTIAL_READ
- if ((rand() & 3)==1) { /* 1 out of 4 */
- errno = EWOULDBLOCK;
+ for ( pw = MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
+ if (pw > MAX_BUFF_SIZE)
return -1;
}
- if( len > 0 )
- len = (rand() % len)+1;
-#endif
-
- buf = (char *) buf_arg;
-
- if (sb->sb_buf.buf_ptr!=sb->sb_buf.buf_end) {
- len = sockbuf_copy_out( sb, &buf, len );
- if (len==0) {
- return (buf - (char *) buf_arg);
- }
+ if ( buf->buf_size < pw ) {
+ p = LBER_REALLOC( buf->buf_base, pw );
+ if ( p == NULL )
+ return -1;
+ buf->buf_base = p;
+ buf->buf_size = pw;
}
-
-#ifdef USE_SASL
- if (sb->sb_sec) {
- ber_slen_t 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 */
- for(;;) {
- ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base +
- sb->sb_sec_buf_in.buf_ptr, max );
-#ifdef EINTR
- if ((ret<0) && (errno==EINTR))
- continue;
-#endif
- break;
- }
- 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->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->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) {
- ber_slen_t max;
- max = sb->sb_buf.buf_size - sb->sb_buf.buf_end;
- if (max> (ber_slen_t) len) {
- for(;;) {
- ret = sockbuf_io_read( sb,
- sb->sb_buf.buf_base +
- sb->sb_buf.buf_end,
- max );
-#ifdef EINTR
- if ((ret<0) && (errno==EINTR))
- continue;
-#endif
- break;
- }
- 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. */
- for(;;) {
- ret = sockbuf_io_read( sb, buf, len );
-#ifdef EINTR
- if ((ret<0) && (errno==EINTR))
- continue;
-#endif
- break;
- }
- 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));
+ return 0;
}
-#ifdef USE_SASL
-long sockbuf_do_write( Sockbuf *sb )
+ber_len_t
+ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
{
- long to_go;
- ber_slen_t ret;
+ ber_len_t max;
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
-
- 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... */
- for(;;) {
- ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+
- sb->sb_sec_out.buf_ptr, to_go );
-#ifdef EINTR
- if ((ret<0) && (errno==EINTR))
- continue;
-#endif
- break;
+ assert( buf != NULL );
+ assert( sbb != NULL );
+ assert( sbb->buf_size > 0 );
+
+ max = sbb->buf_end - sbb->buf_ptr;
+ max = ( max < len) ? max : len;
+ if ( max ) {
+ memcpy( buf, sbb->buf_base + sbb->buf_ptr, max );
+ sbb->buf_ptr += max;
+ if ( sbb->buf_ptr >= sbb->buf_end )
+ sbb->buf_ptr = sbb->buf_end = 0;
}
- 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;
+ return max;
}
-#endif
-ber_slen_t ber_pvt_sb_write( Sockbuf *sb, void *buf, ber_len_t len_arg )
+ber_slen_t
+ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
{
+ ber_len_t to_go;
ber_slen_t ret;
- ber_len_t len = len_arg;
- assert( buf != NULL );
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- assert( status_is_ok(sb) );
-
- /* slapd might have problems with this */
- assert( ber_pvt_sb_in_use( sb ) );
-
-#ifdef TEST_PARTIAL_WRITE
- if ((rand() & 3)==1) { /* 1 out of 4 */
- errno = EWOULDBLOCK;
- return -1;
- }
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- len_arg = (rand() % len_arg)+1;
- len = len_arg;
-#endif
+ to_go = buf_out->buf_end - buf_out->buf_ptr;
+ assert( to_go > 0 );
-#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
for(;;) {
- ret = sockbuf_io_write( sb, buf, len );
+ ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
+ buf_out->buf_ptr, to_go );
#ifdef EINTR
if ((ret<0) && (errno==EINTR))
continue;
#endif
break;
}
-#ifdef USE_SASL
- }
-#endif
+ if ( ret <= 0 )
return ret;
-}
-
-int ber_pvt_sb_close( Sockbuf *sb )
-{
- int ret;
-
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- assert( sb->sb_io );
- assert( sb->sb_io->sbi_close );
- assert( status_is_ok(sb) );
- assert( ber_pvt_sb_in_use( sb ) );
- ret = sb->sb_io->sbi_close( sb );
- ber_pvt_sb_set_desc( sb, -1 );
-
+ buf_out->buf_ptr += ret;
+ if (buf_out->buf_ptr == buf_out->buf_end)
+ buf_out->buf_end = buf_out->buf_ptr = 0;
+ if ( ret < to_go )
+ /* not enough data, so pretend no data was sent. */
+ return -1;
return ret;
}
-int ber_pvt_sb_set_readahead( Sockbuf *sb, int rh )
-{
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- assert( status_is_ok(sb) );
- sb->sb_read_ahead = (rh!=0);
- return 0;
-}
-
-int ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
+int
+ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
{
#if HAVE_FCNTL
- int flags = fcntl(ber_pvt_sb_get_desc(sb), F_GETFL);
- if( nb ) {
+ int flags = fcntl( sd, F_GETFL);
+ if( nb )
flags |= O_NONBLOCK;
- } else {
+ else
flags &= ~O_NONBLOCK;
- }
- return fcntl( ber_pvt_sb_get_desc(sb), F_SETFL, flags );
+ return fcntl( sd, F_SETFL, flags );
#elif defined( FIONBIO )
ioctl_t status = nb ? 1 : 0;
#endif
}
-#define USE_NONBLOCK
-#ifdef USE_NONBLOCK
-int ber_pvt_sb_set_nonblock( Sockbuf *sb, int nb )
-{
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- 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 (ber_pvt_sb_in_use(sb)) {
- return ber_pvt_socket_set_nonblock(
- ber_pvt_sb_get_desc(sb), nb );
- }
- return 0;
-}
-#endif
-
-#define sockbuf_buf_init( bb ) do { \
- Sockbuf_Buf *sbb = (bb); \
- sbb->buf_base = NULL; \
- sbb->buf_ptr = 0; \
- sbb->buf_end = 0; \
- sbb->buf_size = 0; \
- } while(0)
-
-static int
-sockbuf_buf_destroy( Sockbuf_Buf *buf )
-{
- assert( buf != NULL);
-
- if (buf->buf_base)
- LBER_FREE( buf->buf_base );
- sockbuf_buf_init( buf );
- return 0;
-}
-
-int ber_pvt_sb_init( Sockbuf *sb )
+int
+ber_int_sb_init( Sockbuf *sb )
{
assert( sb != NULL);
- ber_int_options.lbo_valid = LBER_INITIALIZED;
-
sb->sb_valid=LBER_VALID_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 = 1; /* test */
- sb->sb_non_block = 0;
+ sb->sb_debug = ber_int_debug;
+ sb->sb_fd = AC_SOCKET_INVALID;
+ sb->sb_iod = NULL;
sb->sb_trans_needs_read = 0;
sb->sb_trans_needs_write = 0;
- sb->sb_fd = -1;
- sb->sb_iodata = NULL;
- sb->sb_io = &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
assert( SOCKBUF_VALID( sb ) );
return 0;
}
-int ber_pvt_sb_destroy( Sockbuf *sb )
+int
+ber_int_sb_close( Sockbuf *sb )
{
- assert( sb != NULL);
- assert( SOCKBUF_VALID(sb) );
-#ifdef USE_SASL
- ber_pvt_sb_clear_sec(sb);
- sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
- sockbuf_buf_destroy( &(sb->sb_sec_buf_out) );
-#endif
- ber_pvt_sb_clear_io(sb);
- sockbuf_buf_destroy( &(sb->sb_buf) );
- return ber_pvt_sb_init( sb );
-}
+ Sockbuf_IO_Desc *p;
-#ifdef USE_SASL
-int ber_pvt_sb_set_sec( Sockbuf *sb, Sockbuf_Sec * sec, void *arg )
-{
- int len;
assert( sb != NULL);
- assert( SOCKBUF_VALID( *sb ) );
- if ((sb->sb_sec) || (sec==NULL))
- return -1;
-
- sb->sb_sec = sec;
- if ((sec->sbs_setup) && (sec->sbs_setup( sb, arg)<0)) {
+ p = sb->sb_iod;
+ while ( p ) {
+ if ( p->sbiod_io->sbi_close &&
+ p->sbiod_io->sbi_close( p ) < 0 )
return -1;
+ p = p->sbiod_next;
}
- len = sb->sb_buf.buf_end - sb->sb_buf.buf_ptr;
+ sb->sb_fd = AC_SOCKET_INVALID;
- 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->sb_sec_buf_in ) : 0;
- sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
- }
- update_status( sb );
return 0;
}
-int ber_pvt_sb_clear_sec( Sockbuf *sb )
+int
+ber_int_sb_destroy( Sockbuf *sb )
{
+ Sockbuf_IO_Desc *p;
+
assert( sb != NULL);
assert( SOCKBUF_VALID( 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;
+ while ( sb->sb_iod ) {
+ p = sb->sb_iod->sbiod_next;
+ ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
+ sb->sb_iod->sbiod_level );
+ sb->sb_iod = p;
+}
+ return ber_int_sb_init( sb );
}
-#endif
-int ber_pvt_sb_set_io( Sockbuf *sb, Sockbuf_IO *trans, void *arg )
+ber_slen_t
+ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
{
+ ber_slen_t ret;
+
+ assert( buf != NULL );
assert( sb != NULL);
+ assert( sb->sb_iod != NULL );
assert( SOCKBUF_VALID( sb ) );
- assert( sb->sb_io == &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;
+ for (;;) {
+ ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
+#ifdef EINTR
+ if ( ( ret < 0 ) && ( errno == EINTR ) )
+ continue;
+#endif
+ break;
+}
+ return ret;
}
-int ber_pvt_sb_clear_io( Sockbuf *sb )
+ber_slen_t
+ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
{
+ ber_slen_t ret;
+
+ assert( buf != NULL );
assert( sb != NULL);
+ assert( sb->sb_iod != NULL );
assert( SOCKBUF_VALID( sb ) );
- if (sb->sb_io==&sb_IO_None)
- return -1;
-
- if ((sb->sb_io->sbi_remove) && (sb->sb_io->sbi_remove( sb )<0))
- return -1;
-
- sb->sb_io = &sb_IO_None;
-
- sb->sb_trans_ready = 0;
- sb->sb_trans_needs_read = 0;
- sb->sb_trans_needs_write = 0;
-
- return 0;
+ for (;;) {
+ ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
+#ifdef EINTR
+ if ( ( ret < 0 ) && ( errno == EINTR ) )
+ continue;
+#endif
+ break;
+}
+ return ret;
}
/*
*/
static ber_slen_t
-stream_read( Sockbuf *sb, void *buf, ber_len_t len )
+sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
- assert( sb != NULL);
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL);
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
#if defined(MACOS)
/*
* MacTCP/OpenTransport
*/
- return tcpread( ber_pvt_sb_get_desc(sb), 0, (unsigned char *)buf,
+ return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
len, NULL );
#elif defined( HAVE_PCNFS ) || \
*/
{
int rc;
- rc = recv( ber_pvt_sb_get_desc(sb), buf, len, 0 );
+
+ rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
#ifdef HAVE_WINSOCK
if ( rc < 0 )
/*
* NCSA Telnet TCP/IP stack (under DOS)
*/
- return nread( ber_pvt_sb_get_desc(sb), buf, len );
+ return nread( sbiod->sbiod_sb->sb_fd, buf, len );
#else
- return read( ber_pvt_sb_get_desc(sb), buf, len );
+ return read( sbiod->sbiod_sb->sb_fd, buf, len );
#endif
}
static ber_slen_t
-stream_write( Sockbuf *sb, void *buf, ber_len_t len )
+sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
- assert( sb != NULL);
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL);
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
#if defined(MACOS)
/*
* MacTCP/OpenTransport
*/
#define MAX_WRITE 65535
- return tcpwrite( ber_pvt_sb_get_desc(sb),
- (unsigned char *)(buf),
+ return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
(len<MAX_WRITE)? len : MAX_WRITE );
#elif defined( HAVE_PCNFS) \
{
int rc;
- rc = send( ber_pvt_sb_get_desc(sb), buf, len, 0 );
+
+ rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
#ifdef HAVE_WINSOCK
if ( rc < 0 )
{
int err;
+
err = WSAGetLastError();
errno = err;
}
}
#elif defined(HAVE_NCSA)
- return netwrite( ber_pvt_sb_get_desc(sb), buf, len );
+ return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
#elif defined(VMS)
/*
* VMS -- each write must be 64K or smaller
*/
#define MAX_WRITE 65535
- return write( ber_pvt_sb_get_desc(sb), buf,
+ return write( sbiod->sbiod_sb->sb_fd, buf,
(len<MAX_WRITE)? len : MAX_WRITE);
#else
- return write( ber_pvt_sb_get_desc(sb), buf, len );
+ return write( sbiod->sbiod_sb->sb_fd, buf, len );
#endif
}
static int
-stream_close( Sockbuf *sb )
+sb_stream_close( Sockbuf_IO_Desc *sbiod )
{
- assert( sb != NULL);
- assert( SOCKBUF_VALID( sb ) );
- tcp_close( ber_pvt_sb_get_desc( sb ) );
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+ tcp_close( sbiod->sbiod_sb->sb_fd );
return 0;
}
-Sockbuf_IO ber_pvt_sb_io_tcp=
+/* The argument is a pointer to the socket descriptor */
+static int
+sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
+ assert( sbiod != NULL );
+
+ if ( arg != NULL )
+ sbiod->sbiod_sb->sb_fd = *((int *)arg);
+ return 0;
+}
+
+static int
+sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
+ /* This is an end IO descriptor */
+ return 0;
+}
+
+Sockbuf_IO ber_sockbuf_io_tcp =
{
- NULL, /* sbi_setup */
- NULL, /* sbi_release */
- stream_read, /* sbi_read */
- stream_write, /* sbi_write */
- stream_close, /* sbi_close */
+ sb_stream_setup, /* sbi_setup */
+ NULL, /* sbi_remove */
+ sb_stream_ctrl, /* sbi_ctrl */
+ sb_stream_read, /* sbi_read */
+ sb_stream_write, /* sbi_write */
+ sb_stream_close /* sbi_close */
};
/*
};
static int
-dgram_setup( Sockbuf *sb, void *arg )
+sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
{
- assert( sb != NULL);
- assert( SOCKBUF_VALID( sb ) );
+ struct dgram_data *p;
+
+ assert( sbiod != NULL);
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- sb->sb_iodata = LBER_MALLOC( sizeof( struct dgram_data ) );
- if (sb->sb_iodata==NULL)
+ p = LBER_MALLOC( sizeof( *p ) );
+ if ( p == NULL )
return -1;
- sb->sb_read_ahead = 1; /* important since udp is packet based. */
+ memset( p, 0, sizeof( *p ) );
+ sbiod->sbiod_pvt = (void *)p;
+ if ( arg != NULL )
+ sbiod->sbiod_sb->sb_fd = *((int *)arg);
return 0;
}
static int
-dgram_release( Sockbuf *sb )
+sb_dgram_release( Sockbuf_IO_Desc *sbiod )
{
- assert( sb != NULL);
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL);
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- LBER_FREE( sb->sb_iodata );
+ LBER_FREE( sbiod->sbiod_pvt );
+ sbiod->sbiod_pvt = NULL;
return 0;
}
static ber_slen_t
-dgram_read( Sockbuf *sb, void *buf, ber_len_t len )
+sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
#ifdef LDAP_CONNECTIONLESS
ber_slen_t rc;
socklen_t addrlen;
- struct dgram_data *dd;
+ struct dgram_data *p;
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
assert( buf != NULL );
- dd = (struct dgram_data *)(sb->sb_iodata);
+ p = (struct dgram_data *)sbiod->sbiod_pvt;
addrlen = sizeof( struct sockaddr );
- rc=recvfrom( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->src), &addrlen );
+ rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->src,
+ &addrlen );
- if ( sb->sb_debug ) {
- ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
- "dgram_read udp_read %ld bytes\n",
- (long) rc );
- if ( rc > 0 )
- ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
- buf, rc );
- }
return rc;
# else /* LDAP_CONNECTIONLESS */
return -1;
}
static ber_slen_t
-dgram_write( Sockbuf *sb, void *buf, ber_len_t len )
+sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
#ifdef LDAP_CONNECTIONLESS
ber_slen_t rc;
- struct dgram_data *dd;
+ struct dgram_data *p;
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
assert( buf != NULL );
- dd = (struct dgram_data *)(sb->sb_iodata);
+ p = (struct dgram_data *)sbiod->sbiod_pvt;
- rc=sendto( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->dst),
+ rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->dst,
sizeof( struct sockaddr ) );
if ( rc <= 0 )
- return( -1 );
+ return -1;
/* fake error if write was not atomic */
if (rc < len) {
# ifdef EMSGSIZE
errno = EMSGSIZE;
# endif
- return( -1 );
+ return -1;
}
return rc;
#else
}
static int
-dgram_close( Sockbuf *sb )
+sb_dgram_close( Sockbuf_IO_Desc *sbiod )
{
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- tcp_close( ber_pvt_sb_get_desc(sb) );
+ tcp_close( sbiod->sbiod_sb->sb_fd );
return 0;
}
-Sockbuf_IO ber_pvt_sb_io_udp=
+static int
+sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
{
- dgram_setup, /* sbi_setup */
- dgram_release, /* sbi_release */
- dgram_read, /* sbi_read */
- dgram_write, /* sbi_write */
- dgram_close, /* sbi_close */
+ struct dgram_data *p;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ p = (struct dgram_data *)sbiod->sbiod_pvt;
+
+ if ( opt == LBER_SB_OPT_UDP_SET_DST ) {
+ memcpy( &p->dst, arg, sizeof( struct sockaddr ) );
+ return 1;
+ }
+ else if ( opt == LBER_SB_OPT_UDP_GET_SRC ) {
+ *(( struct sockaddr **)arg) = &p->src;
+ return 1;
+ }
+ /* This is an end IO descriptor */
+ return 0;
+}
+
+Sockbuf_IO ber_sockbuf_io_udp =
+{
+ sb_dgram_setup, /* sbi_setup */
+ sb_dgram_release, /* sbi_release */
+ sb_dgram_ctrl, /* sbi_ctrl */
+ sb_dgram_read, /* sbi_read */
+ sb_dgram_write, /* sbi_write */
+ sb_dgram_close /* sbi_close */
};
-int ber_pvt_sb_udp_set_dst(Sockbuf *sb, void *addr )
+/*
+ * Support for readahead (UDP needs it)
+ */
+
+static int
+sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
{
- struct dgram_data *dd;
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- assert( sb->sb_io == &ber_pvt_sb_io_udp );
- dd = (struct dgram_data *) (sb->sb_iodata);
- memcpy( &(dd->dst), addr, sizeof( struct sockaddr ) );
+ Sockbuf_Buf *p;
+
+ assert( sbiod != NULL );
+
+ p = LBER_MALLOC( sizeof( *p ) );
+ if ( p == NULL )
+ return -1;
+ ber_pvt_sb_buf_init( p );
+ if ( arg == NULL )
+ ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
+ else
+ ber_pvt_sb_grow_buffer( p, *((int *)arg) );
+ sbiod->sbiod_pvt = p;
return 0;
}
-void *ber_pvt_sb_udp_get_src( Sockbuf *sb )
+static int
+sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
{
- struct dgram_data *dd;
+ Sockbuf_Buf *p;
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
- assert( sb->sb_io == &ber_pvt_sb_io_udp );
- dd = (struct dgram_data *) (sb->sb_iodata);
- return &(dd->src);
+ assert( sbiod != NULL );
+
+ p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
+
+ if ( p->buf_ptr != p->buf_end )
+ return -1;
+
+ ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
+ LBER_FREE( sbiod->sbiod_pvt );
+ sbiod->sbiod_pvt = NULL;
+
+ return 0;
}
+static ber_slen_t
+sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
+{
+ Sockbuf_Buf *p;
+ ber_slen_t bufptr = 0, ret, max;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+ assert( sbiod->sbiod_next != NULL );
+
+ p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
+
+ assert( p->buf_size > 0 );
+
+ /* Are there anything left in the buffer? */
+ ret = ber_pvt_sb_copy_out( p, buf, len );
+ bufptr += ret;
+ len -= ret;
+
+ if ( len == 0 )
+ return bufptr;
+
+ max = p->buf_size - p->buf_end;
+ ret = 0;
+ while ( max > 0 ) {
+ ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
+ max );
+#ifdef EINTR
+ if ( ( ret < 0 ) && ( errno == EINTR ) )
+ continue;
+#endif
+ break;
+}
+
+ if ( ret < 0 )
+ return ( bufptr ? bufptr : ret );
+
+ p->buf_end += ret;
+ bufptr += ber_pvt_sb_copy_out( p, buf + bufptr, len );
+ return bufptr;
+}
+
+static ber_slen_t
+sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
+{
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_next != NULL );
+
+ return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
+}
+
+static int
+sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
+{
+ assert( sbiod != NULL );
+
+ /* Just erase the buffer */
+ ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
+ return 0;
+}
+
+static int
+sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+ Sockbuf_Buf *p;
+
+ p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
+
+ if ( opt == LBER_SB_OPT_DATA_READY ) {
+ if ( p->buf_ptr != p->buf_end )
+ return 1;
+ }
+ else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
+ if ( p->buf_size >= *((ber_len_t *)arg) )
+ return 0;
+ return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
+ -1 : 1 );
+ }
+
+ return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
+}
+
+Sockbuf_IO ber_sockbuf_io_readahead =
+{
+ sb_rdahead_setup, /* sbi_setup */
+ sb_rdahead_remove, /* sbi_remove */
+ sb_rdahead_ctrl, /* sbi_ctrl */
+ sb_rdahead_read, /* sbi_read */
+ sb_rdahead_write, /* sbi_write */
+ sb_rdahead_close /* sbi_close */
+};
+
/*
- * debug routines.
- *
- * BUGS:
- * These routines should really call abort, but at the moment that would
- * break the servers.
+ * Support for simple file IO
*/
static ber_slen_t
-have_no_read( Sockbuf *sb, void *buf, ber_len_t len )
+sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL);
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
- "warning: reading from uninitialized sockbuf\n");
- errno = EBADF;
- return -1;
+ return read( sbiod->sbiod_sb->sb_fd, buf, len );
}
static ber_slen_t
-have_no_write( Sockbuf *sb, void *buf, ber_len_t len )
+sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL);
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
- "warning: writing to uninitialized sockbuf\n");
- errno = EBADF;
- return -1;
+ return write( sbiod->sbiod_sb->sb_fd, buf, len );
}
static int
-have_no_close( Sockbuf *sb )
+sb_fd_close( Sockbuf_IO_Desc *sbiod )
{
- assert( sb != NULL );
- assert( SOCKBUF_VALID( sb ) );
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ close( sbiod->sbiod_sb->sb_fd );
+ return 0;
+}
+
+/* The argument is a pointer to the file descriptor */
+static int
+sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
+ assert( sbiod != NULL );
+
+ if ( arg != NULL )
+ sbiod->sbiod_sb->sb_fd = *((int *)arg);
+ return 0;
+}
+
+static int
+sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
+ /* This is an end IO descriptor */
+ return 0;
+}
+
+Sockbuf_IO ber_sockbuf_io_fd =
+{
+ sb_fd_setup, /* sbi_setup */
+ NULL, /* sbi_remove */
+ sb_fd_ctrl, /* sbi_ctrl */
+ sb_fd_read, /* sbi_read */
+ sb_fd_write, /* sbi_write */
+ sb_fd_close /* sbi_close */
+};
+
+/*
+ * Debugging layer
+ */
- assert( 0 );
+static int
+sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+{
+ assert( sbiod != NULL );
+
+ if ( arg == NULL )
+ arg = "sockbuf_";
+
+ sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
+ if ( sbiod->sbiod_pvt == NULL )
return -1;
+ strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
+ return 0;
}
+
+static int
+sb_debug_remove( Sockbuf_IO_Desc *sbiod )
+{
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_pvt != NULL );
+
+ LBER_FREE( sbiod->sbiod_pvt );
+ sbiod->sbiod_pvt = NULL;
+ return 0;
+}
+
+static int
+sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+ return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
+}
+
+static ber_slen_t
+sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
+{
+ ber_slen_t ret;
+
+ ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
+ if ( ret < 0 ) {
+ ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
+ "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
+ (long)len, strerror( errno ) );
+ }
+ else {
+ ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
+ "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
+ (long)len, (long)ret );
+ ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
+ (const char *)buf, ret );
+ }
+ return ret;
+}
+
+static ber_slen_t
+sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
+{
+ ber_slen_t ret;
+
+ ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
+ if ( ret < 0 ) {
+ ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
+ "%swrite: want=%ld error=%s\n",
+ (char *)sbiod->sbiod_pvt, (long)len,
+ strerror( errno ) );
+ }
+ else {
+ ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
+ "%swrite: want=%ld, written=%ld\n",
+ (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
+ ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
+ (const char *)buf, ret );
+ }
+ return ret;
+}
+
+Sockbuf_IO ber_sockbuf_io_debug =
+{
+ sb_debug_setup, /* sbi_setup */
+ sb_debug_remove, /* sbi_remove */
+ sb_debug_ctrl, /* sbi_ctrl */
+ sb_debug_read, /* sbi_read */
+ sb_debug_write, /* sbi_write */
+ NULL /* sbi_close */
+};
+
if ( lr != NULL ) {
sb = lr->lr_conn->lconn_sb;
} else {
- sb = &ld->ld_sb;
+ sb = ld->ld_sb;
}
if ( ber_flush( sb, ber, 1 ) != 0 ) {
ld->ld_cldapnaddr = 0;
ld->ld_cldapaddrs = NULL;
- if (ber_pvt_sb_set_io( &(ld->ld_sb), &ber_pvt_sb_io_udp, NULL )<0) {
+ if ( ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_udp,
+ LBER_SBIOD_LEVEL_PROVIDER, (void *)&s ) < 0 ) {
ldap_ld_free(ld, 1, NULL, NULL );
+ tcp_close( s );
return NULL;
}
+ if ( ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_readahead,
+ LBER_SBIOD_LEVEL_PROVIDER, NULL ) < 0 ) {
+ ldap_ld_free( ld, 1, NULL, NULL );
+ return NULL;
+ }
+#ifdef LDAP_DEBUG
+ ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_debug, INT_MAX, NULL );
+#endif
ld->ld_version = LDAP_VERSION2;
DO_RETURN( NULL );
}
- ber_pvt_sb_udp_set_dst( &ld->ld_sb, ld->ld_cldapaddrs[0] );
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST,
+ ld->ld_cldapaddrs[0] );
cldap_setretryinfo( ld, 0, 0 );
--ld->ld_msgid; /* use same id as before */
}
- ber_pvt_sb_udp_set_dst( &(ld->ld_sb),
- ld->ld_cldapaddrs[ cri.cri_useaddr ] );
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)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 *)
cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
struct cldap_retinfo *crip, const char *base )
{
- Sockbuf *sb = &ld->ld_sb;
BerElement ber;
char *logdn;
int ret, fromaddr, i;
* got a result: determine which server it came from
* decode into ldap message chain
*/
- src = (struct sockaddr_in *) ber_pvt_sb_udp_get_src( sb );
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_GET_SRC, (void *)&src );
for ( fromaddr = 0; fromaddr < ld->ld_cldapnaddr; ++fromaddr ) {
if ( memcmp( &((struct sockaddr_in *)
if ( i == fromaddr ) {
continue;
}
- ber_pvt_sb_udp_set_dst( sb, ld->ld_cldapaddrs[i] );
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)ld->ld_cldapaddrs[i] );
Debug( LDAP_DEBUG_TRACE, "cldap_result abandoning id %d (to %s)\n",
msgid, inet_ntoa( ((struct sockaddr_in *)
return( NULL );
}
- if( ! ber_pvt_sb_in_use( &ld->ld_sb ) ) {
+ if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected yet */
int rc = ldap_open_defconn( ld );
#include "../liblber/lber-int.h"
#define ldap_debug (ldap_int_global_options.ldo_debug)
+
+#include "ldap_log.h"
+
#undef Debug
#define Debug( level, fmt, arg1, arg2, arg3 ) \
ldap_log_printf( NULL, (level), (fmt), (arg1), (arg2), (arg3) )
-#include "ldap_log.h"
-
#include "ldap.h"
#include "ldap_pvt.h"
*/
struct ldap {
- Sockbuf ld_sb; /* socket descriptor & buffer */
+ Sockbuf *ld_sb; /* socket descriptor & buffer */
struct ldapoptions ld_options;
LIBLDAP_F (int) ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm );
LIBLDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, unsigned long address, int port, int async );
-LIBLDAP_F (void) ldap_close_connection( Sockbuf *sb );
-
#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
LIBLDAP_F (char *) ldap_host_connected_to( Sockbuf *sb );
#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
- ber_pvt_sb_init( &(ld->ld_sb) );
+ ld->ld_sb = ber_sockbuf_alloc( );
+ if ( ld->ld_sb == NULL ) {
+ ldap_free_urllist( ld->ld_options.ldo_defludp );
+ LDAP_FREE( (char*) ld );
+ WSACleanup( );
+ return LDAP_NO_MEMORY;
+ }
*ldp = ld;
return LDAP_SUCCESS;
switch ( srv->lud_protocol ) {
case LDAP_PROTO_TCP:
+ rc = ldap_connect_to_host( ld, sb, srv->lud_host,
+ addr, port, async );
+ if ( rc == -1 )
+ return rc;
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_tcp,
+ LBER_SBIOD_LEVEL_PROVIDER, NULL );
+ break;
case LDAP_PROTO_UDP:
- rc = ldap_connect_to_host( ld, sb, srv->lud_host, addr, port, async );
+ rc = ldap_connect_to_host( ld, sb, srv->lud_host,
+ addr, port, async );
+ if ( rc == -1 )
+ return rc;
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_udp,
+ LBER_SBIOD_LEVEL_PROVIDER, NULL );
break;
#ifdef LDAP_PF_LOCAL
case LDAP_PROTO_LOCAL:
- rc = ldap_connect_to_path( ld, sb, srv->lud_host, async );
+ rc = ldap_connect_to_path( ld, sb, srv->lud_host,
+ async );
+ if ( rc == -1 )
+ return rc;
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd,
+ LBER_SBIOD_LEVEL_PROVIDER, NULL );
break;
#endif /* LDAP_PF_LOCAL */
default:
- rc = -1;
+ return -1;
break;
}
- if ( rc == -1 ) {
- return( rc );
- }
-
- ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_readahead,
+ LBER_SBIOD_LEVEL_PROVIDER, NULL );
+#ifdef LDAP_DEBUG
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, INT_MAX, NULL );
+#endif
#ifdef HAVE_TLS
if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
} break;
case LDAP_OPT_DESC:
- if(ld == NULL) {
+ if( ld == NULL || ld->ld_sb == NULL ) {
/* bad param */
break;
}
- * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
return LDAP_OPT_SUCCESS;
case LDAP_OPT_TIMEOUT:
rc = ldap_pvt_connect(ld, s, &sin, async);
if ( (rc == 0) || (rc == -2) ) {
- ber_pvt_sb_set_desc( sb, s );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
break;
}
return rc;
}
-void
-ldap_close_connection( Sockbuf *sb )
-{
- ber_pvt_sb_close( sb );
-}
-
-
#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL )
char *
ldap_host_connected_to( Sockbuf *sb )
struct hostent he_buf;
int local_h_errno;
char *ha_buf=NULL;
+ ber_socket_t sd;
#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
(void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
len = sizeof( sin );
- if ( getpeername( ber_pvt_sb_get_desc(sb), (struct sockaddr *)&sin, &len ) == -1 ) {
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
return( NULL );
}
ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
+ ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
- if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_writefds )) {
- FD_SET( (u_int) sb->sb_sd, &sip->si_writefds );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ if ( !FD_ISSET( sd, &sip->si_writefds )) {
+ FD_SET( sd, &sip->si_writefds );
}
}
ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
+ ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
- if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_readfds )) {
- FD_SET( (u_int) sb->sb_sd, &sip->si_readfds );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ if ( !FD_ISSET( sd, &sip->si_readfds )) {
+ FD_SET( sd, &sip->si_readfds );
}
}
ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
+ ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
- FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_writefds );
- FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_readfds );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ FD_CLR( sd, &sip->si_writefds );
+ FD_CLR( sd, &sip->si_readfds );
}
ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
+ ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
- return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_writefds ));
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ return( FD_ISSET( sd, &sip->si_use_writefds ));
}
ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
+ ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
- return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_readfds ));
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
+ return( FD_ISSET( sd, &sip->si_use_readfds ));
}
rc = ldap_pvt_connect(ld, s, &server, async);
if (rc == 0) {
- ber_pvt_sb_set_desc( sb, s );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, (void *)&s );
} else {
ldap_pvt_close_socket(ld, s);
}
Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
- if ( ! ber_pvt_sb_in_use(&ld->ld_sb ) ) {
+ if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected yet */
int rc = ldap_open_defconn( ld );
return( NULL );
}
- lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb;
+ lc->lconn_sb = ( use_ldsb ) ? ld->ld_sb : sb;
if ( connect ) {
for ( srv = srvlist; srv != NULL; srv = srv->lud_next ) {
}
}
- /* force closure */
- ldap_close_connection( lc->lconn_sb );
- ber_pvt_sb_destroy( lc->lconn_sb );
-
if( lc->lconn_ber != NULL ) {
ber_free( lc->lconn_ber, 1 );
}
if ( lc->lconn_krbinstance != NULL ) {
LDAP_FREE( lc->lconn_krbinstance );
}
- if ( lc->lconn_sb != &ld->ld_sb ) {
+ if ( lc->lconn_sb != ld->ld_sb ) {
ber_sockbuf_free( lc->lconn_sb );
}
if( lc->lconn_rebind_queue != NULL) {
( lc->lconn_server->lud_host == NULL ) ? "(null)"
: lc->lconn_server->lud_host,
lc->lconn_server->lud_port, ( lc->lconn_sb ==
- &ld->ld_sb ) ? " (default)" : "" );
+ ld->ld_sb ) ? " (default)" : "" );
}
fprintf( stderr, " refcnt: %d status: %s\n", lc->lconn_refcnt,
( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ?
}
#endif /* LDAP_DEBUG */
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
- if ( ber_pvt_sb_data_ready(lc->lconn_sb) ) {
+ if ( ber_sockbuf_ctrl( lc->lconn_sb,
+ LBER_SB_OPT_DATA_READY, NULL ) ) {
rc = try_read1msg( ld, msgid, all, lc->lconn_sb,
lc, result );
break;
int rc;
ber_tag_t tag;
ber_len_t len;
+ ber_socket_t sd;
- if ( ! ber_pvt_sb_data_ready(&ld->ld_sb) ) {
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
+ if ( sd != AC_SOCKET_INVALID ) {
/* restored from ldap_select1() in result.c version 1.24 */
fd_set readfds;
if ( ldap_int_tblsize == 0 )
ldap_int_ip_init();
FD_ZERO( &readfds );
- FD_SET( ber_pvt_sb_get_desc(&ld->ld_sb), &readfds );
+ FD_SET( sd, &readfds );
rc = select( ldap_int_tblsize, &readfds, 0, 0, timeout );
if ( rc == -1 || rc == 0 ) {
}
/* get the next message */
- if ( (tag = ber_get_next( &ld->ld_sb, &len, ber ))
+ if ( (tag = ber_get_next( ld->ld_sb, &len, ber ))
!= LDAP_TAG_MESSAGE ) {
ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
LDAP_LOCAL_ERROR);
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
+#include <ac/errno.h>
#include "ldap-int.h"
* Various Cyrus SASL related stuff.
*/
-static int sasl_setup( Sockbuf *sb, void *arg );
-static int sasl_remove( Sockbuf *sb );
-static ber_slen_t sasl_read( Sockbuf *sb, void *buf, ber_len_t len );
-static ber_slen_t sasl_write( Sockbuf *sb, void *buf, ber_len_t len );
-static int sasl_close( Sockbuf *sb );
-
-static Sockbuf_IO sasl_io=
-{
-sasl_setup,
-sasl_remove,
-sasl_read,
-sasl_write,
-sasl_close
-};
-
-#define HAS_SASL( sb ) ((sb)->sb_io==&sasl_io)
+#define MAX_BUFF_SIZE 65536
+#define MIN_BUFF_SIZE 4096
static char *
array2str( char **a )
return -1;
}
-int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
+/*
+ * SASL encryption support for LBER Sockbufs
+ */
+
+struct sb_sasl_data {
+ sasl_conn_t *sasl_context;
+ Sockbuf_Buf sec_buf_in;
+ Sockbuf_Buf buf_in;
+ Sockbuf_Buf buf_out;
+};
+
+static int
+sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg )
{
- /* don't install the stuff unless security has been negotiated */
+ struct sb_sasl_data *p;
- if ( !HAS_SASL( sb ) ) {
- ber_pvt_sb_clear_io( sb );
- ber_pvt_sb_set_io( sb, &sasl_io, ctx_arg );
+ assert( sbiod != NULL );
+
+ p = LBER_MALLOC( sizeof( *p ) );
+ if ( p == NULL )
+ return -1;
+ p->sasl_context = (sasl_conn_t *)arg;
+ ber_pvt_sb_buf_init( &p->sec_buf_in );
+ ber_pvt_sb_buf_init( &p->buf_in );
+ ber_pvt_sb_buf_init( &p->buf_out );
+ if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, MIN_BUFF_SIZE ) < 0 ) {
+ errno = ENOMEM;
+ return -1;
}
+ sbiod->sbiod_pvt = p;
+
return 0;
}
-static int sasl_setup( Sockbuf *sb, void *arg )
+static int
+sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
{
- sb->sb_iodata = arg;
+ struct sb_sasl_data *p;
+
+ assert( sbiod != NULL );
+
+ p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+ ber_pvt_sb_buf_destroy( &p->sec_buf_in );
+ ber_pvt_sb_buf_destroy( &p->buf_in );
+ ber_pvt_sb_buf_destroy( &p->buf_out );
+ LBER_FREE( p );
+ sbiod->sbiod_pvt = NULL;
return 0;
}
-static int sasl_remove( Sockbuf *sb )
+static ber_len_t
+sb_sasl_pkt_length( const char *buf, int debuglevel )
{
- return 0;
+ ber_len_t size;
+ long tmp;
+
+ assert( buf != NULL );
+
+ tmp = *((long *)buf);
+ size = ntohl( tmp );
+
+ if ( size > MAX_BUFF_SIZE ) {
+ /* somebody is trying to mess me up. */
+ ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
+ "sb_sasl_pkt_length: received illegal packet length "
+ "of %lu bytes\n", (unsigned long)size );
+ size = 16; /* this should lead to an error. */
+}
+
+ return size + 4; /* include the size !!! */
}
-static ber_slen_t sasl_read( Sockbuf *sb, void *buf, ber_len_t buflen )
+/* Drop a processed packet from the input buffer */
+static void
+sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel )
{
- char *recv_tok;
- unsigned recv_tok_len;
- sasl_conn_t *conn = (sasl_conn_t *)sb->sb_iodata;
+ ber_slen_t len;
+
+ len = sec_buf_in->buf_ptr - sec_buf_in->buf_end;
+ if ( len > 0 )
+ memmove( sec_buf_in->buf_base, sec_buf_in->buf_base +
+ sec_buf_in->buf_end, len );
+
+ if ( len >= 4 ) {
+ sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base,
+ debuglevel);
+ }
+ else {
+ sec_buf_in->buf_end = 0;
+ }
+ sec_buf_in->buf_ptr = len;
+}
- if ((ber_pvt_sb_io_tcp.sbi_read)( sb, buf, buflen ) != buflen ) {
- return -1;
+static ber_slen_t
+sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct sb_sasl_data *p;
+ ber_slen_t ret, bufptr;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+
+ /* Are there anything left in the buffer? */
+ ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len );
+ bufptr = ret;
+ len -= ret;
+
+ if ( len == 0 )
+ return bufptr;
+
+ ber_pvt_sb_buf_destroy( &p->buf_in );
+
+ /* Read the length of the packet */
+ while ( p->sec_buf_in.buf_ptr < 4 ) {
+ ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base,
+ 4 - p->sec_buf_in.buf_ptr );
+#ifdef EINTR
+ if ( ( ret < 0 ) && ( errno == EINTR ) )
+ continue;
+#endif
+ if ( ret <= 0 )
+ return ret;
+
+ p->sec_buf_in.buf_ptr += ret;
}
- if ( sasl_decode( conn, buf, buflen, &recv_tok, &recv_tok_len ) != SASL_OK ) {
+ /* The new packet always starts at p->sec_buf_in.buf_base */
+ ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base,
+ sbiod->sbiod_sb->sb_debug );
+
+ /* Grow the packet buffer if neccessary */
+ if ( ( p->sec_buf_in.buf_size < ret ) &&
+ ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) {
+ errno = ENOMEM;
return -1;
}
-
- if ( recv_tok_len > buflen ) {
- LDAP_FREE( recv_tok );
+ p->sec_buf_in.buf_end = ret;
+
+ /* Did we read the whole encrypted packet? */
+ while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) {
+ /* No, we have got only a part of it */
+ ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr;
+
+ ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base +
+ p->sec_buf_in.buf_ptr, ret );
+#ifdef EINTR
+ if ( ( ret < 0 ) && ( errno == EINTR ) )
+ continue;
+#endif
+ if ( ret <= 0 )
+ return ret;
+
+ p->sec_buf_in.buf_ptr += ret;
+ }
+
+ /* Decode the packet */
+ ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base,
+ p->sec_buf_in.buf_end, &p->buf_in.buf_base,
+ (unsigned *)&p->buf_in.buf_end );
+ if ( ret != SASL_OK ) {
+ ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
+ "sb_sasl_read: failed to decode packet: %s\n",
+ sasl_errstring( ret, NULL, NULL ) );
+ sb_sasl_drop_packet( &p->sec_buf_in,
+ sbiod->sbiod_sb->sb_debug );
+ errno = EIO;
return -1;
}
+
+ /* Drop the packet from the input buffer */
+ sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug );
- memcpy( buf, recv_tok, recv_tok_len );
+ p->buf_in.buf_size = p->buf_in.buf_end;
- LDAP_FREE( recv_tok );
+ bufptr += ber_pvt_sb_copy_out( &p->buf_in, buf + bufptr, len );
- return recv_tok_len;
+ return bufptr;
}
-static ber_slen_t sasl_write( Sockbuf *sb, void *buf, ber_len_t len )
+static ber_slen_t
+sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
- char *wrapped_tok;
- unsigned wrapped_tok_len;
- sasl_conn_t *conn = (sasl_conn_t *)sb->sb_iodata;
+ struct sb_sasl_data *p;
+ int ret;
- if ( sasl_encode( conn, (const char *)buf, len,
- &wrapped_tok, &wrapped_tok_len ) != SASL_OK ) {
- return -1;
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+
+ /* Are there anything left in the buffer? */
+ if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
+ ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
+ if ( ret <= 0 )
+ return ret;
}
- if ((ber_pvt_sb_io_tcp.sbi_write)( sb, wrapped_tok, wrapped_tok_len ) != wrapped_tok_len ) {
- LDAP_FREE( wrapped_tok );
+ /* now encode the next packet. */
+ ber_pvt_sb_buf_destroy( &p->buf_out );
+ ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base,
+ (unsigned *)&p->buf_out.buf_size );
+ if ( ret != SASL_OK ) {
+ ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
+ "sb_sasl_write: failed to encode packet: %s\n",
+ sasl_errstring( ret, NULL, NULL ) );
return -1;
}
+ p->buf_out.buf_end = p->buf_out.buf_size;
- LDAP_FREE( wrapped_tok );
-
+ ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
+ if ( ret <= 0 )
+ return ret;
return len;
}
-static int sasl_close( Sockbuf *sb )
+static int
+sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
{
- return (ber_pvt_sb_io_tcp.sbi_close)( sb );
+ struct sb_sasl_data *p;
+
+ p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
+
+ if ( opt == LBER_SB_OPT_DATA_READY ) {
+ if ( p->buf_in.buf_ptr != p->buf_in.buf_end )
+ return 1;
+ }
+
+ return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
+}
+
+Sockbuf_IO ldap_pvt_sockbuf_io_sasl =
+{
+ sb_sasl_setup, /* sbi_setup */
+ sb_sasl_remove, /* sbi_remove */
+ sb_sasl_ctrl, /* sbi_ctrl */
+ sb_sasl_read, /* sbi_read */
+ sb_sasl_write, /* sbi_write */
+ NULL /* sbi_close */
+};
+
+int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
+{
+ /* don't install the stuff unless security has been negotiated */
+
+ if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
+ &ldap_pvt_sockbuf_io_sasl ) )
+ ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl,
+ LBER_SBIOD_LEVEL_APPLICATION, ctx_arg );
+
+ return LDAP_SUCCESS;
}
static int
LDAPControl **cctrls )
{
const char *mech;
- int saslrc, rc, ssf = 0;
+ int saslrc, rc;
+ sasl_ssf_t *ssf = NULL;
unsigned credlen;
struct berval ccred, *scred;
char *host;
sasl_interact_t *client_interact = NULL;
+ struct sockaddr_in sin;
+ socklen_t len;
+ sasl_security_properties_t secprops;
+ ber_socket_t sd;
Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 );
return ld->ld_errno;
}
- if( ! ber_pvt_sb_in_use( &ld->ld_sb ) ) {
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
+
+ if ( sd == AC_SOCKET_INVALID ) {
/* not connected yet */
int rc = ldap_open_defconn( ld );
if( rc < 0 ) return ld->ld_errno;
+ ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
}
/* XXX this doesn't work with PF_LOCAL hosts */
- host = ldap_host_connected_to( &ld->ld_sb );
+ host = ldap_host_connected_to( ld->ld_sb );
if ( host == NULL ) {
ld->ld_errno = LDAP_UNAVAILABLE;
sasl_dispose( &ld->ld_sasl_context );
}
- saslrc = sasl_client_new( "ldap", host, callbacks, 0, &ld->ld_sasl_context );
+ saslrc = sasl_client_new( "ldap", host, callbacks, SASL_SECURITY_LAYER,
+ &ld->ld_sasl_context );
LDAP_FREE( host );
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
- ld->ld_errno = sasl_err2ldap( rc );
+ ld->ld_errno = sasl_err2ldap( saslrc );
sasl_dispose( &ld->ld_sasl_context );
return ld->ld_errno;
}
+ len = sizeof( sin );
+ if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "SASL: can't query remote IP.\n",
+ 0, 0, 0 );
+ ld->ld_errno = LDAP_OPERATIONS_ERROR;
+ return ld->ld_errno;
+ }
+ sasl_setprop( ld->ld_sasl_context, SASL_IP_REMOTE, &sin );
+
+ len = sizeof( sin );
+ if ( getsockname( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "SASL: can't query local IP.\n",
+ 0, 0, 0 );
+ ld->ld_errno = LDAP_OPERATIONS_ERROR;
+ return ld->ld_errno;
+ }
+ sasl_setprop( ld->ld_sasl_context, SASL_IP_LOCAL, &sin );
+
+ memset( &secprops, 0, sizeof( secprops ) );
+ secprops.min_ssf = ld->ld_options.ldo_sasl_minssf;
+ secprops.max_ssf = ld->ld_options.ldo_sasl_maxssf;
+ secprops.security_flags = SASL_SECURITY_LAYER;
+ secprops.maxbufsize = 65536;
+ sasl_setprop( ld->ld_sasl_context, SASL_SEC_PROPS, &secprops );
+
ccred.bv_val = NULL;
ccred.bv_len = 0;
assert ( rc == LDAP_SUCCESS );
if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf )
- == SASL_OK && ssf ) {
- ldap_pvt_sasl_install( &ld->ld_sb, ld->ld_sasl_context );
+ == SASL_OK && ssf && *ssf ) {
+ ldap_pvt_sasl_install( ld->ld_sb, ld->ld_sasl_context );
}
return rc;
char *dnp;
int authmethod;
+ printf("rebind for request=%d msgid=%ld url=%s\n",
+ request, (long) msgid, url );
+
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
getline( dn, sizeof(dn), stdin,
"re-bind method (0->simple, 1->krbv41, 2->krbv42, 3->krbv41&2)? " );
case 't': /* copy ber's to given file */
copyfname = strdup( optarg );
- copyoptions = LBER_TO_FILE;
+/* copyoptions = LBER_TO_FILE; */
break;
case 'T': /* only output ber's to given file */
copyfname = strdup( optarg );
- copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY);
+/* copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); */
break;
default:
}
if ( copyfname != NULL ) {
- if ( (ld->ld_sb.sb_fd = open( copyfname, O_WRONLY | O_CREAT,
+ if ( ( ld->ld_sb->sb_fd = open( copyfname, O_WRONLY | O_CREAT,
0600 )) == -1 ) {
perror( copyfname );
exit ( EXIT_FAILURE );
}
- ld->ld_sb.sb_options = copyoptions;
+ ld->ld_sb->sb_options = copyoptions;
}
bound = 0;
static int tls_opt_require_cert = 0;
static char *tls_opt_ciphersuite = NULL;
-#define HAS_TLS( sb ) ((sb)->sb_io==&tls_io)
+#define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
+ (void *)&ldap_pvt_sockbuf_io_tls )
-static int tls_setup( Sockbuf *sb, void *arg );
-static int tls_remove( Sockbuf *sb );
-static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
-static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
-static int tls_close( Sockbuf *sb );
static void tls_report_error( void );
-static Sockbuf_IO tls_io=
-{
- tls_setup,
- tls_remove,
- tls_read,
- tls_write,
- tls_close
-};
-
static void tls_info_cb( SSL *ssl, int where, int ret );
static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
}
static SSL *
-alloc_handle( Sockbuf *sb, void *ctx_arg )
+alloc_handle( void *ctx_arg )
{
- int err;
SSL_CTX *ctx;
SSL *ssl;
if ( tls_opt_trace ) {
SSL_set_info_callback( ssl, tls_info_cb );
}
- sb->sb_iodata = ssl;
- SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) );
return ssl;
}
return 0;
}
+/*
+ * TLS support for LBER Sockbufs
+ */
+
+struct tls_data {
+ SSL *ssl;
+ Sockbuf_IO_Desc *sbiod;
+};
+
+extern BIO_METHOD ldap_pvt_sb_bio_method;
+
+static int
+sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+{
+ struct tls_data *p;
+ BIO *bio;
+
+ assert( sbiod != NULL );
+
+ p = LBER_MALLOC( sizeof( *p ) );
+ if ( p == NULL )
+ return -1;
+
+ p->ssl = (SSL *)arg;
+ p->sbiod = sbiod;
+ bio = BIO_new( &ldap_pvt_sb_bio_method );
+ bio->ptr = (void *)p;
+ SSL_set_bio( p->ssl, bio, bio );
+ sbiod->sbiod_pvt = p;
+ return 0;
+}
+
+static int
+sb_tls_remove( Sockbuf_IO_Desc *sbiod )
+{
+ struct tls_data *p;
+
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_pvt != NULL );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+ SSL_free( p->ssl );
+ LBER_FREE( sbiod->sbiod_pvt );
+ sbiod->sbiod_pvt = NULL;
+ return 0;
+}
+
+static int
+sb_tls_close( Sockbuf_IO_Desc *sbiod )
+{
+ struct tls_data *p;
+
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_pvt != NULL );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+ SSL_shutdown( p->ssl );
+ return 0;
+}
+
+static int
+sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+ struct tls_data *p;
+
+ assert( sbiod != NULL );
+ assert( sbiod->sbiod_pvt != NULL );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+
+ if ( opt == LBER_SB_OPT_GET_SSL ) {
+ *((SSL **)arg) = p->ssl;
+ return 1;
+ }
+
+ return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
+}
+
+static ber_slen_t
+sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct tls_data *p;
+ ber_slen_t ret;
+ int err;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+
+ ret = SSL_read( p->ssl, (char *)buf, len );
+#ifdef HAVE_WINSOCK
+ errno = WSAGetLastError();
+#endif
+ err = SSL_get_error( p->ssl, ret );
+ if (err == SSL_ERROR_WANT_READ ) {
+ sbiod->sbiod_sb->sb_trans_needs_read = 1;
+#ifdef WIN32
+ errno = EWOULDBLOCK;
+#endif
+ }
+ else
+ sbiod->sbiod_sb->sb_trans_needs_read = 0;
+ return ret;
+}
+
+static ber_slen_t
+sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct tls_data *p;
+ ber_slen_t ret;
+ int err;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ p = (struct tls_data *)sbiod->sbiod_pvt;
+
+ ret = SSL_write( p->ssl, (char *)buf, len );
+#ifdef HAVE_WINSOCK
+ errno = WSAGetLastError();
+#endif
+ err = SSL_get_error( p->ssl, ret );
+ if (err == SSL_ERROR_WANT_WRITE ) {
+ sbiod->sbiod_sb->sb_trans_needs_write = 1;
+#ifdef WIN32
+ errno = EWOULDBLOCK;
+#endif
+ }
+ else
+ sbiod->sbiod_sb->sb_trans_needs_write = 0;
+ return ret;
+}
+
+Sockbuf_IO ldap_pvt_sockbuf_io_tls =
+{
+ sb_tls_setup, /* sbi_setup */
+ sb_tls_remove, /* sbi_remove */
+ sb_tls_ctrl, /* sbi_ctrl */
+ sb_tls_read, /* sbi_read */
+ sb_tls_write, /* sbi_write */
+ sb_tls_close /* sbi_close */
+};
+
+static int
+sb_tls_bio_create( BIO *b ) {
+ b->init = 1;
+ b->num = 0;
+ b->ptr = NULL;
+ b->flags = 0;
+ return 1;
+}
+
+static int
+sb_tls_bio_destroy( BIO *b )
+{
+ if ( b == NULL )
+ return 0;
+
+ b->ptr = NULL; /* sb_tls_remove() will free it */
+ b->init = 0;
+ b->flags = 0;
+ return 1;
+}
+
+static int
+sb_tls_bio_read( BIO *b, char *buf, int len )
+{
+ struct tls_data *p;
+ int ret;
+
+ if ( buf == NULL || len <= 0 )
+ return 0;
+
+ p = (struct tls_data *)b->ptr;
+
+ if ( p == NULL || p->sbiod == NULL )
+ return 0;
+
+ ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
+
+ BIO_clear_retry_flags( b );
+ if ( ret < 0 && errno == EWOULDBLOCK )
+ BIO_set_retry_read( b );
+
+ return ret;
+}
+
+static int
+sb_tls_bio_write( BIO *b, char *buf, int len )
+{
+ struct tls_data *p;
+ int ret;
+
+ if ( buf == NULL || len <= 0 )
+ return 0;
+
+ p = (struct tls_data *)b->ptr;
+
+ if ( p == NULL || p->sbiod == NULL )
+ return 0;
+
+ ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, buf, len );
+
+ BIO_clear_retry_flags( b );
+ if ( ret < 0 && errno == EWOULDBLOCK )
+ BIO_set_retry_write( b );
+
+ return ret;
+}
+
+static long
+sb_tls_bio_ctrl( BIO *b, int cmd, long num, char *ptr )
+{
+ if ( cmd == BIO_CTRL_FLUSH ) {
+ /* The OpenSSL library needs this */
+ return 1;
+ }
+ return 0;
+}
+
+static int
+sb_tls_bio_gets( BIO *b, char *buf, int len )
+{
+ return -1;
+}
+
+static int
+sb_tls_bio_puts( BIO *b, char *str )
+{
+ return sb_tls_bio_write( b, str, strlen( str ) );
+}
+
+BIO_METHOD ldap_pvt_sb_bio_method =
+{
+ ( 100 | 0x400 ), /* it's a source/sink BIO */
+ "sockbuf glue",
+ sb_tls_bio_write,
+ sb_tls_bio_read,
+ sb_tls_bio_puts,
+ sb_tls_bio_gets,
+ sb_tls_bio_ctrl,
+ sb_tls_bio_create,
+ sb_tls_bio_destroy
+};
+
/*
* Call this to do a TLS connect on a sockbuf. ctx_arg can be
* a SSL_CTX * or NULL, in which case the default ctx is used.
SSL *ssl;
if ( HAS_TLS( sb ) ) {
- ssl = (SSL *) sb->sb_iodata;
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
} else {
- ssl = alloc_handle( sb, ctx_arg );
+ ssl = alloc_handle( ctx_arg );
if ( ssl == NULL )
return -1;
- ber_pvt_sb_clear_io( sb );
- ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
+#ifdef LDAP_DEBUG
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
+ LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
+#endif
+ ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
+ LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
}
err = SSL_connect( ssl );
ld->ld_error = ldap_strdup(ERR_error_string(err, buf));
}
Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
- ber_pvt_sb_clear_io( sb );
- ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
+ ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
+ LBER_SBIOD_LEVEL_TRANSPORT );
+#ifdef LDAP_DEBUG
+ ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
+ LBER_SBIOD_LEVEL_TRANSPORT );
+#endif
return -1;
}
return 0;
SSL *ssl;
if ( HAS_TLS( sb ) ) {
- ssl = (SSL *) sb->sb_iodata;
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
} else {
- ssl = alloc_handle( sb, ctx_arg );
+ ssl = alloc_handle( ctx_arg );
if ( ssl == NULL )
return -1;
- ber_pvt_sb_clear_io( sb );
- ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
+#ifdef LDAP_DEBUG
+ ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
+ LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
+#endif
+ ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
+ LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
}
err = SSL_accept( ssl );
return 1;
Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
tls_report_error();
- ber_pvt_sb_clear_io( sb );
- ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
+ ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
+ LBER_SBIOD_LEVEL_TRANSPORT );
+#ifdef LDAP_DEBUG
+ ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
+ LBER_SBIOD_LEVEL_TRANSPORT );
+#endif
return -1;
}
return 0;
void *
ldap_pvt_tls_sb_handle( Sockbuf *sb )
{
- if (HAS_TLS( sb ))
- return sb->sb_iodata;
- else
+ void *p;
+
+ if (HAS_TLS( sb )) {
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p );
+ return p;
+ }
return NULL;
}
void *
ldap_pvt_tls_get_handle( LDAP *ld )
{
- return ldap_pvt_tls_sb_handle(&ld->ld_sb);
+ return ldap_pvt_tls_sb_handle( ld->ld_sb );
}
const char *
return LDAP_SUCCESS;
}
-
-static int
-tls_setup( Sockbuf *sb, void *arg )
-{
- sb->sb_iodata = arg;
- return 0;
-}
-
-static int
-tls_remove( Sockbuf *sb )
-{
- SSL_free( (SSL *) sb->sb_iodata );
- return 0;
-}
-
-static ber_slen_t
-tls_write( Sockbuf *sb, void *buf, ber_len_t sz )
-{
- int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
-
-#ifdef HAVE_WINSOCK
- errno = WSAGetLastError();
-#endif
- update_flags(sb, (SSL *)sb->sb_iodata, ret );
-#ifdef WIN32
- if (sb->sb_trans_needs_write)
- errno = EWOULDBLOCK;
-#endif
- return ret;
-}
-
-static ber_slen_t
-tls_read( Sockbuf *sb, void *buf, ber_len_t sz )
-{
- int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
-
-#ifdef HAVE_WINSOCK
- errno = WSAGetLastError();
-#endif
- update_flags(sb, (SSL *)sb->sb_iodata, ret );
-#ifdef WIN32
- if (sb->sb_trans_needs_read)
- errno = EWOULDBLOCK;
-#endif
- return ret;
-}
-
-static int
-tls_close( Sockbuf *sb )
-{
- tcp_close( ber_pvt_sb_get_desc( sb ) );
- return 0;
-}
-
/* Derived from openssl/apps/s_cb.c */
static void
tls_info_cb( SSL *ssl, int where, int ret )
}
#endif
- ber_pvt_sb_destroy( &(ld->ld_sb) );
+ ber_sockbuf_free( ld->ld_sb );
LDAP_FREE( (char *) ld );
#include <quipu/ds_error.h>
#include "lber.h"
-#include "../../libraries/liblber/lber-int.h" /* get struct sockbuf */
#include "ldap.h"
#include "common.h"
#include "lutil.h" /* Get lutil_detach() */
fd_set readfds;
int rc;
struct timeval timeout;
- Sockbuf sb;
+ Sockbuf *sb;
#ifdef LDAP_CONNECTIONLESS
struct sockaddr saddr, faddr;
struct sockaddr *saddrlist[ 1 ];
conn_init();
}
- ber_pvt_sb_init( &sb );
- ber_pvt_sb_set_desc( &sb, clientsock );
- ber_pvt_sb_set_io( &sb, (udp) ? &ber_pvt_sb_io_udp :
- &ber_pvt_sb_io_tcp, NULL );
+ sb = ber_sockbuf_alloc( );
+ ber_sockbuf_add_io( sb, (udp) ? &ber_sockbuf_io_udp :
+ &ber_sockbuf_io_tcp, (void *)&clientsock );
timeout.tv_sec = idletime;
timeout.tv_usec = 0;
for ( ;; ) {
* already waiting for us on the client sock.
*/
- if ( ! ber_pvt_sb_data_ready( &sb ) ) {
+ if ( ! ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
if ( (rc = select( dtblsize, &readfds, 0, 0,
udp ? 0 : &timeout )) < 1 ) {
#ifdef LDAP_DEBUG
}
}
- if ( ber_pvt_sb_data_ready( &sb ) ||
+ if ( ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ) ||
FD_ISSET( clientsock, &readfds ) ) {
- client_request( &sb, conns, udp );
+ client_request( sb, conns, udp );
} else {
if ( (dsaconn = conn_getfd( &readfds )) == NULL ) {
Debug( LDAP_DEBUG_ANY, "No DSA activity!\n",
continue;
}
- dsa_response( dsaconn, &sb );
+ dsa_response( dsaconn, sb );
}
}
/* NOT REACHED */
#include <quipu/dua.h>
#include "lber.h"
-#include "../../libraries/liblber/lber-int.h" /* get struct berelement */
#include "ldap.h"
#include "common.h"
#ifdef LDAP_CONNECTIONLESS
if ( udp && dosyslog ) {
- sai = (struct sockaddr_in *)ber_pvt_sb_udp_get_src( &clientsb );
+ ber_sockbuf_ctrl( clientsb, LBER_SB_OPT_UDP_GET_SRC,
+ (void *)&sai );
syslog( LOG_INFO, "UDP request from unknown (%s)",
inet_ntoa( sai->sin_addr ) );
}
free( ber.ber_buf );
return;
}
- sai = (struct sockaddr_in *) ber_pvt_sb_udp_get_src( &clientsb );
+ ber_sockbuf_ctrl( clientsb, LBER_SB_OPT_UDP_GET_SRC, (void *)&sai );
if ( get_cldap_msg( msgid, tag,
(struct sockaddr *)sai ) != NULL ) {
#include <quipu/dua.h>
#include "lber.h"
-#include "../../libraries/liblber/lber-int.h" /* get struct berelement */
#include "ldap.h"
#include "common.h"
{
#ifdef LDAP_CONNECTIONLESS
if ( m->m_cldap ) {
- ber_pvt_sb_udp_set_dst( &sb, &m->m_clientaddr );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)&m->m_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
int rc;
#ifdef LDAP_CONNECTIONLESS
int cldap;
- cldap = ( sb->sb_io == &ber_pvt_sb_io_udp );
+ cldap = ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, &ber_sockbuf_io_udp );
#endif
Debug( LDAP_DEBUG_TRACE, "send_ldap_result\n", 0, 0, 0 );
#include <quipu/dua.h>
#include "lber.h"
-#include "../../libraries/liblber/lber-int.h" /* get struct berelement */
#include "ldap.h"
#include "common.h"
LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
return;
}
- ber_pvt_sb_udp_set_dst( sb, &m->m_clientaddr );
+ ber_sockbuf_ctrl( sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)&m->m_clientaddr );
if ( ber_flush( sb, ber, 1 ) != 0 ) {
send_ldap_msgresult( sb, SEARCHRESTAG, m,
#include "slap.h"
-/* we need LBER internals */
-#include "../../libraries/liblber/lber-int.h"
-
/* protected by connections_mutex */
static ldap_pvt_thread_mutex_t connections_mutex;
static Connection *connections = NULL;
#else
c = NULL;
{
- ber_socket_t i;
+ ber_socket_t i, sd;
for(i=0; i<dtblsize; i++) {
+ ber_sockbuf_ctrl( connections[i].c_sb,
+ LBER_SB_OPT_GET_FD, &sd );
+
if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[i].c_conn_state == SLAP_C_INVALID );
assert( connections[i].c_sb == 0 );
if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
assert( connections[i].c_conn_state == SLAP_C_INVALID );
- assert( !ber_pvt_sb_in_use( connections[i].c_sb ) );
+ assert( sd == AC_SOCKET_INVALID );
continue;
}
* so don't assert details here.
*/
- if( ber_pvt_sb_get_desc( connections[i].c_sb ) == s ) {
+ if( sd == s ) {
c = &connections[i];
break;
}
#endif
if( c != NULL ) {
+ ber_socket_t sd;
+
ldap_pvt_thread_mutex_lock( &c->c_mutex );
+ ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
if( c->c_struct_state != SLAP_C_USED ) {
/* connection must have been closed due to resched */
assert( c->c_conn_state == SLAP_C_INVALID );
- assert( !ber_pvt_sb_in_use( c->c_sb ) );
+ assert( sd == AC_SOCKET_INVALID );
Debug( LDAP_DEBUG_TRACE,
"connection_get(%d): connection not used\n",
assert( c->c_struct_state == SLAP_C_USED );
assert( c->c_conn_state != SLAP_C_INVALID );
- assert( ber_pvt_sb_in_use( c->c_sb ) );
+ assert( sd != AC_SOCKET_INVALID );
c->c_activitytime = slap_get_time();
}
c = NULL;
for( i=0; i < dtblsize; i++) {
+ ber_socket_t sd;
+
+ ber_sockbuf_ctrl( connections[i].c_sb, LBER_SB_OPT_GET_FD, &sd );
+
if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[i].c_sb == 0 );
c = &connections[i];
}
if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
- assert( !ber_pvt_sb_in_use( connections[i].c_sb ));
+ assert( sd == AC_SOCKET_INVALID );
c = &connections[i];
break;
}
assert( connections[i].c_struct_state == SLAP_C_USED );
assert( connections[i].c_conn_state != SLAP_C_INVALID );
- assert( ber_pvt_sb_in_use( connections[i].c_sb ));
+ assert( sd != AC_SOCKET_INVALID );
}
if( c == NULL ) {
c->c_activitytime = c->c_starttime = slap_get_time();
- ber_pvt_sb_set_desc( c->c_sb, s );
- ber_pvt_sb_set_io( c->c_sb, &ber_pvt_sb_io_tcp, NULL );
-
- if( ber_pvt_sb_set_nonblock( c->c_sb, 1 ) < 0 ) {
+ ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_tcp, LBER_SBIOD_LEVEL_PROVIDER,
+ (void *)&s );
+ ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
+ LBER_SBIOD_LEVEL_PROVIDER, NULL );
+#ifdef LDAP_DEBUG
+ ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug, INT_MAX, NULL );
+#endif
+ if( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_NONBLOCK, (void *)1 ) < 0 ) {
Debug( LDAP_DEBUG_ANY,
"connection_init(%d, %s): set nonblocking failed\n",
s, c->c_peer_name,0 );
connection_destroy( Connection *c )
{
/* note: connections_mutex should be locked by caller */
+ ber_socket_t sd;
assert( connections != NULL );
assert( c != NULL );
c->c_currentber = NULL;
}
- if ( ber_pvt_sb_in_use(c->c_sb) ) {
- int sd = ber_pvt_sb_get_desc(c->c_sb);
-
+ ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
+ if ( sd != AC_SOCKET_INVALID ) {
slapd_remove( sd, 0 );
- ber_pvt_sb_close( c->c_sb );
Statslog( LDAP_DEBUG_STATS,
"conn=%ld fd=%d closed\n",
c->c_connid, sd, 0, 0, 0 );
}
- ber_pvt_sb_destroy( c->c_sb );
+ ber_sockbuf_free( c->c_sb );
+ c->c_sb = ber_sockbuf_alloc( );
c->c_conn_state = SLAP_C_INVALID;
c->c_struct_state = SLAP_C_UNUSED;
/* c_mutex must be locked by caller */
if( c->c_conn_state != SLAP_C_CLOSING ) {
+ ber_socket_t sd;
+
+ ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
Debug( LDAP_DEBUG_TRACE,
"connection_closing: readying conn=%ld sd=%d for close\n",
- c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
+ c->c_connid, sd, 0 );
/* update state to closing */
c->c_conn_state = SLAP_C_CLOSING;
/* don't listen on this port anymore */
- slapd_clr_read( ber_pvt_sb_get_desc( c->c_sb ), 1 );
+ slapd_clr_read( sd, 1 );
/* abandon active operations */
connection_abandon( c );
/* wake write blocked operations */
- slapd_clr_write( ber_pvt_sb_get_desc(c->c_sb), 1 );
+ slapd_clr_write( sd, 1 );
ldap_pvt_thread_cond_signal( &c->c_write_cv );
}
}
static void connection_close( Connection *c )
{
+ ber_socket_t sd;
+
assert( connections != NULL );
assert( c != NULL );
assert( c->c_struct_state == SLAP_C_USED );
/* note: connections_mutex and c_mutex should be locked by caller */
+ ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
if( c->c_ops != NULL ) {
Debug( LDAP_DEBUG_TRACE,
"connection_close: deferring conn=%ld sd=%d\n",
- c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
+ c->c_connid, sd, 0 );
return;
}
Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%ld sd=%d\n",
- c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
+ c->c_connid, sd, 0 );
connection_destroy( c );
}
* to propagate to client. */
FD_ZERO(&rfd);
FD_SET(s, &rfd);
- ber_pvt_sb_set_readahead(c->c_sb, 0);
for (rc=1; rc>0;)
{
- char buf[4096];
tv.tv_sec = 1;
tv.tv_usec = 0;
rc = select(s+1, &rfd, NULL, NULL, &tv);
if (rc == 1)
- rc = ber_pvt_sb_read(c->c_sb, buf, sizeof(buf));
+ ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DRAIN,
+ NULL);
}
connection_close( c );
} else if ( rc == 0 ) {
#define CONNECTION_INPUT_LOOP 1
#ifdef DATA_READY_LOOP
- while(!rc && ber_pvt_sb_data_ready(&c->c_sb))
+ while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_DATA_READY, NULL ) )
#elif CONNECTION_INPUT_LOOP
while(!rc)
#endif
connection_close( c );
}
- if ( ber_pvt_sb_needs_read( c->c_sb ) )
+ if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) )
slapd_set_read( s, 1 );
- if ( ber_pvt_sb_needs_write( c->c_sb ) )
+ if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) )
slapd_set_write( s, 1 );
connection_return( c );
ldap_pvt_thread_mutex_unlock( &connections_mutex );
!= LDAP_TAG_MESSAGE )
{
int err = errno;
+ ber_socket_t sd;
+
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
Debug( LDAP_DEBUG_TRACE,
"ber_get_next on fd %d failed errno=%d (%s)\n",
- ber_pvt_sb_get_desc( conn->c_sb ), err, sock_errstr(err) );
- Debug( LDAP_DEBUG_TRACE,
- "\t*** got %ld of %lu so far\n",
- (long) ( conn->c_currentber->ber_buf
- ? conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf
- : 0 ),
- (long) conn->c_currentber->ber_len, 0 );
+ sd, err, sock_errstr(err) );
if ( err != EWOULDBLOCK && err != EAGAIN ) {
/* log, close and send error */
Operation *op;
if( conn->c_conn_state == SLAP_C_CLOSING ) {
+ ber_socket_t sd;
+
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
Debug( LDAP_DEBUG_TRACE,
"connection_resched: attempting closing conn=%ld sd=%d\n",
- conn->c_connid, ber_pvt_sb_get_desc( conn->c_sb ), 0 );
+ conn->c_connid, sd, 0 );
connection_close( conn );
return 0;
ldap_pvt_thread_cond_signal( &c->c_write_cv );
- if ( ber_pvt_sb_needs_read( c->c_sb ) )
+ if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) )
slapd_set_read( s, 1 );
- if ( ber_pvt_sb_needs_write( c->c_sb ) )
+ if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) )
slapd_set_write( s, 1 );
connection_return( c );
ldap_pvt_thread_mutex_unlock( &connections_mutex );
#include "slap.h"
-/* we need LBER internals */
-#include "../../libraries/liblber/lber-int.h"
-
static char *v2ref( struct berval **ref, const char *text )
{
size_t len = 0, i = 0;
/* write the pdu */
while( 1 ) {
int err;
+ ber_socket_t sd;
if ( connection_state_closing( conn ) ) {
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
/* wait for socket to be write-ready */
conn->c_writewaiter = 1;
- slapd_set_write( ber_pvt_sb_get_desc( conn->c_sb ), 1 );
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
+ slapd_set_write( sd, 1 );
ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
conn->c_writewaiter = 0;
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
- ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
- ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
- ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
- ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
- ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
+ ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
+ (void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),