1 /* search.c - search operation */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/string.h>
17 static int base_candidate(
21 static int search_candidates(
22 Operation *stackop, /* op with the current threadctx/slab cache */
23 Operation *sop, /* search op */
29 static void send_pagerequest_response(
35 /* Dereference aliases for a single alias entry. Return the final
36 * dereferenced entry on success, NULL on any failure.
38 static Entry * deref_base (
48 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
53 rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;
54 rs->sr_text = "maximum deref depth exceeded";
56 while (BDB_IDL_N(tmp) < op->o_bd->be_max_deref_depth) {
58 /* Remember the last entry we looked at, so we can
63 /* If this is part of a subtree or onelevel search,
64 * have we seen this ID before? If so, quit.
66 if ( visited && bdb_idl_insert( visited, e->e_id ) ) {
71 /* If we've seen this ID during this deref iteration,
74 if ( bdb_idl_insert( tmp, e->e_id ) ) {
75 rs->sr_err = LDAP_ALIAS_PROBLEM;
76 rs->sr_text = "circular alias";
81 /* If there was a problem getting the aliasedObjectName,
82 * get_alias_dn will have set the error status.
84 if ( get_alias_dn(e, &ndn, &rs->sr_err, &rs->sr_text) ) {
89 rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &ndn, &ei,
90 0, locker, &lockr, op->o_tmpmemctx );
92 if ( ei ) e = ei->bei_e;
96 rs->sr_err = LDAP_ALIAS_PROBLEM;
97 rs->sr_text = "aliasedObject not found";
101 /* Free the previous entry, continue to work with the
102 * one we just retrieved.
104 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,
108 /* We found a regular entry. Return this to the caller. The
109 * entry is still locked for Read.
111 if (!is_entry_alias(e)) {
112 rs->sr_err = LDAP_SUCCESS;
120 /* Look for and dereference all aliases within the search scope. Adds
121 * the dereferenced entries to the "ids" list. Requires "stack" to be
122 * able to hold 8 levels of DB_SIZE IDLs.
124 static int search_aliases(
135 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
136 ID *aliases, *curscop, *subscop, *visited, *newsubs, *oldsubs, *tmp;
137 ID cursora, ida, cursoro, ido, *subscop2;
140 struct berval bv_alias = { sizeof("alias")-1, "alias" };
141 AttributeAssertion aa_alias;
143 DB_LOCK locka, lockr;
147 aliases = stack; /* IDL of all aliases in the database */
148 curscop = aliases + BDB_IDL_DB_SIZE; /* Aliases in the current scope */
149 subscop = curscop + BDB_IDL_DB_SIZE; /* The current scope */
150 visited = subscop + BDB_IDL_DB_SIZE; /* IDs we've seen in this search */
151 newsubs = visited + BDB_IDL_DB_SIZE; /* New subtrees we've added */
152 oldsubs = newsubs + BDB_IDL_DB_SIZE; /* Subtrees added previously */
153 tmp = oldsubs + BDB_IDL_DB_SIZE; /* Scratch space for deref_base() */
155 /* A copy of subscop, because subscop gets clobbered by
156 * the bdb_idl_union/intersection routines
158 subscop2 = tmp + BDB_IDL_DB_SIZE;
160 af.f_choice = LDAP_FILTER_EQUALITY;
161 af.f_ava = &aa_alias;
162 af.f_av_desc = slap_schema.si_ad_objectClass;
163 af.f_av_value = bv_alias;
166 /* Find all aliases in database */
167 BDB_IDL_ZERO( aliases );
168 rs->sr_err = bdb_filter_candidates( op, &af, aliases,
170 if (rs->sr_err != LDAP_SUCCESS) {
174 oldsubs[1] = e->e_id;
177 BDB_IDL_ZERO( visited );
178 BDB_IDL_ZERO( newsubs );
181 ido = bdb_idl_first( oldsubs, &cursoro );
184 /* Set curscop to only the aliases in the current scope. Start with
185 * all the aliases, obtain the IDL for the current scope, and then
186 * get the intersection of these two IDLs. Add the current scope
187 * to the cumulative list of candidates.
189 BDB_IDL_CPY( curscop, aliases );
190 rs->sr_err = bdb_filter_candidates( op, sf, subscop, NULL, NULL );
194 bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &locka);
196 BDB_IDL_CPY(subscop2, subscop);
197 rs->sr_err = bdb_idl_intersection(curscop, subscop);
198 bdb_idl_union( ids, subscop2 );
200 /* Dereference all of the aliases in the current scope. */
202 for (ida = bdb_idl_first(curscop, &cursora); ida != NOID;
203 ida = bdb_idl_next(curscop, &cursora))
206 rs->sr_err = bdb_cache_find_id(op->o_bd, NULL,
207 ida, &ei, 0, locker, &lockr, op->o_tmpmemctx );
208 if (rs->sr_err != LDAP_SUCCESS) {
213 /* This should only happen if the curscop IDL has maxed out and
214 * turned into a range that spans IDs indiscriminately
216 if (!is_entry_alias(a)) {
217 bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache,
222 /* Actually dereference the alias */
224 a = deref_base( op, rs, a, &matched, locker, &lockr,
227 /* If the target was not already in our current candidates,
228 * make note of it in the newsubs list. Also
229 * set it in the scopes list so that bdb_search
232 if (bdb_idl_insert(ids, a->e_id) == 0) {
233 bdb_idl_insert(newsubs, a->e_id);
234 bdb_idl_insert(scopes, a->e_id);
236 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,
239 } else if (matched) {
240 /* Alias could not be dereferenced, or it deref'd to
241 * an ID we've already seen. Ignore it.
243 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,
248 /* If this is a OneLevel search, we're done; oldsubs only had one
249 * ID in it. For a Subtree search, oldsubs may be a list of scope IDs.
251 if (op->ors_scope != LDAP_SCOPE_SUBTREE) break;
253 ido = bdb_idl_next( oldsubs, &cursoro );
255 /* If we're done processing the old scopes, did we add any new
256 * scopes in this iteration? If so, go back and do those now.
259 if (BDB_IDL_IS_ZERO(newsubs)) break;
260 BDB_IDL_CPY(oldsubs, newsubs);
261 BDB_IDL_ZERO(newsubs);
263 ido = bdb_idl_first( oldsubs, &cursoro );
266 /* Find the entry corresponding to the next scope. If it can't
267 * be found, ignore it and move on. This should never happen;
268 * we should never see the ID of an entry that doesn't exist.
269 * Set the name so that the scope's IDL can be retrieved.
272 rs->sr_err = bdb_cache_find_id(op->o_bd, NULL, ido, &ei,
273 0, locker, &locka, op->o_tmpmemctx );
274 if (rs->sr_err != LDAP_SUCCESS) goto nextido;
277 sf->f_dn = &e->e_nname;
279 /* bdb_dn2idl uses IDs for keys, not DNs */
280 sf->f_dn = (struct berval *)ei;
287 int is_sync_protocol( Operation *op )
289 #if !defined(LDAP_CLIENT_UPDATE) && !defined(LDAP_SYNC)
293 #ifdef LDAP_CLIENT_UPDATE
294 if ( op->o_clientupdate_type & SLAP_LCUP_SYNC_AND_PERSIST )
298 if ( op->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST )
304 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
305 #define IS_BDB_REPLACE(type) (( type == LDAP_PSEARCH_BY_DELETE ) || \
306 ( type == LDAP_PSEARCH_BY_SCOPEOUT ))
307 #define IS_PSEARCH (op != sop)
310 bdb_abandon( Operation *op, SlapReply *rs )
313 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
315 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
316 if ( ps_list->o_connid == op->o_connid ) {
317 if ( ps_list->o_msgid == op->oq_abandon.rs_msgid ) {
318 ps_list->o_abandon = 1;
319 LDAP_LIST_REMOVE( ps_list, o_ps_link );
320 slap_op_free ( ps_list );
325 return LDAP_UNAVAILABLE;
329 bdb_cancel( Operation *op, SlapReply *rs )
332 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
334 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
335 if ( ps_list->o_connid == op->o_connid ) {
336 if ( ps_list->o_msgid == op->oq_cancel.rs_msgid ) {
337 ps_list->o_cancel = SLAP_CANCEL_DONE;
338 LDAP_LIST_REMOVE( ps_list, o_ps_link );
341 bdb_build_sync_done_ctrl( conn, ps_list, ps_list->ctrls,
342 1, &latest_entrycsn_bv );
343 send_ldap_result( conn, ps_list, LDAP_CANCELLED,
344 NULL, NULL, NULL, ps_list->ctrls, ps_list->nentries);
346 rs->sr_err = LDAP_CANCELLED;
347 send_ldap_result( ps_list, rs );
349 slap_op_free ( ps_list );
354 return LDAP_UNAVAILABLE;
357 int bdb_search( Operation *op, SlapReply *rs )
359 return bdb_do_search( op, rs, op, NULL, 0 );
362 /* For persistent searches, op is the currently executing operation,
363 * sop is the persistent search. For regular searches, sop = op.
366 bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
367 Entry *ps_e, int ps_type )
371 int bdb_search( Operation *op, SlapReply *rs )
374 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
377 ID candidates[BDB_IDL_UM_SIZE];
378 ID scopes[BDB_IDL_DB_SIZE];
379 Entry *e = NULL, base;
380 Entry *matched = NULL;
382 struct berval realbase = { 0, NULL };
386 AttributeName *attrs;
388 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
389 Filter cookief, csnfnot, csnfeq, csnfand, csnfge;
390 AttributeAssertion aa_ge, aa_eq;
393 struct berval entrycsn_bv = { 0, NULL };
395 struct berval latest_entrycsn_bv = { 0, NULL };
396 LDAPControl *ctrls[SLAP_SEARCH_MAX_CTRLS];
398 AttributeName uuid_attr[2];
401 int entry_sync_state = -1;
402 AttributeName null_attr;
405 struct slap_limits_set *limit = NULL;
408 u_int32_t locker = 0;
412 LDAP_LOG( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
414 Debug( LDAP_DEBUG_TRACE, "=> bdb_back_search\n",
417 attrs = sop->oq_search.rs_attrs;
419 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
420 #ifdef LDAP_CLIENT_UPDATE
421 if ( !IS_PSEARCH && sop->o_clientupdate_type & SLAP_LCUP_PERSIST ) {
422 sop->o_ps_protocol = LDAP_CLIENT_UPDATE;
423 LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link );
428 /* psearch needs to be registered before refresh begins */
429 /* psearch and refresh transmission is serialized in send_ldap_ber() */
430 if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_PERSIST ) {
431 sop->o_ps_protocol = LDAP_SYNC;
432 LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link );
434 null_attr.an_desc = NULL;
435 null_attr.an_oc = NULL;
436 null_attr.an_name.bv_len = 0;
437 null_attr.an_name.bv_val = NULL;
440 for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ ) {
441 ctrls[num_ctrls] = NULL;
445 if ( IS_PSEARCH && IS_BDB_REPLACE(ps_type)) {
446 #ifdef LDAP_CLIENT_UPDATE
447 if ( sop->o_ps_protocol == LDAP_CLIENT_UPDATE ) {
449 attrs[0].an_desc = slap_schema.si_ad_entryUUID;
450 attrs[0].an_oc = NULL;
451 attrs[0].an_name = attrs[0].an_desc->ad_cname;
452 attrs[1].an_desc = NULL;
453 attrs[1].an_oc = NULL;
454 attrs[1].an_name.bv_len = 0;
455 attrs[1].an_name.bv_val = NULL;
459 if (sop->o_ps_protocol == LDAP_SYNC ) {
461 attrs[0].an_desc = NULL;
462 attrs[0].an_oc = NULL;
463 attrs[0].an_name.bv_len = 0;
464 attrs[0].an_name.bv_val = NULL;
474 manageDSAit = get_manageDSAit( sop );
476 /* Sync / LCUP controls override manageDSAit */
478 #ifdef LDAP_CLIENT_UPDATE
479 if ( !IS_PSEARCH && sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
480 if ( manageDSAit == SLAP_NO_CONTROL )
481 manageDSAit = SLAP_CRITICAL_CONTROL;
485 if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
486 if ( manageDSAit == SLAP_NO_CONTROL )
487 manageDSAit = SLAP_CRITICAL_CONTROL;
491 if ( manageDSAit == SLAP_NO_CONTROL )
492 manageDSAit = SLAP_CRITICAL_CONTROL;
495 rs->sr_err = LOCK_ID (bdb->bi_dbenv, &locker );
501 send_ldap_error( sop, rs, LDAP_OTHER, "internal error" );
505 if ( sop->o_req_ndn.bv_len == 0 ) {
506 /* DIT root special case */
507 e = (Entry *) &slap_entry_root;
511 /* get entry with reader lock */
512 rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &sop->o_req_ndn, &ei,
513 1, locker, &lock, op->o_tmpmemctx );
518 matched = ei->bei_e; break;
520 e = ei->bei_e; break;
522 send_ldap_error( sop, rs, LDAP_BUSY, "ldap server busy" );
523 LOCK_ID_FREE (bdb->bi_dbenv, locker );
525 case DB_LOCK_DEADLOCK:
526 case DB_LOCK_NOTGRANTED:
529 send_ldap_error( sop, rs, LDAP_OTHER, "internal error" );
530 LOCK_ID_FREE (bdb->bi_dbenv, locker );
534 if ( e && (op->ors_deref & LDAP_DEREF_FINDING) && is_entry_alias(e) ) {
535 BDB_IDL_ZERO(candidates);
536 e = deref_base( op, rs, e, &matched, locker, &lock,
541 struct berval matched_dn = { 0, NULL };
543 if ( matched != NULL ) {
545 ber_dupbv( &matched_dn, &matched->e_name );
547 erefs = is_entry_referral( matched )
548 ? get_entry_referrals( op, matched )
551 bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache,
556 rs->sr_ref = referral_rewrite( erefs, &matched_dn,
557 &sop->o_req_dn, sop->oq_search.rs_scope );
558 ber_bvarray_free( erefs );
562 rs->sr_ref = referral_rewrite( default_referral,
563 NULL, &sop->o_req_dn, sop->oq_search.rs_scope );
566 rs->sr_err=LDAP_REFERRAL;
567 rs->sr_matched = matched_dn.bv_val;
568 send_ldap_result( sop, rs );
570 LOCK_ID_FREE (bdb->bi_dbenv, locker );
572 ber_bvarray_free( rs->sr_ref );
575 if ( matched_dn.bv_val ) {
576 ber_memfree( matched_dn.bv_val );
577 rs->sr_matched = NULL;
582 if (!manageDSAit && e != &slap_entry_root && is_entry_referral( e ) ) {
583 /* entry is a referral, don't allow add */
584 struct berval matched_dn;
587 ber_dupbv( &matched_dn, &e->e_name );
588 erefs = get_entry_referrals( op, e );
590 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
594 rs->sr_ref = referral_rewrite( erefs, &matched_dn,
595 &sop->o_req_dn, sop->oq_search.rs_scope );
596 ber_bvarray_free( erefs );
600 LDAP_LOG ( OPERATION, RESULTS,
601 "bdb_search: entry is referral\n", 0, 0, 0 );
603 Debug( LDAP_DEBUG_TRACE, "bdb_search: entry is referral\n",
607 if (!rs->sr_ref) rs->sr_text = "bad_referral object";
608 rs->sr_err = LDAP_REFERRAL;
609 rs->sr_matched = matched_dn.bv_val;
610 send_ldap_result( sop, rs );
612 LOCK_ID_FREE (bdb->bi_dbenv, locker );
613 ber_bvarray_free( rs->sr_ref );
615 ber_memfree( matched_dn.bv_val );
616 rs->sr_matched = NULL;
620 /* if not root, get appropriate limits */
621 if ( be_isroot( op->o_bd, &sop->o_ndn ) ) {
624 ( void ) get_limits( op->o_bd, &sop->o_ndn, &limit );
627 /* The time/size limits come first because they require very little
628 * effort, so there's no chance the candidates are selected and then
629 * the request is not honored only because of time/size constraints */
631 /* if no time limit requested, use soft limit (unless root!) */
633 if ( sop->oq_search.rs_tlimit == 0 ) {
634 sop->oq_search.rs_tlimit = -1; /* allow root to set no limit */
637 if ( sop->oq_search.rs_slimit == 0 ) {
638 sop->oq_search.rs_slimit = -1;
642 /* if no limit is required, use soft limit */
643 if ( sop->oq_search.rs_tlimit <= 0 ) {
644 sop->oq_search.rs_tlimit = limit->lms_t_soft;
646 /* if requested limit higher than hard limit, abort */
647 } else if ( sop->oq_search.rs_tlimit > limit->lms_t_hard ) {
648 /* no hard limit means use soft instead */
649 if ( limit->lms_t_hard == 0
650 && limit->lms_t_soft > -1
651 && sop->oq_search.rs_tlimit > limit->lms_t_soft ) {
652 sop->oq_search.rs_tlimit = limit->lms_t_soft;
654 /* positive hard limit means abort */
655 } else if ( limit->lms_t_hard > 0 ) {
656 rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
657 send_ldap_result( sop, rs );
662 /* negative hard limit means no limit */
665 /* if no limit is required, use soft limit */
666 if ( sop->oq_search.rs_slimit <= 0 ) {
667 if ( get_pagedresults(sop) && limit->lms_s_pr != 0 ) {
668 sop->oq_search.rs_slimit = limit->lms_s_pr;
670 sop->oq_search.rs_slimit = limit->lms_s_soft;
673 /* if requested limit higher than hard limit, abort */
674 } else if ( sop->oq_search.rs_slimit > limit->lms_s_hard ) {
675 /* no hard limit means use soft instead */
676 if ( limit->lms_s_hard == 0
677 && limit->lms_s_soft > -1
678 && sop->oq_search.rs_slimit > limit->lms_s_soft ) {
679 sop->oq_search.rs_slimit = limit->lms_s_soft;
681 /* positive hard limit means abort */
682 } else if ( limit->lms_s_hard > 0 ) {
683 rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
684 send_ldap_result( sop, rs );
689 /* negative hard limit means no limit */
693 /* compute it anyway; root does not use it */
694 stoptime = op->o_time + sop->oq_search.rs_tlimit;
696 /* need normalized dn below */
697 ber_dupbv( &realbase, &e->e_nname );
699 /* Copy info to base, must free entry before accessing the database
700 * in search_candidates, to avoid deadlocks.
702 base.e_private = e->e_private;
703 base.e_nname = realbase;
706 if ( e != &slap_entry_root ) {
707 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
711 /* select candidates */
712 if ( sop->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
713 rs->sr_err = base_candidate( op->o_bd, &base, candidates );
716 BDB_IDL_ZERO( candidates );
717 BDB_IDL_ZERO( scopes );
718 rs->sr_err = search_candidates( op, sop, rs, &base, locker, candidates, scopes );
721 /* start cursor at beginning of candidates.
724 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
726 if ( !BDB_IDL_IS_RANGE( candidates ) ) {
727 cursor = bdb_idl_search( candidates, ps_e->e_id );
728 if ( candidates[cursor] != ps_e->e_id ) {
729 rs->sr_err = LDAP_SUCCESS;
733 if ( ps_e->e_id < BDB_IDL_RANGE_FIRST(candidates)
734 || ps_e->e_id > BDB_IDL_RANGE_LAST(candidates)){
735 rs->sr_err = LDAP_SUCCESS;
740 candidates[1] = ps_e->e_id;
744 if ( candidates[0] == 0 ) {
746 LDAP_LOG ( OPERATION, RESULTS,
747 "bdb_search: no candidates\n", 0, 0, 0 );
749 Debug( LDAP_DEBUG_TRACE, "bdb_search: no candidates\n",
753 rs->sr_err = LDAP_SUCCESS;
754 send_ldap_result( sop, rs );
759 /* if not root and candidates exceed to-be-checked entries, abort */
760 if ( !isroot && limit->lms_s_unchecked != -1 ) {
761 if ( BDB_IDL_N(candidates) > (unsigned) limit->lms_s_unchecked ) {
762 rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
763 send_ldap_result( sop, rs );
769 if ( isroot || !limit->lms_s_pr_hide ) {
770 tentries = BDB_IDL_N(candidates);
773 #ifdef LDAP_CONTROL_PAGEDRESULTS
774 if ( get_pagedresults(sop) ) {
775 if ( sop->o_pagedresults_state.ps_cookie == 0 ) {
778 if ( sop->o_pagedresults_size == 0 ) {
779 rs->sr_err = LDAP_SUCCESS;
780 rs->sr_text = "search abandoned by pagedResult size=0";
781 send_ldap_result( sop, rs );
784 for ( id = bdb_idl_first( candidates, &cursor );
785 id != NOID && id <= (ID)( sop->o_pagedresults_state.ps_cookie );
786 id = bdb_idl_next( candidates, &cursor ) );
788 if ( cursor == NOID ) {
790 LDAP_LOG ( OPERATION, RESULTS,
791 "bdb_search: no paged results candidates\n",
794 Debug( LDAP_DEBUG_TRACE,
795 "bdb_search: no paged results candidates\n",
798 send_pagerequest_response( sop, rs, lastid, 0 );
807 #ifdef LDAP_CLIENT_UPDATE
808 if ( (sop->o_clientupdate_type & SLAP_LCUP_SYNC) ||
809 (IS_PSEARCH && sop->o_ps_protocol == LDAP_CLIENT_UPDATE ))
811 cookief.f_choice = LDAP_FILTER_AND;
812 cookief.f_and = &csnfnot;
813 cookief.f_next = NULL;
815 csnfnot.f_choice = LDAP_FILTER_NOT;
816 csnfnot.f_not = &csnfeq;
817 csnfnot.f_next = &csnfand;
819 csnfeq.f_choice = LDAP_FILTER_EQUALITY;
820 csnfeq.f_ava = &aa_eq;
821 csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
822 csnfeq.f_av_value = sop->o_clientupdate_state;
824 csnfand.f_choice = LDAP_FILTER_AND;
825 csnfand.f_and = &csnfge;
826 csnfand.f_next = NULL;
828 csnfge.f_choice = LDAP_FILTER_GE;
829 csnfge.f_ava = &aa_ge;
830 csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
831 csnfge.f_av_value = sop->o_clientupdate_state;
832 csnfge.f_next = sop->oq_search.rs_filter;
835 #if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
839 if ( (sop->o_sync_mode & SLAP_SYNC_REFRESH) ||
840 ( IS_PSEARCH && sop->o_ps_protocol == LDAP_SYNC ))
842 cookief.f_choice = LDAP_FILTER_AND;
843 cookief.f_and = &csnfnot;
844 cookief.f_next = NULL;
846 csnfnot.f_choice = LDAP_FILTER_NOT;
847 csnfnot.f_not = &csnfeq;
848 csnfnot.f_next = &csnfand;
850 csnfeq.f_choice = LDAP_FILTER_EQUALITY;
851 csnfeq.f_ava = &aa_eq;
852 csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
853 csnfeq.f_av_value = sop->o_sync_state;
855 csnfand.f_choice = LDAP_FILTER_AND;
856 csnfand.f_and = &csnfge;
857 csnfand.f_next = NULL;
859 csnfge.f_choice = LDAP_FILTER_GE;
860 csnfge.f_ava = &aa_ge;
861 csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
862 csnfge.f_av_value = sop->o_sync_state;
863 csnfge.f_next = sop->oq_search.rs_filter;
867 for ( id = bdb_idl_first( candidates, &cursor );
869 id = bdb_idl_next( candidates, &cursor ) )
874 /* check for abandon */
875 if ( sop->o_abandon ) {
880 #ifdef LDAP_EXOP_X_CANCEL
881 if ( sop->o_cancel ) {
882 assert( sop->o_cancel == SLAP_CANCEL_REQ );
883 rs->sr_err = LDAP_CANCELLED;
884 send_ldap_result( sop, rs );
885 sop->o_cancel = SLAP_CANCEL_ACK;
891 /* check time limit */
892 if ( sop->oq_search.rs_tlimit != -1 && slap_get_time() > stoptime ) {
893 rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
894 rs->sr_ref = rs->sr_v2ref;
895 send_ldap_result( sop, rs );
900 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
904 /* get the entry with reader lock */
906 rs->sr_err = bdb_cache_find_id( op->o_bd, NULL,
907 id, &ei, 0, locker, &lock, op->o_tmpmemctx );
909 if (rs->sr_err == LDAP_BUSY) {
910 rs->sr_text = "ldap server busy";
911 send_ldap_result( sop, rs );
914 } else if ( rs->sr_err == DB_LOCK_DEADLOCK
915 || rs->sr_err == DB_LOCK_NOTGRANTED )
920 if ( ei && rs->sr_err == 0 ) {
927 if( !BDB_IDL_IS_RANGE(candidates) ) {
928 /* only complain for non-range IDLs */
930 LDAP_LOG ( OPERATION, RESULTS,
931 "bdb_search: candidate %ld not found\n",
934 Debug( LDAP_DEBUG_TRACE,
935 "bdb_search: candidate %ld not found\n",
942 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
949 #ifdef BDB_SUBENTRIES
950 if ( !is_sync_protocol( sop ) ) {
951 if ( is_entry_subentry( e ) ) {
952 if( sop->oq_search.rs_scope != LDAP_SCOPE_BASE ) {
953 if(!get_subentries_visibility( sop )) {
954 /* only subentries are visible */
958 } else if ( get_subentries( sop ) &&
959 !get_subentries_visibility( sop ))
961 /* only subentries are visible */
965 } else if ( get_subentries_visibility( sop )) {
966 /* only subentries are visible */
972 /* Does this candidate actually satisfy the search scope?
974 * Note that we don't lock access to the bei_parent pointer.
975 * Since only leaf nodes can be deleted, the parent of any
976 * node will always be a valid node. Also since we have
977 * a Read lock on the data, it cannot be renamed out of the
978 * scope while we are looking at it, and unless we're using
979 * BDB_HIER, its parents cannot be moved either.
981 switch( op->ors_scope ) {
982 case LDAP_SCOPE_BASE:
983 /* This is always true, yes? */
984 if ( id == base.e_id )
987 case LDAP_SCOPE_ONELEVEL:
988 if ( ei->bei_parent->bei_id == base.e_id )
991 case LDAP_SCOPE_SUBTREE:
993 for ( tmp = BEI(e); tmp->bei_parent;
994 tmp = tmp->bei_parent ) {
995 if ( tmp->bei_id == base.e_id ) {
1004 /* aliases were already dereferenced in candidate list */
1005 if ( sop->ors_deref & LDAP_DEREF_SEARCHING ) {
1006 /* but if the search base is an alias, and we didn't
1007 * deref it when finding, return it.
1009 if ( is_entry_alias(e) &&
1010 ((sop->ors_deref & LDAP_DEREF_FINDING)
1011 || !bvmatch(&e->e_nname, &op->o_req_ndn)))
1016 /* scopes is only non-empty for onelevel or subtree */
1017 if ( !scopeok && BDB_IDL_N(scopes) ) {
1019 if ( sop->ors_scope == LDAP_SCOPE_ONELEVEL ) {
1020 x = bdb_idl_search( scopes,
1022 if ( scopes[x] == e->e_id )
1025 /* subtree, walk up the tree */
1026 EntryInfo *tmp = BEI(e);
1027 for (;tmp->bei_parent;
1028 tmp=tmp->bei_parent) {
1030 scopes, tmp->bei_id );
1031 if ( scopes[x] == tmp->bei_id ) {
1041 /* Not in scope, ignore it */
1044 LDAP_LOG ( OPERATION, RESULTS,
1045 "bdb_search: %ld scope not okay\n",
1048 Debug( LDAP_DEBUG_TRACE,
1049 "bdb_search: %ld scope not okay\n",
1056 * if it's a referral, add it to the list of referrals. only do
1057 * this for non-base searches, and don't check the filter
1058 * explicitly here since it's only a candidate anyway.
1060 if ( !manageDSAit && sop->oq_search.rs_scope != LDAP_SCOPE_BASE
1061 && is_entry_referral( e ) )
1063 BerVarray erefs = get_entry_referrals( sop, e );
1064 rs->sr_ref = referral_rewrite( erefs,
1066 sop->oq_search.rs_scope == LDAP_SCOPE_SUBTREE
1067 ? LDAP_SCOPE_SUBTREE
1068 : LDAP_SCOPE_BASE );
1070 send_search_reference( sop, rs );
1072 ber_bvarray_free( rs->sr_ref );
1073 ber_bvarray_free( erefs );
1079 /* if it matches the filter and scope, send it */
1080 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1082 if (ps_type != LDAP_PSEARCH_BY_SCOPEOUT) {
1083 rs->sr_err = test_filter( sop, rs->sr_entry, &cookief );
1085 rs->sr_err = LDAP_COMPARE_TRUE;
1088 #ifdef LDAP_CLIENT_UPDATE
1089 if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
1090 rs->sr_err = test_filter( sop, rs->sr_entry, &cookief );
1094 if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
1095 rc_sync = test_filter( sop, rs->sr_entry, &cookief );
1096 rs->sr_err = test_filter( sop,
1097 rs->sr_entry, sop->oq_search.rs_filter );
1098 if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
1099 if ( rc_sync == LDAP_COMPARE_TRUE ) {
1100 entry_sync_state = LDAP_SYNC_ADD;
1102 entry_sync_state = LDAP_SYNC_PRESENT;
1109 rs->sr_err = test_filter( sop,
1110 rs->sr_entry, sop->oq_search.rs_filter );
1112 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1116 if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
1117 /* check size limit */
1118 if ( --sop->oq_search.rs_slimit == -1 ) {
1119 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1122 bdb_cache_return_entry_r( bdb->bi_dbenv,
1123 &bdb->bi_cache, e, &lock );
1125 rs->sr_entry = NULL;
1126 rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
1127 rs->sr_ref = rs->sr_v2ref;
1128 send_ldap_result( sop, rs );
1132 #ifdef LDAP_CONTROL_PAGEDRESULTS
1133 if ( get_pagedresults(sop) ) {
1134 if ( rs->sr_nentries >= sop->o_pagedresults_size ) {
1135 send_pagerequest_response( sop, rs,
1147 #if 0 /* noop is masked SLAP_CTRL_UPDATE */
1152 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1155 int premodify_found = 0;
1156 int entry_sync_state;
1159 if ( ps_type == LDAP_PSEARCH_BY_ADD ||
1160 ps_type == LDAP_PSEARCH_BY_DELETE ||
1161 ps_type == LDAP_PSEARCH_BY_MODIFY ||
1162 ps_type == LDAP_PSEARCH_BY_SCOPEOUT )
1164 if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) {
1165 struct psid_entry* psid_e;
1166 LDAP_LIST_FOREACH( psid_e,
1167 &op->o_pm_list, ps_link)
1169 if( psid_e->ps_op == sop ) {
1171 premodify_found = 1;
1173 LDAP_LIST_REMOVE(psid_e, ps_link);
1177 if (psid_e != NULL) free (psid_e);
1180 if ( ps_type == LDAP_PSEARCH_BY_ADD ) {
1181 entry_sync_state = LDAP_SYNC_ADD;
1182 } else if ( ps_type == LDAP_PSEARCH_BY_DELETE ) {
1183 entry_sync_state = LDAP_SYNC_DELETE;
1184 } else if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) {
1185 if ( premodify_found ) {
1186 entry_sync_state = LDAP_SYNC_MODIFY;
1188 entry_sync_state = LDAP_SYNC_ADD;
1190 } else if ( ps_type == LDAP_PSEARCH_BY_SCOPEOUT )
1191 entry_sync_state = LDAP_SYNC_DELETE;
1198 #ifdef LDAP_CLIENT_UPDATE
1199 if ( sop->o_ps_protocol == LDAP_CLIENT_UPDATE ) {
1200 int entry_count = ++sop->o_ps_entries;
1201 if ( IS_BDB_REPLACE(ps_type) ) {
1202 rs->sr_err = bdb_build_lcup_update_ctrl( sop,
1203 rs, e, entry_count, ctrls,
1204 num_ctrls++, &latest_entrycsn_bv,
1205 SLAP_LCUP_ENTRY_DELETED_TRUE );
1207 rs->sr_err = bdb_build_lcup_update_ctrl( sop,
1208 rs, e, entry_count, ctrls,
1209 num_ctrls++, &latest_entrycsn_bv,
1210 SLAP_LCUP_ENTRY_DELETED_FALSE );
1212 if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1213 rs->sr_attrs = attrs;
1214 rs->sr_ctrls = ctrls;
1215 result = send_search_entry( sop, rs );
1216 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1217 ch_free( ctrls[--num_ctrls] );
1218 ctrls[num_ctrls] = NULL;
1219 rs->sr_ctrls = NULL;
1223 if ( sop->o_ps_protocol == LDAP_SYNC ) {
1224 rs->sr_err = bdb_build_sync_state_ctrl( sop,
1225 rs, e, entry_sync_state, ctrls,
1226 num_ctrls++, 1, &latest_entrycsn_bv );
1227 if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1228 rs->sr_attrs = attrs;
1229 rs->sr_ctrls = ctrls;
1230 result = send_search_entry( sop, rs );
1231 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1232 ch_free( ctrls[--num_ctrls] );
1233 ctrls[num_ctrls] = NULL;
1234 rs->sr_ctrls = NULL;
1242 } else if ( ps_type == LDAP_PSEARCH_BY_PREMODIFY ) {
1243 struct psid_entry* psid_e;
1244 psid_e = (struct psid_entry *) calloc (1,
1245 sizeof(struct psid_entry));
1246 psid_e->ps_op = sop;
1247 LDAP_LIST_INSERT_HEAD( &op->o_pm_list,
1251 printf("Error !\n");
1254 #ifdef LDAP_CLIENT_UPDATE
1255 if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
1256 rs->sr_err = bdb_build_lcup_update_ctrl( sop,
1257 rs, e, ++entry_count, ctrls,
1258 num_ctrls++, &latest_entrycsn_bv,
1259 SLAP_LCUP_ENTRY_DELETED_FALSE );
1260 if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1261 rs->sr_ctrls = ctrls;
1262 rs->sr_attrs = sop->oq_search.rs_attrs;
1263 result = send_search_entry( sop, rs );
1264 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1265 ch_free( ctrls[--num_ctrls] );
1266 ctrls[num_ctrls] = NULL;
1267 rs->sr_ctrls = NULL;
1271 if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
1272 rs->sr_err = bdb_build_sync_state_ctrl( sop,
1273 rs, e, entry_sync_state, ctrls,
1274 num_ctrls++, 0, &latest_entrycsn_bv );
1275 if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1277 rs->sr_ctrls = ctrls;
1278 if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */
1279 rs->sr_attrs = sop->oq_search.rs_attrs;
1280 } else { /* PRESENT */
1281 rs->sr_attrs = &null_attr;
1283 result = send_search_entry( sop, rs );
1284 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1285 ch_free( ctrls[--num_ctrls] );
1286 ctrls[num_ctrls] = NULL;
1287 rs->sr_ctrls = NULL;
1292 rs->sr_attrs = sop->oq_search.rs_attrs;
1293 rs->sr_ctrls = NULL;
1294 result = send_search_entry( sop, rs );
1299 case 0: /* entry sent ok */
1301 case 1: /* entry not sent */
1303 case -1: /* connection closed */
1305 bdb_cache_return_entry_r(bdb->bi_dbenv,
1306 &bdb->bi_cache, e, &lock);
1308 rs->sr_entry = NULL;
1309 rs->sr_err = LDAP_OTHER;
1315 LDAP_LOG ( OPERATION, RESULTS,
1316 "bdb_search: %ld does not match filter\n", (long) id, 0, 0);
1318 Debug( LDAP_DEBUG_TRACE,
1319 "bdb_search: %ld does not match filter\n",
1326 /* free reader lock */
1328 bdb_cache_return_entry_r( bdb->bi_dbenv,
1329 &bdb->bi_cache, e , &lock);
1332 rs->sr_entry = NULL;
1335 ldap_pvt_thread_yield();
1339 #ifdef LDAP_CLIENT_UPDATE
1340 if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
1341 bdb_build_lcup_done_ctrl( sop, rs, ctrls,
1342 num_ctrls++, &latest_entrycsn_bv );
1344 rs->sr_ctrls = ctrls;
1345 rs->sr_ref = rs->sr_v2ref;
1346 rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
1347 send_ldap_result( sop, rs );
1349 ch_free( latest_entrycsn_bv.bv_val );
1350 latest_entrycsn_bv.bv_val = NULL;
1352 if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) {
1353 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1355 ch_free( ctrls[--num_ctrls] );
1356 ctrls[num_ctrls] = NULL;
1360 if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
1361 if ( sop->o_sync_mode & SLAP_SYNC_PERSIST ) {
1362 /* refreshAndPersist mode */
1363 rs->sr_err = LDAP_SUCCESS;
1364 rs->sr_rspoid = LDAP_SYNC_INFO;
1365 rs->sr_ctrls = NULL;
1366 bdb_send_ldap_intermediate( sop, rs,
1367 LDAP_SYNC_REFRESH_DONE, &latest_entrycsn_bv );
1369 /* refreshOnly mode */
1370 bdb_build_sync_done_ctrl( sop, rs, ctrls,
1371 num_ctrls++, 1, &latest_entrycsn_bv );
1372 rs->sr_ctrls = ctrls;
1373 rs->sr_ref = rs->sr_v2ref;
1374 rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
1375 send_ldap_result( sop, rs );
1376 if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) {
1377 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1379 ch_free( ctrls[--num_ctrls] );
1380 ctrls[num_ctrls] = NULL;
1383 ch_free( latest_entrycsn_bv.bv_val );
1384 latest_entrycsn_bv.bv_val = NULL;
1388 rs->sr_ctrls = NULL;
1389 rs->sr_ref = rs->sr_v2ref;
1390 rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
1391 send_ldap_result( sop, rs );
1395 rs->sr_err = LDAP_SUCCESS;
1398 if( !IS_PSEARCH && e != NULL ) {
1399 /* free reader lock */
1400 bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
1403 LOCK_ID_FREE (bdb->bi_dbenv, locker );
1405 if( rs->sr_v2ref ) {
1406 ber_bvarray_free( rs->sr_v2ref );
1407 rs->sr_v2ref = NULL;
1409 if( realbase.bv_val ) ch_free( realbase.bv_val );
1415 static int base_candidate(
1421 LDAP_LOG ( OPERATION, ENTRY,
1422 "base_candidate: base: \"%s\" (0x%08lx)\n",
1423 e->e_nname.bv_val, (long) e->e_id, 0);
1425 Debug(LDAP_DEBUG_ARGS, "base_candidates: base: \"%s\" (0x%08lx)\n",
1426 e->e_nname.bv_val, (long) e->e_id, 0);
1434 /* Look for "objectClass Present" in this filter.
1435 * Also count depth of filter tree while we're at it.
1437 static int oc_filter(
1445 if( cur > *max ) *max = cur;
1447 switch(f->f_choice) {
1448 case LDAP_FILTER_PRESENT:
1449 if (f->f_desc == slap_schema.si_ad_objectClass) {
1454 case LDAP_FILTER_AND:
1455 case LDAP_FILTER_OR:
1457 for (f=f->f_and; f; f=f->f_next) {
1458 (void) oc_filter(f, cur, max);
1468 static void search_stack_free( void *key, void *data )
1470 ber_memfree_x(data, NULL);
1473 static void *search_stack(
1477 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
1480 if ( op->o_threadctx ) {
1481 ldap_pvt_thread_pool_getkey( op->o_threadctx, search_stack,
1484 ret = bdb->bi_search_stack;
1488 ret = ch_malloc( bdb->bi_search_stack_depth * BDB_IDL_UM_SIZE
1490 if ( op->o_threadctx ) {
1491 ldap_pvt_thread_pool_setkey( op->o_threadctx, search_stack,
1492 ret, search_stack_free );
1494 bdb->bi_search_stack = ret;
1500 static int search_candidates(
1509 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
1511 Filter f, scopef, rf, xf, nf;
1513 AttributeAssertion aa_ref;
1514 #ifdef BDB_SUBENTRIES
1516 AttributeAssertion aa_subentry;
1520 * This routine takes as input a filter (user-filter)
1521 * and rewrites it as follows:
1522 * (&(scope=DN)[(objectClass=subentry)]
1523 * (|[(objectClass=referral)(objectClass=alias)](user-filter))
1527 LDAP_LOG ( OPERATION, ENTRY,
1528 "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
1529 e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope);
1531 Debug(LDAP_DEBUG_TRACE,
1532 "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
1533 e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope );
1536 xf.f_or = op->oq_search.rs_filter;
1537 xf.f_choice = LDAP_FILTER_OR;
1540 /* If the user's filter uses objectClass=*,
1541 * these clauses are redundant.
1543 if (!oc_filter(op->oq_search.rs_filter, 1, &depth)
1544 && !get_subentries_visibility(op)
1545 && !is_sync_protocol(op) )
1547 if( !get_manageDSAit(op) && !get_domainScope(op) ) {
1548 /* match referral objects */
1549 struct berval bv_ref = { sizeof("referral")-1, "referral" };
1550 rf.f_choice = LDAP_FILTER_EQUALITY;
1552 rf.f_av_desc = slap_schema.si_ad_objectClass;
1553 rf.f_av_value = bv_ref;
1554 rf.f_next = xf.f_or;
1560 scopef.f_choice = op->oq_search.rs_scope == LDAP_SCOPE_SUBTREE
1561 ? SLAPD_FILTER_DN_SUBTREE
1562 : SLAPD_FILTER_DN_ONE;
1564 scopef.f_dn = (struct berval *)e->e_private;
1566 scopef.f_dn = &e->e_nname;
1568 scopef.f_next = NULL;
1571 f.f_choice = LDAP_FILTER_AND;
1573 /* Dummy; we compute scope separately now */
1574 nf.f_choice = SLAPD_FILTER_COMPUTED;
1575 nf.f_result = SLAPD_COMPARE_UNDEFINED;
1576 nf.f_next = xf.f_or == op->oq_search.rs_filter
1577 ? op->oq_search.rs_filter : &xf ;
1578 /* Filter depth increased again, adding dummy clause */
1581 #ifdef BDB_SUBENTRIES
1582 if( get_subentries_visibility( op ) ) {
1583 struct berval bv_subentry = { sizeof("SUBENTRY")-1, "SUBENTRY" };
1584 sf.f_choice = LDAP_FILTER_EQUALITY;
1585 sf.f_ava = &aa_subentry;
1586 sf.f_av_desc = slap_schema.si_ad_objectClass;
1587 sf.f_av_value = bv_subentry;
1588 sf.f_next = nf.f_next;
1593 /* Allocate IDL stack, plus 1 more for former tmp */
1594 if ( depth+1 > bdb->bi_search_stack_depth ) {
1595 stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
1597 stack = search_stack( stackop );
1600 if( op->ors_deref & LDAP_DEREF_SEARCHING ) {
1601 rc = search_aliases( op, rs, e, locker, &scopef, ids, scopes, stack );
1603 rc = bdb_filter_candidates( op, &scopef, ids,
1604 stack, stack+BDB_IDL_UM_SIZE );
1607 if ( rc == LDAP_SUCCESS ) {
1608 rc = bdb_filter_candidates( op, &f, ids,
1609 stack, stack+BDB_IDL_UM_SIZE );
1612 if ( depth+1 > bdb->bi_search_stack_depth ) {
1618 LDAP_LOG ( OPERATION, DETAIL1,
1619 "bdb_search_candidates: failed (rc=%d)\n", rc, 0, 0 );
1621 Debug(LDAP_DEBUG_TRACE,
1622 "bdb_search_candidates: failed (rc=%d)\n",
1628 LDAP_LOG ( OPERATION, DETAIL1,
1629 "bdb_search_candidates: id=%ld first=%ld last=%ld\n",
1630 (long) ids[0], (long) BDB_IDL_FIRST(ids),
1631 (long) BDB_IDL_LAST(ids));
1633 Debug(LDAP_DEBUG_TRACE,
1634 "bdb_search_candidates: id=%ld first=%ld last=%ld\n",
1636 (long) BDB_IDL_FIRST(ids),
1637 (long) BDB_IDL_LAST(ids) );
1644 #ifdef LDAP_CONTROL_PAGEDRESULTS
1646 send_pagerequest_response(
1652 LDAPControl ctrl, *ctrls[2];
1653 char berbuf[LBER_ELEMENT_SIZEOF];
1654 BerElement *ber = (BerElement *)berbuf;
1655 struct berval cookie = { 0, NULL };
1656 PagedResultsCookie respcookie;
1659 LDAP_LOG ( OPERATION, ENTRY,
1660 "send_pagerequest_response: lastid: (0x%08lx) "
1661 "nentries: (0x%081x)\n",
1662 lastid, rs->sr_nentries, NULL );
1664 Debug(LDAP_DEBUG_ARGS, "send_pagerequest_response: lastid: (0x%08lx) "
1665 "nentries: (0x%081x)\n", lastid, rs->sr_nentries, NULL );
1668 ctrl.ldctl_value.bv_val = NULL;
1672 ber_init2( ber, NULL, LBER_USE_DER );
1674 respcookie = ( PagedResultsCookie )lastid;
1675 op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
1676 cookie.bv_len = sizeof( respcookie );
1677 cookie.bv_val = (char *)&respcookie;
1680 * FIXME: we should consider sending an estimate of the entries
1681 * left, after appropriate security check is done
1683 ber_printf( ber, "{iO}", tentries, &cookie );
1685 if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
1689 ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
1690 ctrls[0]->ldctl_iscritical = 0;
1692 rs->sr_ctrls = ctrls;
1693 rs->sr_err = LDAP_SUCCESS;
1694 send_ldap_result( op, rs );
1697 (void) ber_free_buf( ber );
1701 #ifdef LDAP_CLIENT_UPDATE
1703 bdb_build_lcup_update_ctrl(
1708 LDAPControl **ctrls,
1710 struct berval *latest_entrycsn_bv,
1716 const char *text = NULL;
1718 char berbuf[LBER_ELEMENT_SIZEOF];
1719 BerElement *ber = (BerElement *)berbuf;
1721 struct berval entrycsn_bv = { 0, NULL };
1723 ber_init2( ber, 0, LBER_USE_DER );
1725 ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1727 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
1728 AttributeDescription *desc = a->a_desc;
1729 if ( desc == slap_schema.si_ad_entryCSN ) {
1730 ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
1731 if ( latest_entrycsn_bv->bv_val == NULL ) {
1732 ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1734 res = value_match( &ret, desc,
1735 desc->ad_type->sat_ordering, 0,
1736 &entrycsn_bv, latest_entrycsn_bv, &text );
1737 if ( res != LDAP_SUCCESS ) {
1740 LDAP_LOG ( OPERATION, RESULTS,
1741 "bdb_search: value_match failed\n",
1744 Debug( LDAP_DEBUG_TRACE,
1745 "bdb_search: value_match failed\n",
1751 ch_free( latest_entrycsn_bv->bv_val );
1752 latest_entrycsn_bv->bv_val = NULL;
1753 ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1759 if ( entry_count % op->o_clientupdate_interval == 0 ) {
1762 SLAP_LCUP_STATE_UPDATE_FALSE,
1764 LDAP_CUP_COOKIE_OID, &entrycsn_bv );
1765 } else { /* Do not send cookie */
1768 SLAP_LCUP_STATE_UPDATE_FALSE,
1772 ch_free( entrycsn_bv.bv_val );
1773 entrycsn_bv.bv_val = NULL;
1775 ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
1776 ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
1777 ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1779 ber_free_buf( ber );
1783 LDAP_LOG ( OPERATION, RESULTS,
1784 "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
1787 Debug( LDAP_DEBUG_TRACE,
1788 "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
1791 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1795 return LDAP_SUCCESS;
1799 bdb_build_lcup_done_ctrl(
1802 LDAPControl **ctrls,
1804 struct berval *latest_entrycsn_bv )
1807 char berbuf[LBER_ELEMENT_SIZEOF];
1808 BerElement *ber = (BerElement *)berbuf;
1810 ber_init2( ber, NULL, LBER_USE_DER );
1812 ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1814 ber_printf( ber, "{sON}", LDAP_CUP_COOKIE_OID, latest_entrycsn_bv );
1816 ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
1817 ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
1818 ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1820 ber_free_buf( ber );
1824 LDAP_LOG ( OPERATION, RESULTS,
1825 "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
1827 Debug( LDAP_DEBUG_TRACE,
1828 "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
1831 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1835 return LDAP_SUCCESS;
1841 bdb_build_sync_state_ctrl(
1845 int entry_sync_state,
1846 LDAPControl **ctrls,
1849 struct berval *latest_entrycsn_bv )
1854 const char *text = NULL;
1856 char berbuf[LBER_ELEMENT_SIZEOF];
1857 BerElement *ber = (BerElement *)berbuf;
1859 struct berval entryuuid_bv = { 0, NULL };
1860 struct berval entrycsn_bv = { 0, NULL };
1862 ber_init2( ber, 0, LBER_USE_DER );
1864 ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1866 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
1867 AttributeDescription *desc = a->a_desc;
1868 if ( desc == slap_schema.si_ad_entryCSN ) {
1869 ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
1870 if ( latest_entrycsn_bv->bv_val == NULL ) {
1871 ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1873 res = value_match( &ret, desc,
1874 desc->ad_type->sat_ordering, 0,
1875 &entrycsn_bv, latest_entrycsn_bv, &text );
1876 if ( res != LDAP_SUCCESS ) {
1879 LDAP_LOG ( OPERATION, RESULTS,
1880 "bdb_search: value_match failed\n",
1883 Debug( LDAP_DEBUG_TRACE,
1884 "bdb_search: value_match failed\n",
1889 ch_free( latest_entrycsn_bv->bv_val );
1890 latest_entrycsn_bv->bv_val = NULL;
1891 ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1894 } else if ( desc == slap_schema.si_ad_entryUUID ) {
1895 ber_dupbv( &entryuuid_bv, &a->a_vals[0] );
1899 if ( send_cookie ) {
1900 ber_printf( ber, "{eOON}",
1901 entry_sync_state, &entryuuid_bv, &entrycsn_bv );
1903 ber_printf( ber, "{eON}",
1904 entry_sync_state, &entryuuid_bv );
1907 ch_free( entrycsn_bv.bv_val );
1908 entrycsn_bv.bv_val = NULL;
1909 ch_free( entryuuid_bv.bv_val );
1910 entryuuid_bv.bv_val = NULL;
1912 ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
1913 ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
1914 ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1916 ber_free_buf( ber );
1920 LDAP_LOG ( OPERATION, RESULTS,
1921 "bdb_build_sync_ctrl: ber_flatten2 failed\n",
1924 Debug( LDAP_DEBUG_TRACE,
1925 "bdb_build_sync_ctrl: ber_flatten2 failed\n",
1928 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1932 return LDAP_SUCCESS;
1936 bdb_build_sync_done_ctrl(
1939 LDAPControl **ctrls,
1942 struct berval *latest_entrycsn_bv )
1945 char berbuf[LBER_ELEMENT_SIZEOF];
1946 BerElement *ber = (BerElement *)berbuf;
1948 ber_init2( ber, NULL, LBER_USE_DER );
1950 ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1952 if ( send_cookie ) {
1953 ber_printf( ber, "{ON}", latest_entrycsn_bv );
1955 ber_printf( ber, "{N}" );
1958 ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
1959 ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
1960 ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1962 ber_free_buf( ber );
1966 LDAP_LOG ( OPERATION, RESULTS,
1967 "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
1970 Debug( LDAP_DEBUG_TRACE,
1971 "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
1974 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1978 return LDAP_SUCCESS;
1982 bdb_send_ldap_intermediate(
1986 struct berval *cookie )
1988 char berbuf[LBER_ELEMENT_SIZEOF];
1989 BerElement *ber = (BerElement *)berbuf;
1990 struct berval rspdata;
1994 ber_init2( ber, NULL, LBER_USE_DER );
1996 if ( cookie == NULL ) {
1997 ber_printf( ber, "{eN}", state );
1999 ber_printf( ber, "{eON}", state, cookie );
2002 ret = ber_flatten2( ber, &rspdata, 0 );
2006 LDAP_LOG ( OPERATION, RESULTS,
2007 "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
2010 Debug( LDAP_DEBUG_TRACE,
2011 "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
2014 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
2018 rs->sr_rspdata = &rspdata;
2019 send_ldap_intermediate_resp( op, rs );
2020 rs->sr_rspdata = NULL;
2021 ber_free_buf( ber );
2023 return LDAP_SUCCESS;