1 /* search.c - ldbm backend search function */
11 #include "back-ldbm.h"
12 #include "proto-back-ldbm.h"
14 static ID_BLOCK *base_candidate(
15 Backend *be, Entry *e );
17 static ID_BLOCK *search_candidates(
18 Backend *be, Entry *e, Filter *filter,
19 int scope, int deref, int manageDSAit );
38 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
45 struct berval **v2refs = NULL;
46 Entry *matched = NULL;
47 char *realbase = NULL;
49 int manageDSAit = get_manageDSAit( op );
51 Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0);
53 /* get entry with reader lock */
54 if ( deref & LDAP_DEREF_FINDING ) {
55 e = deref_dn_r( be, base, &err, &matched, &text );
58 e = dn2entry_r( be, base, &matched );
59 err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
64 char *matched_dn = NULL;
65 struct berval **refs = NULL;
67 if ( matched != NULL ) {
68 matched_dn = ch_strdup( matched->e_dn );
70 refs = is_entry_referral( matched )
71 ? get_entry_referrals( be, conn, op, matched )
74 cache_return_entry_r( &li->li_cache, matched );
76 refs = default_referral;
79 send_ldap_result( conn, op, err,
80 matched_dn, text, refs, NULL );
82 if( matched != NULL ) {
90 if (!manageDSAit && is_entry_referral( e ) ) {
91 /* entry is a referral, don't allow add */
92 char *matched_dn = ch_strdup( e->e_dn );
93 struct berval **refs = get_entry_referrals( be,
96 cache_return_entry_r( &li->li_cache, e );
98 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
101 send_ldap_result( conn, op, LDAP_REFERRAL,
102 matched_dn, NULL, refs, NULL );
104 ber_bvecfree( refs );
110 if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
111 tlimit = -1; /* allow root to set no limit */
113 tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
114 be->be_timelimit : tlimit;
115 stoptime = op->o_time + tlimit;
118 if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
119 slimit = -1; /* allow root to set no limit */
121 slimit = (slimit > be->be_sizelimit || slimit < 1) ?
122 be->be_sizelimit : slimit;
125 if ( scope == LDAP_SCOPE_BASE) {
126 candidates = base_candidate( be, e );
129 candidates = search_candidates( be, e, filter,
130 scope, deref, manageDSAit );
133 /* need normalized dn below */
134 realbase = ch_strdup( e->e_ndn );
135 cache_return_entry_r( &li->li_cache, e );
137 if ( candidates == NULL ) {
139 Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
142 send_search_result( conn, op,
144 NULL, NULL, NULL, NULL, 0 );
150 for ( id = idl_firstid( candidates ); id != NOID;
151 id = idl_nextid( candidates, id ) )
155 /* check for abandon */
156 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
158 if ( op->o_abandon ) {
159 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
164 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
166 /* check time limit */
167 if ( tlimit != -1 && slap_get_time() > stoptime ) {
168 send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
169 NULL, NULL, v2refs, NULL, nentries );
174 /* get the entry with reader lock */
175 e = id2entry_r( be, id );
178 Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
184 if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
189 e = deref_entry_r( be, e, &err, &matched, &text );
196 if( e->e_id == id ) {
201 /* need to skip alias which deref into scope */
202 if( scope & LDAP_SCOPE_ONELEVEL ) {
203 char *pdn = dn_parent( NULL, e->e_ndn );
205 if( strcmp( pdn, realbase ) ) {
212 } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
213 /* alias is within scope */
214 Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
223 * if it's a referral, add it to the list of referrals. only do
224 * this for non-base searches, and don't check the filter
225 * explicitly here since it's only a candidate anyway.
227 if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
228 is_entry_referral( e ) )
230 struct berval **refs = get_entry_referrals(
233 send_search_reference( be, conn, op,
234 e, refs, scope, NULL, &v2refs );
236 ber_bvecfree( refs );
241 /* if it matches the filter and scope, send it */
242 if ( test_filter( be, conn, op, e, filter ) == 0 ) {
246 if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
247 if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
248 (void) dn_normalize_case( dn );
249 scopeok = (dn == realbase)
251 : (strcmp( dn, realbase ) ? 0 : 1 );
255 scopeok = (realbase == NULL || *realbase == '\0');
258 } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
259 dn = ch_strdup( e->e_ndn );
260 scopeok = dn_issuffix( dn, realbase );
268 /* check size limit */
269 if ( --slimit == -1 ) {
270 cache_return_entry_r( &li->li_cache, e );
271 send_search_result( conn, op,
272 LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
273 v2refs, NULL, nentries );
279 switch ( send_search_entry( be, conn, op, e,
280 attrs, attrsonly, NULL ) ) {
281 case 0: /* entry sent ok */
284 case 1: /* entry not sent */
286 case -1: /* connection closed */
287 cache_return_entry_r( &li->li_cache, e );
293 Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
297 Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
303 /* free reader lock */
304 cache_return_entry_r( &li->li_cache, e );
307 ldap_pvt_thread_yield();
309 send_search_result( conn, op,
310 v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
311 NULL, NULL, v2refs, NULL, nentries );
316 idl_free( candidates );
318 ber_bvecfree( v2refs );
319 if( realbase ) free( realbase );
332 Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
335 idl = idl_alloc( 1 );
336 idl_insert( &idl, e->e_id, 1 );
351 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
352 ID_BLOCK *candidates;
353 Filter *f, *rf, *af, *lf;
355 Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
356 e->e_ndn, scope, deref );
361 /* match referrals */
362 rf = (Filter *) ch_malloc( sizeof(Filter) );
364 rf->f_choice = LDAP_FILTER_OR;
365 rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
366 rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
367 rf->f_or->f_avtype = ch_strdup( "objectclass" );
368 rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
369 rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
370 rf->f_or->f_next = filter;
377 if( deref & LDAP_DEREF_SEARCHING ) {
379 af = (Filter *) ch_malloc( sizeof(Filter) );
381 af->f_choice = LDAP_FILTER_OR;
382 af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
383 af->f_or->f_choice = LDAP_FILTER_EQUALITY;
384 af->f_or->f_avtype = ch_strdup( "objectclass" );
385 af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
386 af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
387 af->f_or->f_next = f;
393 if ( scope == LDAP_SCOPE_SUBTREE ) {
394 lf = (Filter *) ch_malloc( sizeof(Filter) );
396 lf->f_choice = LDAP_FILTER_AND;
397 lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
399 lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
400 lf->f_and->f_sub_type = ch_strdup( "dn" );
401 lf->f_and->f_sub_initial = NULL;
402 lf->f_and->f_sub_any = NULL;
403 lf->f_and->f_sub_final = ch_strdup( e->e_ndn );
405 lf->f_and->f_next = f;
408 } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
411 lf = (Filter *) ch_malloc( sizeof(Filter) );
413 lf->f_choice = LDAP_FILTER_AND;
414 lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
416 lf->f_and->f_choice = LDAP_FILTER_EQUALITY;
417 lf->f_and->f_ava.ava_type = ch_strdup( "id2children" );
418 sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
419 lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
420 lf->f_and->f_ava.ava_value.bv_len = strlen( buf );
422 lf->f_and->f_next = f;
429 candidates = filter_candidates( be, f );
431 /* free up filter additions we allocated above */
433 lf->f_and->f_next = NULL;
438 af->f_or->f_next = NULL;
443 rf->f_or->f_next = NULL;
447 return( candidates );