📄 search.c
字号:
candidates[ i ].sr_msgid = META_MSGID_IGNORE; assert( ncandidates > 0 ); --ncandidates; candidates[ i ].sr_err = rs->sr_err; if ( META_BACK_ONERR_STOP( mi ) ) { savepriv = op->o_private; op->o_private = (void *)i; send_ldap_result( op, rs ); op->o_private = savepriv; goto finish; } /* fall thru */ case META_SEARCH_CANDIDATE: /* get back into business... */ continue; case META_SEARCH_BINDING: case META_SEARCH_NEED_BIND: case META_SEARCH_UNDEFINED: assert( 0 ); default: /* unrecoverable error */ candidates[ i ].sr_msgid = META_MSGID_IGNORE; rc = rs->sr_err = LDAP_OTHER; goto finish; } } candidates[ i ].sr_err = rs->sr_err; if ( META_BACK_ONERR_STOP( mi ) ) { savepriv = op->o_private; op->o_private = (void *)i; send_ldap_result( op, rs ); op->o_private = savepriv; goto finish; } } /* * When no candidates are left, * the outer cycle finishes */ candidates[ i ].sr_msgid = META_MSGID_IGNORE; assert( ncandidates > 0 ); --ncandidates; rs->sr_err = candidates[ i ].sr_err; continue; default: lastres_time = slap_get_time(); /* only touch when activity actually took place... */ if ( mi->mi_idle_timeout != 0 && msc->msc_time < lastres_time ) { msc->msc_time = lastres_time; } break; } for ( msg = ldap_first_message( msc->msc_ld, res ); msg != NULL; msg = ldap_next_message( msc->msc_ld, msg ) ) { rc = ldap_msgtype( msg ); if ( rc == LDAP_RES_SEARCH_ENTRY ) { LDAPMessage *e; if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } is_ok++; 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; save_tv.tv_sec = 0; save_tv.tv_usec = 0; } 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, 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++ ) ; 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, 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 ) { sres = slap_map_api2result( &candidates[ i ] ); candidates[ i ].sr_type = REP_RESULT; ldap_msgfree( res ); res = NULL; goto really_bad; } rs->sr_err = candidates[ i ].sr_err; /* 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 */ /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( references != NULL && references[ 0 ] != NULL && references[ 0 ][ 0 ] != '\0' ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s meta_back_search[%ld]: " "got referrals with err=%d\n", op->o_log_prefix, i, rs->sr_err ); } else { BerVarray sr_ref; int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 ); 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 ); 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 ); } } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s meta_back_search[%ld]: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, i, rs->sr_err ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } /* cleanup */ ber_memvfree( (void **)references ); sres = slap_map_api2result( rs ); if ( StatslogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) { 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 { Debug( LDAP_DEBUG_ANY, "%s (%s).\n", buf, ldap_err2string( candidates[ i ].sr_err ), 0 ); } } switch ( sres ) { case LDAP_NO_SUCH_OBJECT: /* is_ok is touched any time a valid * (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_SUCCESS: case LDAP_REFERRAL: is_ok++; break; case LDAP_SIZELIMIT_EXCEEDED: /* if a target returned sizelimitExceeded * and the entry count is equal to the * proxy's limit, the target would have * returned more, and the error must be * propagated to the client; otherwise, * the target enforced a limit lower * than what requested by the proxy; * ignore it */ candidates[ i ].sr_err = rs->sr_err; if ( rs->sr_nentries == op->ors_slimit || 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: candidates[ i ].sr_err = rs->sr_err; 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; } last = i; rc = 0; /* * When no candidates are left, * the outer cycle finishes */ candidates[ i ].sr_msgid = META_MSGID_IGNORE; assert( ncandidates > 0 ); --ncandidates; } else if ( rc == LDAP_RES_BIND ) { meta_search_candidate_t retcode; retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg ); 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: break; /* means that failed but onerr == continue */ case META_SEARCH_NOT_CANDIDATE: case META_SEARCH_ERR: candidates[ i ].sr_msgid = META_MSGID_IGNORE; assert( ncandidates > 0 ); --ncandidates; candidates[ i ].sr_err = rs->sr_err; 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; } goto free_message; default: assert( 0 ); break; } } else { assert( 0 ); ldap_msgfree( res ); res = NULL; goto really_bad; } }free_message:; ldap_msgfree( res ); res = NULL; } /* check for abandon */ if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) { for ( i = 0; i < mi->mi_ntargets; i++ ) { if ( candidates[ i ].sr_msgid >= 0 ) { if ( META_IS_BINDING( &candidates[ i ] ) ) { ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) { /* if still binding, destroy */#ifdef DEBUG_205 char buf[ SLAP_TEXT_BUFLEN ]; snprintf( buf, sizeof( buf), "%s meta_back_search(abandon) " "ldap_unbind_ext[%ld] mc=%p ld=%p", op->o_log_prefix, i, (void *)mc, (void *)mc->mc_conns[i].msc_ld ); Debug( LDAP_DEBUG_ANY, "### %s\n", buf, 0, 0 );#endif /* DEBUG_205 */ meta_clear_one_candidate( op, mc, i ); } ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); META_BINDING_CLEAR( &candidates[ i ] ); } else { (void)meta_back_cancel( mc, op, rs, candidates[ i ].sr_msgid, i, LDAP_BACK_DONTSEND ); } candidates[ i ].sr_msgid = META_MSGID_IGNORE; assert( ncandidates > 0 ); --ncandidates; } } if ( op->o_abandon ) { rc = SLAPD_ABANDON; } /* let send_ldap_result play cleanup handlers (ITS#4645) */ break; } /* if no entry was found during this loop, * set a minimal timeout */ if ( ncandidates > 0 && gotit == 0 ) { if ( save_tv.tv_sec == 0 && save_tv.tv_usec == 0 ) { save_tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates; /* arbitrarily limit to something between 1 and 2 minutes */ } else if ( ( stoptime == -1 && save_tv.tv_sec < 60 ) || save_tv.tv_sec < ( stoptime - slap_get_time() ) / ( 2 * ncandidates ) ) { /* double the timeout */ lutil_timermul( &save_tv, 2, &save_tv ); } if ( alreadybound == 0 ) { tv = save_tv; (void)select( 0, NULL, NULL, NULL, &tv ); } else { ldap_pvt_thread_yield(); } } } if ( rc == -1 ) { /* * FIXME: need a better strategy to handle errors */ if ( mc ) { rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE, -1, stoptime != -1 ? (stoptime - slap_get_time()) : 0, LDAP_BACK_SENDERR ); } else { rc = rs->sr_err; } goto finish; } /* * Rewrite the matched portion of the search base, if required * * FIXME: only the last one gets caught! */ savepriv = op->o_private; op->o_private = (void *)(long)mi->mi_ntargets; if ( candidate_match > 0 ) { struct berval pmatched = BER_BVNULL; /* we use the first one */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -