From 798289fd503bdc32ee9407b858fcf68b2e3903e9 Mon Sep 17 00:00:00 2001
From: Pierangelo Masarati <ando@openldap.org>
Date: Thu, 3 Apr 2003 21:35:54 +0000
Subject: [PATCH] new API; compiles if proxy is disabled

---
 servers/slapd/back-meta/Makefile.in |   4 +-
 servers/slapd/back-meta/add.c       |  66 ++++----
 servers/slapd/back-meta/back-meta.h |   9 +-
 servers/slapd/back-meta/bind.c      |  59 ++++----
 servers/slapd/back-meta/compare.c   | 103 +++++++------
 servers/slapd/back-meta/conn.c      |  64 +++++---
 servers/slapd/back-meta/delete.c    |  51 ++++---
 servers/slapd/back-meta/modify.c    | 112 ++++++++------
 servers/slapd/back-meta/modrdn.c    | 120 +++++++++------
 servers/slapd/back-meta/search.c    | 227 +++++++++++++++-------------
 10 files changed, 448 insertions(+), 367 deletions(-)

diff --git a/servers/slapd/back-meta/Makefile.in b/servers/slapd/back-meta/Makefile.in
index e275e2e37e..4e479e3779 100644
--- a/servers/slapd/back-meta/Makefile.in
+++ b/servers/slapd/back-meta/Makefile.in
@@ -3,12 +3,12 @@
 SRCS	= init.c config.c search.c bind.c unbind.c add.c compare.c \
 		cache-query.c cache-search.c cache-config.c cache-merge.c \
 		cache-template.c cache-substring.c cache-remove.c \
-		delete.c modify.c modrdn.c group.c attribute.c \
+		delete.c modify.c modrdn.c \
 		conn.c candidates.c dncache.c
 OBJS	= init.lo config.lo search.lo bind.lo unbind.lo add.lo compare.lo \
 		cache-query.lo cache-search.lo cache-config.lo cache-merge.lo \
 		cache-template.lo cache-substring.lo cache-remove.lo \
-		delete.lo modify.lo modrdn.lo group.lo attribute.lo \
+		delete.lo modify.lo modrdn.lo \
 		conn.lo candidates.lo dncache.lo
 
 LDAP_INCDIR= ../../../include       
diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c
index 64e1efafda..8e1fc4eecc 100644
--- a/servers/slapd/back-meta/add.c
+++ b/servers/slapd/back-meta/add.c
@@ -77,14 +77,9 @@
 #include "back-meta.h"
 
 int
-meta_back_add(
-		Backend		*be,
-		Connection	*conn,
-		Operation	*op,
-		Entry		*e
-)
+meta_back_add( Operation *op, SlapReply *rs )
 {
-	struct metainfo *li = ( struct metainfo * )be->be_private;
+	struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
 	struct metaconn *lc;
 	int i, candidate = -1;
 	Attribute *a;
@@ -92,20 +87,26 @@ meta_back_add(
 	struct berval mdn = { 0, NULL }, mapped;
 
 #ifdef NEW_LOGGING
-	LDAP_LOG( BACK_META, ENTRY, "meta_back_add: %s\n", e->e_dn, 0, 0 );
+	LDAP_LOG( BACK_META, ENTRY, "meta_back_add: %s\n",
+			op->o_req_dn.bv_val, 0, 0 );
 #else /* !NEW_LOGGING */
-	Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n%s%s", e->e_dn, "", "");
+	Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
+			op->o_req_dn.bv_val, 0, 0 );
 #endif /* !NEW_LOGGING */
 
 	/*
 	 * get the current connection
 	 */
-	lc = meta_back_getconn( li, conn, op, META_OP_REQUIRE_SINGLE,
-			&e->e_nname, &candidate );
-	if ( !lc || !meta_back_dobind( lc, op )
+	lc = meta_back_getconn( li, op, rs, META_OP_REQUIRE_SINGLE,
+			&op->o_req_ndn, &candidate );
+	if ( !lc ) {
+		send_ldap_result( op, rs );
+	}
+
+	if ( !meta_back_dobind( lc, op )
 			|| !meta_back_is_valid( lc, candidate ) ) {
- 		send_ldap_result( conn, op, LDAP_OTHER,
- 				NULL, NULL, NULL, NULL );
+		rs->sr_err = LDAP_OTHER;
+ 		send_ldap_result( op, rs );
 		return -1;
 	}
 
@@ -113,41 +114,45 @@ meta_back_add(
 	 * Rewrite the add dn, if needed
 	 */
 	switch ( rewrite_session( li->targets[ candidate ]->rwinfo,
-				"addDn", e->e_dn, conn, &mdn.bv_val )) {
+				"addDn", op->o_req_dn.bv_val, op->o_conn,
+				&mdn.bv_val ) ) {
 	case REWRITE_REGEXEC_OK:
 		if ( mdn.bv_val != NULL && mdn.bv_val[ 0 ] != '\0' ) {
 			mdn.bv_len = strlen( mdn.bv_val );
 		} else {
-			mdn = e->e_name;
+			mdn = op->o_req_dn;
 		}
 
 #ifdef NEW_LOGGING
 		LDAP_LOG( BACK_META, DETAIL1,
-			"[rw] addDn: \"%s\" -> \"%s\"\n", e->e_dn, mdn.bv_val, 0 );
+				"[rw] addDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn.bv_val, 0 );
 #else /* !NEW_LOGGING */
-		Debug( LDAP_DEBUG_ARGS, "rw> addDn: \"%s\" -> \"%s\"\n%s", 
-				e->e_dn, mdn.bv_val, "" );
+		Debug( LDAP_DEBUG_ARGS, "rw> addDn: \"%s\" -> \"%s\"\n", 
+				op->o_req_dn.bv_val, mdn.bv_val, 0 );
 #endif /* !NEW_LOGGING */
 		break;
  		
  	case REWRITE_REGEXEC_UNWILLING:
- 		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
- 				NULL, "Operation not allowed", NULL, NULL );
+		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+		rs->sr_text = "Operation not allowed";
+ 		send_ldap_result( op, rs );
 		return -1;
 	       	
 	case REWRITE_REGEXEC_ERR:
- 		send_ldap_result( conn, op, LDAP_OTHER,
- 				NULL, "Rewrite error", NULL, NULL );
+		rs->sr_err = LDAP_OTHER;
+		rs->sr_text = "Rewrite error";
+ 		send_ldap_result( op, rs );
 		return -1;
 	}
 
 	/* Count number of attributes in entry */
-	for ( i = 1, a = e->e_attrs; a; i++, a = a->a_next );
+	for ( i = 1, a = op->oq_add.rs_e->e_attrs; a; i++, a = a->a_next );
 	
 	/* Create array of LDAPMods for ldap_add() */
 	attrs = ch_malloc( sizeof( LDAPMod * )*i );
 
-	for ( i = 0, a = e->e_attrs; a; a = a->a_next ) {
+	for ( i = 0, a = op->oq_add.rs_e->e_attrs; a; a = a->a_next ) {
 		int j;
 
 		if ( a->a_desc->ad_type->sat_no_user_mod  ) {
@@ -175,13 +180,14 @@ meta_back_add(
 		if ( strcmp( a->a_desc->ad_type->sat_syntax->ssyn_oid,
 					SLAPD_DN_SYNTAX ) == 0 ) {
 			ldap_dnattr_rewrite( li->targets[ candidate ]->rwinfo,
-					a->a_vals, conn );
+					a->a_vals, op->o_conn );
 		}
 
-		for (j=0; a->a_vals[ j ].bv_val; j++);
+		for ( j = 0; a->a_vals[ j ].bv_val; j++ );
 		attrs[ i ]->mod_vals.modv_bvals = ch_malloc((j+1)*sizeof(struct berval *));
-		for (j=0; a->a_vals[ j ].bv_val; j++)
+		for ( j = 0; a->a_vals[ j ].bv_val; j++ ) {
 			attrs[ i ]->mod_vals.modv_bvals[ j ] = &a->a_vals[ j ];
+		}
 		attrs[ i ]->mod_vals.modv_bvals[ j ] = NULL;
 		i++;
 	}
@@ -193,9 +199,9 @@ meta_back_add(
 		free( attrs[ i ] );
 	}
 	free( attrs );
-	if ( mdn.bv_val != e->e_dn ) {
+	if ( mdn.bv_val != op->oq_add.rs_e->e_dn ) {
 		free( mdn.bv_val );
 	}
-	return meta_back_op_result( lc, op );
+	return meta_back_op_result( lc, op, rs );
 }
 
diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h
index bcd1e9990e..a81767eb3f 100644
--- a/servers/slapd/back-meta/back-meta.h
+++ b/servers/slapd/back-meta/back-meta.h
@@ -165,9 +165,9 @@ struct metainfo {
 #define META_OP_REQUIRE_ALL		0x02
 extern struct metaconn *
 meta_back_getconn(
-		struct			metainfo *li,
-	       	struct			slap_conn *conn,
-		struct			slap_op *op,
+		struct metainfo		*li,
+		Operation		*op,
+		SlapReply		*rs,
 		int			op_type,
 		struct berval		*dn,
 		int			*candidate
@@ -188,7 +188,8 @@ meta_back_is_valid(
 extern int
 meta_back_op_result(
 		struct metaconn		*lc,
-		Operation		*op
+		Operation		*op,
+		SlapReply		*rs
 );
 
 extern int
diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c
index 4c1c9bec78..5cff3a9427 100644
--- a/servers/slapd/back-meta/bind.c
+++ b/servers/slapd/back-meta/bind.c
@@ -92,7 +92,8 @@ meta_back_do_single_bind(
 );
 
 int
-meta_back_bind(
+meta_back_bind( Operation *op, SlapReply *rs )
+		/*
 		Backend		*be,
 		Connection	*conn,
 		Operation	*op,
@@ -101,34 +102,35 @@ meta_back_bind(
 		int		method,
 		struct berval	*cred,
 		struct berval	*edn
-)
+) */
 {
-	struct metainfo	*li = ( struct metainfo * )be->be_private;
+	struct metainfo	*li = ( struct metainfo * )op->o_bd->be_private;
 	struct metaconn *lc;
 
 	int rc = -1, i, gotit = 0, ndnlen, isroot = 0;
 	int op_type = META_OP_ALLOW_MULTIPLE;
 	int err = LDAP_SUCCESS;
 
-	struct berval *realdn = dn;
-	struct berval *realndn = ndn;
-	struct berval *realcred = cred;
-	int realmethod = method;
+	struct berval *realdn = &op->o_req_dn;
+	struct berval *realndn = &op->o_req_ndn;
+	struct berval *realcred = &op->oq_bind.rb_cred;
+	int realmethod = op->oq_bind.rb_method;
 
 #ifdef NEW_LOGGING
-	LDAP_LOG( BACK_META, ENTRY,
-			"meta_back_bind: dn: %s.\n", dn->bv_val, 0, 0 );
+	LDAP_LOG( BACK_META, ENTRY, "meta_back_bind: dn: %s.\n",
+			op->o_req_dn.bv_val, 0, 0 );
 #else /* !NEW_LOGGING */
-	Debug( LDAP_DEBUG_ARGS, "meta_back_bind: dn: %s.\n%s%s", dn->bv_val, "", "" );
+	Debug( LDAP_DEBUG_ARGS, "meta_back_bind: dn: %s.\n%s%s",
+			op->o_req_dn.bv_val, "", "" );
 #endif /* !NEW_LOGGING */
 
-	if ( method == LDAP_AUTH_SIMPLE 
-			&& be_isroot_pw( be, conn, ndn, cred ) ) {
+	if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op ) ) {
 		isroot = 1;
-		ber_dupbv( edn, be_root_dn( be ) );
+		ber_dupbv( &op->oq_bind.rb_edn, be_root_dn( op->o_bd ) );
 		op_type = META_OP_REQUIRE_ALL;
 	}
-	lc = meta_back_getconn( li, conn, op, op_type, ndn, NULL );
+	lc = meta_back_getconn( li, op, rs, op_type,
+			&op->o_req_ndn, NULL );
 	if ( !lc ) {
 #ifdef NEW_LOGGING
 		LDAP_LOG( BACK_META, NOTICE,
@@ -136,10 +138,10 @@ meta_back_bind(
 #else /* !NEW_LOGGING */
 		Debug( LDAP_DEBUG_ANY,
 				"meta_back_bind: no target for dn %s.\n%s%s",
-				dn->bv_val, "", "");
+				op->o_req_dn.bv_val, "", "");
 #endif /* !NEW_LOGGING */
-		send_ldap_result( conn, op, LDAP_OTHER, 
-				NULL, NULL, NULL, NULL );
+
+		send_ldap_result( op, rs );
 		return -1;
 	}
 
@@ -147,7 +149,7 @@ meta_back_bind(
 	 * Each target is scanned ...
 	 */
 	lc->bound_target = META_BOUND_NONE;
-	ndnlen = ndn->bv_len;
+	ndnlen = op->o_req_ndn.bv_len;
 	for ( i = 0; i < li->ntargets; i++ ) {
 		int lerr;
 
@@ -185,10 +187,10 @@ meta_back_bind(
 			realcred = &li->targets[ i ]->pseudorootpw;
 			realmethod = LDAP_AUTH_SIMPLE;
 		} else {
-			realdn = dn;
-			realndn = ndn;
-			realcred = cred;
-			realmethod = method;
+			realdn = &op->o_req_dn;
+			realndn = &op->o_req_ndn;
+			realcred = &op->oq_bind.rb_cred;
+			realmethod = op->oq_bind.rb_method;
 		}
 		
 		lerr = meta_back_do_single_bind( li, lc, op,
@@ -224,8 +226,8 @@ meta_back_bind(
 			err = LDAP_INVALID_CREDENTIALS;
 		}
 
-		err = ldap_back_map_result( err );
-		send_ldap_result( conn, op, err, NULL, NULL, NULL, NULL );
+		rs->sr_err = ldap_back_map_result( err );
+		send_ldap_result( op, rs );
 		return -1;
 	}
 
@@ -459,7 +461,7 @@ meta_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
  * FIXME: error return must be handled in a cleaner way ...
  */
 int
-meta_back_op_result( struct metaconn *lc, Operation *op )
+meta_back_op_result( struct metaconn *lc, Operation *op, SlapReply *rs )
 {
 	int i, rerr = LDAP_SUCCESS;
 	struct metasingleconn *lsc;
@@ -524,7 +526,12 @@ meta_back_op_result( struct metaconn *lc, Operation *op )
 		}
 	}
 
-	send_ldap_result( lc->conn, op, rerr, rmatch, rmsg, NULL, NULL );
+	rs->sr_err = rerr;
+	rs->sr_text = rmsg;
+	rs->sr_matched = rmatch;
+	send_ldap_result( op, rs );
+	rs->sr_text = NULL;
+	rs->sr_matched = NULL;
 
 	return ( ( rerr == LDAP_SUCCESS ) ? 0 : -1 );
 }
diff --git a/servers/slapd/back-meta/compare.c b/servers/slapd/back-meta/compare.c
index b4131c7557..3da152810f 100644
--- a/servers/slapd/back-meta/compare.c
+++ b/servers/slapd/back-meta/compare.c
@@ -76,16 +76,9 @@
 #include "back-meta.h"
 
 int
-meta_back_compare(
-		Backend			*be,
-		Connection		*conn,
-		Operation		*op,
-		struct berval		*dn,
-		struct berval		*ndn,
-		AttributeAssertion 	*ava
-)
+meta_back_compare( Operation *op, SlapReply *rs )
 {
-	struct metainfo	*li = ( struct metainfo * )be->be_private;
+	struct metainfo	*li = ( struct metainfo * )op->o_bd->be_private;
 	struct metaconn *lc;
 	struct metasingleconn *lsc;
 	char *match = NULL, *err = NULL, *mmatch = NULL;
@@ -93,11 +86,16 @@ meta_back_compare(
        	int cres = LDAP_SUCCESS, rres = LDAP_SUCCESS;
 	int *msgid;
 
-	lc = meta_back_getconn( li, conn, op, META_OP_ALLOW_MULTIPLE,
-			ndn, NULL );
-	if ( !lc || !meta_back_dobind( lc, op ) ) {
- 		send_ldap_result( conn, op, LDAP_OTHER,
- 				NULL, NULL, NULL, NULL );
+	lc = meta_back_getconn( li, op, rs, META_OP_ALLOW_MULTIPLE,
+			&op->o_req_ndn, NULL );
+	if ( !lc ) {
+ 		send_ldap_result( op, rs );
+		return -1;
+	}
+	
+	if ( !meta_back_dobind( lc, op ) ) {
+		rs->sr_err = LDAP_OTHER;
+ 		send_ldap_result( op, rs );
 		return -1;
 	}
 
@@ -111,8 +109,8 @@ meta_back_compare(
 	 */
 	for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
 		char *mdn = NULL;
-		struct berval mapped_attr = ava->aa_desc->ad_cname;
-		struct berval mapped_value = ava->aa_value;
+		struct berval mapped_attr = op->oq_compare.rs_ava->aa_desc->ad_cname;
+		struct berval mapped_value = op->oq_compare.rs_ava->aa_value;
 
 		if ( lsc->candidate != META_CANDIDATE ) {
 			msgid[ i ] = -1;
@@ -124,41 +122,42 @@ meta_back_compare(
 		 */
 		switch ( rewrite_session( li->targets[ i ]->rwinfo,
 					"compareDn", 
-					dn->bv_val, conn, &mdn ) ) {
+					op->o_req_dn.bv_val, op->o_conn, &mdn ) ) {
 		case REWRITE_REGEXEC_OK:
 			if ( mdn == NULL ) {
-				mdn = ( char * )dn->bv_val;
+				mdn = ( char * )op->o_req_dn.bv_val;
 			}
 #ifdef NEW_LOGGING
 			LDAP_LOG( BACK_META, DETAIL1,
-				"[rw] compareDn: \"%s\" -> \"%s\"\n", dn->bv_val, mdn, 0 );
+				"[rw] compareDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn, 0 );
 #else /* !NEW_LOGGING */
 			Debug( LDAP_DEBUG_ARGS,
-				     	"rw> compareDn: \"%s\" -> \"%s\"\n%s",
-					dn->bv_val, mdn, "" );
+				     	"rw> compareDn: \"%s\" -> \"%s\"\n",
+					op->o_req_dn.bv_val, mdn, 0 );
 #endif /* !NEW_LOGGING */
 			break;
 		
 		case REWRITE_REGEXEC_UNWILLING:
-			send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-					NULL, "Operation not allowed",
-					NULL, NULL );
+			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rs->sr_text = "Operation not allowed";
+			send_ldap_result( op, rs );
 			return -1;
 			
 		case REWRITE_REGEXEC_ERR:
-			send_ldap_result( conn, op,  LDAP_OTHER,
-					NULL, "Rewrite error",
-					NULL, NULL );
+			rs->sr_err = LDAP_OTHER;
+			rs->sr_text = "Rewrite error";
+			send_ldap_result( op, rs );
 			return -1;
 		}
 
 		/*
 		 * if attr is objectClass, try to remap the value
 		 */
-		if ( ava->aa_desc == slap_schema.si_ad_objectClass ) {
+		if ( op->oq_compare.rs_ava->aa_desc == slap_schema.si_ad_objectClass ) {
 			ldap_back_map( &li->targets[ i ]->oc_map,
-					&ava->aa_value, &mapped_value,
-					BACKLDAP_MAP );
+					&op->oq_compare.rs_ava->aa_value,
+					&mapped_value, BACKLDAP_MAP );
 
 			if ( mapped_value.bv_val == NULL || mapped_value.bv_val[0] == '\0' ) {
 				continue;
@@ -168,8 +167,8 @@ meta_back_compare(
 		 */
 		} else {
 			ldap_back_map( &li->targets[ i ]->at_map,
-				&ava->aa_desc->ad_cname, &mapped_attr,
-				BACKLDAP_MAP );
+				&op->oq_compare.rs_ava->aa_desc->ad_cname,
+				&mapped_attr, BACKLDAP_MAP );
 			if ( mapped_attr.bv_val == NULL || mapped_attr.bv_val[0] == '\0' ) {
 				continue;
 			}
@@ -182,13 +181,13 @@ meta_back_compare(
 		 */
 		msgid[ i ] = ldap_compare( lc->conns[ i ].ld, mdn,
 				mapped_attr.bv_val, mapped_value.bv_val );
-		if ( mdn != dn->bv_val ) {
+		if ( mdn != op->o_req_dn.bv_val ) {
 			free( mdn );
 		}
-		if ( mapped_attr.bv_val != ava->aa_desc->ad_cname.bv_val ) {
+		if ( mapped_attr.bv_val != op->oq_compare.rs_ava->aa_desc->ad_cname.bv_val ) {
 			free( mapped_attr.bv_val );
 		}
-		if ( mapped_value.bv_val != ava->aa_value.bv_val ) {
+		if ( mapped_value.bv_val != op->oq_compare.rs_ava->aa_value.bv_val ) {
 			free( mapped_value.bv_val );
 		}
 
@@ -208,8 +207,8 @@ meta_back_compare(
 		 * FIXME: should we check for abandon?
 		 */
 		for ( i = 0, lsc = lc->conns; !META_LAST(lsc); lsc++, i++ ) {
-			int lrc;
-			LDAPMessage *res = NULL;
+			int		lrc;
+			LDAPMessage	*res = NULL;
 
 			if ( msgid[ i ] == -1 ) {
 				continue;
@@ -226,6 +225,7 @@ meta_back_compare(
 					ldap_msgfree( res );
 				}
 				continue;
+
 			} else if ( lrc == LDAP_RES_COMPARE ) {
 				if ( count > 0 ) {
 					rres = LDAP_OTHER;
@@ -243,7 +243,7 @@ meta_back_compare(
 					 * sending to cache ...
 					 */
 					if ( li->cache.ttl != META_DNCACHE_DISABLED ) {
-						( void )meta_dncache_update_entry( &li->cache, ndn, i );
+						( void )meta_dncache_update_entry( &li->cache, &op->o_req_ndn, i );
 					}
 
 					count++;
@@ -308,39 +308,44 @@ finish:;
 		 * and none was successful
 		 */
 		switch ( rewrite_session( li->targets[ last ]->rwinfo,
-					"matchedDn", match, conn, &mmatch ) ) {
+					"matchedDn", match, op->o_conn,
+					&mmatch ) ) {
 		case REWRITE_REGEXEC_OK:
 			if ( mmatch == NULL ) {
 				mmatch = ( char * )match;
 			}
 #ifdef NEW_LOGGING
 			LDAP_LOG( BACK_META, DETAIL1,
-				"[rw] matchedDn: \"%s\" -> \"%s\"\n", match, mmatch, 0 );
+					"[rw] matchedDn: \"%s\" -> \"%s\"\n",
+					match, mmatch, 0 );
 #else /* !NEW_LOGGING */
 			Debug( LDAP_DEBUG_ARGS, "rw> matchedDn:"
-					" \"%s\" -> \"%s\"\n%s",
-					match, mmatch, "" );
+					" \"%s\" -> \"%s\"\n",
+					match, mmatch, 0 );
 #endif /* !NEW_LOGGING */
 			break;
 			
 		
 		case REWRITE_REGEXEC_UNWILLING:
-			send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-					NULL, "Operation not allowed",
-					NULL, NULL );
+			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rs->sr_text = "Operation not allowed";
+			send_ldap_result( op, rs );
 			rc = -1;
 			goto cleanup;
 			
 		case REWRITE_REGEXEC_ERR:
-			send_ldap_result( conn, op, LDAP_OTHER,
-					NULL, "Rewrite error",
-					NULL, NULL );
+			rs->sr_err = LDAP_OTHER;
+			rs->sr_text = "Rewrite error";
+			send_ldap_result( op, rs );
 			rc = -1;
 			goto cleanup;
 		}
 	}
 
-	send_ldap_result( conn, op, rres, mmatch, err, NULL, NULL );
+	rs->sr_err = rres;
+	rs->sr_matched = mmatch;
+	send_ldap_result( op, rs );
+	rs->sr_matched = NULL;
 
 cleanup:;
 	if ( match != NULL ) {
diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c
index 8289819a88..58dc1f0448 100644
--- a/servers/slapd/back-meta/conn.c
+++ b/servers/slapd/back-meta/conn.c
@@ -221,13 +221,13 @@ metaconn_free(
  */
 static int
 init_one_conn(
-		Connection *conn, 
-		Operation *op, 
-		struct metatarget *lt, 
-		struct metasingleconn *lsc
+		Operation *op,
+		SlapReply *rs,
+		struct metatarget	*lt, 
+		struct metasingleconn	*lsc
 		)
 {
-	int err, vers;
+	int		err, vers;
 
 	/*
 	 * Already init'ed
@@ -248,54 +248,66 @@ init_one_conn(
 	 * Set LDAP version. This will always succeed: If the client
 	 * bound with a particular version, then so can we.
 	 */
-	vers = conn->c_protocol;
+	vers = op->o_conn->c_protocol;
 	ldap_set_option( lsc->ld, LDAP_OPT_PROTOCOL_VERSION, &vers );
+	/* FIXME: configurable? */
+	ldap_set_option(lsc->ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
 
 	/*
 	 * Sets a cookie for the rewrite session
 	 */
-	( void )rewrite_session_init( lt->rwinfo, conn );
+	( void )rewrite_session_init( lt->rwinfo, op->o_conn );
 
 	/*
 	 * If the connection dn is not null, an attempt to rewrite it is made
 	 */
-	if ( conn->c_dn.bv_len != 0 ) {
+	if ( op->o_conn->c_dn.bv_len != 0 ) {
 		
 		/*
 		 * Rewrite the bind dn if needed
 		 */
 		lsc->bound_dn.bv_val = NULL;
 		switch ( rewrite_session( lt->rwinfo, "bindDn",
-					conn->c_dn.bv_val, conn, 
+					op->o_conn->c_dn.bv_val, op->o_conn, 
 					&lsc->bound_dn.bv_val ) ) {
 		case REWRITE_REGEXEC_OK:
 			if ( lsc->bound_dn.bv_val == NULL ) {
-				ber_dupbv( &lsc->bound_dn, &conn->c_dn );
+				ber_dupbv( &lsc->bound_dn, &op->o_conn->c_dn );
 			}
 #ifdef NEW_LOGGING
 			LDAP_LOG( BACK_META, DETAIL1,
 				"[rw] bindDn: \"%s\" -> \"%s\"\n",
-				conn->c_dn.bv_val, lsc->bound_dn.bv_val, 0 );
+				op->o_conn->c_dn.bv_val,
+				lsc->bound_dn.bv_val, 0 );
 #else /* !NEW_LOGGING */
 			Debug( LDAP_DEBUG_ARGS,
 				       	"rw> bindDn: \"%s\" -> \"%s\"\n",
-					conn->c_dn.bv_val, lsc->bound_dn.bv_val, 0 );
+					op->o_conn->c_dn.bv_val,
+					lsc->bound_dn.bv_val, 0 );
 #endif /* !NEW_LOGGING */
 			break;
 			
 		case REWRITE_REGEXEC_UNWILLING:
+			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rs->sr_text = "Operation not allowed";
+#if 0
 			send_ldap_result( conn, op,
 					LDAP_UNWILLING_TO_PERFORM,
 					NULL, "Operation not allowed",
 					NULL, NULL );
-			return LDAP_UNWILLING_TO_PERFORM;
+#endif
+			return rs->sr_err;
 			
 		case REWRITE_REGEXEC_ERR:
+			rs->sr_err = LDAP_OTHER;
+			rs->sr_text = "Rewrite error";
+#if 0
 			send_ldap_result( conn, op,
 					LDAP_OTHER,
 					NULL, "Rewrite error",
 					NULL, NULL );
-			return LDAP_OTHER;
+#endif
+			return rs->sr_err;
 		}
 
 		assert( lsc->bound_dn.bv_val );
@@ -328,8 +340,8 @@ init_one_conn(
 struct metaconn *
 meta_back_getconn(
 		struct metainfo *li,
-	       	Connection 	*conn,
 	       	Operation 	*op,
+		SlapReply	*rs,
 		int 		op_type,
 		struct berval	*ndn,
 		int 		*candidate )
@@ -339,7 +351,7 @@ meta_back_getconn(
 	int new_conn = 0;
 
 	/* Searches for a metaconn in the avl tree */
-	lc_curr.conn = conn;
+	lc_curr.conn = op->o_conn;
 	ldap_pvt_thread_mutex_lock( &li->conn_mutex );
 	lc = (struct metaconn *)avl_find( li->conntree, 
 		(caddr_t)&lc_curr, meta_back_conn_cmp );
@@ -348,7 +360,7 @@ meta_back_getconn(
 	/* Looks like we didn't get a bind. Open a new session... */
 	if ( !lc ) {
 		lc = metaconn_alloc( li->ntargets );
-		lc->conn = conn;
+		lc->conn = op->o_conn;
 		new_conn = 1;
 	}
 
@@ -377,9 +389,7 @@ meta_back_getconn(
 				metaconn_free( lc );
 			}
 
-			send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
-				NULL, "", NULL, NULL );
-
+			rs->sr_err = LDAP_NO_SUCH_OBJECT;
 			return NULL;
 		}
 				
@@ -403,7 +413,7 @@ meta_back_getconn(
 		 * also init'd. In case of error, init_one_conn
 		 * sends the appropriate result.
 		 */
-		err = init_one_conn( conn, op, li->targets[ i ],
+		err = init_one_conn( op, rs, li->targets[ i ],
 				&lc->conns[ i ] );
 		if ( err != LDAP_SUCCESS ) {
 		
@@ -433,7 +443,7 @@ meta_back_getconn(
 			 * The target is activated; if needed, it is
 			 * also init'd
 			 */
-			int lerr = init_one_conn( conn, op, li->targets[ i ],
+			int lerr = init_one_conn( op, rs, li->targets[ i ],
 					&lc->conns[ i ] );
 			if ( lerr != LDAP_SUCCESS ) {
 				
@@ -460,7 +470,7 @@ meta_back_getconn(
 				 * The target is activated; if needed, it is
 				 * also init'd
 				 */
-				int lerr = init_one_conn( conn, op,
+				int lerr = init_one_conn( op, rs,
 						li->targets[ i ],
 						&lc->conns[ i ] );
 				if ( lerr != LDAP_SUCCESS ) {
@@ -478,6 +488,10 @@ meta_back_getconn(
 		}
 	}
 
+	/* clear out init_one_conn non-fatal errors */
+	rs->sr_err = LDAP_SUCCESS;
+	rs->sr_text = NULL;
+
 	if ( new_conn ) {
 		
 		/*
@@ -506,8 +520,8 @@ meta_back_getconn(
 		 * Err could be -1 in case a duplicate metaconn is inserted
 		 */
 		if ( err != 0 ) {
-			send_ldap_result( conn, op, LDAP_OTHER,
-			NULL, "Internal server error", NULL, NULL );
+			rs->sr_err = LDAP_OTHER;
+			rs->sr_text = "Internal server error";
 			metaconn_free( lc );
 			return NULL;
 		}
diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c
index 22a9e569ed..bc8041e62f 100644
--- a/servers/slapd/back-meta/delete.c
+++ b/servers/slapd/back-meta/delete.c
@@ -76,26 +76,25 @@
 #include "back-meta.h"
 
 int
-meta_back_delete(
-		Backend		*be,
-		Connection	*conn,
-		Operation	*op,
-		struct berval	*dn,
-		struct berval	*ndn
-)
+meta_back_delete( Operation *op, SlapReply *rs )
 {
-	struct metainfo *li = ( struct metainfo * )be->be_private;
+	struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
 	struct metaconn *lc;
 	int candidate = -1;
 
 	char *mdn = NULL;
 
-	lc = meta_back_getconn( li, conn, op, META_OP_REQUIRE_SINGLE,
-			ndn, &candidate );
-	if ( !lc || !meta_back_dobind( lc, op )
+	lc = meta_back_getconn( li, op, rs, META_OP_REQUIRE_SINGLE,
+			&op->o_req_ndn, &candidate );
+	if ( !lc ) {
+ 		send_ldap_result( op, rs );
+		return -1;
+	}
+	
+	if ( !meta_back_dobind( lc, op )
 			|| !meta_back_is_valid( lc, candidate ) ) {
- 		send_ldap_result( conn, op, LDAP_OTHER,
- 				NULL, NULL, NULL, NULL );
+		rs->sr_err = LDAP_OTHER;
+ 		send_ldap_result( op, rs );
 		return -1;
 	}
 
@@ -103,37 +102,41 @@ meta_back_delete(
 	 * Rewrite the compare dn, if needed
 	 */
 	switch ( rewrite_session( li->targets[ candidate ]->rwinfo,
-				"deleteDn", dn->bv_val, conn, &mdn ) ) {
+				"deleteDn", op->o_req_dn.bv_val,
+				op->o_conn, &mdn ) ) {
 	case REWRITE_REGEXEC_OK:
 		if ( mdn == NULL ) {
-			mdn = ( char * )dn->bv_val;
+			mdn = ( char * )op->o_req_dn.bv_val;
 		}
 #ifdef NEW_LOGGING
 		LDAP_LOG( BACK_META, DETAIL1,
-			"[rw] deleteDn: \"%s\" -> \"%s\"\n", dn->bv_val, mdn, 0 );
+				"[rw] deleteDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn, 0 );
 #else /* !NEW_LOGGING */
-		Debug( LDAP_DEBUG_ARGS, "rw> deleteDn: \"%s\" -> \"%s\"\n%s",
-				dn->bv_val, mdn, "" );
+		Debug( LDAP_DEBUG_ARGS, "rw> deleteDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn, 0 );
 #endif /* !NEW_LOGGING */
 		break;
 		
 	case REWRITE_REGEXEC_UNWILLING:
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-				NULL, "Operation not allowed", NULL, NULL );
+		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+		rs->sr_text = "Operation not allowed";
+		send_ldap_result( op, rs );
 		return -1;
 
 	case REWRITE_REGEXEC_ERR:
-		send_ldap_result( conn, op, LDAP_OTHER,
-				NULL, "Rewrite error", NULL, NULL );
+		rs->sr_err = LDAP_OTHER;
+		rs->sr_text = "Rewrite error";
+		send_ldap_result( op, rs );
 		return -1;
 	}
 	
 	ldap_delete_s( lc->conns[ candidate ].ld, mdn );
 
-	if ( mdn != dn->bv_val ) {
+	if ( mdn != op->o_req_dn.bv_val ) {
 		free( mdn );
 	}
 	
-	return meta_back_op_result( lc, op );
+	return meta_back_op_result( lc, op, rs );
 }
 
diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c
index 0480d4936b..e8f4487174 100644
--- a/servers/slapd/back-meta/modify.c
+++ b/servers/slapd/back-meta/modify.c
@@ -76,82 +76,82 @@
 #include "back-meta.h"
 
 int
-meta_back_modify(
-		Backend	*be,
-		Connection	*conn,
-		Operation	*op,
-		struct berval	*dn,
-		struct berval	*ndn,
-		Modifications	*modlist
-)
+meta_back_modify( Operation *op, SlapReply *rs )
 {
-	struct metainfo	*li = ( struct metainfo * )be->be_private;
-	struct metaconn *lc;
-	LDAPMod **modv;
-	LDAPMod *mods;
-	Modifications *ml;
-	int candidate = -1, i;
-	char *mdn;
-	struct berval mapped;
-
-	lc = meta_back_getconn( li, conn, op, META_OP_REQUIRE_SINGLE,
-			ndn, &candidate );
-	if ( !lc || !meta_back_dobind( lc, op )
+	struct metainfo		*li = ( struct metainfo * )op->o_bd->be_private;
+	struct metaconn 	*lc;
+	int			rc = 0;
+	LDAPMod			**modv = NULL;
+	LDAPMod			*mods = NULL;
+	Modifications		*ml;
+	int			candidate = -1, i;
+	char			*mdn;
+	struct berval		mapped;
+
+	lc = meta_back_getconn( li, op, rs, META_OP_REQUIRE_SINGLE,
+			&op->o_req_ndn, &candidate );
+	if ( !lc ) {
+		rc = -1;
+		goto cleanup;
+	}
+	
+	if ( !meta_back_dobind( lc, op )
 			|| !meta_back_is_valid( lc, candidate ) ) {
- 		send_ldap_result( conn, op, LDAP_OTHER,
- 				NULL, NULL, NULL, NULL );
-		return -1;
+		rs->sr_err = LDAP_OTHER;
+		rc = -1;
+		goto cleanup;
 	}
 
 	/*
 	 * Rewrite the modify dn, if needed
 	 */
 	switch ( rewrite_session( li->targets[ candidate ]->rwinfo,
-				"modifyDn", dn->bv_val, conn, &mdn ) ) {
+				"modifyDn", op->o_req_dn.bv_val,
+				op->o_conn, &mdn ) ) {
 	case REWRITE_REGEXEC_OK:
 		if ( mdn == NULL ) {
-			mdn = ( char * )dn->bv_val;
+			mdn = ( char * )op->o_req_dn.bv_val;
 		}
 #ifdef NEW_LOGGING
 		LDAP_LOG( BACK_META, DETAIL1,
-			"[rw] modifyDn: \"%s\" -> \"%s\"\n", dn->bv_val, mdn, 0 );
+				"[rw] modifyDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn, 0 );
 #else /* !NEW_LOGGING */
-		Debug( LDAP_DEBUG_ARGS, "rw> modifyDn: \"%s\" -> \"%s\"\n%s",
-				dn->bv_val, mdn, "" );
+		Debug( LDAP_DEBUG_ARGS, "rw> modifyDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn, 0 );
 #endif /* !NEW_LOGGING */
 		break;
 		
 	case REWRITE_REGEXEC_UNWILLING:
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-				NULL, "Operation not allowed", NULL, NULL );
-		return -1;
+		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+		rs->sr_text = "Operation not allowed";
+		rc = -1;
+		goto cleanup;
 
 	case REWRITE_REGEXEC_ERR:
-		send_ldap_result( conn, op, LDAP_OTHER,
-				NULL, "Rewrite error", NULL, NULL );
-		return -1;
+		rs->sr_err = LDAP_OTHER;
+		rs->sr_text = "Rewrite error";
+		rc = -1;
+		goto cleanup;
 	}
 
-	for ( i = 0, ml = modlist; ml; i++ ,ml = ml->sml_next )
+	for ( i = 0, ml = op->oq_modify.rs_modlist; ml; i++ ,ml = ml->sml_next )
 		;
 
 	mods = ch_malloc( sizeof( LDAPMod )*i );
 	if ( mods == NULL ) {
-		if ( mdn != dn->bv_val ) {
-			free( mdn );
-		}
-		return -1;
+		rs->sr_err = LDAP_NO_MEMORY;
+		rc = -1;
+		goto cleanup;
 	}
 	modv = ( LDAPMod ** )ch_malloc( ( i + 1 )*sizeof( LDAPMod * ) );
 	if ( modv == NULL ) {
-		free( mods );
-		if ( mdn != dn->bv_val ) {
-			free( mdn );
-		}
-		return -1;
+		rs->sr_err = LDAP_NO_MEMORY;
+		rc = -1;
+		goto cleanup;
 	}
 
-	for ( i = 0, ml = modlist; ml; ml = ml->sml_next ) {
+	for ( i = 0, ml = op->oq_modify.rs_modlist; ml; ml = ml->sml_next ) {
 		int j;
 
 		if ( ml->sml_desc->ad_type->sat_no_user_mod  ) {
@@ -178,7 +178,7 @@ meta_back_modify(
 					SLAPD_DN_SYNTAX ) == 0 ) {
 			ldap_dnattr_rewrite(
 				li->targets[ candidate ]->rwinfo,
-				ml->sml_bvalues, conn );
+				ml->sml_bvalues, op->o_conn );
 		}
 
 		if ( ml->sml_bvalues != NULL ){
@@ -199,13 +199,25 @@ meta_back_modify(
 
 	ldap_modify_s( lc->conns[ candidate ].ld, mdn, modv );
 
-	if ( mdn != dn->bv_val ) {
+cleanup:;
+	if ( mdn != op->o_req_dn.bv_val ) {
 		free( mdn );
 	}
-	for ( i=0; modv[ i ]; i++)
-		free( modv[ i ]->mod_bvalues );
+	if ( modv != NULL ) {
+		for ( i = 0; modv[ i ]; i++) {
+			free( modv[ i ]->mod_bvalues );
+		}
+	}
 	free( mods );
 	free( modv );
-	return meta_back_op_result( lc, op );
+	
+	if ( rc == 0 ) {
+		return meta_back_op_result( lc, op, rs ) == LDAP_SUCCESS
+			? 0 : 1;
+	} /* else */
+
+	send_ldap_result( op, rs );
+
+	return rc;
 }
 
diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c
index 34cfebfe96..79ab4ec477 100644
--- a/servers/slapd/back-meta/modrdn.c
+++ b/servers/slapd/back-meta/modrdn.c
@@ -76,7 +76,8 @@
 #include "back-meta.h"
 
 int
-meta_back_modrdn(
+meta_back_modrdn( Operation *op, SlapReply *rs )
+		/*
 		Backend		*be,
 		Connection	*conn,
 		Operation	*op,
@@ -87,28 +88,34 @@ meta_back_modrdn(
 		int		deleteoldrdn,
 		struct berval	*newSuperior,
 		struct berval	*nnewSuperior
-)
+) */
 {
-	struct metainfo *li = ( struct metainfo * )be->be_private;
-	struct metaconn *lc;
-	int candidate = -1;
-
-	char *mdn = NULL, *mnewSuperior = NULL;
+	struct metainfo		*li = ( struct metainfo * )op->o_bd->be_private;
+	struct metaconn		*lc;
+	int			rc = 0;
+	int			candidate = -1;
+	char			*mdn = NULL,
+				*mnewSuperior = NULL;
+
+	lc = meta_back_getconn( li, op, rs, META_OP_REQUIRE_SINGLE,
+			&op->o_req_ndn, &candidate );
+	if ( !lc ) {
+		rc = -1;
+		goto cleanup;
+	}
 
-	lc = meta_back_getconn( li, conn, op, META_OP_REQUIRE_SINGLE,
-			ndn, &candidate );
-	if ( !lc || !meta_back_dobind( lc, op ) 
+	if ( !meta_back_dobind( lc, op ) 
 			|| !meta_back_is_valid( lc, candidate ) ) {
- 		send_ldap_result( conn, op, LDAP_OTHER,
- 				NULL, NULL, NULL, NULL );
-		return -1;
+		rs->sr_err = LDAP_OTHER;
+		rc = -1;
+		goto cleanup;
 	}
 
-	if ( newSuperior ) {
+	if ( op->oq_modrdn.rs_newSup ) {
 		int nsCandidate, version = LDAP_VERSION3;
 
 		nsCandidate = meta_back_select_unique_candidate( li,
-				newSuperior );
+				op->oq_modrdn.rs_newSup );
 
 		if ( nsCandidate != candidate ) {
 			/*
@@ -123,9 +130,9 @@ meta_back_modrdn(
 			/*
 			 * FIXME: is this the correct return code?
 			 */
-			send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-					NULL, NULL, NULL, NULL );
-			return -1;
+			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rc = -1;
+			goto cleanup;
 		}
 
 		ldap_set_option( lc->conns[ nsCandidate ].ld,
@@ -136,34 +143,36 @@ meta_back_modrdn(
 	 	 */
 		switch ( rewrite_session( li->targets[ nsCandidate ]->rwinfo,
 					"newSuperiorDn",
-					newSuperior->bv_val, 
-					conn, 
+					op->oq_modrdn.rs_newSup->bv_val, 
+					op->o_conn, 
 					&mnewSuperior ) ) {
 		case REWRITE_REGEXEC_OK:
 			if ( mnewSuperior == NULL ) {
-				mnewSuperior = ( char * )newSuperior;
+				mnewSuperior = ( char * )op->oq_modrdn.rs_newSup;
 			}
 #ifdef NEW_LOGGING
 			LDAP_LOG( BACK_META, DETAIL1,
 				"[rw] newSuperiorDn: \"%s\" -> \"%s\"\n",
-				newSuperior, mnewSuperior, 0 );
+				op->oq_modrdn.rs_newSup, mnewSuperior, 0 );
 #else /* !NEW_LOGGING */
 			Debug( LDAP_DEBUG_ARGS, "rw> newSuperiorDn:"
-					" \"%s\" -> \"%s\"\n%s",
-					newSuperior->bv_val, mnewSuperior, "" );
+					" \"%s\" -> \"%s\"\n",
+					op->oq_modrdn.rs_newSup->bv_val,
+					mnewSuperior, 0 );
 #endif /* !NEW_LOGGING */
 			break;
 
 		case REWRITE_REGEXEC_UNWILLING:
-			send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-					NULL, "Operation not allowed", 
-					NULL, NULL );
-			return -1;
+			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rs->sr_text = "Operation not allowed";
+			rc = -1;
+			goto cleanup;
 
 		case REWRITE_REGEXEC_ERR:
-			send_ldap_result( conn, op, LDAP_OTHER,
-					NULL, "Rewrite error", NULL, NULL );
-			return -1;
+			rs->sr_err = LDAP_OTHER;
+			rs->sr_text = "Rewrite error";
+			rc = -1;
+			goto cleanup;
 		}
 	}
 
@@ -171,41 +180,56 @@ meta_back_modrdn(
 	 * Rewrite the modrdn dn, if required
 	 */
 	switch ( rewrite_session( li->targets[ candidate ]->rwinfo,
-				"modrDn", dn->bv_val, conn, &mdn ) ) {
+				"modrDn", op->o_req_dn.bv_val,
+				op->o_conn, &mdn ) ) {
 	case REWRITE_REGEXEC_OK:
 		if ( mdn == NULL ) {
-			mdn = ( char * )dn->bv_val;
+			mdn = ( char * )op->o_req_dn.bv_val;
 		}
 #ifdef NEW_LOGGING
 		LDAP_LOG( BACK_META, DETAIL1,
-			"[rw] modrDn: \"%s\" -> \"%s\"\n", dn->bv_val, mdn, 0 );
+				"[rw] modrDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn, 0 );
 #else /* !NEW_LOGGING */
-		Debug( LDAP_DEBUG_ARGS, "rw> modrDn: \"%s\" -> \"%s\"\n%s",
-				dn->bv_val, mdn, "" );
+		Debug( LDAP_DEBUG_ARGS, "rw> modrDn: \"%s\" -> \"%s\"\n",
+				op->o_req_dn.bv_val, mdn, 0 );
 #endif /* !NEW_LOGGING */
 		break;
 		
 	case REWRITE_REGEXEC_UNWILLING:
-		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-				NULL, "Operation not allowed", NULL, NULL );
-		return -1;
+		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+		rs->sr_text = "Operation not allowed";
+		rc = -1;
+		goto cleanup;
 
 	case REWRITE_REGEXEC_ERR:
-		send_ldap_result( conn, op, LDAP_OTHER,
-				NULL, "Rewrite error", NULL, NULL );
-		return -1;
+		rs->sr_err = LDAP_OTHER;
+		rs->sr_text = "Rewrite error";
+		rc = -1;
+		goto cleanup;
 	}
 
-	ldap_rename2_s( lc->conns[ candidate ].ld, mdn, newrdn->bv_val,
-			mnewSuperior, deleteoldrdn );
+	ldap_rename2_s( lc->conns[ candidate ].ld, mdn,
+			op->oq_modrdn.rs_newrdn.bv_val,
+			mnewSuperior, op->oq_modrdn.rs_deleteoldrdn );
 
-	if ( mdn != dn->bv_val ) {
+cleanup:;
+	if ( mdn != op->o_req_dn.bv_val ) {
 		free( mdn );
 	}
-	if ( mnewSuperior != NULL && mnewSuperior != newSuperior->bv_val ) {
+	
+	if ( mnewSuperior != NULL 
+			&& mnewSuperior != op->oq_modrdn.rs_newSup->bv_val ) {
 		free( mnewSuperior );
 	}
-	
-	return meta_back_op_result( lc, op );
+
+	if ( rc == 0 ) {
+		return meta_back_op_result( lc, op, rs ) == LDAP_SUCCESS
+			? 0 : 1;
+	} /* else */
+
+	send_ldap_result( op, rs );
+	return rc;
+
 }
 
diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c
index 15ebc56946..78a297194a 100644
--- a/servers/slapd/back-meta/search.c
+++ b/servers/slapd/back-meta/search.c
@@ -82,13 +82,11 @@
 
 static int
 meta_send_entry(
-		Backend		*be,
 		Operation 	*op,
+		SlapReply	*rs,
 		struct metaconn	*lc,
 		int 		i,
-		LDAPMessage 	*e,
-		AttributeName 	*attrs,
-		int 		attrsonly
+		LDAPMessage 	*e
 );
 
 static int
@@ -98,23 +96,9 @@ is_one_level_rdn(
 );
 
 int
-meta_back_search(
-		Backend		*be,
-		Connection	*conn,
-		Operation	*op,
-		struct berval	*base,
-		struct berval	*nbase,
-		int		scope,
-		int		deref,
-		int		slimit,
-		int		tlimit,
-		Filter		*filter,
-		struct berval	*filterstr,
-		AttributeName	*attrs,
-		int		attrsonly
-)
+meta_back_search( Operation *op, SlapReply *rs )
 {
-	struct metainfo	*li = ( struct metainfo * )be->be_private;
+	struct metainfo	*li = ( struct metainfo * )op->o_bd->be_private;
 	struct metaconn *lc;
 	struct metasingleconn *lsc;
 	struct timeval	tv = { 0, 0 };
@@ -133,9 +117,16 @@ meta_back_search(
 	cache_manager*  cm = li->cm;
 
  	if (cm->caching) {
- 		return meta_back_cache_search(be, conn, op, base, nbase, 
-					scope, deref, slimit, tlimit,
-					filter, filterstr, attrs, attrsonly); 
+ 		return meta_back_cache_search(op->o_bd, op->o_conn, op,
+				&op->o_req_dn, &op->o_req_ndn, 
+				op->oq_search.rs_scope,
+				op->oq_search.rs_deref,
+				op->oq_search.rs_slimit,
+				op->oq_search.rs_tlimit,
+				op->oq_search.rs_filter,
+				&op->oq_search.rs_filterstr,
+				op->oq_search.rs_attrs,
+				op->oq_search.rs_attrsonly); 
 	}
 #endif /* LDAP_CACHING */
 	
@@ -145,11 +136,16 @@ meta_back_search(
 	 * FIXME: in case of values return filter, we might want
 	 * to map attrs and maybe rewrite value
 	 */
-	lc = meta_back_getconn( li, conn, op, META_OP_ALLOW_MULTIPLE, 
-			nbase, NULL );
-	if ( !lc || !meta_back_dobind( lc, op ) ) {
- 		send_ldap_result( conn, op, LDAP_OTHER,
- 				NULL, NULL, NULL, NULL );
+	lc = meta_back_getconn( li, op, rs, META_OP_ALLOW_MULTIPLE, 
+			&op->o_req_ndn, NULL );
+	if ( !lc ) {
+ 		send_ldap_result( op, rs );
+		return -1;
+	}
+
+	if ( !meta_back_dobind( lc, op ) ) {
+		rs->sr_err = LDAP_OTHER;
+ 		send_ldap_result( op, rs );
 		return -1;
 	}
 
@@ -158,31 +154,31 @@ meta_back_search(
 	 */
 	msgid = ch_calloc( sizeof( int ), li->ntargets );
 	if ( msgid == NULL ) {
-		send_ldap_result( conn, op, LDAP_OTHER,
-				NULL, NULL, NULL, NULL );
+		rs->sr_err = LDAP_OTHER;
+ 		send_ldap_result( op, rs );
 		return -1;
 	}
 	
 	/* if not root, get appropriate limits */
-	if ( be_isroot( be, &op->o_ndn ) ) {
+	if ( be_isroot( op->o_bd, &op->o_ndn ) ) {
 		isroot = 1;
 	} else {
-		( void ) get_limits( be, &op->o_ndn, &limit );
+		( void ) get_limits( op->o_bd, &op->o_ndn, &limit );
 	}
 
 	/* if no time limit requested, rely on remote server limits */
 	/* if requested limit higher than hard limit, abort */
-	if ( !isroot && tlimit > limit->lms_t_hard ) {
+	if ( !isroot && op->oq_search.rs_tlimit > limit->lms_t_hard ) {
 		/* no hard limit means use soft instead */
 		if ( limit->lms_t_hard == 0
 				&& limit->lms_t_soft > -1
-				&& tlimit > limit->lms_t_soft ) {
-			tlimit = limit->lms_t_soft;
+				&& op->oq_search.rs_tlimit > limit->lms_t_soft ) {
+			op->oq_search.rs_tlimit = limit->lms_t_soft;
 			
 		/* positive hard limit means abort */
 		} else if ( limit->lms_t_hard > 0 ) {
-			send_ldap_result( conn, op, LDAP_ADMINLIMIT_EXCEEDED,
-					NULL, NULL, NULL, NULL );
+			rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
+			send_ldap_result( op, rs );
 			rc = 0;
 			goto finish;
 		}
@@ -192,17 +188,17 @@ meta_back_search(
 	
 	/* if no size limit requested, rely on remote server limits */
 	/* if requested limit higher than hard limit, abort */
-	if ( !isroot && slimit > limit->lms_s_hard ) {
+	if ( !isroot && op->oq_search.rs_slimit > limit->lms_s_hard ) {
 		/* no hard limit means use soft instead */
 		if ( limit->lms_s_hard == 0
 				&& limit->lms_s_soft > -1
-				&& slimit > limit->lms_s_soft ) {
-			slimit = limit->lms_s_soft;
+				&& op->oq_search.rs_slimit > limit->lms_s_soft ) {
+			op->oq_search.rs_slimit = limit->lms_s_soft;
 			
 		/* positive hard limit means abort */
 		} else if ( limit->lms_s_hard > 0 ) {
-			send_ldap_result( conn, op, LDAP_ADMINLIMIT_EXCEEDED,
-					NULL, NULL, NULL, NULL );
+			rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
+			send_ldap_result( op, rs );
 			rc = 0;
 			goto finish;
 		}
@@ -214,8 +210,8 @@ meta_back_search(
 	 * Inits searches
 	 */
 	for ( i = 0, lsc = lc->conns; !META_LAST(lsc); ++i, ++lsc ) {
-		char 	*realbase = ( char * )base->bv_val;
-		int 	realscope = scope;
+		char 	*realbase = ( char * )op->o_req_dn.bv_val;
+		int 	realscope = op->oq_search.rs_scope;
 		ber_len_t suffixlen;
 		char	**mapped_attrs;
 
@@ -225,25 +221,25 @@ meta_back_search(
 		}
 
 		/* should we check return values? */
-		if ( deref != -1 ) {
+		if ( op->oq_search.rs_deref != -1 ) {
 			ldap_set_option( lsc->ld, LDAP_OPT_DEREF,
-					( void * )&deref);
+					( void * )&op->oq_search.rs_deref);
 		}
-		if ( tlimit != -1 ) {
+		if ( op->oq_search.rs_tlimit != -1 ) {
 			ldap_set_option( lsc->ld, LDAP_OPT_TIMELIMIT,
-					( void * )&tlimit);
+					( void * )&op->oq_search.rs_tlimit);
 		}
-		if ( slimit != -1 ) {
+		if ( op->oq_search.rs_slimit != -1 ) {
 			ldap_set_option( lsc->ld, LDAP_OPT_SIZELIMIT,
-					( void * )&slimit);
+					( void * )&op->oq_search.rs_slimit);
 		}
 
 		/*
 		 * modifies the base according to the scope, if required
 		 */
 		suffixlen = li->targets[ i ]->suffix.bv_len;
-		if ( suffixlen > nbase->bv_len ) {
-			switch ( scope ) {
+		if ( suffixlen > op->o_req_ndn.bv_len ) {
+			switch ( op->oq_search.rs_scope ) {
 			case LDAP_SCOPE_SUBTREE:
 				/*
 				 * make the target suffix the new base
@@ -252,7 +248,7 @@ meta_back_search(
 				 * the suffix of the target.
 				 */
 				if ( dnIsSuffix( &li->targets[ i ]->suffix,
-						nbase ) ) {
+						&op->o_req_ndn ) ) {
 					realbase = li->targets[ i ]->suffix.bv_val;
 				} else {
 					/*
@@ -265,8 +261,8 @@ meta_back_search(
 
 			case LDAP_SCOPE_ONELEVEL:
 				if ( is_one_level_rdn( li->targets[ i ]->suffix.bv_val,
-						suffixlen - nbase->bv_len - 1 ) 
-			&& dnIsSuffix( &li->targets[ i ]->suffix, nbase ) ) {
+						suffixlen - op->o_req_ndn.bv_len - 1 ) 
+			&& dnIsSuffix( &li->targets[ i ]->suffix, &op->o_req_ndn ) ) {
 					/*
 					 * if there is exactly one level,
 					 * make the target suffix the new
@@ -292,7 +288,7 @@ meta_back_search(
 		 */
 	 	switch ( rewrite_session( li->targets[ i ]->rwinfo,
 					"searchBase",
- 					realbase, conn, &mbase ) ) {
+ 					realbase, op->o_conn, &mbase ) ) {
 		case REWRITE_REGEXEC_OK:
 		if ( mbase == NULL ) {
 			mbase = realbase;
@@ -300,24 +296,25 @@ meta_back_search(
 #ifdef NEW_LOGGING
 		LDAP_LOG( BACK_META, DETAIL1,
 			"[rw] searchBase [%d]: \"%s\" -> \"%s\"\n",
-			i, base->bv_val, mbase );
+			i, op->o_req_dn.bv_val, mbase );
 #else /* !NEW_LOGGING */
 		Debug( LDAP_DEBUG_ARGS,
 			"rw> searchBase [%d]: \"%s\" -> \"%s\"\n",
-				i, base->bv_val, mbase );
+				i, op->o_req_dn.bv_val, mbase );
 #endif /* !NEW_LOGGING */
 		break;
 		
 		case REWRITE_REGEXEC_UNWILLING:
-			send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-					NULL, "Operation not allowed",
-					NULL, NULL );
+			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rs->sr_text = "Operation not allowed";
+			send_ldap_result( op, rs );
 			rc = -1;
 			goto finish;
 
 		case REWRITE_REGEXEC_ERR:
-			send_ldap_result( conn, op, LDAP_OTHER,
-					NULL, "rewrite error", NULL, NULL );
+			rs->sr_err = LDAP_OTHER;
+			rs->sr_text = "rewrite error";
+			send_ldap_result( op, rs );
 			rc = -1;
 			goto finish;
 		}
@@ -380,20 +377,23 @@ meta_back_search(
 		mfilter.bv_len = 0;
 #endif
 	
-		rc = ldap_back_filter_map_rewrite_( li->targets[ i ]->rwinfo, conn,
-			&li->targets[ i ]->at_map, &li->targets[ i ]->oc_map, 
-			filter, &mfilter, BACKLDAP_MAP );
+		rc = ldap_back_filter_map_rewrite_( li->targets[ i ]->rwinfo,
+				op->o_conn,
+				&li->targets[ i ]->at_map,
+				&li->targets[ i ]->oc_map, 
+				op->oq_search.rs_filter,
+				&mfilter, BACKLDAP_MAP );
 
 		/*
 		 * Maps required attributes
 		 */
 		mapped_attrs = ldap_back_map_attrs( &li->targets[ i ]->at_map,
-				attrs, BACKLDAP_MAP );
-		if ( mapped_attrs == NULL && attrs) {
-			for ( count=0; attrs[ count ].an_name.bv_val; count++ );
+				op->oq_search.rs_attrs, BACKLDAP_MAP );
+		if ( mapped_attrs == NULL && op->oq_search.rs_attrs) {
+			for ( count = 0; op->oq_search.rs_attrs[ count ].an_name.bv_val; count++ );
 			mapped_attrs = ch_malloc( ( count + 1 ) * sizeof(char *));
-			for ( count=0; attrs[ count ].an_name.bv_val; count++ ) {
-				mapped_attrs[ count ] = attrs[ count ].an_name.bv_val;
+			for ( count = 0; op->oq_search.rs_attrs[ count ].an_name.bv_val; count++ ) {
+				mapped_attrs[ count ] = op->oq_search.rs_attrs[ count ].an_name.bv_val;
 			}
 			mapped_attrs[ count ] = NULL;
 		}
@@ -402,12 +402,13 @@ meta_back_search(
 		 * Starts the search
 		 */
 		msgid[ i ] = ldap_search( lsc->ld, mbase, realscope,
-				mfilter.bv_val, mapped_attrs, attrsonly ); 
+				mfilter.bv_val, mapped_attrs,
+				op->oq_search.rs_attrsonly ); 
 		if ( mapped_attrs ) {
 			free( mapped_attrs );
 			mapped_attrs = NULL;
 		}
-		if ( mfilter.bv_val != filterstr->bv_val ) {
+		if ( mfilter.bv_val != op->oq_search.rs_filterstr.bv_val ) {
 			free( mfilter.bv_val );
 			mfilter.bv_val = NULL;
 		}
@@ -437,7 +438,7 @@ new_candidate:;
 	 * FIXME: we might use a queue, to balance the load 
 	 * among the candidates
 	 */
-	for ( count = 0, rc = 0; candidates > 0; ) {
+	for ( rc = 0; candidates > 0; ) {
 		int ab, gotit = 0;
 
 		/* check for abandon */
@@ -454,11 +455,11 @@ new_candidate:;
 				break;
 			}
 
-			if ( slimit > 0 && count == slimit ) {
-				send_search_result( conn, op,
-						LDAP_SIZELIMIT_EXCEEDED,
-						NULL, NULL, v2refs, NULL, 
-						count );
+			if ( op->oq_search.rs_slimit > 0
+					&& rs->sr_nentries == op->oq_search.rs_slimit ) {
+				rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+				rs->sr_v2ref = v2refs;
+				send_ldap_result( op, rs );
 				goto finish;
 			}
 
@@ -479,19 +480,16 @@ new_candidate:;
 				/* something REALLY bad happened! */
 				( void )meta_clear_unused_candidates( li,
 						lc, -1, 0 );
-				send_search_result( conn, op, LDAP_OTHER,
-						NULL, NULL, v2refs, NULL, 
-						count );
+				rs->sr_err = LDAP_OTHER;
+				rs->sr_v2ref = v2refs;
+				send_ldap_result( op, rs );
 				
 				/* anything else needs be done? */
 				goto finish;
 
 			} else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
 				e = ldap_first_entry( lsc->ld, res );
-				if ( meta_send_entry( be, op, lc, i, e, attrs,
-						attrsonly ) == LDAP_SUCCESS ) {
-					count++;
-				}
+				meta_send_entry( op, rs, lc, i, e );
 
 				/*
 				 * If scope is BASE, we need to jump out
@@ -500,7 +498,8 @@ new_candidate:;
 				 * this should correspond to the sole
 				 * entry that has the base DN
 				 */
-				if ( scope == LDAP_SCOPE_BASE && count > 0 ) {
+				if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE
+						&& rs->sr_nentries > 0 ) {
 					candidates = 0;
 					sres = LDAP_SUCCESS;
 					break;
@@ -510,8 +509,6 @@ new_candidate:;
 
 			} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
 				char		**references = NULL;
-				LDAPControl	**ctrls = NULL;
-				BerVarray	refs;
 				int		cnt;
 
 				/*
@@ -520,7 +517,7 @@ new_candidate:;
 				 */
 
 				rc = ldap_parse_reference( lsc->ld, res,
-						&references, &ctrls, 1 );
+						&references, &rs->sr_ctrls, 1 );
 
 				if ( rc != LDAP_SUCCESS ) {
 					continue;
@@ -533,25 +530,26 @@ new_candidate:;
 				for ( cnt = 0; references[ cnt ]; cnt++ )
 					/* NO OP */ ;
 				
-				refs = ch_calloc( cnt + 1, sizeof( struct berval ) );
+				rs->sr_ref = ch_calloc( cnt + 1, sizeof( struct berval ) );
 
 				for ( cnt = 0; references[ cnt ]; cnt++ ) {
-					refs[ cnt ].bv_val = references[ cnt ];
-					refs[ cnt ].bv_len = strlen( references[ cnt ] );
+					rs->sr_ref[ cnt ].bv_val = references[ cnt ];
+					rs->sr_ref[ cnt ].bv_len = strlen( references[ cnt ] );
 				}
 
 				/* ignore return value by now */
-				( void )send_search_reference( be, conn, op, 
-						NULL, refs, ctrls, &v2refs );
+				( void )send_search_reference( op, rs );
 
 				/* cleanup */
 				if ( references ) {
 					ldap_value_free( references );
-					ch_free( refs );
+					ch_free( rs->sr_ref );
+					rs->sr_ref = NULL;
 				}
 
-				if ( ctrls ) {
-					ldap_controls_free( ctrls );
+				if ( rs->sr_ctrls ) {
+					ldap_controls_free( rs->sr_ctrls );
+					rs->sr_ctrls = NULL;
 				}
 
 			} else {
@@ -611,7 +609,7 @@ new_candidate:;
 		/*
 		 * FIXME: need a strategy to handle errors
 		 */
-		rc = meta_back_op_result( lc, op );
+		rc = meta_back_op_result( lc, op, rs );
 		goto finish;
 	}
 
@@ -622,7 +620,8 @@ new_candidate:;
 	 */
 	if ( match != NULL ) {
 		switch ( rewrite_session( li->targets[ last ]->rwinfo,
-					"matchedDn", match, conn, &mmatch ) ) {
+					"matchedDn", match, op->o_conn,
+					&mmatch ) ) {
 		case REWRITE_REGEXEC_OK:
 			if ( mmatch == NULL ) {
 				mmatch = ( char * )match;
@@ -657,7 +656,13 @@ new_candidate:;
 	if ( sres == LDAP_SUCCESS && v2refs ) {
 		sres = LDAP_REFERRAL;
 	}
-	send_search_result( conn, op, sres, mmatch, err, v2refs, NULL, count );
+	rs->sr_err = sres;
+	rs->sr_matched = mmatch;
+	rs->sr_v2ref = v2refs;
+	send_ldap_result( op, rs );
+	rs->sr_matched = NULL;
+	rs->sr_v2ref = NULL;
+
 
 finish:;
 	if ( match ) {
@@ -680,16 +685,14 @@ finish:;
 
 static int
 meta_send_entry(
-		Backend 	*be,
 		Operation 	*op,
+		SlapReply	*rs,
 		struct metaconn *lc,
 		int 		target,
-		LDAPMessage 	*e,
-		AttributeName 	*attrs,
-		int 		attrsonly
+		LDAPMessage 	*e
 )
 {
-	struct metainfo 	*li = ( struct metainfo * )be->be_private;
+	struct metainfo 	*li = ( struct metainfo * )op->o_bd->be_private;
 	struct berval		a, mapped;
 	Entry 			ent;
 	BerElement 		ber = *e->lm_ber;
@@ -706,7 +709,8 @@ meta_send_entry(
 	 * Rewrite the dn of the result, if needed
 	 */
 	switch ( rewrite_session( li->targets[ target ]->rwinfo,
-				"searchResult", bdn.bv_val, lc->conn, &ent.e_name.bv_val ) ) {
+				"searchResult", bdn.bv_val, lc->conn,
+				&ent.e_name.bv_val ) ) {
 	case REWRITE_REGEXEC_OK:
 		if ( ent.e_name.bv_val == NULL ) {
 			ent.e_name = bdn;
@@ -718,7 +722,8 @@ meta_send_entry(
 				target, bdn.bv_val, ent.e_name.bv_val );
 #else /* !NEW_LOGGING */
 			Debug( LDAP_DEBUG_ARGS, "rw> searchResult[%d]: \"%s\""
- 					" -> \"%s\"\n", target, bdn.bv_val, ent.e_name.bv_val );
+ 					" -> \"%s\"\n", target, bdn.bv_val,
+					ent.e_name.bv_val );
 #endif /* !NEW_LOGGING */
 			ent.e_name.bv_len = strlen( ent.e_name.bv_val );
 		}
@@ -892,7 +897,11 @@ next_attr:;
 		*attrp = attr;
 		attrp = &attr->a_next;
 	}
-	send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, NULL );
+	rs->sr_entry = &ent;
+	rs->sr_attrs = op->oq_search.rs_attrs;
+	send_search_entry( op, rs );
+	rs->sr_entry = NULL;
+	rs->sr_attrs = NULL;
 	while ( ent.e_attrs ) {
 		attr = ent.e_attrs;
 		ent.e_attrs = attr->a_next;
-- 
GitLab