int fe_op_search( Operation *op, SlapReply *rs ) { BackendDB *bd = op->o_bd; if ( op->ors_scope == LDAP_SCOPE_BASE ) { Entry *entry = NULL; if ( BER_BVISEMPTY( &op->o_req_ndn ) ) { #ifdef LDAP_CONNECTIONLESS /* Ignore LDAPv2 CLDAP Root DSE queries */ if (op->o_protocol == LDAP_VERSION2 && op->o_conn->c_is_udp) { goto return_results; } #endif /* check restrictions */ if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto return_results; } rs->sr_err = root_dse_info( op->o_conn, &entry, &rs->sr_text ); } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) { /* check restrictions */ if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto return_results; } rs->sr_err = schema_info( &entry, &rs->sr_text ); } if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto return_results; } else if ( entry != NULL ) { if ( get_assert( op ) && ( test_filter( op, entry, get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto fail1; } rs->sr_err = test_filter( op, entry, op->ors_filter ); if( rs->sr_err == LDAP_COMPARE_TRUE ) { /* note: we set no limits because either * no limit is specified, or at least 1 * is specified, and we're going to return * at most one entry */ op->ors_slimit = SLAP_NO_LIMIT; op->ors_tlimit = SLAP_NO_LIMIT; rs->sr_entry = entry; rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_flags = 0; send_search_entry( op, rs ); rs->sr_entry = NULL; rs->sr_operational_attrs = NULL; } rs->sr_err = LDAP_SUCCESS; fail1: entry_free( entry ); send_ldap_result( op, rs ); goto return_results; } } if( BER_BVISEMPTY( &op->o_req_ndn ) && !BER_BVISEMPTY( &default_search_nbase ) ) { slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); ber_dupbv_x( &op->o_req_dn, &default_search_base, op->o_tmpmemctx ); ber_dupbv_x( &op->o_req_ndn, &default_search_nbase, op->o_tmpmemctx ); } /* * We could be serving multiple database backends. Select the * appropriate one, or send a referral to our "referral server" * if we don't hold it. */ op->o_bd = select_backend( &op->o_req_ndn, 1 ); if ( op->o_bd == NULL ) { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, op->ors_scope ); if (!rs->sr_ref) rs->sr_ref = default_referral; rs->sr_err = LDAP_REFERRAL; op->o_bd = bd; send_ldap_result( op, rs ); if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; goto return_results; } /* check restrictions */ if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto return_results; } /* check for referrals */ if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) { goto return_results; } if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) { /* don't use shadow copy */ BerVarray defref = op->o_bd->be_update_refs ? op->o_bd->be_update_refs : default_referral; if( defref != NULL ) { rs->sr_ref = referral_rewrite( defref, NULL, &op->o_req_dn, op->ors_scope ); if( !rs->sr_ref) rs->sr_ref = defref; rs->sr_err = LDAP_REFERRAL; send_ldap_result( op, rs ); if (rs->sr_ref != defref) ber_bvarray_free( rs->sr_ref ); } else { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "copy not used; no referral information available" ); } } else if ( op->o_bd->be_search ) { if ( limits_check( op, rs ) == 0 ) { /* actually do the search and send the result(s) */ (op->o_bd->be_search)( op, rs ); } /* else limits_check() sends error */ } else { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "operation not supported within namingContext" ); } return_results:; op->o_bd = bd; return rs->sr_err; }
static int sssvlv_op_search( Operation *op, SlapReply *rs) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; sssvlv_info *si = on->on_bi.bi_private; int rc = SLAP_CB_CONTINUE; int ok, need_unlock = 0; sort_ctrl *sc; PagedResultsState *ps; vlv_ctrl *vc; int sess_id; if ( op->o_ctrlflag[sss_cid] <= SLAP_CONTROL_IGNORED ) { if ( op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ) { sort_op so; memset(&so, 0, sizeof(so)); so.so_vlv_rc = LDAP_VLV_SSS_MISSING; so.so_vlv = op->o_ctrlflag[vlv_cid]; LDAPControl *ctrls[2]; rc = pack_vlv_response_control( op, rs, &so, ctrls ); if ( rc == LDAP_SUCCESS ) { ctrls[1] = NULL; slap_add_ctrls( op, rs, ctrls ); } rs->sr_err = LDAP_VLV_ERROR; rs->sr_text = "Sort control is required with VLV"; goto leave; } /* Not server side sort so just continue */ return SLAP_CB_CONTINUE; } Debug(LDAP_DEBUG_TRACE, "==> sssvlv_search: <%s> %s, control flag: %d\n", op->o_req_dn.bv_val, op->ors_filterstr.bv_val, op->o_ctrlflag[sss_cid]); sc = op->o_controls[sss_cid]; if ( sc->sc_nkeys > si->svi_max_keys ) { rs->sr_text = "Too many sort keys"; rs->sr_err = LDAP_UNWILLING_TO_PERFORM; goto leave; } ps = ( op->o_pagedresults > SLAP_CONTROL_IGNORED ) ? (PagedResultsState*)(op->o_pagedresults_state) : NULL; vc = op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ? op->o_controls[vlv_cid] : NULL; if ( ps && vc ) { rs->sr_text = "VLV incompatible with PagedResults"; rs->sr_err = LDAP_UNWILLING_TO_PERFORM; goto leave; } ldap_pvt_thread_mutex_lock( &sort_conns_mutex ); ok = need_unlock = 1; sort_op *so = NULL; /* Is there already a sort running on this conn? */ sess_id = find_session_by_context( si->svi_max_percon, op->o_conn->c_conn_idx, vc ? vc->vc_context : NO_VC_CONTEXT, ps ? ps->ps_cookie : NO_PS_COOKIE ); if ( sess_id >= 0 ) { so = sort_conns[op->o_conn->c_conn_idx][sess_id]; if (so->so_running) { /* another thread is handling, response busy to client */ ok = 0; so = NULL; } else { /* Is it a continuation of a VLV search? */ if ( !vc || so->so_vlv <= SLAP_CONTROL_IGNORED || vc->vc_context != so->so_vcontext ) { /* Is it a continuation of a paged search? */ if ( !ps || so->so_paged <= SLAP_CONTROL_IGNORED || op->o_conn->c_pagedresults_state.ps_cookie != ps->ps_cookie ) { ok = 0; } else if ( !ps->ps_size ) { /* Abandoning current request */ ok = 0; so->so_nentries = 0; rs->sr_err = LDAP_SUCCESS; } } if (( vc && so->so_paged > SLAP_CONTROL_IGNORED ) || ( ps && so->so_vlv > SLAP_CONTROL_IGNORED )) { /* changed from paged to vlv or vice versa, abandon */ ok = 0; so->so_nentries = 0; rs->sr_err = LDAP_UNWILLING_TO_PERFORM; } if ( ok ) { /* occupy before mutex unlock */ so->so_running = 1; } } /* Are there too many running overall? */ } else if ( si->svi_num >= si->svi_max ) { ok = 0; } else if ( ( sess_id = find_next_session(si->svi_max_percon, op->o_conn->c_conn_idx ) ) < 0 ) { ok = 0; } else { /* OK, this connection going a sort running as the sess_id */ } if (! ok || so != NULL) { assert(need_unlock != 0); ldap_pvt_thread_mutex_unlock( &sort_conns_mutex ); need_unlock = 0; } if ( ok ) { /* If we're a global overlay, this check got bypassed */ if ( !op->ors_limit && limits_check( op, rs )) { if (need_unlock) { ldap_pvt_thread_mutex_unlock( &sort_conns_mutex ); need_unlock = 0; } if (so) free_sort_op( op->o_conn, so ); return rs->sr_err; } /* are we continuing a VLV search? */ if ( so && vc && vc->vc_context ) { assert(need_unlock == 0); so->so_ctrl = sc; send_list( op, rs, so ); send_result( op, rs, so ); rc = LDAP_SUCCESS; /* are we continuing a paged search? */ } else if ( so && ps && ps->ps_cookie ) { assert(need_unlock == 0); so->so_ctrl = sc; send_page( op, rs, so ); send_result( op, rs, so ); rc = LDAP_SUCCESS; } else { /* Install serversort response callback to handle a new search */ assert(need_unlock != 0); assert(so == NULL); so = ch_calloc( 1, sizeof(sort_op)); slap_callback *cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); LDAP_ENSURE(so != NULL && cb != NULL); /* FIXME: LDAP_OTHER */ cb->sc_response = sssvlv_op_response; cb->sc_next = op->o_callback; cb->sc_private = so; assert(so->so_tree == NULL); so->so_ctrl = sc; so->so_info = si; if ( ps ) { so->so_paged = op->o_pagedresults; so->so_page_size = ps->ps_size; op->o_pagedresults = SLAP_CONTROL_IGNORED; assert(so->so_page_size != 0); } else { if ( vc ) { so->so_vlv = op->o_ctrlflag[vlv_cid]; assert(so->so_vlv_target == 0); assert(so->so_vlv_rc == 0); assert(so->so_vlv != SLAP_CONTROL_NONE); } else { assert(so->so_vlv == SLAP_CONTROL_NONE); } } so->so_session = sess_id; so->so_vlv = op->o_ctrlflag[vlv_cid]; so->so_vcontext = (size_t)so; assert(so->so_nentries == 0); op->o_callback = cb; assert(sess_id >= 0); so->so_running = 1; sort_conns[op->o_conn->c_conn_idx][sess_id] = so; si->svi_num++; ldap_pvt_thread_mutex_unlock( &sort_conns_mutex ); need_unlock = 0; } assert(need_unlock == 0); } else { assert(need_unlock == 0); if ( so && !so->so_nentries ) { free_sort_op( op->o_conn, so ); } else { rs->sr_text = "Other sort requests already in progress"; rs->sr_err = LDAP_BUSY; } leave: assert(need_unlock == 0); rc = rs->sr_err; send_ldap_result( op, rs ); } assert(need_unlock == 0); return rc; }