diff --git a/clients/tools/common.c b/clients/tools/common.c
index 415be46b9dc7bcfd6b1180a90a5d8e1d9cf6445c..583da5a33c6116f0a619d876b0069e9585bbfa90 100644
--- a/clients/tools/common.c
+++ b/clients/tools/common.c
@@ -80,6 +80,12 @@ int   protocol = -1;
 int   verbose = 0;
 int   version = 0;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+int chaining = 0;
+static int chainingResolve = -1;
+static int chainingContinuation = -1;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 /* Set in main() */
 char *prog = NULL;
 
@@ -107,6 +113,11 @@ N_("             [!]noop\n")
 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
 N_("             ppolicy\n")
 #endif
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+N_("             [!]chaining[=<resolveBehavior>[,<continuationBehavior>]]\n")
+N_("                     one of \"chainingPreferred\", \"chainingRequired\",\n")
+N_("                     \"referralsPreferred\", \"referralsRequired\"\n")
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 N_("             [!]postread[=<attrs>]  (a comma-separated attribute list)\n")
 N_("             [!]preread[=<attrs>]   (a comma-separated attribute list)\n"),
 N_("  -f file    read operations from `file'\n"),
@@ -286,6 +297,52 @@ tool_args( int argc, char **argv )
 				postread = 1 + crit;
 				postread_attrs = cvalue;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+			} else if ( strcasecmp( control, "chaining" ) == 0 ) {
+				chaining = 1 + crit;
+
+				if ( cvalue != NULL ) {
+					char	*continuation;
+
+					continuation = strchr( cvalue, ',' );
+					if ( continuation ) {
+						/* FIXME: this makes sense only in searches */
+						*continuation++ = '\0';
+						if ( strcasecmp( continuation, "chainingPreferred" ) == 0 ) {
+							chainingContinuation = LDAP_CHAINING_PREFERRED;
+						} else if ( strcasecmp( continuation, "chainingRequired" ) == 0 ) {
+							chainingContinuation = LDAP_CHAINING_REQUIRED;
+						} else if ( strcasecmp( continuation, "referralsPreferred" ) == 0 ) {
+							chainingContinuation = LDAP_REFERRALS_PREFERRED;
+						} else if ( strcasecmp( continuation, "referralsRequired" ) == 0 ) {
+							chainingContinuation = LDAP_REFERRALS_REQUIRED;
+						} else {
+							fprintf( stderr,
+								"chaining behavior control "
+								"continuation value \"%s\" invalid\n",
+								continuation );
+							exit( EXIT_FAILURE );
+						}
+					}
+	
+					if ( strcasecmp( cvalue, "chainingPreferred" ) == 0 ) {
+						chainingResolve = LDAP_CHAINING_PREFERRED;
+					} else if ( strcasecmp( cvalue, "chainingRequired" ) == 0 ) {
+						chainingResolve = LDAP_CHAINING_REQUIRED;
+					} else if ( strcasecmp( cvalue, "referralsPreferred" ) == 0 ) {
+						chainingResolve = LDAP_REFERRALS_PREFERRED;
+					} else if ( strcasecmp( cvalue, "referralsRequired" ) == 0 ) {
+						chainingResolve = LDAP_REFERRALS_REQUIRED;
+					} else {
+						fprintf( stderr,
+							"chaining behavior control "
+							"resolve value \"%s\" invalid\n",
+							cvalue);
+						exit( EXIT_FAILURE );
+					}
+				}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 			} else {
 				fprintf( stderr, "Invalid general control name: %s\n",
 					control );
@@ -867,7 +924,7 @@ void
 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 {
 	int i = 0, j, crit = 0, err;
-	LDAPControl c[8], **ctrls;
+	LDAPControl c[9], **ctrls;
 
 	ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
 	if ( ctrls == NULL ) {
@@ -915,8 +972,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 
 	if ( manageDSAit ) {
 		c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-		c[i].ldctl_value.bv_val = NULL;
-		c[i].ldctl_value.bv_len = 0;
+		BER_BVZERO( &c[i].ldctl_value );
 		c[i].ldctl_iscritical = manageDSAit > 1;
 		ctrls[i] = &c[i];
 		i++;
@@ -924,8 +980,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 
 	if ( noop ) {
 		c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-		c[i].ldctl_value.bv_val = NULL;
-		c[i].ldctl_value.bv_len = 0;
+		BER_BVZERO( &c[i].ldctl_value );
 		c[i].ldctl_iscritical = noop > 1;
 		ctrls[i] = &c[i];
 		i++;
@@ -991,6 +1046,52 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 		if( attrs ) ldap_charray_free( attrs );
 	}
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+	if ( chaining ) {
+		if ( chainingResolve > -1 ) {
+			BerElementBuffer berbuf;
+			BerElement *ber = (BerElement *)&berbuf;
+
+			ber_init2( ber, NULL, LBER_USE_DER );
+
+			err = ber_printf( ber, "{e" /* } */, chainingResolve );
+		    	if ( err == -1 ) {
+				ber_free( ber, 1 );
+				fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+				exit( EXIT_FAILURE );
+			}
+
+			if ( chainingContinuation > -1 ) {
+				err = ber_printf( ber, "e", chainingContinuation );
+		    		if ( err == -1 ) {
+					ber_free( ber, 1 );
+					fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+					exit( EXIT_FAILURE );
+				}
+			}
+
+			err = ber_printf( ber, /* { */ "N}" );
+		    	if ( err == -1 ) {
+				ber_free( ber, 1 );
+				fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+				exit( EXIT_FAILURE );
+			}
+
+			if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
+				exit( EXIT_FAILURE );
+			}
+
+		} else {
+			BER_BVZERO( &c[i].ldctl_value );
+		}
+
+		c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
+		c[i].ldctl_iscritical = chaining > 1;
+		ctrls[i] = &c[i];
+		i++;
+	}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 	while ( count-- ) {
 		ctrls[i++] = extra_c++;
 	}
diff --git a/clients/tools/common.h b/clients/tools/common.h
index 3022721d5bc99518b54ebc76ab2f7e0935324d07..d6903ac9f9a6dd6cfa64dec0533a54ff3b7bfccc 100644
--- a/clients/tools/common.h
+++ b/clients/tools/common.h
@@ -49,6 +49,9 @@ extern int   manageDSAit;
 extern int   noop;
 extern int   ppolicy;
 extern int	preread, postread;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+extern int	chaining;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 
 extern int   not;
 extern int   want_bindpw;
diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c
index e2f99449591a1261bba2f79a951a703758e750cc..c603281d970e5f7209f065ee701c03dbfa67a36a 100644
--- a/clients/tools/ldapsearch.c
+++ b/clients/tools/ldapsearch.c
@@ -379,7 +379,7 @@ handle_private_option( int i )
 			if( crit ) subentries *= -1;
 #endif
 
-	} else if ( strcasecmp( control, "sync" ) == 0 ) {
+		} else if ( strcasecmp( control, "sync" ) == 0 ) {
 			char *cookiep;
 			char *slimitp;
 			if ( ldapsync ) {
@@ -664,31 +664,34 @@ getNextPage:
 #ifdef LDAP_CONTROL_PAGEDRESULTS
 		|| pagedResults
 #endif
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+		|| chaining
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 		|| ldapsync
 		|| subentries || valuesReturnFilter )
 	{
 		int err;
 		int i=0;
-		LDAPControl c[6];
+		LDAPControl c[10];
 
 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
-	if ( domainScope ) {
-		c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
-		c[i].ldctl_value.bv_val = NULL;
-		c[i].ldctl_value.bv_len = 0;
-		c[i].ldctl_iscritical = domainScope > 1;
-		i++;
-	}
+		if ( domainScope ) {
+			c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
+			c[i].ldctl_value.bv_val = NULL;
+			c[i].ldctl_value.bv_len = 0;
+			c[i].ldctl_iscritical = domainScope > 1;
+			i++;
+		}
 #endif
 
 #ifdef LDAP_CONTROL_SUBENTRIES
 		if ( subentries ) {
-	        if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+			if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
 				return EXIT_FAILURE;
 			}
 
 			err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
-	    	if ( err == -1 ) {
+		    	if ( err == -1 ) {
 				ber_free( seber, 1 );
 				fprintf( stderr, _("Subentries control encoding error!\n") );
 				return EXIT_FAILURE;
diff --git a/include/ldap.h b/include/ldap.h
index b06dd612c3fda8a3e04e1f79772e64d80cec4d68..dda9db93df3b3faae62549d1c85dd836eea8b978 100644
--- a/include/ldap.h
+++ b/include/ldap.h
@@ -277,6 +277,18 @@ typedef struct ldapcontrol {
 #define LDAP_SEARCH_FLAG_DOMAIN_SCOPE		1 /* do not generate referrals */
 #define LDAP_SEARCH_FLAG_PHANTOM_ROOT		2 /* search all NCs subordinate to base */
 
+/* LDAP Chaining Behavior Control *//* work in progress */
+/* <draft-sermersheim-ldap-chaining>;
+ * see also LDAP_REQUIRES_CHAINING, LDAP_CANNOT_CHAIN */
+#ifdef LDAP_DEVEL
+#define LDAP_CONTROL_X_CHAINING_BEHAVIOR	"1.3.6.1.4.1.4203.666.11.3"
+
+#define	LDAP_CHAINING_PREFERRED				0
+#define	LDAP_CHAINING_REQUIRED				1
+#define LDAP_REFERRALS_PREFERRED			2
+#define LDAP_REFERRALS_REQUIRED				3
+#endif
+
 /* LDAP Unsolicited Notifications */
 #define	LDAP_NOTICE_OF_DISCONNECTION	"1.3.6.1.4.1.1466.20036" /* RFC 2251 */
 #define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION
@@ -550,6 +562,13 @@ typedef struct ldapcontrol {
 /* for the Assertion control */
 #define LDAP_ASSERTION_FAILED			0x410f
 
+/* for the Chaining Behavior control (consecutive result codes requested;
+ * see <draft-sermersheim-ldap-chaining> ) */
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#define	LDAP_REQUIRES_CHAINING			0x4110
+#define LDAP_CANNOT_CHAIN			0x4111
+#endif
+
 /* API Error Codes
  *
  * Based on draft-ietf-ldap-c-api-xx
diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c
index 67927c40d767c0c98eb6d788c79ee3af13abe3bf..59f79f11aa69c50f995e7bcc93ff0d8cfe04498e 100644
--- a/servers/slapd/back-ldap/chain.c
+++ b/servers/slapd/back-ldap/chain.c
@@ -29,7 +29,31 @@
 #include "slap.h"
 #include "back-ldap.h"
 
-static BackendInfo *lback;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#define SLAP_CH_RESOLVE_SHIFT				SLAP_CONTROL_SHIFT
+#define SLAP_CH_RESOLVE_MASK				(0x3 << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_CHAINING_PREFERRED		(LDAP_CHAINING_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_CHAINING_REQUIRED		(LDAP_CHAINING_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_REFERRALS_PREFERRED		(LDAP_REFERRALS_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_REFERRALS_REQUIRED		(LDAP_REFERRALS_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_DEFAULT				SLAP_CH_RESOLVE_CHAINING_PREFERRED
+#define	SLAP_CH_CONTINUATION_SHIFT			(SLAP_CH_RESOLVE_SHIFT + 2)
+#define SLAP_CH_CONTINUATION_MASK			(0x3 << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_CHAINING_PREFERRED		(LDAP_CHAINING_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_CHAINING_REQUIRED		(LDAP_CHAINING_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_REFERRALS_PREFERRED	(LDAP_REFERRALS_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_REFERRALS_REQUIRED		(LDAP_REFERRALS_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_DEFAULT			SLAP_CH_CONTINUATION_CHAINING_PREFERRED
+
+#define o_chaining			o_ctrlflag[sc_chainingBehavior]
+#define get_chaining(op)		((op)->o_chaining & SLAP_CONTROL_MASK)
+#define get_chainingBehavior(op)	((op)->o_chaining & (SLAP_CH_RESOLVE_MASK|SLAP_CH_CONTINUATION_MASK))
+#define get_resolveBehavior(op)		((op)->o_chaining & SLAP_CH_RESOLVE_MASK)
+#define get_continuationBehavior(op)	((op)->o_chaining & SLAP_CH_CONTINUATION_MASK)
+#endif /*  LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
+static int		sc_chainingBehavior;
+static BackendInfo	*lback;
 
 static int
 ldap_chain_operational( Operation *op, SlapReply *rs )
@@ -204,10 +228,44 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 
 	struct ldapinfo	li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+	int		sr_err = rs->sr_err;
+	slap_reply_t	sr_type = rs->sr_type;
+	slap_mask_t	chain_mask = 0;
+	ber_len_t	chain_shift = 0;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 	if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) {
 		return SLAP_CB_CONTINUE;
 	}
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+	if ( rs->sr_err == LDAP_REFERRAL && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+		switch ( get_resolveBehavior( op ) ) {
+		case SLAP_CH_RESOLVE_REFERRALS_PREFERRED:
+		case SLAP_CH_RESOLVE_REFERRALS_REQUIRED:
+			return SLAP_CB_CONTINUE;
+
+		default:
+			chain_mask = SLAP_CH_RESOLVE_MASK;
+			chain_shift = SLAP_CH_RESOLVE_SHIFT;
+			break;
+		}
+
+	} else if ( rs->sr_type == REP_SEARCHREF && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+		switch ( get_continuationBehavior( op ) ) {
+		case SLAP_CH_CONTINUATION_REFERRALS_PREFERRED:
+		case SLAP_CH_CONTINUATION_REFERRALS_REQUIRED:
+			return SLAP_CB_CONTINUE;
+
+		default:
+			chain_mask = SLAP_CH_CONTINUATION_MASK;
+			chain_shift = SLAP_CH_CONTINUATION_SHIFT;
+			break;
+		}
+	}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 	/*
 	 * TODO: add checks on who/when chain operations; e.g.:
 	 *   a) what identities are authorized
@@ -393,12 +451,33 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 		break;
 	}
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+	if ( rc != LDAP_SUCCESS ) {
+		switch ( ( get_chainingBehavior( op ) & chain_mask ) >> chain_shift ) {
+		case LDAP_CHAINING_REQUIRED:
+			op->o_callback = NULL;
+			send_ldap_error( op, rs, LDAP_CANNOT_CHAIN, "operation cannot be completed without chaining" );
+			break;
+
+		default:
+			rc = SLAP_CB_CONTINUE;
+			rs->sr_err = sr_err;
+			rs->sr_type = sr_type;
+			break;
+		}
+		goto dont_chain;
+	}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 	if ( sc2.sc_private == NULL ) {
 		op->o_callback = NULL;
 		rc = rs->sr_err = slap_map_api2result( rs );
 		send_ldap_result( op, rs );
 	}
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+dont_chain:;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 	op->o_do_not_cache = cache;
 	op->o_bd->be_private = private;
 	op->o_callback = sc;
@@ -476,11 +555,151 @@ ldap_chain_db_destroy(
 	return rc;
 }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+static int
+ldap_chain_parse_ctrl(
+	Operation	*op,
+	SlapReply	*rs,
+	LDAPControl	*ctrl )
+{
+	ber_tag_t	tag;
+	BerElement	*ber;
+	ber_int_t	mode,
+			behavior;
+
+	if ( get_chaining( op ) != SLAP_CONTROL_NONE ) {
+		rs->sr_text = "Chaining behavior control specified multiple times";
+		return LDAP_PROTOCOL_ERROR;
+	}
+
+	if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
+		rs->sr_text = "Chaining behavior control specified with pagedResults control";
+		return LDAP_PROTOCOL_ERROR;
+	}
+
+	if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
+		mode = (SLAP_CH_RESOLVE_DEFAULT|SLAP_CH_CONTINUATION_DEFAULT);
+
+	} else {
+		ber_len_t	len;
+
+		/* Parse the control value
+		 *      ChainingBehavior ::= SEQUENCE { 
+		 *           resolveBehavior         Behavior OPTIONAL, 
+		 *           continuationBehavior    Behavior OPTIONAL } 
+		 *                             
+		 *      Behavior :: = ENUMERATED { 
+		 *           chainingPreferred       (0), 
+		 *           chainingRequired        (1), 
+		 *           referralsPreferred      (2), 
+		 *           referralsRequired       (3) } 
+		 */
+
+		ber = ber_init( &ctrl->ldctl_value );
+		if( ber == NULL ) {
+			rs->sr_text = "internal error";
+			return LDAP_OTHER;
+		}
+
+		tag = ber_scanf( ber, "{e" /* } */, &behavior );
+		/* FIXME: since the whole SEQUENCE is optional,
+		 * should we accept no enumerations at all? */
+		if ( tag != LBER_ENUMERATED ) {
+			rs->sr_text = "Chaining behavior control: resolveBehavior decoding error";
+			return LDAP_PROTOCOL_ERROR;
+		}
+
+		switch ( behavior ) {
+		case LDAP_CHAINING_PREFERRED:
+			mode = SLAP_CH_RESOLVE_CHAINING_PREFERRED;
+			break;
+
+		case LDAP_CHAINING_REQUIRED:
+			mode = SLAP_CH_RESOLVE_CHAINING_REQUIRED;
+			break;
+
+		case LDAP_REFERRALS_PREFERRED:
+			mode = SLAP_CH_RESOLVE_REFERRALS_PREFERRED;
+			break;
+
+		case LDAP_REFERRALS_REQUIRED:
+			mode = SLAP_CH_RESOLVE_REFERRALS_REQUIRED;
+			break;
+
+		default:
+			rs->sr_text = "Chaining behavior control: unknown resolveBehavior";
+			return LDAP_PROTOCOL_ERROR;
+		}
+
+		tag = ber_peek_tag( ber, &len );
+		if ( tag == LBER_ENUMERATED ) {
+			tag = ber_scanf( ber, "e", &behavior );
+			if ( tag == LBER_ERROR ) {
+				rs->sr_text = "Chaining behavior control: continuationBehavior decoding error";
+				return LDAP_PROTOCOL_ERROR;
+			}
+		}
+
+		if ( tag == LBER_DEFAULT ) {
+			mode |= SLAP_CH_CONTINUATION_DEFAULT;
+
+		} else {
+			switch ( behavior ) {
+			case LDAP_CHAINING_PREFERRED:
+				mode |= SLAP_CH_CONTINUATION_CHAINING_PREFERRED;
+				break;
+
+			case LDAP_CHAINING_REQUIRED:
+				mode |= SLAP_CH_CONTINUATION_CHAINING_REQUIRED;
+				break;
+
+			case LDAP_REFERRALS_PREFERRED:
+				mode |= SLAP_CH_CONTINUATION_REFERRALS_PREFERRED;
+				break;
+
+			case LDAP_REFERRALS_REQUIRED:
+				mode |= SLAP_CH_CONTINUATION_REFERRALS_REQUIRED;
+				break;
+
+			default:
+				rs->sr_text = "Chaining behavior control: unknown continuationBehavior";
+				return LDAP_PROTOCOL_ERROR;
+			}
+		}
+
+		if ( ( ber_scanf( ber, /* { */ "}") ) == LBER_ERROR ) {
+			rs->sr_text = "Chaining behavior control: decoding error";
+			return LDAP_PROTOCOL_ERROR;
+		}
+
+		(void) ber_free( ber, 1 );
+	}
+
+	op->o_chaining = mode | ( ctrl->ldctl_iscritical
+			? SLAP_CONTROL_CRITICAL
+			: SLAP_CONTROL_NONCRITICAL );
+
+	return LDAP_SUCCESS;
+}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 static slap_overinst ldapchain;
 
 int
 chain_init( void )
 {
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+	int	rc;
+
+	rc = register_supported_control( LDAP_CONTROL_X_CHAINING_BEHAVIOR,
+			SLAP_CTRL_ACCESS, NULL,
+			ldap_chain_parse_ctrl, &sc_chainingBehavior );
+	if ( rc != LDAP_SUCCESS ) {
+		fprintf( stderr, "Failed to register chaining behavior control: %d\n", rc );
+		return rc;
+	}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 	ldapchain.on_bi.bi_type = "chain";
 	ldapchain.on_bi.bi_db_init = ldap_chain_db_init;
 	ldapchain.on_bi.bi_db_config = ldap_chain_db_config;