diff --git a/clients/tools/ldapcompare.c b/clients/tools/ldapcompare.c
index c47f609ea4f7ceac6dfa6e9bd5f348fea9498553..1f01d7e74e0f2b9050b8376087a55f216a2f6637 100644
--- a/clients/tools/ldapcompare.c
+++ b/clients/tools/ldapcompare.c
@@ -47,6 +47,9 @@ usage( const char *s )
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -h host    LDAP server\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
 "  -I         use SASL Interactive mode\n"
@@ -105,14 +108,15 @@ main( int argc, char **argv )
 {
 	char	*compdn = NULL, *attrs = NULL;
 	char	*sep;
-	int		rc, i, manageDSAit, quiet;
+	int		rc, i, crit, manageDSAit, noop, quiet;
 	int		referrals, debug;
 	int		authmethod, version, want_bindpw;
 	LDAP	*ld = NULL;
 	struct berval bvalue = { 0, NULL };
 	char	*pw_file = NULL;
+	char	*control, *cvalue;
 
-	debug = verbose = not = referrals =
+	debug = verbose = not = referrals = noop =
 		manageDSAit = want_bindpw = quiet = 0;
 
 	version = -1;
@@ -122,9 +126,34 @@ main( int argc, char **argv )
 	prog = lutil_progname( "ldapcompare", argc, argv );
 
 	while (( i = getopt( argc, argv,
-		"Cd:D:h:H:IkKMnO:p:P:qQR:U:vw:WxX:y:Y:zZ")) != EOF )
+		"Cd:D:e:h:H:IkKMnO:p:P:qQR:U:vw:WxX:y:Y:zZ")) != EOF )
 	{
 		switch( i ) {
+	case 'E': /* compare controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+		fprintf( stderr, "Invalid compare control name: %s\n", control );
+		usage(prog);
+		return EXIT_FAILURE;
 
 		/* Common Options */
 		case 'C':
@@ -140,6 +169,57 @@ main( int argc, char **argv )
 			}
 			binddn = strdup( optarg );
 			break;
+
+	case 'e': /* general controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+
+		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "manageDSAit: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			manageDSAit = 1 + crit;
+			free( control );
+			break;
+			
+		} else if ( strcasecmp( control, "noop" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "noop: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			noop = 1 + crit;
+			free( control );
+			break;
+
+		} else {
+			fprintf( stderr, "Invalid general control name: %s\n", control );
+			usage(prog);
+			return EXIT_FAILURE;
+		}
 		case 'h':	/* ldap host */
 			if( ldapuri != NULL ) {
 				fprintf( stderr, "%s: -h incompatible with -H\n", prog );
diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c
index 35e3d9f8b7f32903ce00a32afb9cca08e22922b9..6abefbe2e1258590b4c3652697b5c66b39a90029 100644
--- a/clients/tools/ldapdelete.c
+++ b/clients/tools/ldapdelete.c
@@ -62,6 +62,9 @@ usage( const char *s )
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -f file    read operations from `file'\n"
 "  -h host    LDAP server\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
@@ -95,10 +98,12 @@ main( int argc, char **argv )
 {
 	char		buf[ 4096 ];
 	FILE		*fp;
-	int		i, rc, authmethod, referrals, want_bindpw, version, debug, manageDSAit;
+	int		i, rc, authmethod, referrals, want_bindpw, version, debug, manageDSAit, noop, crit;
 	char	*pw_file;
+	char	*control, *cvalue;
 
-    not = verbose = contoper = want_bindpw = debug = manageDSAit = referrals = 0;
+    not = verbose = contoper = want_bindpw = debug
+		= manageDSAit = noop = referrals = 0;
     fp = NULL;
     authmethod = -1;
 	version = -1;
@@ -107,13 +112,38 @@ main( int argc, char **argv )
     prog = lutil_progname( "ldapdelete", argc, argv );
 
     while (( i = getopt( argc, argv, "cf:r"
-		"Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
+		"Cd:D:e:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
 	{
 	switch( i ) {
 	/* Delete Specific Options */
 	case 'c':	/* continuous operation mode */
 	    ++contoper;
 	    break;
+	case 'E': /* delete controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+		fprintf( stderr, "Invalid delete control name: %s\n", control );
+		usage(prog);
+		return EXIT_FAILURE;
 	case 'f':	/* read DNs from a file */
 		if( fp != NULL ) {
 			fprintf( stderr, "%s: -f previously specified\n", prog );
@@ -142,6 +172,56 @@ main( int argc, char **argv )
 		}
 	    binddn = strdup( optarg );
 	    break;
+	case 'e': /* general controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+
+		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "manageDSAit: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			manageDSAit = 1 + crit;
+			free( control );
+			break;
+			
+		} else if ( strcasecmp( control, "noop" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "noop: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			noop = 1 + crit;
+			free( control );
+			break;
+
+		} else {
+			fprintf( stderr, "Invalid general control name: %s\n", control );
+			usage(prog);
+			return EXIT_FAILURE;
+		}
 	case 'h':	/* ldap host */
 		if( ldapuri != NULL ) {
 			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c
index 60bc559f6af30c14fcd776ee1c81b95559646433..6ce9d99f9b69ec6a860c56a5e21154a37f253d2d 100644
--- a/clients/tools/ldapmodify.c
+++ b/clients/tools/ldapmodify.c
@@ -105,15 +105,15 @@ usage( const char *prog )
 "Add or modify options:\n"
 "  -a         add values (default%s)\n"
 "  -c         continuous operation mode (do not stop on errors)\n"
-"  -E <ctrl>[=<ctrlparam>] controls\n"
-"             manageDSAit[={no|yes|critical}]   (alternate form, see -M)\n"
-"             noop[={no|yes|critical}]          (no operation)\n"
 "  -F         force all changes records to be used\n"
 "  -S file    write skipped modifications to `file'\n"
 
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -f file    read operations from `file'\n"
 "  -h host    LDAP server\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
@@ -151,7 +151,8 @@ main( int argc, char **argv )
 	int		rc, i, authmethod, version, want_bindpw, debug, manageDSAit, noop, referrals;
 	int count, len;
 	char	*pw_file = NULL;
-	char	*control, *s;
+	char	*control, *cvalue;
+	int		crit;
 
     prog = lutil_progname( "ldapmodify", argc, argv );
 
@@ -168,7 +169,7 @@ main( int argc, char **argv )
 	version = -1;
 
     while (( i = getopt( argc, argv, "acrf:E:F"
-		"Cd:D:h:H:IkKMnO:p:P:QR:S:U:vw:WxX:y:Y:Z" )) != EOF )
+		"Cd:D:e:h:H:IkKMnO:p:P:QR:S:U:vw:WxX:y:Y:Z" )) != EOF )
 	{
 	switch( i ) {
 	/* Modify Options */
@@ -178,75 +179,31 @@ main( int argc, char **argv )
 	case 'c':	/* continuous operation */
 	    contoper = 1;
 	    break;
-	case 'E': /* controls */
+	case 'E': /* modify controls */
 		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -C incompatible with LDAPv%d\n",
+			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
 			return EXIT_FAILURE;
 		}
 
 		/* should be extended to support comma separated list of
-		 *	key/value pairs:  -E foo=123,bar=567
+		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
 		 */
 
-		control = strdup( optarg );
-		if ( (s = strchr( control, '=' )) != NULL ) {
-			*s++ = '\0';
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
 		}
 
-		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if ( s == NULL ) {
-				manageDSAit = 1;
-
-			} else if ( strcasecmp( s, "no" ) == 0 ) {
-				manageDSAit = 0;
-				
-			} else if ( strcasecmp( s, "yes" ) == 0 ) {
-				manageDSAit = 1;
-				
-			} else if ( strcasecmp( s, "critical" ) == 0 ) {
-				manageDSAit = 2;
-
-			} else {
-				fprintf( stderr, "unknown manageDSAit control "
-						"value: %s (accepts \"no\", "
-						"\"yes\", \"critical\")\n", 
-						s );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			free( control );
-			break;
-			
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if ( s == NULL ) {
-				noop = 1;
-
-			} else if ( strcasecmp( s, "no" ) == 0 ) {
-				noop = 0;
-				
-			} else if ( strcasecmp( s, "yes" ) == 0 ) {
-				noop = 1;
-				
-			} else if ( strcasecmp( s, "critical" ) == 0 ) {
-				noop = 2;
-
-			} else {
-				fprintf( stderr, "unknown noop control "
-						"value: %s (accepts \"no\", "
-						"\"yes\", \"critical\")\n", 
-						s );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			free( control );
-			break;
-
-		} else {
-			fprintf( stderr, "Invalid control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
 		}
+		fprintf( stderr, "Invalid modify control name: %s\n", control );
+		usage(prog);
+		return EXIT_FAILURE;
 	case 'f':	/* read from file */
 		if( infile != NULL ) {
 			fprintf( stderr, "%s: -f previously specified\n", prog );
@@ -272,6 +229,56 @@ main( int argc, char **argv )
 		}
 	    binddn = strdup( optarg );
 	    break;
+	case 'e': /* general controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+
+		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "manageDSAit: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			manageDSAit = 1 + crit;
+			free( control );
+			break;
+			
+		} else if ( strcasecmp( control, "noop" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "noop: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			noop = 1 + crit;
+			free( control );
+			break;
+
+		} else {
+			fprintf( stderr, "Invalid general control name: %s\n", control );
+			usage(prog);
+			return EXIT_FAILURE;
+		}
 	case 'h':	/* ldap host */
 		if( ldapuri != NULL ) {
 			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c
index 5e69273144d89bcde3178a529a0951019c57b7ab..daf1eeddabb3e3fe44e70268d50ac169c1ef8949 100644
--- a/clients/tools/ldapmodrdn.c
+++ b/clients/tools/ldapmodrdn.c
@@ -76,6 +76,9 @@ usage( const char *s )
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -f file    read operations from `file'\n"
 "  -h host    LDAP server\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
@@ -108,27 +111,53 @@ main(int argc, char **argv)
 {
     char		*infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ];
     FILE		*fp;
-	int		rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit;
+	int		rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit, noop, crit;
 	int		referrals;
     char	*newSuperior=NULL;
 	char	*pw_file = NULL;
+	char	*control, *cvalue;
 
     infile = NULL;
     not = contoper = verbose = remove = want_bindpw =
-		debug = manageDSAit = referrals = 0;
+		debug = manageDSAit = noop = referrals = 0;
     authmethod = -1;
 	version = -1;
 
     prog = lutil_progname( "ldapmodrdn", argc, argv );
 
     while (( i = getopt( argc, argv, "cf:rs:"
-		"Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
+		"Cd:D:e:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
 	{
 	switch( i ) {
 	/* Modrdn Options */
 	case 'c':
 		contoper++;
 		break;
+	case 'E': /* modrdn controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+		fprintf( stderr, "Invalid modrdn control name: %s\n", control );
+		usage(prog);
+		return EXIT_FAILURE;
 	case 'f':	/* read from file */
 		if( infile != NULL ) {
 			fprintf( stderr, "%s: -f previously specified\n", prog );
@@ -163,6 +192,56 @@ main(int argc, char **argv)
 		}
 	    binddn = strdup( optarg );
 	    break;
+	case 'e': /* general controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+
+		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "manageDSAit: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			manageDSAit = 1 + crit;
+			free( control );
+			break;
+			
+		} else if ( strcasecmp( control, "noop" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "noop: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			noop = 1 + crit;
+			free( control );
+			break;
+
+		} else {
+			fprintf( stderr, "Invalid general control name: %s\n", control );
+			usage(prog);
+			return EXIT_FAILURE;
+		}
 	case 'h':	/* ldap host */
 		if( ldapuri != NULL ) {
 			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c
index f78d5ce5c4c09be4809737f788a618c53ab806d3..b39d7d387a24079c12da5c362449f8f61e8df7e9 100644
--- a/clients/tools/ldappasswd.c
+++ b/clients/tools/ldappasswd.c
@@ -40,6 +40,9 @@ usage(const char *s)
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -f file    read operations from `file'\n"
 "  -h host    LDAP server(s)\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
@@ -88,6 +91,9 @@ main( int argc, char *argv[] )
 	int		version = -1;
 	int		authmethod = -1;
 	int		manageDSAit = 0;
+	int		noop = 0;
+	int		crit;
+	char	*control, *cvalue;
 #ifdef HAVE_CYRUS_SASL
 	unsigned	sasl_flags = LDAP_SASL_AUTOMATIC;
 	char		*sasl_realm = NULL;
@@ -110,7 +116,7 @@ main( int argc, char *argv[] )
     prog = lutil_progname( "ldappasswd", argc, argv );
 
 	while( (i = getopt( argc, argv, "Aa:Ss:"
-		"Cd:D:h:H:InO:p:QR:U:vw:WxX:Y:Z" )) != EOF )
+		"Cd:D:e:h:H:InO:p:QR:U:vw:WxX:Y:Z" )) != EOF )
 	{
 		switch (i) {
 		/* Password Options */
@@ -130,6 +136,31 @@ main( int argc, char *argv[] )
 			}
 			break;
 
+	case 'E': /* passwd controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+		fprintf( stderr, "Invalid passwd control name: %s\n", control );
+		usage(prog);
+		return EXIT_FAILURE;
 		case 'S':	/* prompt for user password */
 			want_newpw++;
 			break;
@@ -159,6 +190,56 @@ main( int argc, char *argv[] )
 		}
 	    binddn = strdup( optarg );
 	    break;
+	case 'e': /* general controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+
+		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "manageDSAit: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			manageDSAit = 1 + crit;
+			free( control );
+			break;
+			
+		} else if ( strcasecmp( control, "noop" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "noop: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			noop = 1 + crit;
+			free( control );
+			break;
+
+		} else {
+			fprintf( stderr, "Invalid general control name: %s\n", control );
+			usage(prog);
+			return EXIT_FAILURE;
+		}
 	case 'h':	/* ldap host */
 		if( ldapuri != NULL ) {
 			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c
index 4db8a5d8a64b965b5967930d834de35748a13375..885bfc36a03669a90722e1637f44fe4c60fee087 100644
--- a/clients/tools/ldapsearch.c
+++ b/clients/tools/ldapsearch.c
@@ -54,9 +54,8 @@ usage( const char *s )
 "  -a deref   one of never (default), always, search, or find\n"
 "  -A         retrieve attribute names only (no values)\n"
 "  -b basedn  base dn for search\n"
-"  -E <ctrl>[=<ctrlparam>] controls\n"
-"             manageDSAit[={no|yes|critical}]   (alternate form, see -M)\n"
-"             mv=<filter>                       (matched values filter)\n"
+"  -E [!]<ctrl>[=<ctrlparam>] search controls (! indicates criticality)\n"
+"             [!]mv=<filter>   (matched values filter)\n"
 "  -F prefix  URL prefix for files (default: %s)\n"
 "  -l limit   time limit (in seconds) for search\n"
 "  -L         print responses in LDIFv1 format\n"
@@ -74,6 +73,9 @@ usage( const char *s )
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -f file    read operations from `file'\n"
 "  -h host    LDAP server\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
@@ -184,20 +186,20 @@ main( int argc, char **argv )
 {
 	char		*infile, *filtpattern, **attrs = NULL, line[BUFSIZ];
 	FILE		*fp = NULL;
-	int			rc, i, first, scope, deref, attrsonly, manageDSAit;
+	int			rc, i, first, scope, deref, attrsonly, manageDSAit, noop, crit;
 	int			referrals, timelimit, sizelimit, debug;
 	int		authmethod, version, want_bindpw;
 	LDAP		*ld = NULL;
 	int		valuesReturnFilter;
 	BerElement	*ber = NULL;
 	struct berval 	*bvalp = NULL;
-	char	*vrFilter  = NULL, *control  = NULL, *s;
+	char	*vrFilter  = NULL, *control = NULL, *cvalue;
 	char	*pw_file = NULL;
 
 
 	infile = NULL;
 	debug = verbose = not = vals2tmp = referrals = valuesReturnFilter =
-		attrsonly = manageDSAit = ldif = want_bindpw = 0;
+		attrsonly = manageDSAit = noop = ldif = want_bindpw = 0;
 
 	prog = lutil_progname( "ldapsearch", argc, argv );
 
@@ -231,7 +233,7 @@ main( int argc, char **argv )
 	urlize( def_urlpre );
 
 	while (( i = getopt( argc, argv, "Aa:b:E:F:f:Ll:S:s:T:tuz:"
-		"Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z")) != EOF )
+		"Cd:e:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z")) != EOF )
 	{
 	switch( i ) {
 	/* Search Options */
@@ -255,66 +257,44 @@ main( int argc, char **argv )
 	case 'b': /* search base */
 		base = strdup( optarg );
 		break;
-	case 'E': /* controls */
+	case 'E': /* search controls */
 		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -C incompatible with LDAPv%d\n",
+			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
 			return EXIT_FAILURE;
 		}
 
 		/* should be extended to support comma separated list of
-		 *	key/value pairs:  -E foo=123,bar=567
+		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
 		 */
 
-		control = strdup( optarg );
-		if ( (s = strchr( control, '=' )) != NULL ) {
-			*s++ = '\0';
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
 		}
 
-		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if ( s == NULL ) {
-				manageDSAit = 1;
-
-			} else if ( strcasecmp( s, "no" ) == 0 ) {
-				manageDSAit = 0;
-				
-			} else if ( strcasecmp( s, "yes" ) == 0 ) {
-				manageDSAit = 1;
-				
-			} else if ( strcasecmp( s, "critical" ) == 0 ) {
-				manageDSAit = 2;
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
 
-			} else {
-				fprintf( stderr, "unknown manageDSAit control "
-						"value: %s (accepts \"no\", "
-						"\"yes\", \"critical\")\n", 
-						s );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			free( control );
-			break;
-			
-		} else if ( strcasecmp( control, "mv" ) == 0 ) {
+		if ( strcasecmp( control, "mv" ) == 0 ) {
 			/* ValuesReturnFilter control */
 			if (valuesReturnFilter!=0) {
 				fprintf( stderr, "ValuesReturnFilter previously specified");
 				return EXIT_FAILURE;
 			}
+			valuesReturnFilter= 1 + crit;
 
-			if ( s == NULL ) {
-				fprintf( stderr, "missing filter in ValuesReturnFilter control\n");
+			if ( cvalue == NULL ) {
+				fprintf( stderr,
+					"missing filter in ValuesReturnFilter control\n");
 				return EXIT_FAILURE;
 			}
 
-			if ( *s == '!' ){
-				s++;
-				valuesReturnFilter=2;
-			} else {
-				valuesReturnFilter=1;
-			}
-
-			vrFilter = s;
+			vrFilter = cvalue;
 			version = LDAP_VERSION3;
 			break;
 
@@ -388,6 +368,56 @@ main( int argc, char **argv )
 		}
 	    binddn = strdup( optarg );
 	    break;
+	case 'e': /* general controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+
+		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "manageDSAit: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			manageDSAit = 1 + crit;
+			free( control );
+			break;
+			
+		} else if ( strcasecmp( control, "noop" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "noop: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			noop = 1 + crit;
+			free( control );
+			break;
+
+		} else {
+			fprintf( stderr, "Invalid general control name: %s\n", control );
+			usage(prog);
+			return EXIT_FAILURE;
+		}
 	case 'h':	/* ldap host */
 		if( ldapuri != NULL ) {
 			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
diff --git a/clients/tools/ldapwhoami.c b/clients/tools/ldapwhoami.c
index 3a894ceb4ee81f1e980c85e0f3ff14440ed11673..ca4d0fa817cd7f224afc759bf100d8a8c23e58f9 100644
--- a/clients/tools/ldapwhoami.c
+++ b/clients/tools/ldapwhoami.c
@@ -34,6 +34,9 @@ usage(const char *s)
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]manageDSAit   (alternate form, see -M)\n"
+"             [!]noop\n"
 "  -f file    read operations from `file'\n"
 "  -h host    LDAP server(s)\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
@@ -90,6 +93,9 @@ main( int argc, char *argv[] )
 	int		use_tls = 0;
 	int		referrals = 0;
 	LDAP	       *ld = NULL;
+	int	manageDSAit=0, noop=0;
+	char	*control, *cvalue;
+	int		crit;
 
 	int id, code = LDAP_OTHER;
 	LDAPMessage *res;
@@ -100,9 +106,35 @@ main( int argc, char *argv[] )
 	prog = lutil_progname( "ldapwhoami", argc, argv );
 
 	while( (i = getopt( argc, argv, 
-		"Cd:D:h:H:InO:p:QR:U:vw:WxX:y:Y:Z" )) != EOF )
+		"Cd:D:e:h:H:InO:p:QR:U:vw:WxX:y:Y:Z" )) != EOF )
 	{
 		switch (i) {
+	case 'E': /* whoami controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+		fprintf( stderr, "Invalid whoami control name: %s\n", control );
+		usage(prog);
+		return EXIT_FAILURE;
+
 	/* Common Options (including options we don't use) */
 	case 'C':
 		referrals++;
@@ -117,6 +149,56 @@ main( int argc, char *argv[] )
 		}
 	    binddn = strdup( optarg );
 	    break;
+	case 'e': /* general controls */
+		if( version == LDAP_VERSION2 ) {
+			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
+				prog, version );
+			return EXIT_FAILURE;
+		}
+
+		/* should be extended to support comma separated list of
+		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+		 */
+
+		crit = 0;
+		cvalue = NULL;
+		if( optarg[0] == '!' ) {
+			crit = 1;
+			optarg++;
+		}
+
+		control = strdup( optarg );
+		if ( (cvalue = strchr( control, '=' )) != NULL ) {
+			*cvalue++ = '\0';
+		}
+
+		if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "manageDSAit: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			manageDSAit = 1 + crit;
+			free( control );
+			break;
+			
+		} else if ( strcasecmp( control, "noop" ) == 0 ) {
+			if( cvalue != NULL ) {
+				fprintf( stderr, "noop: no control value expected" );
+				usage(prog);
+				return EXIT_FAILURE;
+			}
+
+			noop = 1 + crit;
+			free( control );
+			break;
+
+		} else {
+			fprintf( stderr, "Invalid general control name: %s\n", control );
+			usage(prog);
+			return EXIT_FAILURE;
+		}
 	case 'h':	/* ldap host */
 		if( ldapuri != NULL ) {
 			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
diff --git a/doc/devel/todo b/doc/devel/todo
index 5a4d74df65c0f729ca6443e526c4b81c1fef30ec..a2cd3978dd5b1966b5c480dae12c7e0bbc3c1de6 100644
--- a/doc/devel/todo
+++ b/doc/devel/todo
@@ -31,7 +31,7 @@ OpenLDAP 2.x Projects
 Large projects
 --------------
 Redesign slapd memory allocation fault handling
-Perform a security audit (and fix any hole found)
+Update to latest autoconf and friends
 Implement localization
 
 
@@ -41,16 +41,14 @@ Implement LDAP Transactions extension
 Implement Proxy Authorization Control extension
 Implement LDAP Cancel extension
 Implement authPassword (RFC 3112)
-Update to latest autoconf and friends
+Populate matchingRuleUse attribute in the subschema
 
 
 Small projects
 --------------
 Add dumpasn1 logging support
 Add LDIFv1 control support
-Populate matchingRuleUse attribute in the subschema
 Implement -V version options
-Add No-Op Control support to client tools (e.g. ldapsearch(1))
 Add tests to test suite (ACI, moddn, manageDSAit, etc.)
 Recode linked-list structs to use <ldap_queue.h> macros
 Create ldapbind(1) to support bind operations
diff --git a/tests/data/search.out.master b/tests/data/search.out.master
index e166b4e3f8cc70322cae35197bcaab2283c31624..3614047aea5b81ae9fb62d0f9997ed5e10337ad9 100644
--- a/tests/data/search.out.master
+++ b/tests/data/search.out.master
@@ -269,292 +269,3 @@ dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michiga
 objectClass: OpenLDAPperson
 uid: uham
 
-dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-member: cn=Manager,o=University of Michigan,c=US
-member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Unive
- rsity of Michigan,c=US
-member: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c
- =US
-member: cn=John Doe,ou=Information Technology Division,ou=People,o=University 
- of Michigan,c=US
-member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michiga
- n,c=US
-member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Mic
- higan,c=US
-member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Univ
- ersity of Michigan,c=US
-member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Mich
- igan,c=US
-member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Mic
- higan,c=US
-member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Mic
- higan,c=US
-member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Univers
- ity of Michigan,c=US
-owner: cn=Manager,o=University of Michigan,c=US
-cn: All Staff
-description: Everyone in the sample data
-objectClass: groupofnames
-
-dn: cn=Alumni Assoc Staff,ou=Groups,o=University of Michigan,c=US
-member: cn=Manager,o=University of Michigan,c=US
-member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Mic
- higan,c=US
-member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Mic
- higan,c=US
-member: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c
- =US
-member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Mich
- igan,c=US
-member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michiga
- n,c=US
-member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Mic
- higan,c=US
-owner: cn=Manager,o=University of Michigan,c=US
-description: All Alumni Assoc Staff
-cn: Alumni Assoc Staff
-objectClass: groupofnames
-
-dn: ou=Alumni Association,ou=People,o=University of Michigan,c=US
-objectClass: organizationalUnit
-ou: Alumni Association
-
-dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Universit
- y of Michigan,c=US
-objectClass: OpenLDAPperson
-cn: Barbara Jensen
-cn: Babs Jensen
-sn: Jensen
-uid: bjensen
-title: Mythical Manager, Research Systems
-postalAddress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Ann 
- Arbor, MI 48103-4943
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-userPassword:: YmplbnNlbg==
-mail: bjensen@mailgw.umich.edu
-homePostalAddress: 123 Wesley $ Ann Arbor, MI 48103
-description: Mythical manager of the rsdd unix project
-drink: water
-homePhone: +1 313 555 2333
-pager: +1 313 555 3233
-facsimileTelephoneNumber: +1 313 555 2274
-telephoneNumber: +1 313 555 9022
-
-dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=University 
- of Michigan,c=US
-objectClass: OpenLDAPperson
-cn: Bjorn Jensen
-cn: Biiff Jensen
-sn: Jensen
-uid: bjorn
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-userPassword:: Ympvcm4=
-homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
-drink: Iced Tea
-description: Hiker, biker
-title: Director, Embedded Systems
-postalAddress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103
-mail: bjorn@mailgw.umich.edu
-homePhone: +1 313 555 5444
-pager: +1 313 555 4474
-facsimileTelephoneNumber: +1 313 555 2177
-telephoneNumber: +1 313 555 0355
-
-dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Michiga
- n,c=US
-objectClass: OpenLDAPperson
-cn: Dorothy Stevens
-cn: Dot Stevens
-sn: Stevens
-uid: dots
-title: Secretary, UM Alumni Association
-postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-drink: Lemonade
-homePostalAddress: 377 White St. Apt. 3 $ Ann Arbor, MI 48104
-description: Very tall
-facsimileTelephoneNumber: +1 313 555 3223
-telephoneNumber: +1 313 555 3664
-mail: dots@mail.alumni.umich.edu
-homePhone: +1 313 555 0454
-
-dn: ou=Groups,o=University of Michigan,c=US
-objectClass: organizationalUnit
-ou: Groups
-
-dn: ou=Information Technology Division,ou=People,o=University of Michigan,c=US
-objectClass: organizationalUnit
-ou: Information Technology Division
-
-dn: cn=ITD Staff,ou=Groups,o=University of Michigan,c=US
-owner: cn=Manager,o=University of Michigan,c=US
-description: All ITD Staff
-cn: ITD Staff
-objectClass: groupofnames
-member: cn=Manager,o=University of Michigan,c=US
-member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Univers
- ity of Michigan,c=US
-member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Univ
- ersity of Michigan,c=US
-member: cn=John Doe,ou=Information Technology Division,ou=People,o=University 
- of Michigan,c=US
-
-dn: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Michiga
- n,c=US
-objectClass: OpenLDAPperson
-cn: James A Jones 1
-cn: James Jones
-cn: Jim Jones
-sn: Jones
-uid: jaj
-postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-userPassword:: amFq
-homePostalAddress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
-homePhone: +1 313 555 4772
-description: Outstanding
-title: Mad Cow Researcher, UM Alumni Association
-pager: +1 313 555 3923
-mail: jaj@mail.alumni.umich.edu
-facsimileTelephoneNumber: +1 313 555 4332
-telephoneNumber: +1 313 555 0895
-
-dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Universi
- ty of Michigan,c=US
-objectClass: OpenLDAPperson
-cn: James A Jones 2
-cn: James Jones
-cn: Jim Jones
-sn: Doe
-uid: jjones
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-homePostalAddress: 933 Brooks $ Ann Arbor, MI 48104
-homePhone: +1 313 555 8838
-title: Senior Manager, Information Technology Division
-description: Not around very much
-mail: jjones@mailgw.umich.edu
-postalAddress: Info Tech Division $ 535 W William $ Ann Arbor, MI 48103
-pager: +1 313 555 2833
-facsimileTelephoneNumber: +1 313 555 8688
-telephoneNumber: +1 313 555 7334
-
-dn: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c=US
-objectClass: OpenLDAPperson
-cn: Jane Doe
-cn: Jane Alverson
-sn: Doe
-uid: jdoe
-title: Programmer Analyst, UM Alumni Association
-postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-homePostalAddress: 123 Anystreet $ Ann Arbor, MI 48104
-drink: diet coke
-description: Enthusiastic
-mail: jdoe@woof.net
-homePhone: +1 313 555 5445
-pager: +1 313 555 1220
-facsimileTelephoneNumber: +1 313 555 2311
-telephoneNumber: +1 313 555 4774
-
-dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Michigan
- ,c=US
-objectClass: OpenLDAPperson
-cn: Jennifer Smith
-cn: Jen Smith
-sn: Smith
-uid: jen
-postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-drink: Sam Adams
-homePostalAddress: 1000 Maple #44 $ Ann Arbor, MI 48103
-title: Telemarketer, UM Alumni Association
-mail: jen@mail.alumni.umich.edu
-homePhone: +1 313 555 2333
-pager: +1 313 555 6442
-facsimileTelephoneNumber: +1 313 555 2756
-telephoneNumber: +1 313 555 8232
-
-dn: cn=John Doe,ou=Information Technology Division,ou=People,o=University of M
- ichigan,c=US
-objectClass: OpenLDAPperson
-cn: John Doe
-cn: Jonathon Doe
-sn: Doe
-uid: johnd
-postalAddress: ITD $ 535 W. William $ Ann Arbor, MI 48109
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-homePostalAddress: 912 East Bllvd $ Ann Arbor, MI 48104
-title: System Administrator, Information Technology Division
-description: overworked!
-mail: johnd@mailgw.umich.edu
-homePhone: +1 313 555 3774
-pager: +1 313 555 6573
-facsimileTelephoneNumber: +1 313 555 4544
-telephoneNumber: +1 313 555 9394
-
-dn: cn=Manager,o=University of Michigan,c=US
-objectClass: person
-cn: Manager
-cn: Directory Manager
-cn: Dir Man
-sn: Manager
-description: Manager of the directory
-userPassword:: c2VjcmV0
-
-dn: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michigan,c=
- US
-objectClass: OpenLDAPperson
-cn: Mark Elliot
-cn: Mark A Elliot
-sn: Elliot
-uid: melliot
-postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-homePostalAddress: 199 Outer Drive $ Ypsilanti, MI 48198
-homePhone: +1 313 555 0388
-drink: Gasoline
-title: Director, UM Alumni Association
-mail: melliot@mail.alumni.umich.edu
-pager: +1 313 555 7671
-facsimileTelephoneNumber: +1 313 555 7762
-telephoneNumber: +1 313 555 4177
-
-dn: ou=People,o=University of Michigan,c=US
-objectClass: organizationalUnit
-ou: People
-
-dn: o=University of Michigan,c=US
-objectClass: organization
-objectClass: domainRelatedObject
-l: Ann Arbor, Michigan
-st: Michigan
-o: University of Michigan
-o: UMICH
-o: UM
-o: U-M
-o: U of M
-description: The University of Michigan at Ann Arbor
-postalAddress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
- 09 $ US
-telephoneNumber: +1 313 764-1817
-associatedDomain: umich.edu
-
-dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michiga
- n,c=US
-objectClass: OpenLDAPperson
-cn: Ursula Hampster
-sn: Hampster
-uid: uham
-title: Secretary, UM Alumni Association
-postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
-seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
-homePostalAddress: 123 Anystreet $ Ann Arbor, MI 48104
-mail: uham@mail.alumni.umich.edu
-homePhone: +1 313 555 8421
-pager: +1 313 555 2844
-facsimileTelephoneNumber: +1 313 555 9700
-telephoneNumber: +1 313 555 5331
-
-dn: o=University of Michigan,c=US
-o: University of Michigan
-
diff --git a/tests/data/search.out.xsearch b/tests/data/search.out.xsearch
new file mode 100644
index 0000000000000000000000000000000000000000..81c533f99413c1bc6b846820c5ea7025af465e18
--- /dev/null
+++ b/tests/data/search.out.xsearch
@@ -0,0 +1,289 @@
+dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+member: cn=Manager,o=University of Michigan,c=US
+member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Unive
+ rsity of Michigan,c=US
+member: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c
+ =US
+member: cn=John Doe,ou=Information Technology Division,ou=People,o=University 
+ of Michigan,c=US
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=US
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Mic
+ higan,c=US
+member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Univ
+ ersity of Michigan,c=US
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Mich
+ igan,c=US
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Mic
+ higan,c=US
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Mic
+ higan,c=US
+member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Univers
+ ity of Michigan,c=US
+owner: cn=Manager,o=University of Michigan,c=US
+cn: All Staff
+description: Everyone in the sample data
+objectClass: groupofnames
+
+dn: cn=Alumni Assoc Staff,ou=Groups,o=University of Michigan,c=US
+member: cn=Manager,o=University of Michigan,c=US
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Mic
+ higan,c=US
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Mic
+ higan,c=US
+member: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c
+ =US
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Mich
+ igan,c=US
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=US
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Mic
+ higan,c=US
+owner: cn=Manager,o=University of Michigan,c=US
+description: All Alumni Assoc Staff
+cn: Alumni Assoc Staff
+objectClass: groupofnames
+
+dn: ou=Alumni Association,ou=People,o=University of Michigan,c=US
+objectClass: organizationalUnit
+ou: Alumni Association
+
+dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Universit
+ y of Michigan,c=US
+objectClass: OpenLDAPperson
+cn: Barbara Jensen
+cn: Babs Jensen
+sn: Jensen
+uid: bjensen
+title: Mythical Manager, Research Systems
+postalAddress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Ann 
+ Arbor, MI 48103-4943
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+userPassword:: YmplbnNlbg==
+mail: bjensen@mailgw.umich.edu
+homePostalAddress: 123 Wesley $ Ann Arbor, MI 48103
+description: Mythical manager of the rsdd unix project
+drink: water
+homePhone: +1 313 555 2333
+pager: +1 313 555 3233
+facsimileTelephoneNumber: +1 313 555 2274
+telephoneNumber: +1 313 555 9022
+
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=University 
+ of Michigan,c=US
+objectClass: OpenLDAPperson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+uid: bjorn
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+userPassword:: Ympvcm4=
+homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+description: Hiker, biker
+title: Director, Embedded Systems
+postalAddress: Info Tech Division $ 535 W. William St. $ Ann Arbor, MI 48103
+mail: bjorn@mailgw.umich.edu
+homePhone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimileTelephoneNumber: +1 313 555 2177
+telephoneNumber: +1 313 555 0355
+
+dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=US
+objectClass: OpenLDAPperson
+cn: Dorothy Stevens
+cn: Dot Stevens
+sn: Stevens
+uid: dots
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+drink: Lemonade
+homePostalAddress: 377 White St. Apt. 3 $ Ann Arbor, MI 48104
+description: Very tall
+facsimileTelephoneNumber: +1 313 555 3223
+telephoneNumber: +1 313 555 3664
+mail: dots@mail.alumni.umich.edu
+homePhone: +1 313 555 0454
+
+dn: ou=Groups,o=University of Michigan,c=US
+objectClass: organizationalUnit
+ou: Groups
+
+dn: ou=Information Technology Division,ou=People,o=University of Michigan,c=US
+objectClass: organizationalUnit
+ou: Information Technology Division
+
+dn: cn=ITD Staff,ou=Groups,o=University of Michigan,c=US
+owner: cn=Manager,o=University of Michigan,c=US
+description: All ITD Staff
+cn: ITD Staff
+objectClass: groupofnames
+member: cn=Manager,o=University of Michigan,c=US
+member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Univers
+ ity of Michigan,c=US
+member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Univ
+ ersity of Michigan,c=US
+member: cn=John Doe,ou=Information Technology Division,ou=People,o=University 
+ of Michigan,c=US
+
+dn: cn=James A Jones 1,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=US
+objectClass: OpenLDAPperson
+cn: James A Jones 1
+cn: James Jones
+cn: Jim Jones
+sn: Jones
+uid: jaj
+postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+userPassword:: amFq
+homePostalAddress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
+homePhone: +1 313 555 4772
+description: Outstanding
+title: Mad Cow Researcher, UM Alumni Association
+pager: +1 313 555 3923
+mail: jaj@mail.alumni.umich.edu
+facsimileTelephoneNumber: +1 313 555 4332
+telephoneNumber: +1 313 555 0895
+
+dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Universi
+ ty of Michigan,c=US
+objectClass: OpenLDAPperson
+cn: James A Jones 2
+cn: James Jones
+cn: Jim Jones
+sn: Doe
+uid: jjones
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+homePostalAddress: 933 Brooks $ Ann Arbor, MI 48104
+homePhone: +1 313 555 8838
+title: Senior Manager, Information Technology Division
+description: Not around very much
+mail: jjones@mailgw.umich.edu
+postalAddress: Info Tech Division $ 535 W William $ Ann Arbor, MI 48103
+pager: +1 313 555 2833
+facsimileTelephoneNumber: +1 313 555 8688
+telephoneNumber: +1 313 555 7334
+
+dn: cn=Jane Doe,ou=Alumni Association,ou=People,o=University of Michigan,c=US
+objectClass: OpenLDAPperson
+cn: Jane Doe
+cn: Jane Alverson
+sn: Doe
+uid: jdoe
+title: Programmer Analyst, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+homePostalAddress: 123 Anystreet $ Ann Arbor, MI 48104
+drink: diet coke
+description: Enthusiastic
+mail: jdoe@woof.net
+homePhone: +1 313 555 5445
+pager: +1 313 555 1220
+facsimileTelephoneNumber: +1 313 555 2311
+telephoneNumber: +1 313 555 4774
+
+dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=University of Michigan
+ ,c=US
+objectClass: OpenLDAPperson
+cn: Jennifer Smith
+cn: Jen Smith
+sn: Smith
+uid: jen
+postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+drink: Sam Adams
+homePostalAddress: 1000 Maple #44 $ Ann Arbor, MI 48103
+title: Telemarketer, UM Alumni Association
+mail: jen@mail.alumni.umich.edu
+homePhone: +1 313 555 2333
+pager: +1 313 555 6442
+facsimileTelephoneNumber: +1 313 555 2756
+telephoneNumber: +1 313 555 8232
+
+dn: cn=John Doe,ou=Information Technology Division,ou=People,o=University of M
+ ichigan,c=US
+objectClass: OpenLDAPperson
+cn: John Doe
+cn: Jonathon Doe
+sn: Doe
+uid: johnd
+postalAddress: ITD $ 535 W. William $ Ann Arbor, MI 48109
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+homePostalAddress: 912 East Bllvd $ Ann Arbor, MI 48104
+title: System Administrator, Information Technology Division
+description: overworked!
+mail: johnd@mailgw.umich.edu
+homePhone: +1 313 555 3774
+pager: +1 313 555 6573
+facsimileTelephoneNumber: +1 313 555 4544
+telephoneNumber: +1 313 555 9394
+
+dn: cn=Manager,o=University of Michigan,c=US
+objectClass: person
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userPassword:: c2VjcmV0
+
+dn: cn=Mark Elliot,ou=Alumni Association,ou=People,o=University of Michigan,c=
+ US
+objectClass: OpenLDAPperson
+cn: Mark Elliot
+cn: Mark A Elliot
+sn: Elliot
+uid: melliot
+postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+homePostalAddress: 199 Outer Drive $ Ypsilanti, MI 48198
+homePhone: +1 313 555 0388
+drink: Gasoline
+title: Director, UM Alumni Association
+mail: melliot@mail.alumni.umich.edu
+pager: +1 313 555 7671
+facsimileTelephoneNumber: +1 313 555 7762
+telephoneNumber: +1 313 555 4177
+
+dn: ou=People,o=University of Michigan,c=US
+objectClass: organizationalUnit
+ou: People
+
+dn: o=University of Michigan,c=US
+objectClass: organization
+objectClass: domainRelatedObject
+l: Ann Arbor, Michigan
+st: Michigan
+o: University of Michigan
+o: UMICH
+o: UM
+o: U-M
+o: U of M
+description: The University of Michigan at Ann Arbor
+postalAddress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
+ 09 $ US
+telephoneNumber: +1 313 764-1817
+associatedDomain: umich.edu
+
+dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=US
+objectClass: OpenLDAPperson
+cn: Ursula Hampster
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
+seeAlso: cn=All Staff,ou=Groups,o=University of Michigan,c=US
+homePostalAddress: 123 Anystreet $ Ann Arbor, MI 48104
+mail: uham@mail.alumni.umich.edu
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+
+dn: o=University of Michigan,c=US
+o: University of Michigan
+
diff --git a/tests/scripts/defines.sh b/tests/scripts/defines.sh
index 3c1eeba5303208556c739328f21ea56a4ce1fd80..d102b75bd5d2013c8dc96a81df8719301859daf2 100755
--- a/tests/scripts/defines.sh
+++ b/tests/scripts/defines.sh
@@ -88,6 +88,7 @@ SUBMASTEROUT=$DBDIR/submaster.out
 TESTOUT=$DBDIR/test.out
 INITOUT=$DBDIR/init.out
 SEARCHOUTMASTER=$DATADIR/search.out.master
+SEARCHOUTX=$DATADIR/search.out.xsearch
 MODIFYOUTMASTER=$DATADIR/modify.out.master
 ADDDELOUTMASTER=$DATADIR/adddel.out.master
 MODRDNOUTMASTER0=$DATADIR/modrdn.out.master.0
diff --git a/tests/scripts/test003-search b/tests/scripts/test003-search
index 4fdb6c7557e80269f596e4b9215acf84d0a034d2..77fb4616dc01345b0d23a7aa783dc11471147aca 100755
--- a/tests/scripts/test003-search
+++ b/tests/scripts/test003-search
@@ -121,28 +121,6 @@ if test $RC != 0 ; then
 	exit $RC
 fi
 
-echo "Testing extended RFC2254 searching..."
-$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT \
-	'(:dn:caseExactMatch:=University of Michigan)' >> $SEARCHOUT 2>&1
-
-RC=$?
-if test $RC != 0 ; then
-	echo "ldapsearch failed ($RC)!"
-	kill -HUP $PID
-	exit $RC
-fi
-
-echo "Testing values return filter searching..."
-$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT \
-	-E 'mv=(o=University of Michigan)' \
-	'(o=University of Michigan)' >> $SEARCHOUT 2>&1
-RC=$?
-if test $RC != 0 ; then
-	echo "ldapsearch failed ($RC)!"
-	kill -HUP $PID
-	exit $RC
-fi
-
 
 kill -HUP $PID
 LDIF=$SEARCHOUTMASTER
diff --git a/tests/scripts/test015-xsearch b/tests/scripts/test015-xsearch
index acdc134128f4b90f9fdbda415422f762e5290267..80214e22095e5b759905993fa87b2557cea193ef 100755
--- a/tests/scripts/test015-xsearch
+++ b/tests/scripts/test015-xsearch
@@ -121,14 +121,39 @@ if test $RC != 0 ; then
 	exit $RC
 fi
 
+echo "Testing extended RFC2254 searching..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT \
+	'(:dn:caseExactMatch:=University of Michigan)' >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapsearch failed ($RC)!"
+	kill -HUP $PID
+	exit $RC
+fi
+
+echo "Testing values return filter searching..."
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT \
+	-E '!mv=(o=University of Michigan)' \
+	'(o=University of Michigan)' >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapsearch failed ($RC)!"
+	kill -HUP $PID
+	exit $RC
+fi
+
+
 kill -HUP $PID
 
 LDIF=$SEARCHOUTMASTER
+LDIF2=$SEARCHOUTX
 
 echo "Filtering ldapsearch results..."
 . $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
 echo "Filtering original ldif used to create database..."
 . $LDIFFILTER < $LDIF > $LDIFFLT
+. $LDIFFILTER < $LDIF2 >> $LDIFFLT
 echo "Comparing filter output..."
 $CMP $SEARCHFLT $LDIFFLT > $CMPOUT