X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblber%2Fsockbuf.c;h=0d1c513b9bcda930aba4fe0c059e59384c3e1249;hb=cba0d05a9dfd3cad69380e3ee2b492ddd7c7ca84;hp=3899206fc5a269527128edf2986e160baac709fc;hpb=a50f391bb37b059733404b7ec380a883162b23fb;p=openldap
diff --git a/libraries/liblber/sockbuf.c b/libraries/liblber/sockbuf.c
index 3899206fc5..0d1c513b9b 100644
--- a/libraries/liblber/sockbuf.c
+++ b/libraries/liblber/sockbuf.c
@@ -1,8 +1,17 @@
/* sockbuf.c - i/o routines with support for adding i/o layers. */
/* $OpenLDAP$ */
-/*
- * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software .
+ *
+ * Copyright 1998-2011 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * .
*/
#include "portable.h"
@@ -21,6 +30,10 @@
#include
#endif /* HAVE_IO_H */
+#if defined( HAVE_FCNTL_H )
+#include
+#endif
+
#if defined( HAVE_SYS_FILIO_H )
#include
#elif defined( HAVE_SYS_IOCTL_H )
@@ -29,21 +42,24 @@
#include "lber-int.h"
-#define MIN_BUFF_SIZE 4096
-#define MAX_BUFF_SIZE 65536
-#define DEFAULT_READAHEAD 16384
+#ifndef LBER_MIN_BUFF_SIZE
+#define LBER_MIN_BUFF_SIZE 4096
+#endif
+#ifndef LBER_MAX_BUFF_SIZE
+#define LBER_MAX_BUFF_SIZE (65536*256)
+#endif
+#ifndef LBER_DEFAULT_READAHEAD
+#define LBER_DEFAULT_READAHEAD 16384
+#endif
Sockbuf *
ber_sockbuf_alloc( void )
{
Sockbuf *sb;
- ber_int_options.lbo_valid = LBER_INITIALIZED;
-
sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
- if( sb == NULL )
- return NULL;
+ if( sb == NULL ) return NULL;
ber_int_sb_init( sb );
return sb;
@@ -68,52 +84,88 @@ ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
{
Sockbuf_IO_Desc *p;
int ret = 0;
- char buf[4096];
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
switch ( opt ) {
case LBER_SB_OPT_HAS_IO:
p = sb->sb_iod;
-
- while ( p && p->sbiod_io != (Sockbuf_IO *)arg )
+ while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
p = p->sbiod_next;
+ }
- if ( p )
+ if ( p ) {
ret = 1;
+ }
break;
+
case LBER_SB_OPT_GET_FD:
- if ( arg != NULL )
- *((int *)arg) = sb->sb_fd;
+ if ( arg != NULL ) {
+ *((ber_socket_t *)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);
+ sb->sb_fd = *((ber_socket_t *)arg);
ret = 1;
break;
+
case LBER_SB_OPT_SET_NONBLOCK:
ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
? -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_DRAIN: {
+ /* Drain the data source to enable possible errors (e.g.
+ * TLS) to be propagated to the upper layers
+ */
+ char buf[LBER_MIN_BUFF_SIZE];
+
+ 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;
+
+ case LBER_SB_OPT_GET_MAX_INCOMING:
+ if ( arg != NULL ) {
+ *((ber_len_t *)arg) = sb->sb_max_incoming;
+ }
+ ret = 1;
+ break;
+
+ case LBER_SB_OPT_SET_MAX_INCOMING:
+ sb->sb_max_incoming = *((ber_len_t *)arg);
+ ret = 1;
+ break;
+
+ case LBER_SB_OPT_UNGET_BUF:
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
+ if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
+ AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
+ sb->sb_ungetlen );
+ ret = 1;
+ } else {
+ sb->sb_ungetlen = 0;
+ ret = -1;
+ }
+#endif
+ break;
+
default:
- ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
- opt, arg );
+ ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
break;
}
@@ -128,8 +180,9 @@ ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
assert( sb != NULL );
assert( SOCKBUF_VALID( sb ) );
- if ( sbio == NULL )
+ if ( sbio == NULL ) {
return -1;
+ }
q = &sb->sb_iod;
p = *q;
@@ -139,8 +192,9 @@ ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
}
d = LBER_MALLOC( sizeof( *d ) );
- if ( d == NULL )
+ if ( d == NULL ) {
return -1;
+ }
d->sbiod_level = layer;
d->sbiod_sb = sb;
@@ -148,37 +202,41 @@ ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
d->sbiod_next = p;
*q = d;
-
- if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) )
+
+ if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
return -1;
-
+ }
+
return 0;
- }
+}
int
ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
{
Sockbuf_IO_Desc *p, **q;
- assert( sb != NULL );
+ assert( sb != NULL );
assert( SOCKBUF_VALID( sb ) );
- if ( sb->sb_iod == NULL )
+ 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 )
+ p->sbiod_io->sbi_remove( p ) < 0 )
+ {
return -1;
+ }
*q = p->sbiod_next;
LBER_FREE( p );
- break;
- }
+ break;
+ }
q = &p->sbiod_next;
-}
+ }
return 0;
}
@@ -197,8 +255,9 @@ ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
{
assert( buf != NULL);
- if (buf->buf_base)
+ if (buf->buf_base) {
LBER_FREE( buf->buf_base );
+ }
ber_pvt_sb_buf_init( buf );
}
@@ -210,18 +269,16 @@ ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
assert( buf != NULL );
- for ( pw = MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
- if (pw > MAX_BUFF_SIZE)
- return -1;
- }
+ for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
+ if (pw > LBER_MAX_BUFF_SIZE) return -1;
+ }
if ( buf->buf_size < pw ) {
p = LBER_REALLOC( buf->buf_base, pw );
- if ( p == NULL )
- return -1;
+ if ( p == NULL ) return -1;
buf->buf_base = p;
buf->buf_size = pw;
- }
+ }
return 0;
}
@@ -239,10 +296,11 @@ ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
max = sbb->buf_end - sbb->buf_ptr;
max = ( max < len) ? max : len;
if ( max ) {
- memcpy( buf, sbb->buf_base + sbb->buf_ptr, max );
+ AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
sbb->buf_ptr += max;
- if ( sbb->buf_ptr >= sbb->buf_end )
+ if ( sbb->buf_ptr >= sbb->buf_end ) {
sbb->buf_ptr = sbb->buf_end = 0;
+ }
}
return max;
}
@@ -251,7 +309,7 @@ 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_slen_t ret;
assert( sbiod != NULL );
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
@@ -259,37 +317,35 @@ ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
to_go = buf_out->buf_end - buf_out->buf_ptr;
assert( to_go > 0 );
- for(;;) {
+ for(;;) {
ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
buf_out->buf_ptr, to_go );
#ifdef EINTR
- if ((ret<0) && (errno==EINTR))
- continue;
+ if ((ret<0) && (errno==EINTR)) continue;
#endif
- break;
- }
+ break;
+ }
- if ( ret <= 0 )
- return ret;
+ if ( ret <= 0 ) return ret;
buf_out->buf_ptr += ret;
- if (buf_out->buf_ptr == buf_out->buf_end)
+ if (buf_out->buf_ptr == buf_out->buf_end) {
buf_out->buf_end = buf_out->buf_ptr = 0;
- if ( (ber_len_t)ret < to_go )
- /* not enough data, so pretend no data was sent. */
- return -1;
- return ret;
+ }
+
+ return ret;
}
int
ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
{
-#if HAVE_FCNTL
+#ifdef HAVE_FCNTL
int flags = fcntl( sd, F_GETFL);
- if( nb )
+ if( nb ) {
flags |= O_NONBLOCK;
- else
+ } else {
flags &= ~O_NONBLOCK;
+ }
return fcntl( sd, F_SETFL, flags );
#elif defined( FIONBIO )
@@ -303,16 +359,16 @@ ber_int_sb_init( Sockbuf *sb )
{
assert( sb != NULL);
- sb->sb_valid=LBER_VALID_SOCKBUF;
- sb->sb_options = 0;
+ sb->sb_valid=LBER_VALID_SOCKBUF;
+ sb->sb_options = 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_trans_needs_read = 0;
+ sb->sb_trans_needs_write = 0;
- assert( SOCKBUF_VALID( sb ) );
- return 0;
+ assert( SOCKBUF_VALID( sb ) );
+ return 0;
}
int
@@ -324,15 +380,15 @@ ber_int_sb_close( Sockbuf *sb )
p = sb->sb_iod;
while ( p ) {
- if ( p->sbiod_io->sbi_close &&
- p->sbiod_io->sbi_close( p ) < 0 )
- return -1;
+ if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) {
+ return -1;
+ }
p = p->sbiod_next;
- }
+ }
sb->sb_fd = AC_SOCKET_INVALID;
- return 0;
+ return 0;
}
int
@@ -348,7 +404,8 @@ ber_int_sb_destroy( Sockbuf *sb )
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 );
}
@@ -364,12 +421,13 @@ ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
for (;;) {
ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
+
#ifdef EINTR
- if ( ( ret < 0 ) && ( errno == EINTR ) )
- continue;
+ if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
#endif
break;
-}
+ }
+
return ret;
}
@@ -385,12 +443,13 @@ ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
for (;;) {
ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
+
#ifdef EINTR
- if ( ( ret < 0 ) && ( errno == EINTR ) )
- continue;
+ if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
#endif
break;
-}
+ }
+
return ret;
}
@@ -409,7 +468,7 @@ sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
* MacTCP/OpenTransport
*/
return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
- len, NULL );
+ len, NULL );
#elif defined( HAVE_PCNFS ) || \
defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
@@ -422,23 +481,8 @@ sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
/*
* 32-bit Windows Socket API (under Windows NT or Windows 95)
*/
- {
- int rc;
-
- rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
-
-#ifdef HAVE_WINSOCK
- if ( rc < 0 )
- {
- int err;
-
- err = WSAGetLastError();
- errno = err;
- }
-#endif
+ return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
- return rc;
- }
#elif defined( HAVE_NCSA )
/*
* NCSA Telnet TCP/IP stack (under DOS)
@@ -462,10 +506,10 @@ sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
*/
#define MAX_WRITE 65535
return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
- (lensbiod_sb->sb_fd, buf, len, 0 );
-#ifdef HAVE_WINSOCK
- if ( rc < 0 )
- {
- int err;
-
- err = WSAGetLastError();
- errno = err;
- }
-#endif
- return rc;
- }
+ return send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
#elif defined(HAVE_NCSA)
return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
@@ -501,7 +530,7 @@ sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
*/
#define MAX_WRITE 65535
return write( sbiod->sbiod_sb->sb_fd, buf,
- (lensbiod_sb->sb_fd, buf, len );
#endif
@@ -512,7 +541,8 @@ sb_stream_close( Sockbuf_IO_Desc *sbiod )
{
assert( sbiod != NULL );
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- tcp_close( sbiod->sbiod_sb->sb_fd );
+ if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
+ tcp_close( sbiod->sbiod_sb->sb_fd );
return 0;
}
@@ -521,8 +551,9 @@ static int
sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
assert( sbiod != NULL );
- if ( arg != NULL )
+ if ( arg != NULL ) {
sbiod->sbiod_sb->sb_fd = *((int *)arg);
+ }
return 0;
}
@@ -532,152 +563,15 @@ sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
return 0;
}
-Sockbuf_IO ber_sockbuf_io_tcp =
-{
+Sockbuf_IO ber_sockbuf_io_tcp = {
sb_stream_setup, /* sbi_setup */
- NULL, /* sbi_remove */
+ NULL, /* sbi_remove */
sb_stream_ctrl, /* sbi_ctrl */
sb_stream_read, /* sbi_read */
sb_stream_write, /* sbi_write */
sb_stream_close /* sbi_close */
};
-/*
- * Support for UDP (CLDAP)
- */
-
-struct dgram_data
-{
- struct sockaddr dst;
- struct sockaddr src;
-};
-
-static int
-sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
-{
- struct dgram_data *p;
-
- assert( sbiod != NULL);
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-
- p = LBER_MALLOC( sizeof( *p ) );
- if ( p == NULL )
- return -1;
- memset( p, '\0', sizeof( *p ) );
- sbiod->sbiod_pvt = (void *)p;
- if ( arg != NULL )
- sbiod->sbiod_sb->sb_fd = *((int *)arg);
- return 0;
-}
-
-static int
-sb_dgram_release( Sockbuf_IO_Desc *sbiod )
-{
- assert( sbiod != NULL);
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-
- LBER_FREE( sbiod->sbiod_pvt );
- sbiod->sbiod_pvt = NULL;
- return 0;
-}
-
-static ber_slen_t
-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 *p;
-
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- assert( buf != NULL );
-
- p = (struct dgram_data *)sbiod->sbiod_pvt;
-
- addrlen = sizeof( struct sockaddr );
- rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->src,
- &addrlen );
-
- return rc;
-# else /* LDAP_CONNECTIONLESS */
- return -1;
-# endif /* LDAP_CONNECTIONLESS */
-}
-
-static ber_slen_t
-sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
-{
-#ifdef LDAP_CONNECTIONLESS
- ber_slen_t rc;
- struct dgram_data *p;
-
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- assert( buf != NULL );
-
- p = (struct dgram_data *)sbiod->sbiod_pvt;
-
- rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->dst,
- sizeof( struct sockaddr ) );
-
- 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
-sb_dgram_close( Sockbuf_IO_Desc *sbiod )
-{
- assert( sbiod != NULL );
- assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-
- tcp_close( sbiod->sbiod_sb->sb_fd );
- return 0;
-}
-
-static int
-sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
-{
- 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 */
-};
/*
* Support for readahead (UDP needs it)
@@ -691,15 +585,18 @@ sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
assert( sbiod != NULL );
p = LBER_MALLOC( sizeof( *p ) );
- if ( p == NULL )
- return -1;
+ if ( p == NULL ) return -1;
+
ber_pvt_sb_buf_init( p );
- if ( arg == NULL )
- ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
- else
+
+ if ( arg == NULL ) {
+ ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD );
+ } else {
ber_pvt_sb_grow_buffer( p, *((int *)arg) );
+ }
+
sbiod->sbiod_pvt = p;
- return 0;
+ return 0;
}
static int
@@ -711,8 +608,7 @@ sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
- if ( p->buf_ptr != p->buf_end )
- return -1;
+ if ( p->buf_ptr != p->buf_end ) return -1;
ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
LBER_FREE( sbiod->sbiod_pvt );
@@ -740,8 +636,7 @@ sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
bufptr += ret;
len -= ret;
- if ( len == 0 )
- return bufptr;
+ if ( len == 0 ) return bufptr;
max = p->buf_size - p->buf_end;
ret = 0;
@@ -749,14 +644,14 @@ sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
max );
#ifdef EINTR
- if ( ( ret < 0 ) && ( errno == EINTR ) )
- continue;
+ if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
#endif
break;
-}
+ }
- if ( ret < 0 )
+ if ( ret < 0 ) {
return ( bufptr ? bufptr : ret );
+ }
p->buf_end += ret;
bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
@@ -790,12 +685,14 @@ sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
if ( opt == LBER_SB_OPT_DATA_READY ) {
- if ( p->buf_ptr != p->buf_end )
+ 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) )
+ }
+
+ } 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 );
}
@@ -803,8 +700,7 @@ sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
}
-Sockbuf_IO ber_sockbuf_io_readahead =
-{
+Sockbuf_IO ber_sockbuf_io_readahead = {
sb_rdahead_setup, /* sbi_setup */
sb_rdahead_remove, /* sbi_remove */
sb_rdahead_ctrl, /* sbi_ctrl */
@@ -823,6 +719,24 @@ sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
assert( sbiod != NULL);
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+#ifdef LDAP_PF_LOCAL_SENDMSG
+ if ( sbiod->sbiod_sb->sb_ungetlen ) {
+ ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
+ if ( blen > len )
+ blen = len;
+ AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
+ buf = (char *) buf + blen;
+ len -= blen;
+ sbiod->sbiod_sb->sb_ungetlen -= blen;
+ if ( sbiod->sbiod_sb->sb_ungetlen ) {
+ AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
+ sbiod->sbiod_sb->sb_ungetbuf+blen,
+ sbiod->sbiod_sb->sb_ungetlen );
+ }
+ if ( len == 0 )
+ return blen;
+ }
+#endif
return read( sbiod->sbiod_sb->sb_fd, buf, len );
}
@@ -841,7 +755,8 @@ sb_fd_close( Sockbuf_IO_Desc *sbiod )
assert( sbiod != NULL );
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
- close( sbiod->sbiod_sb->sb_fd );
+ if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
+ close( sbiod->sbiod_sb->sb_fd );
return 0;
}
@@ -861,9 +776,8 @@ sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
return 0;
}
-Sockbuf_IO ber_sockbuf_io_fd =
-{
- sb_fd_setup, /* sbi_setup */
+Sockbuf_IO ber_sockbuf_io_fd = {
+ sb_fd_setup, /* sbi_setup */
NULL, /* sbi_remove */
sb_fd_ctrl, /* sbi_ctrl */
sb_fd_read, /* sbi_read */
@@ -880,12 +794,11 @@ sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
{
assert( sbiod != NULL );
- if ( arg == NULL )
- arg = "sockbuf_";
+ if ( arg == NULL ) arg = "sockbuf_";
sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
- if ( sbiod->sbiod_pvt == NULL )
- return -1;
+ if ( sbiod->sbiod_pvt == NULL ) return -1;
+
strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
return 0;
}
@@ -911,19 +824,23 @@ static ber_slen_t
sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
ber_slen_t ret;
+ char ebuf[128];
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 );
+ if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
+ int err = sock_errno();
+ 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, AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
+ } 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 );
+ }
+ sock_errset(err);
}
return ret;
}
@@ -932,31 +849,136 @@ static ber_slen_t
sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
{
ber_slen_t ret;
+ char ebuf[128];
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 );
+ if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
+ int err = sock_errno();
+ 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,
+ AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
+ } 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 );
+ }
+ sock_errset(err);
}
+
return ret;
}
-Sockbuf_IO ber_sockbuf_io_debug =
-{
+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 */
+ NULL /* sbi_close */
+};
+
+#ifdef LDAP_CONNECTIONLESS
+
+/*
+ * Support for UDP (CLDAP)
+ *
+ * All I/O at this level must be atomic. For ease of use, the sb_readahead
+ * must be used above this module. All data reads and writes are prefixed
+ * with a sockaddr containing the address of the remote entity. Upper levels
+ * must read and write this sockaddr before doing the usual ber_printf/scanf
+ * operations on LDAP messages.
+ */
+
+static int
+sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
+{
+ assert( sbiod != NULL);
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg);
+ return 0;
+}
+
+static ber_slen_t
+sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
+{
+ ber_slen_t rc;
+ ber_socklen_t addrlen;
+ struct sockaddr *src;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+ assert( buf != NULL );
+
+ addrlen = sizeof( struct sockaddr );
+ src = buf;
+ buf = (char *) buf + addrlen;
+ len -= addrlen;
+ rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
+
+ return rc > 0 ? rc+sizeof(struct sockaddr) : rc;
+}
+
+static ber_slen_t
+sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
+{
+ ber_slen_t rc;
+ struct sockaddr *dst;
+
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+ assert( buf != NULL );
+
+ dst = buf;
+ buf = (char *) buf + sizeof( struct sockaddr );
+ len -= sizeof( struct sockaddr );
+
+ rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
+ sizeof( struct sockaddr ) );
+
+ if ( rc < 0 ) return -1;
+
+ /* fake error if write was not atomic */
+ if (rc < len) {
+# ifdef EMSGSIZE
+ errno = EMSGSIZE;
+# endif
+ return -1;
+ }
+ rc = len + sizeof(struct sockaddr);
+ return rc;
+}
+
+static int
+sb_dgram_close( Sockbuf_IO_Desc *sbiod )
+{
+ assert( sbiod != NULL );
+ assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
+
+ if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
+ tcp_close( sbiod->sbiod_sb->sb_fd );
+ return 0;
+}
+
+static int
+sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
+{
+ /* This is an end IO descriptor */
+ return 0;
+}
+
+Sockbuf_IO ber_sockbuf_io_udp =
+{
+ sb_dgram_setup, /* sbi_setup */
+ NULL, /* sbi_remove */
+ sb_dgram_ctrl, /* sbi_ctrl */
+ sb_dgram_read, /* sbi_read */
+ sb_dgram_write, /* sbi_write */
+ sb_dgram_close /* sbi_close */
};
+#endif /* LDAP_CONNECTIONLESS */