diff --git a/include/ldap.h b/include/ldap.h
index 1950c40ad6bffb45ff348fe5f33de875ec65da63..85b968a75ec3fd3685974d3a8c45fb3edaa54767 100644
--- a/include/ldap.h
+++ b/include/ldap.h
@@ -141,16 +141,16 @@ typedef struct ldapcontrol {
 	char			ldctl_iscritical;
 } LDAPControl;
 
-/* LDAP "Standard" Controls */
-
+/* LDAP Controls */
 	/* chase referrals controls */
 #define LDAP_CONTROL_REFERRALS	"1.2.840.113666.1.4.616"
 #define LDAP_CHASE_SUBORDINATE_REFERRALS	0x0020
 #define LDAP_CHASE_EXTERNAL_REFERRALS	0x0040
 
-/* LDAP "Extension" Controls */
+/* LDAP Unsolicited Notifications */
+#define	LDAP_NOTICE_DISCONNECT	"1.3.6.1.4.1.1466.20036"
 
-/* LDAP "Private/Experiemental" Controls */
+/* LDAP Extended Operations */
 
 
 /* 
@@ -289,6 +289,8 @@ typedef struct ldapmod {
  * possible error codes we can return
  */
 
+#define LDAP_RANGE(n,x,y)	(((x) >= (n)) && ((n) <= (y)))
+
 #define LDAP_SUCCESS			0x00
 #define LDAP_OPERATIONS_ERROR		0x01
 #define LDAP_PROTOCOL_ERROR		0x02
@@ -307,6 +309,8 @@ typedef struct ldapmod {
 #define LDAP_CONFIDENTIALITY_REQUIRED	0x0d /* LDAPv3 */
 #define	LDAP_SASL_BIND_IN_PROGRESS	0x0e /* LDAPv3 */	
 
+#define LDAP_ATTR_ERROR(n)	LDAP_RANGE((n),0x10,0x15) /* 16-21 */
+
 #define LDAP_NO_SUCH_ATTRIBUTE		0x10
 #define LDAP_UNDEFINED_TYPE		0x11
 #define LDAP_INAPPROPRIATE_MATCHING	0x12
@@ -314,22 +318,29 @@ typedef struct ldapmod {
 #define LDAP_TYPE_OR_VALUE_EXISTS	0x14
 #define LDAP_INVALID_SYNTAX		0x15
 
+#define LDAP_NAME_ERROR(n)	LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */
+
 #define LDAP_NO_SUCH_OBJECT		0x20
 #define LDAP_ALIAS_PROBLEM		0x21
 #define LDAP_INVALID_DN_SYNTAX		0x22
 #define LDAP_IS_LEAF			0x23 /* not LDAPv3 */
 #define LDAP_ALIAS_DEREF_PROBLEM	0x24
 
-#define LDAP_NAME_ERROR(n)	(((int)(n) & 0x00f0) == 0x0020)
+#define LDAP_SECURITY_ERROR(n)	LDAP_RANGE((n),0x30,0x32) /* 48-50 */
 
 #define LDAP_INAPPROPRIATE_AUTH		0x30
 #define LDAP_INVALID_CREDENTIALS	0x31
 #define LDAP_INSUFFICIENT_ACCESS	0x32
+
+#define LDAP_SERVICE_ERROR(n)	LDAP_RANGE((n),0x33,0x36) /* 51-54 */
+
 #define LDAP_BUSY			0x33
 #define LDAP_UNAVAILABLE		0x34
 #define LDAP_UNWILLING_TO_PERFORM	0x35
 #define LDAP_LOOP_DETECT		0x36
 
+#define LDAP_UPDATE_ERROR(n)	LDAP_RANGE((n),0x40,0x47) /* 64-69,71 */
+
 #define LDAP_NAMING_VIOLATION		0x40
 #define LDAP_OBJECT_CLASS_VIOLATION	0x41
 #define LDAP_NOT_ALLOWED_ON_NONLEAF	0x42
@@ -339,9 +350,10 @@ typedef struct ldapmod {
 #define LDAP_RESULTS_TOO_LARGE		0x46 /* CLDAP */
 #define LDAP_AFFECTS_MULTIPLE_DSAS	0x47 /* LDAPv3 */
 
-#define LDAP_CLIENT_ERROR(n)	( (int)(n) >= 0x50 )
-
 #define LDAP_OTHER			0x50
+
+#define LDAP_API_ERROR(n)		LDAP_RANGE((n),0x51,0xff) /* 81+ */
+
 #define LDAP_SERVER_DOWN		0x51
 #define LDAP_LOCAL_ERROR		0x52
 #define LDAP_ENCODING_ERROR		0x53
diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c
index 5678589bb9658871383bc171862c78e3ce0a4252..b8c3438576d1ed163a4f1bbd2e044b046f84da0d 100644
--- a/servers/slapd/abandon.c
+++ b/servers/slapd/abandon.c
@@ -19,7 +19,7 @@
 
 #include "slap.h"
 
-void
+int
 do_abandon(
     Connection	*conn,
     Operation	*op
@@ -28,6 +28,7 @@ do_abandon(
 	ber_int_t		id;
 	Operation	*o;
 	Operation	**oo;
+	int rc;
 
 	Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
 
@@ -39,13 +40,13 @@ do_abandon(
 
 	if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
 		Debug( LDAP_DEBUG_ANY, "do_abandon: ber_scanf failed\n", 0, 0 ,0 );
-		return;
+		return LDAP_PROTOCOL_ERROR;
 	}
 
 #ifdef GET_CTRLS
-	if( get_ctrls( conn, op, 0 ) == -1 ) {
+	if( (rc = get_ctrls( conn, op, 0 )) != LDAP_SUCCESS ) {
 		Debug( LDAP_DEBUG_ANY, "do_abandon: get_ctrls failed\n", 0, 0 ,0 );
-		return;
+		return rc;
 	} 
 #endif
 
@@ -88,4 +89,5 @@ do_abandon(
 
 found_it:
 	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+	return LDAP_SUCCESS;
 }
diff --git a/servers/slapd/add.c b/servers/slapd/add.c
index 6293b44ebb0e1dbdf5cab8fe09b2546f3e0f4e65..1c897d91f89c2c23754810d45c7bf4cd4bf8811f 100644
--- a/servers/slapd/add.c
+++ b/servers/slapd/add.c
@@ -22,7 +22,7 @@
 
 static void	add_created_attrs(Operation *op, Entry *e);
 
-void
+int
 do_add( Connection *conn, Operation *op )
 {
 	BerElement	*ber = op->o_ber;
@@ -31,6 +31,7 @@ do_add( Connection *conn, Operation *op )
 	ber_tag_t	tag;
 	Entry		*e;
 	Backend		*be;
+	int			rc = LDAP_SUCCESS;
 
 	Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 );
 
@@ -51,7 +52,7 @@ do_add( Connection *conn, Operation *op )
 		Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
 		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
 		    "decoding error" );
-		return;
+		return LDAP_PROTOCOL_ERROR;
 	}
 
 	e = (Entry *) ch_calloc( 1, sizeof(Entry) );
@@ -75,7 +76,7 @@ do_add( Connection *conn, Operation *op )
 			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
 			    NULL, "decoding error" );
 			entry_free( e );
-			return;
+			return LDAP_PROTOCOL_ERROR;
 		}
 
 		if ( vals == NULL ) {
@@ -85,7 +86,7 @@ do_add( Connection *conn, Operation *op )
 			    NULL );
 			free( type );
 			entry_free( e );
-			return;
+			return LDAP_PROTOCOL_ERROR;
 		}
 
 		attr_merge( e, type, vals );
@@ -99,14 +100,14 @@ do_add( Connection *conn, Operation *op )
 		Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
 		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
 		    "decoding error" );
-		return;
+		return LDAP_PROTOCOL_ERROR;
 	}
 
 #ifdef GET_CTRLS
-	if( get_ctrls( conn, op, 1 ) == -1 ) {
+	if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
 		entry_free( e );
 		Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
-		return;
+		return rc;
 	} 
 #endif
 
@@ -123,7 +124,7 @@ do_add( Connection *conn, Operation *op )
 		entry_free( e );
 		send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
 		    default_referral );
-		return;
+		return rc;
 	}
 
 	/*
@@ -149,15 +150,17 @@ do_add( Connection *conn, Operation *op )
 
 		} else {
 			entry_free( e );
-			send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 			    default_referral );
 		}
 	} else {
 	    Debug( LDAP_DEBUG_ARGS, "    do_add: HHH\n", 0, 0, 0 );
 		entry_free( e );
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+		send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "Function not implemented" );
 	}
+
+	return rc;
 }
 
 static void
diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c
index 41e94d310693ee2f34234720034fce021fac26fd..bb9ccd3e1638a431ac888853c60f9ccad3cebadd 100644
--- a/servers/slapd/bind.c
+++ b/servers/slapd/bind.c
@@ -21,7 +21,13 @@
 
 #include "slap.h"
 
-void
+char *supportedSASLMechanisms[] = {
+	"X-CRAM-MD5",
+	"X-DIGEST-MD5",
+	NULL
+};
+
+int
 do_bind(
     Connection	*conn,
     Operation	*op
@@ -32,7 +38,8 @@ do_bind(
 	ber_tag_t method;
 	char		*mech;
 	char		*cdn, *ndn;
-	ber_tag_t	rc;
+	ber_tag_t	tag;
+	int			rc;
 	struct berval	cred;
 	Backend		*be;
 
@@ -57,43 +64,43 @@ do_bind(
 	 *	}
 	 */
 
-	rc = ber_scanf( ber, "{iat" /*}*/, &version, &cdn, &method );
+	tag = ber_scanf( ber, "{iat" /*}*/, &version, &cdn, &method );
 
-	if ( rc == LBER_ERROR ) {
+	if ( tag == LBER_ERROR ) {
 		Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 		    "decoding error" );
 		goto cleanup;
 	}
 
 	if( method != LDAP_AUTH_SASL ) {
-		rc = ber_scanf( ber, /*{*/ "o}", &cred );
+		tag = ber_scanf( ber, /*{*/ "o}", &cred );
 
 	} else {
-		rc = ber_scanf( ber, "{a" /*}*/, &mech );
+		tag = ber_scanf( ber, "{a" /*}*/, &mech );
 
-		if ( rc != LBER_ERROR ) {
+		if ( tag != LBER_ERROR ) {
 			ber_len_t len;
-			rc = ber_peek_tag( ber, &len );
+			tag = ber_peek_tag( ber, &len );
 
-			if ( rc == LDAP_TAG_LDAPCRED ) { 
-				rc = ber_scanf( ber, "o", &cred );
+			if ( tag == LDAP_TAG_LDAPCRED ) { 
+				tag = ber_scanf( ber, "o", &cred );
 			}
 
-			if ( rc != LBER_ERROR ) {
-				rc = ber_scanf( ber, /*{{*/ "}}" );
+			if ( tag != LBER_ERROR ) {
+				tag = ber_scanf( ber, /*{{*/ "}}" );
 			}
 		}
 	}
 
-	if ( rc == LBER_ERROR ) {
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+	if ( tag == LBER_ERROR ) {
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
     		"decoding error" );
 		goto cleanup;
 	}
 
 #ifdef GET_CTRLS
-	if( get_ctrls( conn, op, 1 ) == -1 ) {
+	if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
 		Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
 		goto cleanup;
 	} 
@@ -114,7 +121,7 @@ do_bind(
 
 	if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
 		Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 		    "version not supported" );
 		goto cleanup;
 	}
@@ -123,7 +130,7 @@ do_bind(
 		if ( version < LDAP_VERSION3 ) {
 			Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%d\n",
 				version, 0, 0 );
-			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 				"sasl bind requires LDAPv3" );
 			goto cleanup;
 		}
@@ -132,19 +139,17 @@ do_bind(
 			Debug( LDAP_DEBUG_ANY,
 				"do_bind: no sasl mechanism provided\n",
 				version, 0, 0 );
-			/* XXYYZ need to check this return code */
-			send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
-				NULL, "no sasl mechanism provided." );
+			send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
+				NULL, "no sasl mechanism provided" );
 			goto cleanup;
 		}
 
-		if( 1 ) {
+		if( !charray_inlist( supportedSASLMechanisms, mech ) ) {
 			Debug( LDAP_DEBUG_ANY,
 				"do_bind: sasl mechanism \"%s\" not supported.\n",
 				mech, 0, 0 );
-			/* XXYYZ need to check this return code */
-			send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
-				NULL, "no sasl mechanism provided." );
+			send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
+				NULL, "sasl mechanism not supported" );
 			goto cleanup;
 		}
 	}
@@ -198,12 +203,13 @@ do_bind(
 			send_ldap_result( conn, op, LDAP_SUCCESS,
 				NULL, NULL );
 		} else if ( default_referral && *default_referral ) {
-			send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS,
+			send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS,
 				NULL, default_referral );
 		} else {
-			send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+			send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
 				NULL, default_referral );
 		}
+
 		goto cleanup;
 	}
 
@@ -249,7 +255,7 @@ do_bind(
 		}
 
 	} else {
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+		send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "Function not implemented" );
 	}
 
@@ -266,4 +272,6 @@ cleanup:
 	if ( cred.bv_val != NULL ) {
 		free( cred.bv_val );
 	}
+
+	return rc;
 }
diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c
index 2709e00c29e4d6ed5006e1d32ec3f8b64b6402db..6519084aa19167e014ff5e2a5f7a8d5d1c548a52 100644
--- a/servers/slapd/compare.c
+++ b/servers/slapd/compare.c
@@ -18,7 +18,7 @@
 
 #include "slap.h"
 
-void
+int
 do_compare(
     Connection	*conn,
     Operation	*op
@@ -27,6 +27,7 @@ do_compare(
 	char	*ndn;
 	Ava	ava;
 	Backend	*be;
+	int rc = LDAP_SUCCESS;
 
 	Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
 
@@ -45,16 +46,16 @@ do_compare(
 	if ( ber_scanf( op->o_ber, "{a{ao}}", &ndn, &ava.ava_type,
 	    &ava.ava_value ) == LBER_ERROR ) {
 		Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
-		return;
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" );
+		return rc;
 	}
 
 #ifdef GET_CTRLS
-	if( get_ctrls( conn, op, 1 ) == -1 ) {
+	if( ( rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
 		free( ndn );
 		ava_free( &ava, 0 );
 		Debug( LDAP_DEBUG_ANY, "do_compare: get_ctrls failed\n", 0, 0, 0 );
-		return;
+		return rc;
 	} 
 #endif
 
@@ -77,9 +78,9 @@ do_compare(
 		free( ndn );
 		ava_free( &ava, 0 );
 
-		send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 		    default_referral );
-		return;
+		return 1;
 	}
 
 	/* alias suffix if approp */
@@ -88,10 +89,12 @@ do_compare(
 	if ( be->be_compare ) {
 		(*be->be_compare)( be, conn, op, ndn, &ava );
 	} else {
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+		send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "Function not implemented" );
 	}
 
 	free( ndn );
 	ava_free( &ava, 0 );
+
+	return rc;
 }
diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c
index 3774ca8db057bbafe2154b1d0f104011bdfec068..13c099b597cb92854897a035fdb4baa17dca2572 100644
--- a/servers/slapd/delete.c
+++ b/servers/slapd/delete.c
@@ -19,7 +19,7 @@
 
 #include "slap.h"
 
-void
+int
 do_delete(
     Connection	*conn,
     Operation	*op
@@ -27,6 +27,7 @@ do_delete(
 {
 	char	*ndn;
 	Backend	*be;
+	int rc;
 
 	Debug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
 
@@ -38,15 +39,15 @@ do_delete(
 
 	if ( ber_scanf( op->o_ber, "a", &ndn ) == LBER_ERROR ) {
 		Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
-		return;
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" );
+		return rc;
 	}
 
 #ifdef GET_CTRLS
-	if( get_ctrls( conn, op, 1 ) == -1 ) {
+	if( ( rc = get_ctrls( conn, op, 1 ) ) != LDAP_SUCCESS ) {
 		free( ndn );
 		Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
-		return;
+		return rc;
 	} 
 #endif
 
@@ -63,9 +64,9 @@ do_delete(
 	 */
 	if ( (be = select_backend( ndn )) == NULL ) {
 		free( ndn );
-		send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 		    default_referral );
-		return;
+		return rc;
 	}
 
 	/* alias suffix if approp */
@@ -86,13 +87,14 @@ do_delete(
 				replog( be, LDAP_REQ_DELETE, ndn, NULL, 0 );
 			}
 		} else {
-			send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 			    default_referral );
 		}
 	} else {
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+		send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "Function not implemented" );
 	}
 
 	free( ndn );
+	return rc;
 }
diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c
index 5722c82ced80dd59395abbacbd51b101865b0b14..2d412d0b1f64070019dbd524d45c2b7e27e3f697 100644
--- a/servers/slapd/modify.c
+++ b/servers/slapd/modify.c
@@ -22,7 +22,7 @@
 
 static void	modlist_free(LDAPModList *ml);
 
-void
+int
 do_modify(
     Connection	*conn,
     Operation	*op
@@ -38,6 +38,7 @@ do_modify(
 	LDAPModList *tmp;
 #endif
 	Backend		*be;
+	int rc;
 
 	Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
 
@@ -62,8 +63,8 @@ do_modify(
 
 	if ( ber_scanf( op->o_ber, "{a" /*}*/, &ndn ) == LBER_ERROR ) {
 		Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
-		return;
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" );
+		return rc;
 	}
 
 	Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", ndn, 0, 0 );
@@ -86,13 +87,13 @@ do_modify(
 		    &(*modtail)->ml_type, &(*modtail)->ml_bvalues )
 		    == LBER_ERROR )
 		{
-			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 			    "decoding error" );
 			free( ndn );
 			free( *modtail );
 			*modtail = NULL;
 			modlist_free( modlist );
-			return;
+			return rc;
 		}
 
 		(*modtail)->ml_op = mop;
@@ -101,21 +102,21 @@ do_modify(
 		    (*modtail)->ml_op != LDAP_MOD_DELETE &&
 		    (*modtail)->ml_op != LDAP_MOD_REPLACE )
 		{
-			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 			    "unrecognized modify operation" );
 			free( ndn );
 			modlist_free( modlist );
-			return;
+			return rc;
 		}
 
 		if ( (*modtail)->ml_bvalues == NULL
 			&& (*modtail)->ml_op != LDAP_MOD_DELETE )
 		{
-			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 			    "no values given" );
 			free( ndn );
 			modlist_free( modlist );
-			return;
+			return rc;
 		}
 		attr_normalize( (*modtail)->ml_type );
 
@@ -134,11 +135,11 @@ do_modify(
 #endif
 
 #ifdef  GET_CTRLS
-	if( get_ctrls( conn, op, 1 ) == -1 ) {
+	if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
 		free( ndn );
 		modlist_free( modlist );
 		Debug( LDAP_DEBUG_ANY, "do_modify: get_ctrls failed\n", 0, 0, 0 );
-		return;
+		return rc;
 	} 
 #endif
 
@@ -153,9 +154,9 @@ do_modify(
 	if ( (be = select_backend( ndn )) == NULL ) {
 		free( ndn );
 		modlist_free( modlist );
-		send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 		    default_referral );
-		return;
+		return rc;
 	}
 
 	/* alias suffix if approp */
@@ -178,16 +179,17 @@ do_modify(
 
 		/* send a referral */
 		} else {
-			send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 			    default_referral );
 		}
 	} else {
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+		send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "Function not implemented" );
 	}
 
 	free( ndn );
 	modlist_free( modlist );
+	return rc;
 }
 
 static void
diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c
index 27e7a100f2f691b439931fc8ac9d000b4aee2e3c..329190f930811bd25a6e8e523f5ad1636e9cffe0 100644
--- a/servers/slapd/modrdn.c
+++ b/servers/slapd/modrdn.c
@@ -32,7 +32,7 @@
 
 #include "slap.h"
 
-void
+int
 do_modrdn(
     Connection	*conn,
     Operation	*op
@@ -46,6 +46,7 @@ do_modrdn(
 	char    *nnewSuperior = NULL;
 	Backend	*newSuperior_be = NULL;
 	ber_len_t	length;
+	int rc;
 
 	Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
 
@@ -63,15 +64,15 @@ do_modrdn(
 	if ( ber_scanf( op->o_ber, "{aab", &ndn, &newrdn, &deloldrdn )
 	    == LBER_ERROR ) {
 		Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
-		return;
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" );
+		return rc;
 	}
 
 	/* Check for newSuperior parameter, if present scan it */
 
 	if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
 
-		if ( op->o_protocol ==  0 ) {
+		if ( op->o_protocol == 0 ) {
 			/*
 			 * Promote to LDAPv3
 			 */
@@ -87,9 +88,9 @@ do_modrdn(
 			Debug( LDAP_DEBUG_ANY,
 			       "modrdn(v2): invalid field newSuperior!\n",
 			       0, 0, 0 );
-			send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+			send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
 					  NULL, "" );
-			return;
+			return rc;
 		}
 
 		if ( ber_scanf( op->o_ber, "a", &newSuperior ) 
@@ -97,9 +98,9 @@ do_modrdn(
 
 		    Debug( LDAP_DEBUG_ANY, "ber_scanf(\"a\"}) failed\n",
 			   0, 0, 0 );
-		    send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+		    send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 				      "" );
-		    return;
+		    return rc;
 
 		}
 
@@ -115,18 +116,18 @@ do_modrdn(
 		free( newrdn );	
 		free( newSuperior );
 		Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 		    "decoding error" );
-		return;
+		return rc;
 	}
 
 #ifdef  GET_CTRLS
-	if( get_ctrls( conn, op, 1 ) == -1 ) {
+	if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
 		free( ndn );
 		free( newrdn );	
 		free( newSuperior );
 		Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
-		return;
+		return rc;
 	} 
 #endif
 
@@ -155,7 +156,7 @@ do_modrdn(
 			free( nnewSuperior );
 			send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
 					  default_referral );
-			return;
+			return 0;
 		}
 	}
 
@@ -175,9 +176,9 @@ do_modrdn(
 		free( newrdn );	
 		free( newSuperior );
 		free( nnewSuperior );
-		send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 		    default_referral );
-		return;
+		return rc;
 	}
 
 	/* Make sure that the entry being changed and the newSuperior are in 
@@ -194,10 +195,10 @@ do_modrdn(
 		free( newSuperior );
 		free( nnewSuperior );
 		
-		send_ldap_result( conn, op, LDAP_AFFECTS_MULTIPLE_DSAS,
+		send_ldap_result( conn, op, rc = LDAP_AFFECTS_MULTIPLE_DSAS,
 				  NULL, "" );
 	    
-		return;
+		return rc;
 
 	}
 
@@ -218,16 +219,16 @@ do_modrdn(
 		{
 			if ( (*be->be_modrdn)( be, conn, op, ndn, newrdn,
 			    deloldrdn, newSuperior ) == 0 ) {
-			        /* XXX: MAY NEEED TO ADD newSuperior HERE */
+			        /* XXX: MAY NEED TO ADD newSuperior HERE */
 				replog( be, LDAP_REQ_MODRDN, ndn, newrdn,
 				    deloldrdn );
 			}
 		} else {
-			send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+			send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 			    default_referral );
 		}
 	} else {
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+		send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "Function not implemented" );
 	}
 
@@ -235,4 +236,5 @@ do_modrdn(
 	free( newrdn );	
 	free( newSuperior );
 	free( nnewSuperior );
+	return rc;
 }
diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c
index 1e0a95546cd06a56aee25678b93f946087e27dcf..a9aef36cf794c7eaeee8fffb82bdc368f39c40ee 100644
--- a/servers/slapd/monitor.c
+++ b/servers/slapd/monitor.c
@@ -21,6 +21,14 @@
 #include "ldap_defaults.h"
 #include "slap.h"
 
+char *supportedControls[] = {
+	NULL
+};
+
+char *supportedExtensions[] = {
+	NULL
+};
+
 #if defined( SLAPD_MONITOR_DN )
 
 void
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 6c60096a47eec21744ded9b3dbbc33a87b1e6838..0407ea158d3284e5d85ae63240958277d2b7ae46 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -218,6 +218,9 @@ int load_module LDAP_P(( const char* file_name, int argc, char *argv[] ));
 /*
  * monitor.c
  */
+extern char *supportedExtensions[];
+extern char *supportedControls[];
+extern char *supportedSASLMechanisms[];
 
 void monitor_info LDAP_P(( Connection *conn, Operation *op ));
 
@@ -386,15 +389,17 @@ extern void	slap_do_nothing   LDAP_P((int sig));
 
 extern void	config_info LDAP_P((Connection *conn, Operation *op));
 extern void	root_dse_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
-extern void	do_abandon LDAP_P((Connection *conn, Operation *op));
-extern void	do_add LDAP_P((Connection *conn, Operation *op));
-extern void	do_bind LDAP_P((Connection *conn, Operation *op));
-extern void	do_compare LDAP_P((Connection *conn, Operation *op));
-extern void	do_delete LDAP_P((Connection *conn, Operation *op));
-extern void	do_modify LDAP_P((Connection *conn, Operation *op));
-extern void	do_modrdn LDAP_P((Connection *conn, Operation *op));
-extern void	do_search LDAP_P((Connection *conn, Operation *op));
-extern void	do_unbind LDAP_P((Connection *conn, Operation *op));
+
+extern int	do_abandon LDAP_P((Connection *conn, Operation *op));
+extern int	do_add LDAP_P((Connection *conn, Operation *op));
+extern int	do_bind LDAP_P((Connection *conn, Operation *op));
+extern int	do_compare LDAP_P((Connection *conn, Operation *op));
+extern int	do_delete LDAP_P((Connection *conn, Operation *op));
+extern int	do_modify LDAP_P((Connection *conn, Operation *op));
+extern int	do_modrdn LDAP_P((Connection *conn, Operation *op));
+extern int	do_search LDAP_P((Connection *conn, Operation *op));
+extern int	do_unbind LDAP_P((Connection *conn, Operation *op));
+extern int	do_exop LDAP_P((Connection *conn, Operation *op));
 
 extern int send_search_entry LDAP_P((Backend *be, Connection *conn, Operation *op, Entry *e, char **attrs, int attrsonly));
 extern int str2result LDAP_P(( char *s, int *code, char **matched, char **info ));
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index aefe07128a767ad0ca1e921787c518d6e287bcd7..e9c05de439232c1a142dc5a5ce8ce60056822af7 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -31,6 +31,8 @@ send_ldap_result2(
 	ber_tag_t	tag;
 	ber_len_t	bytes;
 
+	assert( !LDAP_API_ERROR( err ) );
+
 	if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') )
 		err = LDAP_NO_SUCH_OBJECT;
 
@@ -154,6 +156,8 @@ send_ldap_result(
     char	*text
 )
 {
+	assert( !LDAP_API_ERROR( err ) );
+
 #ifdef LDAP_CONNECTIONLESS
 	if ( op->o_cldap ) {
 		ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr );
diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c
index 257bd37015b29af0b66e304eb5ff92333d17ff62..f609e7114223e21b80ad7dbdeb16946029c477cf 100644
--- a/servers/slapd/root_dse.c
+++ b/servers/slapd/root_dse.c
@@ -59,7 +59,8 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
 #endif
 
 #if defined( SLAPD_SCHEMA_DN )
-	val.bv_val = ch_strdup( SLAPD_SCHEMA_DN );
+	strcpy( buf, SLAPD_SCHEMA_DN );
+	val.bv_val = buf;
 	val.bv_len = strlen( val.bv_val );
 	attr_merge( e, "namingContexts", vals );
 	attr_merge( e, "subschemaSubentry", vals );
@@ -67,17 +68,40 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
 #endif
 
 	/* altServer unsupported */
-	/* supportedExtension: no extensions supported */
-	/* supportedControl: no controls supported */
-	/* supportedSASLMechanism: not yet */
 
+	/* supportedControl */
+	for ( i=0; supportedControls[i] != NULL; i++ ) {
+		strcpy( buf, supportedControls[i] );
+		val.bv_val = buf;
+		val.bv_len = strlen( buf );
+		attr_merge( e, "supportedControl", vals );
+	}
+
+	/* supportedExtension */
+	for ( i=0; supportedExtensions[i] != NULL; i++ ) {
+		strcpy( buf, supportedExtensions[i] );
+		val.bv_val = buf;
+		val.bv_len = strlen( buf );
+		attr_merge( e, "supportedExtension", vals );
+	}
+
+	/* supportedLDAPVersion */
 	for ( i=LDAP_VERSION_MIN; i<=LDAP_VERSION_MAX; i++ ) {
 		sprintf(buf,"%d",i);
 		val.bv_val = buf;
 		val.bv_len = strlen( buf );
 		attr_merge( e, "supportedLDAPVersion", vals );
 	}
-	
+
+	/* supportedSASLMechanism */
+	for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) {
+		strcpy( buf, supportedSASLMechanisms[i] );
+		val.bv_val = buf;
+		val.bv_len = strlen( buf );
+		attr_merge( e, "supportedSASLMechanism", vals );
+	}
+
+
 	send_search_entry( &backends[0], conn, op, e, attrs, attrsonly );
 	send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
 
diff --git a/servers/slapd/search.c b/servers/slapd/search.c
index c0fef8bf6fbeedb053a8c4dff2f24c3789f537dd..920685e58a7cdf41a7d2fd3725f4025a14240a29 100644
--- a/servers/slapd/search.c
+++ b/servers/slapd/search.c
@@ -21,7 +21,7 @@
 #include "slap.h"
 
 
-void
+int
 do_search(
     Connection	*conn,	/* where to send results 		       */
     Operation	*op	/* info about the op to which we're responding */
@@ -34,6 +34,7 @@ do_search(
 	Filter		*filter = NULL;
 	char		**attrs = NULL;
 	Backend		*be;
+	int			rc;
 
 	Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
 
@@ -62,14 +63,16 @@ do_search(
 	 */
 
 	/* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
-	if ( ber_scanf( op->o_ber, "{aiiiib", &base, &scope, &deref, &sizelimit,
+	if ( ber_scanf( op->o_ber, "{aiiiib",
+		&base, &scope, &deref, &sizelimit,
 	    &timelimit, &attrsonly ) == LBER_ERROR ) {
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" );
 		goto return_results;
 	}
+
 	if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
 	    && scope != LDAP_SCOPE_SUBTREE ) {
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
 		    "Unknown search scope" );
 		goto return_results;
 	}
@@ -89,17 +92,19 @@ do_search(
 
 	/* attributes */
 	if ( ber_scanf( op->o_ber, /*{*/ "{v}}", &attrs ) == LBER_ERROR ) {
-		send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
+		send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" );
 		goto return_results;
 	}
 
 #ifdef GET_CTRLS
-	if( get_ctrls( conn, op, 1 ) == -1 ) {
+	if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
 		Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
 		goto return_results;
 	} 
 #endif
 
+	rc = 0;
+
 	Debug( LDAP_DEBUG_ARGS, "    attrs:", 0, 0, 0 );
 
 	if ( attrs != NULL ) {
@@ -149,7 +154,7 @@ do_search(
 	 * if we don't hold it.
 	 */
 	if ( (be = select_backend( base )) == NULL ) {
-		send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
+		send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
 		    default_referral );
 
 		goto return_results;
@@ -163,7 +168,7 @@ do_search(
 		(*be->be_search)( be, conn, op, base, scope, deref, sizelimit,
 		    timelimit, filter, fstr, attrs, attrsonly );
 	} else {
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
+		send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "Function not implemented" );
 	}
 
@@ -174,4 +179,6 @@ return_results:;
 	if ( attrs != NULL ) {
 		charray_free( attrs );
 	}
+
+	return rc;
 }
diff --git a/servers/slapd/unbind.c b/servers/slapd/unbind.c
index f351e554099ecd8d24c883ed989640f627583023..72342b7b706d289f72301ed37fe3624ed181cff7 100644
--- a/servers/slapd/unbind.c
+++ b/servers/slapd/unbind.c
@@ -22,7 +22,7 @@
 #include "slap.h"
 
 
-void
+int
 do_unbind(
     Connection	*conn,
     Operation	*op
@@ -41,4 +41,6 @@ do_unbind(
 
 	/* pass the unbind to all backends */
 	backend_unbind( conn, op );
+
+	return 0;
 }