Home | History | Annotate | Line # | Download | only in back-meta
search.c revision 1.1
      1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/search.c,v 1.146.2.11 2008/04/21 17:03:23 quanah Exp $ */
      2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      3  *
      4  * Copyright 1999-2008 The OpenLDAP Foundation.
      5  * Portions Copyright 2001-2003 Pierangelo Masarati.
      6  * Portions Copyright 1999-2003 Howard Chu.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted only as authorized by the OpenLDAP
     11  * Public License.
     12  *
     13  * A copy of this license is available in the file LICENSE in the
     14  * top-level directory of the distribution or, alternatively, at
     15  * <http://www.OpenLDAP.org/license.html>.
     16  */
     17 /* ACKNOWLEDGEMENTS:
     18  * This work was initially developed by the Howard Chu for inclusion
     19  * in OpenLDAP Software and subsequently enhanced by Pierangelo
     20  * Masarati.
     21  */
     22 
     23 #include "portable.h"
     24 
     25 #include <stdio.h>
     26 
     27 #include <ac/socket.h>
     28 #include <ac/string.h>
     29 #include <ac/time.h>
     30 
     31 #include "lutil.h"
     32 #include "slap.h"
     33 #include "../back-ldap/back-ldap.h"
     34 #include "back-meta.h"
     35 #undef ldap_debug	/* silence a warning in ldap-int.h */
     36 #include "ldap_log.h"
     37 #include "../../../libraries/libldap/ldap-int.h"
     38 
     39 /* IGNORE means that target does not (no longer) participate
     40  * in the search;
     41  * NOTREADY means the search on that target has not been initialized yet
     42  */
     43 #define	META_MSGID_IGNORE	(-1)
     44 #define	META_MSGID_NEED_BIND	(-2)
     45 #define	META_MSGID_CONNECTING	(-3)
     46 
     47 static int
     48 meta_send_entry(
     49 	Operation 	*op,
     50 	SlapReply	*rs,
     51 	metaconn_t	*mc,
     52 	int 		i,
     53 	LDAPMessage 	*e );
     54 
     55 typedef enum meta_search_candidate_t {
     56 	META_SEARCH_UNDEFINED = -2,
     57 	META_SEARCH_ERR = -1,
     58 	META_SEARCH_NOT_CANDIDATE,
     59 	META_SEARCH_CANDIDATE,
     60 	META_SEARCH_BINDING,
     61 	META_SEARCH_NEED_BIND,
     62 	META_SEARCH_CONNECTING
     63 } meta_search_candidate_t;
     64 
     65 /*
     66  * meta_search_dobind_init()
     67  *
     68  * initiates bind for a candidate target of a search.
     69  */
     70 static meta_search_candidate_t
     71 meta_search_dobind_init(
     72 	Operation		*op,
     73 	SlapReply		*rs,
     74 	metaconn_t		**mcp,
     75 	int			candidate,
     76 	SlapReply		*candidates )
     77 {
     78 	metaconn_t		*mc = *mcp;
     79 	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
     80 	metatarget_t		*mt = mi->mi_targets[ candidate ];
     81 	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
     82 
     83 	struct berval		binddn = msc->msc_bound_ndn,
     84 				cred = msc->msc_cred;
     85 	int			method;
     86 
     87 	int			rc;
     88 
     89 	meta_search_candidate_t	retcode;
     90 
     91 	Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n",
     92 		op->o_log_prefix, candidate, 0 );
     93 
     94 	/*
     95 	 * all the targets are already bound as pseudoroot
     96 	 */
     97 	if ( mc->mc_authz_target == META_BOUND_ALL ) {
     98 		return META_SEARCH_CANDIDATE;
     99 	}
    100 
    101 	retcode = META_SEARCH_BINDING;
    102 	ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
    103 	if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
    104 		/* already bound (or anonymous) */
    105 
    106 #ifdef DEBUG_205
    107 		char	buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
    108 		int	bound = 0;
    109 
    110 		if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
    111 			bound = 1;
    112 		}
    113 
    114 		snprintf( buf, sizeof( buf ), " mc=%p ld=%p%s DN=\"%s\"",
    115 			(void *)mc, (void *)msc->msc_ld,
    116 			bound ? " bound" : " anonymous",
    117 			bound == 0 ? "" : msc->msc_bound_ndn.bv_val );
    118 		Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
    119 			op->o_log_prefix, candidate, buf );
    120 #endif /* DEBUG_205 */
    121 
    122 		retcode = META_SEARCH_CANDIDATE;
    123 
    124 	} else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) ) {
    125 		/* another thread is binding the target for this conn; wait */
    126 
    127 #ifdef DEBUG_205
    128 		char	buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
    129 
    130 		snprintf( buf, sizeof( buf ), " mc=%p ld=%p needbind",
    131 			(void *)mc, (void *)msc->msc_ld );
    132 		Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
    133 			op->o_log_prefix, candidate, buf );
    134 #endif /* DEBUG_205 */
    135 
    136 		candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;
    137 		retcode = META_SEARCH_NEED_BIND;
    138 
    139 	} else {
    140 		/* we'll need to bind the target for this conn */
    141 
    142 #ifdef DEBUG_205
    143 		char buf[ SLAP_TEXT_BUFLEN ];
    144 
    145 		snprintf( buf, sizeof( buf ), " mc=%p ld=%p binding",
    146 			(void *)mc, (void *)msc->msc_ld );
    147 		Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
    148 			op->o_log_prefix, candidate, buf );
    149 #endif /* DEBUG_205 */
    150 
    151 		if ( msc->msc_ld == NULL ) {
    152 			/* for some reason (e.g. because formerly in "binding"
    153 			 * state, with eventual connection expiration or invalidation)
    154 			 * it was not initialized as expected */
    155 
    156 			Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n",
    157 				op->o_log_prefix, candidate, (void *)mc );
    158 
    159 			rc = meta_back_init_one_conn( op, rs, *mcp, candidate,
    160 				LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND, 0 );
    161 			switch ( rc ) {
    162 			case LDAP_SUCCESS:
    163 				assert( msc->msc_ld != NULL );
    164 				break;
    165 
    166 			case LDAP_SERVER_DOWN:
    167 			case LDAP_UNAVAILABLE:
    168 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    169 				goto down;
    170 
    171 			default:
    172 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    173 				goto other;
    174 			}
    175 		}
    176 
    177 		LDAP_BACK_CONN_BINDING_SET( msc );
    178 	}
    179 
    180 	ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    181 
    182 	if ( retcode != META_SEARCH_BINDING ) {
    183 		return retcode;
    184 	}
    185 
    186 	/* NOTE: this obsoletes pseudorootdn */
    187 	if ( op->o_conn != NULL &&
    188 		!op->o_do_not_cache &&
    189 		( BER_BVISNULL( &msc->msc_bound_ndn ) ||
    190 			BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
    191 			( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
    192 	{
    193 		rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, LDAP_BACK_DONTSEND, &binddn, &cred, &method );
    194 		if ( rc != LDAP_SUCCESS ) {
    195 			goto down;
    196 		}
    197 
    198 		/* NOTE: we copy things here, even if bind didn't succeed yet,
    199 		 * because the connection is not shared until bind is over */
    200 		if ( !BER_BVISNULL( &binddn ) ) {
    201 			ber_bvreplace( &msc->msc_bound_ndn, &binddn );
    202 			if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &cred ) ) {
    203 				if ( !BER_BVISNULL( &msc->msc_cred ) ) {
    204 					memset( msc->msc_cred.bv_val, 0,
    205 						msc->msc_cred.bv_len );
    206 				}
    207 				ber_bvreplace( &msc->msc_cred, &cred );
    208 			}
    209 		}
    210 
    211 		if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
    212 			/* apparently, idassert was configured with SASL bind,
    213 			 * so bind occurred inside meta_back_proxy_authz_cred() */
    214 			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
    215 			LDAP_BACK_CONN_BINDING_CLEAR( msc );
    216 			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    217 			return META_SEARCH_CANDIDATE;
    218 		}
    219 
    220 		/* paranoid */
    221 		switch ( method ) {
    222 		case LDAP_AUTH_NONE:
    223 		case LDAP_AUTH_SIMPLE:
    224 			/* do a simple bind with binddn, cred */
    225 			break;
    226 
    227 		default:
    228 			assert( 0 );
    229 			break;
    230 		}
    231 	}
    232 
    233 	assert( msc->msc_ld != NULL );
    234 
    235 	/* connect must be async only the first time... */
    236 	ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON );
    237 
    238 retry:;
    239 	rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
    240 			NULL, NULL, &candidates[ candidate ].sr_msgid );
    241 
    242 #ifdef DEBUG_205
    243 	{
    244 		char buf[ SLAP_TEXT_BUFLEN ];
    245 
    246 		snprintf( buf, sizeof( buf ), "meta_search_dobind_init[%d] mc=%p ld=%p rc=%d",
    247 			candidate, (void *)mc, (void *)mc->mc_conns[ candidate ].msc_ld, rc );
    248 		Debug( LDAP_DEBUG_ANY, "### %s %s\n",
    249 			op->o_log_prefix, buf, 0 );
    250 	}
    251 #endif /* DEBUG_205 */
    252 
    253 	switch ( rc ) {
    254 	case LDAP_SUCCESS:
    255 		assert( candidates[ candidate ].sr_msgid >= 0 );
    256 		META_BINDING_SET( &candidates[ candidate ] );
    257 		return META_SEARCH_BINDING;
    258 
    259 	case LDAP_X_CONNECTING:
    260 		/* must retry, same conn */
    261 		candidates[ candidate ].sr_msgid = META_MSGID_CONNECTING;
    262 		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
    263 		LDAP_BACK_CONN_BINDING_CLEAR( msc );
    264 		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    265 		return META_SEARCH_CONNECTING;
    266 
    267 	case LDAP_SERVER_DOWN:
    268 down:;
    269 		/* This is the worst thing that could happen:
    270 		 * the search will wait until the retry is over. */
    271 		if ( !META_IS_RETRYING( &candidates[ candidate ] ) ) {
    272 			META_RETRYING_SET( &candidates[ candidate ] );
    273 
    274 			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
    275 
    276 			assert( mc->mc_refcnt > 0 );
    277 			if ( LogTest( LDAP_DEBUG_ANY ) ) {
    278 				char	buf[ SLAP_TEXT_BUFLEN ];
    279 
    280 				/* this lock is required; however,
    281 				 * it's invoked only when logging is on */
    282 				ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
    283 				snprintf( buf, sizeof( buf ),
    284 					"retrying URI=\"%s\" DN=\"%s\"",
    285 					mt->mt_uri,
    286 					BER_BVISNULL( &msc->msc_bound_ndn ) ?
    287 						"" : msc->msc_bound_ndn.bv_val );
    288 				ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
    289 
    290 				Debug( LDAP_DEBUG_ANY,
    291 					"%s meta_search_dobind_init[%d]: %s.\n",
    292 					op->o_log_prefix, candidate, buf );
    293 			}
    294 
    295 			meta_clear_one_candidate( op, mc, candidate );
    296 			LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
    297 
    298 			( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
    299 
    300 			/* mc here must be the regular mc, reset and ready for init */
    301 			rc = meta_back_init_one_conn( op, rs, mc, candidate,
    302 				LDAP_BACK_CONN_ISPRIV( mc ), LDAP_BACK_DONTSEND, 0 );
    303 
    304 			if ( rc == LDAP_SUCCESS ) {
    305 				LDAP_BACK_CONN_BINDING_SET( msc );
    306 			}
    307 
    308 			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    309 
    310 			if ( rc == LDAP_SUCCESS ) {
    311 				candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    312 				goto retry;
    313 			}
    314 		}
    315 
    316 		if ( *mcp == NULL ) {
    317 			retcode = META_SEARCH_ERR;
    318 			rs->sr_err = LDAP_UNAVAILABLE;
    319 			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    320 			break;
    321 		}
    322 		/* fall thru */
    323 
    324 	default:
    325 other:;
    326 		rs->sr_err = rc;
    327 		rc = slap_map_api2result( rs );
    328 
    329 		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
    330 		meta_clear_one_candidate( op, mc, candidate );
    331 		candidates[ candidate ].sr_err = rc;
    332 		if ( META_BACK_ONERR_STOP( mi ) ) {
    333 			LDAP_BACK_CONN_TAINTED_SET( mc );
    334 			meta_back_release_conn_lock( mi, mc, 0 );
    335 			*mcp = NULL;
    336 			rs->sr_err = rc;
    337 
    338 			retcode = META_SEARCH_ERR;
    339 
    340 		} else {
    341 			retcode = META_SEARCH_NOT_CANDIDATE;
    342 		}
    343 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    344 		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    345 		break;
    346 	}
    347 
    348 	return retcode;
    349 }
    350 
    351 static meta_search_candidate_t
    352 meta_search_dobind_result(
    353 	Operation		*op,
    354 	SlapReply		*rs,
    355 	metaconn_t		**mcp,
    356 	int			candidate,
    357 	SlapReply		*candidates,
    358 	LDAPMessage		*res )
    359 {
    360 	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
    361 	metaconn_t		*mc = *mcp;
    362 	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
    363 
    364 	meta_search_candidate_t	retcode = META_SEARCH_NOT_CANDIDATE;
    365 	int			rc;
    366 
    367 	assert( msc->msc_ld != NULL );
    368 
    369 	/* FIXME: matched? referrals? response controls? */
    370 	rc = ldap_parse_result( msc->msc_ld, res,
    371 		&candidates[ candidate ].sr_err,
    372 		NULL, NULL, NULL, NULL, 0 );
    373 	if ( rc != LDAP_SUCCESS ) {
    374 		candidates[ candidate ].sr_err = rc;
    375 
    376 	} else {
    377 		rc = slap_map_api2result( &candidates[ candidate ] );
    378 	}
    379 
    380 	ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
    381 	LDAP_BACK_CONN_BINDING_CLEAR( msc );
    382 	if ( rc != LDAP_SUCCESS ) {
    383 		meta_clear_one_candidate( op, mc, candidate );
    384 		candidates[ candidate ].sr_err = rc;
    385 		if ( META_BACK_ONERR_STOP( mi ) ) {
    386 	        	LDAP_BACK_CONN_TAINTED_SET( mc );
    387 			meta_back_release_conn_lock( mi, mc, 0 );
    388 			*mcp = NULL;
    389 			retcode = META_SEARCH_ERR;
    390 			rs->sr_err = rc;
    391 		}
    392 
    393 	} else {
    394 		/* FIXME: check if bound as idassert authcDN! */
    395 		if ( BER_BVISNULL( &msc->msc_bound_ndn )
    396 			|| BER_BVISEMPTY( &msc->msc_bound_ndn ) )
    397 		{
    398 			LDAP_BACK_CONN_ISANON_SET( msc );
    399 
    400 		} else {
    401 			LDAP_BACK_CONN_ISBOUND_SET( msc );
    402 		}
    403 		retcode = META_SEARCH_CANDIDATE;
    404 
    405 		/* connect must be async */
    406 		ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_OFF );
    407 	}
    408 
    409 	candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    410 	META_BINDING_CLEAR( &candidates[ candidate ] );
    411 
    412 	ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
    413 
    414 	return retcode;
    415 }
    416 
    417 static meta_search_candidate_t
    418 meta_back_search_start(
    419 	Operation		*op,
    420 	SlapReply		*rs,
    421 	dncookie		*dc,
    422 	metaconn_t		**mcp,
    423 	int			candidate,
    424 	SlapReply		*candidates )
    425 {
    426 	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
    427 	metatarget_t		*mt = mi->mi_targets[ candidate ];
    428 	metasingleconn_t	*msc = &(*mcp)->mc_conns[ candidate ];
    429 	struct berval		realbase = op->o_req_dn;
    430 	int			realscope = op->ors_scope;
    431 	struct berval		mbase = BER_BVNULL;
    432 	struct berval		mfilter = BER_BVNULL;
    433 	char			**mapped_attrs = NULL;
    434 	int			rc;
    435 	meta_search_candidate_t	retcode;
    436 	struct timeval		tv, *tvp = NULL;
    437 	int			nretries = 1;
    438 	LDAPControl		**ctrls = NULL;
    439 
    440 	/* this should not happen; just in case... */
    441 	if ( msc->msc_ld == NULL ) {
    442 		Debug( LDAP_DEBUG_ANY,
    443 			"%s: meta_back_search_start candidate=%d ld=NULL%s.\n",
    444 			op->o_log_prefix, candidate,
    445 			META_BACK_ONERR_STOP( mi ) ? "" : " (ignored)" );
    446 		candidates[ candidate ].sr_err = LDAP_OTHER;
    447 		if ( META_BACK_ONERR_STOP( mi ) ) {
    448 			return META_SEARCH_ERR;
    449 		}
    450 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    451 		return META_SEARCH_NOT_CANDIDATE;
    452 	}
    453 
    454 	Debug( LDAP_DEBUG_TRACE, "%s >>> meta_back_search_start[%d]\n", op->o_log_prefix, candidate, 0 );
    455 
    456 	/*
    457 	 * modifies the base according to the scope, if required
    458 	 */
    459 	if ( mt->mt_nsuffix.bv_len > op->o_req_ndn.bv_len ) {
    460 		switch ( op->ors_scope ) {
    461 		case LDAP_SCOPE_SUBTREE:
    462 			/*
    463 			 * make the target suffix the new base
    464 			 * FIXME: this is very forgiving, because
    465 			 * "illegal" searchBases may be turned
    466 			 * into the suffix of the target; however,
    467 			 * the requested searchBase already passed
    468 			 * thru the candidate analyzer...
    469 			 */
    470 			if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) {
    471 				realbase = mt->mt_nsuffix;
    472 				if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
    473 					realscope = LDAP_SCOPE_SUBORDINATE;
    474 				}
    475 
    476 			} else {
    477 				/*
    478 				 * this target is no longer candidate
    479 				 */
    480 				retcode = META_SEARCH_NOT_CANDIDATE;
    481 				goto doreturn;
    482 			}
    483 			break;
    484 
    485 		case LDAP_SCOPE_SUBORDINATE:
    486 		case LDAP_SCOPE_ONELEVEL:
    487 		{
    488 			struct berval	rdn = mt->mt_nsuffix;
    489 			rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," );
    490 			if ( dnIsOneLevelRDN( &rdn )
    491 					&& dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) )
    492 			{
    493 				/*
    494 				 * if there is exactly one level,
    495 				 * make the target suffix the new
    496 				 * base, and make scope "base"
    497 				 */
    498 				realbase = mt->mt_nsuffix;
    499 				if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) {
    500 					if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
    501 						realscope = LDAP_SCOPE_SUBORDINATE;
    502 					} else {
    503 						realscope = LDAP_SCOPE_SUBTREE;
    504 					}
    505 				} else {
    506 					realscope = LDAP_SCOPE_BASE;
    507 				}
    508 				break;
    509 			} /* else continue with the next case */
    510 		}
    511 
    512 		case LDAP_SCOPE_BASE:
    513 			/*
    514 			 * this target is no longer candidate
    515 			 */
    516 			retcode = META_SEARCH_NOT_CANDIDATE;
    517 			goto doreturn;
    518 		}
    519 	}
    520 
    521 	/* initiate dobind */
    522 	retcode = meta_search_dobind_init( op, rs, mcp, candidate, candidates );
    523 
    524 	Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%d]=%d\n", op->o_log_prefix, candidate, retcode );
    525 
    526 	if ( retcode != META_SEARCH_CANDIDATE ) {
    527 		goto doreturn;
    528 	}
    529 
    530 	/*
    531 	 * Rewrite the search base, if required
    532 	 */
    533 	dc->target = mt;
    534 	dc->ctx = "searchBase";
    535 	switch ( ldap_back_dn_massage( dc, &realbase, &mbase ) ) {
    536 	case LDAP_SUCCESS:
    537 		break;
    538 
    539 	case LDAP_UNWILLING_TO_PERFORM:
    540 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
    541 		rs->sr_text = "Operation not allowed";
    542 		send_ldap_result( op, rs );
    543 		retcode = META_SEARCH_ERR;
    544 		goto doreturn;
    545 
    546 	default:
    547 
    548 		/*
    549 		 * this target is no longer candidate
    550 		 */
    551 		retcode = META_SEARCH_NOT_CANDIDATE;
    552 		goto doreturn;
    553 	}
    554 
    555 	/*
    556 	 * Maps filter
    557 	 */
    558 	rc = ldap_back_filter_map_rewrite( dc, op->ors_filter,
    559 			&mfilter, BACKLDAP_MAP );
    560 	switch ( rc ) {
    561 	case LDAP_SUCCESS:
    562 		break;
    563 
    564 	case LDAP_COMPARE_FALSE:
    565 	default:
    566 		/*
    567 		 * this target is no longer candidate
    568 		 */
    569 		retcode = META_SEARCH_NOT_CANDIDATE;
    570 		goto done;
    571 	}
    572 
    573 	/*
    574 	 * Maps required attributes
    575 	 */
    576 	rc = ldap_back_map_attrs( &mt->mt_rwmap.rwm_at,
    577 			op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );
    578 	if ( rc != LDAP_SUCCESS ) {
    579 		/*
    580 		 * this target is no longer candidate
    581 		 */
    582 		retcode = META_SEARCH_NOT_CANDIDATE;
    583 		goto done;
    584 	}
    585 
    586 	/* should we check return values? */
    587 	if ( op->ors_deref != -1 ) {
    588 		assert( msc->msc_ld != NULL );
    589 		(void)ldap_set_option( msc->msc_ld, LDAP_OPT_DEREF,
    590 				( void * )&op->ors_deref );
    591 	}
    592 
    593 	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
    594 		tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
    595 		tv.tv_usec = 0;
    596 		tvp = &tv;
    597 	}
    598 
    599 retry:;
    600 	ctrls = op->o_ctrls;
    601 	if ( meta_back_controls_add( op, rs, *mcp, candidate, &ctrls )
    602 		!= LDAP_SUCCESS )
    603 	{
    604 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    605 		retcode = META_SEARCH_NOT_CANDIDATE;
    606 		goto done;
    607 	}
    608 
    609 	/*
    610 	 * Starts the search
    611 	 */
    612 	assert( msc->msc_ld != NULL );
    613 	rc = ldap_search_ext( msc->msc_ld,
    614 			mbase.bv_val, realscope, mfilter.bv_val,
    615 			mapped_attrs, op->ors_attrsonly,
    616 			ctrls, NULL, tvp, op->ors_slimit,
    617 			&candidates[ candidate ].sr_msgid );
    618 	switch ( rc ) {
    619 	case LDAP_SUCCESS:
    620 		retcode = META_SEARCH_CANDIDATE;
    621 		break;
    622 
    623 	case LDAP_SERVER_DOWN:
    624 		if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
    625 			nretries = 0;
    626 			/* if the identity changed, there might be need to re-authz */
    627 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
    628 			goto retry;
    629 		}
    630 
    631 		if ( *mcp == NULL ) {
    632 			retcode = META_SEARCH_ERR;
    633 			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    634 			break;
    635 		}
    636 		/* fall thru */
    637 
    638 	default:
    639 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
    640 		retcode = META_SEARCH_NOT_CANDIDATE;
    641 	}
    642 
    643 done:;
    644 	(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
    645 
    646 	if ( mapped_attrs ) {
    647 		free( mapped_attrs );
    648 	}
    649 	if ( mfilter.bv_val != op->ors_filterstr.bv_val ) {
    650 		free( mfilter.bv_val );
    651 	}
    652 	if ( mbase.bv_val != realbase.bv_val ) {
    653 		free( mbase.bv_val );
    654 	}
    655 
    656 doreturn:;
    657 	Debug( LDAP_DEBUG_TRACE, "%s <<< meta_back_search_start[%d]=%d\n", op->o_log_prefix, candidate, retcode );
    658 
    659 	return retcode;
    660 }
    661 
    662 int
    663 meta_back_search( Operation *op, SlapReply *rs )
    664 {
    665 	metainfo_t	*mi = ( metainfo_t * )op->o_bd->be_private;
    666 	metaconn_t	*mc;
    667 	struct timeval	save_tv = { 0, 0 },
    668 			tv;
    669 	time_t		stoptime = (time_t)(-1),
    670 			lastres_time = slap_get_time(),
    671 			timeout = 0;
    672 	int		rc = 0, sres = LDAP_SUCCESS;
    673 	char		*matched = NULL;
    674 	int		last = 0, ncandidates = 0,
    675 			initial_candidates = 0, candidate_match = 0,
    676 			needbind = 0;
    677 	ldap_back_send_t	sendok = LDAP_BACK_SENDERR;
    678 	long		i;
    679 	dncookie	dc;
    680 	int		is_ok = 0;
    681 	void		*savepriv;
    682 	SlapReply	*candidates = NULL;
    683 
    684 	/*
    685 	 * controls are set in ldap_back_dobind()
    686 	 *
    687 	 * FIXME: in case of values return filter, we might want
    688 	 * to map attrs and maybe rewrite value
    689 	 */
    690 getconn:;
    691 	mc = meta_back_getconn( op, rs, NULL, sendok );
    692 	if ( !mc ) {
    693 		return rs->sr_err;
    694 	}
    695 
    696 	dc.conn = op->o_conn;
    697 	dc.rs = rs;
    698 
    699 	if ( candidates == NULL ) candidates = meta_back_candidates_get( op );
    700 	/*
    701 	 * Inits searches
    702 	 */
    703 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
    704 		/* reset sr_msgid; it is used in most loops
    705 		 * to check if that target is still to be considered */
    706 		candidates[ i ].sr_msgid = META_MSGID_IGNORE;
    707 
    708 		/* a target is marked as candidate by meta_back_getconn();
    709 		 * if for any reason (an error, it's over or so) it is
    710 		 * no longer active, sr_msgid is set to META_MSGID_IGNORE
    711 		 * but it remains candidate, which means it has been active
    712 		 * at some point during the operation.  This allows to
    713 		 * use its response code and more to compute the final
    714 		 * response */
    715 		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
    716 			continue;
    717 		}
    718 
    719 		candidates[ i ].sr_matched = NULL;
    720 		candidates[ i ].sr_text = NULL;
    721 		candidates[ i ].sr_ref = NULL;
    722 		candidates[ i ].sr_ctrls = NULL;
    723 
    724 		/* get largest timeout among candidates */
    725 		if ( mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ]
    726 			&& mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ] > timeout )
    727 		{
    728 			timeout = mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ];
    729 		}
    730 	}
    731 
    732 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
    733 		if ( !META_IS_CANDIDATE( &candidates[ i ] )
    734 			|| candidates[ i ].sr_err != LDAP_SUCCESS )
    735 		{
    736 			continue;
    737 		}
    738 
    739 		switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
    740 		{
    741 		case META_SEARCH_NOT_CANDIDATE:
    742 			candidates[ i ].sr_msgid = META_MSGID_IGNORE;
    743 			break;
    744 
    745 		case META_SEARCH_NEED_BIND:
    746 			++needbind;
    747 			/* fallthru */
    748 
    749 		case META_SEARCH_CONNECTING:
    750 		case META_SEARCH_CANDIDATE:
    751 		case META_SEARCH_BINDING:
    752 			candidates[ i ].sr_type = REP_INTERMEDIATE;
    753 			++ncandidates;
    754 			break;
    755 
    756 		case META_SEARCH_ERR:
    757 			savepriv = op->o_private;
    758 			op->o_private = (void *)i;
    759 			send_ldap_result( op, rs );
    760 			op->o_private = savepriv;
    761 			rc = -1;
    762 			goto finish;
    763 
    764 		default:
    765 			assert( 0 );
    766 			break;
    767 		}
    768 	}
    769 
    770 	if ( ncandidates > 0 && needbind == ncandidates ) {
    771 		/*
    772 		 * give up the second time...
    773 		 *
    774 		 * NOTE: this should not occur the second time, since a fresh
    775 		 * connection has ben created; however, targets may also
    776 		 * need bind because the bind timed out or so.
    777 		 */
    778 		if ( sendok & LDAP_BACK_BINDING ) {
    779 			Debug( LDAP_DEBUG_ANY,
    780 				"%s meta_back_search: unable to initialize conn\n",
    781 				op->o_log_prefix, 0, 0 );
    782 			rs->sr_err = LDAP_UNAVAILABLE;
    783 			rs->sr_text = "unable to initialize connection to remote targets";
    784 			send_ldap_result( op, rs );
    785 			rc = -1;
    786 			goto finish;
    787 		}
    788 
    789 		/* FIXME: better create a separate connection? */
    790 		sendok |= LDAP_BACK_BINDING;
    791 
    792 #ifdef DEBUG_205
    793 		Debug( LDAP_DEBUG_ANY, "*** %s drop mc=%p create new connection\n",
    794 			op->o_log_prefix, (void *)mc, 0 );
    795 #endif /* DEBUG_205 */
    796 
    797 		meta_back_release_conn( mi, mc );
    798 		mc = NULL;
    799 
    800 		needbind = 0;
    801 		ncandidates = 0;
    802 
    803 		goto getconn;
    804 	}
    805 
    806 	initial_candidates = ncandidates;
    807 
    808 	if ( LogTest( LDAP_DEBUG_TRACE ) ) {
    809 		char	cnd[ SLAP_TEXT_BUFLEN ];
    810 		int	c;
    811 
    812 		for ( c = 0; c < mi->mi_ntargets; c++ ) {
    813 			if ( META_IS_CANDIDATE( &candidates[ c ] ) ) {
    814 				cnd[ c ] = '*';
    815 			} else {
    816 				cnd[ c ] = ' ';
    817 			}
    818 		}
    819 		cnd[ c ] = '\0';
    820 
    821 		Debug( LDAP_DEBUG_TRACE, "%s meta_back_search: ncandidates=%d "
    822 			"cnd=\"%s\"\n", op->o_log_prefix, ncandidates, cnd );
    823 	}
    824 
    825 	if ( initial_candidates == 0 ) {
    826 		/* NOTE: here we are not sending any matchedDN;
    827 		 * this is intended, because if the back-meta
    828 		 * is serving this search request, but no valid
    829 		 * candidate could be looked up, it means that
    830 		 * there is a hole in the mapping of the targets
    831 		 * and thus no knowledge of any remote superior
    832 		 * is available */
    833 		Debug( LDAP_DEBUG_ANY, "%s meta_back_search: "
    834 			"base=\"%s\" scope=%d: "
    835 			"no candidate could be selected\n",
    836 			op->o_log_prefix, op->o_req_dn.bv_val,
    837 			op->ors_scope );
    838 
    839 		/* FIXME: we're sending the first error we encounter;
    840 		 * maybe we should pick the worst... */
    841 		rc = LDAP_NO_SUCH_OBJECT;
    842 		for ( i = 0; i < mi->mi_ntargets; i++ ) {
    843 			if ( META_IS_CANDIDATE( &candidates[ i ] )
    844 				&& candidates[ i ].sr_err != LDAP_SUCCESS )
    845 			{
    846 				rc = candidates[ i ].sr_err;
    847 				break;
    848 			}
    849 		}
    850 
    851 		send_ldap_error( op, rs, rc, NULL );
    852 
    853 		goto finish;
    854 	}
    855 
    856 	/* We pull apart the ber result, stuff it into a slapd entry, and
    857 	 * let send_search_entry stuff it back into ber format. Slow & ugly,
    858 	 * but this is necessary for version matching, and for ACL processing.
    859 	 */
    860 
    861 	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
    862 		stoptime = op->o_time + op->ors_tlimit;
    863 	}
    864 
    865 	/*
    866 	 * In case there are no candidates, no cycle takes place...
    867 	 *
    868 	 * FIXME: we might use a queue, to better balance the load
    869 	 * among the candidates
    870 	 */
    871 	for ( rc = 0; ncandidates > 0; ) {
    872 		int	gotit = 0,
    873 			doabandon = 0,
    874 			alreadybound = ncandidates;
    875 
    876 		/* check timeout */
    877 		if ( timeout && lastres_time > 0
    878 			&& ( slap_get_time() - lastres_time ) > timeout )
    879 		{
    880 			doabandon = 1;
    881 			rs->sr_text = "Operation timed out";
    882 			rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
    883 				LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
    884 			savepriv = op->o_private;
    885 			op->o_private = (void *)i;
    886 			send_ldap_result( op, rs );
    887 			op->o_private = savepriv;
    888 			goto finish;
    889 		}
    890 
    891 		/* check time limit */
    892 		if ( op->ors_tlimit != SLAP_NO_LIMIT
    893 				&& slap_get_time() > stoptime )
    894 		{
    895 			doabandon = 1;
    896 			rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
    897 			savepriv = op->o_private;
    898 			op->o_private = (void *)i;
    899 			send_ldap_result( op, rs );
    900 			op->o_private = savepriv;
    901 			goto finish;
    902 		}
    903 
    904 		for ( i = 0; i < mi->mi_ntargets; i++ ) {
    905 			meta_search_candidate_t	retcode = META_SEARCH_UNDEFINED;
    906 			metasingleconn_t	*msc = &mc->mc_conns[ i ];
    907 			LDAPMessage		*res = NULL, *msg;
    908 
    909 			/* if msgid is invalid, don't ldap_result() */
    910 			if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
    911 				continue;
    912 			}
    913 
    914 			/* if target still needs bind, retry */
    915 			if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND
    916 				|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
    917 			{
    918 				/* initiate dobind */
    919 				retcode = meta_search_dobind_init( op, rs, &mc, i, candidates );
    920 
    921 				Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%ld]=%d\n",
    922 					op->o_log_prefix, i, retcode );
    923 
    924 				switch ( retcode ) {
    925 				case META_SEARCH_NEED_BIND:
    926 					alreadybound--;
    927 					/* fallthru */
    928 
    929 				case META_SEARCH_CONNECTING:
    930 				case META_SEARCH_BINDING:
    931 					break;
    932 
    933 				case META_SEARCH_ERR:
    934 					candidates[ i ].sr_err = rs->sr_err;
    935 					if ( META_BACK_ONERR_STOP( mi ) ) {
    936 						savepriv = op->o_private;
    937 						op->o_private = (void *)i;
    938 						send_ldap_result( op, rs );
    939 						op->o_private = savepriv;
    940 						goto finish;
    941 					}
    942 					/* fallthru */
    943 
    944 				case META_SEARCH_NOT_CANDIDATE:
    945 					/*
    946 					 * When no candidates are left,
    947 					 * the outer cycle finishes
    948 					 */
    949 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
    950 					assert( ncandidates > 0 );
    951 					--ncandidates;
    952 					break;
    953 
    954 				case META_SEARCH_CANDIDATE:
    955 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
    956 					switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
    957 					{
    958 					case META_SEARCH_CANDIDATE:
    959 						assert( candidates[ i ].sr_msgid >= 0 );
    960 						break;
    961 
    962 					case META_SEARCH_ERR:
    963 						candidates[ i ].sr_err = rs->sr_err;
    964 						if ( META_BACK_ONERR_STOP( mi ) ) {
    965 							savepriv = op->o_private;
    966 							op->o_private = (void *)i;
    967 							send_ldap_result( op, rs );
    968 							op->o_private = savepriv;
    969 							goto finish;
    970 						}
    971 						/* fallthru */
    972 
    973 					case META_SEARCH_NOT_CANDIDATE:
    974 						/* means that meta_back_search_start()
    975 						 * failed but onerr == continue */
    976 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
    977 						assert( ncandidates > 0 );
    978 						--ncandidates;
    979 						break;
    980 
    981 					default:
    982 						/* impossible */
    983 						assert( 0 );
    984 						break;
    985 					}
    986 					break;
    987 
    988 				default:
    989 					/* impossible */
    990 					assert( 0 );
    991 					break;
    992 				}
    993 				continue;
    994 			}
    995 
    996 			/* check for abandon */
    997 			if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {
    998 				break;
    999 			}
   1000 
   1001 #ifdef DEBUG_205
   1002 			if ( msc->msc_ld == NULL ) {
   1003 				char	buf[ SLAP_TEXT_BUFLEN ];
   1004 
   1005 				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
   1006 				snprintf( buf, sizeof( buf ),
   1007 					"%s meta_back_search[%ld] mc=%p msgid=%d%s%s%s\n",
   1008 					op->o_log_prefix, (long)i, (void *)mc,
   1009 					candidates[ i ].sr_msgid,
   1010 					META_IS_BINDING( &candidates[ i ] ) ? " binding" : "",
   1011 					LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ? " connbinding" : "",
   1012 					META_BACK_CONN_CREATING( &mc->mc_conns[ i ] ) ? " conncreating" : "" );
   1013 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
   1014 
   1015 				Debug( LDAP_DEBUG_ANY, "!!! %s\n", buf, 0, 0 );
   1016 			}
   1017 #endif /* DEBUG_205 */
   1018 
   1019 			/*
   1020 			 * FIXME: handle time limit as well?
   1021 			 * Note that target servers are likely
   1022 			 * to handle it, so at some time we'll
   1023 			 * get a LDAP_TIMELIMIT_EXCEEDED from
   1024 			 * one of them ...
   1025 			 */
   1026 			tv = save_tv;
   1027 			rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid,
   1028 					LDAP_MSG_RECEIVED, &tv, &res );
   1029 			switch ( rc ) {
   1030 			case 0:
   1031 				/* FIXME: res should not need to be freed */
   1032 				assert( res == NULL );
   1033 				continue;
   1034 
   1035 			case -1:
   1036 really_bad:;
   1037 				/* something REALLY bad happened! */
   1038 				if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
   1039 					candidates[ i ].sr_type = REP_RESULT;
   1040 
   1041 					if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
   1042 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1043 						switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
   1044 						{
   1045 							/* means that failed but onerr == continue */
   1046 						case META_SEARCH_NOT_CANDIDATE:
   1047 							candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1048 
   1049 							assert( ncandidates > 0 );
   1050 							--ncandidates;
   1051 
   1052 							candidates[ i ].sr_err = rs->sr_err;
   1053 							if ( META_BACK_ONERR_STOP( mi ) ) {
   1054 								savepriv = op->o_private;
   1055 								op->o_private = (void *)i;
   1056 								send_ldap_result( op, rs );
   1057 								op->o_private = savepriv;
   1058 								goto finish;
   1059 							}
   1060 							/* fall thru */
   1061 
   1062 						case META_SEARCH_CANDIDATE:
   1063 							/* get back into business... */
   1064 							continue;
   1065 
   1066 						case META_SEARCH_BINDING:
   1067 						case META_SEARCH_CONNECTING:
   1068 						case META_SEARCH_NEED_BIND:
   1069 						case META_SEARCH_UNDEFINED:
   1070 							assert( 0 );
   1071 
   1072 						default:
   1073 							/* unrecoverable error */
   1074 							candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1075 							rc = rs->sr_err = LDAP_OTHER;
   1076 							goto finish;
   1077 						}
   1078 					}
   1079 
   1080 					candidates[ i ].sr_err = rs->sr_err;
   1081 					if ( META_BACK_ONERR_STOP( mi ) ) {
   1082 						savepriv = op->o_private;
   1083 						op->o_private = (void *)i;
   1084 						send_ldap_result( op, rs );
   1085 						op->o_private = savepriv;
   1086 						goto finish;
   1087 					}
   1088 				}
   1089 
   1090 				/*
   1091 				 * When no candidates are left,
   1092 				 * the outer cycle finishes
   1093 				 */
   1094 				candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1095 				assert( ncandidates > 0 );
   1096 				--ncandidates;
   1097 				rs->sr_err = candidates[ i ].sr_err;
   1098 				continue;
   1099 
   1100 			default:
   1101 				lastres_time = slap_get_time();
   1102 
   1103 				/* only touch when activity actually took place... */
   1104 				if ( mi->mi_idle_timeout != 0 && msc->msc_time < lastres_time ) {
   1105 					msc->msc_time = lastres_time;
   1106 				}
   1107 				break;
   1108 			}
   1109 
   1110 			for ( msg = ldap_first_message( msc->msc_ld, res );
   1111 				msg != NULL;
   1112 				msg = ldap_next_message( msc->msc_ld, msg ) )
   1113 			{
   1114 				rc = ldap_msgtype( msg );
   1115 				if ( rc == LDAP_RES_SEARCH_ENTRY ) {
   1116 					LDAPMessage	*e;
   1117 
   1118 					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
   1119 						/* don't retry any more... */
   1120 						candidates[ i ].sr_type = REP_RESULT;
   1121 					}
   1122 
   1123 					is_ok++;
   1124 
   1125 					e = ldap_first_entry( msc->msc_ld, msg );
   1126 					savepriv = op->o_private;
   1127 					op->o_private = (void *)i;
   1128 					rs->sr_err = meta_send_entry( op, rs, mc, i, e );
   1129 
   1130 					switch ( rs->sr_err ) {
   1131 					case LDAP_SIZELIMIT_EXCEEDED:
   1132 						savepriv = op->o_private;
   1133 						op->o_private = (void *)i;
   1134 						send_ldap_result( op, rs );
   1135 						op->o_private = savepriv;
   1136 						rs->sr_err = LDAP_SUCCESS;
   1137 						ldap_msgfree( res );
   1138 						res = NULL;
   1139 						goto finish;
   1140 
   1141 					case LDAP_UNAVAILABLE:
   1142 						rs->sr_err = LDAP_OTHER;
   1143 						ldap_msgfree( res );
   1144 						res = NULL;
   1145 						goto finish;
   1146 					}
   1147 					op->o_private = savepriv;
   1148 
   1149 					/* don't wait any longer... */
   1150 					gotit = 1;
   1151 					save_tv.tv_sec = 0;
   1152 					save_tv.tv_usec = 0;
   1153 
   1154 				} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
   1155 					char		**references = NULL;
   1156 					int		cnt;
   1157 
   1158 					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
   1159 						/* don't retry any more... */
   1160 						candidates[ i ].sr_type = REP_RESULT;
   1161 					}
   1162 
   1163 					is_ok++;
   1164 
   1165 					rc = ldap_parse_reference( msc->msc_ld, msg,
   1166 							&references, &rs->sr_ctrls, 0 );
   1167 
   1168 					if ( rc != LDAP_SUCCESS ) {
   1169 						continue;
   1170 					}
   1171 
   1172 					if ( references == NULL ) {
   1173 						continue;
   1174 					}
   1175 
   1176 #ifdef ENABLE_REWRITE
   1177 					dc.ctx = "referralDN";
   1178 #else /* ! ENABLE_REWRITE */
   1179 					dc.tofrom = 0;
   1180 					dc.normalized = 0;
   1181 #endif /* ! ENABLE_REWRITE */
   1182 
   1183 					/* FIXME: merge all and return at the end */
   1184 
   1185 					for ( cnt = 0; references[ cnt ]; cnt++ )
   1186 						;
   1187 
   1188 					rs->sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
   1189 
   1190 					for ( cnt = 0; references[ cnt ]; cnt++ ) {
   1191 						ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );
   1192 					}
   1193 					BER_BVZERO( &rs->sr_ref[ cnt ] );
   1194 
   1195 					( void )ldap_back_referral_result_rewrite( &dc, rs->sr_ref );
   1196 
   1197 					if ( rs->sr_ref != NULL && !BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
   1198 						/* ignore return value by now */
   1199 						savepriv = op->o_private;
   1200 						op->o_private = (void *)i;
   1201 						( void )send_search_reference( op, rs );
   1202 						op->o_private = savepriv;
   1203 
   1204 						ber_bvarray_free( rs->sr_ref );
   1205 						rs->sr_ref = NULL;
   1206 					}
   1207 
   1208 					/* cleanup */
   1209 					if ( references ) {
   1210 						ber_memvfree( (void **)references );
   1211 					}
   1212 
   1213 					if ( rs->sr_ctrls ) {
   1214 						ldap_controls_free( rs->sr_ctrls );
   1215 						rs->sr_ctrls = NULL;
   1216 					}
   1217 
   1218 				} else if ( rc == LDAP_RES_SEARCH_RESULT ) {
   1219 					char		buf[ SLAP_TEXT_BUFLEN ];
   1220 					char		**references = NULL;
   1221 
   1222 					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
   1223 						/* don't retry any more... */
   1224 						candidates[ i ].sr_type = REP_RESULT;
   1225 					}
   1226 
   1227 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1228 
   1229 					/* NOTE: ignores response controls
   1230 					 * (and intermediate response controls
   1231 					 * as well, except for those with search
   1232 					 * references); this may not be correct,
   1233 					 * but if they're not ignored then
   1234 					 * back-meta would need to merge them
   1235 					 * consistently (think of pagedResults...)
   1236 					 */
   1237 					/* FIXME: response controls? */
   1238 					rs->sr_err = ldap_parse_result( msc->msc_ld,
   1239 						msg,
   1240 						&candidates[ i ].sr_err,
   1241 						(char **)&candidates[ i ].sr_matched,
   1242 						NULL /* (char **)&candidates[ i ].sr_text */ ,
   1243 						&references,
   1244 						NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
   1245 						0 );
   1246 					if ( rs->sr_err != LDAP_SUCCESS ) {
   1247 						sres = slap_map_api2result( &candidates[ i ] );
   1248 						candidates[ i ].sr_type = REP_RESULT;
   1249 						ldap_msgfree( res );
   1250 						res = NULL;
   1251 						goto really_bad;
   1252 					}
   1253 
   1254 					rs->sr_err = candidates[ i ].sr_err;
   1255 
   1256 					/* massage matchedDN if need be */
   1257 					if ( candidates[ i ].sr_matched != NULL ) {
   1258 						struct berval	match, mmatch;
   1259 
   1260 						ber_str2bv( candidates[ i ].sr_matched,
   1261 							0, 0, &match );
   1262 						candidates[ i ].sr_matched = NULL;
   1263 
   1264 						dc.ctx = "matchedDN";
   1265 						dc.target = mi->mi_targets[ i ];
   1266 						if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {
   1267 							if ( mmatch.bv_val == match.bv_val ) {
   1268 								candidates[ i ].sr_matched
   1269 									= ch_strdup( mmatch.bv_val );
   1270 
   1271 							} else {
   1272 								candidates[ i ].sr_matched = mmatch.bv_val;
   1273 							}
   1274 
   1275 							candidate_match++;
   1276 						}
   1277 						ldap_memfree( match.bv_val );
   1278 					}
   1279 
   1280 					/* add references to array */
   1281 					/* RFC 4511: referrals can only appear
   1282 					 * if result code is LDAP_REFERRAL */
   1283 					if ( references != NULL
   1284 						&& references[ 0 ] != NULL
   1285 						&& references[ 0 ][ 0 ] != '\0' )
   1286 					{
   1287 						if ( rs->sr_err != LDAP_REFERRAL ) {
   1288 							Debug( LDAP_DEBUG_ANY,
   1289 								"%s meta_back_search[%ld]: "
   1290 								"got referrals with err=%d\n",
   1291 								op->o_log_prefix,
   1292 								i, rs->sr_err );
   1293 
   1294 						} else {
   1295 							BerVarray	sr_ref;
   1296 							int		cnt;
   1297 
   1298 							for ( cnt = 0; references[ cnt ]; cnt++ )
   1299 								;
   1300 
   1301 							sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
   1302 
   1303 							for ( cnt = 0; references[ cnt ]; cnt++ ) {
   1304 								ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
   1305 							}
   1306 							BER_BVZERO( &sr_ref[ cnt ] );
   1307 
   1308 							( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
   1309 
   1310 							if ( rs->sr_v2ref == NULL ) {
   1311 								rs->sr_v2ref = sr_ref;
   1312 
   1313 							} else {
   1314 								for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
   1315 									ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
   1316 								}
   1317 								ber_memfree( sr_ref );
   1318 							}
   1319 						}
   1320 
   1321 					} else if ( rs->sr_err == LDAP_REFERRAL ) {
   1322 						Debug( LDAP_DEBUG_ANY,
   1323 							"%s meta_back_search[%ld]: "
   1324 							"got err=%d with null "
   1325 							"or empty referrals\n",
   1326 							op->o_log_prefix,
   1327 							i, rs->sr_err );
   1328 
   1329 						rs->sr_err = LDAP_NO_SUCH_OBJECT;
   1330 					}
   1331 
   1332 					/* cleanup */
   1333 					ber_memvfree( (void **)references );
   1334 
   1335 					sres = slap_map_api2result( rs );
   1336 
   1337 					if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
   1338 						snprintf( buf, sizeof( buf ),
   1339 							"%s meta_back_search[%ld] "
   1340 							"match=\"%s\" err=%ld",
   1341 							op->o_log_prefix, i,
   1342 							candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
   1343 							(long) candidates[ i ].sr_err );
   1344 						if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
   1345 							Debug( LDAP_DEBUG_TRACE, "%s.\n", buf, 0, 0 );
   1346 
   1347 						} else {
   1348 							Debug( LDAP_DEBUG_ANY, "%s (%s).\n",
   1349 								buf, ldap_err2string( candidates[ i ].sr_err ), 0 );
   1350 						}
   1351 					}
   1352 
   1353 					switch ( sres ) {
   1354 					case LDAP_NO_SUCH_OBJECT:
   1355 						/* is_ok is touched any time a valid
   1356 						 * (even intermediate) result is
   1357 						 * returned; as a consequence, if
   1358 						 * a candidate returns noSuchObject
   1359 						 * it is ignored and the candidate
   1360 						 * is simply demoted. */
   1361 						if ( is_ok ) {
   1362 							sres = LDAP_SUCCESS;
   1363 						}
   1364 						break;
   1365 
   1366 					case LDAP_SUCCESS:
   1367 					case LDAP_REFERRAL:
   1368 						is_ok++;
   1369 						break;
   1370 
   1371 					case LDAP_SIZELIMIT_EXCEEDED:
   1372 						/* if a target returned sizelimitExceeded
   1373 						 * and the entry count is equal to the
   1374 						 * proxy's limit, the target would have
   1375 						 * returned more, and the error must be
   1376 						 * propagated to the client; otherwise,
   1377 						 * the target enforced a limit lower
   1378 						 * than what requested by the proxy;
   1379 						 * ignore it */
   1380 						candidates[ i ].sr_err = rs->sr_err;
   1381 						if ( rs->sr_nentries == op->ors_slimit
   1382 							|| META_BACK_ONERR_STOP( mi ) )
   1383 						{
   1384 							savepriv = op->o_private;
   1385 							op->o_private = (void *)i;
   1386 							send_ldap_result( op, rs );
   1387 							op->o_private = savepriv;
   1388 							ldap_msgfree( res );
   1389 							res = NULL;
   1390 							goto finish;
   1391 						}
   1392 						break;
   1393 
   1394 					default:
   1395 						candidates[ i ].sr_err = rs->sr_err;
   1396 						if ( META_BACK_ONERR_STOP( mi ) ) {
   1397 							savepriv = op->o_private;
   1398 							op->o_private = (void *)i;
   1399 							send_ldap_result( op, rs );
   1400 							op->o_private = savepriv;
   1401 							ldap_msgfree( res );
   1402 							res = NULL;
   1403 							goto finish;
   1404 						}
   1405 						break;
   1406 					}
   1407 
   1408 					last = i;
   1409 					rc = 0;
   1410 
   1411 					/*
   1412 					 * When no candidates are left,
   1413 					 * the outer cycle finishes
   1414 					 */
   1415 					assert( ncandidates > 0 );
   1416 					--ncandidates;
   1417 
   1418 				} else if ( rc == LDAP_RES_BIND ) {
   1419 					meta_search_candidate_t	retcode;
   1420 
   1421 					retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg );
   1422 					if ( retcode == META_SEARCH_CANDIDATE ) {
   1423 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1424 						retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );
   1425 					}
   1426 
   1427 					switch ( retcode ) {
   1428 					case META_SEARCH_CANDIDATE:
   1429 						break;
   1430 
   1431 						/* means that failed but onerr == continue */
   1432 					case META_SEARCH_NOT_CANDIDATE:
   1433 					case META_SEARCH_ERR:
   1434 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1435 						assert( ncandidates > 0 );
   1436 						--ncandidates;
   1437 
   1438 						candidates[ i ].sr_err = rs->sr_err;
   1439 						if ( META_BACK_ONERR_STOP( mi ) ) {
   1440 							savepriv = op->o_private;
   1441 							op->o_private = (void *)i;
   1442 							send_ldap_result( op, rs );
   1443 							op->o_private = savepriv;
   1444 							ldap_msgfree( res );
   1445 							res = NULL;
   1446 							goto finish;
   1447 						}
   1448 						goto free_message;
   1449 
   1450 					default:
   1451 						assert( 0 );
   1452 						break;
   1453 					}
   1454 
   1455 				} else {
   1456 					assert( 0 );
   1457 					ldap_msgfree( res );
   1458 					res = NULL;
   1459 					goto really_bad;
   1460 				}
   1461 			}
   1462 
   1463 free_message:;
   1464 			ldap_msgfree( res );
   1465 			res = NULL;
   1466 		}
   1467 
   1468 		/* check for abandon */
   1469 		if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {
   1470 			for ( i = 0; i < mi->mi_ntargets; i++ ) {
   1471 				if ( candidates[ i ].sr_msgid >= 0
   1472 					|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
   1473 				{
   1474 					if ( META_IS_BINDING( &candidates[ i ] )
   1475 						|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
   1476 					{
   1477 						ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
   1478 						if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
   1479 							|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
   1480 						{
   1481 							/* if still binding, destroy */
   1482 
   1483 #ifdef DEBUG_205
   1484 							char buf[ SLAP_TEXT_BUFLEN ];
   1485 
   1486 							snprintf( buf, sizeof( buf), "%s meta_back_search(abandon) "
   1487 								"ldap_unbind_ext[%ld] mc=%p ld=%p",
   1488 								op->o_log_prefix, i, (void *)mc,
   1489 								(void *)mc->mc_conns[i].msc_ld );
   1490 
   1491 							Debug( LDAP_DEBUG_ANY, "### %s\n", buf, 0, 0 );
   1492 #endif /* DEBUG_205 */
   1493 
   1494 							meta_clear_one_candidate( op, mc, i );
   1495 						}
   1496 						ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
   1497 						META_BINDING_CLEAR( &candidates[ i ] );
   1498 
   1499 					} else {
   1500 						(void)meta_back_cancel( mc, op, rs,
   1501 							candidates[ i ].sr_msgid, i,
   1502 							LDAP_BACK_DONTSEND );
   1503 					}
   1504 
   1505 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
   1506 					assert( ncandidates > 0 );
   1507 					--ncandidates;
   1508 				}
   1509 			}
   1510 
   1511 			if ( op->o_abandon ) {
   1512 				rc = SLAPD_ABANDON;
   1513 			}
   1514 
   1515 			/* let send_ldap_result play cleanup handlers (ITS#4645) */
   1516 			break;
   1517 		}
   1518 
   1519 		/* if no entry was found during this loop,
   1520 		 * set a minimal timeout */
   1521 		if ( ncandidates > 0 && gotit == 0 ) {
   1522 			if ( save_tv.tv_sec == 0 && save_tv.tv_usec == 0 ) {
   1523 				save_tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates;
   1524 
   1525 				/* arbitrarily limit to something between 1 and 2 minutes */
   1526 			} else if ( ( stoptime == -1 && save_tv.tv_sec < 60 )
   1527 				|| save_tv.tv_sec < ( stoptime - slap_get_time() ) / ( 2 * ncandidates ) )
   1528 			{
   1529 				/* double the timeout */
   1530 				lutil_timermul( &save_tv, 2, &save_tv );
   1531 			}
   1532 
   1533 			if ( alreadybound == 0 ) {
   1534 				tv = save_tv;
   1535 				(void)select( 0, NULL, NULL, NULL, &tv );
   1536 
   1537 			} else {
   1538 				ldap_pvt_thread_yield();
   1539 			}
   1540 		}
   1541 	}
   1542 
   1543 	if ( rc == -1 ) {
   1544 		/*
   1545 		 * FIXME: need a better strategy to handle errors
   1546 		 */
   1547 		if ( mc ) {
   1548 			rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE,
   1549 				-1, stoptime != -1 ? (stoptime - slap_get_time()) : 0,
   1550 				LDAP_BACK_SENDERR );
   1551 		} else {
   1552 			rc = rs->sr_err;
   1553 		}
   1554 		goto finish;
   1555 	}
   1556 
   1557 	/*
   1558 	 * Rewrite the matched portion of the search base, if required
   1559 	 *
   1560 	 * FIXME: only the last one gets caught!
   1561 	 */
   1562 	savepriv = op->o_private;
   1563 	op->o_private = (void *)(long)mi->mi_ntargets;
   1564 	if ( candidate_match > 0 ) {
   1565 		struct berval	pmatched = BER_BVNULL;
   1566 
   1567 		/* we use the first one */
   1568 		for ( i = 0; i < mi->mi_ntargets; i++ ) {
   1569 			if ( META_IS_CANDIDATE( &candidates[ i ] )
   1570 					&& candidates[ i ].sr_matched != NULL )
   1571 			{
   1572 				struct berval	bv, pbv;
   1573 				int		rc;
   1574 
   1575 				/* if we got success, and this target
   1576 				 * returned noSuchObject, and its suffix
   1577 				 * is a superior of the searchBase,
   1578 				 * ignore the matchedDN */
   1579 				if ( sres == LDAP_SUCCESS
   1580 					&& candidates[ i ].sr_err == LDAP_NO_SUCH_OBJECT
   1581 					&& op->o_req_ndn.bv_len > mi->mi_targets[ i ]->mt_nsuffix.bv_len )
   1582 				{
   1583 					free( (char *)candidates[ i ].sr_matched );
   1584 					candidates[ i ].sr_matched = NULL;
   1585 					continue;
   1586 				}
   1587 
   1588 				ber_str2bv( candidates[ i ].sr_matched, 0, 0, &bv );
   1589 				rc = dnPretty( NULL, &bv, &pbv, op->o_tmpmemctx );
   1590 
   1591 				if ( rc == LDAP_SUCCESS ) {
   1592 
   1593 					/* NOTE: if they all are superiors
   1594 					 * of the baseDN, the shorter is also
   1595 					 * superior of the longer... */
   1596 					if ( pbv.bv_len > pmatched.bv_len ) {
   1597 						if ( !BER_BVISNULL( &pmatched ) ) {
   1598 							op->o_tmpfree( pmatched.bv_val, op->o_tmpmemctx );
   1599 						}
   1600 						pmatched = pbv;
   1601 						op->o_private = (void *)i;
   1602 
   1603 					} else {
   1604 						op->o_tmpfree( pbv.bv_val, op->o_tmpmemctx );
   1605 					}
   1606 				}
   1607 
   1608 				if ( candidates[ i ].sr_matched != NULL ) {
   1609 					free( (char *)candidates[ i ].sr_matched );
   1610 					candidates[ i ].sr_matched = NULL;
   1611 				}
   1612 			}
   1613 		}
   1614 
   1615 		if ( !BER_BVISNULL( &pmatched ) ) {
   1616 			matched = pmatched.bv_val;
   1617 		}
   1618 
   1619 	} else if ( sres == LDAP_NO_SUCH_OBJECT ) {
   1620 		matched = op->o_bd->be_suffix[ 0 ].bv_val;
   1621 	}
   1622 
   1623 	/*
   1624 	 * In case we returned at least one entry, we return LDAP_SUCCESS
   1625 	 * otherwise, the latter error code we got
   1626 	 */
   1627 
   1628 	if ( sres == LDAP_SUCCESS ) {
   1629 		if ( rs->sr_v2ref ) {
   1630 			sres = LDAP_REFERRAL;
   1631 		}
   1632 
   1633 		if ( META_BACK_ONERR_REPORT( mi ) ) {
   1634 			/*
   1635 			 * Report errors, if any
   1636 			 *
   1637 			 * FIXME: we should handle error codes and return the more
   1638 			 * important/reasonable
   1639 			 */
   1640 			for ( i = 0; i < mi->mi_ntargets; i++ ) {
   1641 				if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
   1642 					continue;
   1643 				}
   1644 
   1645 				if ( candidates[ i ].sr_err != LDAP_SUCCESS
   1646 					&& candidates[ i ].sr_err != LDAP_NO_SUCH_OBJECT )
   1647 				{
   1648 					sres = candidates[ i ].sr_err;
   1649 					break;
   1650 				}
   1651 			}
   1652 		}
   1653 	}
   1654 
   1655 	rs->sr_err = sres;
   1656 	rs->sr_matched = matched;
   1657 	rs->sr_ref = ( sres == LDAP_REFERRAL ? rs->sr_v2ref : NULL );
   1658 	send_ldap_result( op, rs );
   1659 	op->o_private = savepriv;
   1660 	rs->sr_matched = NULL;
   1661 	rs->sr_ref = NULL;
   1662 
   1663 finish:;
   1664 	if ( matched && matched != op->o_bd->be_suffix[ 0 ].bv_val ) {
   1665 		op->o_tmpfree( matched, op->o_tmpmemctx );
   1666 	}
   1667 
   1668 	if ( rs->sr_v2ref ) {
   1669 		ber_bvarray_free( rs->sr_v2ref );
   1670 	}
   1671 
   1672 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
   1673 		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
   1674 			continue;
   1675 		}
   1676 
   1677 		if ( mc ) {
   1678 			if ( META_IS_BINDING( &candidates[ i ] )
   1679 				|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
   1680 			{
   1681 				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
   1682 				if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
   1683 					|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
   1684 				{
   1685 					assert( candidates[ i ].sr_msgid >= 0
   1686 						|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING );
   1687 					assert( mc->mc_conns[ i ].msc_ld != NULL );
   1688 
   1689 #ifdef DEBUG_205
   1690 					Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
   1691 						"ldap_unbind_ext[%ld] ld=%p\n",
   1692 						op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
   1693 #endif /* DEBUG_205 */
   1694 
   1695 					/* if still binding, destroy */
   1696 					meta_clear_one_candidate( op, mc, i );
   1697 				}
   1698 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
   1699 				META_BINDING_CLEAR( &candidates[ i ] );
   1700 
   1701 			} else if ( candidates[ i ].sr_msgid >= 0 ) {
   1702 				(void)meta_back_cancel( mc, op, rs,
   1703 					candidates[ i ].sr_msgid, i,
   1704 					LDAP_BACK_DONTSEND );
   1705 			}
   1706 		}
   1707 
   1708 		if ( candidates[ i ].sr_matched ) {
   1709 			free( (char *)candidates[ i ].sr_matched );
   1710 			candidates[ i ].sr_matched = NULL;
   1711 		}
   1712 
   1713 		if ( candidates[ i ].sr_text ) {
   1714 			ldap_memfree( (char *)candidates[ i ].sr_text );
   1715 			candidates[ i ].sr_text = NULL;
   1716 		}
   1717 
   1718 		if ( candidates[ i ].sr_ref ) {
   1719 			ber_bvarray_free( candidates[ i ].sr_ref );
   1720 			candidates[ i ].sr_ref = NULL;
   1721 		}
   1722 
   1723 		if ( candidates[ i ].sr_ctrls ) {
   1724 			ldap_controls_free( candidates[ i ].sr_ctrls );
   1725 			candidates[ i ].sr_ctrls = NULL;
   1726 		}
   1727 
   1728 		if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {
   1729 			meta_back_quarantine( op, &candidates[ i ], i );
   1730 		}
   1731 
   1732 		/* only in case of timelimit exceeded, if the timelimit exceeded because
   1733 		 * one contacted target never responded, invalidate the connection
   1734 		 * NOTE: should we quarantine the target as well?  right now, the connection
   1735 		 * is invalidated; the next time it will be recreated and the target
   1736 		 * will be quarantined if it cannot be contacted */
   1737 		if ( mi->mi_idle_timeout != 0
   1738 			&& rs->sr_err == LDAP_TIMELIMIT_EXCEEDED
   1739 			&& op->o_time > mc->mc_conns[ i ].msc_time )
   1740 		{
   1741 			/* don't let anyone else use this expired connection */
   1742 			LDAP_BACK_CONN_TAINTED_SET( mc );
   1743 		}
   1744 	}
   1745 
   1746 	if ( mc ) {
   1747 		meta_back_release_conn( mi, mc );
   1748 	}
   1749 
   1750 	return rs->sr_err;
   1751 }
   1752 
   1753 static int
   1754 meta_send_entry(
   1755 	Operation 	*op,
   1756 	SlapReply	*rs,
   1757 	metaconn_t	*mc,
   1758 	int 		target,
   1759 	LDAPMessage 	*e )
   1760 {
   1761 	metainfo_t 		*mi = ( metainfo_t * )op->o_bd->be_private;
   1762 	struct berval		a, mapped;
   1763 	int			check_duplicate_attrs = 0;
   1764 	Entry 			ent = { 0 };
   1765 	BerElement 		ber = *e->lm_ber;
   1766 	Attribute 		*attr, **attrp;
   1767 	struct berval 		bdn,
   1768 				dn = BER_BVNULL;
   1769 	const char 		*text;
   1770 	dncookie		dc;
   1771 	int			rc;
   1772 
   1773 	if ( ber_scanf( &ber, "{m{", &bdn ) == LBER_ERROR ) {
   1774 		return LDAP_DECODING_ERROR;
   1775 	}
   1776 
   1777 	/*
   1778 	 * Rewrite the dn of the result, if needed
   1779 	 */
   1780 	dc.target = mi->mi_targets[ target ];
   1781 	dc.conn = op->o_conn;
   1782 	dc.rs = rs;
   1783 	dc.ctx = "searchResult";
   1784 
   1785 	rs->sr_err = ldap_back_dn_massage( &dc, &bdn, &dn );
   1786 	if ( rs->sr_err != LDAP_SUCCESS) {
   1787 		return rs->sr_err;
   1788 	}
   1789 
   1790 	/*
   1791 	 * Note: this may fail if the target host(s) schema differs
   1792 	 * from the one known to the meta, and a DN with unknown
   1793 	 * attributes is returned.
   1794 	 *
   1795 	 * FIXME: should we log anything, or delegate to dnNormalize?
   1796 	 */
   1797 	rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname,
   1798 		op->o_tmpmemctx );
   1799 	if ( dn.bv_val != bdn.bv_val ) {
   1800 		free( dn.bv_val );
   1801 	}
   1802 	BER_BVZERO( &dn );
   1803 
   1804 	if ( rc != LDAP_SUCCESS ) {
   1805 		return LDAP_INVALID_DN_SYNTAX;
   1806 	}
   1807 
   1808 	/*
   1809 	 * cache dn
   1810 	 */
   1811 	if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {
   1812 		( void )meta_dncache_update_entry( &mi->mi_cache,
   1813 				&ent.e_nname, target );
   1814 	}
   1815 
   1816 	attrp = &ent.e_attrs;
   1817 
   1818 	dc.ctx = "searchAttrDN";
   1819 	while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
   1820 		int				last = 0;
   1821 		slap_syntax_validate_func	*validate;
   1822 		slap_syntax_transform_func	*pretty;
   1823 
   1824 		ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_at,
   1825 				&a, &mapped, BACKLDAP_REMAP );
   1826 		if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
   1827 			( void )ber_scanf( &ber, "x" /* [W] */ );
   1828 			continue;
   1829 		}
   1830 		if ( mapped.bv_val != a.bv_val ) {
   1831 			/* will need to check for duplicate attrs */
   1832 			check_duplicate_attrs++;
   1833 		}
   1834 		attr = attr_alloc( NULL );
   1835 		if ( attr == NULL ) {
   1836 			continue;
   1837 		}
   1838 		if ( slap_bv2ad( &mapped, &attr->a_desc, &text )
   1839 				!= LDAP_SUCCESS) {
   1840 			if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text,
   1841 				SLAP_AD_PROXIED ) != LDAP_SUCCESS )
   1842 			{
   1843 				char	buf[ SLAP_TEXT_BUFLEN ];
   1844 
   1845 				snprintf( buf, sizeof( buf ),
   1846 					"%s meta_send_entry(\"%s\"): "
   1847 					"slap_bv2undef_ad(%s): %s\n",
   1848 					op->o_log_prefix, ent.e_name.bv_val,
   1849 					mapped.bv_val, text );
   1850 
   1851 				Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 );
   1852 				attr_free( attr );
   1853 				continue;
   1854 			}
   1855 		}
   1856 
   1857 		/* no subschemaSubentry */
   1858 		if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
   1859 			|| attr->a_desc == slap_schema.si_ad_entryDN )
   1860 		{
   1861 
   1862 			/*
   1863 			 * We eat target's subschemaSubentry because
   1864 			 * a search for this value is likely not
   1865 			 * to resolve to the appropriate backend;
   1866 			 * later, the local subschemaSubentry is
   1867 			 * added.
   1868 			 *
   1869 			 * We also eat entryDN because the frontend
   1870 			 * will reattach it without checking if already
   1871 			 * present...
   1872 			 */
   1873 			( void )ber_scanf( &ber, "x" /* [W] */ );
   1874 
   1875 			attr_free(attr);
   1876 			continue;
   1877 		}
   1878 
   1879 		if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
   1880 				|| attr->a_vals == NULL )
   1881 		{
   1882 			attr->a_vals = (struct berval *)&slap_dummy_bv;
   1883 
   1884 		} else {
   1885 			for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last )
   1886 				;
   1887 		}
   1888 		attr->a_numvals = last;
   1889 
   1890 		validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
   1891 		pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;
   1892 
   1893 		if ( !validate && !pretty ) {
   1894 			attr_free( attr );
   1895 			goto next_attr;
   1896 		}
   1897 
   1898 		if ( attr->a_desc == slap_schema.si_ad_objectClass
   1899 				|| attr->a_desc == slap_schema.si_ad_structuralObjectClass )
   1900 		{
   1901 			struct berval 	*bv;
   1902 
   1903 			for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) {
   1904 				ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
   1905 						bv, &mapped, BACKLDAP_REMAP );
   1906 				if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
   1907 remove_oc:;
   1908 					free( bv->bv_val );
   1909 					BER_BVZERO( bv );
   1910 					if ( --last < 0 ) {
   1911 						break;
   1912 					}
   1913 					*bv = attr->a_vals[ last ];
   1914 					BER_BVZERO( &attr->a_vals[ last ] );
   1915 					bv--;
   1916 
   1917 				} else if ( mapped.bv_val != bv->bv_val ) {
   1918 					int	i;
   1919 
   1920 					for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {
   1921 						if ( &attr->a_vals[ i ] == bv ) {
   1922 							continue;
   1923 						}
   1924 
   1925 						if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) {
   1926 							break;
   1927 						}
   1928 					}
   1929 
   1930 					if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) {
   1931 						goto remove_oc;
   1932 					}
   1933 
   1934 					ber_bvreplace( bv, &mapped );
   1935 				}
   1936 			}
   1937 		/*
   1938 		 * It is necessary to try to rewrite attributes with
   1939 		 * dn syntax because they might be used in ACLs as
   1940 		 * members of groups; since ACLs are applied to the
   1941 		 * rewritten stuff, no dn-based subecj clause could
   1942 		 * be used at the ldap backend side (see
   1943 		 * http://www.OpenLDAP.org/faq/data/cache/452.html)
   1944 		 * The problem can be overcome by moving the dn-based
   1945 		 * ACLs to the target directory server, and letting
   1946 		 * everything pass thru the ldap backend.
   1947 		 */
   1948 		} else {
   1949 			int	i;
   1950 
   1951 			if ( attr->a_desc->ad_type->sat_syntax ==
   1952 				slap_schema.si_syn_distinguishedName )
   1953 			{
   1954 				ldap_dnattr_result_rewrite( &dc, attr->a_vals );
   1955 
   1956 			} else if ( attr->a_desc == slap_schema.si_ad_ref ) {
   1957 				ldap_back_referral_result_rewrite( &dc, attr->a_vals );
   1958 
   1959 			}
   1960 
   1961 			for ( i = 0; i < last; i++ ) {
   1962 				struct berval	pval;
   1963 				int		rc;
   1964 
   1965 				if ( pretty ) {
   1966 					rc = pretty( attr->a_desc->ad_type->sat_syntax,
   1967 						&attr->a_vals[i], &pval, NULL );
   1968 
   1969 				} else {
   1970 					rc = validate( attr->a_desc->ad_type->sat_syntax,
   1971 						&attr->a_vals[i] );
   1972 				}
   1973 
   1974 				if ( rc ) {
   1975 					LBER_FREE( attr->a_vals[i].bv_val );
   1976 					if ( --last == i ) {
   1977 						BER_BVZERO( &attr->a_vals[ i ] );
   1978 						break;
   1979 					}
   1980 					attr->a_vals[i] = attr->a_vals[last];
   1981 					BER_BVZERO( &attr->a_vals[last] );
   1982 					i--;
   1983 					continue;
   1984 				}
   1985 
   1986 				if ( pretty ) {
   1987 					LBER_FREE( attr->a_vals[i].bv_val );
   1988 					attr->a_vals[i] = pval;
   1989 				}
   1990 			}
   1991 
   1992 			if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
   1993 				attr_free( attr );
   1994 				goto next_attr;
   1995 			}
   1996 		}
   1997 
   1998 		if ( last && attr->a_desc->ad_type->sat_equality &&
   1999 			attr->a_desc->ad_type->sat_equality->smr_normalize )
   2000 		{
   2001 			int i;
   2002 
   2003 			attr->a_nvals = ch_malloc( ( last + 1 ) * sizeof( struct berval ) );
   2004 			for ( i = 0; i<last; i++ ) {
   2005 				attr->a_desc->ad_type->sat_equality->smr_normalize(
   2006 					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
   2007 					attr->a_desc->ad_type->sat_syntax,
   2008 					attr->a_desc->ad_type->sat_equality,
   2009 					&attr->a_vals[i], &attr->a_nvals[i],
   2010 					NULL );
   2011 			}
   2012 			BER_BVZERO( &attr->a_nvals[i] );
   2013 
   2014 		} else {
   2015 			attr->a_nvals = attr->a_vals;
   2016 		}
   2017 
   2018 		*attrp = attr;
   2019 		attrp = &attr->a_next;
   2020 next_attr:;
   2021 	}
   2022 
   2023 	/* only check if some mapping occurred */
   2024 	if ( check_duplicate_attrs ) {
   2025 		Attribute	**ap;
   2026 
   2027 		for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) {
   2028 			Attribute	**tap;
   2029 
   2030 			for ( tap = &(*ap)->a_next; *tap != NULL; ) {
   2031 				if ( (*tap)->a_desc == (*ap)->a_desc ) {
   2032 					Entry		e = { 0 };
   2033 					Modification	mod = { 0 };
   2034 					const char	*text = NULL;
   2035 					char		textbuf[ SLAP_TEXT_BUFLEN ];
   2036 					Attribute	*next = (*tap)->a_next;
   2037 
   2038 					BER_BVSTR( &e.e_name, "" );
   2039 					BER_BVSTR( &e.e_nname, "" );
   2040 					e.e_attrs = *ap;
   2041 					mod.sm_op = LDAP_MOD_ADD;
   2042 					mod.sm_desc = (*ap)->a_desc;
   2043 					mod.sm_type = mod.sm_desc->ad_cname;
   2044 					mod.sm_numvals = (*ap)->a_numvals;
   2045 					mod.sm_values = (*tap)->a_vals;
   2046 					if ( (*tap)->a_nvals != (*tap)->a_vals ) {
   2047 						mod.sm_nvalues = (*tap)->a_nvals;
   2048 					}
   2049 
   2050 					(void)modify_add_values( &e, &mod,
   2051 						/* permissive */ 1,
   2052 						&text, textbuf, sizeof( textbuf ) );
   2053 
   2054 					/* should not insert new attrs! */
   2055 					assert( e.e_attrs == *ap );
   2056 
   2057 					attr_free( *tap );
   2058 					*tap = next;
   2059 
   2060 				} else {
   2061 					tap = &(*tap)->a_next;
   2062 				}
   2063 			}
   2064 		}
   2065 	}
   2066 
   2067 	ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
   2068 		e, &rs->sr_ctrls );
   2069 	rs->sr_entry = &ent;
   2070 	rs->sr_attrs = op->ors_attrs;
   2071 	rs->sr_operational_attrs = NULL;
   2072 	rs->sr_flags = 0;
   2073 	rs->sr_err = LDAP_SUCCESS;
   2074 	rc = send_search_entry( op, rs );
   2075 	switch ( rc ) {
   2076 	case LDAP_UNAVAILABLE:
   2077 		rc = LDAP_OTHER;
   2078 		break;
   2079 	}
   2080 	rs->sr_entry = NULL;
   2081 	rs->sr_attrs = NULL;
   2082 	if ( rs->sr_ctrls != NULL ) {
   2083 		ldap_controls_free( rs->sr_ctrls );
   2084 		rs->sr_ctrls = NULL;
   2085 	}
   2086 	if ( !BER_BVISNULL( &ent.e_name ) ) {
   2087 		free( ent.e_name.bv_val );
   2088 		BER_BVZERO( &ent.e_name );
   2089 	}
   2090 	if ( !BER_BVISNULL( &ent.e_nname ) ) {
   2091 		free( ent.e_nname.bv_val );
   2092 		BER_BVZERO( &ent.e_nname );
   2093 	}
   2094 	entry_clean( &ent );
   2095 
   2096 	return rc;
   2097 }
   2098 
   2099