]> git.sur5r.net Git - openldap/blob - servers/slapd/syncrepl.c
ITS #3131 - propagate SSF to syncrepl operation
[openldap] / servers / slapd / syncrepl.c
1 /* syncrepl.c -- Replication Engine which uses the LDAP Sync protocol */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2004 The OpenLDAP Foundation.
6  * Portions Copyright 2003 by IBM Corporation.
7  * Portions Copyright 2003 by Howard Chu, Symas Corporation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18
19 #include "portable.h"
20
21 #include <stdio.h>
22
23 #include <ac/string.h>
24 #include <ac/socket.h>
25
26 #include "ldap_pvt.h"
27 #include "lutil.h"
28 #include "slap.h"
29 #include "lutil_ldap.h"
30
31 #include "ldap_rq.h"
32
33 #define SYNCREPL_STR    "syncreplxxx"
34 #define CN_STR  "cn="
35
36 static const struct berval slap_syncrepl_bvc = BER_BVC(SYNCREPL_STR);
37 static const struct berval slap_syncrepl_cn_bvc = BER_BVC(CN_STR SYNCREPL_STR);
38
39 static int syncuuid_cmp( const void *, const void * );
40 static void avl_ber_bvfree( void * );
41 static void syncrepl_del_nonpresent( Operation *, syncinfo_t * );
42
43 /* callback functions */
44 static int dn_callback( struct slap_op *, struct slap_rep * );
45 static int nonpresent_callback( struct slap_op *, struct slap_rep * );
46 static int null_callback( struct slap_op *, struct slap_rep * );
47
48 static AttributeDescription *sync_descs[4];
49
50 struct runqueue_s syncrepl_rq;
51
52 void
53 init_syncrepl(syncinfo_t *si)
54 {
55         int i, j, k, n;
56         char **tmp;
57
58         if ( !sync_descs[0] ) {
59                 sync_descs[0] = slap_schema.si_ad_objectClass;
60                 sync_descs[1] = slap_schema.si_ad_structuralObjectClass;
61                 sync_descs[2] = slap_schema.si_ad_entryCSN;
62                 sync_descs[3] = NULL;
63         }
64
65         for ( n = 0; si->si_attrs[ n ] != NULL; n++ ) /* empty */;
66
67         if ( n ) {
68                 /* Delete Attributes */
69                 for ( i = 0; sync_descs[i] != NULL; i++ ) {
70                         for ( j = 0; si->si_attrs[j] != NULL; j++ ) {
71                                 if ( strcmp( si->si_attrs[j], sync_descs[i]->ad_cname.bv_val )
72                                         == 0 )
73                                 {
74                                         ch_free( si->si_attrs[j] );
75                                         for ( k = j; si->si_attrs[k] != NULL; k++ ) {
76                                                 si->si_attrs[k] = si->si_attrs[k+1];
77                                         }
78                                 }
79                         }
80                 }
81                 for ( n = 0; si->si_attrs[ n ] != NULL; n++ ) /* empty */;
82                 tmp = ( char ** ) ch_realloc( si->si_attrs, (n + 4)*sizeof( char * ));
83                 if ( tmp == NULL ) {
84 #ifdef NEW_LOGGING
85                         LDAP_LOG( OPERATION, ERR, "out of memory\n", 0,0,0 );
86 #else
87                         Debug( LDAP_DEBUG_ANY, "out of memory\n", 0,0,0 );
88 #endif
89                 }
90
91         } else {
92                 tmp = ( char ** ) ch_realloc( si->si_attrs, 5 * sizeof( char * ));
93                 if ( tmp == NULL ) {
94 #ifdef NEW_LOGGING
95                         LDAP_LOG( OPERATION, ERR, "out of memory\n", 0,0,0 );
96 #else
97                         Debug( LDAP_DEBUG_ANY, "out of memory\n", 0,0,0 );
98 #endif
99                 }
100                 tmp[ n++ ] = ch_strdup( "*" );
101         }
102         
103         si->si_attrs = tmp;
104
105         /* Add Attributes */
106         for ( i = 0; sync_descs[ i ] != NULL; i++ ) {
107                 si->si_attrs[ n++ ] = ch_strdup ( sync_descs[i]->ad_cname.bv_val );
108                 si->si_attrs[ n ] = NULL;
109         }
110 }
111
112 static int
113 ldap_sync_search(
114         syncinfo_t *si,
115         void *ctx )
116 {
117         BerElementBuffer berbuf;
118         BerElement *ber = (BerElement *)&berbuf;
119         LDAPControl c[2], *ctrls[3];
120         struct timeval timeout;
121         ber_int_t       msgid;
122         int rc;
123
124         /* setup LDAP SYNC control */
125         ber_init2( ber, NULL, LBER_USE_DER );
126         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &ctx );
127
128         if ( si->si_syncCookie.octet_str &&
129                 si->si_syncCookie.octet_str[0].bv_val )
130         {
131                 ber_printf( ber, "{eO}",
132                         abs(si->si_type),
133                         &si->si_syncCookie.octet_str[0] );
134         } else {
135                 ber_printf( ber, "{e}",
136                         abs(si->si_type) );
137         }
138
139         if ( (rc = ber_flatten2( ber, &c[0].ldctl_value, 0 )) == LBER_ERROR ) {
140                 ber_free_buf( ber );
141                 return rc;
142         }
143
144         c[0].ldctl_oid = LDAP_CONTROL_SYNC;
145         c[0].ldctl_iscritical = si->si_type < 0;
146         ctrls[0] = &c[0];
147
148         if ( si->si_authzId ) {
149                 c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
150                 ber_str2bv( si->si_authzId, 0, 0, &c[1].ldctl_value );
151                 c[1].ldctl_iscritical = 1;
152                 ctrls[1] = &c[1];
153                 ctrls[2] = NULL;
154         } else {
155                 ctrls[1] = NULL;
156         }
157
158         timeout.tv_sec = si->si_tlimit > 0 ? si->si_tlimit : 1;
159         timeout.tv_usec = 0;
160
161         rc = ldap_search_ext( si->si_ld, si->si_base.bv_val, si->si_scope,
162                 si->si_filterstr.bv_val, si->si_attrs, si->si_attrsonly,
163                 ctrls, NULL, si->si_tlimit < 0 ? NULL : &timeout,
164                 si->si_slimit, &msgid );
165         ber_free_buf( ber );
166         return rc;
167 }
168
169 static int
170 do_syncrep1(
171         Operation *op,
172         syncinfo_t *si )
173 {
174         int     rc;
175         int cmdline_cookie_found = 0;
176
177         char syncrepl_cbuf[sizeof(CN_STR SYNCREPL_STR)];
178         struct berval syncrepl_cn_bv;
179         struct sync_cookie      *sc = NULL;
180         struct sync_cookie      syncCookie = { NULL, -1, NULL };
181         struct berval   *psub;
182
183         psub = &si->si_be->be_nsuffix[0];
184
185         /* Init connection to master */
186         rc = ldap_initialize( &si->si_ld, si->si_provideruri );
187         if ( rc != LDAP_SUCCESS ) {
188 #ifdef NEW_LOGGING
189                 LDAP_LOG( OPERATION, ERR,
190                         "do_syncrep1: ldap_initialize failed (%s)\n",
191                         si->si_provideruri, 0, 0 );
192 #else
193                 Debug( LDAP_DEBUG_ANY,
194                         "do_syncrep1: ldap_initialize failed (%s)\n",
195                         si->si_provideruri, 0, 0 );
196 #endif
197                 return rc;
198         }
199
200         op->o_protocol = LDAP_VERSION3;
201         ldap_set_option( si->si_ld, LDAP_OPT_PROTOCOL_VERSION, &op->o_protocol );
202
203         /* Bind to master */
204
205         if ( si->si_tls ) {
206                 rc = ldap_start_tls_s( si->si_ld, NULL, NULL );
207                 if( rc != LDAP_SUCCESS ) {
208 #ifdef NEW_LOGGING
209                         LDAP_LOG ( OPERATION, ERR, "do_syncrep1: "
210                                 "%s: ldap_start_tls failed (%d)\n",
211                                 si->si_tls == SYNCINFO_TLS_CRITICAL ? "Error" : "Warning",
212                                 rc, 0 );
213 #else
214                         Debug( LDAP_DEBUG_ANY,
215                                 "%s: ldap_start_tls failed (%d)\n",
216                                 si->si_tls == SYNCINFO_TLS_CRITICAL ? "Error" : "Warning",
217                                 rc, 0 );
218 #endif
219                         if( si->si_tls == SYNCINFO_TLS_CRITICAL ) goto done;
220                 }
221         }
222
223         if ( si->si_bindmethod == LDAP_AUTH_SASL ) {
224 #ifdef HAVE_CYRUS_SASL
225                 void *defaults;
226
227                 if ( si->si_secprops != NULL ) {
228                         rc = ldap_set_option( si->si_ld,
229                                 LDAP_OPT_X_SASL_SECPROPS, si->si_secprops);
230
231                         if( rc != LDAP_OPT_SUCCESS ) {
232 #ifdef NEW_LOGGING
233                                 LDAP_LOG ( OPERATION, ERR, "do_bind: Error: "
234                                         "ldap_set_option(%s,SECPROPS,\"%s\") failed!\n",
235                                         si->si_provideruri, si->si_secprops, 0 );
236 #else
237                                 Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
238                                         "(%s,SECPROPS,\"%s\") failed!\n",
239                                         si->si_provideruri, si->si_secprops, 0 );
240 #endif
241                                 goto done;
242                         }
243                 }
244
245                 defaults = lutil_sasl_defaults( si->si_ld, si->si_saslmech,
246                         si->si_realm, si->si_authcId, si->si_passwd, si->si_authzId );
247
248                 rc = ldap_sasl_interactive_bind_s( si->si_ld,
249                                 si->si_binddn,
250                                 si->si_saslmech,
251                                 NULL, NULL,
252                                 LDAP_SASL_QUIET,
253                                 lutil_sasl_interact,
254                                 defaults );
255
256                 lutil_sasl_freedefs( defaults );
257
258                 /* FIXME: different error behaviors according to
259                  *      1) return code
260                  *      2) on err policy : exit, retry, backoff ...
261                  */
262                 if ( rc != LDAP_SUCCESS ) {
263 #ifdef NEW_LOGGING
264                         LDAP_LOG ( OPERATION, ERR, "do_syncrep1: "
265                                 "ldap_sasl_interactive_bind_s failed (%d)\n",
266                                 rc, 0, 0 );
267 #else
268                         Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
269                                 "ldap_sasl_interactive_bind_s failed (%d)\n",
270                                 rc, 0, 0 );
271 #endif
272
273                         /* FIXME (see above comment) */
274                         /* if Kerberos credentials cache is not active, retry */
275                         if ( strcmp( si->si_saslmech, "GSSAPI" ) == 0 &&
276                                 rc == LDAP_LOCAL_ERROR )
277                         {
278                                 rc = LDAP_SERVER_DOWN;
279                         }
280
281                         goto done;
282                 }
283 #else /* HAVE_CYRUS_SASL */
284                 /* Should never get here, we trapped this at config time */
285                 assert(0);
286                 fprintf( stderr, "not compiled with SASL support\n" );
287                 rc = LDAP_OTHER;
288                 goto done;
289 #endif
290
291         } else {
292                 rc = ldap_bind_s( si->si_ld,
293                         si->si_binddn, si->si_passwd, si->si_bindmethod );
294                 if ( rc != LDAP_SUCCESS ) {
295 #ifdef NEW_LOGGING
296                         LDAP_LOG ( OPERATION, ERR, "do_syncrep1: "
297                                 "ldap_bind_s failed (%d)\n", rc, 0, 0 );
298 #else
299                         Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
300                                 "ldap_bind_s failed (%d)\n", rc, 0, 0 );
301 #endif
302                         goto done;
303                 }
304         }
305
306         /* set SSF for local authorization */
307         ldap_get_option( si->si_ld, LDAP_OPT_X_SASL_SSF, &op->o_ssf );
308
309         /* get syncrepl cookie of shadow replica from subentry */
310         assert( si->si_rid < 1000 );
311         syncrepl_cn_bv.bv_val = syncrepl_cbuf;
312         syncrepl_cn_bv.bv_len = snprintf(syncrepl_cbuf, sizeof(syncrepl_cbuf),
313                 CN_STR "syncrepl%ld", si->si_rid );
314         build_new_dn( &op->o_req_ndn, psub, &syncrepl_cn_bv, op->o_tmpmemctx );
315         op->o_req_dn = op->o_req_ndn;
316
317         LDAP_STAILQ_FOREACH( sc, &slap_sync_cookie, sc_next ) {
318                 if ( si->si_rid == sc->rid ) {
319                         cmdline_cookie_found = 1;
320                         break;
321                 }
322         }
323
324         if ( cmdline_cookie_found ) {
325                 /* cookie is supplied in the command line */
326                 BerVarray cookie = NULL;
327                 struct berval cookie_bv;
328
329                 LDAP_STAILQ_REMOVE( &slap_sync_cookie, sc, sync_cookie, sc_next );
330                 slap_sync_cookie_free( &si->si_syncCookie, 0 );
331
332                 /* read stored cookie if it exists */
333                 backend_attribute( op, NULL, &op->o_req_ndn,
334                         slap_schema.si_ad_syncreplCookie, &cookie );
335
336                 if ( !cookie ) {
337                         /* no stored cookie */
338                         if ( sc->ctxcsn == NULL ||
339                                  sc->ctxcsn->bv_val == NULL ) {
340                                 /* if cmdline cookie does not have ctxcsn */
341                                 /* component, set it to an initial value */
342                                 slap_init_sync_cookie_ctxcsn( sc );
343                         }
344                         slap_dup_sync_cookie( &si->si_syncCookie, sc );
345                         slap_sync_cookie_free( sc, 1 );
346                         sc = NULL;
347
348                 } else {
349                         /* stored cookie */
350                         struct berval newcookie = BER_BVNULL;
351                         ber_dupbv( &cookie_bv, &cookie[0] );
352                         ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv );
353                         slap_parse_sync_cookie( &si->si_syncCookie );
354                         ber_bvarray_free( si->si_syncCookie.octet_str );
355                         si->si_syncCookie.octet_str = NULL;
356                         ber_bvarray_free_x( cookie, op->o_tmpmemctx );
357                         if ( sc->sid != -1 ) {
358                                 /* command line cookie wins */
359                                 si->si_syncCookie.sid = sc->sid;
360                         }
361                         if ( sc->ctxcsn != NULL ) {
362                                 /* command line cookie wins */
363                                 if ( si->si_syncCookie.ctxcsn ) {
364                                         ber_bvarray_free( si->si_syncCookie.ctxcsn );
365                                         si->si_syncCookie.ctxcsn = NULL;
366                                 }
367                                 ber_dupbv( &cookie_bv, &sc->ctxcsn[0] );
368                                 ber_bvarray_add( &si->si_syncCookie.ctxcsn, &cookie_bv );
369                         }
370                         if ( sc->rid != -1 ) {
371                                 /* command line cookie wins */
372                                 si->si_syncCookie.rid = sc->rid;
373                         }
374                         slap_sync_cookie_free( sc, 1 );
375                         sc = NULL;
376                         slap_compose_sync_cookie( NULL, &newcookie,
377                                         &si->si_syncCookie.ctxcsn[0],
378                                         si->si_syncCookie.sid, si->si_syncCookie.rid );
379                         ber_bvarray_add( &si->si_syncCookie.octet_str, &newcookie );
380                 }
381
382         } else {
383                 /* no command line cookie is specified */
384                 if ( si->si_syncCookie.octet_str == NULL ) {
385                         BerVarray cookie = NULL;
386                         struct berval cookie_bv;
387                         /* try to read stored cookie */
388                         backend_attribute( op, NULL, &op->o_req_ndn,
389                                 slap_schema.si_ad_syncreplCookie, &cookie );
390                         if ( cookie ) {
391                                 ber_dupbv( &cookie_bv, &cookie[0] );
392                                 ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv );
393                                 slap_parse_sync_cookie( &si->si_syncCookie );
394                                 ber_bvarray_free_x( cookie, op->o_tmpmemctx );
395                         }
396                 }
397         }
398
399         rc = ldap_sync_search( si, op->o_tmpmemctx );
400
401         if( rc != LDAP_SUCCESS ) {
402 #ifdef NEW_LOGGING
403                 LDAP_LOG ( OPERATION, ERR, "do_syncrep1: "
404                         "ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 );
405 #else
406                 Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
407                         "ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 );
408 #endif
409         }
410
411 done:
412         if ( rc ) {
413                 if ( si->si_ld ) {
414                         ldap_unbind( si->si_ld );
415                         si->si_ld = NULL;
416                 }
417         }
418
419         return rc;
420 }
421
422 static int
423 do_syncrep2(
424         Operation *op,
425         syncinfo_t *si )
426 {
427         LDAPControl     **rctrls = NULL;
428         LDAPControl     *rctrlp;
429
430         BerElementBuffer berbuf;
431         BerElement      *ber = (BerElement *)&berbuf;
432
433         LDAPMessage     *res = NULL;
434         LDAPMessage     *msg = NULL;
435
436         char            *retoid = NULL;
437         struct berval   *retdata = NULL;
438
439         Entry           *entry = NULL;
440
441         int             syncstate;
442         struct berval   syncUUID = BER_BVNULL;
443         struct sync_cookie      syncCookie = { NULL, -1, NULL };
444         struct sync_cookie      syncCookie_req = { NULL, -1, NULL };
445         struct berval           cookie = BER_BVNULL;
446
447         int     rc, err, i;
448         ber_len_t       len;
449
450         int rc_efree = 1;
451
452         struct berval   *psub;
453         Modifications   *modlist = NULL;
454
455         const char              *text;
456         int                             match;
457
458         struct timeval *tout_p = NULL;
459         struct timeval tout = { 0, 0 };
460
461         int             refreshDeletes = 0;
462         int             refreshDone = 1;
463         BerVarray syncUUIDs = NULL;
464         ber_tag_t si_tag;
465
466         if ( slapd_shutdown ) {
467                 rc = -2;
468                 goto done;
469         }
470
471         ber_init2( ber, NULL, LBER_USE_DER );
472         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
473
474 #ifdef NEW_LOGGING
475         LDAP_LOG ( OPERATION, DETAIL1, "do_syncrep2\n", 0, 0, 0 );
476 #else
477         Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2\n", 0, 0, 0 );
478 #endif
479
480         psub = &si->si_be->be_nsuffix[0];
481
482         slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie );
483
484         if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
485                 tout_p = &tout;
486         } else {
487                 tout_p = NULL;
488         }
489
490         while (( rc = ldap_result( si->si_ld, LDAP_RES_ANY, LDAP_MSG_ONE,
491                 tout_p, &res )) > 0 )
492         {
493                 if ( slapd_shutdown ) {
494                         rc = -2;
495                         goto done;
496                 }
497                 for( msg = ldap_first_message( si->si_ld, res );
498                         msg != NULL;
499                         msg = ldap_next_message( si->si_ld, msg ) )
500                 {
501                         switch( ldap_msgtype( msg ) ) {
502                         case LDAP_RES_SEARCH_ENTRY:
503                                 ldap_get_entry_controls( si->si_ld, msg, &rctrls );
504                                 /* we can't work without the control */
505                                 if ( !rctrls ) {
506                                         rc = -1;
507                                         goto done;
508                                 }
509                                 rctrlp = *rctrls;
510                                 ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
511                                 ber_scanf( ber, "{em" /*"}"*/, &syncstate, &syncUUID );
512                                 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
513                                         ber_scanf( ber, /*"{"*/ "m}", &cookie );
514                                         if ( cookie.bv_val ) {
515                                                 struct berval tmp_bv;
516                                                 ber_dupbv( &tmp_bv, &cookie );
517                                                 ber_bvarray_add( &syncCookie.octet_str, &tmp_bv );
518                                         }
519                                         if ( syncCookie.octet_str &&
520                                                         syncCookie.octet_str[0].bv_val )
521                                                 slap_parse_sync_cookie( &syncCookie );
522                                 }
523                                 if ( syncrepl_message_to_entry( si, op, msg,
524                                         &modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
525                                         rc_efree = syncrepl_entry( si, op, entry, modlist,
526                                                 syncstate, &syncUUID, &syncCookie_req );
527                                         if ( syncCookie.octet_str &&
528                                                 syncCookie.octet_str[0].bv_val )
529                                         {
530                                                 syncrepl_updateCookie( si, op, psub, &syncCookie );
531                                         }
532                                 }
533                                 ldap_controls_free( rctrls );
534                                 if ( modlist ) {
535                                         slap_mods_free( modlist );
536                                 }
537                                 if ( rc_efree && entry ) {
538                                         entry_free( entry );
539                                         entry = NULL;
540                                 }
541                                 break;
542
543                         case LDAP_RES_SEARCH_REFERENCE:
544 #ifdef NEW_LOGGING
545                                 LDAP_LOG( OPERATION, ERR,
546                                         "do_syncrep2 : reference received\n", 0, 0, 0 );
547 #else
548                                 Debug( LDAP_DEBUG_ANY,
549                                         "do_syncrep2 : reference received\n", 0, 0, 0 );
550 #endif
551                                 break;
552
553                         case LDAP_RES_SEARCH_RESULT:
554                                 ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL,
555                                         &rctrls, 0 );
556                                 if ( rctrls ) {
557                                         rctrlp = *rctrls;
558                                         ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
559
560                                         ber_scanf( ber, "{" /*"}"*/);
561                                         if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
562                                                 ber_scanf( ber, "m", &cookie );
563                                                 if ( cookie.bv_val ) {
564                                                         struct berval tmp_bv;
565                                                         ber_dupbv( &tmp_bv, &cookie );
566                                                         ber_bvarray_add( &syncCookie.octet_str, &tmp_bv);
567                                                 }
568                                                 if ( syncCookie.octet_str &&
569                                                         syncCookie.octet_str[0].bv_val )
570                                                 {
571                                                         slap_parse_sync_cookie( &syncCookie );
572                                                 }
573                                         }
574                                         if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES )
575                                         {
576                                                 ber_scanf( ber, "b", &refreshDeletes );
577                                         }
578                                         ber_scanf( ber, /*"{"*/ "}" );
579                                 }
580                                 if ( syncCookie_req.ctxcsn == NULL ) {
581                                         match = -1;
582                                 } else if ( syncCookie.ctxcsn == NULL ) {
583                                         match = 1;
584                                 } else {
585                                         value_match( &match, slap_schema.si_ad_entryCSN,
586                                                 slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
587                                                 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
588                                                 &syncCookie_req.ctxcsn[0], &syncCookie.ctxcsn[0],
589                                                 &text );
590                                 }
591                                 if ( syncCookie.octet_str && syncCookie.octet_str->bv_val &&
592                                         match < 0 && err == LDAP_SUCCESS )
593                                 {
594                                         syncrepl_updateCookie( si, op, psub, &syncCookie );
595                                 }
596                                 if ( rctrls ) {
597                                         ldap_controls_free( rctrls );
598                                 }
599                                 if (si->si_type != LDAP_SYNC_REFRESH_AND_PERSIST) {
600                                         /* FIXME : different error behaviors according to
601                                          *      1) err code : LDAP_BUSY ...
602                                          *      2) on err policy : stop service, stop sync, retry
603                                          */
604                                         if ( refreshDeletes == 0 && match < 0 &&
605                                                 err == LDAP_SUCCESS )
606                                         {
607                                                 syncrepl_del_nonpresent( op, si );
608                                         } else {
609                                                 avl_free( si->si_presentlist, avl_ber_bvfree );
610                                                 si->si_presentlist = NULL;
611                                         }
612                                 }
613                                 rc = -2;
614                                 goto done;
615                                 break;
616
617                         case LDAP_RES_INTERMEDIATE:
618                                 rc = ldap_parse_intermediate( si->si_ld, msg,
619                                         &retoid, &retdata, NULL, 0 );
620                                 if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) {
621                                         int             si_refreshDelete = 0;
622                                         int             si_refreshPresent = 0;
623                                         ber_init2( ber, retdata, LBER_USE_DER );
624
625                                         switch ( si_tag = ber_peek_tag( ber, &len )) {
626                                         ber_tag_t tag;
627                                         case LDAP_TAG_SYNC_NEW_COOKIE:
628                                                 ber_scanf( ber, "tm", &tag, &cookie );
629                                                 break;
630                                         case LDAP_TAG_SYNC_REFRESH_DELETE:
631                                                 si_refreshDelete = 1;
632                                         case LDAP_TAG_SYNC_REFRESH_PRESENT:
633                                                 si_refreshPresent = 1;
634                                                 ber_scanf( ber, "t{" /*"}"*/, &tag );
635                                                 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE )
636                                                 {
637                                                         ber_scanf( ber, "m", &cookie );
638                                                         if ( cookie.bv_val ) {
639                                                                 struct berval tmp_bv;
640                                                                 ber_dupbv( &tmp_bv, &cookie );
641                                                                 ber_bvarray_add( &syncCookie.octet_str,
642                                                                         &tmp_bv);
643                                                         }
644                                                         if ( syncCookie.octet_str &&
645                                                                 syncCookie.octet_str[0].bv_val )
646                                                         {
647                                                                 slap_parse_sync_cookie( &syncCookie );
648                                                         }
649                                                 }
650                                                 if ( ber_peek_tag( ber, &len ) ==
651                                                         LDAP_TAG_REFRESHDONE )
652                                                 {
653                                                         ber_scanf( ber, "b", &refreshDone );
654                                                 }
655                                                 ber_scanf( ber, /*"{"*/ "}" );
656                                                 break;
657                                         case LDAP_TAG_SYNC_ID_SET:
658                                                 ber_scanf( ber, "t{" /*"}"*/, &tag );
659                                                 if ( ber_peek_tag( ber, &len ) ==
660                                                         LDAP_TAG_SYNC_COOKIE )
661                                                 {
662                                                         ber_scanf( ber, "m", &cookie );
663                                                         if ( cookie.bv_val ) {
664                                                                 struct berval tmp_bv;
665                                                                 ber_dupbv( &tmp_bv, &cookie );
666                                                                 ber_bvarray_add( &syncCookie.octet_str,
667                                                                         &tmp_bv );
668                                                         }
669                                                         if ( syncCookie.octet_str &&
670                                                                 syncCookie.octet_str[0].bv_val )
671                                                         {
672                                                                 slap_parse_sync_cookie( &syncCookie );
673                                                         }
674                                                 }
675                                                 if ( ber_peek_tag( ber, &len ) ==
676                                                         LDAP_TAG_REFRESHDELETES )
677                                                 {
678                                                         ber_scanf( ber, "b", &refreshDeletes );
679                                                 }
680                                                 ber_scanf( ber, "[W]", &syncUUIDs );
681                                                 ber_scanf( ber, /*"{"*/ "}" );
682                                                 for ( i = 0; syncUUIDs[i].bv_val; i++ ) {
683                                                         struct berval *syncuuid_bv;
684                                                         syncuuid_bv = ber_dupbv( NULL, &syncUUIDs[i] );
685                                                         avl_insert( &si->si_presentlist,
686                                                                 (caddr_t) syncuuid_bv,
687                                                                 syncuuid_cmp, avl_dup_error );
688                                                 }
689                                                 ber_memfree_x( syncUUIDs, op->o_tmpmemctx );
690                                                 break;
691                                         default:
692 #ifdef NEW_LOGGING
693                                         LDAP_LOG( OPERATION, ERR,
694                                                 "do_syncrep2 : unknown syncinfo tag (%ld)\n",
695                                                 (long) si_tag, 0, 0 );
696 #else
697                                         Debug( LDAP_DEBUG_ANY,
698                                                 "do_syncrep2 : unknown syncinfo tag (%ld)\n",
699                                                 (long) si_tag, 0, 0 );
700 #endif
701                                                 ldap_memfree( retoid );
702                                                 ber_bvfree( retdata );
703                                                 continue;
704                                         }
705
706                                         if ( syncCookie_req.ctxcsn == NULL ) {
707                                                 match = -1;
708                                         } else if ( syncCookie.ctxcsn == NULL ) {
709                                                 match = 1;
710                                         } else {
711                                                 value_match( &match, slap_schema.si_ad_entryCSN,
712                                                         slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
713                                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
714                                                         &syncCookie_req.ctxcsn[0],
715                                                         &syncCookie.ctxcsn[0], &text );
716                                         }
717
718                                         if ( syncCookie.ctxcsn && syncCookie.ctxcsn[0].bv_val &&
719                                                 match < 0 )
720                                         {
721                                                 syncrepl_updateCookie( si, op, psub, &syncCookie);
722                                         }
723
724                                         if ( si_refreshPresent == 1 ) {
725                                                 if ( match < 0 ) {
726                                                         syncrepl_del_nonpresent( op, si );
727                                                 }
728                                         } 
729
730                                         ldap_memfree( retoid );
731                                         ber_bvfree( retdata );
732                                         break;
733
734                                 } else {
735 #ifdef NEW_LOGGING
736                                         LDAP_LOG( OPERATION, ERR, "do_syncrep2 :"
737                                                 " unknown intermediate "
738                                                 "response\n", 0, 0, 0 );
739 #else
740                                         Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
741                                                 "unknown intermediate response (%d)\n",
742                                                 rc, 0, 0 );
743 #endif
744                                         ldap_memfree( retoid );
745                                         ber_bvfree( retdata );
746                                         break;
747                                 }
748                                 break;
749
750                         default:
751 #ifdef NEW_LOGGING
752                                 LDAP_LOG( OPERATION, ERR, "do_syncrep2 : "
753                                         "unknown message\n", 0, 0, 0 );
754 #else
755                                 Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
756                                         "unknown message\n", 0, 0, 0 );
757 #endif
758                                 break;
759
760                         }
761                         if ( syncCookie.octet_str ) {
762                                 slap_sync_cookie_free( &syncCookie_req, 0 );
763                                 slap_dup_sync_cookie( &syncCookie_req, &syncCookie );
764                                 slap_sync_cookie_free( &syncCookie, 0 );
765                         }
766                 }
767                 ldap_msgfree( res );
768                 res = NULL;
769         }
770
771         if ( rc == -1 ) {
772                 const char *errstr;
773
774                 ldap_get_option( si->si_ld, LDAP_OPT_ERROR_NUMBER, &rc );
775                 errstr = ldap_err2string( rc );
776                 
777 #ifdef NEW_LOGGING
778                 LDAP_LOG( OPERATION, ERR,
779                         "do_syncrep2 : %s\n", errstr, 0, 0 );
780 #else
781                 Debug( LDAP_DEBUG_ANY,
782                         "do_syncrep2 : %s\n", errstr, 0, 0 );
783 #endif
784         }
785
786 done:
787         slap_sync_cookie_free( &syncCookie, 0 );
788         slap_sync_cookie_free( &syncCookie_req, 0 );
789
790         if ( res ) ldap_msgfree( res );
791
792         if ( rc && si->si_ld ) {
793                 ldap_unbind( si->si_ld );
794                 si->si_ld = NULL;
795         }
796
797         return rc;
798 }
799
800 void *
801 do_syncrepl(
802         void    *ctx,
803         void    *arg )
804 {
805         struct re_s* rtask = arg;
806         syncinfo_t *si = ( syncinfo_t * ) rtask->arg;
807         Connection conn = {0};
808         Operation op = {0};
809         int rc = LDAP_SUCCESS;
810         int first = 0;
811         int dostop = 0;
812         ber_socket_t s;
813
814 #ifdef NEW_LOGGING
815         LDAP_LOG ( OPERATION, DETAIL1, "do_syncrepl\n", 0, 0, 0 );
816 #else
817         Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl\n", 0, 0, 0 );
818 #endif
819
820         if ( si == NULL )
821                 return NULL;
822
823         switch( abs( si->si_type )) {
824         case LDAP_SYNC_REFRESH_ONLY:
825         case LDAP_SYNC_REFRESH_AND_PERSIST:
826                 break;
827         default:
828                 return NULL;
829         }
830
831         if ( slapd_shutdown && si->si_ld ) {
832                 ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s );
833                 connection_client_stop( s );
834                 ldap_unbind( si->si_ld );
835                 si->si_ld = NULL;
836                 return NULL;
837         }
838
839         connection_fake_init( &conn, &op, ctx );
840
841         op.o_dn = si->si_updatedn;
842         op.o_ndn = si->si_updatedn;
843         op.o_managedsait = 1;
844         op.o_bd = si->si_be;
845
846         op.o_sync_state.ctxcsn = NULL;
847         op.o_sync_state.sid = -1;
848         op.o_sync_state.octet_str = NULL;
849         op.o_sync_slog_size = -1;
850         LDAP_STAILQ_FIRST( &op.o_sync_slog_list ) = NULL;
851         op.o_sync_slog_list.stqh_last = &LDAP_STAILQ_FIRST(&op.o_sync_slog_list);
852
853         /* Establish session, do search */
854         if ( !si->si_ld ) {
855                 first = 1;
856                 rc = do_syncrep1( &op, si );
857         }
858
859         /* Process results */
860         if ( rc == LDAP_SUCCESS ) {
861                 ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s );
862
863                 rc = do_syncrep2( &op, si );
864
865                 if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
866                         /* If we succeeded, enable the connection for further listening.
867                          * If we failed, tear down the connection and reschedule.
868                          */
869                         if ( rc == LDAP_SUCCESS ) {
870                                 if ( first ) {
871                                         rc = connection_client_setup( s, do_syncrepl,
872                                                 arg );
873                                 } else {
874                                         connection_client_enable( s );
875                                 }
876                         } else if ( !first ) {
877                                 dostop = 1;
878                         }
879                 } else {
880                         if ( rc == -2 ) rc = 0;
881                 }
882         }
883
884         /* At this point, we have 4 cases:
885          * 1) for any hard failure, give up and remove this task
886          * 2) for ServerDown, reschedule this task to run
887          * 3) for Refresh and Success, reschedule to run
888          * 4) for Persist and Success, reschedule to defer
889          */
890         ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex );
891         if ( ldap_pvt_runqueue_isrunning( &syncrepl_rq, rtask )) {
892                 ldap_pvt_runqueue_stoptask( &syncrepl_rq, rtask );
893         }
894
895         if ( dostop ) {
896                 connection_client_stop( s );
897         }
898
899         if ( rc && rc != LDAP_SERVER_DOWN ) {
900                 ldap_pvt_runqueue_remove( &syncrepl_rq, rtask );
901         } else {
902                 if ( rc == LDAP_SERVER_DOWN ||
903                         si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
904                         rc = 0;
905                 } else {
906                         rc = 1;
907                 }
908                 ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, rc );
909         }
910         ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex );
911
912         return NULL;
913 }
914
915 int
916 syncrepl_message_to_entry(
917         syncinfo_t      *si,
918         Operation       *op,
919         LDAPMessage     *msg,
920         Modifications   **modlist,
921         Entry                   **entry,
922         int             syncstate
923 )
924 {
925         Entry           *e = NULL;
926         BerElement      *ber = NULL;
927         Modifications   tmp;
928         Modifications   *mod;
929         Modifications   **modtail = modlist;
930
931         const char      *text;
932         char txtbuf[SLAP_TEXT_BUFLEN];
933         size_t textlen = sizeof txtbuf;
934
935         struct berval   bdn = {0, NULL}, dn, ndn;
936         int             rc;
937
938         *modlist = NULL;
939
940         if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
941 #ifdef NEW_LOGGING
942                 LDAP_LOG( OPERATION, ERR,
943                         "Message type should be entry (%d)", ldap_msgtype( msg ), 0, 0 );
944 #else
945                 Debug( LDAP_DEBUG_ANY,
946                         "Message type should be entry (%d)", ldap_msgtype( msg ), 0, 0 );
947 #endif
948                 return -1;
949         }
950
951         op->o_tag = LDAP_REQ_ADD;
952
953         rc = ldap_get_dn_ber( si->si_ld, msg, &ber, &bdn );
954
955         if ( rc != LDAP_SUCCESS ) {
956 #ifdef NEW_LOGGING
957                 LDAP_LOG( OPERATION, ERR,
958                         "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
959 #else
960                 Debug( LDAP_DEBUG_ANY,
961                         "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
962 #endif
963                 return rc;
964         }
965
966         dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
967         ber_dupbv( &op->o_req_dn, &dn );
968         ber_dupbv( &op->o_req_ndn, &ndn );
969         slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
970         slap_sl_free( dn.bv_val, op->o_tmpmemctx );
971
972         if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE ) {
973                 return LDAP_SUCCESS;
974         }
975
976         if ( entry == NULL ) {
977                 return -1;
978         }
979
980         e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
981         *entry = e;
982         e->e_name = op->o_req_dn;
983         e->e_nname = op->o_req_ndn;
984
985         while ( ber_remaining( ber ) ) {
986                 if ( (ber_scanf( ber, "{mW}", &tmp.sml_type, &tmp.sml_values ) ==
987                         LBER_ERROR ) || ( tmp.sml_type.bv_val == NULL ))
988                 {
989                         break;
990                 }
991
992                 mod  = (Modifications *) ch_malloc( sizeof( Modifications ));
993
994                 mod->sml_op = LDAP_MOD_REPLACE;
995                 mod->sml_next = NULL;
996                 mod->sml_desc = NULL;
997                 mod->sml_type = tmp.sml_type;
998                 mod->sml_values = tmp.sml_values;
999                 mod->sml_nvalues = NULL;
1000
1001                 *modtail = mod;
1002                 modtail = &mod->sml_next;
1003         }
1004
1005         if ( *modlist == NULL ) {
1006 #ifdef NEW_LOGGING
1007                 LDAP_LOG( OPERATION, ERR,
1008                         "syncrepl_message_to_entry: no attributes\n", 0, 0, 0 );
1009 #else
1010                 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: no attributes\n",
1011                         0, 0, 0 );
1012 #endif
1013         }
1014
1015         rc = slap_mods_check( *modlist, 1, &text, txtbuf, textlen, NULL );
1016
1017         if ( rc != LDAP_SUCCESS ) {
1018 #ifdef NEW_LOGGING
1019                 LDAP_LOG( OPERATION, ERR,
1020                         "syncrepl_message_to_entry: mods check (%s)\n", text, 0, 0 );
1021 #else
1022                 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods check (%s)\n",
1023                         text, 0, 0 );
1024 #endif
1025                 goto done;
1026         }
1027         
1028         rc = slap_mods2entry( *modlist, &e, 1, 1, &text, txtbuf, textlen);
1029         if( rc != LDAP_SUCCESS ) {
1030 #ifdef NEW_LOGGING
1031                 LDAP_LOG( OPERATION, ERR,
1032                         "syncrepl_message_to_entry: mods2entry (%s)\n", text, 0, 0 );
1033 #else
1034                 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods2entry (%s)\n",
1035                         text, 0, 0 );
1036 #endif
1037         }
1038
1039 done:
1040         ber_free ( ber, 0 );
1041         if ( rc != LDAP_SUCCESS ) {
1042                 entry_free( e );
1043                 e = NULL;
1044         }
1045
1046         return rc;
1047 }
1048
1049 int
1050 syncrepl_entry(
1051         syncinfo_t* si,
1052         Operation *op,
1053         Entry* e,
1054         Modifications* modlist,
1055         int syncstate,
1056         struct berval* syncUUID,
1057         struct sync_cookie* syncCookie_req )
1058 {
1059         Backend *be = op->o_bd;
1060         slap_callback   cb = { NULL };
1061         struct berval   *syncuuid_bv = NULL;
1062         struct berval   syncUUID_strrep = BER_BVNULL;
1063         struct berval   uuid_bv = BER_BVNULL;
1064
1065         SlapReply       rs = {REP_RESULT};
1066         Filter f = {0};
1067         AttributeAssertion ava = {0};
1068         int rc = LDAP_SUCCESS;
1069         int ret = LDAP_SUCCESS;
1070         const char *text;
1071
1072         struct berval pdn = BER_BVNULL;
1073         struct berval org_req_dn = BER_BVNULL;
1074         struct berval org_req_ndn = BER_BVNULL;
1075         struct berval org_dn = BER_BVNULL;
1076         struct berval org_ndn = BER_BVNULL;
1077         int     org_managedsait;
1078
1079         if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD )) {
1080                 syncuuid_bv = ber_dupbv( NULL, syncUUID );
1081                 avl_insert( &si->si_presentlist, (caddr_t) syncuuid_bv,
1082                         syncuuid_cmp, avl_dup_error );
1083         }
1084
1085         if ( syncstate == LDAP_SYNC_PRESENT ) {
1086                 return e ? 1 : 0;
1087         }
1088
1089         f.f_choice = LDAP_FILTER_EQUALITY;
1090         f.f_ava = &ava;
1091         ava.aa_desc = slap_schema.si_ad_entryUUID;
1092         slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
1093         ava.aa_value = *syncUUID;
1094         op->ors_filter = &f;
1095
1096         op->ors_filterstr.bv_len = (sizeof("entryUUID=")-1) + syncUUID->bv_len;
1097         op->ors_filterstr.bv_val = (char *) slap_sl_malloc(
1098                 op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); 
1099         AC_MEMCPY( op->ors_filterstr.bv_val, "entryUUID=", sizeof("entryUUID=")-1 );
1100         AC_MEMCPY( &op->ors_filterstr.bv_val[sizeof("entryUUID=")-1],
1101                 syncUUID->bv_val, syncUUID->bv_len );
1102         op->ors_filterstr.bv_val[op->ors_filterstr.bv_len] = '\0';
1103
1104         op->o_tag = LDAP_REQ_SEARCH;
1105         op->ors_scope = LDAP_SCOPE_SUBTREE;
1106
1107         /* get syncrepl cookie of shadow replica from subentry */
1108         op->o_req_dn = si->si_base;
1109         op->o_req_ndn = si->si_base;
1110
1111         /* set callback function */
1112         op->o_callback = &cb;
1113         cb.sc_response = dn_callback;
1114         cb.sc_private = si;
1115
1116         si->si_syncUUID_ndn.bv_val = NULL;
1117
1118         if ( limits_check( op, &rs ) == 0 ) {
1119                 rc = be->be_search( op, &rs );
1120         }
1121
1122         if ( op->ors_filterstr.bv_val ) {
1123                 slap_sl_free( op->ors_filterstr.bv_val, op->o_tmpmemctx );
1124         }
1125
1126         cb.sc_response = null_callback;
1127         cb.sc_private = si;
1128
1129         if ( rc == LDAP_SUCCESS && si->si_syncUUID_ndn.bv_val ) {
1130                 char *subseq_ptr;
1131
1132                 if ( syncstate != LDAP_SYNC_DELETE ) {
1133                         op->o_no_psearch = 1;
1134                 }
1135
1136                 ber_dupbv( &op->o_sync_csn, syncCookie_req->ctxcsn );
1137                 if ( op->o_sync_csn.bv_val ) {
1138                         subseq_ptr = strstr( op->o_sync_csn.bv_val, "#0000" );
1139                         subseq_ptr += 4;
1140                         *subseq_ptr = '1';
1141                 }
1142                 
1143                 op->o_req_dn = si->si_syncUUID_ndn;
1144                 op->o_req_ndn = si->si_syncUUID_ndn;
1145                 op->o_tag = LDAP_REQ_DELETE;
1146                 rc = be->be_delete( op, &rs );
1147
1148                 org_req_dn = op->o_req_dn;
1149                 org_req_ndn = op->o_req_ndn;
1150                 org_dn = op->o_dn;
1151                 org_ndn = op->o_ndn;
1152                 org_managedsait = get_manageDSAit( op );
1153                 op->o_dn = op->o_bd->be_rootdn;
1154                 op->o_ndn = op->o_bd->be_rootndn;
1155                 op->o_managedsait = 1;
1156
1157                 while ( rs.sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) {
1158                         op->o_delete_glue_parent = 0;
1159                         if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
1160                                 slap_callback cb = { NULL };
1161                                 cb.sc_response = slap_null_cb;
1162                                 dnParent( &op->o_req_ndn, &pdn );
1163                                 op->o_req_dn = pdn;
1164                                 op->o_req_ndn = pdn;
1165                                 op->o_callback = &cb;
1166                                 op->o_bd->be_delete( op, &rs );
1167                         } else {
1168                                 break;
1169                     }
1170                 }
1171
1172                 op->o_managedsait = org_managedsait;
1173                 op->o_dn = org_dn;
1174                 op->o_ndn = org_ndn;
1175                 op->o_req_dn = org_req_dn;
1176                 op->o_req_ndn = org_req_ndn;
1177                 op->o_delete_glue_parent = 0;
1178
1179                 op->o_no_psearch = 0;
1180         }
1181
1182         switch ( syncstate ) {
1183         case LDAP_SYNC_ADD:
1184         case LDAP_SYNC_MODIFY:
1185                 if ( rc == LDAP_SUCCESS ||
1186                          rc == LDAP_REFERRAL ||
1187                          rc == LDAP_NO_SUCH_OBJECT ||
1188                          rc == LDAP_NOT_ALLOWED_ON_NONLEAF )
1189                 {
1190                         attr_delete( &e->e_attrs, slap_schema.si_ad_entryUUID );
1191                         attr_merge_one( e, slap_schema.si_ad_entryUUID,
1192                                 syncUUID, &ava.aa_value );
1193
1194                         op->o_tag = LDAP_REQ_ADD;
1195                         op->ora_e = e;
1196                         op->o_req_dn = e->e_name;
1197                         op->o_req_ndn = e->e_nname;
1198                         rc = be->be_add( op, &rs );
1199
1200                         if ( rc != LDAP_SUCCESS ) {
1201                                 if ( rc == LDAP_ALREADY_EXISTS ) {
1202                                         Modifications *mod;
1203                                         Modifications *modtail = modlist;
1204
1205                                         assert( modlist );
1206
1207                                         for ( mod = modlist; mod != NULL; mod = mod->sml_next ) {
1208                                                 modtail = mod;
1209                                         }
1210
1211                                         mod = (Modifications *)ch_calloc(1, sizeof(Modifications));
1212                                         ber_dupbv( &uuid_bv, syncUUID );
1213                                         mod->sml_op = LDAP_MOD_REPLACE;
1214                                         mod->sml_desc = slap_schema.si_ad_entryUUID;
1215                                         mod->sml_type = mod->sml_desc->ad_cname;
1216                                         ber_bvarray_add( &mod->sml_values, &uuid_bv );
1217                                         modtail->sml_next = mod;
1218                                         
1219                                         op->o_tag = LDAP_REQ_MODIFY;
1220                                         op->orm_modlist = modlist;
1221                                         op->o_req_dn = e->e_name;
1222                                         op->o_req_ndn = e->e_nname;
1223
1224                                         rc = be->be_modify( op, &rs );
1225                                         if ( rc != LDAP_SUCCESS ) {
1226 #ifdef NEW_LOGGING
1227                                                 LDAP_LOG( OPERATION, ERR,
1228                                                         "syncrepl_entry : be_modify failed (%d)\n",
1229                                                         rc, 0, 0 );
1230 #else
1231                                                 Debug( LDAP_DEBUG_ANY,
1232                                                         "syncrepl_entry : be_modify failed (%d)\n",
1233                                                         rc, 0, 0 );
1234 #endif
1235                                         }
1236                                         ret = 1;
1237                                         goto done;
1238                                 } else if ( rc == LDAP_REFERRAL || rc == LDAP_NO_SUCH_OBJECT ) {
1239                                         syncrepl_add_glue( op, e );
1240                                         ret = 0;
1241                                         goto done;
1242                                 } else {
1243 #ifdef NEW_LOGGING
1244                                         LDAP_LOG( OPERATION, ERR,
1245                                                 "syncrepl_entry : be_add failed (%d)\n",
1246                                                 rc, 0, 0 );
1247 #else
1248                                         Debug( LDAP_DEBUG_ANY,
1249                                                 "syncrepl_entry : be_add failed (%d)\n",
1250                                                 rc, 0, 0 );
1251 #endif
1252                                         ret = 1;
1253                                         goto done;
1254                                 }
1255                         } else {
1256                                 be_entry_release_w( op, e );
1257                                 ret = 0;
1258                                 goto done;
1259                         }
1260                 } else {
1261 #ifdef NEW_LOGGING
1262                         LDAP_LOG( OPERATION, ERR,
1263                                 "syncrepl_entry : be_search failed (%d)\n", rc, 0, 0 );
1264 #else
1265                         Debug( LDAP_DEBUG_ANY,
1266                                 "syncrepl_entry : be_search failed (%d)\n", rc, 0, 0 );
1267 #endif
1268                         ret = 1;
1269                         goto done;
1270                 }
1271
1272         case LDAP_SYNC_DELETE :
1273                 /* Already deleted */
1274                 ret = 0;
1275                 goto done;
1276
1277         default :
1278 #ifdef NEW_LOGGING
1279                 LDAP_LOG( OPERATION, ERR,
1280                         "syncrepl_entry : unknown syncstate\n", 0, 0, 0 );
1281 #else
1282                 Debug( LDAP_DEBUG_ANY,
1283                         "syncrepl_entry : unknown syncstate\n", 0, 0, 0 );
1284 #endif
1285                 ret = 1;
1286                 goto done;
1287         }
1288
1289 done :
1290
1291         if ( syncUUID_strrep.bv_val ) {
1292                 ber_memfree_x( syncUUID_strrep.bv_val, op->o_tmpmemctx );
1293         }
1294         if ( si->si_syncUUID_ndn.bv_val ) {
1295                 ber_memfree_x( si->si_syncUUID_ndn.bv_val, op->o_tmpmemctx );
1296         }
1297         return ret;
1298 }
1299
1300 static struct berval gcbva[] = {
1301         BER_BVC("top"),
1302         BER_BVC("glue"),
1303         BER_BVNULL
1304 };
1305
1306 static void
1307 syncrepl_del_nonpresent(
1308         Operation *op,
1309         syncinfo_t *si )
1310 {
1311         Backend* be = op->o_bd;
1312         slap_callback   cb = { NULL };
1313         SlapReply       rs = {REP_RESULT};
1314         struct nonpresent_entry *np_list, *np_prev;
1315         int rc;
1316         Modifications *ml;
1317         Modifications *mlnext;
1318         Modifications *mod;
1319         Modifications *modlist = NULL;
1320         Modifications **modtail = &modlist;
1321         Attribute       *attr;
1322
1323         struct berval pdn = BER_BVNULL;
1324         struct berval org_req_dn = BER_BVNULL;
1325         struct berval org_req_ndn = BER_BVNULL;
1326         struct berval org_dn = BER_BVNULL;
1327         struct berval org_ndn = BER_BVNULL;
1328         int     org_managedsait;
1329
1330         op->o_req_dn = si->si_base;
1331         op->o_req_ndn = si->si_base;
1332
1333         cb.sc_response = nonpresent_callback;
1334         cb.sc_private = si;
1335
1336         op->o_callback = &cb;
1337         op->o_tag = LDAP_REQ_SEARCH;
1338         op->ors_scope = si->si_scope;
1339         op->ors_deref = LDAP_DEREF_NEVER;
1340         op->ors_slimit = 0;
1341         op->ors_tlimit = 0;
1342         op->ors_attrsonly = 0;
1343         op->ors_attrs = NULL;
1344         op->ors_filter = str2filter_x( op, si->si_filterstr.bv_val );
1345         op->ors_filterstr = si->si_filterstr;
1346
1347         op->o_nocaching = 1;
1348         op->o_managedsait = 0;
1349
1350         if ( limits_check( op, &rs ) == 0 ) {
1351                 be->be_search( op, &rs );
1352         }
1353
1354         op->o_managedsait = 1;
1355         op->o_nocaching = 0;
1356
1357         if ( op->ors_filter ) filter_free_x( op, op->ors_filter );
1358
1359         if ( !LDAP_LIST_EMPTY( &si->si_nonpresentlist ) ) {
1360                 np_list = LDAP_LIST_FIRST( &si->si_nonpresentlist );
1361                 while ( np_list != NULL ) {
1362                         LDAP_LIST_REMOVE( np_list, npe_link );
1363                         np_prev = np_list;
1364                         np_list = LDAP_LIST_NEXT( np_list, npe_link );
1365                         op->o_tag = LDAP_REQ_DELETE;
1366                         op->o_callback = &cb;
1367                         cb.sc_response = null_callback;
1368                         cb.sc_private = si;
1369                         op->o_req_dn = *np_prev->npe_name;
1370                         op->o_req_ndn = *np_prev->npe_nname;
1371                         rc = op->o_bd->be_delete( op, &rs );
1372
1373                         if ( rc == LDAP_NOT_ALLOWED_ON_NONLEAF ) {
1374                                 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1375                                 mod->sml_op = LDAP_MOD_REPLACE;
1376                                 mod->sml_desc = slap_schema.si_ad_objectClass;
1377                                 mod->sml_type = mod->sml_desc->ad_cname;
1378                                 mod->sml_values = &gcbva[0];
1379                                 *modtail = mod;
1380                                 modtail = &mod->sml_next;
1381
1382                                 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1383                                 mod->sml_op = LDAP_MOD_REPLACE;
1384                                 mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
1385                                 mod->sml_type = mod->sml_desc->ad_cname;
1386                                 mod->sml_values = &gcbva[1];
1387                                 *modtail = mod;
1388                                 modtail = &mod->sml_next;
1389
1390                                 op->o_tag = LDAP_REQ_MODIFY;
1391                                 op->orm_modlist = modlist;
1392
1393                                 rc = be->be_modify( op, &rs );
1394
1395                                 for ( ml = modlist; ml != NULL; ml = mlnext ) {
1396                                         mlnext = ml->sml_next;
1397                                         free( ml );
1398                                 }
1399                         }
1400
1401                         org_req_dn = op->o_req_dn;
1402                         org_req_ndn = op->o_req_ndn;
1403                         org_dn = op->o_dn;
1404                         org_ndn = op->o_ndn;
1405                         org_managedsait = get_manageDSAit( op );
1406                         op->o_dn = op->o_bd->be_rootdn;
1407                         op->o_ndn = op->o_bd->be_rootndn;
1408                         op->o_managedsait = 1;
1409
1410                         while ( rs.sr_err == LDAP_SUCCESS &&
1411                                         op->o_delete_glue_parent ) {
1412                                 op->o_delete_glue_parent = 0;
1413                                 if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
1414                                         slap_callback cb = { NULL };
1415                                         cb.sc_response = slap_null_cb;
1416                                         dnParent( &op->o_req_ndn, &pdn );
1417                                         op->o_req_dn = pdn;
1418                                         op->o_req_ndn = pdn;
1419                                         op->o_callback = &cb;
1420                                         /* give it a root privil ? */
1421                                         op->o_bd->be_delete( op, &rs );
1422                                 } else {
1423                                         break;
1424                             }
1425                         }
1426
1427                         op->o_managedsait = org_managedsait;
1428                         op->o_dn = org_dn;
1429                         op->o_ndn = org_ndn;
1430                         op->o_req_dn = org_req_dn;
1431                         op->o_req_ndn = org_req_ndn;
1432                         op->o_delete_glue_parent = 0;
1433
1434                         ber_bvfree( np_prev->npe_name );
1435                         ber_bvfree( np_prev->npe_nname );
1436                         op->o_req_dn.bv_val = NULL;
1437                         op->o_req_ndn.bv_val = NULL;
1438                         ch_free( np_prev );
1439                 }
1440         }
1441
1442         return;
1443 }
1444
1445 void
1446 syncrepl_add_glue(
1447         Operation* op,
1448         Entry *e )
1449 {
1450         Backend *be = op->o_bd;
1451         slap_callback cb = { NULL };
1452         Attribute       *a;
1453         int     rc;
1454         int suffrdns;
1455         int i;
1456         struct berval dn = {0, NULL};
1457         struct berval ndn = {0, NULL};
1458         Entry   *glue;
1459         SlapReply       rs = {REP_RESULT};
1460         char    *ptr, *comma;
1461
1462         op->o_tag = LDAP_REQ_ADD;
1463         op->o_callback = &cb;
1464         cb.sc_response = null_callback;
1465         cb.sc_private = NULL;
1466
1467         dn = e->e_name;
1468         ndn = e->e_nname;
1469
1470         /* count RDNs in suffix */
1471         if ( be->be_nsuffix[0].bv_len ) {
1472                 for (i=0, ptr=be->be_nsuffix[0].bv_val; ptr; ptr=strchr( ptr, ',' )) {
1473                         ptr++;
1474                         i++;
1475                 }
1476                 suffrdns = i;
1477         } else {
1478                 /* suffix is "" */
1479                 suffrdns = 0;
1480         }
1481
1482         /* Start with BE suffix */
1483         for ( i = 0, ptr = NULL; i < suffrdns; i++ ) {
1484                 comma = strrchr(dn.bv_val, ',');
1485                 if ( ptr ) *ptr = ',';
1486                 if ( comma ) *comma = '\0';
1487                 ptr = comma;
1488         }
1489         if ( ptr ) {
1490                 *ptr++ = ',';
1491                 dn.bv_len -= ptr - dn.bv_val;
1492                 dn.bv_val = ptr;
1493         }
1494         /* the normalizedDNs are always the same length, no counting
1495          * required.
1496          */
1497         if ( ndn.bv_len > be->be_nsuffix[0].bv_len ) {
1498                 ndn.bv_val += ndn.bv_len - be->be_nsuffix[0].bv_len;
1499                 ndn.bv_len = be->be_nsuffix[0].bv_len;
1500         }
1501
1502         while ( ndn.bv_val > e->e_nname.bv_val ) {
1503                 glue = (Entry *) ch_calloc( 1, sizeof(Entry) );
1504                 ber_dupbv( &glue->e_name, &dn );
1505                 ber_dupbv( &glue->e_nname, &ndn );
1506
1507                 a = ch_calloc( 1, sizeof( Attribute ));
1508                 a->a_desc = slap_schema.si_ad_objectClass;
1509
1510                 a->a_vals = ch_calloc( 3, sizeof( struct berval ));
1511                 ber_dupbv( &a->a_vals[0], &gcbva[0] );
1512                 ber_dupbv( &a->a_vals[1], &gcbva[1] );
1513                 ber_dupbv( &a->a_vals[2], &gcbva[2] );
1514
1515                 a->a_nvals = a->a_vals;
1516
1517                 a->a_next = glue->e_attrs;
1518                 glue->e_attrs = a;
1519
1520                 a = ch_calloc( 1, sizeof( Attribute ));
1521                 a->a_desc = slap_schema.si_ad_structuralObjectClass;
1522
1523                 a->a_vals = ch_calloc( 2, sizeof( struct berval ));
1524                 ber_dupbv( &a->a_vals[0], &gcbva[1] );
1525                 ber_dupbv( &a->a_vals[1], &gcbva[2] );
1526
1527                 a->a_nvals = a->a_vals;
1528
1529                 a->a_next = glue->e_attrs;
1530                 glue->e_attrs = a;
1531
1532                 op->o_req_dn = glue->e_name;
1533                 op->o_req_ndn = glue->e_nname;
1534                 op->ora_e = glue;
1535                 rc = be->be_add ( op, &rs );
1536                 if ( rc == LDAP_SUCCESS ) {
1537                         be_entry_release_w( op, glue );
1538                 } else {
1539                 /* incl. ALREADY EXIST */
1540                         entry_free( glue );
1541                 }
1542
1543                 /* Move to next child */
1544                 for (ptr = dn.bv_val-2; ptr > e->e_name.bv_val && *ptr != ','; ptr--) {
1545                         /* empty */
1546                 }
1547                 if ( ptr == e->e_name.bv_val ) break;
1548                 dn.bv_val = ++ptr;
1549                 dn.bv_len = e->e_name.bv_len - (ptr-e->e_name.bv_val);
1550                 for( ptr = ndn.bv_val-2;
1551                         ptr > e->e_nname.bv_val && *ptr != ',';
1552                         ptr--)
1553                 {
1554                         /* empty */
1555                 }
1556                 ndn.bv_val = ++ptr;
1557                 ndn.bv_len = e->e_nname.bv_len - (ptr-e->e_nname.bv_val);
1558         }
1559
1560         op->o_req_dn = e->e_name;
1561         op->o_req_ndn = e->e_nname;
1562         op->ora_e = e;
1563         rc = be->be_add ( op, &rs );
1564         if ( rc == LDAP_SUCCESS ) {
1565                 be_entry_release_w( op, e );
1566         } else {
1567                 entry_free( e );
1568         }
1569
1570         return;
1571 }
1572
1573 static struct berval ocbva[] = {
1574         BER_BVC("top"),
1575         BER_BVC("subentry"),
1576         BER_BVC("syncConsumerSubentry"),
1577         BER_BVNULL
1578 };
1579
1580 static struct berval cnbva[] = {
1581         BER_BVNULL,
1582         BER_BVNULL
1583 };
1584
1585 static struct berval ssbva[] = {
1586         BER_BVC("{}"),
1587         BER_BVNULL
1588 };
1589
1590 static struct berval scbva[] = {
1591         BER_BVNULL,
1592         BER_BVNULL
1593 };
1594
1595 void
1596 syncrepl_updateCookie(
1597         syncinfo_t *si,
1598         Operation *op,
1599         struct berval *pdn,
1600         struct sync_cookie *syncCookie )
1601 {
1602         Backend *be = op->o_bd;
1603         Modifications *ml;
1604         Modifications *mlnext;
1605         Modifications *mod;
1606         Modifications *modlist = NULL;
1607         Modifications **modtail = &modlist;
1608
1609         const char      *text;
1610         char txtbuf[SLAP_TEXT_BUFLEN];
1611         size_t textlen = sizeof txtbuf;
1612
1613         Entry* e = NULL;
1614         int rc;
1615
1616         char syncrepl_cbuf[sizeof(CN_STR SYNCREPL_STR)];
1617         struct berval slap_syncrepl_dn_bv = BER_BVNULL;
1618         struct berval slap_syncrepl_cn_bv = BER_BVNULL;
1619         
1620         slap_callback cb = { NULL };
1621         SlapReply       rs = {REP_RESULT};
1622
1623         slap_sync_cookie_free( &si->si_syncCookie, 0 );
1624         slap_dup_sync_cookie( &si->si_syncCookie, syncCookie );
1625
1626         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1627         mod->sml_op = LDAP_MOD_REPLACE;
1628         mod->sml_desc = slap_schema.si_ad_objectClass;
1629         mod->sml_type = mod->sml_desc->ad_cname;
1630         mod->sml_values = ocbva;
1631         *modtail = mod;
1632         modtail = &mod->sml_next;
1633
1634         ber_dupbv( &cnbva[0], (struct berval *) &slap_syncrepl_bvc );
1635         assert( si->si_rid < 1000 );
1636         cnbva[0].bv_len = snprintf( cnbva[0].bv_val,
1637                 slap_syncrepl_bvc.bv_len + 1,
1638                 "syncrepl%ld", si->si_rid );
1639         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1640         mod->sml_op = LDAP_MOD_REPLACE;
1641         mod->sml_desc = slap_schema.si_ad_cn;
1642         mod->sml_type = mod->sml_desc->ad_cname;
1643         mod->sml_values = cnbva;
1644         *modtail = mod;
1645         modtail = &mod->sml_next;
1646
1647         if ( scbva[0].bv_val ) ch_free( scbva[0].bv_val );
1648         ber_dupbv( &scbva[0], &si->si_syncCookie.octet_str[0] );
1649         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1650         mod->sml_op = LDAP_MOD_REPLACE;
1651         mod->sml_desc = slap_schema.si_ad_syncreplCookie;
1652         mod->sml_type = mod->sml_desc->ad_cname;
1653         mod->sml_values = scbva;
1654         *modtail = mod;
1655         modtail = &mod->sml_next;
1656
1657         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1658         mod->sml_op = LDAP_MOD_REPLACE;
1659         mod->sml_desc = slap_schema.si_ad_subtreeSpecification;
1660         mod->sml_type = mod->sml_desc->ad_cname;
1661         mod->sml_values = ssbva;
1662         *modtail = mod;
1663         modtail = &mod->sml_next;
1664
1665         mlnext = mod;
1666
1667         op->o_tag = LDAP_REQ_ADD;
1668         rc = slap_mods_opattrs( op, modlist, modtail,
1669                  &text, txtbuf, textlen );
1670
1671         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
1672                 ml->sml_op = LDAP_MOD_REPLACE;
1673         }
1674
1675         if( rc != LDAP_SUCCESS ) {
1676 #ifdef NEW_LOGGING
1677                 LDAP_LOG( OPERATION, ERR,
1678                         "syncrepl_updateCookie: mods opattrs (%s)\n", text, 0, 0 );
1679 #else
1680                 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods opattrs (%s)\n",
1681                          text, 0, 0 );
1682 #endif
1683         }
1684
1685         e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1686
1687         slap_syncrepl_cn_bv.bv_val = syncrepl_cbuf;
1688         assert( si->si_rid < 1000 );
1689         slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
1690                 slap_syncrepl_cn_bvc.bv_len + 1,
1691                 "cn=syncrepl%ld", si->si_rid );
1692
1693         build_new_dn( &slap_syncrepl_dn_bv, pdn, &slap_syncrepl_cn_bv,
1694                 op->o_tmpmemctx );
1695         ber_dupbv( &e->e_name, &slap_syncrepl_dn_bv );
1696         ber_dupbv( &e->e_nname, &slap_syncrepl_dn_bv );
1697
1698         if ( slap_syncrepl_dn_bv.bv_val ) {
1699                 slap_sl_free( slap_syncrepl_dn_bv.bv_val, op->o_tmpmemctx );
1700         }
1701
1702         e->e_attrs = NULL;
1703
1704         rc = slap_mods2entry( modlist, &e, 1, 1, &text, txtbuf, textlen );
1705
1706         if( rc != LDAP_SUCCESS ) {
1707 #ifdef NEW_LOGGING
1708                 LDAP_LOG( OPERATION, ERR,
1709                         "syncrepl_updateCookie: mods2entry (%s)\n", text, 0, 0 );
1710 #else
1711                 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods2entry (%s)\n",
1712                          text, 0, 0 );
1713 #endif
1714         }
1715
1716         cb.sc_response = null_callback;
1717         cb.sc_private = si;
1718
1719         op->o_callback = &cb;
1720         op->o_req_dn = e->e_name;
1721         op->o_req_ndn = e->e_nname;
1722
1723         /* update persistent cookie */
1724 update_cookie_retry:
1725         op->o_tag = LDAP_REQ_MODIFY;
1726         op->orm_modlist = modlist;
1727         rc = be->be_modify( op, &rs );
1728
1729         if ( rc != LDAP_SUCCESS ) {
1730                 if ( rc == LDAP_REFERRAL ||
1731                          rc == LDAP_NO_SUCH_OBJECT ) {
1732                         op->o_tag = LDAP_REQ_ADD;
1733                         op->ora_e = e;
1734                         rc = be->be_add( op, &rs );
1735                         if ( rc != LDAP_SUCCESS ) {
1736                                 if ( rc == LDAP_ALREADY_EXISTS ) {
1737                                         goto update_cookie_retry;
1738                                 } else if ( rc == LDAP_REFERRAL ||
1739                                                         rc == LDAP_NO_SUCH_OBJECT ) {
1740 #ifdef NEW_LOGGING
1741                                         LDAP_LOG( OPERATION, ERR,
1742                                                 "cookie will be non-persistent\n",
1743                                                 0, 0, 0 );
1744 #else
1745                                         Debug( LDAP_DEBUG_ANY,
1746                                                 "cookie will be non-persistent\n",
1747                                                 0, 0, 0 );
1748 #endif
1749                                 } else {
1750 #ifdef NEW_LOGGING
1751                                         LDAP_LOG( OPERATION, ERR,
1752                                                 "be_add failed (%d)\n",
1753                                                 rc, 0, 0 );
1754 #else
1755                                         Debug( LDAP_DEBUG_ANY,
1756                                                 "be_add failed (%d)\n",
1757                                                 rc, 0, 0 );
1758 #endif
1759                                 }
1760                         } else {
1761                                 be_entry_release_w( op, e );
1762                                 goto done;
1763                         }
1764                 } else {
1765 #ifdef NEW_LOGGING
1766                         LDAP_LOG( OPERATION, ERR,
1767                                 "be_modify failed (%d)\n", rc, 0, 0 );
1768 #else
1769                         Debug( LDAP_DEBUG_ANY,
1770                                 "be_modify failed (%d)\n", rc, 0, 0 );
1771 #endif
1772                 }
1773         }
1774
1775         if ( e != NULL ) {
1776                 entry_free( e );
1777         }
1778
1779 done :
1780
1781         if ( cnbva[0].bv_val ) {
1782                 ch_free( cnbva[0].bv_val );
1783                 cnbva[0].bv_val = NULL;
1784         }
1785         if ( scbva[0].bv_val ) {
1786                 ch_free( scbva[0].bv_val );
1787                 scbva[0].bv_val = NULL;
1788         }
1789
1790         if ( mlnext->sml_next ) {
1791                 slap_mods_free( mlnext->sml_next );
1792                 mlnext->sml_next = NULL;
1793         }
1794
1795         for (ml = modlist ; ml != NULL; ml = mlnext ) {
1796                 mlnext = ml->sml_next;
1797                 free( ml );
1798         }
1799
1800         return;
1801 }
1802
1803 int
1804 syncrepl_isupdate( Operation *op )
1805 {
1806         return ( syncrepl_isupdate_dn( op->o_bd, &op->o_ndn ));
1807 }
1808
1809 int
1810 syncrepl_isupdate_dn(
1811         Backend*                be,
1812         struct berval*  ndn )
1813 {
1814         syncinfo_t*     si;
1815         int                     ret = 0;
1816
1817         if ( !LDAP_STAILQ_EMPTY( &be->be_syncinfo )) {
1818                 LDAP_STAILQ_FOREACH( si, &be->be_syncinfo, si_next ) {
1819                         if ( ( ret = dn_match( &si->si_updatedn, ndn ) ) ) {
1820                                 return ret;
1821                         }
1822                 }
1823         }
1824         return 0;
1825 }
1826
1827 static int
1828 dn_callback(
1829         Operation*      op,
1830         SlapReply*      rs )
1831 {
1832         syncinfo_t *si = op->o_callback->sc_private;
1833
1834         if ( rs->sr_type == REP_SEARCH ) {
1835                 if ( si->si_syncUUID_ndn.bv_val != NULL ) {
1836 #ifdef NEW_LOGGING
1837                         LDAP_LOG( OPERATION, ERR,
1838                                 "dn_callback : multiple entries match dn\n", 0, 0, 0 );
1839 #else
1840                         Debug( LDAP_DEBUG_ANY,
1841                                 "dn_callback : multiple entries match dn\n", 0, 0, 0 );
1842 #endif
1843                 } else {
1844                         ber_dupbv_x( &si->si_syncUUID_ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx );
1845                 }
1846         }
1847
1848         return LDAP_SUCCESS;
1849 }
1850
1851 static int
1852 nonpresent_callback(
1853         Operation*      op,
1854         SlapReply*      rs )
1855 {
1856         syncinfo_t *si = op->o_callback->sc_private;
1857         Attribute *a;
1858         int count = 0;
1859         struct berval* present_uuid = NULL;
1860         struct nonpresent_entry *np_entry;
1861
1862         if ( rs->sr_type == REP_RESULT ) {
1863                 count = avl_free( si->si_presentlist, avl_ber_bvfree );
1864                 si->si_presentlist = NULL;
1865
1866         } else if ( rs->sr_type == REP_SEARCH ) {
1867                 a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
1868
1869                 if ( a == NULL ) return 0;
1870
1871                 present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
1872                         syncuuid_cmp );
1873
1874                 if ( present_uuid == NULL ) {
1875                         np_entry = (struct nonpresent_entry *)
1876                                 ch_calloc( 1, sizeof( struct nonpresent_entry ));
1877                         np_entry->npe_name = ber_dupbv( NULL, &rs->sr_entry->e_name );
1878                         np_entry->npe_nname = ber_dupbv( NULL, &rs->sr_entry->e_nname );
1879                         LDAP_LIST_INSERT_HEAD( &si->si_nonpresentlist, np_entry, npe_link );
1880
1881                 } else {
1882                         avl_delete( &si->si_presentlist,
1883                                         &a->a_nvals[0], syncuuid_cmp );
1884                         ch_free( present_uuid->bv_val );
1885                         ch_free( present_uuid );
1886                 }
1887         }
1888         return LDAP_SUCCESS;
1889 }
1890
1891 static int
1892 null_callback(
1893         Operation*      op,
1894         SlapReply*      rs )
1895 {
1896         if ( rs->sr_err != LDAP_SUCCESS &&
1897                 rs->sr_err != LDAP_REFERRAL &&
1898                 rs->sr_err != LDAP_ALREADY_EXISTS &&
1899                 rs->sr_err != LDAP_NO_SUCH_OBJECT &&
1900                 rs->sr_err != LDAP_NOT_ALLOWED_ON_NONLEAF )
1901         {
1902 #ifdef NEW_LOGGING
1903                 LDAP_LOG( OPERATION, ERR,
1904                         "null_callback : error code 0x%x\n",
1905                         rs->sr_err, 0, 0 );
1906 #else
1907                 Debug( LDAP_DEBUG_ANY,
1908                         "null_callback : error code 0x%x\n",
1909                         rs->sr_err, 0, 0 );
1910 #endif
1911         }
1912         return LDAP_SUCCESS;
1913 }
1914
1915 Entry *
1916 slap_create_syncrepl_entry(
1917         Backend *be,
1918         struct berval *context_csn,
1919         struct berval *rdn,
1920         struct berval *cn )
1921 {
1922         Entry* e;
1923
1924         struct berval bv;
1925
1926         e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1927
1928         attr_merge( e, slap_schema.si_ad_objectClass, ocbva, NULL );
1929
1930         attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
1931                 &ocbva[1], NULL );
1932
1933         attr_merge_one( e, slap_schema.si_ad_cn, cn, NULL );
1934
1935         if ( context_csn ) {
1936                 attr_merge_one( e, slap_schema.si_ad_syncreplCookie,
1937                         context_csn, NULL );
1938         }
1939
1940         bv.bv_val = "{}";
1941         bv.bv_len = sizeof("{}")-1;
1942         attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
1943
1944         build_new_dn( &e->e_name, &be->be_nsuffix[0], rdn, NULL );
1945         ber_dupbv( &e->e_nname, &e->e_name );
1946
1947         return e;
1948 }
1949
1950 struct berval *
1951 slap_uuidstr_from_normalized(
1952         struct berval* uuidstr,
1953         struct berval* normalized,
1954         void *ctx )
1955 {
1956         struct berval *new;
1957         unsigned char nibble;
1958         int i, d = 0;
1959
1960         if ( normalized == NULL ) return NULL;
1961         if ( normalized->bv_len != 16 ) return NULL;
1962
1963         if ( uuidstr ) {
1964                 new = uuidstr;
1965         } else {
1966                 new = (struct berval *)slap_sl_malloc( sizeof(struct berval), ctx );
1967         }
1968
1969         new->bv_len = 36;
1970
1971         if (( new->bv_val = slap_sl_malloc( new->bv_len + 1, ctx )) == NULL) {
1972                 if ( !uuidstr ) slap_sl_free( new, ctx );
1973                 return NULL;
1974         }
1975
1976         for ( i = 0; i < 16; i++ ) {
1977                 if ( i == 4 || i == 6 || i == 8 || i == 10 ) {
1978                         new->bv_val[(i<<1)+d] = '-';
1979                         d += 1;
1980                 }
1981
1982                 nibble = (normalized->bv_val[i] >> 4) & 0xF;
1983                 if ( nibble < 10 ) {
1984                         new->bv_val[(i<<1)+d] = nibble + '0';
1985                 } else {
1986                         new->bv_val[(i<<1)+d] = nibble - 10 + 'a';
1987                 }
1988
1989                 nibble = (normalized->bv_val[i]) & 0xF;
1990                 if ( nibble < 10 ) {
1991                         new->bv_val[(i<<1)+d+1] = nibble + '0';
1992                 } else {
1993                         new->bv_val[(i<<1)+d+1] = nibble - 10 + 'a';
1994                 }
1995         }
1996
1997         new->bv_val[new->bv_len] = '\0';
1998         return new;
1999 }
2000
2001 static int
2002 syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 )
2003 {
2004         const struct berval *uuid1 = v_uuid1;
2005         const struct berval *uuid2 = v_uuid2;
2006         int rc = uuid1->bv_len - uuid2->bv_len;
2007         if ( rc ) return rc;
2008         return ( memcmp( uuid1->bv_val, uuid2->bv_val, uuid1->bv_len ) );
2009 }
2010
2011 static void
2012 avl_ber_bvfree( void *bv )
2013 {
2014         if( bv == NULL ) return;
2015         if ( ((struct berval *)bv)->bv_val != NULL ) {
2016                 ch_free( ((struct berval *)bv)->bv_val );
2017         }
2018         ch_free( (char *) bv );
2019 }