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;
44 struct berval **v2refs = NULL;
45 Entry *matched = NULL;
46 char *matched_dn = NULL;
48 int manageDSAit = get_manageDSAit( op );
50 Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0);
52 /* get entry with reader lock */
55 case LDAP_DEREF_FINDING:
56 case LDAP_DEREF_ALWAYS:
57 e = alias_dn2entry_r( be, base, &matched, &err );
61 e = dn2entry_r( be, base, &matched );
62 err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
66 char *matched_dn = NULL;
67 struct berval **refs = NULL;
69 if ( matched != NULL ) {
70 matched_dn = ch_strdup( matched->e_dn );
71 refs = is_entry_referral( matched )
72 ? 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, NULL, 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, matched );
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 matched_dn = ch_strdup( e->e_dn );
134 cache_return_entry_r( &li->li_cache, e );
136 /* null candidates means we could not find the base object */
137 if ( candidates == NULL ) {
138 /* return a NO SUCH OBJECT */
139 Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
142 send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
143 matched_dn, "no search candidates", NULL, NULL );
149 for ( id = idl_firstid( candidates ); id != NOID;
150 id = idl_nextid( candidates, id ) ) {
152 /* check for abandon */
153 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
154 if ( op->o_abandon ) {
155 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
156 idl_free( candidates );
157 ber_bvecfree( v2refs );
161 ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
163 /* check time limit */
164 if ( tlimit != -1 && slap_get_time() > stoptime ) {
165 send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
166 NULL, NULL, v2refs, NULL, nentries );
167 idl_free( candidates );
168 ber_bvecfree( v2refs );
173 /* get the entry with reader lock */
176 case LDAP_DEREF_SEARCHING:
177 case LDAP_DEREF_ALWAYS:
178 e = alias_id2entry_r( be, id, &matched, &err );
182 e = dn2entry_r( be, base, &matched );
183 err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
187 Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
193 * if it's a referral, add it to the list of referrals. only do
194 * this for subtree searches, and don't check the filter
195 * explicitly here since it's only a candidate anyway.
197 if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
198 is_entry_referral( e ) )
200 struct berval **refs = get_entry_referrals( be, conn, op, e );
202 send_search_reference( be, conn, op,
203 e, refs, NULL, &v2refs );
205 ber_bvecfree( refs );
207 /* otherwise it's an entry - see if it matches the filter */
209 /* if it matches the filter and scope, send it */
210 if ( test_filter( be, conn, op, e, filter ) == 0 ) {
215 if ( scope == LDAP_SCOPE_ONELEVEL ) {
216 if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
217 (void) dn_normalize_case( dn );
218 scopeok = (dn == matched_dn)
220 : (strcmp( dn, matched_dn ) ? 0 : 1 );
223 scopeok = (matched_dn == NULL || *matched_dn == '\0');
225 } else if ( scope == LDAP_SCOPE_SUBTREE ) {
226 dn = ch_strdup( e->e_ndn );
227 scopeok = dn_issuffix( dn, matched_dn );
234 /* check size limit */
235 if ( --slimit == -1 ) {
236 cache_return_entry_r( &li->li_cache, e );
237 send_search_result( conn, op,
238 LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
239 v2refs, NULL, nentries );
240 idl_free( candidates );
241 ber_bvecfree( v2refs );
247 switch ( send_search_entry( be, conn, op, e,
248 attrs, attrsonly, 0, NULL ) ) {
249 case 0: /* entry sent ok */
252 case 1: /* entry not sent */
254 case -1: /* connection closed */
255 cache_return_entry_r( &li->li_cache, e );
256 idl_free( candidates );
257 ber_bvecfree( v2refs );
267 /* free reader lock */
268 cache_return_entry_r( &li->li_cache, e );
271 ldap_pvt_thread_yield();
273 idl_free( candidates );
275 send_search_result( conn, op,
276 v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
277 NULL, NULL, v2refs, NULL, nentries );
279 ber_bvecfree( v2refs );
292 Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
295 idl = idl_alloc( 1 );
296 idl_insert( &idl, e->e_id, 1 );
311 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
312 ID_BLOCK *candidates;
313 Filter *f, *rf, *af, *lf;
315 Debug(LDAP_DEBUG_TRACE, "search_candidates: base: \"%s\" %s\n",
321 /* match referrals */
322 rf = (Filter *) ch_malloc( sizeof(Filter) );
324 rf->f_choice = LDAP_FILTER_OR;
325 rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
326 rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
327 rf->f_or->f_avtype = ch_strdup( "objectclass" );
328 rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
329 rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
330 rf->f_or->f_next = filter;
337 if( deref == LDAP_DEREF_SEARCHING || deref == LDAP_DEREF_ALWAYS ) {
339 af = (Filter *) ch_malloc( sizeof(Filter) );
341 af->f_choice = LDAP_FILTER_OR;
342 af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
343 af->f_or->f_choice = LDAP_FILTER_EQUALITY;
344 af->f_or->f_avtype = ch_strdup( "objectclass" );
345 af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
346 af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
347 af->f_or->f_next = f;
353 lf = (Filter *) ch_malloc( sizeof(Filter) );
355 lf->f_choice = LDAP_FILTER_AND;
356 lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
357 lf->f_and->f_next = f;
359 if ( scope == LDAP_SCOPE_SUBTREE ) {
360 lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
361 lf->f_and->f_sub_type = ch_strdup( "dn" );
362 lf->f_and->f_sub_initial = NULL;
363 lf->f_and->f_sub_any = NULL;
364 lf->f_and->f_sub_final = ch_strdup( e->e_ndn );
365 value_normalize( lf->f_and->f_sub_final, SYNTAX_DN|SYNTAX_CIS );
369 lf->f_and->f_choice = LDAP_FILTER_EQUALITY;
370 lf->f_and->f_ava.ava_type = ch_strdup( "id2children" );
371 sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
372 lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
373 lf->f_and->f_ava.ava_value.bv_len = strlen( buf );
376 candidates = filter_candidates( be, lf );
378 /* free up filter additions we allocated above */
379 lf->f_and->f_next = NULL;
383 af->f_or->f_next = NULL;
388 rf->f_or->f_next = NULL;
392 return( candidates );