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