mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-12 10:54:48 +08:00
cleanup and streamline response handling
This commit is contained in:
parent
968da1cb14
commit
f449ee6500
@ -117,6 +117,10 @@ meta_search_dobind_init(
|
|||||||
/* for some reason (e.g. because formerly in "binding"
|
/* for some reason (e.g. because formerly in "binding"
|
||||||
* state, with eventual connection expiration or invalidation)
|
* state, with eventual connection expiration or invalidation)
|
||||||
* it was not initialized as expected */
|
* it was not initialized as expected */
|
||||||
|
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] ld=NULL\n",
|
||||||
|
op->o_log_prefix, candidate, 0 );
|
||||||
|
|
||||||
rc = meta_back_init_one_conn( op, rs, *mcp, candidate,
|
rc = meta_back_init_one_conn( op, rs, *mcp, candidate,
|
||||||
LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND );
|
LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND );
|
||||||
switch ( rc ) {
|
switch ( rc ) {
|
||||||
@ -175,6 +179,8 @@ meta_search_dobind_init(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert( msc->msc_ld != NULL );
|
||||||
|
|
||||||
rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
|
rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
|
||||||
NULL, NULL, &candidates[ candidate ].sr_msgid );
|
NULL, NULL, &candidates[ candidate ].sr_msgid );
|
||||||
switch ( rc ) {
|
switch ( rc ) {
|
||||||
@ -182,8 +188,8 @@ meta_search_dobind_init(
|
|||||||
META_BINDING_SET( &candidates[ candidate ] );
|
META_BINDING_SET( &candidates[ candidate ] );
|
||||||
return META_SEARCH_BINDING;
|
return META_SEARCH_BINDING;
|
||||||
|
|
||||||
down:;
|
|
||||||
case LDAP_SERVER_DOWN:
|
case LDAP_SERVER_DOWN:
|
||||||
|
down:;
|
||||||
/* This is the worst thing that could happen:
|
/* This is the worst thing that could happen:
|
||||||
* the search will wait until the retry is over. */
|
* the search will wait until the retry is over. */
|
||||||
if ( meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
|
if ( meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
|
||||||
@ -197,8 +203,8 @@ down:;
|
|||||||
}
|
}
|
||||||
/* fall thru */
|
/* fall thru */
|
||||||
|
|
||||||
other:;
|
|
||||||
default:
|
default:
|
||||||
|
other:;
|
||||||
rs->sr_err = rc;
|
rs->sr_err = rc;
|
||||||
rc = slap_map_api2result( rs );
|
rc = slap_map_api2result( rs );
|
||||||
|
|
||||||
@ -243,7 +249,7 @@ meta_search_dobind_result(
|
|||||||
/* FIXME: matched? referrals? response controls? */
|
/* FIXME: matched? referrals? response controls? */
|
||||||
rc = ldap_parse_result( msc->msc_ld, res,
|
rc = ldap_parse_result( msc->msc_ld, res,
|
||||||
&candidates[ candidate ].sr_err,
|
&candidates[ candidate ].sr_err,
|
||||||
NULL, NULL, NULL, NULL, 1 );
|
NULL, NULL, NULL, NULL, 0 );
|
||||||
if ( rc != LDAP_SUCCESS ) {
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
candidates[ candidate ].sr_err = rc;
|
candidates[ candidate ].sr_err = rc;
|
||||||
}
|
}
|
||||||
@ -525,7 +531,6 @@ meta_back_search( Operation *op, SlapReply *rs )
|
|||||||
metaconn_t *mc;
|
metaconn_t *mc;
|
||||||
struct timeval tv = { 0, 0 };
|
struct timeval tv = { 0, 0 };
|
||||||
time_t stoptime = (time_t)-1;
|
time_t stoptime = (time_t)-1;
|
||||||
LDAPMessage *res = NULL, *e;
|
|
||||||
int rc = 0, sres = LDAP_SUCCESS;
|
int rc = 0, sres = LDAP_SUCCESS;
|
||||||
char *matched = NULL;
|
char *matched = NULL;
|
||||||
int last = 0, ncandidates = 0,
|
int last = 0, ncandidates = 0,
|
||||||
@ -678,6 +683,7 @@ meta_back_search( Operation *op, SlapReply *rs )
|
|||||||
|
|
||||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||||
metasingleconn_t *msc = &mc->mc_conns[ i ];
|
metasingleconn_t *msc = &mc->mc_conns[ i ];
|
||||||
|
LDAPMessage *res = NULL, *msg;
|
||||||
|
|
||||||
if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
|
if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
|
||||||
continue;
|
continue;
|
||||||
@ -721,7 +727,7 @@ meta_back_search( Operation *op, SlapReply *rs )
|
|||||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
||||||
{
|
{
|
||||||
case META_SEARCH_CANDIDATE:
|
case META_SEARCH_CANDIDATE:
|
||||||
goto get_result;
|
break;
|
||||||
|
|
||||||
/* means that failed but onerr == continue */
|
/* means that failed but onerr == continue */
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
@ -765,9 +771,8 @@ meta_back_search( Operation *op, SlapReply *rs )
|
|||||||
* get a LDAP_TIMELIMIT_EXCEEDED from
|
* get a LDAP_TIMELIMIT_EXCEEDED from
|
||||||
* one of them ...
|
* one of them ...
|
||||||
*/
|
*/
|
||||||
get_result:;
|
|
||||||
rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid,
|
rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid,
|
||||||
LDAP_MSG_ONE, &tv, &res );
|
LDAP_MSG_RECEIVED, &tv, &res );
|
||||||
switch ( rc ) {
|
switch ( rc ) {
|
||||||
case 0:
|
case 0:
|
||||||
/* FIXME: res should not need to be freed */
|
/* FIXME: res should not need to be freed */
|
||||||
@ -785,7 +790,7 @@ really_bad:;
|
|||||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
||||||
{
|
{
|
||||||
case META_SEARCH_CANDIDATE:
|
case META_SEARCH_CANDIDATE:
|
||||||
goto get_result;
|
break;
|
||||||
|
|
||||||
/* means that failed but onerr == continue */
|
/* means that failed but onerr == continue */
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
@ -837,333 +842,332 @@ really_bad:;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( rc == LDAP_RES_SEARCH_ENTRY ) {
|
for ( msg = ldap_first_message( msc->msc_ld, res );
|
||||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
msg != NULL;
|
||||||
/* don't retry any more... */
|
msg = ldap_next_message( msc->msc_ld, msg ) )
|
||||||
candidates[ i ].sr_type = REP_RESULT;
|
{
|
||||||
}
|
rc = ldap_msgtype( msg );
|
||||||
|
if ( rc == LDAP_RES_SEARCH_ENTRY ) {
|
||||||
|
LDAPMessage *e;
|
||||||
|
|
||||||
is_ok++;
|
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||||
|
/* don't retry any more... */
|
||||||
e = ldap_first_entry( msc->msc_ld, res );
|
candidates[ i ].sr_type = REP_RESULT;
|
||||||
savepriv = op->o_private;
|
|
||||||
op->o_private = (void *)i;
|
|
||||||
rs->sr_err = meta_send_entry( op, rs, mc, i, e );
|
|
||||||
ldap_msgfree( res );
|
|
||||||
res = NULL;
|
|
||||||
|
|
||||||
switch ( rs->sr_err ) {
|
|
||||||
case LDAP_SIZELIMIT_EXCEEDED:
|
|
||||||
savepriv = op->o_private;
|
|
||||||
op->o_private = (void *)i;
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
op->o_private = savepriv;
|
|
||||||
rs->sr_err = LDAP_SUCCESS;
|
|
||||||
goto finish;
|
|
||||||
|
|
||||||
case LDAP_UNAVAILABLE:
|
|
||||||
rs->sr_err = LDAP_OTHER;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
op->o_private = savepriv;
|
|
||||||
|
|
||||||
/* don't wait any longer... */
|
|
||||||
gotit = 1;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* If scope is BASE, we need to jump out
|
|
||||||
* as soon as one entry is found; if
|
|
||||||
* the target pool is properly crafted,
|
|
||||||
* this should correspond to the sole
|
|
||||||
* entry that has the base DN
|
|
||||||
*/
|
|
||||||
/* FIXME: this defeats the purpose of
|
|
||||||
* doing a search with scope == base and
|
|
||||||
* sizelimit = 1 to determine if a
|
|
||||||
* candidate is actually unique */
|
|
||||||
if ( op->ors_scope == LDAP_SCOPE_BASE
|
|
||||||
&& rs->sr_nentries > 0 )
|
|
||||||
{
|
|
||||||
doabandon = 1;
|
|
||||||
ncandidates = 0;
|
|
||||||
sres = LDAP_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
|
|
||||||
char **references = NULL;
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
|
||||||
/* don't retry any more... */
|
|
||||||
candidates[ i ].sr_type = REP_RESULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_ok++;
|
|
||||||
|
|
||||||
rc = ldap_parse_reference( msc->msc_ld, res,
|
|
||||||
&references, &rs->sr_ctrls, 1 );
|
|
||||||
res = NULL;
|
|
||||||
|
|
||||||
if ( rc != LDAP_SUCCESS ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( references == NULL ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_REWRITE
|
|
||||||
dc.ctx = "referralDN";
|
|
||||||
#else /* ! ENABLE_REWRITE */
|
|
||||||
dc.tofrom = 0;
|
|
||||||
dc.normalized = 0;
|
|
||||||
#endif /* ! ENABLE_REWRITE */
|
|
||||||
|
|
||||||
/* FIXME: merge all and return at the end */
|
|
||||||
|
|
||||||
for ( cnt = 0; references[ cnt ]; cnt++ )
|
|
||||||
;
|
|
||||||
|
|
||||||
rs->sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
|
|
||||||
|
|
||||||
for ( cnt = 0; references[ cnt ]; cnt++ ) {
|
|
||||||
ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );
|
|
||||||
}
|
|
||||||
BER_BVZERO( &rs->sr_ref[ cnt ] );
|
|
||||||
|
|
||||||
( void )ldap_back_referral_result_rewrite( &dc, rs->sr_ref );
|
|
||||||
|
|
||||||
if ( rs->sr_ref != NULL && !BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
|
|
||||||
/* ignore return value by now */
|
|
||||||
savepriv = op->o_private;
|
|
||||||
op->o_private = (void *)i;
|
|
||||||
( void )send_search_reference( op, rs );
|
|
||||||
op->o_private = savepriv;
|
|
||||||
|
|
||||||
ber_bvarray_free( rs->sr_ref );
|
|
||||||
rs->sr_ref = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cleanup */
|
|
||||||
if ( references ) {
|
|
||||||
ber_memvfree( (void **)references );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( rs->sr_ctrls ) {
|
|
||||||
ldap_controls_free( rs->sr_ctrls );
|
|
||||||
rs->sr_ctrls = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ( rc == LDAP_RES_SEARCH_RESULT ) {
|
|
||||||
char buf[ SLAP_TEXT_BUFLEN ];
|
|
||||||
char **references = NULL;
|
|
||||||
|
|
||||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
|
||||||
/* don't retry any more... */
|
|
||||||
candidates[ i ].sr_type = REP_RESULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTE: ignores response controls
|
|
||||||
* (and intermediate response controls
|
|
||||||
* as well, except for those with search
|
|
||||||
* references); this may not be correct,
|
|
||||||
* but if they're not ignored then
|
|
||||||
* back-meta would need to merge them
|
|
||||||
* consistently (think of pagedResults...)
|
|
||||||
*/
|
|
||||||
/* FIXME: response controls? */
|
|
||||||
rs->sr_err = ldap_parse_result( msc->msc_ld,
|
|
||||||
res,
|
|
||||||
&candidates[ i ].sr_err,
|
|
||||||
(char **)&candidates[ i ].sr_matched,
|
|
||||||
NULL /* (char **)&candidates[ i ].sr_text */ ,
|
|
||||||
&references,
|
|
||||||
NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
|
|
||||||
1 );
|
|
||||||
res = NULL;
|
|
||||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
|
||||||
ldap_get_option( msc->msc_ld,
|
|
||||||
LDAP_OPT_RESULT_CODE,
|
|
||||||
&rs->sr_err );
|
|
||||||
sres = slap_map_api2result( rs );
|
|
||||||
candidates[ i ].sr_type = REP_RESULT;
|
|
||||||
goto really_bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* massage matchedDN if need be */
|
|
||||||
if ( candidates[ i ].sr_matched != NULL ) {
|
|
||||||
struct berval match, mmatch;
|
|
||||||
|
|
||||||
ber_str2bv( candidates[ i ].sr_matched,
|
|
||||||
0, 0, &match );
|
|
||||||
candidates[ i ].sr_matched = NULL;
|
|
||||||
|
|
||||||
dc.ctx = "matchedDN";
|
|
||||||
dc.target = mi->mi_targets[ i ];
|
|
||||||
if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {
|
|
||||||
if ( mmatch.bv_val == match.bv_val ) {
|
|
||||||
candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
candidates[ i ].sr_matched = mmatch.bv_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
candidate_match++;
|
|
||||||
}
|
}
|
||||||
ldap_memfree( match.bv_val );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add references to array */
|
is_ok++;
|
||||||
if ( references ) {
|
|
||||||
BerVarray sr_ref;
|
e = ldap_first_entry( msc->msc_ld, msg );
|
||||||
|
savepriv = op->o_private;
|
||||||
|
op->o_private = (void *)i;
|
||||||
|
rs->sr_err = meta_send_entry( op, rs, mc, i, e );
|
||||||
|
|
||||||
|
switch ( rs->sr_err ) {
|
||||||
|
case LDAP_SIZELIMIT_EXCEEDED:
|
||||||
|
savepriv = op->o_private;
|
||||||
|
op->o_private = (void *)i;
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
op->o_private = savepriv;
|
||||||
|
rs->sr_err = LDAP_SUCCESS;
|
||||||
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
case LDAP_UNAVAILABLE:
|
||||||
|
rs->sr_err = LDAP_OTHER;
|
||||||
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
op->o_private = savepriv;
|
||||||
|
|
||||||
|
/* don't wait any longer... */
|
||||||
|
gotit = 1;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
|
||||||
|
char **references = NULL;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
|
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||||
|
/* don't retry any more... */
|
||||||
|
candidates[ i ].sr_type = REP_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_ok++;
|
||||||
|
|
||||||
|
rc = ldap_parse_reference( msc->msc_ld, msg,
|
||||||
|
&references, &rs->sr_ctrls, 0 );
|
||||||
|
|
||||||
|
if ( rc != LDAP_SUCCESS ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( references == NULL ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_REWRITE
|
||||||
|
dc.ctx = "referralDN";
|
||||||
|
#else /* ! ENABLE_REWRITE */
|
||||||
|
dc.tofrom = 0;
|
||||||
|
dc.normalized = 0;
|
||||||
|
#endif /* ! ENABLE_REWRITE */
|
||||||
|
|
||||||
|
/* FIXME: merge all and return at the end */
|
||||||
for ( cnt = 0; references[ cnt ]; cnt++ )
|
for ( cnt = 0; references[ cnt ]; cnt++ )
|
||||||
;
|
;
|
||||||
|
|
||||||
sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
|
rs->sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
|
||||||
|
|
||||||
for ( cnt = 0; references[ cnt ]; cnt++ ) {
|
for ( cnt = 0; references[ cnt ]; cnt++ ) {
|
||||||
ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
|
ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );
|
||||||
}
|
}
|
||||||
BER_BVZERO( &sr_ref[ cnt ] );
|
BER_BVZERO( &rs->sr_ref[ cnt ] );
|
||||||
|
|
||||||
( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
|
( void )ldap_back_referral_result_rewrite( &dc, rs->sr_ref );
|
||||||
|
|
||||||
|
if ( rs->sr_ref != NULL && !BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
|
||||||
|
/* ignore return value by now */
|
||||||
|
savepriv = op->o_private;
|
||||||
|
op->o_private = (void *)i;
|
||||||
|
( void )send_search_reference( op, rs );
|
||||||
|
op->o_private = savepriv;
|
||||||
|
|
||||||
|
ber_bvarray_free( rs->sr_ref );
|
||||||
|
rs->sr_ref = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
ber_memvfree( (void **)references );
|
if ( references ) {
|
||||||
|
ber_memvfree( (void **)references );
|
||||||
|
}
|
||||||
|
|
||||||
if ( rs->sr_v2ref == NULL ) {
|
if ( rs->sr_ctrls ) {
|
||||||
rs->sr_v2ref = sr_ref;
|
ldap_controls_free( rs->sr_ctrls );
|
||||||
|
rs->sr_ctrls = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else if ( rc == LDAP_RES_SEARCH_RESULT ) {
|
||||||
for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
|
char buf[ SLAP_TEXT_BUFLEN ];
|
||||||
ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
|
char **references = NULL;
|
||||||
|
|
||||||
|
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||||
|
/* don't retry any more... */
|
||||||
|
candidates[ i ].sr_type = REP_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: ignores response controls
|
||||||
|
* (and intermediate response controls
|
||||||
|
* as well, except for those with search
|
||||||
|
* references); this may not be correct,
|
||||||
|
* but if they're not ignored then
|
||||||
|
* back-meta would need to merge them
|
||||||
|
* consistently (think of pagedResults...)
|
||||||
|
*/
|
||||||
|
/* FIXME: response controls? */
|
||||||
|
rs->sr_err = ldap_parse_result( msc->msc_ld,
|
||||||
|
msg,
|
||||||
|
&candidates[ i ].sr_err,
|
||||||
|
(char **)&candidates[ i ].sr_matched,
|
||||||
|
NULL /* (char **)&candidates[ i ].sr_text */ ,
|
||||||
|
&references,
|
||||||
|
NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
|
||||||
|
0 );
|
||||||
|
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||||
|
ldap_get_option( msc->msc_ld,
|
||||||
|
LDAP_OPT_RESULT_CODE,
|
||||||
|
&rs->sr_err );
|
||||||
|
sres = slap_map_api2result( rs );
|
||||||
|
candidates[ i ].sr_type = REP_RESULT;
|
||||||
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
|
goto really_bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* massage matchedDN if need be */
|
||||||
|
if ( candidates[ i ].sr_matched != NULL ) {
|
||||||
|
struct berval match, mmatch;
|
||||||
|
|
||||||
|
ber_str2bv( candidates[ i ].sr_matched,
|
||||||
|
0, 0, &match );
|
||||||
|
candidates[ i ].sr_matched = NULL;
|
||||||
|
|
||||||
|
dc.ctx = "matchedDN";
|
||||||
|
dc.target = mi->mi_targets[ i ];
|
||||||
|
if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {
|
||||||
|
if ( mmatch.bv_val == match.bv_val ) {
|
||||||
|
candidates[ i ].sr_matched
|
||||||
|
= ch_strdup( mmatch.bv_val );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
candidates[ i ].sr_matched = mmatch.bv_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
candidate_match++;
|
||||||
}
|
}
|
||||||
ber_memfree( sr_ref );
|
ldap_memfree( match.bv_val );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
rs->sr_err = candidates[ i ].sr_err;
|
/* add references to array */
|
||||||
sres = slap_map_api2result( rs );
|
if ( references ) {
|
||||||
|
BerVarray sr_ref;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
|
for ( cnt = 0; references[ cnt ]; cnt++ )
|
||||||
snprintf( buf, sizeof( buf ),
|
;
|
||||||
"%s meta_back_search[%ld] "
|
|
||||||
"match=\"%s\" err=%ld",
|
|
||||||
op->o_log_prefix, i,
|
|
||||||
candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
|
|
||||||
(long) candidates[ i ].sr_err );
|
|
||||||
if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "%s.\n", buf, 0, 0 );
|
|
||||||
|
|
||||||
} else {
|
sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
|
||||||
Debug( LDAP_DEBUG_ANY, "%s (%s).\n",
|
|
||||||
buf, ldap_err2string( candidates[ i ].sr_err ), 0 );
|
for ( cnt = 0; references[ cnt ]; cnt++ ) {
|
||||||
|
ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
|
||||||
|
}
|
||||||
|
BER_BVZERO( &sr_ref[ cnt ] );
|
||||||
|
|
||||||
|
( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
ber_memvfree( (void **)references );
|
||||||
|
|
||||||
|
if ( rs->sr_v2ref == NULL ) {
|
||||||
|
rs->sr_v2ref = sr_ref;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
|
||||||
|
ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
|
||||||
|
}
|
||||||
|
ber_memfree( sr_ref );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch ( sres ) {
|
rs->sr_err = candidates[ i ].sr_err;
|
||||||
case LDAP_NO_SUCH_OBJECT:
|
sres = slap_map_api2result( rs );
|
||||||
/* is_ok is touched any time a valid
|
|
||||||
* (even intermediate) result is
|
if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
|
||||||
* returned; as a consequence, if
|
snprintf( buf, sizeof( buf ),
|
||||||
* a candidate returns noSuchObject
|
"%s meta_back_search[%ld] "
|
||||||
* it is ignored and the candidate
|
"match=\"%s\" err=%ld",
|
||||||
* is simply demoted. */
|
op->o_log_prefix, i,
|
||||||
if ( is_ok ) {
|
candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
|
||||||
sres = LDAP_SUCCESS;
|
(long) candidates[ i ].sr_err );
|
||||||
|
if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
|
||||||
|
Debug( LDAP_DEBUG_TRACE, "%s.\n", buf, 0, 0 );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Debug( LDAP_DEBUG_ANY, "%s (%s).\n",
|
||||||
|
buf, ldap_err2string( candidates[ i ].sr_err ), 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case LDAP_SUCCESS:
|
switch ( sres ) {
|
||||||
case LDAP_REFERRAL:
|
case LDAP_NO_SUCH_OBJECT:
|
||||||
is_ok++;
|
/* is_ok is touched any time a valid
|
||||||
break;
|
* (even intermediate) result is
|
||||||
|
* returned; as a consequence, if
|
||||||
|
* a candidate returns noSuchObject
|
||||||
|
* it is ignored and the candidate
|
||||||
|
* is simply demoted. */
|
||||||
|
if ( is_ok ) {
|
||||||
|
sres = LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case LDAP_SIZELIMIT_EXCEEDED:
|
case LDAP_SUCCESS:
|
||||||
/* if a target returned sizelimitExceeded
|
case LDAP_REFERRAL:
|
||||||
* and the entry count is equal to the
|
is_ok++;
|
||||||
* proxy's limit, the target would have
|
break;
|
||||||
* returned more, and the error must be
|
|
||||||
* propagated to the client; otherwise,
|
case LDAP_SIZELIMIT_EXCEEDED:
|
||||||
* the target enforced a limit lower
|
/* if a target returned sizelimitExceeded
|
||||||
* than what requested by the proxy;
|
* and the entry count is equal to the
|
||||||
* ignore it */
|
* proxy's limit, the target would have
|
||||||
if ( rs->sr_nentries == op->ors_slimit
|
* returned more, and the error must be
|
||||||
|| META_BACK_ONERR_STOP( mi ) )
|
* propagated to the client; otherwise,
|
||||||
{
|
* the target enforced a limit lower
|
||||||
savepriv = op->o_private;
|
* than what requested by the proxy;
|
||||||
op->o_private = (void *)i;
|
* ignore it */
|
||||||
send_ldap_result( op, rs );
|
if ( rs->sr_nentries == op->ors_slimit
|
||||||
op->o_private = savepriv;
|
|| META_BACK_ONERR_STOP( mi ) )
|
||||||
goto finish;
|
{
|
||||||
|
savepriv = op->o_private;
|
||||||
|
op->o_private = (void *)i;
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
op->o_private = savepriv;
|
||||||
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if ( META_BACK_ONERR_STOP( mi ) ) {
|
||||||
|
savepriv = op->o_private;
|
||||||
|
op->o_private = (void *)i;
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
op->o_private = savepriv;
|
||||||
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
last = i;
|
||||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
rc = 0;
|
||||||
savepriv = op->o_private;
|
|
||||||
op->o_private = (void *)i;
|
|
||||||
send_ldap_result( op, rs );
|
|
||||||
op->o_private = savepriv;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
last = i;
|
/*
|
||||||
rc = 0;
|
* When no candidates are left,
|
||||||
|
* the outer cycle finishes
|
||||||
/*
|
*/
|
||||||
* When no candidates are left,
|
|
||||||
* the outer cycle finishes
|
|
||||||
*/
|
|
||||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
|
||||||
--ncandidates;
|
|
||||||
|
|
||||||
} else if ( rc == LDAP_RES_BIND ) {
|
|
||||||
meta_search_candidate_t retcode;
|
|
||||||
|
|
||||||
retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, res );
|
|
||||||
if ( retcode == META_SEARCH_CANDIDATE ) {
|
|
||||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
|
||||||
retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( retcode ) {
|
|
||||||
case META_SEARCH_CANDIDATE:
|
|
||||||
goto get_result;
|
|
||||||
|
|
||||||
/* means that failed but onerr == continue */
|
|
||||||
case META_SEARCH_NOT_CANDIDATE:
|
|
||||||
case META_SEARCH_ERR:
|
|
||||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||||
--ncandidates;
|
--ncandidates;
|
||||||
|
|
||||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
} else if ( rc == LDAP_RES_BIND ) {
|
||||||
savepriv = op->o_private;
|
meta_search_candidate_t retcode;
|
||||||
op->o_private = (void *)i;
|
|
||||||
send_ldap_result( op, rs );
|
retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg );
|
||||||
op->o_private = savepriv;
|
if ( retcode == META_SEARCH_CANDIDATE ) {
|
||||||
goto finish;
|
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||||
|
retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
switch ( retcode ) {
|
||||||
|
case META_SEARCH_CANDIDATE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* means that failed but onerr == continue */
|
||||||
|
case META_SEARCH_NOT_CANDIDATE:
|
||||||
|
case META_SEARCH_ERR:
|
||||||
|
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||||
|
--ncandidates;
|
||||||
|
|
||||||
|
if ( META_BACK_ONERR_STOP( mi ) ) {
|
||||||
|
savepriv = op->o_private;
|
||||||
|
op->o_private = (void *)i;
|
||||||
|
send_ldap_result( op, rs );
|
||||||
|
op->o_private = savepriv;
|
||||||
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert( 0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
break;
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
|
goto really_bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
assert( 0 );
|
|
||||||
goto really_bad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ldap_msgfree( res );
|
||||||
|
res = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for abandon */
|
/* check for abandon */
|
||||||
|
Loading…
Reference in New Issue
Block a user