]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/lcup.c
fix hasSubordinate filtering; now it can be safely turned on
[openldap] / servers / slapd / back-bdb / lcup.c
1 /* lcup.c - lcup operations */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include "back-bdb.h"
12 #include "idl.h"
13 #include "external.h"
14
15 #ifdef LDAP_CLIENT_UPDATE
16
17 int
18 bdb_abandon(
19         BackendDB       *be,
20         Connection      *conn,
21         ber_int_t       id )
22 {
23         Operation       *ps_list;
24         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
25
26         LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
27                 if ( ps_list->o_connid == conn->c_connid ) {
28                         if ( ps_list->o_msgid == id ) {
29                                 ps_list->o_abandon = 1;
30                                 LDAP_LIST_REMOVE( ps_list, link );
31                                 slap_op_free ( ps_list );
32                                 return LDAP_SUCCESS;
33                         }
34                 }
35         }
36         return LDAP_UNAVAILABLE;
37 }
38
39 int
40 bdb_add_psearch_spec(
41         BackendDB       *be,
42         Connection      *conn,
43         Operation       *op,
44         struct berval   *base,
45         struct berval   *nbase,
46         int             scope,
47         int             deref,
48         int             slimit,
49         int             tlimit,
50         Filter          *filter,
51         struct berval   *fstr,
52         AttributeName   *attrs,
53         int             attrsonly )
54 {
55         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
56
57         LDAP_LIST_FIRST(&op->psearch_spec) = (struct lcup_search_spec *)
58                         calloc ( 1, sizeof ( struct lcup_search_spec ) );
59
60         LDAP_LIST_FIRST(&op->psearch_spec)->op = op;
61
62         LDAP_LIST_FIRST(&op->psearch_spec)->base = ber_dupbv(NULL, base);
63         LDAP_LIST_FIRST(&op->psearch_spec)->nbase = ber_dupbv(NULL, nbase);
64
65         LDAP_LIST_FIRST(&op->psearch_spec)->scope = scope;
66         LDAP_LIST_FIRST(&op->psearch_spec)->deref = deref;
67         LDAP_LIST_FIRST(&op->psearch_spec)->slimit = slimit;
68         LDAP_LIST_FIRST(&op->psearch_spec)->tlimit = tlimit;
69
70         LDAP_LIST_FIRST(&op->psearch_spec)->filter = filter;
71         LDAP_LIST_FIRST(&op->psearch_spec)->filterstr = ber_dupbv(NULL, fstr);
72         LDAP_LIST_FIRST(&op->psearch_spec)->attrs = attrs;
73
74         LDAP_LIST_FIRST(&op->psearch_spec)->attrsonly = attrsonly;
75
76         LDAP_LIST_FIRST(&op->psearch_spec)->entry_count = 0;
77
78         LDAP_LIST_INSERT_HEAD( &bdb->psearch_list, op, link );
79 }
80
81 int
82 bdb_psearch(
83         BackendDB       *be,
84         Connection      *conn,
85         Operation       *op,
86         Operation       *ps_op,
87         Entry           *entry,
88         int             psearch_type )
89 {
90         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
91         int             rc;
92         const char *text = NULL;
93         time_t          stoptime;
94         unsigned        cursor;
95         ID              id;
96         ID              candidates[BDB_IDL_UM_SIZE];
97         Entry           *e = NULL;
98         BerVarray v2refs = NULL;
99         Entry   *matched = NULL;
100         struct berval   realbase = { 0, NULL };
101         int             nentries = 0;
102         int             manageDSAit;
103
104         Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
105         AttributeAssertion aa_ge, aa_eq;
106         struct berval entrycsn_bv = { 0, NULL };
107         struct berval latest_entrycsn_bv = { 0, NULL };
108
109         struct slap_limits_set *limit = NULL;
110         int isroot = 0;
111         int scopeok = 0;
112
113         u_int32_t       locker;
114         DB_LOCK         lock;
115
116         Connection      *ps_conn   = ps_op->o_conn;
117         struct berval   *base      = LDAP_LIST_FIRST(&ps_op->psearch_spec)->base;
118         struct berval   *nbase     = LDAP_LIST_FIRST(&ps_op->psearch_spec)->nbase;
119         int             scope      = LDAP_LIST_FIRST(&ps_op->psearch_spec)->scope;
120         int             deref      = LDAP_LIST_FIRST(&ps_op->psearch_spec)->deref;
121         int             slimit     = LDAP_LIST_FIRST(&ps_op->psearch_spec)->slimit;
122         int             tlimit     = LDAP_LIST_FIRST(&ps_op->psearch_spec)->tlimit;
123         Filter          *filter    = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filter;
124         struct berval   *filterstr = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filterstr;
125         int             attrsonly  = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrsonly;
126         AttributeName   *attrs;
127
128         if ( psearch_type != LCUP_PSEARCH_BY_DELETE &&
129                                 psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
130                 attrs     = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
131         } else {
132                 attrs     = uuid_attr;
133         }
134
135 #ifdef NEW_LOGGING
136         LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
137 #else
138         Debug( LDAP_DEBUG_TRACE, "=> bdb_back_search\n",
139                 0, 0, 0);
140 #endif
141
142         manageDSAit = get_manageDSAit( ps_op );
143
144         rc = LOCK_ID (bdb->bi_dbenv, &locker );
145         switch(rc) {
146         case 0:
147                 break;
148         default:
149                 send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
150                         NULL, "internal error", NULL, NULL );
151                 return rc;
152         }
153
154         if ( nbase->bv_len == 0 ) {
155                 /* DIT root special case */
156                 e = (Entry *) &slap_entry_root;
157                 rc = 0;
158         } else                                          
159 #ifdef BDB_ALIASES
160         /* get entry with reader lock */
161         if ( deref & LDAP_DEREF_FINDING ) {
162                 e = deref_dn_r( be, nbase-, &err, &matched, &text );
163
164         } else
165 #endif
166         {
167 dn2entry_retry:
168                 rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0, locker, &lock );
169         }
170
171         switch(rc) {
172         case DB_NOTFOUND:
173         case 0:
174                 break;
175         case LDAP_BUSY:
176                 if (e != NULL) {
177                         bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
178                 }
179                 if (matched != NULL) {
180                         bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
181                 }
182                 send_ldap_result( ps_conn, ps_op, LDAP_BUSY,
183                         NULL, "ldap server busy", NULL, NULL );
184                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
185                 return LDAP_BUSY;
186         case DB_LOCK_DEADLOCK:
187         case DB_LOCK_NOTGRANTED:
188                 goto dn2entry_retry;
189         default:
190                 if (e != NULL) {
191                         bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
192                 }
193                 if (matched != NULL) {
194                         bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
195                 }
196                 send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
197                         NULL, "internal error", NULL, NULL );
198                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
199                 return rc;
200         }
201
202         if ( e == NULL ) {
203                 struct berval matched_dn = { 0, NULL };
204                 BerVarray refs = NULL;
205
206                 if ( matched != NULL ) {
207                         BerVarray erefs;
208                         ber_dupbv( &matched_dn, &matched->e_name );
209
210                         erefs = is_entry_referral( matched )
211                                 ? get_entry_referrals( be, ps_conn, ps_op, matched )
212                                 : NULL;
213
214                         bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
215                         matched = NULL;
216
217                         if( erefs ) {
218                                 refs = referral_rewrite( erefs, &matched_dn,
219                                         base, scope );
220                                 ber_bvarray_free( erefs );
221                         }
222
223                 } else {
224                         refs = referral_rewrite( default_referral,
225                                 NULL, base, scope );
226                 }
227
228                 send_ldap_result( ps_conn, ps_op,       rc=LDAP_REFERRAL ,
229                         matched_dn.bv_val, text, refs, NULL );
230
231                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
232                 if ( refs ) ber_bvarray_free( refs );
233                 if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
234                 return rc;
235         }
236
237         if (!manageDSAit && e != &slap_entry_root && is_entry_referral( e ) ) {
238                 /* entry is a referral, don't allow add */
239                 struct berval matched_dn;
240                 BerVarray erefs, refs;
241                 
242                 ber_dupbv( &matched_dn, &e->e_name );
243                 erefs = get_entry_referrals( be, ps_conn, ps_op, e );
244                 refs = NULL;
245
246                 bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
247                 e = NULL;
248
249                 if( erefs ) {
250                         refs = referral_rewrite( erefs, &matched_dn,
251                                 base, scope );
252                         ber_bvarray_free( erefs );
253                 }
254
255 #ifdef NEW_LOGGING
256                 LDAP_LOG ( OPERATION, RESULTS, 
257                         "bdb_search: entry is referral\n", 0, 0, 0 );
258 #else
259                 Debug( LDAP_DEBUG_TRACE, "bdb_search: entry is referral\n",
260                         0, 0, 0 );
261 #endif
262
263                 send_ldap_result( ps_conn, ps_op, LDAP_REFERRAL,
264                         matched_dn.bv_val,
265                         refs ? NULL : "bad referral object",
266                         refs, NULL );
267
268                 LOCK_ID_FREE (bdb->bi_dbenv, locker );
269                 ber_bvarray_free( refs );
270                 ber_memfree( matched_dn.bv_val );
271                 return 1;
272         }
273
274         /* if not root, get appropriate limits */
275         if ( be_isroot( be, &ps_op->o_ndn ) ) {
276                 isroot = 1;
277         } else {
278                 ( void ) get_limits( be, &ps_op->o_ndn, &limit );
279         }
280
281         /* The time/size limits come first because they require very little
282          * effort, so there's no chance the candidates are selected and then 
283          * the request is not honored only because of time/size constraints */
284
285         /* if no time limit requested, use soft limit (unless root!) */
286         if ( isroot ) {
287                 if ( tlimit == 0 ) {
288                         tlimit = -1;    /* allow root to set no limit */
289                 }
290
291                 if ( slimit == 0 ) {
292                         slimit = -1;
293                 }
294
295         } else {
296                 /* if no limit is required, use soft limit */
297                 if ( tlimit <= 0 ) {
298                         tlimit = limit->lms_t_soft;
299
300                 /* if requested limit higher than hard limit, abort */
301                 } else if ( tlimit > limit->lms_t_hard ) {
302                         /* no hard limit means use soft instead */
303                         if ( limit->lms_t_hard == 0 && tlimit > limit->lms_t_soft ) {
304                                 tlimit = limit->lms_t_soft;
305
306                         /* positive hard limit means abort */
307                         } else if ( limit->lms_t_hard > 0 ) {
308                                 send_search_result( ps_conn, ps_op, 
309                                                 LDAP_UNWILLING_TO_PERFORM,
310                                                 NULL, NULL, NULL, NULL, 0 );
311                                 rc = 0;
312                                 goto done;
313                         }
314                 
315                         /* negative hard limit means no limit */
316                 }
317                 
318                 /* if no limit is required, use soft limit */
319                 if ( slimit <= 0 ) {
320                         slimit = limit->lms_s_soft;
321
322                 /* if requested limit higher than hard limit, abort */
323                 } else if ( slimit > limit->lms_s_hard ) {
324                         /* no hard limit means use soft instead */
325                         if ( limit->lms_s_hard == 0 && slimit > limit->lms_s_soft ) {
326                                 slimit = limit->lms_s_soft;
327
328                         /* positive hard limit means abort */
329                         } else if ( limit->lms_s_hard > 0 ) {
330                                 send_search_result( ps_conn, ps_op, 
331                                                 LDAP_UNWILLING_TO_PERFORM,
332                                                 NULL, NULL, NULL, NULL, 0 );
333                                 rc = 0; 
334                                 goto done;
335                         }
336                         
337                         /* negative hard limit means no limit */
338                 }
339         }
340
341         /* compute it anyway; root does not use it */
342         stoptime = ps_op->o_time + tlimit;
343
344         /* candidates = { e } */
345         candidates[0] = 1;
346         candidates[1] = entry->e_id;
347
348         /* need normalized dn below */
349         ber_dupbv( &realbase, &e->e_nname );
350
351         if ( e != &slap_entry_root ) {
352                 bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
353         }
354         e = NULL;
355
356         if ( candidates[0] == 0 ) {
357 #ifdef NEW_LOGGING
358                 LDAP_LOG ( OPERATION, RESULTS,
359                         "bdb_search: no candidates\n", 0, 0, 0 );
360 #else
361                 Debug( LDAP_DEBUG_TRACE, "bdb_search: no candidates\n",
362                         0, 0, 0 );
363 #endif
364
365                 send_search_result( ps_conn, ps_op,
366                         LDAP_SUCCESS,
367                         NULL, NULL, NULL, NULL, 0 );
368
369                 rc = 1;
370                 goto done;
371         }
372
373         /* if not root and candidates exceed to-be-checked entries, abort */
374         if ( !isroot && limit->lms_s_unchecked != -1 ) {
375                 if ( BDB_IDL_N(candidates) > (unsigned) limit->lms_s_unchecked ) {
376                         send_search_result( ps_conn, ps_op, 
377                                         LDAP_ADMINLIMIT_EXCEEDED,
378                                         NULL, NULL, NULL, NULL, 0 );
379                         rc = 1;
380                         goto done;
381                 }
382         }
383
384         lcupf.f_choice = LDAP_FILTER_AND;
385         lcupf.f_and = &csnfnot;
386         lcupf.f_next = NULL;
387
388         csnfnot.f_choice = LDAP_FILTER_NOT;
389         csnfnot.f_not = &csnfeq;
390         csnfnot.f_next = &csnfand;
391
392         csnfeq.f_choice = LDAP_FILTER_EQUALITY;
393         csnfeq.f_ava = &aa_eq;
394         csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
395         ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
396
397         csnfand.f_choice = LDAP_FILTER_AND;
398         csnfand.f_and = &csnfge;
399         csnfand.f_next = NULL;
400
401         csnfge.f_choice = LDAP_FILTER_GE;
402         csnfge.f_ava = &aa_ge;
403         csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
404         ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
405         csnfge.f_next = filter;
406
407         if ( !BDB_IDL_IS_RANGE( candidates ) ) {
408                 cursor = bdb_idl_search( candidates, entry->e_id );
409                 if ( candidates[cursor] != entry->e_id ) {
410                         rc = LDAP_SUCCESS;
411                         goto done;
412                 }
413         } else {
414                 if ( entry->e_id < BDB_IDL_RANGE_FIRST(candidates) &&
415                      entry->e_id > BDB_IDL_RANGE_LAST(candidates) ) {
416                         rc = LDAP_SUCCESS;
417                         goto done;
418                 }
419         }
420
421         id = entry->e_id;
422
423         /* check for abandon */
424         if ( ps_op->o_abandon ) {
425                 rc = 0;
426                 goto done;
427         }
428
429         /* check time limit */
430         if ( tlimit != -1 && slap_get_time() > stoptime ) {
431                 send_search_result( ps_conn, ps_op, rc = LDAP_TIMELIMIT_EXCEEDED,
432                         NULL, NULL, v2refs, NULL, nentries );
433                 goto done;
434         }
435
436         e = entry;
437
438 #ifdef BDB_SUBENTRIES
439         if ( is_entry_subentry( e ) ) {
440                 if( scope != LDAP_SCOPE_BASE ) {
441                         if(!get_subentries_visibility( ps_op )) {
442                                 /* only subentries are visible */
443                                 goto test_done;
444                         }
445
446                 } else if ( get_subentries( ps_op ) &&
447                         !get_subentries_visibility( ps_op ))
448                 {
449                         /* only subentries are visible */
450                         goto test_done;
451                 }
452
453         } else if ( get_subentries_visibility( ps_op )) {
454                 /* only subentries are visible */
455                 goto test_done;
456         }
457 #endif
458
459 #ifdef BDB_ALIASES
460         if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
461                 Entry *matched;
462                 int err;
463                 const char *text;
464                 
465                 e = deref_entry_r( be, e, &err, &matched, &text );
466
467                 if( e == NULL ) {
468                         e = matched;
469                         goto test_done;
470                 }
471
472                 if( e->e_id == id ) {
473                         /* circular loop */
474                         goto test_done;
475                 }
476
477                 /* need to skip alias which deref into scope */
478                 if( scope & LDAP_SCOPE_ONELEVEL ) {
479                         struct berval   pdn;
480                         
481                         dnParent( &e->e_nname, &pdn ):
482                         if ( ber_bvcmp( pdn, &realbase ) ) {
483                                 goto test_done;
484                         }
485
486                 } else if ( dnIsSuffix( &e->e_nname, &realbase ) ) {
487                         /* alias is within scope */
488 #ifdef NEW_LOGGING
489                         LDAP_LOG ( OPERATION, RESULTS,
490                                 "bdb_search: \"%s\" in subtree\n", e->edn, 0, 0);
491 #else
492                         Debug( LDAP_DEBUG_TRACE,
493                                 "bdb_search: \"%s\" in subtree\n",
494                                 e->e_dn, 0, 0 );
495 #endif
496                         goto test_done;
497                 }
498
499                 scopeok = 1;
500         }
501 #endif
502
503         /*
504          * if it's a referral, add it to the list of referrals. only do
505          * this for non-base searches, and don't check the filter
506          * explicitly here since it's only a candidate anyway.
507          */
508         if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
509                 is_entry_referral( e ) )
510         {
511                 struct berval   dn;
512
513                 /* check scope */
514                 if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
515                         if ( !be_issuffix( be, &e->e_nname ) ) {
516                                 dnParent( &e->e_nname, &dn );
517                                 scopeok = dn_match( &dn, &realbase );
518                         } else {
519                                 scopeok = (realbase.bv_len == 0);
520                         }
521
522                 } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
523                         scopeok = dnIsSuffix( &e->e_nname, &realbase );
524
525                 } else {
526                         scopeok = 1;
527                 }
528
529                 if( scopeok ) {
530                         BerVarray erefs = get_entry_referrals(
531                                 be, ps_conn, ps_op, e );
532                         BerVarray refs = referral_rewrite( erefs,
533                                 &e->e_name, NULL,
534                                 scope == LDAP_SCOPE_SUBTREE
535                                         ? LDAP_SCOPE_SUBTREE
536                                         : LDAP_SCOPE_BASE );
537
538                         send_search_reference( be, ps_conn, ps_op,
539                                 e, refs, NULL, &v2refs );
540
541                         ber_bvarray_free( refs );
542
543                 } else {
544 #ifdef NEW_LOGGING
545                         LDAP_LOG(OPERATION, DETAIL2, 
546                                 "bdb_search: candidate referral %ld scope not okay\n",
547                                 id, 0, 0 );
548 #else
549                         Debug( LDAP_DEBUG_TRACE,
550                                 "bdb_search: candidate referral %ld scope not okay\n",
551                                 id, 0, 0 );
552 #endif
553                 }
554
555                 goto test_done;
556         }
557
558         if ( psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
559                 rc = test_filter( be, ps_conn, ps_op, e, &lcupf );
560         } else {
561                 rc = LDAP_COMPARE_TRUE;
562         }
563
564         if ( rc == LDAP_COMPARE_TRUE ) {
565                 struct berval   dn;
566
567                 /* check scope */
568                 if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
569                         if ( be_issuffix( be, &e->e_nname ) ) {
570                                 scopeok = (realbase.bv_len == 0);
571                         } else {
572                                 dnParent( &e->e_nname, &dn );
573                                 scopeok = dn_match( &dn, &realbase );
574                         }
575
576                 } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
577                         scopeok = dnIsSuffix( &e->e_nname, &realbase );
578
579                 } else {
580                         scopeok = 1;
581                 }
582
583                 if ( scopeok ) {
584                         /* check size limit */
585                         if ( --slimit == -1 ) {
586                                 send_search_result( ps_conn, ps_op,
587                                         rc = LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
588                                         v2refs, NULL, nentries );
589                                 goto done;
590                         }
591
592                         if (e) {
593                                 int result;
594                                 
595 #if 0   /* noop is masked SLAP_CTRL_UPDATE */
596                                 if( ps_op->o_noop ) {
597                                         result = 0;
598                                 } else
599 #endif
600                                 {
601                                         if ( psearch_type == LCUP_PSEARCH_BY_ADD ||
602                                              psearch_type == LCUP_PSEARCH_BY_DELETE ||
603                                              psearch_type == LCUP_PSEARCH_BY_MODIFY ||
604                                              psearch_type == LCUP_PSEARCH_BY_SCOPEOUT ) {
605                                                 Attribute* a;
606                                                 int ret;
607                                                 int res;
608                                                 const char *text = NULL;
609                                                 LDAPControl *ctrls[2];
610                                                 struct berval *bv;
611
612                                                 BerElement *ber = ber_alloc_t( LBER_USE_DER );
613
614                                                 if ( ber == NULL ) {
615 #ifdef NEW_LOGGING
616                                                         LDAP_LOG ( OPERATION, RESULTS, 
617                                                                 "bdb_search: ber_alloc_t failed\n",
618                                                                 0, 0, 0 );
619 #else
620                                                         Debug( LDAP_DEBUG_TRACE,
621                                                                 "bdb_search: ber_alloc_t failed\n",
622                                                                 0, 0, 0 );
623 #endif
624                                                         send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
625                                                                 NULL, "internal error", NULL, NULL );
626                                                         goto done;
627                                                 }
628
629                                                 LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count++;
630
631                                                 ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
632                                                 ctrls[1] = NULL;
633
634                                                 if ( LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count % ps_op->o_clientupdate_interval == 0 ) {
635                                                         /* Send cookie */
636                                                         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
637                                                                 AttributeDescription *desc = a->a_desc;
638                                                                 if ( desc == slap_schema.si_ad_entryCSN ) {
639                                                                         ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
640                                                                         if ( latest_entrycsn_bv.bv_val == NULL ) {
641                                                                                 ber_dupbv( &latest_entrycsn_bv, &entrycsn_bv );
642                                                                         } else {
643                                                                                 res = value_match( &ret, desc,
644                                                                                         desc->ad_type->sat_ordering,
645                                                                                         SLAP_MR_ASSERTION_SYNTAX_MATCH,
646                                                                                         &entrycsn_bv, &latest_entrycsn_bv, &text );
647                                                                                 if ( res != LDAP_SUCCESS ) {
648                                                                                         ret = 0;
649 #ifdef NEW_LOGGING
650                                                                                         LDAP_LOG ( OPERATION, RESULTS, 
651                                                                                                 "bdb_search: value_match failed\n",
652                                                                                                 0, 0, 0 );
653 #else
654                                                                                         Debug( LDAP_DEBUG_TRACE,
655                                                                                                 "bdb_search: value_match failed\n",
656                                                                                                 0, 0, 0 );
657 #endif
658                                                                                 }
659
660                                                                                 if ( ret > 0 ) {
661                                                                                         ch_free( latest_entrycsn_bv.bv_val );
662                                                                                         latest_entrycsn_bv.bv_val = NULL;
663                                                                                         ber_dupbv( &latest_entrycsn_bv,
664                                                                                                 &entrycsn_bv );
665                                                                                 }
666                                                                         }
667                                                                 }
668                                                         }
669
670                                                         if ( psearch_type != LCUP_PSEARCH_BY_DELETE || psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
671                                                                 ber_printf( ber,
672                                                                         "{bb{sON}N}",
673                                                                         SLAP_LCUP_STATE_UPDATE_FALSE,
674                                                                         SLAP_LCUP_ENTRY_DELETED_FALSE,
675                                                                         LCUP_COOKIE_OID, &entrycsn_bv );
676                                                         } else {
677                                                                 ber_printf( ber,
678                                                                         "{bb{sON}N}",
679                                                                         SLAP_LCUP_STATE_UPDATE_FALSE,
680                                                                         SLAP_LCUP_ENTRY_DELETED_TRUE,
681                                                                         LCUP_COOKIE_OID, &entrycsn_bv );
682                                                         }
683
684                                                         ch_free( entrycsn_bv.bv_val );
685                                                         entrycsn_bv.bv_val = NULL;
686
687                                                 } else {
688                                                         /* Do not send cookie */
689                                                         if ( psearch_type != LCUP_PSEARCH_BY_DELETE || psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
690                                                                 ber_printf( ber,
691                                                                         "{bbN}",
692                                                                         SLAP_LCUP_STATE_UPDATE_FALSE,
693                                                                         SLAP_LCUP_ENTRY_DELETED_FALSE );
694                                                         } else {
695                                                                 ber_printf( ber,
696                                                                         "{bbN}",
697                                                                         SLAP_LCUP_STATE_UPDATE_FALSE,
698                                                                         SLAP_LCUP_ENTRY_DELETED_TRUE );
699                                                         }
700                                                 }
701
702                                                 ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
703                                                 ctrls[0]->ldctl_iscritical = ps_op->o_clientupdate;
704                                                 ret = ber_flatten( ber, &bv );
705
706                                                 if ( ret < 0 ) {
707 #ifdef NEW_LOGGING
708                                                         LDAP_LOG ( OPERATION, RESULTS, 
709                                                                 "bdb_search: ber_flatten failed\n",
710                                                                 0, 0, 0 );
711 #else
712                                                         Debug( LDAP_DEBUG_TRACE,
713                                                                 "bdb_search: ber_flatten failed\n",
714                                                                 0, 0, 0 );
715 #endif
716                                                         send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
717                                                                 NULL, "internal error", NULL, NULL );
718                                                         goto done;
719                                                 }
720
721                                                 ber_dupbv( &ctrls[0]->ldctl_value, bv );
722                                                 
723                                                 result = send_search_entry( be, ps_conn, ps_op,
724                                                         e, attrs, attrsonly, ctrls);
725
726                                                 ch_free( ctrls[0]->ldctl_value.bv_val );
727                                                 ch_free( ctrls[0] );
728                                                 ber_free( ber, 1 );
729                                                 ber_bvfree( bv );
730
731                                                 if ( psearch_type == LCUP_PSEARCH_BY_MODIFY ) {
732                                                         struct psid_entry* psid_e;
733                                                         LDAP_LIST_FOREACH( psid_e, &op->premodify_list, link) {
734                                                                 if (psid_e->ps == LDAP_LIST_FIRST(&ps_op->psearch_spec)) {
735                                                                         LDAP_LIST_REMOVE(psid_e, link);
736                                                                         break;
737                                                                 }
738                                                         }
739                                                         if (psid_e != NULL) 
740                                                                 free (psid_e);
741                                                 }
742                                         } else if ( psearch_type == LCUP_PSEARCH_BY_PREMODIFY ) {
743                                                 struct psid_entry* psid_e;
744                                                 psid_e = (struct psid_entry *) calloc (1, sizeof (struct psid_entry));
745                                                 psid_e->ps = LDAP_LIST_FIRST(&ps_op->psearch_spec);
746                                                 LDAP_LIST_INSERT_HEAD( &op->premodify_list, psid_e, link );
747                                         }
748                                         else
749                                         {
750                                                 printf("Error !\n");
751                                         }
752                                 }
753
754                                 switch (result) {
755                                 case 0:         /* entry sent ok */
756                                         nentries++;
757                                         break;
758                                 case 1:         /* entry not sent */
759                                         break;
760                                 case -1:        /* connection closed */
761                                         rc = LDAP_OTHER;
762                                         goto done;
763                                 }
764                         }
765                 } else {
766 #ifdef NEW_LOGGING
767                         LDAP_LOG ( OPERATION, RESULTS,
768                                 "bdb_search: %ld scope not okay\n", (long) id, 0, 0);
769 #else
770                         Debug( LDAP_DEBUG_TRACE,
771                                 "bdb_search: %ld scope not okay\n",
772                                 (long) id, 0, 0 );
773 #endif
774                 }
775         } else {
776 #ifdef NEW_LOGGING
777                 LDAP_LOG ( OPERATION, RESULTS,
778                         "bdb_search: %ld does match filter\n", (long) id, 0, 0);
779 #else
780                 Debug( LDAP_DEBUG_TRACE,
781                         "bdb_search: %ld does match filter\n",
782                         (long) id, 0, 0 );
783 #endif
784         }
785
786 test_done:
787         rc = LDAP_SUCCESS;
788
789 done:
790         if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) {
791                 ch_free( csnfeq.f_av_value.bv_val );
792         }
793         
794         if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) {
795                 ch_free( csnfge.f_av_value.bv_val );
796         }
797
798         LOCK_ID_FREE (bdb->bi_dbenv, locker );
799
800         if( v2refs ) ber_bvarray_free( v2refs );
801         if( realbase.bv_val ) ch_free( realbase.bv_val );
802
803         return rc;
804 }
805
806 #endif /* LDAP_CLIENT_UPDATE */