diff --git a/include/lber.h b/include/lber.h
index 5af98579ae425e03a13b66da915d69f6caffcc31..bf939f90b31a44449621c6106830f797745cb657 100644
--- a/include/lber.h
+++ b/include/lber.h
@@ -177,6 +177,7 @@ LDAP_F long ber_read LDAP_P(( BerElement *ber, char *buf, unsigned long len ));
 LDAP_F long ber_write LDAP_P(( BerElement *ber, char *buf, unsigned long len,
 	int nosos ));
 LDAP_F void ber_free LDAP_P(( BerElement *ber, int freebuf ));
+LDAP_F void ber_clear LDAP_P(( BerElement *ber, int freebuf ));
 LDAP_F int ber_flush LDAP_P(( Sockbuf *sb, BerElement *ber, int freeit ));
 LDAP_F BerElement *ber_alloc LDAP_P(( void ));
 LDAP_F BerElement *der_alloc LDAP_P(( void ));
@@ -205,9 +206,9 @@ lber_set_option LDAP_P((void *item, int option, void *invalue));
 /*
  * LBER Sockbuf functions
  */
-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_F Sockbuf *lber_pvt_sk_alloc LDAP_P((void));
+LDAP_F Sockbuf *lber_pvt_sb_alloc_fd LDAP_P((int fd));
+LDAP_F void lber_pvt_sb_free LDAP_P((Sockbuf *sb));
 
 LDAP_END_DECL
 
diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c
index dd8bc5f14f753272f05faf2a9f5dea98340526b8..7d529500d784c4eed2581d88df30f0a7b186cd8a 100644
--- a/libraries/liblber/io.c
+++ b/libraries/liblber/io.c
@@ -32,11 +32,25 @@
 
 #include "lber-int.h"
 
+#ifdef LDAP_DEBUG
+#include <assert.h>
+#else
+#define assert(cond)
+#endif
+
 static long BerRead LDAP_P(( Sockbuf *sb, char *buf, long len ));
 static int ber_realloc LDAP_P(( BerElement *ber, unsigned long len ));
 
 #define EXBUFSIZ	1024
 
+/* probably far too large... */
+#define MAX_BERBUFSIZE	(128*1024)
+
+#if defined( DOS ) && !defined( _WIN32 ) && (MAX_BERBUFSIZE > 65535)
+# undef MAX_BERBUFSIZE
+# define MAX_BERBUFSIZE 65535
+#endif
+
 static long
 BerRead( Sockbuf *sb, char *buf, long len )
 {
@@ -329,6 +343,7 @@ ber_reset( BerElement *ber, int was_writing )
 	ber->ber_rwptr = NULL;
 }
 
+#if 0
 /* return the tag - LBER_DEFAULT returned means trouble */
 static unsigned long
 get_tag( Sockbuf *sb )
@@ -363,21 +378,22 @@ get_tag( Sockbuf *sb )
 	/* want leading, not trailing 0's */
 	return( tag >> (sizeof(long) - i - 1) );
 }
+#endif
+
+/*
+ * A rewrite of get_get_next that can safely be called multiple times 
+ * for the same packet. It will simply continue were it stopped until
+ * a full packet is read.
+ */
 
 unsigned long
 ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber )
 {
-	unsigned long	tag = 0, netlen, toread;
-	unsigned char	lc;
-	long		rc;
-	long		noctets;
-	unsigned int	diff;
-
 	if ( ber->ber_debug ) {
 		lber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
 			"ber_get_next\n" );
 	}
-
+	
 	/*
 	 * Any ber element looks like this: tag length contents.
 	 * Assuming everything's ok, we return the tag byte (we
@@ -389,95 +405,140 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber )
 	 *	2) definite lengths
 	 *	3) primitive encodings used whenever possible
 	 */
+	
+	if (ber->ber_rwptr == NULL) {
+		assert( ber->ber_buf == NULL );
+		ber->ber_rwptr = (char *) &ber->ber_tag;
+		ber->ber_tag = 0;
+	}
 
-	/*
-	 * first time through - malloc the buffer, set up ptrs, and
-	 * read the tag and the length and as much of the rest as we can
-	 */
-
-	if ( ber->ber_rwptr == NULL ) {
-		/*
-		 * First, we read the tag.
-		 */
-
-		if ( (tag = get_tag( sb )) == LBER_DEFAULT ) {
-			return( LBER_DEFAULT );
-		}
-		ber->ber_tag = tag;
-
-		/*
-		 * Next, read the length.  The first byte contains the length
-		 * of the length.  If bit 8 is set, the length is the long
-		 * form, otherwise it's the short form.  We don't allow a
-		 * length that's greater than what we can hold in an unsigned
-		 * long.
-		 */
-
-		*len = netlen = 0;
-		if ( lber_pvt_sb_read( sb, (char *) &lc, 1 ) != 1 ) {
-			return( LBER_DEFAULT );
+#define PTR_IN_VAR( ptr, var )\
+(((ptr)>=(char *) &(var)) && ((ptr)< (char *) &(var)+sizeof(var)))
+	
+	if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_tag)) {
+		if (ber->ber_rwptr == (char *) &ber->ber_tag) {
+			if (lber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0)
+				return LBER_DEFAULT;
+			if ((ber->ber_rwptr[0] & LBER_BIG_TAG_MASK)
+				!= LBER_BIG_TAG_MASK) {
+				ber->ber_tag = ber->ber_rwptr[0];
+				ber->ber_rwptr = (char *) &ber->ber_usertag;
+				goto get_lenbyte;
+			}
+			ber->ber_rwptr++;
 		}
-		if ( lc & 0x80 ) {
-			noctets = (lc & 0x7f);
-			if ( noctets > sizeof(unsigned long) )
-				return( LBER_DEFAULT );
-			diff = sizeof(unsigned long) - noctets;
-			if ( BerRead( sb, (char *) &netlen + diff, noctets ) !=
-			    noctets ) {
-				return( LBER_DEFAULT );
+		do {
+			/* reading the tag... */
+			if (lber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0)
+				return LBER_DEFAULT;
+			if (! (ber->ber_rwptr[0] & LBER_MORE_TAG_MASK) ) {
+				ber->ber_tag>>=sizeof(ber->ber_tag) -
+				  ((char *) &ber->ber_tag - ber->ber_rwptr);
+				ber->ber_rwptr = (char *) &ber->ber_usertag;
+				goto get_lenbyte;
+			}
+		} while (PTR_IN_VAR(ber->ber_rwptr,ber->ber_tag));
+		errno = ERANGE; /* this is a serious error. */
+		return LBER_DEFAULT;
+	}
+get_lenbyte:
+	if (ber->ber_rwptr==(char *) &ber->ber_usertag) {
+		unsigned char c;
+		if (lber_pvt_sb_read( sb, (char *) &c, 1)<=0)
+			return LBER_DEFAULT;
+		if (c & 0x80) {
+			int len = c & 0x7f;
+			if ( (len==0) || ( len>sizeof( ber->ber_len ) ) ) {
+				errno = ERANGE;
+				return LBER_DEFAULT;
 			}
-			*len = AC_NTOHL( netlen );
+			ber->ber_rwptr = (char *) &ber->ber_len +
+				sizeof(ber->ber_len) - len;
+			ber->ber_len = 0;
 		} else {
-			*len = lc;
+			ber->ber_len = c;
+			goto fill_buffer;
 		}
-		ber->ber_len = *len;
-
-		/*
-		 * Finally, malloc a buffer for the contents and read it in.
-		 * It's this buffer that's passed to all the other ber decoding
-		 * routines.
-		 */
-
-#if defined( DOS ) && !defined( _WIN32 )
-		if ( *len > 65535 ) {	/* DOS can't allocate > 64K */
-		    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 );
+	}
+	if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_len)) {
+		int res;
+		int to_go;
+		to_go = (char *) &ber->ber_len + sizeof( ber->ber_len ) -
+			ber->ber_rwptr;
+		assert( to_go > 0 );
+		res = lber_pvt_sb_read( sb, ber->ber_rwptr, to_go );
+		if (res <=0)
+			return LBER_DEFAULT;
+		ber->ber_rwptr += res;
+		if (res==to_go) {
+			/* convert length. */
+			ber->ber_len = AC_NTOHL( ber->ber_len );
+			goto fill_buffer;
+		} else {
+#if defined( EWOULDBLOCK )
+			errno = EWOULDBLOCK;
+#elif defined( EAGAIN )
+			errno = EAGAIN;
+#endif			
+			return LBER_DEFAULT;
 		}
-#endif
-		if ( (ber->ber_buf = (char *) malloc( (size_t)*len )) == NULL ) {
-			return( LBER_DEFAULT );
+	}
+fill_buffer:	
+	/* now fill the buffer. */
+	if (ber->ber_buf==NULL) {
+		if (ber->ber_len > MAX_BERBUFSIZE) {
+			errno = ERANGE;
+			return LBER_DEFAULT;
 		}
-		ber->ber_ptr = ber->ber_buf;
-		ber->ber_end = ber->ber_buf + *len;
+		ber->ber_buf = (char *) malloc( ber->ber_len );
+		if (ber->ber_buf==NULL)
+			return LBER_DEFAULT;
 		ber->ber_rwptr = ber->ber_buf;
+		ber->ber_ptr = ber->ber_buf;
+		ber->ber_end = ber->ber_buf + ber->ber_len;
 	}
-
-	toread = (unsigned long)ber->ber_end - (unsigned long)ber->ber_rwptr;
-	do {
-		if ( (rc = lber_pvt_sb_read( sb, ber->ber_rwptr, (long)toread )) <= 0 ) {
-			return( LBER_DEFAULT );
+	if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptr<ber->ber_end)) {
+		int res;
+		int to_go;
+		
+		to_go = ber->ber_end - ber->ber_rwptr;
+		assert( to_go > 0 );
+		
+		res = lber_pvt_sb_read( sb, ber->ber_rwptr, to_go );
+		if (res<=0)
+			return LBER_DEFAULT;
+		ber->ber_rwptr+=res;
+		
+		if (res<to_go) {
+#if defined( EWOULDBLOCK )
+			errno = EWOULDBLOCK;
+#elif defined( EAGAIN )
+			errno = EAGAIN;
+#endif			
+			return LBER_DEFAULT;
 		}
-
-		toread -= rc;
-		ber->ber_rwptr += rc;
-	} while ( toread > 0 );
-
-	if ( ber->ber_debug ) {
-		lber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
-			"ber_get_next: tag 0x%lx len %ld contents:\n",
-		    tag, ber->ber_len );
-
-		lber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
+		
+		ber->ber_rwptr = NULL;
+		*len = ber->ber_len;
+		if ( ber->ber_debug ) {
+			lber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
+				"ber_get_next: tag 0x%lx len %ld contents:\n",
+				ber->ber_tag, ber->ber_len );
+			lber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
+		}
+		return (ber->ber_tag);
 	}
+	assert( 0 ); /* ber structure is messed up ?*/
+	return LBER_DEFAULT;
+}
 
-	*len = ber->ber_len;
+void	ber_clear( BerElement *ber, int freebuf )
+{
+	if ((freebuf) && (ber->ber_buf))
+		free( ber->ber_buf );
+	ber->ber_buf = NULL;
 	ber->ber_rwptr = NULL;
-	return( ber->ber_tag );
+	ber->ber_end = NULL;
 }
 
 Sockbuf *lber_pvt_sb_alloc( void )
diff --git a/libraries/liblber/sockbuf.c b/libraries/liblber/sockbuf.c
index 8902af162dfc8a3a3cb4ac253766f433d622310d..4fec6f9f8ffa00e8b90888780086eb8933ab4554 100644
--- a/libraries/liblber/sockbuf.c
+++ b/libraries/liblber/sockbuf.c
@@ -29,6 +29,8 @@
 
 #ifdef LDAP_DEBUG
 #include <assert.h>
+#undef TEST_PARTIAL_READ
+#undef TEST_PARTIAL_WRITE
 #else
 #define assert( cond )
 #endif
@@ -112,16 +114,16 @@ packet_length( char *buf )
 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) {
+   long pw=MIN_BUF_SIZE;
+   
+   for(;(pw<minsize);pw<<=1) {
+      if (pw > MAX_BUF_SIZE) {
 	 /* this could mean that somebody is trying to crash us. */
 	 return -1;
       }
    }
+   minsize = pw;
+
    if (buf->buf_size<minsize) {
       if ((buf->buf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) {
 	 /* empty buffer */
@@ -309,13 +311,23 @@ lber_pvt_sb_read( Sockbuf *sb, void *buf_arg, long len )
    /* breaks slapd :-) */
    assert( lber_pvt_sb_in_use( sb ) );
 #endif 
+
+#ifdef TEST_PARTIAL_READ
+   if ((rand() & 3)==1) { /* 1 out of 4 */
+      errno = EWOULDBLOCK;
+      return -1;
+   }
+
+   len = (rand() % len)+1;
+#endif   
    
    buf = (char *) buf_arg;
 
-   len = sockbuf_copy_out( sb, &buf, len );
-   
-   if (len==0) {
-      return (buf - (char *) buf_arg);
+   if (sb->sb_buf.buf_ptr!=sb->sb_buf.buf_end) {
+      len = sockbuf_copy_out( sb, &buf, len );
+      if (len==0) {
+	 return (buf - (char *) buf_arg);
+      }
    }
 
 #ifdef USE_SASL
@@ -336,8 +348,15 @@ lber_pvt_sb_read( Sockbuf *sb, void *buf_arg, long len )
       }
       for(;;) {
 	 /* read from stream into sb_sec_buf_in */
-	 ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base +
+	 for(;;) {
+	    ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base +
 				  sb->sb_sec_buf_in.buf_ptr, max );
+#ifdef EINTR
+	    if ((ret<0) && (errno==EINTR))
+	      continue;
+#endif
+	    break;
+	 }
 	 if (ret<=0) {
 	    /* read error. return */
 	    goto do_return;
@@ -393,10 +412,17 @@ decode_packet:
 	 long max;
 	 max = sb->sb_buf.buf_size - sb->sb_buf.buf_end;
 	 if (max>len) {
-	    ret = sockbuf_io_read( sb, 
+	    for(;;) {
+	       ret = sockbuf_io_read( sb, 
 				     sb->sb_buf.buf_base +
 				     sb->sb_buf.buf_end,
-					max );
+				     max );
+#ifdef EINTR	       
+	       if ((ret<0) && (errno==EINTR))
+		 continue;
+#endif
+	       break;
+	    }
 	    if (ret<=0) {
 	       /* some error occured */
 	       goto do_return;
@@ -408,7 +434,14 @@ decode_packet:
 	 }
       }
       /* no read_ahead, just try to put the data in the buf. */
-      ret = sockbuf_io_read( sb, buf, len );
+      for(;;) {
+	 ret = sockbuf_io_read( sb, buf, len );
+#ifdef EINTR	 
+	 if ((ret<0) && (errno==EINTR))
+	   continue;
+#endif
+	 break;
+      }
       if (ret>0) {
 	 buf+=ret;
 	 len-=ret;
@@ -433,8 +466,15 @@ long sockbuf_do_write( Sockbuf *sb )
    to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr;
    assert( to_go > 0 );
    /* there is something left of the last time... */
-   ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+
-			      sb->sb_sec_out.buf_ptr, to_go );
+   for(;;) {
+      ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+
+			     sb->sb_sec_out.buf_ptr, to_go );
+#ifdef EINTR
+      if ((ret<0) && (errno==EINTR))
+	continue;
+#endif
+      break;
+   }
    if (ret<=0) /* error */
      return ret;
    sb->sb_sec_out.buf_ptr += ret;
@@ -453,6 +493,16 @@ long lber_pvt_sb_write( Sockbuf *sb, void *buf, long len_arg )
    /* unfortunately breaks slapd */
    assert( lber_pvt_sb_in_use( sb ) );
 #endif   
+#ifdef TEST_PARTIAL_WRITE
+   if ((rand() & 3)==1) { /* 1 out of 4 */
+      errno = EWOULDBLOCK;
+      return -1;
+   }
+
+   len_arg = (rand() % len_arg)+1;
+   len = len_arg;
+#endif   
+   
 #ifdef USE_SASL
    if (sb->sb_sec) {
       assert( sb->sb_sec_prev_len <= len );
@@ -477,7 +527,14 @@ long lber_pvt_sb_write( Sockbuf *sb, void *buf, long len_arg )
       return len_arg;
    } else {
 #endif
-      return sockbuf_io_write( sb, buf, len );
+      for(;;) {
+	 ret = sockbuf_io_write( sb, buf, len );
+#ifdef EINTR
+	 if ((ret<0) && (errno==EINTR))
+	   continue;
+#endif
+	 break;
+      }
 #ifdef USE_SASL      
    }
 #endif
diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
index 474807582efa7d4d85881be5a2d04f94cba938dd..9f27a0a6a347086c52114095720f0fe6ba06170a 100644
--- a/libraries/libldap/ldap-int.h
+++ b/libraries/libldap/ldap-int.h
@@ -127,6 +127,7 @@ typedef struct ldap_conn {
 	LDAPServer		*lconn_server;
 	char			*lconn_krbinstance;
 	struct ldap_conn	*lconn_next;
+	BerElement		lconn_ber;/* ber receiving on this conn. */
 } LDAPConn;
 
 
@@ -227,8 +228,11 @@ struct ldap {
 	/* 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 */	
-	
+   	void		**ld_cldapaddrs;/* addresses to send request to */
+#ifndef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS	
+	/* BerElement that this connection is receiving. */
+	BerElement	ld_ber;
+#endif	
 	/* do not mess with the rest though */
 	BERTranslateProc ld_lber_encode_translate_proc;
 	BERTranslateProc ld_lber_decode_translate_proc;
diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c
index ab00e00986055336f92c2c21c0ba1470c7637479..5b8ecc8c5e45a0d4028f7b2f7a8288a95f348e85 100644
--- a/libraries/libldap/request.c
+++ b/libraries/libldap/request.c
@@ -21,6 +21,7 @@
 #include <ac/unistd.h>
 
 #include "ldap-int.h"
+#include "lber.h"
 
 #if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS ) || defined( LDAP_API_FEATURE_X_OPENLDAP_V2_DNS )
 static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPServer *srv, int any ));
@@ -444,6 +445,7 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
 			}
 			ldap_close_connection( lc->lconn_sb );
 		   	lber_pvt_sb_destroy( lc->lconn_sb );
+			ber_clear( &lc->lconn_ber, 1 );
 		}
 		prevlc = NULL;
 		for ( tmplc = ld->ld_conns; tmplc != NULL;
diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c
index df532f08f6fbfac30330be985e08ee627bd5039f..40729f18c5d0fc3eaa942f623624edc404a7a36f 100644
--- a/libraries/libldap/result.c
+++ b/libraries/libldap/result.c
@@ -28,12 +28,12 @@ static int ldap_mark_abandoned LDAP_P(( LDAP *ld, int msgid ));
 static int wait4msg LDAP_P(( LDAP *ld, int msgid, int all, struct timeval *timeout,
 	LDAPMessage **result ));
 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
-static int read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc,
+static int try_read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc,
 	LDAPMessage **result ));
 static unsigned long build_result_ber LDAP_P(( LDAP *ld, BerElement *ber, LDAPRequest *lr ));
 static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ));
 #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
-static int read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb,
+static int try_read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb,
 	LDAPMessage **result ));
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
 #if defined( LDAP_CONNECTIONLESS ) || !defined( LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS )
@@ -182,7 +182,7 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout,
 		if ( rc == -1 ) {
 			rc = -2;	/* select interrupted: loop */
 		} else {
-			rc = read1msg( ld, msgid, all, &ld->ld_sb, result );
+			rc = try_read1msg( ld, msgid, all, &ld->ld_sb, result );
 		}
 #else /* !LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
 #ifdef LDAP_DEBUG
@@ -193,7 +193,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 ( lber_pvt_sb_data_ready(lc->lconn_sb) ) {
-				rc = read1msg( ld, msgid, all, lc->lconn_sb,
+				rc = try_read1msg( ld, msgid, all, lc->lconn_sb,
 				    lc, result );
 				break;
 			}
@@ -232,7 +232,7 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout,
 					    LDAP_CONNST_CONNECTED &&
 					    ldap_is_read_ready( ld,
 					    lc->lconn_sb )) {
-						rc = read1msg( ld, msgid, all,
+						rc = try_read1msg( ld, msgid, all,
 						    lc->lconn_sb, lc, result );
 					}
 				}
@@ -259,13 +259,13 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout,
 
 
 static int
-read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
+try_read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
     LDAPConn *lc,
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
     LDAPMessage **result )
 {
-	BerElement	ber;
+	BerElement	*ber;
 	LDAPMessage	*new, *l, *prev, *tmp;
 	long		id;
 	unsigned long	tag, len;
@@ -275,30 +275,47 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
 	BerElement	tmpber;
 	int		rc, refer_cnt, hadref, simple_request;
 	unsigned long	lderr;
+	
+	ber = &lc->lconn_ber;
+#else
+	ber = &ld->ld_ber;
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
 
 	Debug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 );
-
+#if 0
 	ber_init_w_nullc( &ber, 0 );
 	ldap_set_ber_options( ld, &ber );
-
+#endif
 	/* get the next message */
-	if ( (tag = ber_get_next( sb, &len, &ber ))
+	if ( (tag = ber_get_next( sb, &len, ber ))
 	    != LDAP_TAG_MESSAGE ) {
-		ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
-		    LDAP_LOCAL_ERROR);
-		return( -1 );
+		if ( tag == LBER_DEFAULT) {
+#ifdef LDAP_DEBUG		   
+			Debug( LDAP_DEBUG_CONNS,
+			      "ber_get_next failed.\n", 0, 0, 0 );
+#endif		   
+#ifdef EWOULDBLOCK			
+			if (errno==EWOULDBLOCK) return -2;
+#endif
+#ifdef EAGAIN
+			if (errno == EAGAIN) return -2;
+#endif
+			ld->ld_errno = LDAP_SERVER_DOWN;
+			return -1;
+		}
+		ld->ld_errno = LDAP_LOCAL_ERROR;
+		return -1;
 	}
 
 	/* message id */
-	if ( ber_get_int( &ber, &id ) == LBER_ERROR ) {
+	if ( ber_get_int( ber, &id ) == LBER_ERROR ) {
 		ld->ld_errno = LDAP_DECODING_ERROR;
 		return( -1 );
 	}
 
 	/* if it's been abandoned, toss it */
 	if ( ldap_abandoned( ld, (int)id ) ) {
-		free( ber.ber_buf );	/* gack! */
+		ber_clear( ber, 1 );	/* gack! */
 		return( -2 );	/* continue looking */
 	}
 
@@ -307,7 +324,7 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
 		Debug( LDAP_DEBUG_ANY,
 		    "no request for response with msgid %ld (tossing)\n",
 		    id, 0, 0 );
-		free( ber.ber_buf );	/* gack! */
+		ber_clear( ber, 1 );	/* gack! */
 		return( -2 );	/* continue looking */
 	}
 	Debug( LDAP_DEBUG_TRACE, "got %s msgid %ld, original id %d\n",
@@ -317,7 +334,7 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
 
 	/* the message type */
-	if ( (tag = ber_peek_tag( &ber, &len )) == LBER_ERROR ) {
+	if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
 		ld->ld_errno = LDAP_DECODING_ERROR;
 		return( -1 );
 	}
@@ -334,7 +351,7 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
 			( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS)
 				!= LDAP_OPT_OFF ) ) )
 		{
-			tmpber = ber;	/* struct copy */
+			tmpber = *ber;	/* struct copy */
 			if ( ber_scanf( &tmpber, "{iaa}", &lderr,
 			    &lr->lr_res_matched, &lr->lr_res_error )
 			    != LBER_ERROR ) {
@@ -365,8 +382,7 @@ Debug( LDAP_DEBUG_TRACE,
 		    "read1msg:  %d new referrals\n", refer_cnt, 0, 0 );
 
 		if ( refer_cnt != 0 ) {	/* chasing referrals */
-			free( ber.ber_buf );	/* gack! */
-			ber.ber_buf = NULL;
+			ber_clear( ber, 1 );	/* gack! */
 			if ( refer_cnt < 0 ) {
 				return( -1 );	/* fatal error */
 			}
@@ -377,8 +393,7 @@ Debug( LDAP_DEBUG_TRACE,
 				simple_request = ( hadref ? 0 : 1 );
 			} else {
 				/* request with referrals or child request */
-				free( ber.ber_buf );	/* gack! */
-				ber.ber_buf = NULL;
+				ber_clear( ber, 1 );	/* gack! */
 			}
 
 			while ( lr->lr_parent != NULL ) {
@@ -400,11 +415,8 @@ Debug( LDAP_DEBUG_TRACE,
 lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "",
 lr->lr_res_matched ? lr->lr_res_matched : "" );
 				if ( !simple_request ) {
-					if ( ber.ber_buf != NULL ) {
-						free( ber.ber_buf ); /* gack! */
-						ber.ber_buf = NULL;
-					}
-					if ( build_result_ber( ld, &ber, lr )
+					ber_clear( ber, 1 ); /* gack! */
+					if ( build_result_ber( ld, ber, lr )
 					    == LBER_ERROR ) {
 						ld->ld_errno = LDAP_NO_MEMORY;
 						rc = -1; /* fatal error */
@@ -420,7 +432,7 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
 		}
 	}
 
-	if ( ber.ber_buf == NULL ) {
+	if ( ber->ber_buf == NULL ) {
 		return( rc );
 	}
 
@@ -433,7 +445,8 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
 	}
 	new->lm_msgid = (int)id;
 	new->lm_msgtype = tag;
-	new->lm_ber = ber_dup( &ber );
+	new->lm_ber = ber_dup( ber );
+	ber_clear( ber, 0 ); /* don't kill buffer */
 
 #ifndef LDAP_NOCACHE
 		if ( ld->ld_cache != NULL ) {
diff --git a/libraries/libldap/unbind.c b/libraries/libldap/unbind.c
index a1c91e5e7122ef4fe4779b08a46f27e7675c0dbd..7f17a1bb7363c24306d15a0f2caf251fcd59f363 100644
--- a/libraries/libldap/unbind.c
+++ b/libraries/libldap/unbind.c
@@ -91,6 +91,8 @@ ldap_ld_free( LDAP *ld, int close )
 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
 	if ( ld->ld_selectinfo != NULL )
 		ldap_free_select_info( ld->ld_selectinfo );
+#else
+	ber_clear( &(ld->ld_ber), 1 );
 #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
 
 	if ( ld->ld_options.ldo_defbase != NULL )