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