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