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