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