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];
661 char berbuf[LBER_ELEMENT_SIZEOF];
662 BerElement *ber = (BerElement *)berbuf;
664 ber_init2( ber, NULL, LBER_USE_DER );
666 LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count++;
668 ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
671 if ( LDAP_LIST_FIRST(
672 &ps_op->psearch_spec)->entry_count %
673 ps_op->o_clientupdate_interval == 0 )
676 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
677 AttributeDescription *desc = a->a_desc;
678 if ( desc == slap_schema.si_ad_entryCSN ) {
679 ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
680 if ( latest_entrycsn_bv.bv_val == NULL ) {
681 ber_dupbv( &latest_entrycsn_bv,
684 res = value_match( &ret, desc,
685 desc->ad_type->sat_ordering,
686 SLAP_MR_ASSERTION_SYNTAX_MATCH,
687 &entrycsn_bv, &latest_entrycsn_bv,
689 if ( res != LDAP_SUCCESS ) {
692 LDAP_LOG ( OPERATION, RESULTS,
694 "value_match failed\n",
697 Debug( LDAP_DEBUG_TRACE,
699 "value_match failed\n",
705 ch_free(latest_entrycsn_bv.bv_val);
706 latest_entrycsn_bv.bv_val = NULL;
707 ber_dupbv( &latest_entrycsn_bv,
714 if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
715 psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
717 ber_printf( ber, "{bb{sON}N}",
718 SLAP_LCUP_STATE_UPDATE_FALSE,
719 SLAP_LCUP_ENTRY_DELETED_FALSE,
720 LCUP_COOKIE_OID, &entrycsn_bv );
722 ber_printf( ber, "{bb{sON}N}",
723 SLAP_LCUP_STATE_UPDATE_FALSE,
724 SLAP_LCUP_ENTRY_DELETED_TRUE,
725 LCUP_COOKIE_OID, &entrycsn_bv );
728 ch_free( entrycsn_bv.bv_val );
729 entrycsn_bv.bv_val = NULL;
732 /* Do not send cookie */
733 if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
734 psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
736 ber_printf( ber, "{bbN}",
737 SLAP_LCUP_STATE_UPDATE_FALSE,
738 SLAP_LCUP_ENTRY_DELETED_FALSE );
740 ber_printf( ber, "{bbN}",
741 SLAP_LCUP_STATE_UPDATE_FALSE,
742 SLAP_LCUP_ENTRY_DELETED_TRUE );
746 ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
747 ctrls[0]->ldctl_iscritical = ps_op->o_clientupdate;
748 ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
753 LDAP_LOG ( OPERATION, RESULTS,
754 "bdb_search: ber_flatten2 failed\n",
757 Debug( LDAP_DEBUG_TRACE,
758 "bdb_search: ber_flatten2 failed\n",
761 send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
762 NULL, "internal error", NULL, NULL );
766 result = send_search_entry( be, ps_conn, ps_op,
767 e, attrs, attrsonly, ctrls);
772 if ( psearch_type == LCUP_PSEARCH_BY_MODIFY ) {
773 struct psid_entry* psid_e;
774 LDAP_LIST_FOREACH( psid_e, &op->premodify_list,
778 LDAP_LIST_FIRST(&ps_op->psearch_spec))
780 LDAP_LIST_REMOVE(psid_e, link);
784 if (psid_e != NULL) free (psid_e);
787 } else if ( psearch_type == LCUP_PSEARCH_BY_PREMODIFY ) {
788 struct psid_entry* psid_e;
789 psid_e = (struct psid_entry *) calloc (1,
790 sizeof(struct psid_entry));
791 psid_e->ps = LDAP_LIST_FIRST(&ps_op->psearch_spec);
792 LDAP_LIST_INSERT_HEAD( &op->premodify_list,
801 case 0: /* entry sent ok */
804 case 1: /* entry not sent */
806 case -1: /* connection closed */
813 LDAP_LOG ( OPERATION, RESULTS,
814 "bdb_search: %ld scope not okay\n", (long) id, 0, 0);
816 Debug( LDAP_DEBUG_TRACE,
817 "bdb_search: %ld scope not okay\n", (long) id, 0, 0 );
822 LDAP_LOG ( OPERATION, RESULTS,
823 "bdb_search: %ld does match filter\n", (long) id, 0, 0);
825 Debug( LDAP_DEBUG_TRACE,
826 "bdb_search: %ld does match filter\n",
835 if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) {
836 ch_free( csnfeq.f_av_value.bv_val );
839 if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) {
840 ch_free( csnfge.f_av_value.bv_val );
843 LOCK_ID_FREE( bdb->bi_dbenv, locker );
845 if( v2refs ) ber_bvarray_free( v2refs );
846 if( realbase.bv_val ) ch_free( realbase.bv_val );
847 if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
848 psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
849 ch_free( attrs[0].an_name.bv_val );
854 static int psearch_base_candidate(
860 LDAP_LOG ( OPERATION, ENTRY,
861 "psearch_base_candidate: base: \"%s\" (0x%08lx)\n", e->e_dn, (long) e->e_id, 0);
863 Debug(LDAP_DEBUG_ARGS, "psearch_base_candidates: base: \"%s\" (0x%08lx)\n",
864 e->e_dn, (long) e->e_id, 0);
872 /* Look for "objectClass Present" in this filter.
873 * Also count depth of filter tree while we're at it.
875 static int psearch_oc_filter(
883 if( cur > *max ) *max = cur;
885 switch(f->f_choice) {
886 case LDAP_FILTER_PRESENT:
887 if (f->f_desc == slap_schema.si_ad_objectClass) {
892 case LDAP_FILTER_AND:
895 for (f=f->f_and; f; f=f->f_next) {
896 (void) psearch_oc_filter(f, cur, max);
906 static int psearch_candidates(
916 Filter f, scopef, rf, xf;
918 AttributeAssertion aa_ref;
919 #ifdef BDB_SUBENTRIES
921 AttributeAssertion aa_subentry;
925 AttributeAssertion aa_alias;
929 * This routine takes as input a filter (user-filter)
930 * and rewrites it as follows:
931 * (&(scope=DN)[(objectClass=subentry)]
932 * (|[(objectClass=referral)(objectClass=alias)](user-filter))
936 LDAP_LOG ( OPERATION, ENTRY,
937 "psearch_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
938 e->e_dn, (long) e->e_id, scope);
940 Debug(LDAP_DEBUG_TRACE,
941 "psearch_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
942 e->e_dn, (long) e->e_id, scope );
946 xf.f_choice = LDAP_FILTER_OR;
949 /* If the user's filter uses objectClass=*,
950 * these clauses are redundant.
952 if (!psearch_oc_filter(filter, 1, &depth) && !get_subentries_visibility(op) ) {
953 if( !get_manageDSAit(op) ) { /* match referrals */
954 struct berval bv_ref = { sizeof("REFERRAL")-1, "REFERRAL" };
955 rf.f_choice = LDAP_FILTER_EQUALITY;
957 rf.f_av_desc = slap_schema.si_ad_objectClass;
958 rf.f_av_value = bv_ref;
964 if( deref & LDAP_DEREF_SEARCHING ) { /* match aliases */
965 struct berval bv_alias = { sizeof("ALIAS")-1, "ALIAS" };
966 af.f_choice = LDAP_FILTER_EQUALITY;
967 af.f_ava = &aa_alias;
968 af.f_av_desc = slap_schema.si_ad_objectClass;
969 af.f_av_value = bv_alias;
974 /* We added one of these clauses, filter depth increased */
975 if( xf.f_or != filter ) depth++;
979 f.f_choice = LDAP_FILTER_AND;
981 scopef.f_choice = scope == LDAP_SCOPE_SUBTREE
982 ? SLAPD_FILTER_DN_SUBTREE
983 : SLAPD_FILTER_DN_ONE;
984 scopef.f_dn = &e->e_nname;
985 scopef.f_next = xf.f_or == filter ? filter : &xf ;
986 /* Filter depth increased again, adding scope clause */
989 #ifdef BDB_SUBENTRIES
990 if( get_subentries_visibility( op ) ) {
991 struct berval bv_subentry = { sizeof("SUBENTRY")-1, "SUBENTRY" };
992 sf.f_choice = LDAP_FILTER_EQUALITY;
993 sf.f_ava = &aa_subentry;
994 sf.f_av_desc = slap_schema.si_ad_objectClass;
995 sf.f_av_value = bv_subentry;
996 sf.f_next = scopef.f_next;
1001 /* Allocate IDL stack, plus 1 more for former tmp */
1002 stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
1004 rc = bdb_filter_candidates( be, &f, ids, stack, stack+BDB_IDL_UM_SIZE );
1010 LDAP_LOG ( OPERATION, DETAIL1,
1011 "bdb_psearch_candidates: failed (rc=%d)\n", rc, 0, 0 );
1013 Debug(LDAP_DEBUG_TRACE,
1014 "bdb_psearch_candidates: failed (rc=%d)\n",
1020 LDAP_LOG ( OPERATION, DETAIL1,
1021 "bdb_psearch_candidates: id=%ld first=%ld last=%ld\n",
1022 (long) ids[0], (long) BDB_IDL_FIRST(ids),
1023 (long) BDB_IDL_LAST(ids));
1025 Debug(LDAP_DEBUG_TRACE,
1026 "bdb_psearch_candidates: id=%ld first=%ld last=%ld\n",
1028 (long) BDB_IDL_FIRST(ids),
1029 (long) BDB_IDL_LAST(ids) );
1037 #endif /* LDAP_CLIENT_UPDATE */