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