]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/search.c
57cc3614b8f4976eaf1bc5b4238bd44c3c94ef63
[openldap] / servers / slapd / back-bdb / search.c
1 /* search.c - search operation */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12
13 #include "back-bdb.h"
14 #include "idl.h"
15 #include "external.h"
16
17 static int base_candidate(
18         BackendDB       *be,
19         Entry   *e,
20         ID              *ids );
21 static int search_candidates(
22         Operation *stackop,     /* op with the current threadctx/slab cache */
23         Operation *sop,         /* search op */
24         SlapReply *rs,
25         Entry *e,
26         u_int32_t locker,
27         ID      *ids,
28         ID      *scopes );
29 static void send_pagerequest_response( 
30         Operation *op,
31         SlapReply *rs,
32         ID  lastid,
33         int tentries );
34
35 /* Dereference aliases for a single alias entry. Return the final
36  * dereferenced entry on success, NULL on any failure.
37  */
38 static Entry * deref_base (
39         Operation *op,
40         SlapReply *rs,
41         Entry *e,
42         Entry **matched,
43         u_int32_t locker,
44         DB_LOCK *lock,
45         ID      *tmp,
46         ID      *visited )
47 {
48         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
49         struct berval ndn;
50         EntryInfo *ei;
51         DB_LOCK lockr;
52
53         rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;
54         rs->sr_text = "maximum deref depth exceeded";
55
56         while (BDB_IDL_N(tmp) < op->o_bd->be_max_deref_depth) {
57
58                 /* Remember the last entry we looked at, so we can
59                  * report broken links
60                  */
61                 *matched = e;
62
63                 /* If this is part of a subtree or onelevel search,
64                  * have we seen this ID before? If so, quit.
65                  */
66                 if ( visited && bdb_idl_insert( visited, e->e_id ) ) {
67                         e = NULL;
68                         break;
69                 }
70
71                 /* If we've seen this ID during this deref iteration,
72                  * we've hit a loop.
73                  */
74                 if ( bdb_idl_insert( tmp, e->e_id ) ) {
75                         rs->sr_err = LDAP_ALIAS_PROBLEM;
76                         rs->sr_text = "circular alias";
77                         e = NULL;
78                         break;
79                 }
80
81                 /* If there was a problem getting the aliasedObjectName,
82                  * get_alias_dn will have set the error status.
83                  */
84                 if ( get_alias_dn(e, &ndn, &rs->sr_err, &rs->sr_text) ) {
85                         e = NULL;
86                         break;
87                 }
88
89                 rs->sr_err = bdb_dn2entry( op, NULL, &ndn, &ei,
90                         0, locker, &lockr );
91
92                 if ( ei ) e = ei->bei_e;
93                 else    e = NULL;
94
95                 if (!e) {
96                         rs->sr_err = LDAP_ALIAS_PROBLEM;
97                         rs->sr_text = "aliasedObject not found";
98                         break;
99                 }
100
101                 /* Free the previous entry, continue to work with the
102                  * one we just retrieved.
103                  */
104                 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,
105                         *matched, lock);
106                 *lock = lockr;
107
108                 /* We found a regular entry. Return this to the caller. The
109                  * entry is still locked for Read.
110                  */
111                 if (!is_entry_alias(e)) {
112                         rs->sr_err = LDAP_SUCCESS;
113                         rs->sr_text = NULL;
114                         break;
115                 }
116         }
117         return e;
118 }
119
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. Of course we're hardcoded to
123  * require a minimum of 8 UM_SIZE IDLs so this is never a problem.
124  */
125 static int search_aliases(
126         Operation *op,
127         SlapReply *rs,
128         Entry *e,
129         u_int32_t locker,
130         ID *ids,
131         ID *scopes,
132         ID *stack
133 )
134 {
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;
138         Entry *matched, *a;
139         EntryInfo *ei;
140         struct berval bv_alias = { sizeof("alias")-1, "alias" };
141         AttributeAssertion aa_alias;
142         Filter  af;
143         DB_LOCK locka, lockr;
144         int first = 1;
145
146         aliases = stack;        /* IDL of all aliases in the database */
147         curscop = aliases + BDB_IDL_DB_SIZE;    /* Aliases in the current scope */
148         subscop = curscop + BDB_IDL_DB_SIZE;    /* The current scope */
149         visited = subscop + BDB_IDL_DB_SIZE;    /* IDs we've seen in this search */
150         newsubs = visited + BDB_IDL_DB_SIZE;    /* New subtrees we've added */
151         oldsubs = newsubs + BDB_IDL_DB_SIZE;    /* Subtrees added previously */
152         tmp = oldsubs + BDB_IDL_DB_SIZE;        /* Scratch space for deref_base() */
153
154         /* A copy of subscop, because subscop gets clobbered by
155          * the bdb_idl_union/intersection routines
156          */
157         subscop2 = tmp + BDB_IDL_DB_SIZE;
158
159         af.f_choice = LDAP_FILTER_EQUALITY;
160         af.f_ava = &aa_alias;
161         af.f_av_desc = slap_schema.si_ad_objectClass;
162         af.f_av_value = bv_alias;
163         af.f_next = NULL;
164
165         /* Find all aliases in database */
166         BDB_IDL_ZERO( aliases );
167         rs->sr_err = bdb_filter_candidates( op, &af, aliases,
168                 curscop, visited );
169         if (rs->sr_err != LDAP_SUCCESS) {
170                 return rs->sr_err;
171         }
172         oldsubs[0] = 1;
173         oldsubs[1] = e->e_id;
174
175         BDB_IDL_ZERO( ids );
176         BDB_IDL_ZERO( visited );
177         BDB_IDL_ZERO( newsubs );
178
179         cursoro = 0;
180         ido = bdb_idl_first( oldsubs, &cursoro );
181
182         for (;;) {
183                 /* Set curscop to only the aliases in the current scope. Start with
184                  * all the aliases, obtain the IDL for the current scope, and then
185                  * get the intersection of these two IDLs. Add the current scope
186                  * to the cumulative list of candidates.
187                  */
188                 BDB_IDL_CPY( curscop, aliases );
189                 rs->sr_err = bdb_dn2idl( op, e, subscop,
190                                         subscop2+BDB_IDL_DB_SIZE );
191                 if (first) {
192                         first = 0;
193                 } else {
194                         bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &locka);
195                 }
196                 BDB_IDL_CPY(subscop2, subscop);
197                 rs->sr_err = bdb_idl_intersection(curscop, subscop);
198                 bdb_idl_union( ids, subscop2 );
199
200                 /* Dereference all of the aliases in the current scope. */
201                 cursora = 0;
202                 for (ida = bdb_idl_first(curscop, &cursora); ida != NOID;
203                         ida = bdb_idl_next(curscop, &cursora))
204                 {
205                         ei = NULL;
206                         rs->sr_err = bdb_cache_find_id(op, NULL,
207                                 ida, &ei, 0, locker, &lockr );
208                         if (rs->sr_err != LDAP_SUCCESS) {
209                                 continue;
210                         }
211                         a = ei->bei_e;
212
213                         /* This should only happen if the curscop IDL has maxed out and
214                          * turned into a range that spans IDs indiscriminately
215                          */
216                         if (!is_entry_alias(a)) {
217                                 bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache,
218                                         a, &lockr);
219                                 continue;
220                         }
221
222                         /* Actually dereference the alias */
223                         BDB_IDL_ZERO(tmp);
224                         a = deref_base( op, rs, a, &matched, locker, &lockr,
225                                 tmp, visited );
226                         if (a) {
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
230                                  * can check it.
231                                  */
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);
235                                 }
236                                 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,
237                                         a, &lockr);
238
239                         } else if (matched) {
240                                 /* Alias could not be dereferenced, or it deref'd to
241                                  * an ID we've already seen. Ignore it.
242                                  */
243                                 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,
244                                         matched, &lockr );
245                                 rs->sr_text = NULL;
246                         }
247                 }
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.
250                  */
251                 if (op->ors_scope != LDAP_SCOPE_SUBTREE) break;
252 nextido:
253                 ido = bdb_idl_next( oldsubs, &cursoro );
254                 
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.
257                  */
258                 if (ido == NOID) {
259                         if (BDB_IDL_IS_ZERO(newsubs)) break;
260                         BDB_IDL_CPY(oldsubs, newsubs);
261                         BDB_IDL_ZERO(newsubs);
262                         cursoro = 0;
263                         ido = bdb_idl_first( oldsubs, &cursoro );
264                 }
265
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.
270                  */
271                 ei = NULL;
272                 rs->sr_err = bdb_cache_find_id(op, NULL, ido, &ei,
273                         0, locker, &locka );
274                 if (rs->sr_err != LDAP_SUCCESS) goto nextido;
275                 e = ei->bei_e;
276         }
277         return rs->sr_err;
278 }
279
280 static
281 int is_sync_protocol( Operation *op )
282 {
283 #if !defined(LDAP_CLIENT_UPDATE) && !defined(LDAP_SYNC)
284         return 0;
285 #endif
286
287 #ifdef LDAP_CLIENT_UPDATE
288         if ( op->o_clientupdate_type & SLAP_LCUP_SYNC_AND_PERSIST )
289                 return 1;
290 #endif
291 #ifdef LDAP_SYNC
292         if ( op->o_sync_mode & SLAP_SYNC_REFRESH_AND_PERSIST )
293                 return 1;
294 #endif
295         return 0;
296 }
297         
298 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
299 #define IS_BDB_REPLACE(type) (( type == LDAP_PSEARCH_BY_DELETE ) || \
300         ( type == LDAP_PSEARCH_BY_SCOPEOUT ))
301 #define IS_PSEARCH (op != sop)
302
303 int
304 bdb_abandon( Operation *op, SlapReply *rs )
305 {
306         Operation       *ps_list;
307         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
308
309         LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
310                 if ( ps_list->o_connid == op->o_connid ) {
311                         if ( ps_list->o_msgid == op->oq_abandon.rs_msgid ) {
312                                 ps_list->o_abandon = 1;
313                                 LDAP_LIST_REMOVE( ps_list, o_ps_link );
314                                 slap_op_free ( ps_list );
315                                 return LDAP_SUCCESS;
316                         }
317                 }
318         }
319         return LDAP_UNAVAILABLE;
320 }
321
322 int
323 bdb_cancel( Operation *op, SlapReply *rs )
324 {
325         Operation       *ps_list;
326         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
327
328         LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
329                 if ( ps_list->o_connid == op->o_connid ) {
330                         if ( ps_list->o_msgid == op->oq_cancel.rs_msgid ) {
331                                 ps_list->o_cancel = SLAP_CANCEL_DONE;
332                                 LDAP_LIST_REMOVE( ps_list, o_ps_link );
333
334 #if 0
335                                 bdb_build_sync_done_ctrl( conn, ps_list, ps_list->ctrls,
336                                         1, &latest_entrycsn_bv );
337                                 send_ldap_result( conn, ps_list, LDAP_CANCELLED,
338                                         NULL, NULL, NULL, ps_list->ctrls, ps_list->nentries);
339 #endif
340                                 rs->sr_err = LDAP_CANCELLED;
341                                 send_ldap_result( ps_list, rs );
342
343                                 if ( ps_list->o_tmpmemctx ) {
344                                         sl_mem_destroy( NULL, ps_list->o_tmpmemctx );
345                                 }
346
347                                 slap_op_free ( ps_list );
348                                 return LDAP_SUCCESS;
349                         }
350                 }
351         }
352         return LDAP_UNAVAILABLE;
353 }
354
355 int bdb_search( Operation *op, SlapReply *rs )
356 {
357         return bdb_do_search( op, rs, op, NULL, 0 );
358 }
359
360 /* For persistent searches, op is the currently executing operation,
361  * sop is the persistent search. For regular searches, sop = op.
362  */
363 int
364 bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
365         Entry *ps_e, int ps_type )
366 #else
367 #define IS_PSEARCH      0
368 #define sop     op
369 int bdb_search( Operation *op, SlapReply *rs )
370 #endif
371 {
372         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
373         time_t          stoptime;
374         ID              id, cursor;
375         ID              candidates[BDB_IDL_UM_SIZE];
376         ID              scopes[BDB_IDL_DB_SIZE];
377         Entry           *e = NULL, base;
378         Entry   *matched = NULL;
379         EntryInfo       *ei;
380         struct berval   realbase = { 0, NULL };
381         int             manageDSAit;
382         int             tentries = 0;
383         ID              lastid = NOID;
384         AttributeName   *attrs;
385
386 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
387         Filter          cookief, csnfnot, csnfeq, csnfand, csnfge;
388         AttributeAssertion aa_ge, aa_eq;
389         int             entry_count = 0;
390 #if 0
391         struct berval   entrycsn_bv = { 0, NULL };
392 #endif
393         struct berval   latest_entrycsn_bv = { 0, NULL };
394         LDAPControl     *ctrls[SLAP_SEARCH_MAX_CTRLS];
395         int             num_ctrls = 0;
396         AttributeName   uuid_attr[2];
397 #ifdef LDAP_SYNC
398         int             rc_sync = 0;
399         int             entry_sync_state = -1;
400         AttributeName   null_attr;
401 #endif
402 #endif
403         struct slap_limits_set *limit = NULL;
404         int isroot = 0;
405
406         u_int32_t       locker = 0;
407         DB_LOCK         lock;
408
409 #ifdef NEW_LOGGING
410         LDAP_LOG( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
411 #else
412         Debug( LDAP_DEBUG_TRACE, "=> bdb_back_search\n",
413                 0, 0, 0);
414 #endif
415         attrs = sop->oq_search.rs_attrs;
416
417 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
418 #ifdef LDAP_CLIENT_UPDATE
419         if ( !IS_PSEARCH && sop->o_clientupdate_type & SLAP_LCUP_PERSIST ) {
420                 sop->o_ps_protocol = LDAP_CLIENT_UPDATE;
421                 LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link );
422                 return LDAP_SUCCESS;
423         }
424 #endif
425 #ifdef LDAP_SYNC
426         /* psearch needs to be registered before refresh begins */
427         /* psearch and refresh transmission is serialized in send_ldap_ber() */
428         if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_PERSIST ) {
429                 sop->o_ps_protocol = LDAP_SYNC;
430                 LDAP_LIST_INSERT_HEAD( &bdb->bi_psearch_list, sop, o_ps_link );
431         }
432         null_attr.an_desc = NULL;
433         null_attr.an_oc = NULL;
434         null_attr.an_name.bv_len = 0;
435         null_attr.an_name.bv_val = NULL;
436 #endif
437
438         for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ ) {
439                 ctrls[num_ctrls] = NULL;
440         }
441         num_ctrls = 0;
442
443         if ( IS_PSEARCH && IS_BDB_REPLACE(ps_type)) {
444 #ifdef LDAP_CLIENT_UPDATE
445                 if ( sop->o_ps_protocol == LDAP_CLIENT_UPDATE ) {
446                         attrs = uuid_attr;
447                         attrs[0].an_desc = slap_schema.si_ad_entryUUID;
448                         attrs[0].an_oc = NULL;
449                         attrs[0].an_name =  attrs[0].an_desc->ad_cname;
450                         attrs[1].an_desc = NULL;
451                         attrs[1].an_oc = NULL;
452                         attrs[1].an_name.bv_len = 0;
453                         attrs[1].an_name.bv_val = NULL;
454                 } else
455 #endif
456 #ifdef LDAP_SYNC
457                 if (sop->o_ps_protocol == LDAP_SYNC ) {
458                         attrs = uuid_attr;
459                         attrs[0].an_desc = NULL;
460                         attrs[0].an_oc = NULL;
461                         attrs[0].an_name.bv_len = 0;
462                         attrs[0].an_name.bv_val = NULL;
463                 } else
464 #endif
465                 {
466                         rs->sr_err = 1;
467                         goto done;
468                 }
469         }
470 #endif
471
472         manageDSAit = get_manageDSAit( sop );
473
474         /* Sync / LCUP controls override manageDSAit */
475
476 #ifdef LDAP_CLIENT_UPDATE
477         if ( !IS_PSEARCH && sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
478                 if ( manageDSAit == SLAP_NO_CONTROL )
479                         manageDSAit = SLAP_CRITICAL_CONTROL;
480         } else
481 #endif
482 #ifdef LDAP_SYNC
483         if ( !IS_PSEARCH && sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
484                 if ( manageDSAit == SLAP_NO_CONTROL )
485                         manageDSAit = SLAP_CRITICAL_CONTROL;
486         } else
487 #endif
488         if ( IS_PSEARCH ) {
489                 if ( manageDSAit == SLAP_NO_CONTROL )
490                         manageDSAit = SLAP_CRITICAL_CONTROL;
491         }
492
493         rs->sr_err = LOCK_ID (bdb->bi_dbenv, &locker );
494
495         switch(rs->sr_err) {
496         case 0:
497                 break;
498         default:
499                 send_ldap_error( sop, rs, LDAP_OTHER, "internal error" );
500                 return rs->sr_err;
501         }
502
503         if ( sop->o_req_ndn.bv_len == 0 ) {
504                 /* DIT root special case */
505                 e = (Entry *) &slap_entry_root;
506                 rs->sr_err = 0;
507         } else {
508 dn2entry_retry:
509                 /* get entry with reader lock */
510                 rs->sr_err = bdb_dn2entry( op, NULL, &sop->o_req_ndn, &ei,
511                         1, locker, &lock );
512         }
513
514         switch(rs->sr_err) {
515         case DB_NOTFOUND:
516                 matched = ei->bei_e; break;
517         case 0:
518                 e = ei->bei_e; break;
519         case LDAP_BUSY:
520                 send_ldap_error( sop, rs, LDAP_BUSY, "ldap server busy" );
521                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
522                 return LDAP_BUSY;
523         case DB_LOCK_DEADLOCK:
524         case DB_LOCK_NOTGRANTED:
525                 goto dn2entry_retry;
526         default:
527                 send_ldap_error( sop, rs, LDAP_OTHER, "internal error" );
528                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
529                 return rs->sr_err;
530         }
531
532         if ( e && (op->ors_deref & LDAP_DEREF_FINDING) && is_entry_alias(e) ) {
533                 BDB_IDL_ZERO(candidates);
534                 e = deref_base( op, rs, e, &matched, locker, &lock,
535                         candidates, NULL );
536         }
537
538         if ( e == NULL ) {
539                 struct berval matched_dn = { 0, NULL };
540
541                 if ( matched != NULL ) {
542                         BerVarray erefs;
543                         ber_dupbv( &matched_dn, &matched->e_name );
544
545                         erefs = is_entry_referral( matched )
546                                 ? get_entry_referrals( op, matched )
547                                 : NULL;
548
549                         bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache,
550                                 matched, &lock);
551                         matched = NULL;
552
553                         if( erefs ) {
554                                 rs->sr_ref = referral_rewrite( erefs, &matched_dn,
555                                         &sop->o_req_dn, sop->oq_search.rs_scope );
556                                 ber_bvarray_free( erefs );
557                         }
558
559                 } else {
560                         rs->sr_ref = referral_rewrite( default_referral,
561                                 NULL, &sop->o_req_dn, sop->oq_search.rs_scope );
562                 }
563
564                 rs->sr_err=LDAP_REFERRAL;
565                 rs->sr_matched = matched_dn.bv_val;
566                 send_ldap_result( sop, rs );
567
568                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
569                 if ( rs->sr_ref ) {
570                         ber_bvarray_free( rs->sr_ref );
571                         rs->sr_ref = NULL;
572                 }
573                 if ( matched_dn.bv_val ) {
574                         ber_memfree( matched_dn.bv_val );
575                         rs->sr_matched = NULL;
576                 }
577                 return rs->sr_err;
578         }
579
580         if (!manageDSAit && e != &slap_entry_root && is_entry_referral( e ) ) {
581                 /* entry is a referral, don't allow add */
582                 struct berval matched_dn;
583                 BerVarray erefs;
584                 
585                 ber_dupbv( &matched_dn, &e->e_name );
586                 erefs = get_entry_referrals( op, e );
587
588                 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
589                 e = NULL;
590
591                 if( erefs ) {
592                         rs->sr_ref = referral_rewrite( erefs, &matched_dn,
593                                 &sop->o_req_dn, sop->oq_search.rs_scope );
594                         ber_bvarray_free( erefs );
595                 }
596
597 #ifdef NEW_LOGGING
598                 LDAP_LOG ( OPERATION, RESULTS, 
599                         "bdb_search: entry is referral\n", 0, 0, 0 );
600 #else
601                 Debug( LDAP_DEBUG_TRACE, "bdb_search: entry is referral\n",
602                         0, 0, 0 );
603 #endif
604
605                 if (!rs->sr_ref) rs->sr_text = "bad_referral object";
606                 rs->sr_err = LDAP_REFERRAL;
607                 rs->sr_matched = matched_dn.bv_val;
608                 send_ldap_result( sop, rs );
609
610                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
611                 ber_bvarray_free( rs->sr_ref );
612                 rs->sr_ref = NULL;
613                 ber_memfree( matched_dn.bv_val );
614                 rs->sr_matched = NULL;
615                 return 1;
616         }
617
618         if ( get_assert( op ) &&
619                 ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
620         {
621                 rs->sr_err = LDAP_ASSERTION_FAILED;
622                 send_ldap_result( sop, rs );
623                 return 1;
624         }
625
626         /* if not root, get appropriate limits */
627         if ( be_isroot( op->o_bd, &sop->o_ndn ) ) {
628                 isroot = 1;
629         } else {
630                 ( void ) get_limits( op->o_bd, &sop->o_ndn, &limit );
631         }
632
633         /* The time/size limits come first because they require very little
634          * effort, so there's no chance the candidates are selected and then 
635          * the request is not honored only because of time/size constraints */
636
637         /* if no time limit requested, use soft limit (unless root!) */
638         if ( isroot ) {
639                 if ( sop->oq_search.rs_tlimit == 0 ) {
640                         sop->oq_search.rs_tlimit = -1;  /* allow root to set no limit */
641                 }
642
643                 if ( sop->oq_search.rs_slimit == 0 ) {
644                         sop->oq_search.rs_slimit = -1;
645                 }
646
647         } else {
648                 /* if no limit is required, use soft limit */
649                 if ( sop->oq_search.rs_tlimit <= 0 ) {
650                         sop->oq_search.rs_tlimit = limit->lms_t_soft;
651
652                 /* if requested limit higher than hard limit, abort */
653                 } else if ( sop->oq_search.rs_tlimit > limit->lms_t_hard ) {
654                         /* no hard limit means use soft instead */
655                         if ( limit->lms_t_hard == 0
656                                         && limit->lms_t_soft > -1
657                                         && sop->oq_search.rs_tlimit > limit->lms_t_soft ) {
658                                 sop->oq_search.rs_tlimit = limit->lms_t_soft;
659
660                         /* positive hard limit means abort */
661                         } else if ( limit->lms_t_hard > 0 ) {
662                                 rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
663                                 send_ldap_result( sop, rs );
664                                 rs->sr_err = 0;
665                                 goto done;
666                         }
667                 
668                         /* negative hard limit means no limit */
669                 }
670                 
671                 /* if no limit is required, use soft limit */
672                 if ( sop->oq_search.rs_slimit <= 0 ) {
673                         if ( get_pagedresults(sop) && limit->lms_s_pr != 0 ) {
674                                 sop->oq_search.rs_slimit = limit->lms_s_pr;
675                         } else {
676                                 sop->oq_search.rs_slimit = limit->lms_s_soft;
677                         }
678
679                 /* if requested limit higher than hard limit, abort */
680                 } else if ( sop->oq_search.rs_slimit > limit->lms_s_hard ) {
681                         /* no hard limit means use soft instead */
682                         if ( limit->lms_s_hard == 0
683                                         && limit->lms_s_soft > -1
684                                         && sop->oq_search.rs_slimit > limit->lms_s_soft ) {
685                                 sop->oq_search.rs_slimit = limit->lms_s_soft;
686
687                         /* positive hard limit means abort */
688                         } else if ( limit->lms_s_hard > 0 ) {
689                                 rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
690                                 send_ldap_result( sop, rs );
691                                 rs->sr_err = 0; 
692                                 goto done;
693                         }
694                         
695                         /* negative hard limit means no limit */
696                 }
697         }
698
699         /* compute it anyway; root does not use it */
700         stoptime = op->o_time + sop->oq_search.rs_tlimit;
701
702         /* need normalized dn below */
703         ber_dupbv( &realbase, &e->e_nname );
704
705         /* Copy info to base, must free entry before accessing the database
706          * in search_candidates, to avoid deadlocks.
707          */
708         base.e_private = e->e_private;
709         base.e_nname = realbase;
710         base.e_id = e->e_id;
711
712         if ( e != &slap_entry_root ) {
713                 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
714         }
715         e = NULL;
716
717         /* select candidates */
718         if ( sop->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
719                 rs->sr_err = base_candidate( op->o_bd, &base, candidates );
720
721         } else {
722                 BDB_IDL_ZERO( candidates );
723                 BDB_IDL_ZERO( scopes );
724                 rs->sr_err = search_candidates( op, sop, rs, &base, locker, candidates, scopes );
725         }
726
727         /* start cursor at beginning of candidates.
728          */
729         cursor = 0;
730 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
731         if (IS_PSEARCH) {
732                 if ( !BDB_IDL_IS_RANGE( candidates ) ) {
733                         cursor = bdb_idl_search( candidates, ps_e->e_id );
734                         if ( candidates[cursor] != ps_e->e_id ) {
735                                 rs->sr_err = LDAP_SUCCESS;
736                                 goto done;
737                         }
738                 } else {
739                         if ( ps_e->e_id < BDB_IDL_RANGE_FIRST(candidates)
740                            || ps_e->e_id > BDB_IDL_RANGE_LAST(candidates)){
741                                 rs->sr_err = LDAP_SUCCESS;
742                                 goto done;
743                         }
744                 }
745                 candidates[0] = 1;
746                 candidates[1] = ps_e->e_id;
747         }
748 #endif
749
750         if ( candidates[0] == 0 ) {
751 #ifdef NEW_LOGGING
752                 LDAP_LOG ( OPERATION, RESULTS,
753                         "bdb_search: no candidates\n", 0, 0, 0 );
754 #else
755                 Debug( LDAP_DEBUG_TRACE, "bdb_search: no candidates\n",
756                         0, 0, 0 );
757 #endif
758
759                 rs->sr_err = LDAP_SUCCESS;
760                 send_ldap_result( sop, rs );
761                 rs->sr_err = 1;
762                 goto done;
763         }
764
765         /* if not root and candidates exceed to-be-checked entries, abort */
766         if ( !isroot && limit->lms_s_unchecked != -1 ) {
767                 if ( BDB_IDL_N(candidates) > (unsigned) limit->lms_s_unchecked ) {
768                         rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
769                         send_ldap_result( sop, rs );
770                         rs->sr_err = 1;
771                         goto done;
772                 }
773         }
774
775         if ( isroot || !limit->lms_s_pr_hide ) {
776                 tentries = BDB_IDL_N(candidates);
777         }
778
779 #ifdef LDAP_CONTROL_PAGEDRESULTS
780         if ( get_pagedresults(sop) ) {
781                 if ( sop->o_pagedresults_state.ps_cookie == 0 ) {
782                         id = 0;
783                 } else {
784                         if ( sop->o_pagedresults_size == 0 ) {
785                                 rs->sr_err = LDAP_SUCCESS;
786                                 rs->sr_text = "search abandoned by pagedResult size=0";
787                                 send_ldap_result( sop, rs );
788                                 goto done;
789                         }
790                         for ( id = bdb_idl_first( candidates, &cursor );
791                                 id != NOID && id <= (ID)( sop->o_pagedresults_state.ps_cookie );
792                                 id = bdb_idl_next( candidates, &cursor ) );
793                 }
794                 if ( cursor == NOID ) {
795 #ifdef NEW_LOGGING
796                         LDAP_LOG ( OPERATION, RESULTS, 
797                                 "bdb_search: no paged results candidates\n", 
798                         0, 0, 0 );
799 #else
800                         Debug( LDAP_DEBUG_TRACE, 
801                                 "bdb_search: no paged results candidates\n",
802                                 0, 0, 0 );
803 #endif
804                         send_pagerequest_response( sop, rs, lastid, 0 );
805
806                         rs->sr_err = 1;
807                         goto done;
808                 }
809                 goto loop_begin;
810         }
811 #endif
812
813 #ifdef LDAP_CLIENT_UPDATE
814         if ( (sop->o_clientupdate_type & SLAP_LCUP_SYNC) ||
815             (IS_PSEARCH && sop->o_ps_protocol == LDAP_CLIENT_UPDATE ))
816         {
817                 cookief.f_choice = LDAP_FILTER_AND;
818                 cookief.f_and = &csnfnot;
819                 cookief.f_next = NULL;
820
821                 csnfnot.f_choice = LDAP_FILTER_NOT;
822                 csnfnot.f_not = &csnfeq;
823                 csnfnot.f_next = &csnfand;
824
825                 csnfeq.f_choice = LDAP_FILTER_EQUALITY;
826                 csnfeq.f_ava = &aa_eq;
827                 csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
828                 csnfeq.f_av_value = sop->o_clientupdate_state;
829
830                 csnfand.f_choice = LDAP_FILTER_AND;
831                 csnfand.f_and = &csnfge;
832                 csnfand.f_next = NULL;
833
834                 csnfge.f_choice = LDAP_FILTER_GE;
835                 csnfge.f_ava = &aa_ge;
836                 csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
837                 csnfge.f_av_value = sop->o_clientupdate_state;
838                 csnfge.f_next = sop->oq_search.rs_filter;
839         }
840 #endif
841 #if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
842         else
843 #endif
844 #ifdef LDAP_SYNC
845         if ( (sop->o_sync_mode & SLAP_SYNC_REFRESH) ||
846                 ( IS_PSEARCH && sop->o_ps_protocol == LDAP_SYNC ))
847         {
848                 cookief.f_choice = LDAP_FILTER_AND;
849                 cookief.f_and = &csnfnot;
850                 cookief.f_next = NULL;
851
852                 csnfnot.f_choice = LDAP_FILTER_NOT;
853                 csnfnot.f_not = &csnfeq;
854                 csnfnot.f_next = &csnfand;
855
856                 csnfeq.f_choice = LDAP_FILTER_EQUALITY;
857                 csnfeq.f_ava = &aa_eq;
858                 csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
859                 csnfeq.f_av_value = sop->o_sync_state;
860
861                 csnfand.f_choice = LDAP_FILTER_AND;
862                 csnfand.f_and = &csnfge;
863                 csnfand.f_next = NULL;
864
865                 csnfge.f_choice = LDAP_FILTER_GE;
866                 csnfge.f_ava = &aa_ge;
867                 csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
868                 csnfge.f_av_value = sop->o_sync_state;
869                 csnfge.f_next = sop->oq_search.rs_filter;
870         }
871 #endif
872
873         for ( id = bdb_idl_first( candidates, &cursor );
874                 id != NOID;
875                 id = bdb_idl_next( candidates, &cursor ) )
876         {
877                 int             scopeok = 0;
878
879 loop_begin:
880                 /* check for abandon */
881                 if ( sop->o_abandon ) {
882                         rs->sr_err = 0;
883                         goto done;
884                 }
885
886 #ifdef LDAP_EXOP_X_CANCEL
887                 if ( sop->o_cancel ) {
888                         assert( sop->o_cancel == SLAP_CANCEL_REQ );
889                         rs->sr_err = LDAP_CANCELLED;
890                         send_ldap_result( sop, rs );
891                         sop->o_cancel = SLAP_CANCEL_ACK;
892                         rs->sr_err = 0;
893                         goto done;
894                 }
895 #endif
896
897                 /* check time limit */
898                 if ( sop->oq_search.rs_tlimit != -1 && slap_get_time() > stoptime ) {
899                         rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
900                         rs->sr_ref = rs->sr_v2ref;
901                         send_ldap_result( sop, rs );
902                         goto done;
903                 }
904
905
906 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
907                 if (!IS_PSEARCH) {
908 #endif
909 id2entry_retry:
910                         /* get the entry with reader lock */
911                         ei = NULL;
912                         rs->sr_err = bdb_cache_find_id( op, NULL,
913                                 id, &ei, 0, locker, &lock );
914
915                         if (rs->sr_err == LDAP_BUSY) {
916                                 rs->sr_text = "ldap server busy";
917                                 send_ldap_result( sop, rs );
918                                 goto done;
919
920                         } else if ( rs->sr_err == DB_LOCK_DEADLOCK
921                                 || rs->sr_err == DB_LOCK_NOTGRANTED )
922                         {
923                                 goto id2entry_retry;    
924                         }
925
926                         if ( ei && rs->sr_err == 0 ) {
927                                 e = ei->bei_e;
928                         } else {
929                                 e = NULL;
930                         }
931
932                         if ( e == NULL ) {
933                                 if( !BDB_IDL_IS_RANGE(candidates) ) {
934                                         /* only complain for non-range IDLs */
935 #ifdef NEW_LOGGING
936                                         LDAP_LOG ( OPERATION, RESULTS,
937                                                 "bdb_search: candidate %ld not found\n",
938                                                 (long) id, 0, 0);
939 #else
940                                         Debug( LDAP_DEBUG_TRACE,
941                                                 "bdb_search: candidate %ld not found\n",
942                                                 (long) id, 0, 0 );
943 #endif
944                                 }
945
946                                 goto loop_continue;
947                         }
948 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
949                 } else {
950                         e = ps_e;
951                 }
952 #endif
953
954                 rs->sr_entry = e;
955 #ifdef BDB_SUBENTRIES
956                 if ( !is_sync_protocol( sop ) ) {
957                         if ( is_entry_subentry( e ) ) {
958                                 if( sop->oq_search.rs_scope != LDAP_SCOPE_BASE ) {
959                                         if(!get_subentries_visibility( sop )) {
960                                                 /* only subentries are visible */
961                                                 goto loop_continue;
962                                         }
963
964                                 } else if ( get_subentries( sop ) &&
965                                         !get_subentries_visibility( sop ))
966                                 {
967                                         /* only subentries are visible */
968                                         goto loop_continue;
969                                 }
970
971                         } else if ( get_subentries_visibility( sop )) {
972                                 /* only subentries are visible */
973                                 goto loop_continue;
974                         }
975                 }
976 #endif
977
978                 /* Does this candidate actually satisfy the search scope?
979                  *
980                  * Note that we don't lock access to the bei_parent pointer.
981                  * Since only leaf nodes can be deleted, the parent of any
982                  * node will always be a valid node. Also since we have
983                  * a Read lock on the data, it cannot be renamed out of the
984                  * scope while we are looking at it, and unless we're using
985                  * BDB_HIER, its parents cannot be moved either.
986                  */
987                 switch( sop->ors_scope ) {
988                 case LDAP_SCOPE_BASE:
989                         /* This is always true, yes? */
990                         if ( id == base.e_id )
991                                 scopeok = 1;
992                         break;
993                 case LDAP_SCOPE_ONELEVEL:
994                         if ( ei->bei_parent->bei_id == base.e_id )
995                                 scopeok = 1;
996                         break;
997                 case LDAP_SCOPE_SUBTREE:
998                         { EntryInfo *tmp;
999                         for ( tmp = BEI(e); tmp->bei_parent;
1000                                 tmp = tmp->bei_parent ) {
1001                                 if ( tmp->bei_id == base.e_id ) {
1002                                         scopeok = 1;
1003                                         break;
1004                                 }
1005                         } }
1006                         break;
1007                 }
1008
1009 #ifdef BDB_ALIASES
1010                 /* aliases were already dereferenced in candidate list */
1011                 if ( sop->ors_deref & LDAP_DEREF_SEARCHING ) {
1012                         /* but if the search base is an alias, and we didn't
1013                          * deref it when finding, return it.
1014                          */
1015                         if ( is_entry_alias(e) &&
1016                                 ((sop->ors_deref & LDAP_DEREF_FINDING)
1017                                   || !bvmatch(&e->e_nname, &op->o_req_ndn)))
1018                         {
1019                                 goto loop_continue;
1020                         }
1021
1022                         /* scopes is only non-empty for onelevel or subtree */
1023                         if ( !scopeok && BDB_IDL_N(scopes) ) {
1024                                 unsigned x;
1025                                 if ( sop->ors_scope == LDAP_SCOPE_ONELEVEL ) {
1026                                         x = bdb_idl_search( scopes,
1027                                                 e->e_id );
1028                                         if ( scopes[x] == e->e_id )
1029                                                 scopeok = 1;
1030                                 } else {
1031                                 /* subtree, walk up the tree */
1032                                         EntryInfo *tmp = BEI(e);
1033                                         for (;tmp->bei_parent;
1034                                                 tmp=tmp->bei_parent) {
1035                                                 x = bdb_idl_search(
1036                                                         scopes, tmp->bei_id );
1037                                                 if ( scopes[x] == tmp->bei_id ) {
1038                                                         scopeok = 1;
1039                                                         break;
1040                                                 }
1041                                         }
1042                                 }
1043                         }
1044                 }
1045 #endif
1046
1047                 /* Not in scope, ignore it */
1048                 if ( !scopeok ) {
1049 #ifdef NEW_LOGGING
1050                         LDAP_LOG ( OPERATION, RESULTS,
1051                                 "bdb_search: %ld scope not okay\n",
1052                                 (long) id, 0, 0);
1053 #else
1054                         Debug( LDAP_DEBUG_TRACE,
1055                                 "bdb_search: %ld scope not okay\n",
1056                                 (long) id, 0, 0 );
1057 #endif
1058                         goto loop_continue;
1059                 }
1060
1061                 /*
1062                  * if it's a referral, add it to the list of referrals. only do
1063                  * this for non-base searches, and don't check the filter
1064                  * explicitly here since it's only a candidate anyway.
1065                  */
1066                 if ( !manageDSAit && sop->oq_search.rs_scope != LDAP_SCOPE_BASE
1067                         && is_entry_referral( e ) )
1068                 {
1069                         BerVarray erefs = get_entry_referrals( sop, e );
1070                         rs->sr_ref = referral_rewrite( erefs,
1071                                 &e->e_name, NULL,
1072                                 sop->oq_search.rs_scope == LDAP_SCOPE_SUBTREE
1073                                         ? LDAP_SCOPE_SUBTREE
1074                                         : LDAP_SCOPE_BASE );
1075
1076                         send_search_reference( sop, rs );
1077
1078                         ber_bvarray_free( rs->sr_ref );
1079                         ber_bvarray_free( erefs );
1080                         rs->sr_ref = NULL;
1081
1082                         goto loop_continue;
1083                 }
1084
1085 #ifdef LDAP_SYNCREPL
1086                 if ( !manageDSAit && is_entry_glue( e ) )
1087                 {
1088                         goto loop_continue;
1089                 }
1090 #endif
1091
1092                 /* if it matches the filter and scope, send it */
1093 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1094                 if (IS_PSEARCH) {
1095                         if (ps_type != LDAP_PSEARCH_BY_SCOPEOUT) {
1096                                 rs->sr_err = test_filter( sop, rs->sr_entry, &cookief );
1097                         } else {
1098                                 rs->sr_err = LDAP_COMPARE_TRUE;
1099                         }
1100                 } else {
1101 #ifdef LDAP_CLIENT_UPDATE
1102                         if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
1103                                 rs->sr_err = test_filter( sop, rs->sr_entry, &cookief );
1104                         } else
1105 #endif
1106 #ifdef LDAP_SYNC
1107                         if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
1108                                 rc_sync = test_filter( sop, rs->sr_entry, &cookief );
1109                                 rs->sr_err = test_filter( sop,
1110                                         rs->sr_entry, sop->oq_search.rs_filter );
1111                                 if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
1112                                         if ( rc_sync == LDAP_COMPARE_TRUE ) {
1113                                                 entry_sync_state = LDAP_SYNC_ADD;
1114                                         } else {
1115                                                 entry_sync_state = LDAP_SYNC_PRESENT;
1116                                         }
1117                                 }
1118                         } else
1119 #endif
1120 #endif
1121                         {
1122                                 rs->sr_err = test_filter( sop,
1123                                         rs->sr_entry, sop->oq_search.rs_filter );
1124                         }
1125 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1126                 }
1127 #endif
1128
1129                 if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
1130                         /* check size limit */
1131                         if ( --sop->oq_search.rs_slimit == -1 ) {
1132 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1133                                 if (!IS_PSEARCH)
1134 #endif
1135                                 bdb_cache_return_entry_r( bdb->bi_dbenv,
1136                                         &bdb->bi_cache, e, &lock );
1137                                 e = NULL;
1138                                 rs->sr_entry = NULL;
1139                                 rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
1140                                 rs->sr_ref = rs->sr_v2ref;
1141                                 send_ldap_result( sop, rs );
1142                                 goto done;
1143                         }
1144
1145 #ifdef LDAP_CONTROL_PAGEDRESULTS
1146                         if ( get_pagedresults(sop) ) {
1147                                 if ( rs->sr_nentries >= sop->o_pagedresults_size ) {
1148                                         send_pagerequest_response( sop, rs,
1149                                                 lastid, tentries );
1150                                         goto done;
1151                                 }
1152                                 lastid = id;
1153                         }
1154 #endif
1155
1156                         if (e) {
1157                                 /* safe default */
1158                                 int result = -1;
1159                                 
1160 #if 0   /* noop is masked SLAP_CTRL_UPDATE */
1161                                 if( op->o_noop ) {
1162                                         result = 0;
1163                                 } else
1164 #endif
1165 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
1166                                 if (IS_PSEARCH) {
1167 #ifdef LDAP_SYNC
1168                                         int premodify_found = 0;
1169                                         int entry_sync_state;
1170 #endif
1171
1172                                         if ( ps_type == LDAP_PSEARCH_BY_ADD ||
1173                                                  ps_type == LDAP_PSEARCH_BY_DELETE ||
1174                                                  ps_type == LDAP_PSEARCH_BY_MODIFY ||
1175                                                  ps_type == LDAP_PSEARCH_BY_SCOPEOUT )
1176                                         {
1177                                                 if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) {
1178                                                         struct psid_entry* psid_e;
1179                                                         LDAP_LIST_FOREACH( psid_e,
1180                                                                 &op->o_pm_list, ps_link)
1181                                                         {
1182                                                                 if( psid_e->ps_op == sop ) {
1183 #ifdef LDAP_SYNC
1184                                                                         premodify_found = 1;
1185 #endif
1186                                                                         LDAP_LIST_REMOVE(psid_e, ps_link);
1187                                                                         break;
1188                                                                 }
1189                                                         }
1190                                                         if (psid_e != NULL) free (psid_e);
1191                                                 }
1192 #ifdef LDAP_SYNC
1193                                                 if ( ps_type == LDAP_PSEARCH_BY_ADD ) {
1194                                                         entry_sync_state = LDAP_SYNC_ADD;
1195                                                 } else if ( ps_type == LDAP_PSEARCH_BY_DELETE ) {
1196                                                         entry_sync_state = LDAP_SYNC_DELETE;
1197                                                 } else if ( ps_type == LDAP_PSEARCH_BY_MODIFY ) {
1198                                                         if ( premodify_found ) {
1199                                                                 entry_sync_state = LDAP_SYNC_MODIFY;
1200                                                         } else {
1201                                                                 entry_sync_state = LDAP_SYNC_ADD;
1202                                                         }
1203                                                 } else if ( ps_type == LDAP_PSEARCH_BY_SCOPEOUT )
1204                                                         entry_sync_state = LDAP_SYNC_DELETE;
1205                                                 else {
1206                                                         rs->sr_err = 1;
1207                                                         goto done;
1208                                                 }
1209 #endif
1210
1211 #ifdef LDAP_CLIENT_UPDATE
1212                                                 if ( sop->o_ps_protocol == LDAP_CLIENT_UPDATE ) {
1213                                                         int entry_count = ++sop->o_ps_entries;
1214                                                         if ( IS_BDB_REPLACE(ps_type) ) {
1215                                                                 rs->sr_err = bdb_build_lcup_update_ctrl( sop,
1216                                                                         rs, e, entry_count, ctrls,
1217                                                                         num_ctrls++, &latest_entrycsn_bv,
1218                                                                         SLAP_LCUP_ENTRY_DELETED_TRUE );
1219                                                         } else {
1220                                                                 rs->sr_err = bdb_build_lcup_update_ctrl( sop,
1221                                                                         rs, e, entry_count, ctrls,
1222                                                                         num_ctrls++, &latest_entrycsn_bv,
1223                                                                         SLAP_LCUP_ENTRY_DELETED_FALSE );
1224                                                         }
1225                                                         if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1226                                                         rs->sr_attrs = attrs;
1227                                                         rs->sr_ctrls = ctrls;
1228                                                         result = send_search_entry( sop, rs );
1229                                                         ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1230                                                         ch_free( ctrls[--num_ctrls] );
1231                                                         ctrls[num_ctrls] = NULL;
1232                                                         rs->sr_ctrls = NULL;
1233                                                 } else
1234 #endif
1235 #ifdef LDAP_SYNC
1236                                                 if ( sop->o_ps_protocol == LDAP_SYNC ) {
1237                                                         rs->sr_err = bdb_build_sync_state_ctrl( sop,
1238                                                                 rs, e, entry_sync_state, ctrls,
1239                                                                 num_ctrls++, 1, &latest_entrycsn_bv );
1240                                                         if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1241                                                         rs->sr_attrs = attrs;
1242                                                         rs->sr_ctrls = ctrls;
1243                                                         result = send_search_entry( sop, rs );
1244                                                         ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1245                                                         ch_free( ctrls[--num_ctrls] );
1246                                                         ctrls[num_ctrls] = NULL;
1247                                                         rs->sr_ctrls = NULL;
1248                                                 } else
1249 #endif
1250                                                 {
1251                                                         rs->sr_err = 1;
1252                                                         goto done;
1253                                                 }
1254
1255                                         } else if ( ps_type == LDAP_PSEARCH_BY_PREMODIFY ) {
1256                                                 struct psid_entry* psid_e;
1257                                                 psid_e = (struct psid_entry *) calloc (1,
1258                                                         sizeof(struct psid_entry));
1259                                                 psid_e->ps_op = sop;
1260                                                 LDAP_LIST_INSERT_HEAD( &op->o_pm_list,
1261                                                         psid_e, ps_link );
1262
1263                                         } else {
1264                                                 printf("Error !\n");
1265                                         }
1266                                 } else {
1267 #ifdef LDAP_CLIENT_UPDATE
1268                                         if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
1269                                                 rs->sr_err = bdb_build_lcup_update_ctrl( sop,
1270                                                         rs, e, ++entry_count, ctrls,
1271                                                         num_ctrls++, &latest_entrycsn_bv,
1272                                                         SLAP_LCUP_ENTRY_DELETED_FALSE );
1273                                                 if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1274                                                 rs->sr_ctrls = ctrls;
1275                                                 rs->sr_attrs = sop->oq_search.rs_attrs;
1276                                                 result = send_search_entry( sop, rs );
1277                                                 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1278                                                 ch_free( ctrls[--num_ctrls] );
1279                                                 ctrls[num_ctrls] = NULL;
1280                                                 rs->sr_ctrls = NULL;
1281                                         } else
1282 #endif
1283 #ifdef LDAP_SYNC
1284                                         if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
1285                                                 rs->sr_err = bdb_build_sync_state_ctrl( sop,
1286                                                         rs, e, entry_sync_state, ctrls,
1287                                                         num_ctrls++, 0, &latest_entrycsn_bv );
1288                                                 if ( rs->sr_err != LDAP_SUCCESS ) goto done;
1289
1290                                                 rs->sr_ctrls = ctrls;
1291                                                 if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */
1292                                                         rs->sr_attrs = sop->oq_search.rs_attrs;
1293                                                 } else { /* PRESENT */
1294                                                         rs->sr_attrs = &null_attr;
1295                                                 }
1296                                                 result = send_search_entry( sop, rs );
1297                                                 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1298                                                 ch_free( ctrls[--num_ctrls] );
1299                                                 ctrls[num_ctrls] = NULL;
1300                                                 rs->sr_ctrls = NULL;
1301                                         } else
1302 #endif
1303 #endif
1304                                         {
1305                                                 rs->sr_attrs = sop->oq_search.rs_attrs;
1306                                                 rs->sr_ctrls = NULL;
1307                                                 result = send_search_entry( sop, rs );
1308                                         }
1309                                 }
1310
1311                                 switch (result) {
1312                                 case 0:         /* entry sent ok */
1313                                         break;
1314                                 case 1:         /* entry not sent */
1315                                         break;
1316                                 case -1:        /* connection closed */
1317                                         if (!IS_PSEARCH)
1318                                         bdb_cache_return_entry_r(bdb->bi_dbenv,
1319                                                 &bdb->bi_cache, e, &lock);
1320                                         e = NULL;
1321                                         rs->sr_entry = NULL;
1322                                         rs->sr_err = LDAP_OTHER;
1323                                         goto done;
1324                                 }
1325                         }
1326                 } else {
1327 #ifdef NEW_LOGGING
1328                         LDAP_LOG ( OPERATION, RESULTS,
1329                                 "bdb_search: %ld does not match filter\n", (long) id, 0, 0);
1330 #else
1331                         Debug( LDAP_DEBUG_TRACE,
1332                                 "bdb_search: %ld does not match filter\n",
1333                                 (long) id, 0, 0 );
1334 #endif
1335                 }
1336
1337 loop_continue:
1338                 if( e != NULL ) {
1339                         /* free reader lock */
1340                         if (!IS_PSEARCH) {
1341                                 bdb_cache_return_entry_r( bdb->bi_dbenv,
1342                                         &bdb->bi_cache, e , &lock);
1343                         }
1344                         e = NULL;
1345                         rs->sr_entry = NULL;
1346                 }
1347
1348                 ldap_pvt_thread_yield();
1349         }
1350
1351         if (!IS_PSEARCH) {
1352 #ifdef LDAP_CLIENT_UPDATE
1353         if ( sop->o_clientupdate_type & SLAP_LCUP_SYNC ) {
1354                 bdb_build_lcup_done_ctrl( sop, rs, ctrls,
1355                         num_ctrls++, &latest_entrycsn_bv );
1356
1357                 rs->sr_ctrls = ctrls;
1358                 rs->sr_ref = rs->sr_v2ref;
1359                 rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
1360                 send_ldap_result( sop, rs );
1361
1362                 ch_free( latest_entrycsn_bv.bv_val );
1363                 latest_entrycsn_bv.bv_val = NULL;
1364
1365                 if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) {
1366                         ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1367                 }
1368                 ch_free( ctrls[--num_ctrls] );
1369                 ctrls[num_ctrls] = NULL;
1370         } else
1371 #endif
1372 #ifdef LDAP_SYNC
1373         if ( sop->o_sync_mode & SLAP_SYNC_REFRESH ) {
1374                 if ( sop->o_sync_mode & SLAP_SYNC_PERSIST ) {
1375                         /* refreshAndPersist mode */
1376                         rs->sr_err = LDAP_SUCCESS;
1377                         rs->sr_rspoid = LDAP_SYNC_INFO;
1378                         rs->sr_ctrls = NULL;
1379                         bdb_send_ldap_intermediate( sop, rs,
1380                                 LDAP_SYNC_REFRESH_DONE, &latest_entrycsn_bv );
1381                 } else {
1382                         /* refreshOnly mode */
1383                         bdb_build_sync_done_ctrl( sop, rs, ctrls,
1384                                 num_ctrls++, 1, &latest_entrycsn_bv );
1385                         rs->sr_ctrls = ctrls;
1386                         rs->sr_ref = rs->sr_v2ref;
1387                         rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
1388                         send_ldap_result( sop, rs );
1389                         if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL ) {
1390                                 ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
1391                         }
1392                         ch_free( ctrls[--num_ctrls] );
1393                         ctrls[num_ctrls] = NULL;
1394                 }
1395
1396                 ch_free( latest_entrycsn_bv.bv_val );
1397                 latest_entrycsn_bv.bv_val = NULL;
1398         } else
1399 #endif
1400         {
1401                 rs->sr_ctrls = NULL;
1402                 rs->sr_ref = rs->sr_v2ref;
1403                 rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
1404                 send_ldap_result( sop, rs );
1405         }
1406         }
1407
1408         rs->sr_err = LDAP_SUCCESS;
1409
1410 done:
1411         if( !IS_PSEARCH && e != NULL ) {
1412                 /* free reader lock */
1413                 bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
1414         }
1415
1416         LOCK_ID_FREE (bdb->bi_dbenv, locker );
1417
1418         if( rs->sr_v2ref ) {
1419                 ber_bvarray_free( rs->sr_v2ref );
1420                 rs->sr_v2ref = NULL;
1421         }
1422         if( realbase.bv_val ) ch_free( realbase.bv_val );
1423
1424         return rs->sr_err;
1425 }
1426
1427
1428 static int base_candidate(
1429         BackendDB       *be,
1430         Entry   *e,
1431         ID              *ids )
1432 {
1433 #ifdef NEW_LOGGING
1434         LDAP_LOG ( OPERATION, ENTRY,
1435                 "base_candidate: base: \"%s\" (0x%08lx)\n",
1436                 e->e_nname.bv_val, (long) e->e_id, 0);
1437 #else
1438         Debug(LDAP_DEBUG_ARGS, "base_candidates: base: \"%s\" (0x%08lx)\n",
1439                 e->e_nname.bv_val, (long) e->e_id, 0);
1440 #endif
1441
1442         ids[0] = 1;
1443         ids[1] = e->e_id;
1444         return 0;
1445 }
1446
1447 /* Look for "objectClass Present" in this filter.
1448  * Also count depth of filter tree while we're at it.
1449  */
1450 static int oc_filter(
1451         Filter *f,
1452         int cur,
1453         int *max
1454 )
1455 {
1456         int rc = 0;
1457
1458         if( cur > *max ) *max = cur;
1459
1460         switch(f->f_choice) {
1461         case LDAP_FILTER_PRESENT:
1462                 if (f->f_desc == slap_schema.si_ad_objectClass) {
1463                         rc = 1;
1464                 }
1465                 break;
1466
1467         case LDAP_FILTER_AND:
1468         case LDAP_FILTER_OR:
1469                 cur++;
1470                 for (f=f->f_and; f; f=f->f_next) {
1471                         (void) oc_filter(f, cur, max);
1472                 }
1473                 break;
1474
1475         default:
1476                 break;
1477         }
1478         return rc;
1479 }
1480
1481 static void search_stack_free( void *key, void *data )
1482 {
1483         ber_memfree_x(data, NULL);
1484 }
1485
1486 static void *search_stack(
1487         Operation *op
1488 )
1489 {
1490         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
1491         void *ret = NULL;
1492
1493         if ( op->o_threadctx ) {
1494                 ldap_pvt_thread_pool_getkey( op->o_threadctx, search_stack,
1495                         &ret, NULL );
1496         } else {
1497                 ret = bdb->bi_search_stack;
1498         }
1499
1500         if ( !ret ) {
1501                 ret = ch_malloc( bdb->bi_search_stack_depth * BDB_IDL_UM_SIZE
1502                         * sizeof( ID ) );
1503                 if ( op->o_threadctx ) {
1504                         ldap_pvt_thread_pool_setkey( op->o_threadctx, search_stack,
1505                                 ret, search_stack_free );
1506                 } else {
1507                         bdb->bi_search_stack = ret;
1508                 }
1509         }
1510         return ret;
1511 }
1512
1513 static int search_candidates(
1514         Operation *stackop,
1515         Operation *op,
1516         SlapReply *rs,
1517         Entry *e,
1518         u_int32_t locker,
1519         ID      *ids,
1520         ID      *scopes )
1521 {
1522         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
1523         int rc, depth = 1;
1524         Filter          f, rf, xf, nf;
1525         ID              *stack;
1526         AttributeAssertion aa_ref;
1527 #ifdef BDB_SUBENTRIES
1528         Filter  sf;
1529         AttributeAssertion aa_subentry;
1530 #endif
1531
1532         /*
1533          * This routine takes as input a filter (user-filter)
1534          * and rewrites it as follows:
1535          *      (&(scope=DN)[(objectClass=subentry)]
1536          *              (|[(objectClass=referral)(objectClass=alias)](user-filter))
1537          */
1538
1539 #ifdef NEW_LOGGING
1540         LDAP_LOG ( OPERATION, ENTRY,
1541                 "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n", 
1542                 e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope);
1543 #else
1544         Debug(LDAP_DEBUG_TRACE,
1545                 "search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
1546                 e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope );
1547 #endif
1548
1549         xf.f_or = op->oq_search.rs_filter;
1550         xf.f_choice = LDAP_FILTER_OR;
1551         xf.f_next = NULL;
1552
1553         /* If the user's filter uses objectClass=*,
1554          * these clauses are redundant.
1555          */
1556         if (!oc_filter(op->oq_search.rs_filter, 1, &depth)
1557                 && !get_subentries_visibility(op)
1558                 && !is_sync_protocol(op) )
1559         {
1560                 if( !get_manageDSAit(op) && !get_domainScope(op) ) {
1561                         /* match referral objects */
1562                         struct berval bv_ref = { sizeof("referral")-1, "referral" };
1563                         rf.f_choice = LDAP_FILTER_EQUALITY;
1564                         rf.f_ava = &aa_ref;
1565                         rf.f_av_desc = slap_schema.si_ad_objectClass;
1566                         rf.f_av_value = bv_ref;
1567                         rf.f_next = xf.f_or;
1568                         xf.f_or = &rf;
1569                         depth++;
1570                 }
1571         }
1572
1573         f.f_next = NULL;
1574         f.f_choice = LDAP_FILTER_AND;
1575         f.f_and = &nf;
1576         /* Dummy; we compute scope separately now */
1577         nf.f_choice = SLAPD_FILTER_COMPUTED;
1578         nf.f_result = LDAP_SUCCESS;
1579         nf.f_next = xf.f_or == op->oq_search.rs_filter
1580                 ? op->oq_search.rs_filter : &xf ;
1581         /* Filter depth increased again, adding dummy clause */
1582         depth++;
1583
1584 #ifdef BDB_SUBENTRIES
1585         if( get_subentries_visibility( op ) ) {
1586                 struct berval bv_subentry = { sizeof("SUBENTRY")-1, "SUBENTRY" };
1587                 sf.f_choice = LDAP_FILTER_EQUALITY;
1588                 sf.f_ava = &aa_subentry;
1589                 sf.f_av_desc = slap_schema.si_ad_objectClass;
1590                 sf.f_av_value = bv_subentry;
1591                 sf.f_next = nf.f_next;
1592                 nf.f_next = &sf;
1593         }
1594 #endif
1595
1596         /* Allocate IDL stack, plus 1 more for former tmp */
1597         if ( depth+1 > bdb->bi_search_stack_depth ) {
1598                 stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
1599         } else {
1600                 stack = search_stack( stackop );
1601         }
1602
1603         if( op->ors_deref & LDAP_DEREF_SEARCHING ) {
1604                 rc = search_aliases( op, rs, e, locker, ids, scopes, stack );
1605         } else {
1606                 rc = bdb_dn2idl( op, e, ids, stack );
1607         }
1608
1609         if ( rc == LDAP_SUCCESS ) {
1610                 rc = bdb_filter_candidates( op, &f, ids,
1611                         stack, stack+BDB_IDL_UM_SIZE );
1612         }
1613
1614         if ( depth+1 > bdb->bi_search_stack_depth ) {
1615                 ch_free( stack );
1616         }
1617
1618         if( rc ) {
1619 #ifdef NEW_LOGGING
1620                 LDAP_LOG ( OPERATION, DETAIL1,
1621                         "bdb_search_candidates: failed (rc=%d)\n", rc, 0, 0  );
1622 #else
1623                 Debug(LDAP_DEBUG_TRACE,
1624                         "bdb_search_candidates: failed (rc=%d)\n",
1625                         rc, NULL, NULL );
1626 #endif
1627
1628         } else {
1629 #ifdef NEW_LOGGING
1630                 LDAP_LOG ( OPERATION, DETAIL1,
1631                         "bdb_search_candidates: id=%ld first=%ld last=%ld\n",
1632                         (long) ids[0], (long) BDB_IDL_FIRST(ids), 
1633                         (long) BDB_IDL_LAST(ids));
1634 #else
1635                 Debug(LDAP_DEBUG_TRACE,
1636                         "bdb_search_candidates: id=%ld first=%ld last=%ld\n",
1637                         (long) ids[0],
1638                         (long) BDB_IDL_FIRST(ids),
1639                         (long) BDB_IDL_LAST(ids) );
1640 #endif
1641         }
1642
1643         return rc;
1644 }
1645
1646 #ifdef LDAP_CONTROL_PAGEDRESULTS
1647 static void
1648 send_pagerequest_response( 
1649         Operation       *op,
1650         SlapReply       *rs,
1651         ID              lastid,
1652         int             tentries )
1653 {
1654         LDAPControl     ctrl, *ctrls[2];
1655         char berbuf[LBER_ELEMENT_SIZEOF];
1656         BerElement      *ber = (BerElement *)berbuf;
1657         struct berval   cookie = { 0, NULL };
1658         PagedResultsCookie respcookie;
1659
1660 #ifdef NEW_LOGGING
1661         LDAP_LOG ( OPERATION, ENTRY,
1662                 "send_pagerequest_response: lastid: (0x%08lx) "
1663                 "nentries: (0x%081x)\n", 
1664                 lastid, rs->sr_nentries, NULL );
1665 #else
1666         Debug(LDAP_DEBUG_ARGS, "send_pagerequest_response: lastid: (0x%08lx) "
1667                         "nentries: (0x%081x)\n", lastid, rs->sr_nentries, NULL );
1668 #endif
1669
1670         ctrl.ldctl_value.bv_val = NULL;
1671         ctrls[0] = &ctrl;
1672         ctrls[1] = NULL;
1673
1674         ber_init2( ber, NULL, LBER_USE_DER );
1675
1676         respcookie = ( PagedResultsCookie )lastid;
1677         op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
1678         cookie.bv_len = sizeof( respcookie );
1679         cookie.bv_val = (char *)&respcookie;
1680
1681         /*
1682          * FIXME: we should consider sending an estimate of the entries
1683          * left, after appropriate security check is done
1684          */
1685         ber_printf( ber, "{iO}", tentries, &cookie ); 
1686
1687         if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
1688                 goto done;
1689         }
1690
1691         ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
1692         ctrls[0]->ldctl_iscritical = 0;
1693
1694         rs->sr_ctrls = ctrls;
1695         rs->sr_err = LDAP_SUCCESS;
1696         send_ldap_result( op, rs );
1697
1698 done:
1699         (void) ber_free_buf( ber );
1700 }                       
1701 #endif
1702
1703 #ifdef LDAP_CLIENT_UPDATE
1704 int
1705 bdb_build_lcup_update_ctrl(
1706         Operation       *op,
1707         SlapReply       *rs,
1708         Entry           *e,
1709         int             entry_count,
1710         LDAPControl     **ctrls,
1711         int             num_ctrls,
1712         struct berval   *latest_entrycsn_bv,
1713         int             isdeleted       )
1714 {
1715         Attribute* a;
1716         int ret;
1717         int res;
1718         const char *text = NULL;
1719
1720         char berbuf[LBER_ELEMENT_SIZEOF];
1721         BerElement *ber = (BerElement *)berbuf;
1722
1723         struct berval entrycsn_bv = { 0, NULL };
1724
1725         ber_init2( ber, 0, LBER_USE_DER );
1726
1727         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1728
1729         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
1730                 AttributeDescription *desc = a->a_desc;
1731                 if ( desc == slap_schema.si_ad_entryCSN ) {
1732                         ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
1733                         if ( latest_entrycsn_bv->bv_val == NULL ) {
1734                                 ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1735                         } else {
1736                                 res = value_match( &ret, desc,
1737                                         desc->ad_type->sat_ordering, 0,
1738                                         &entrycsn_bv, latest_entrycsn_bv, &text );
1739                                 if ( res != LDAP_SUCCESS ) {
1740                                         ret = 0;
1741 #ifdef NEW_LOGGING
1742                                         LDAP_LOG ( OPERATION, RESULTS, 
1743                                                 "bdb_search: value_match failed\n",
1744                                                 0, 0, 0 );
1745 #else
1746                                         Debug( LDAP_DEBUG_TRACE,
1747                                                 "bdb_search: value_match failed\n",
1748                                                 0, 0, 0 );
1749 #endif
1750                                 }
1751
1752                                 if ( ret > 0 ) {
1753                                         ch_free( latest_entrycsn_bv->bv_val );
1754                                         latest_entrycsn_bv->bv_val = NULL;
1755                                         ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1756                                 }
1757                         }
1758                 }
1759         }
1760
1761         if ( entry_count % op->o_clientupdate_interval == 0 ) {
1762                 ber_printf( ber,
1763                         "{bb{sON}N}",
1764                         SLAP_LCUP_STATE_UPDATE_FALSE,
1765                         isdeleted,
1766                         LDAP_CUP_COOKIE_OID, &entrycsn_bv );
1767         } else { /* Do not send cookie */
1768                 ber_printf( ber,
1769                         "{bbN}",
1770                         SLAP_LCUP_STATE_UPDATE_FALSE,
1771                         isdeleted );
1772         }
1773
1774         ch_free( entrycsn_bv.bv_val );
1775         entrycsn_bv.bv_val = NULL;
1776
1777         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
1778         ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
1779         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1780
1781         ber_free_buf( ber );
1782
1783         if ( ret < 0 ) {
1784 #ifdef NEW_LOGGING
1785                 LDAP_LOG ( OPERATION, RESULTS, 
1786                         "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
1787                         0, 0, 0 );
1788 #else
1789                 Debug( LDAP_DEBUG_TRACE,
1790                         "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
1791                         0, 0, 0 );
1792 #endif
1793                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1794                 return ret;
1795         }
1796
1797         return LDAP_SUCCESS;
1798 }
1799
1800 int
1801 bdb_build_lcup_done_ctrl(
1802         Operation       *op,
1803         SlapReply       *rs,
1804         LDAPControl     **ctrls,
1805         int             num_ctrls,
1806         struct berval   *latest_entrycsn_bv     )
1807 {
1808         int ret;
1809         char berbuf[LBER_ELEMENT_SIZEOF];
1810         BerElement *ber = (BerElement *)berbuf;
1811
1812         ber_init2( ber, NULL, LBER_USE_DER );
1813
1814         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1815
1816         ber_printf( ber, "{sON}", LDAP_CUP_COOKIE_OID, latest_entrycsn_bv );
1817
1818         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
1819         ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
1820         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1821
1822         ber_free_buf( ber );
1823
1824         if ( ret < 0 ) {
1825 #ifdef NEW_LOGGING
1826                 LDAP_LOG ( OPERATION, RESULTS, 
1827                         "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
1828 #else
1829                 Debug( LDAP_DEBUG_TRACE,
1830                         "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
1831                         0, 0, 0 );
1832 #endif
1833                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1834                 return ret;
1835         }
1836
1837         return LDAP_SUCCESS;
1838 }
1839 #endif
1840
1841 #ifdef LDAP_SYNC
1842 int
1843 bdb_build_sync_state_ctrl(
1844         Operation       *op,
1845         SlapReply       *rs,
1846         Entry           *e,
1847         int             entry_sync_state,
1848         LDAPControl     **ctrls,
1849         int             num_ctrls,
1850         int             send_cookie,
1851         struct berval   *latest_entrycsn_bv     )
1852 {
1853         Attribute* a;
1854         int ret;
1855         int res;
1856         const char *text = NULL;
1857
1858         char berbuf[LBER_ELEMENT_SIZEOF];
1859         BerElement *ber = (BerElement *)berbuf;
1860
1861         struct berval entryuuid_bv      = { 0, NULL };
1862         struct berval entrycsn_bv       = { 0, NULL };
1863
1864         ber_init2( ber, 0, LBER_USE_DER );
1865
1866         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1867
1868         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
1869                 AttributeDescription *desc = a->a_desc;
1870                 if ( desc == slap_schema.si_ad_entryCSN ) {
1871                         ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
1872                         if ( latest_entrycsn_bv->bv_val == NULL ) {
1873                                 ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1874                         } else {
1875                                 res = value_match( &ret, desc,
1876                                                 desc->ad_type->sat_ordering, 0,
1877                                                 &entrycsn_bv, latest_entrycsn_bv, &text );
1878                                 if ( res != LDAP_SUCCESS ) {
1879                                         ret = 0;
1880 #ifdef NEW_LOGGING
1881                                         LDAP_LOG ( OPERATION, RESULTS,
1882                                                         "bdb_search: value_match failed\n",
1883                                                         0, 0, 0 );
1884 #else
1885                                         Debug( LDAP_DEBUG_TRACE,
1886                                                         "bdb_search: value_match failed\n",
1887                                                         0, 0, 0 );
1888 #endif
1889                                 }
1890                                 if ( ret > 0 ) {
1891                                         ch_free( latest_entrycsn_bv->bv_val );
1892                                         latest_entrycsn_bv->bv_val = NULL;
1893                                         ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
1894                                 }
1895                         }
1896                 } else if ( desc == slap_schema.si_ad_entryUUID ) {
1897                         ber_dupbv( &entryuuid_bv, &a->a_vals[0] );
1898                 }
1899         }
1900
1901         if ( send_cookie ) {
1902                 ber_printf( ber, "{eOON}",
1903                         entry_sync_state, &entryuuid_bv, &entrycsn_bv );
1904         } else {
1905                 ber_printf( ber, "{eON}",
1906                         entry_sync_state, &entryuuid_bv );
1907         }
1908
1909         ch_free( entrycsn_bv.bv_val );
1910         entrycsn_bv.bv_val = NULL;
1911         ch_free( entryuuid_bv.bv_val );
1912         entryuuid_bv.bv_val = NULL;
1913
1914         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
1915         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
1916         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1917
1918         ber_free_buf( ber );
1919
1920         if ( ret < 0 ) {
1921 #ifdef NEW_LOGGING
1922                 LDAP_LOG ( OPERATION, RESULTS, 
1923                         "bdb_build_sync_ctrl: ber_flatten2 failed\n",
1924                         0, 0, 0 );
1925 #else
1926                 Debug( LDAP_DEBUG_TRACE,
1927                         "bdb_build_sync_ctrl: ber_flatten2 failed\n",
1928                         0, 0, 0 );
1929 #endif
1930                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1931                 return ret;
1932         }
1933
1934         return LDAP_SUCCESS;
1935 }
1936
1937 int
1938 bdb_build_sync_done_ctrl(
1939         Operation       *op,
1940         SlapReply       *rs,
1941         LDAPControl     **ctrls,
1942         int             num_ctrls,
1943         int             send_cookie,
1944         struct berval   *latest_entrycsn_bv     )
1945 {
1946         int ret;
1947         char berbuf[LBER_ELEMENT_SIZEOF];
1948         BerElement *ber = (BerElement *)berbuf;
1949
1950         ber_init2( ber, NULL, LBER_USE_DER );
1951
1952         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
1953
1954         if ( send_cookie ) {
1955                 ber_printf( ber, "{ON}", latest_entrycsn_bv );
1956         } else {
1957                 ber_printf( ber, "{N}" );
1958         }
1959
1960         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
1961         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
1962         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
1963
1964         ber_free_buf( ber );
1965
1966         if ( ret < 0 ) {
1967 #ifdef NEW_LOGGING
1968                 LDAP_LOG ( OPERATION, RESULTS, 
1969                         "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
1970                         0, 0, 0 );
1971 #else
1972                 Debug( LDAP_DEBUG_TRACE,
1973                         "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
1974                         0, 0, 0 );
1975 #endif
1976                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
1977                 return ret;
1978         }
1979
1980         return LDAP_SUCCESS;
1981 }
1982
1983 int
1984 bdb_send_ldap_intermediate(
1985         Operation   *op,
1986         SlapReply   *rs,
1987         int         state,
1988         struct berval *cookie )
1989 {
1990         char berbuf[LBER_ELEMENT_SIZEOF];
1991         BerElement *ber = (BerElement *)berbuf;
1992         struct berval rspdata;
1993
1994         int ret;
1995
1996         ber_init2( ber, NULL, LBER_USE_DER );
1997
1998         if ( cookie == NULL ) {
1999                 ber_printf( ber, "{eN}", state );
2000         } else {
2001                 ber_printf( ber, "{eON}", state, cookie );
2002         }
2003
2004         ret = ber_flatten2( ber, &rspdata, 0 );
2005
2006         if ( ret < 0 ) {
2007 #ifdef NEW_LOGGING
2008                 LDAP_LOG ( OPERATION, RESULTS, 
2009                         "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
2010                         0, 0, 0 );
2011 #else
2012                 Debug( LDAP_DEBUG_TRACE,
2013                         "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
2014                         0, 0, 0 );
2015 #endif
2016                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
2017                 return ret;
2018         }
2019
2020         rs->sr_rspdata = &rspdata;
2021         send_ldap_intermediate( op, rs );
2022         rs->sr_rspdata = NULL;
2023         ber_free_buf( ber );
2024
2025         return LDAP_SUCCESS;
2026 }
2027 #endif