1 /* search.c - bdb2 backend search function */
13 #include "back-bdb2.h"
14 #include "proto-back-bdb2.h"
16 static ID_BLOCK *base_candidate(
17 Backend *be, Entry *e );
19 static ID_BLOCK *search_candidates(
20 Backend *be, Entry *e, Filter *filter,
21 int scope, int deref, int manageDSAit );
24 bdb2i_back_search_internal(
39 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
46 struct berval **v2refs = NULL;
47 Entry *matched = NULL;
48 char *realbase = NULL;
50 int manageDSAit = get_manageDSAit( op );
52 Debug(LDAP_DEBUG_TRACE, "=> bdb2_back_search\n", 0, 0, 0);
54 /* get entry with reader lock */
55 if ( deref & LDAP_DEREF_FINDING ) {
56 e = deref_dn_r( be, base, &err, &matched, &text );
59 e = bdb2i_dn2entry_r( be, base, &matched );
60 err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
65 char *matched_dn = NULL;
66 struct berval **refs = NULL;
68 if ( matched != NULL ) {
69 matched_dn = ch_strdup( matched->e_dn );
71 refs = is_entry_referral( matched )
72 ? get_entry_referrals( be, conn, op, matched )
75 bdb2i_cache_return_entry_r( &li->li_cache, matched );
77 refs = default_referral;
80 send_ldap_result( conn, op, err,
81 matched_dn, text, refs, NULL );
83 if( matched != NULL ) {
91 if (!manageDSAit && is_entry_referral( e ) ) {
92 /* entry is a referral, don't allow add */
93 char *matched_dn = ch_strdup( e->e_dn );
94 struct berval **refs = get_entry_referrals( be,
97 bdb2i_cache_return_entry_r( &li->li_cache, e );
99 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
102 send_ldap_result( conn, op, LDAP_REFERRAL,
103 matched_dn, NULL, refs, NULL );
105 ber_bvecfree( refs );
111 if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
112 tlimit = -1; /* allow root to set no limit */
114 tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
115 be->be_timelimit : tlimit;
116 stoptime = op->o_time + tlimit;
119 if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
120 slimit = -1; /* allow root to set no limit */
122 slimit = (slimit > be->be_sizelimit || slimit < 1) ?
123 be->be_sizelimit : slimit;
126 if ( scope == LDAP_SCOPE_BASE) {
127 candidates = base_candidate( be, e );
130 candidates = search_candidates( be, e, filter,
131 scope, deref, manageDSAit );
134 /* need normalized dn below */
135 realbase = ch_strdup( e->e_ndn );
136 bdb2i_cache_return_entry_r( &li->li_cache, e );
138 if ( candidates == NULL ) {
140 Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
143 send_search_result( conn, op,
145 NULL, NULL, NULL, NULL, 0 );
151 for ( id = bdb2i_idl_firstid( candidates, &cursor ); id != NOID;
152 id = bdb2i_idl_nextid( candidates, &cursor ) )
156 /* check for abandon */
157 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
159 if ( op->o_abandon ) {
160 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
165 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
167 /* check time limit */
168 if ( tlimit != -1 && slap_get_time() > stoptime ) {
169 send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
170 NULL, NULL, v2refs, NULL, nentries );
175 /* get the entry with reader lock */
176 e = bdb2i_id2entry_r( be, id );
179 Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
185 if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
190 e = deref_entry_r( be, e, &err, &matched, &text );
197 if( e->e_id == id ) {
202 /* need to skip alias which deref into scope */
203 if( scope & LDAP_SCOPE_ONELEVEL ) {
204 char *pdn = dn_parent( NULL, e->e_ndn );
206 if( strcmp( pdn, realbase ) ) {
213 } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
214 /* alias is within scope */
215 Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
224 * if it's a referral, add it to the list of referrals. only do
225 * this for non-base searches, and don't check the filter
226 * explicitly here since it's only a candidate anyway.
228 if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
229 is_entry_referral( e ) )
231 struct berval **refs = get_entry_referrals(
234 send_search_reference( be, conn, op,
235 e, refs, scope, NULL, &v2refs );
237 ber_bvecfree( refs );
242 /* if it matches the filter and scope, send it */
243 if ( test_filter( be, conn, op, e, filter ) == 0 ) {
247 if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
248 if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
249 (void) dn_normalize_case( dn );
250 scopeok = (dn == realbase)
252 : (strcmp( dn, realbase ) ? 0 : 1 );
256 scopeok = (realbase == NULL || *realbase == '\0');
259 } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
260 dn = ch_strdup( e->e_ndn );
261 scopeok = dn_issuffix( dn, realbase );
269 /* check size limit */
270 if ( --slimit == -1 ) {
271 bdb2i_cache_return_entry_r( &li->li_cache, e );
272 send_search_result( conn, op,
273 LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
274 v2refs, NULL, nentries );
280 switch ( send_search_entry( be, conn, op, e,
281 attrs, attrsonly, NULL ) ) {
282 case 0: /* entry sent ok */
285 case 1: /* entry not sent */
287 case -1: /* connection closed */
288 bdb2i_cache_return_entry_r( &li->li_cache, e );
294 Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
298 Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
304 /* free reader lock */
305 bdb2i_cache_return_entry_r( &li->li_cache, e );
308 ldap_pvt_thread_yield();
310 send_search_result( conn, op,
311 v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
312 NULL, NULL, v2refs, NULL, nentries );
317 bdb2i_idl_free( candidates );
319 ber_bvecfree( v2refs );
320 if( realbase ) free( realbase );
343 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
344 struct timeval time1;
347 bdb2i_start_timing( be->bd_info, &time1 );
349 if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
350 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
351 NULL, NULL, NULL, NULL );
356 ret = bdb2i_back_search_internal( be, conn, op, base, scope, deref,
357 slimit, tlimit, filter, filterstr, attrs, attrsonly );
359 (void) bdb2i_leave_backend_r( lock );
360 bdb2i_stop_timing( be->bd_info, time1, "SRCH", conn, op );
374 Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
377 idl = bdb2i_idl_alloc( 1 );
378 bdb2i_idl_insert( &idl, e->e_id, 1 );
393 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
394 ID_BLOCK *candidates;
395 Filter *f, *rf, *af, *lf;
397 Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
398 e->e_ndn, scope, deref );
403 /* match referrals */
404 rf = (Filter *) ch_malloc( sizeof(Filter) );
406 rf->f_choice = LDAP_FILTER_OR;
407 rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
408 rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
409 rf->f_or->f_avtype = ch_strdup( "objectclass" );
410 rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
411 rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
412 rf->f_or->f_next = filter;
419 if( deref & LDAP_DEREF_SEARCHING ) {
421 af = (Filter *) ch_malloc( sizeof(Filter) );
423 af->f_choice = LDAP_FILTER_OR;
424 af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
425 af->f_or->f_choice = LDAP_FILTER_EQUALITY;
426 af->f_or->f_avtype = ch_strdup( "objectclass" );
427 af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
428 af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
429 af->f_or->f_next = f;
435 if ( scope == LDAP_SCOPE_SUBTREE ) {
436 lf = (Filter *) ch_malloc( sizeof(Filter) );
438 lf->f_choice = LDAP_FILTER_AND;
439 lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
441 lf->f_and->f_choice = SLAPD_FILTER_DN_SUBTREE;
442 lf->f_and->f_dn = e->e_ndn;
444 lf->f_and->f_next = f;
447 } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
448 lf = (Filter *) ch_malloc( sizeof(Filter) );
450 lf->f_choice = LDAP_FILTER_AND;
451 lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
453 lf->f_and->f_choice = SLAPD_FILTER_DN_ONE;
454 lf->f_and->f_dn = e->e_ndn;
456 lf->f_and->f_next = f;
463 candidates = bdb2i_filter_candidates( be, f );
465 /* free up filter additions we allocated above */
472 af->f_or->f_next = NULL;
477 rf->f_or->f_next = NULL;
481 return( candidates );