diff --git a/doc/man/man3/lber-encode.3 b/doc/man/man3/lber-encode.3
index 4c917b0a9833c898ca2276e9fde70df9d753f650..ad43d0d0d49d3f32ea25791770378746ab451d06 100644
--- a/doc/man/man3/lber-encode.3
+++ b/doc/man/man3/lber-encode.3
@@ -3,7 +3,7 @@
 .\" Copyright 1998-2006 The OpenLDAP Foundation All Rights Reserved.
 .\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ber_alloc_t, ber_flush, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- LBER simplified Basic Encoding Rules library routines for encoding
+ber_alloc_t, ber_flush, ber_flush2, ber_printf, ber_put_int, ber_put_enum, ber_put_ostring, ber_put_string, ber_put_null, ber_put_boolean, ber_put_bitstring, ber_start_seq, ber_start_set, ber_put_seq, ber_put_set \- LBER simplified Basic Encoding Rules library routines for encoding
 .SH LIBRARY
 OpenLDAP LBER (liblber, -llber)
 .SH SYNOPSIS
@@ -13,6 +13,8 @@ OpenLDAP LBER (liblber, -llber)
 .LP
 .BI "int ber_flush(Sockbuf *" sb ", BerElement *" ber ", int " freeit ");"
 .LP
+.BI "int ber_flush2(Sockbuf *" sb ", BerElement *" ber ", int " freeit ");"
+.LP
 .BI "int ber_printf(BerElement *" ber ", const char *" fmt ", ...);"
 .LP
 .BI "int ber_put_int(BerElement *" ber ", ber_int_t " num ", ber_tag_t " tag ");"
@@ -56,7 +58,7 @@ are
 to allocate a BER element for encoding,
 .BR ber_printf ()
 to do the actual encoding, and
-.BR ber_flush ()
+.BR ber_flush2 ()
 to actually write the element.  The other routines are provided for those
 applications that need more control than
 .BR ber_printf ()
@@ -70,7 +72,7 @@ routine is used to allocate a new BER element.  It
 should be called with an argument of LBER_USE_DER.
 .LP
 The
-.BR ber_flush ()
+.BR ber_flush2 ()
 routine is used to actually write the element to a socket
 (or file) descriptor, once it has been fully encoded (using
 .BR ber_printf ()
@@ -78,7 +80,21 @@ and friends).  See
 .BR lber-sockbuf (3)
 for more details on the Sockbuf implementation of the \fIsb\fP parameter.
 If the \fIfreeit\fP parameter is non-zero, the supplied \fIber\fP will
-be freed after its contents have been flushed.
+be freed.
+If \fILBER_FLUSH_FREE_ON_SUCCESS\fP is used, the \fIber\fP is only freed
+when successfully flushed, otherwise it is left intact;
+if \fILBER_FLUSH_FREE_ON_ERROR\fP is used, the \fIber\fP is only freed
+when an error occurs, otherwise it is left intact;
+if \fILBER_FLUSH_FREE_ALWAYS\fP is used, the \fIber\fP is freed anyway.
+This function differs from the original
+.BR ber_flush (3)
+function, whose behavior corresponds to that indicated
+for \fILBER_FLUSH_FREE_ON_SUCCESS\fP.
+Note that in the future, the behavior of
+.BR ber_flush (3)
+with \fIfreeit\fP non-zero might change into that of
+.BR ber_flush2 (3)
+with \fIfreeit\fP set to \fILBER_FLUSH_FREE_ALWAYS\fP.
 .LP
 The
 .BR ber_printf ()
diff --git a/include/lber.h b/include/lber.h
index 3017d56181602970f5b11488d56c9e5f2276fdb1..522ff4c88703763b638fcdb83dd5e5eb3181d75b 100644
--- a/include/lber.h
+++ b/include/lber.h
@@ -423,10 +423,20 @@ LBER_F( void )
 ber_free_buf LDAP_P(( BerElement *ber ));
 
 LBER_F( int )
-ber_flush LDAP_P((
+ber_flush2 LDAP_P((
 	Sockbuf *sb,
 	BerElement *ber,
 	int freeit ));
+#define LBER_FLUSH_FREE_NEVER		(0x0)	/* traditional behavior */
+#define LBER_FLUSH_FREE_ON_SUCCESS	(0x1)	/* traditional behavior */
+#define LBER_FLUSH_FREE_ON_ERROR	(0x2)
+#define LBER_FLUSH_FREE_ALWAYS		(LBER_FLUSH_FREE_ON_SUCCESS|LBER_FLUSH_FREE_ON_ERROR)
+
+LBER_F( int )
+ber_flush LDAP_P((
+	Sockbuf *sb,
+	BerElement *ber,
+	int freeit )); /* DEPRECATED */
 
 LBER_F( BerElement * )
 ber_alloc LDAP_P(( void )); /* DEPRECATED */
diff --git a/libraries/liblber/etest.c b/libraries/liblber/etest.c
index 65735575525bd728ea478d0be48bd6cf611251a9..c6befe12d2a2356590d9d0d6da64e5c2f3b4f42f 100644
--- a/libraries/liblber/etest.c
+++ b/libraries/liblber/etest.c
@@ -171,8 +171,8 @@ main( int argc, char **argv )
 		return( EXIT_FAILURE );
 	}
 
-	if ( ber_flush( sb, ber, 1 ) == -1 ) {
-		perror( "ber_flush" );
+	if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) {
+		perror( "ber_flush2" );
 		return( EXIT_FAILURE );
 	}
 
diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c
index 1c162ecebcbe6053f4ac51ac573c6a0ebaad621d..befc02d9bcf28d761052e534539c136b0388b6ee 100644
--- a/libraries/liblber/io.c
+++ b/libraries/liblber/io.c
@@ -200,10 +200,17 @@ ber_free( BerElement *ber, int freebuf )
 
 int
 ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
+{
+	return ber_flush2( sb, ber,
+		freeit ? LBER_FLUSH_FREE_ON_SUCCESS
+			: LBER_FLUSH_FREE_NEVER );
+}
+
+int
+ber_flush2( Sockbuf *sb, BerElement *ber, int freeit )
 {
 	ber_len_t	towrite;
 	ber_slen_t	rc;
-	int		retcode = 0;
 
 	assert( sb != NULL );
 	assert( ber != NULL );
@@ -218,7 +225,7 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
 
 	if ( sb->sb_debug ) {
 		ber_log_printf( LDAP_DEBUG_TRACE, sb->sb_debug,
-			"ber_flush: %ld bytes to sd %ld%s\n",
+			"ber_flush2: %ld bytes to sd %ld%s\n",
 			towrite, (long) sb->sb_fd,
 			ber->ber_rwptr != ber->ber_buf ?  " (re-flush)" : "" );
 		ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
@@ -233,17 +240,17 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
 		rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite );
 #endif
 		if ( rc <= 0 ) {
-			retcode = -1;
-			goto done;
+			if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
+			return -1;
 		}
 		towrite -= rc;
 		ber->ber_rwptr += rc;
 	} 
 
 done:;
-	if ( freeit ) ber_free( ber, 1 );
+	if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 );
 
-	return retcode;
+	return 0;
 }
 
 BerElement *
diff --git a/libraries/libldap/abandon.c b/libraries/libldap/abandon.c
index a69aa4dc20b4dae6bf58a92f11f5a49bb5e1eba6..bc9aae03e03cfe691acb8b7ef5306ac723f7e7da 100644
--- a/libraries/libldap/abandon.c
+++ b/libraries/libldap/abandon.c
@@ -244,7 +244,7 @@ do_abandon(
 					sb = ld->ld_sb;
 				}
 
-				if ( ber_flush( sb, ber, 1 ) != 0 ) {
+				if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) {
 					ld->ld_errno = LDAP_SERVER_DOWN;
 					err = -1;
 				} else {
diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c
index 921d8aa760d64b3acb86241c4ca3c7ab486bb5ba..c4a5514a1bc8ce08fd78a64e25aab185fdd32d90 100644
--- a/libraries/libldap/request.c
+++ b/libraries/libldap/request.c
@@ -142,7 +142,7 @@ ldap_int_flush_request(
 {
 	LDAPConn *lc = lr->lr_conn;
 
-	if ( ber_flush( lc->lconn_sb, lr->lr_ber, 0 ) != 0 ) {
+	if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) {
 		if ( errno == EAGAIN ) {
 			/* need to continue write later */
 			lr->lr_status = LDAP_REQST_WRITING;
diff --git a/libraries/libldap/unbind.c b/libraries/libldap/unbind.c
index 38a8e67a8af1cb41eb1a8207d9e173bcdf4c3704..da4163354592dd74a5016b8b57f6dde9a2350b3d 100644
--- a/libraries/libldap/unbind.c
+++ b/libraries/libldap/unbind.c
@@ -261,7 +261,7 @@ ldap_send_unbind(
 
 	ld->ld_errno = LDAP_SUCCESS;
 	/* send the message */
-	if ( ber_flush( sb, ber, 1 ) == -1 ) {
+	if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) {
 		ld->ld_errno = LDAP_SERVER_DOWN;
 	}
 
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index aefe3fac538cf73809cb12ac4cbd5444d440396a..e412c6169eecf7a9f70113ac3bb33232c846c056 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -167,7 +167,7 @@ static long send_ldap_ber(
 			return 0;
 		}
 
-		if ( ber_flush( conn->c_sb, ber, 0 ) == 0 ) {
+		if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) {
 			break;
 		}
 
@@ -179,7 +179,7 @@ static long send_ldap_ber(
 		 * it's a hard error and return.
 		 */
 
-		Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno=%d reason=\"%s\"\n",
+		Debug( LDAP_DEBUG_CONNS, "ber_flush2 failed errno=%d reason=\"%s\"\n",
 		    err, sock_errstr(err), 0 );
 
 		if ( err != EWOULDBLOCK && err != EAGAIN ) {