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