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