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