1 /* lcup.c - lcup operations */
4 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
16 #ifdef LDAP_CLIENT_UPDATE
18 static int psearch_base_candidate(
22 static int psearch_candidates(
38 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
40 LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
41 if ( ps_list->o_connid == conn->c_connid ) {
42 if ( ps_list->o_msgid == id ) {
43 ps_list->o_abandon = 1;
44 LDAP_LIST_REMOVE( ps_list, link );
45 slap_op_free ( ps_list );
50 return LDAP_UNAVAILABLE;
69 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
71 LDAP_LIST_FIRST(&op->psearch_spec) = (struct lcup_search_spec *)
72 calloc ( 1, sizeof ( struct lcup_search_spec ) );
74 LDAP_LIST_FIRST(&op->psearch_spec)->op = op;
76 LDAP_LIST_FIRST(&op->psearch_spec)->base = ber_dupbv(NULL, base);
77 LDAP_LIST_FIRST(&op->psearch_spec)->nbase = ber_dupbv(NULL, nbase);
79 LDAP_LIST_FIRST(&op->psearch_spec)->scope = scope;
80 LDAP_LIST_FIRST(&op->psearch_spec)->deref = deref;
81 LDAP_LIST_FIRST(&op->psearch_spec)->slimit = slimit;
82 LDAP_LIST_FIRST(&op->psearch_spec)->tlimit = tlimit;
84 LDAP_LIST_FIRST(&op->psearch_spec)->filter = filter;
85 LDAP_LIST_FIRST(&op->psearch_spec)->filterstr = ber_dupbv(NULL, fstr);
86 LDAP_LIST_FIRST(&op->psearch_spec)->attrs = attrs;
88 LDAP_LIST_FIRST(&op->psearch_spec)->attrsonly = attrsonly;
90 LDAP_LIST_FIRST(&op->psearch_spec)->entry_count = 0;
92 LDAP_LIST_INSERT_HEAD( &bdb->psearch_list, op, link );
104 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
106 const char *text = NULL;
110 ID candidates[BDB_IDL_UM_SIZE];
112 BerVarray v2refs = NULL;
113 Entry *matched = NULL;
114 struct berval realbase = { 0, NULL };
118 Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
119 AttributeAssertion aa_ge, aa_eq;
120 struct berval entrycsn_bv = { 0, NULL };
121 struct berval latest_entrycsn_bv = { 0, NULL };
123 struct slap_limits_set *limit = NULL;
130 Connection *ps_conn = ps_op->o_conn;
131 struct berval *base = LDAP_LIST_FIRST(&ps_op->psearch_spec)->base;
132 struct berval *nbase = LDAP_LIST_FIRST(&ps_op->psearch_spec)->nbase;
133 int scope = LDAP_LIST_FIRST(&ps_op->psearch_spec)->scope;
134 int deref = LDAP_LIST_FIRST(&ps_op->psearch_spec)->deref;
135 int slimit = LDAP_LIST_FIRST(&ps_op->psearch_spec)->slimit;
136 int tlimit = LDAP_LIST_FIRST(&ps_op->psearch_spec)->tlimit;
137 Filter *filter = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filter;
138 struct berval *filterstr = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filterstr;
139 int attrsonly = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrsonly;
140 AttributeName uuid_attr[2];
141 AttributeName *attrs = uuid_attr;
143 if ( psearch_type != LCUP_PSEARCH_BY_DELETE &&
144 psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
146 attrs = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
148 attrs[0].an_desc = slap_schema.si_ad_entryUUID;
149 attrs[0].an_oc = NULL;
150 ber_dupbv( &attrs[0].an_name, &attrs[0].an_desc->ad_cname );
151 attrs[1].an_desc = NULL;
152 attrs[1].an_oc = NULL;
153 attrs[1].an_name.bv_len = 0;
154 attrs[1].an_name.bv_val = NULL;
158 LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
160 Debug( LDAP_DEBUG_TRACE, "=> bdb_back_search\n",
164 manageDSAit = get_manageDSAit( ps_op );
166 rc = LOCK_ID (bdb->bi_dbenv, &locker );
171 send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
172 NULL, "internal error", NULL, NULL );
173 if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
174 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
175 ch_free( attrs[0].an_name.bv_val );
179 if ( nbase->bv_len == 0 ) {
180 /* DIT root special case */
181 e = (Entry *) &slap_entry_root;
185 /* get entry with reader lock */
186 if ( deref & LDAP_DEREF_FINDING ) {
187 e = deref_dn_r( be, nbase-, &err, &matched, &text );
193 rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0, locker, &lock );
202 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache,
205 if (matched != NULL) {
206 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache,
209 send_ldap_result( ps_conn, ps_op, LDAP_BUSY,
210 NULL, "ldap server busy", NULL, NULL );
211 LOCK_ID_FREE( bdb->bi_dbenv, locker );
212 if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
213 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
214 ch_free( attrs[0].an_name.bv_val );
216 case DB_LOCK_DEADLOCK:
217 case DB_LOCK_NOTGRANTED:
221 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache,
224 if (matched != NULL) {
225 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache,
228 send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
229 NULL, "internal error", NULL, NULL );
230 LOCK_ID_FREE( bdb->bi_dbenv, locker );
231 if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
232 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
233 ch_free( attrs[0].an_name.bv_val );
238 struct berval matched_dn = { 0, NULL };
239 BerVarray refs = NULL;
241 if ( matched != NULL ) {
243 ber_dupbv( &matched_dn, &matched->e_name );
245 erefs = is_entry_referral( matched )
246 ? get_entry_referrals( be, ps_conn, ps_op, matched )
249 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache,
254 refs = referral_rewrite( erefs, &matched_dn,
256 ber_bvarray_free( erefs );
260 refs = referral_rewrite( default_referral,
264 send_ldap_result( ps_conn, ps_op, rc=LDAP_REFERRAL ,
265 matched_dn.bv_val, text, refs, NULL );
267 LOCK_ID_FREE( bdb->bi_dbenv, locker );
268 if ( refs ) ber_bvarray_free( refs );
269 if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
270 if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
271 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
272 ch_free( attrs[0].an_name.bv_val );
276 if (!manageDSAit && e != &slap_entry_root && is_entry_referral( e ) ) {
277 /* entry is a referral, don't allow add */
278 struct berval matched_dn;
279 BerVarray erefs, refs;
281 ber_dupbv( &matched_dn, &e->e_name );
282 erefs = get_entry_referrals( be, ps_conn, ps_op, e );
285 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
289 refs = referral_rewrite( erefs, &matched_dn,
291 ber_bvarray_free( erefs );
295 LDAP_LOG( OPERATION, RESULTS,
296 "bdb_search: entry is referral\n", 0, 0, 0 );
298 Debug( LDAP_DEBUG_TRACE, "bdb_search: entry is referral\n",
302 send_ldap_result( ps_conn, ps_op, LDAP_REFERRAL,
304 refs ? NULL : "bad referral object",
307 LOCK_ID_FREE( bdb->bi_dbenv, locker );
308 ber_bvarray_free( refs );
309 ber_memfree( matched_dn.bv_val );
310 if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
311 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
312 ch_free( attrs[0].an_name.bv_val );
316 /* if not root, get appropriate limits */
317 if ( be_isroot( be, &ps_op->o_ndn ) ) {
320 ( void ) get_limits( be, &ps_op->o_ndn, &limit );
323 /* The time/size limits come first because they require very little
324 * effort, so there's no chance the candidates are selected and then
325 * the request is not honored only because of time/size constraints */
327 /* if no time limit requested, use soft limit (unless root!) */
330 tlimit = -1; /* allow root to set no limit */
338 /* if no limit is required, use soft limit */
340 tlimit = limit->lms_t_soft;
342 /* if requested limit higher than hard limit, abort */
343 } else if ( tlimit > limit->lms_t_hard ) {
344 /* no hard limit means use soft instead */
345 if ( limit->lms_t_hard == 0 && tlimit > limit->lms_t_soft ) {
346 tlimit = limit->lms_t_soft;
348 /* positive hard limit means abort */
349 } else if ( limit->lms_t_hard > 0 ) {
350 send_search_result( ps_conn, ps_op,
351 LDAP_UNWILLING_TO_PERFORM,
352 NULL, NULL, NULL, NULL, 0 );
357 /* negative hard limit means no limit */
360 /* if no limit is required, use soft limit */
362 slimit = limit->lms_s_soft;
364 /* if requested limit higher than hard limit, abort */
365 } else if ( slimit > limit->lms_s_hard ) {
366 /* no hard limit means use soft instead */
367 if ( limit->lms_s_hard == 0 && slimit > limit->lms_s_soft ) {
368 slimit = limit->lms_s_soft;
370 /* positive hard limit means abort */
371 } else if ( limit->lms_s_hard > 0 ) {
372 send_search_result( ps_conn, ps_op,
373 LDAP_UNWILLING_TO_PERFORM,
374 NULL, NULL, NULL, NULL, 0 );
379 /* negative hard limit means no limit */
383 /* compute it anyway; root does not use it */
384 stoptime = ps_op->o_time + tlimit;
386 /* select candidates */
387 if ( scope == LDAP_SCOPE_BASE ) {
388 rc = psearch_base_candidate( be, e, candidates );
390 BDB_IDL_ALL( bdb, candidates );
391 rc = psearch_candidates( be, op, e, filter,
392 scope, deref, candidates );
395 if ( !BDB_IDL_IS_RANGE( candidates ) ) {
396 cursor = bdb_idl_search( candidates, entry->e_id );
397 if ( candidates[cursor] != entry->e_id ) {
401 if ( entry->e_id < BDB_IDL_RANGE_FIRST(candidates) &&
402 entry->e_id > BDB_IDL_RANGE_LAST(candidates) )
408 /* candidates = { e } */
410 candidates[1] = entry->e_id;
412 /* need normalized dn below */
413 ber_dupbv( &realbase, &e->e_nname );
415 if ( e != &slap_entry_root ) {
416 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
420 if ( candidates[0] == 0 ) {
422 LDAP_LOG ( OPERATION, RESULTS,
423 "bdb_search: no candidates\n", 0, 0, 0 );
425 Debug( LDAP_DEBUG_TRACE, "bdb_search: no candidates\n",
429 send_search_result( ps_conn, ps_op,
431 NULL, NULL, NULL, NULL, 0 );
437 /* if not root and candidates exceed to-be-checked entries, abort */
438 if ( !isroot && limit->lms_s_unchecked != -1 ) {
439 if ( BDB_IDL_N(candidates) > (unsigned) limit->lms_s_unchecked ) {
440 send_search_result( ps_conn, ps_op, LDAP_ADMINLIMIT_EXCEEDED,
441 NULL, NULL, NULL, NULL, 0 );
447 lcupf.f_choice = LDAP_FILTER_AND;
448 lcupf.f_and = &csnfnot;
451 csnfnot.f_choice = LDAP_FILTER_NOT;
452 csnfnot.f_not = &csnfeq;
453 csnfnot.f_next = &csnfand;
455 csnfeq.f_choice = LDAP_FILTER_EQUALITY;
456 csnfeq.f_ava = &aa_eq;
457 csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
458 ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
460 csnfand.f_choice = LDAP_FILTER_AND;
461 csnfand.f_and = &csnfge;
462 csnfand.f_next = NULL;
464 csnfge.f_choice = LDAP_FILTER_GE;
465 csnfge.f_ava = &aa_ge;
466 csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
467 ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
468 csnfge.f_next = filter;
472 /* check for abandon */
473 if ( ps_op->o_abandon ) {
478 /* check time limit */
479 if ( tlimit != -1 && slap_get_time() > stoptime ) {
480 send_search_result( ps_conn, ps_op, rc = LDAP_TIMELIMIT_EXCEEDED,
481 NULL, NULL, v2refs, NULL, nentries );
487 #ifdef BDB_SUBENTRIES
488 if ( is_entry_subentry( e ) ) {
489 if( scope != LDAP_SCOPE_BASE ) {
490 if(!get_subentries_visibility( ps_op )) {
491 /* only subentries are visible */
495 } else if ( get_subentries( ps_op ) &&
496 !get_subentries_visibility( ps_op ))
498 /* only subentries are visible */
502 } else if ( get_subentries_visibility( ps_op )) {
503 /* only subentries are visible */
509 if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
514 e = deref_entry_r( be, e, &err, &matched, &text );
521 if( e->e_id == id ) {
526 /* need to skip alias which deref into scope */
527 if( scope & LDAP_SCOPE_ONELEVEL ) {
530 dnParent( &e->e_nname, &pdn ):
531 if ( ber_bvcmp( pdn, &realbase ) ) {
535 } else if ( dnIsSuffix( &e->e_nname, &realbase ) ) {
536 /* alias is within scope */
538 LDAP_LOG ( OPERATION, RESULTS,
539 "bdb_search: \"%s\" in subtree\n", e->edn, 0, 0);
541 Debug( LDAP_DEBUG_TRACE,
542 "bdb_search: \"%s\" in subtree\n",
553 * if it's a referral, add it to the list of referrals. only do
554 * this for non-base searches, and don't check the filter
555 * explicitly here since it's only a candidate anyway.
557 if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
558 is_entry_referral( e ) )
563 if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
564 if ( !be_issuffix( be, &e->e_nname ) ) {
565 dnParent( &e->e_nname, &dn );
566 scopeok = dn_match( &dn, &realbase );
568 scopeok = (realbase.bv_len == 0);
571 } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
572 scopeok = dnIsSuffix( &e->e_nname, &realbase );
579 BerVarray erefs = get_entry_referrals(
580 be, ps_conn, ps_op, e );
581 BerVarray refs = referral_rewrite( erefs,
583 scope == LDAP_SCOPE_SUBTREE
587 send_search_reference( be, ps_conn, ps_op,
588 e, refs, NULL, &v2refs );
590 ber_bvarray_free( refs );
594 LDAP_LOG(OPERATION, DETAIL2,
595 "bdb_search: candidate referral %ld scope not okay\n",
598 Debug( LDAP_DEBUG_TRACE,
599 "bdb_search: candidate referral %ld scope not okay\n",
607 if ( psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
608 rc = test_filter( be, ps_conn, ps_op, e, &lcupf );
610 rc = LDAP_COMPARE_TRUE;
613 if ( rc == LDAP_COMPARE_TRUE ) {
617 if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
618 if ( be_issuffix( be, &e->e_nname ) ) {
619 scopeok = (realbase.bv_len == 0);
621 dnParent( &e->e_nname, &dn );
622 scopeok = dn_match( &dn, &realbase );
625 } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
626 scopeok = dnIsSuffix( &e->e_nname, &realbase );
633 /* check size limit */
634 if ( --slimit == -1 ) {
635 send_search_result( ps_conn, ps_op,
636 rc = LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
637 v2refs, NULL, nentries );
644 #if 0 /* noop is masked SLAP_CTRL_UPDATE */
645 if( ps_op->o_noop ) {
650 if ( psearch_type == LCUP_PSEARCH_BY_ADD ||
651 psearch_type == LCUP_PSEARCH_BY_DELETE ||
652 psearch_type == LCUP_PSEARCH_BY_MODIFY ||
653 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
658 const char *text = NULL;
659 LDAPControl *ctrls[2];
662 BerElement *ber = ber_alloc_t( LBER_USE_DER );
666 LDAP_LOG ( OPERATION, RESULTS,
667 "bdb_search: ber_alloc_t failed\n",
670 Debug( LDAP_DEBUG_TRACE,
671 "bdb_search: ber_alloc_t failed\n",
674 send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
675 NULL, "internal error", NULL, NULL );
679 LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count++;
681 ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
684 if ( LDAP_LIST_FIRST(
685 &ps_op->psearch_spec)->entry_count %
686 ps_op->o_clientupdate_interval == 0 )
689 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
690 AttributeDescription *desc = a->a_desc;
691 if ( desc == slap_schema.si_ad_entryCSN ) {
692 ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
693 if ( latest_entrycsn_bv.bv_val == NULL ) {
694 ber_dupbv( &latest_entrycsn_bv,
697 res = value_match( &ret, desc,
698 desc->ad_type->sat_ordering,
699 SLAP_MR_ASSERTION_SYNTAX_MATCH,
700 &entrycsn_bv, &latest_entrycsn_bv,
702 if ( res != LDAP_SUCCESS ) {
705 LDAP_LOG ( OPERATION, RESULTS,
707 "value_match failed\n",
710 Debug( LDAP_DEBUG_TRACE,
712 "value_match failed\n",
718 ch_free(latest_entrycsn_bv.bv_val);
719 latest_entrycsn_bv.bv_val = NULL;
720 ber_dupbv( &latest_entrycsn_bv,
727 if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
728 psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
730 ber_printf( ber, "{bb{sON}N}",
731 SLAP_LCUP_STATE_UPDATE_FALSE,
732 SLAP_LCUP_ENTRY_DELETED_FALSE,
733 LCUP_COOKIE_OID, &entrycsn_bv );
735 ber_printf( ber, "{bb{sON}N}",
736 SLAP_LCUP_STATE_UPDATE_FALSE,
737 SLAP_LCUP_ENTRY_DELETED_TRUE,
738 LCUP_COOKIE_OID, &entrycsn_bv );
741 ch_free( entrycsn_bv.bv_val );
742 entrycsn_bv.bv_val = NULL;
745 /* Do not send cookie */
746 if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
747 psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
749 ber_printf( ber, "{bbN}",
750 SLAP_LCUP_STATE_UPDATE_FALSE,
751 SLAP_LCUP_ENTRY_DELETED_FALSE );
753 ber_printf( ber, "{bbN}",
754 SLAP_LCUP_STATE_UPDATE_FALSE,
755 SLAP_LCUP_ENTRY_DELETED_TRUE );
759 ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
760 ctrls[0]->ldctl_iscritical = ps_op->o_clientupdate;
761 ret = ber_flatten( ber, &bv );
765 LDAP_LOG ( OPERATION, RESULTS,
766 "bdb_search: ber_flatten failed\n",
769 Debug( LDAP_DEBUG_TRACE,
770 "bdb_search: ber_flatten failed\n",
773 send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
774 NULL, "internal error", NULL, NULL );
778 ber_dupbv( &ctrls[0]->ldctl_value, bv );
780 result = send_search_entry( be, ps_conn, ps_op,
781 e, attrs, attrsonly, ctrls);
783 ch_free( ctrls[0]->ldctl_value.bv_val );
788 if ( psearch_type == LCUP_PSEARCH_BY_MODIFY ) {
789 struct psid_entry* psid_e;
790 LDAP_LIST_FOREACH( psid_e, &op->premodify_list,
794 LDAP_LIST_FIRST(&ps_op->psearch_spec))
796 LDAP_LIST_REMOVE(psid_e, link);
800 if (psid_e != NULL) free (psid_e);
803 } else if ( psearch_type == LCUP_PSEARCH_BY_PREMODIFY ) {
804 struct psid_entry* psid_e;
805 psid_e = (struct psid_entry *) calloc (1,
806 sizeof(struct psid_entry));
807 psid_e->ps = LDAP_LIST_FIRST(&ps_op->psearch_spec);
808 LDAP_LIST_INSERT_HEAD( &op->premodify_list,
817 case 0: /* entry sent ok */
820 case 1: /* entry not sent */
822 case -1: /* connection closed */
829 LDAP_LOG ( OPERATION, RESULTS,
830 "bdb_search: %ld scope not okay\n", (long) id, 0, 0);
832 Debug( LDAP_DEBUG_TRACE,
833 "bdb_search: %ld scope not okay\n", (long) id, 0, 0 );
838 LDAP_LOG ( OPERATION, RESULTS,
839 "bdb_search: %ld does match filter\n", (long) id, 0, 0);
841 Debug( LDAP_DEBUG_TRACE,
842 "bdb_search: %ld does match filter\n",
851 if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) {
852 ch_free( csnfeq.f_av_value.bv_val );
855 if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) {
856 ch_free( csnfge.f_av_value.bv_val );
859 LOCK_ID_FREE( bdb->bi_dbenv, locker );
861 if( v2refs ) ber_bvarray_free( v2refs );
862 if( realbase.bv_val ) ch_free( realbase.bv_val );
863 if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
864 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
865 ch_free( attrs[0].an_name.bv_val );
870 static int psearch_base_candidate(
876 LDAP_LOG ( OPERATION, ENTRY,
877 "psearch_base_candidate: base: \"%s\" (0x%08lx)\n", e->e_dn, (long) e->e_id, 0);
879 Debug(LDAP_DEBUG_ARGS, "psearch_base_candidates: base: \"%s\" (0x%08lx)\n",
880 e->e_dn, (long) e->e_id, 0);
888 /* Look for "objectClass Present" in this filter.
889 * Also count depth of filter tree while we're at it.
891 static int psearch_oc_filter(
899 if( cur > *max ) *max = cur;
901 switch(f->f_choice) {
902 case LDAP_FILTER_PRESENT:
903 if (f->f_desc == slap_schema.si_ad_objectClass) {
908 case LDAP_FILTER_AND:
911 for (f=f->f_and; f; f=f->f_next) {
912 (void) psearch_oc_filter(f, cur, max);
922 static int psearch_candidates(
932 Filter f, scopef, rf, xf;
934 AttributeAssertion aa_ref;
935 #ifdef BDB_SUBENTRIES
937 AttributeAssertion aa_subentry;
941 AttributeAssertion aa_alias;
945 * This routine takes as input a filter (user-filter)
946 * and rewrites it as follows:
947 * (&(scope=DN)[(objectClass=subentry)]
948 * (|[(objectClass=referral)(objectClass=alias)](user-filter))
952 LDAP_LOG ( OPERATION, ENTRY,
953 "psearch_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
954 e->e_dn, (long) e->e_id, scope);
956 Debug(LDAP_DEBUG_TRACE,
957 "psearch_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
958 e->e_dn, (long) e->e_id, scope );
962 xf.f_choice = LDAP_FILTER_OR;
965 /* If the user's filter uses objectClass=*,
966 * these clauses are redundant.
968 if (!psearch_oc_filter(filter, 1, &depth) && !get_subentries_visibility(op) ) {
969 if( !get_manageDSAit(op) ) { /* match referrals */
970 struct berval bv_ref = { sizeof("REFERRAL")-1, "REFERRAL" };
971 rf.f_choice = LDAP_FILTER_EQUALITY;
973 rf.f_av_desc = slap_schema.si_ad_objectClass;
974 rf.f_av_value = bv_ref;
980 if( deref & LDAP_DEREF_SEARCHING ) { /* match aliases */
981 struct berval bv_alias = { sizeof("ALIAS")-1, "ALIAS" };
982 af.f_choice = LDAP_FILTER_EQUALITY;
983 af.f_ava = &aa_alias;
984 af.f_av_desc = slap_schema.si_ad_objectClass;
985 af.f_av_value = bv_alias;
990 /* We added one of these clauses, filter depth increased */
991 if( xf.f_or != filter ) depth++;
995 f.f_choice = LDAP_FILTER_AND;
997 scopef.f_choice = scope == LDAP_SCOPE_SUBTREE
998 ? SLAPD_FILTER_DN_SUBTREE
999 : SLAPD_FILTER_DN_ONE;
1000 scopef.f_dn = &e->e_nname;
1001 scopef.f_next = xf.f_or == filter ? filter : &xf ;
1002 /* Filter depth increased again, adding scope clause */
1005 #ifdef BDB_SUBENTRIES
1006 if( get_subentries_visibility( op ) ) {
1007 struct berval bv_subentry = { sizeof("SUBENTRY")-1, "SUBENTRY" };
1008 sf.f_choice = LDAP_FILTER_EQUALITY;
1009 sf.f_ava = &aa_subentry;
1010 sf.f_av_desc = slap_schema.si_ad_objectClass;
1011 sf.f_av_value = bv_subentry;
1012 sf.f_next = scopef.f_next;
1013 scopef.f_next = &sf;
1017 /* Allocate IDL stack, plus 1 more for former tmp */
1018 stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
1020 rc = bdb_filter_candidates( be, &f, ids, stack, stack+BDB_IDL_UM_SIZE );
1026 LDAP_LOG ( OPERATION, DETAIL1,
1027 "bdb_psearch_candidates: failed (rc=%d)\n", rc, 0, 0 );
1029 Debug(LDAP_DEBUG_TRACE,
1030 "bdb_psearch_candidates: failed (rc=%d)\n",
1036 LDAP_LOG ( OPERATION, DETAIL1,
1037 "bdb_psearch_candidates: id=%ld first=%ld last=%ld\n",
1038 (long) ids[0], (long) BDB_IDL_FIRST(ids),
1039 (long) BDB_IDL_LAST(ids));
1041 Debug(LDAP_DEBUG_TRACE,
1042 "bdb_psearch_candidates: id=%ld first=%ld last=%ld\n",
1044 (long) BDB_IDL_FIRST(ids),
1045 (long) BDB_IDL_LAST(ids) );
1053 #endif /* LDAP_CLIENT_UPDATE */