]> git.sur5r.net Git - openldap/blob - servers/slapd/syncrepl.c
ITS#3092: Rename sl_free() and friends to slap_sl_free()
[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         /* get syncrepl cookie of shadow replica from subentry */
307         assert( si->si_rid < 1000 );
308         syncrepl_cn_bv.bv_val = syncrepl_cbuf;
309         syncrepl_cn_bv.bv_len = snprintf(syncrepl_cbuf, sizeof(syncrepl_cbuf),
310                 CN_STR "syncrepl%ld", si->si_rid );
311         build_new_dn( &op->o_req_ndn, psub, &syncrepl_cn_bv, op->o_tmpmemctx );
312         op->o_req_dn = op->o_req_ndn;
313
314         LDAP_STAILQ_FOREACH( sc, &slap_sync_cookie, sc_next ) {
315                 if ( si->si_rid == sc->rid ) {
316                         cmdline_cookie_found = 1;
317                         break;
318                 }
319         }
320
321         if ( cmdline_cookie_found ) {
322                 /* cookie is supplied in the command line */
323                 BerVarray cookie = NULL;
324                 struct berval cookie_bv;
325
326                 LDAP_STAILQ_REMOVE( &slap_sync_cookie, sc, sync_cookie, sc_next );
327                 slap_sync_cookie_free( &si->si_syncCookie, 0 );
328
329                 /* read stored cookie if it exists */
330                 backend_attribute( op, NULL, &op->o_req_ndn,
331                         slap_schema.si_ad_syncreplCookie, &cookie );
332
333                 if ( !cookie ) {
334                         /* no stored cookie */
335                         if ( sc->ctxcsn == NULL ||
336                                  sc->ctxcsn->bv_val == NULL ) {
337                                 /* if cmdline cookie does not have ctxcsn */
338                                 /* component, set it to an initial value */
339                                 slap_init_sync_cookie_ctxcsn( sc );
340                         }
341                         slap_dup_sync_cookie( &si->si_syncCookie, sc );
342                         slap_sync_cookie_free( sc, 1 );
343                         sc = NULL;
344
345                 } else {
346                         /* stored cookie */
347                         struct berval newcookie = BER_BVNULL;
348                         ber_dupbv( &cookie_bv, &cookie[0] );
349                         ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv );
350                         slap_parse_sync_cookie( &si->si_syncCookie );
351                         ber_bvarray_free( si->si_syncCookie.octet_str );
352                         si->si_syncCookie.octet_str = NULL;
353                         ber_bvarray_free_x( cookie, op->o_tmpmemctx );
354                         if ( sc->sid != -1 ) {
355                                 /* command line cookie wins */
356                                 si->si_syncCookie.sid = sc->sid;
357                         }
358                         if ( sc->ctxcsn != NULL ) {
359                                 /* command line cookie wins */
360                                 if ( si->si_syncCookie.ctxcsn ) {
361                                         ber_bvarray_free( si->si_syncCookie.ctxcsn );
362                                         si->si_syncCookie.ctxcsn = NULL;
363                                 }
364                                 ber_dupbv( &cookie_bv, &sc->ctxcsn[0] );
365                                 ber_bvarray_add( &si->si_syncCookie.ctxcsn, &cookie_bv );
366                         }
367                         if ( sc->rid != -1 ) {
368                                 /* command line cookie wins */
369                                 si->si_syncCookie.rid = sc->rid;
370                         }
371                         slap_sync_cookie_free( sc, 1 );
372                         sc = NULL;
373                         slap_compose_sync_cookie( NULL, &newcookie,
374                                         &si->si_syncCookie.ctxcsn[0],
375                                         si->si_syncCookie.sid, si->si_syncCookie.rid );
376                         ber_bvarray_add( &si->si_syncCookie.octet_str, &newcookie );
377                 }
378
379         } else {
380                 /* no command line cookie is specified */
381                 if ( si->si_syncCookie.octet_str == NULL ) {
382                         BerVarray cookie = NULL;
383                         struct berval cookie_bv;
384                         /* try to read stored cookie */
385                         backend_attribute( op, NULL, &op->o_req_ndn,
386                                 slap_schema.si_ad_syncreplCookie, &cookie );
387                         if ( cookie ) {
388                                 ber_dupbv( &cookie_bv, &cookie[0] );
389                                 ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv );
390                                 slap_parse_sync_cookie( &si->si_syncCookie );
391                                 ber_bvarray_free_x( cookie, op->o_tmpmemctx );
392                         }
393                 }
394         }
395
396         rc = ldap_sync_search( si, op->o_tmpmemctx );
397
398         if( rc != LDAP_SUCCESS ) {
399 #ifdef NEW_LOGGING
400                 LDAP_LOG ( OPERATION, ERR, "do_syncrep1: "
401                         "ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 );
402 #else
403                 Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
404                         "ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 );
405 #endif
406         }
407
408 done:
409         if ( rc ) {
410                 if ( si->si_ld ) {
411                         ldap_unbind( si->si_ld );
412                         si->si_ld = NULL;
413                 }
414         }
415
416         return rc;
417 }
418
419 static int
420 do_syncrep2(
421         Operation *op,
422         syncinfo_t *si )
423 {
424         LDAPControl     **rctrls = NULL;
425         LDAPControl     *rctrlp;
426
427         BerElementBuffer berbuf;
428         BerElement      *ber = (BerElement *)&berbuf;
429
430         LDAPMessage     *res = NULL;
431         LDAPMessage     *msg = NULL;
432
433         char            *retoid = NULL;
434         struct berval   *retdata = NULL;
435
436         Entry           *entry = NULL;
437
438         int             syncstate;
439         struct berval   syncUUID = BER_BVNULL;
440         struct sync_cookie      syncCookie = { NULL, -1, NULL };
441         struct sync_cookie      syncCookie_req = { NULL, -1, NULL };
442         struct berval           cookie = BER_BVNULL;
443
444         int     rc, err, i;
445         ber_len_t       len;
446
447         int rc_efree = 1;
448
449         struct berval   *psub;
450         Modifications   *modlist = NULL;
451
452         const char              *text;
453         int                             match;
454
455         struct timeval *tout_p = NULL;
456         struct timeval tout = { 0, 0 };
457
458         int             refreshDeletes = 0;
459         int             refreshDone = 1;
460         BerVarray syncUUIDs = NULL;
461         ber_tag_t si_tag;
462
463         if ( slapd_shutdown ) {
464                 rc = -2;
465                 goto done;
466         }
467
468         ber_init2( ber, NULL, LBER_USE_DER );
469         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
470
471 #ifdef NEW_LOGGING
472         LDAP_LOG ( OPERATION, DETAIL1, "do_syncrep2\n", 0, 0, 0 );
473 #else
474         Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2\n", 0, 0, 0 );
475 #endif
476
477         psub = &si->si_be->be_nsuffix[0];
478
479         slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie );
480
481         if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
482                 tout_p = &tout;
483         } else {
484                 tout_p = NULL;
485         }
486
487         while (( rc = ldap_result( si->si_ld, LDAP_RES_ANY, LDAP_MSG_ONE,
488                 tout_p, &res )) > 0 )
489         {
490                 if ( slapd_shutdown ) {
491                         rc = -2;
492                         goto done;
493                 }
494                 for( msg = ldap_first_message( si->si_ld, res );
495                         msg != NULL;
496                         msg = ldap_next_message( si->si_ld, msg ) )
497                 {
498                         switch( ldap_msgtype( msg ) ) {
499                         case LDAP_RES_SEARCH_ENTRY:
500                                 ldap_get_entry_controls( si->si_ld, msg, &rctrls );
501                                 /* we can't work without the control */
502                                 if ( !rctrls ) {
503                                         rc = -1;
504                                         goto done;
505                                 }
506                                 rctrlp = *rctrls;
507                                 ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
508                                 ber_scanf( ber, "{em" /*"}"*/, &syncstate, &syncUUID );
509                                 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
510                                         ber_scanf( ber, /*"{"*/ "m}", &cookie );
511                                         if ( cookie.bv_val ) {
512                                                 struct berval tmp_bv;
513                                                 ber_dupbv( &tmp_bv, &cookie );
514                                                 ber_bvarray_add( &syncCookie.octet_str, &tmp_bv );
515                                         }
516                                         if ( syncCookie.octet_str &&
517                                                         syncCookie.octet_str[0].bv_val )
518                                                 slap_parse_sync_cookie( &syncCookie );
519                                 }
520                                 if ( syncrepl_message_to_entry( si, op, msg,
521                                         &modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
522                                         rc_efree = syncrepl_entry( si, op, entry, modlist,
523                                                 syncstate, &syncUUID, &syncCookie_req );
524                                         if ( syncCookie.octet_str &&
525                                                 syncCookie.octet_str[0].bv_val )
526                                         {
527                                                 syncrepl_updateCookie( si, op, psub, &syncCookie );
528                                         }
529                                 }
530                                 ldap_controls_free( rctrls );
531                                 if ( modlist ) {
532                                         slap_mods_free( modlist );
533                                 }
534                                 if ( rc_efree && entry ) {
535                                         entry_free( entry );
536                                         entry = NULL;
537                                 }
538                                 break;
539
540                         case LDAP_RES_SEARCH_REFERENCE:
541 #ifdef NEW_LOGGING
542                                 LDAP_LOG( OPERATION, ERR,
543                                         "do_syncrep2 : reference received\n", 0, 0, 0 );
544 #else
545                                 Debug( LDAP_DEBUG_ANY,
546                                         "do_syncrep2 : reference received\n", 0, 0, 0 );
547 #endif
548                                 break;
549
550                         case LDAP_RES_SEARCH_RESULT:
551                                 ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL,
552                                         &rctrls, 0 );
553                                 if ( rctrls ) {
554                                         rctrlp = *rctrls;
555                                         ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
556
557                                         ber_scanf( ber, "{" /*"}"*/);
558                                         if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
559                                                 ber_scanf( ber, "m", &cookie );
560                                                 if ( cookie.bv_val ) {
561                                                         struct berval tmp_bv;
562                                                         ber_dupbv( &tmp_bv, &cookie );
563                                                         ber_bvarray_add( &syncCookie.octet_str, &tmp_bv);
564                                                 }
565                                                 if ( syncCookie.octet_str &&
566                                                         syncCookie.octet_str[0].bv_val )
567                                                 {
568                                                         slap_parse_sync_cookie( &syncCookie );
569                                                 }
570                                         }
571                                         if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES )
572                                         {
573                                                 ber_scanf( ber, "b", &refreshDeletes );
574                                         }
575                                         ber_scanf( ber, /*"{"*/ "}" );
576                                 }
577                                 if ( syncCookie_req.ctxcsn == NULL ) {
578                                         match = -1;
579                                 } else if ( syncCookie.ctxcsn == NULL ) {
580                                         match = 1;
581                                 } else {
582                                         value_match( &match, slap_schema.si_ad_entryCSN,
583                                                 slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
584                                                 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
585                                                 &syncCookie_req.ctxcsn[0], &syncCookie.ctxcsn[0],
586                                                 &text );
587                                 }
588                                 if ( syncCookie.octet_str && syncCookie.octet_str->bv_val &&
589                                         match < 0 && err == LDAP_SUCCESS )
590                                 {
591                                         syncrepl_updateCookie( si, op, psub, &syncCookie );
592                                 }
593                                 if ( rctrls ) {
594                                         ldap_controls_free( rctrls );
595                                 }
596                                 if (si->si_type != LDAP_SYNC_REFRESH_AND_PERSIST) {
597                                         /* FIXME : different error behaviors according to
598                                          *      1) err code : LDAP_BUSY ...
599                                          *      2) on err policy : stop service, stop sync, retry
600                                          */
601                                         if ( refreshDeletes == 0 && match < 0 &&
602                                                 err == LDAP_SUCCESS )
603                                         {
604                                                 syncrepl_del_nonpresent( op, si );
605                                         } else {
606                                                 avl_free( si->si_presentlist, avl_ber_bvfree );
607                                                 si->si_presentlist = NULL;
608                                         }
609                                 }
610                                 rc = -2;
611                                 goto done;
612                                 break;
613
614                         case LDAP_RES_INTERMEDIATE:
615                                 rc = ldap_parse_intermediate( si->si_ld, msg,
616                                         &retoid, &retdata, NULL, 0 );
617                                 if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) {
618                                         int             si_refreshDelete = 0;
619                                         int             si_refreshPresent = 0;
620                                         ber_init2( ber, retdata, LBER_USE_DER );
621
622                                         switch ( si_tag = ber_peek_tag( ber, &len )) {
623                                         ber_tag_t tag;
624                                         case LDAP_TAG_SYNC_NEW_COOKIE:
625                                                 ber_scanf( ber, "tm", &tag, &cookie );
626                                                 break;
627                                         case LDAP_TAG_SYNC_REFRESH_DELETE:
628                                                 si_refreshDelete = 1;
629                                         case LDAP_TAG_SYNC_REFRESH_PRESENT:
630                                                 si_refreshPresent = 1;
631                                                 ber_scanf( ber, "t{" /*"}"*/, &tag );
632                                                 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE )
633                                                 {
634                                                         ber_scanf( ber, "m", &cookie );
635                                                         if ( cookie.bv_val ) {
636                                                                 struct berval tmp_bv;
637                                                                 ber_dupbv( &tmp_bv, &cookie );
638                                                                 ber_bvarray_add( &syncCookie.octet_str,
639                                                                         &tmp_bv);
640                                                         }
641                                                         if ( syncCookie.octet_str &&
642                                                                 syncCookie.octet_str[0].bv_val )
643                                                         {
644                                                                 slap_parse_sync_cookie( &syncCookie );
645                                                         }
646                                                 }
647                                                 if ( ber_peek_tag( ber, &len ) ==
648                                                         LDAP_TAG_REFRESHDONE )
649                                                 {
650                                                         ber_scanf( ber, "b", &refreshDone );
651                                                 }
652                                                 ber_scanf( ber, /*"{"*/ "}" );
653                                                 break;
654                                         case LDAP_TAG_SYNC_ID_SET:
655                                                 ber_scanf( ber, "t{" /*"}"*/, &tag );
656                                                 if ( ber_peek_tag( ber, &len ) ==
657                                                         LDAP_TAG_SYNC_COOKIE )
658                                                 {
659                                                         ber_scanf( ber, "m", &cookie );
660                                                         if ( cookie.bv_val ) {
661                                                                 struct berval tmp_bv;
662                                                                 ber_dupbv( &tmp_bv, &cookie );
663                                                                 ber_bvarray_add( &syncCookie.octet_str,
664                                                                         &tmp_bv );
665                                                         }
666                                                         if ( syncCookie.octet_str &&
667                                                                 syncCookie.octet_str[0].bv_val )
668                                                         {
669                                                                 slap_parse_sync_cookie( &syncCookie );
670                                                         }
671                                                 }
672                                                 if ( ber_peek_tag( ber, &len ) ==
673                                                         LDAP_TAG_REFRESHDELETES )
674                                                 {
675                                                         ber_scanf( ber, "b", &refreshDeletes );
676                                                 }
677                                                 ber_scanf( ber, "[W]", &syncUUIDs );
678                                                 ber_scanf( ber, /*"{"*/ "}" );
679                                                 for ( i = 0; syncUUIDs[i].bv_val; i++ ) {
680                                                         struct berval *syncuuid_bv;
681                                                         syncuuid_bv = ber_dupbv( NULL, &syncUUIDs[i] );
682                                                         avl_insert( &si->si_presentlist,
683                                                                 (caddr_t) syncuuid_bv,
684                                                                 syncuuid_cmp, avl_dup_error );
685                                                 }
686                                                 ber_memfree_x( syncUUIDs, op->o_tmpmemctx );
687                                                 break;
688                                         default:
689 #ifdef NEW_LOGGING
690                                         LDAP_LOG( OPERATION, ERR,
691                                                 "do_syncrep2 : unknown syncinfo tag (%ld)\n",
692                                                 (long) si_tag, 0, 0 );
693 #else
694                                         Debug( LDAP_DEBUG_ANY,
695                                                 "do_syncrep2 : unknown syncinfo tag (%ld)\n",
696                                                 (long) si_tag, 0, 0 );
697 #endif
698                                                 ldap_memfree( retoid );
699                                                 ber_bvfree( retdata );
700                                                 continue;
701                                         }
702
703                                         if ( syncCookie_req.ctxcsn == NULL ) {
704                                                 match = -1;
705                                         } else if ( syncCookie.ctxcsn == NULL ) {
706                                                 match = 1;
707                                         } else {
708                                                 value_match( &match, slap_schema.si_ad_entryCSN,
709                                                         slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
710                                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
711                                                         &syncCookie_req.ctxcsn[0],
712                                                         &syncCookie.ctxcsn[0], &text );
713                                         }
714
715                                         if ( syncCookie.ctxcsn && syncCookie.ctxcsn[0].bv_val &&
716                                                 match < 0 )
717                                         {
718                                                 syncrepl_updateCookie( si, op, psub, &syncCookie);
719                                         }
720
721                                         if ( si_refreshPresent == 1 ) {
722                                                 if ( match < 0 ) {
723                                                         syncrepl_del_nonpresent( op, si );
724                                                 }
725                                         } 
726
727                                         ldap_memfree( retoid );
728                                         ber_bvfree( retdata );
729                                         break;
730
731                                 } else {
732 #ifdef NEW_LOGGING
733                                         LDAP_LOG( OPERATION, ERR, "do_syncrep2 :"
734                                                 " unknown intermediate "
735                                                 "response\n", 0, 0, 0 );
736 #else
737                                         Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
738                                                 "unknown intermediate response (%d)\n",
739                                                 rc, 0, 0 );
740 #endif
741                                         ldap_memfree( retoid );
742                                         ber_bvfree( retdata );
743                                         break;
744                                 }
745                                 break;
746
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         slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
967         slap_sl_free( dn.bv_val, op->o_tmpmemctx );
968
969         if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE ) {
970                 return LDAP_SUCCESS;
971         }
972
973         if ( entry == NULL ) {
974                 return -1;
975         }
976
977         e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
978         *entry = e;
979         e->e_name = op->o_req_dn;
980         e->e_nname = op->o_req_ndn;
981
982         while ( ber_remaining( ber ) ) {
983                 if ( (ber_scanf( ber, "{mW}", &tmp.sml_type, &tmp.sml_values ) ==
984                         LBER_ERROR ) || ( tmp.sml_type.bv_val == NULL ))
985                 {
986                         break;
987                 }
988
989                 mod  = (Modifications *) ch_malloc( sizeof( Modifications ));
990
991                 mod->sml_op = LDAP_MOD_REPLACE;
992                 mod->sml_next = NULL;
993                 mod->sml_desc = NULL;
994                 mod->sml_type = tmp.sml_type;
995                 mod->sml_values = tmp.sml_values;
996                 mod->sml_nvalues = NULL;
997
998                 *modtail = mod;
999                 modtail = &mod->sml_next;
1000         }
1001
1002         if ( *modlist == NULL ) {
1003 #ifdef NEW_LOGGING
1004                 LDAP_LOG( OPERATION, ERR,
1005                         "syncrepl_message_to_entry: no attributes\n", 0, 0, 0 );
1006 #else
1007                 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: no attributes\n",
1008                         0, 0, 0 );
1009 #endif
1010         }
1011
1012         rc = slap_mods_check( *modlist, 1, &text, txtbuf, textlen, NULL );
1013
1014         if ( rc != LDAP_SUCCESS ) {
1015 #ifdef NEW_LOGGING
1016                 LDAP_LOG( OPERATION, ERR,
1017                         "syncrepl_message_to_entry: mods check (%s)\n", text, 0, 0 );
1018 #else
1019                 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods check (%s)\n",
1020                         text, 0, 0 );
1021 #endif
1022                 goto done;
1023         }
1024         
1025         rc = slap_mods2entry( *modlist, &e, 1, 1, &text, txtbuf, textlen);
1026         if( rc != LDAP_SUCCESS ) {
1027 #ifdef NEW_LOGGING
1028                 LDAP_LOG( OPERATION, ERR,
1029                         "syncrepl_message_to_entry: mods2entry (%s)\n", text, 0, 0 );
1030 #else
1031                 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods2entry (%s)\n",
1032                         text, 0, 0 );
1033 #endif
1034         }
1035
1036 done:
1037         ber_free ( ber, 0 );
1038         if ( rc != LDAP_SUCCESS ) {
1039                 entry_free( e );
1040                 e = NULL;
1041         }
1042
1043         return rc;
1044 }
1045
1046 int
1047 syncrepl_entry(
1048         syncinfo_t* si,
1049         Operation *op,
1050         Entry* e,
1051         Modifications* modlist,
1052         int syncstate,
1053         struct berval* syncUUID,
1054         struct sync_cookie* syncCookie_req )
1055 {
1056         Backend *be = op->o_bd;
1057         slap_callback   cb = { NULL };
1058         struct berval   *syncuuid_bv = NULL;
1059         struct berval   syncUUID_strrep = BER_BVNULL;
1060         struct berval   uuid_bv = BER_BVNULL;
1061
1062         SlapReply       rs = {REP_RESULT};
1063         Filter f = {0};
1064         AttributeAssertion ava = {0};
1065         int rc = LDAP_SUCCESS;
1066         int ret = LDAP_SUCCESS;
1067         const char *text;
1068
1069         struct berval pdn = BER_BVNULL;
1070         struct berval org_req_dn = BER_BVNULL;
1071         struct berval org_req_ndn = BER_BVNULL;
1072         struct berval org_dn = BER_BVNULL;
1073         struct berval org_ndn = BER_BVNULL;
1074         int     org_managedsait;
1075
1076         if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD )) {
1077                 syncuuid_bv = ber_dupbv( NULL, syncUUID );
1078                 avl_insert( &si->si_presentlist, (caddr_t) syncuuid_bv,
1079                         syncuuid_cmp, avl_dup_error );
1080         }
1081
1082         if ( syncstate == LDAP_SYNC_PRESENT ) {
1083                 return e ? 1 : 0;
1084         }
1085
1086         f.f_choice = LDAP_FILTER_EQUALITY;
1087         f.f_ava = &ava;
1088         ava.aa_desc = slap_schema.si_ad_entryUUID;
1089         slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
1090         ava.aa_value = *syncUUID;
1091         op->ors_filter = &f;
1092
1093         op->ors_filterstr.bv_len = (sizeof("entryUUID=")-1) + syncUUID->bv_len;
1094         op->ors_filterstr.bv_val = (char *) slap_sl_malloc(
1095                 op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); 
1096         AC_MEMCPY( op->ors_filterstr.bv_val, "entryUUID=", sizeof("entryUUID=")-1 );
1097         AC_MEMCPY( &op->ors_filterstr.bv_val[sizeof("entryUUID=")-1],
1098                 syncUUID->bv_val, syncUUID->bv_len );
1099         op->ors_filterstr.bv_val[op->ors_filterstr.bv_len] = '\0';
1100
1101         op->o_tag = LDAP_REQ_SEARCH;
1102         op->ors_scope = LDAP_SCOPE_SUBTREE;
1103
1104         /* get syncrepl cookie of shadow replica from subentry */
1105         op->o_req_dn = si->si_base;
1106         op->o_req_ndn = si->si_base;
1107
1108         /* set callback function */
1109         op->o_callback = &cb;
1110         cb.sc_response = dn_callback;
1111         cb.sc_private = si;
1112
1113         si->si_syncUUID_ndn.bv_val = NULL;
1114
1115         if ( limits_check( op, &rs ) == 0 ) {
1116                 rc = be->be_search( op, &rs );
1117         }
1118
1119         if ( op->ors_filterstr.bv_val ) {
1120                 slap_sl_free( op->ors_filterstr.bv_val, op->o_tmpmemctx );
1121         }
1122
1123         cb.sc_response = null_callback;
1124         cb.sc_private = si;
1125
1126         if ( rc == LDAP_SUCCESS && si->si_syncUUID_ndn.bv_val ) {
1127                 char *subseq_ptr;
1128
1129                 if ( syncstate != LDAP_SYNC_DELETE ) {
1130                         op->o_no_psearch = 1;
1131                 }
1132
1133                 ber_dupbv( &op->o_sync_csn, syncCookie_req->ctxcsn );
1134                 if ( op->o_sync_csn.bv_val ) {
1135                         subseq_ptr = strstr( op->o_sync_csn.bv_val, "#0000" );
1136                         subseq_ptr += 4;
1137                         *subseq_ptr = '1';
1138                 }
1139                 
1140                 op->o_req_dn = si->si_syncUUID_ndn;
1141                 op->o_req_ndn = si->si_syncUUID_ndn;
1142                 op->o_tag = LDAP_REQ_DELETE;
1143                 rc = be->be_delete( op, &rs );
1144
1145                 org_req_dn = op->o_req_dn;
1146                 org_req_ndn = op->o_req_ndn;
1147                 org_dn = op->o_dn;
1148                 org_ndn = op->o_ndn;
1149                 org_managedsait = get_manageDSAit( op );
1150                 op->o_dn = op->o_bd->be_rootdn;
1151                 op->o_ndn = op->o_bd->be_rootndn;
1152                 op->o_managedsait = 1;
1153
1154                 while ( rs.sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) {
1155                         op->o_delete_glue_parent = 0;
1156                         if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
1157                                 slap_callback cb = { NULL };
1158                                 cb.sc_response = slap_null_cb;
1159                                 dnParent( &op->o_req_ndn, &pdn );
1160                                 op->o_req_dn = pdn;
1161                                 op->o_req_ndn = pdn;
1162                                 op->o_callback = &cb;
1163                                 op->o_bd->be_delete( op, &rs );
1164                         } else {
1165                                 break;
1166                     }
1167                 }
1168
1169                 op->o_managedsait = org_managedsait;
1170                 op->o_dn = org_dn;
1171                 op->o_ndn = org_ndn;
1172                 op->o_req_dn = org_req_dn;
1173                 op->o_req_ndn = org_req_ndn;
1174                 op->o_delete_glue_parent = 0;
1175
1176                 op->o_no_psearch = 0;
1177         }
1178
1179         switch ( syncstate ) {
1180         case LDAP_SYNC_ADD:
1181         case LDAP_SYNC_MODIFY:
1182                 if ( rc == LDAP_SUCCESS ||
1183                          rc == LDAP_REFERRAL ||
1184                          rc == LDAP_NO_SUCH_OBJECT ||
1185                          rc == LDAP_NOT_ALLOWED_ON_NONLEAF )
1186                 {
1187                         attr_delete( &e->e_attrs, slap_schema.si_ad_entryUUID );
1188                         attr_merge_one( e, slap_schema.si_ad_entryUUID,
1189                                 syncUUID, &ava.aa_value );
1190
1191                         op->o_tag = LDAP_REQ_ADD;
1192                         op->ora_e = e;
1193                         op->o_req_dn = e->e_name;
1194                         op->o_req_ndn = e->e_nname;
1195                         rc = be->be_add( op, &rs );
1196
1197                         if ( rc != LDAP_SUCCESS ) {
1198                                 if ( rc == LDAP_ALREADY_EXISTS ) {
1199                                         Modifications *mod;
1200                                         Modifications *modtail = modlist;
1201
1202                                         assert( modlist );
1203
1204                                         for ( mod = modlist; mod != NULL; mod = mod->sml_next ) {
1205                                                 modtail = mod;
1206                                         }
1207
1208                                         mod = (Modifications *)ch_calloc(1, sizeof(Modifications));
1209                                         ber_dupbv( &uuid_bv, syncUUID );
1210                                         mod->sml_op = LDAP_MOD_REPLACE;
1211                                         mod->sml_desc = slap_schema.si_ad_entryUUID;
1212                                         mod->sml_type = mod->sml_desc->ad_cname;
1213                                         ber_bvarray_add( &mod->sml_values, &uuid_bv );
1214                                         modtail->sml_next = mod;
1215                                         
1216                                         op->o_tag = LDAP_REQ_MODIFY;
1217                                         op->orm_modlist = modlist;
1218                                         op->o_req_dn = e->e_name;
1219                                         op->o_req_ndn = e->e_nname;
1220
1221                                         rc = be->be_modify( op, &rs );
1222                                         if ( rc != LDAP_SUCCESS ) {
1223 #ifdef NEW_LOGGING
1224                                                 LDAP_LOG( OPERATION, ERR,
1225                                                         "syncrepl_entry : be_modify failed (%d)\n",
1226                                                         rc, 0, 0 );
1227 #else
1228                                                 Debug( LDAP_DEBUG_ANY,
1229                                                         "syncrepl_entry : be_modify failed (%d)\n",
1230                                                         rc, 0, 0 );
1231 #endif
1232                                         }
1233                                         ret = 1;
1234                                         goto done;
1235                                 } else if ( rc == LDAP_REFERRAL || rc == LDAP_NO_SUCH_OBJECT ) {
1236                                         syncrepl_add_glue( op, e );
1237                                         ret = 0;
1238                                         goto done;
1239                                 } else {
1240 #ifdef NEW_LOGGING
1241                                         LDAP_LOG( OPERATION, ERR,
1242                                                 "syncrepl_entry : be_add failed (%d)\n",
1243                                                 rc, 0, 0 );
1244 #else
1245                                         Debug( LDAP_DEBUG_ANY,
1246                                                 "syncrepl_entry : be_add failed (%d)\n",
1247                                                 rc, 0, 0 );
1248 #endif
1249                                         ret = 1;
1250                                         goto done;
1251                                 }
1252                         } else {
1253                                 be_entry_release_w( op, e );
1254                                 ret = 0;
1255                                 goto done;
1256                         }
1257                 } else {
1258 #ifdef NEW_LOGGING
1259                         LDAP_LOG( OPERATION, ERR,
1260                                 "syncrepl_entry : be_search failed (%d)\n", rc, 0, 0 );
1261 #else
1262                         Debug( LDAP_DEBUG_ANY,
1263                                 "syncrepl_entry : be_search failed (%d)\n", rc, 0, 0 );
1264 #endif
1265                         ret = 1;
1266                         goto done;
1267                 }
1268
1269         case LDAP_SYNC_DELETE :
1270                 /* Already deleted */
1271                 ret = 0;
1272                 goto done;
1273
1274         default :
1275 #ifdef NEW_LOGGING
1276                 LDAP_LOG( OPERATION, ERR,
1277                         "syncrepl_entry : unknown syncstate\n", 0, 0, 0 );
1278 #else
1279                 Debug( LDAP_DEBUG_ANY,
1280                         "syncrepl_entry : unknown syncstate\n", 0, 0, 0 );
1281 #endif
1282                 ret = 1;
1283                 goto done;
1284         }
1285
1286 done :
1287
1288         if ( syncUUID_strrep.bv_val ) {
1289                 ber_memfree_x( syncUUID_strrep.bv_val, op->o_tmpmemctx );
1290         }
1291         if ( si->si_syncUUID_ndn.bv_val ) {
1292                 ber_memfree_x( si->si_syncUUID_ndn.bv_val, op->o_tmpmemctx );
1293         }
1294         return ret;
1295 }
1296
1297 static struct berval gcbva[] = {
1298         BER_BVC("top"),
1299         BER_BVC("glue"),
1300         BER_BVNULL
1301 };
1302
1303 static void
1304 syncrepl_del_nonpresent(
1305         Operation *op,
1306         syncinfo_t *si )
1307 {
1308         Backend* be = op->o_bd;
1309         slap_callback   cb = { NULL };
1310         SlapReply       rs = {REP_RESULT};
1311         struct nonpresent_entry *np_list, *np_prev;
1312         int rc;
1313         Modifications *ml;
1314         Modifications *mlnext;
1315         Modifications *mod;
1316         Modifications *modlist = NULL;
1317         Modifications **modtail = &modlist;
1318         Attribute       *attr;
1319
1320         struct berval pdn = BER_BVNULL;
1321         struct berval org_req_dn = BER_BVNULL;
1322         struct berval org_req_ndn = BER_BVNULL;
1323         struct berval org_dn = BER_BVNULL;
1324         struct berval org_ndn = BER_BVNULL;
1325         int     org_managedsait;
1326
1327         op->o_req_dn = si->si_base;
1328         op->o_req_ndn = si->si_base;
1329
1330         cb.sc_response = nonpresent_callback;
1331         cb.sc_private = si;
1332
1333         op->o_callback = &cb;
1334         op->o_tag = LDAP_REQ_SEARCH;
1335         op->ors_scope = si->si_scope;
1336         op->ors_deref = LDAP_DEREF_NEVER;
1337         op->ors_slimit = 0;
1338         op->ors_tlimit = 0;
1339         op->ors_attrsonly = 0;
1340         op->ors_attrs = NULL;
1341         op->ors_filter = str2filter_x( op, si->si_filterstr.bv_val );
1342         op->ors_filterstr = si->si_filterstr;
1343
1344         op->o_nocaching = 1;
1345         op->o_managedsait = 0;
1346
1347         if ( limits_check( op, &rs ) == 0 ) {
1348                 be->be_search( op, &rs );
1349         }
1350
1351         op->o_managedsait = 1;
1352         op->o_nocaching = 0;
1353
1354         if ( op->ors_filter ) filter_free_x( op, op->ors_filter );
1355
1356         if ( !LDAP_LIST_EMPTY( &si->si_nonpresentlist ) ) {
1357                 np_list = LDAP_LIST_FIRST( &si->si_nonpresentlist );
1358                 while ( np_list != NULL ) {
1359                         LDAP_LIST_REMOVE( np_list, npe_link );
1360                         np_prev = np_list;
1361                         np_list = LDAP_LIST_NEXT( np_list, npe_link );
1362                         op->o_tag = LDAP_REQ_DELETE;
1363                         op->o_callback = &cb;
1364                         cb.sc_response = null_callback;
1365                         cb.sc_private = si;
1366                         op->o_req_dn = *np_prev->npe_name;
1367                         op->o_req_ndn = *np_prev->npe_nname;
1368                         rc = op->o_bd->be_delete( op, &rs );
1369
1370                         if ( rc == LDAP_NOT_ALLOWED_ON_NONLEAF ) {
1371                                 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1372                                 mod->sml_op = LDAP_MOD_REPLACE;
1373                                 mod->sml_desc = slap_schema.si_ad_objectClass;
1374                                 mod->sml_type = mod->sml_desc->ad_cname;
1375                                 mod->sml_values = &gcbva[0];
1376                                 *modtail = mod;
1377                                 modtail = &mod->sml_next;
1378
1379                                 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1380                                 mod->sml_op = LDAP_MOD_REPLACE;
1381                                 mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
1382                                 mod->sml_type = mod->sml_desc->ad_cname;
1383                                 mod->sml_values = &gcbva[1];
1384                                 *modtail = mod;
1385                                 modtail = &mod->sml_next;
1386
1387                                 op->o_tag = LDAP_REQ_MODIFY;
1388                                 op->orm_modlist = modlist;
1389
1390                                 rc = be->be_modify( op, &rs );
1391
1392                                 for ( ml = modlist; ml != NULL; ml = mlnext ) {
1393                                         mlnext = ml->sml_next;
1394                                         free( ml );
1395                                 }
1396                         }
1397
1398                         org_req_dn = op->o_req_dn;
1399                         org_req_ndn = op->o_req_ndn;
1400                         org_dn = op->o_dn;
1401                         org_ndn = op->o_ndn;
1402                         org_managedsait = get_manageDSAit( op );
1403                         op->o_dn = op->o_bd->be_rootdn;
1404                         op->o_ndn = op->o_bd->be_rootndn;
1405                         op->o_managedsait = 1;
1406
1407                         while ( rs.sr_err == LDAP_SUCCESS &&
1408                                         op->o_delete_glue_parent ) {
1409                                 op->o_delete_glue_parent = 0;
1410                                 if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
1411                                         slap_callback cb = { NULL };
1412                                         cb.sc_response = slap_null_cb;
1413                                         dnParent( &op->o_req_ndn, &pdn );
1414                                         op->o_req_dn = pdn;
1415                                         op->o_req_ndn = pdn;
1416                                         op->o_callback = &cb;
1417                                         /* give it a root privil ? */
1418                                         op->o_bd->be_delete( op, &rs );
1419                                 } else {
1420                                         break;
1421                             }
1422                         }
1423
1424                         op->o_managedsait = org_managedsait;
1425                         op->o_dn = org_dn;
1426                         op->o_ndn = org_ndn;
1427                         op->o_req_dn = org_req_dn;
1428                         op->o_req_ndn = org_req_ndn;
1429                         op->o_delete_glue_parent = 0;
1430
1431                         ber_bvfree( np_prev->npe_name );
1432                         ber_bvfree( np_prev->npe_nname );
1433                         op->o_req_dn.bv_val = NULL;
1434                         op->o_req_ndn.bv_val = NULL;
1435                         ch_free( np_prev );
1436                 }
1437         }
1438
1439         return;
1440 }
1441
1442 void
1443 syncrepl_add_glue(
1444         Operation* op,
1445         Entry *e )
1446 {
1447         Backend *be = op->o_bd;
1448         slap_callback cb = { NULL };
1449         Attribute       *a;
1450         int     rc;
1451         int suffrdns;
1452         int i;
1453         struct berval dn = {0, NULL};
1454         struct berval ndn = {0, NULL};
1455         Entry   *glue;
1456         SlapReply       rs = {REP_RESULT};
1457         char    *ptr, *comma;
1458
1459         op->o_tag = LDAP_REQ_ADD;
1460         op->o_callback = &cb;
1461         cb.sc_response = null_callback;
1462         cb.sc_private = NULL;
1463
1464         dn = e->e_name;
1465         ndn = e->e_nname;
1466
1467         /* count RDNs in suffix */
1468         if ( be->be_nsuffix[0].bv_len ) {
1469                 for (i=0, ptr=be->be_nsuffix[0].bv_val; ptr; ptr=strchr( ptr, ',' )) {
1470                         ptr++;
1471                         i++;
1472                 }
1473                 suffrdns = i;
1474         } else {
1475                 /* suffix is "" */
1476                 suffrdns = 0;
1477         }
1478
1479         /* Start with BE suffix */
1480         for ( i = 0, ptr = NULL; i < suffrdns; i++ ) {
1481                 comma = strrchr(dn.bv_val, ',');
1482                 if ( ptr ) *ptr = ',';
1483                 if ( comma ) *comma = '\0';
1484                 ptr = comma;
1485         }
1486         if ( ptr ) {
1487                 *ptr++ = ',';
1488                 dn.bv_len -= ptr - dn.bv_val;
1489                 dn.bv_val = ptr;
1490         }
1491         /* the normalizedDNs are always the same length, no counting
1492          * required.
1493          */
1494         if ( ndn.bv_len > be->be_nsuffix[0].bv_len ) {
1495                 ndn.bv_val += ndn.bv_len - be->be_nsuffix[0].bv_len;
1496                 ndn.bv_len = be->be_nsuffix[0].bv_len;
1497         }
1498
1499         while ( ndn.bv_val > e->e_nname.bv_val ) {
1500                 glue = (Entry *) ch_calloc( 1, sizeof(Entry) );
1501                 ber_dupbv( &glue->e_name, &dn );
1502                 ber_dupbv( &glue->e_nname, &ndn );
1503
1504                 a = ch_calloc( 1, sizeof( Attribute ));
1505                 a->a_desc = slap_schema.si_ad_objectClass;
1506
1507                 a->a_vals = ch_calloc( 3, sizeof( struct berval ));
1508                 ber_dupbv( &a->a_vals[0], &gcbva[0] );
1509                 ber_dupbv( &a->a_vals[1], &gcbva[1] );
1510                 ber_dupbv( &a->a_vals[2], &gcbva[2] );
1511
1512                 a->a_nvals = a->a_vals;
1513
1514                 a->a_next = glue->e_attrs;
1515                 glue->e_attrs = a;
1516
1517                 a = ch_calloc( 1, sizeof( Attribute ));
1518                 a->a_desc = slap_schema.si_ad_structuralObjectClass;
1519
1520                 a->a_vals = ch_calloc( 2, sizeof( struct berval ));
1521                 ber_dupbv( &a->a_vals[0], &gcbva[1] );
1522                 ber_dupbv( &a->a_vals[1], &gcbva[2] );
1523
1524                 a->a_nvals = a->a_vals;
1525
1526                 a->a_next = glue->e_attrs;
1527                 glue->e_attrs = a;
1528
1529                 op->o_req_dn = glue->e_name;
1530                 op->o_req_ndn = glue->e_nname;
1531                 op->ora_e = glue;
1532                 rc = be->be_add ( op, &rs );
1533                 if ( rc == LDAP_SUCCESS ) {
1534                         be_entry_release_w( op, glue );
1535                 } else {
1536                 /* incl. ALREADY EXIST */
1537                         entry_free( glue );
1538                 }
1539
1540                 /* Move to next child */
1541                 for (ptr = dn.bv_val-2; ptr > e->e_name.bv_val && *ptr != ','; ptr--) {
1542                         /* empty */
1543                 }
1544                 if ( ptr == e->e_name.bv_val ) break;
1545                 dn.bv_val = ++ptr;
1546                 dn.bv_len = e->e_name.bv_len - (ptr-e->e_name.bv_val);
1547                 for( ptr = ndn.bv_val-2;
1548                         ptr > e->e_nname.bv_val && *ptr != ',';
1549                         ptr--)
1550                 {
1551                         /* empty */
1552                 }
1553                 ndn.bv_val = ++ptr;
1554                 ndn.bv_len = e->e_nname.bv_len - (ptr-e->e_nname.bv_val);
1555         }
1556
1557         op->o_req_dn = e->e_name;
1558         op->o_req_ndn = e->e_nname;
1559         op->ora_e = e;
1560         rc = be->be_add ( op, &rs );
1561         if ( rc == LDAP_SUCCESS ) {
1562                 be_entry_release_w( op, e );
1563         } else {
1564                 entry_free( e );
1565         }
1566
1567         return;
1568 }
1569
1570 static struct berval ocbva[] = {
1571         BER_BVC("top"),
1572         BER_BVC("subentry"),
1573         BER_BVC("syncConsumerSubentry"),
1574         BER_BVNULL
1575 };
1576
1577 static struct berval cnbva[] = {
1578         BER_BVNULL,
1579         BER_BVNULL
1580 };
1581
1582 static struct berval ssbva[] = {
1583         BER_BVC("{}"),
1584         BER_BVNULL
1585 };
1586
1587 static struct berval scbva[] = {
1588         BER_BVNULL,
1589         BER_BVNULL
1590 };
1591
1592 void
1593 syncrepl_updateCookie(
1594         syncinfo_t *si,
1595         Operation *op,
1596         struct berval *pdn,
1597         struct sync_cookie *syncCookie )
1598 {
1599         Backend *be = op->o_bd;
1600         Modifications *ml;
1601         Modifications *mlnext;
1602         Modifications *mod;
1603         Modifications *modlist = NULL;
1604         Modifications **modtail = &modlist;
1605
1606         const char      *text;
1607         char txtbuf[SLAP_TEXT_BUFLEN];
1608         size_t textlen = sizeof txtbuf;
1609
1610         Entry* e = NULL;
1611         int rc;
1612
1613         char syncrepl_cbuf[sizeof(CN_STR SYNCREPL_STR)];
1614         struct berval slap_syncrepl_dn_bv = BER_BVNULL;
1615         struct berval slap_syncrepl_cn_bv = BER_BVNULL;
1616         
1617         slap_callback cb = { NULL };
1618         SlapReply       rs = {REP_RESULT};
1619
1620         slap_sync_cookie_free( &si->si_syncCookie, 0 );
1621         slap_dup_sync_cookie( &si->si_syncCookie, syncCookie );
1622
1623         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1624         mod->sml_op = LDAP_MOD_REPLACE;
1625         mod->sml_desc = slap_schema.si_ad_objectClass;
1626         mod->sml_type = mod->sml_desc->ad_cname;
1627         mod->sml_values = ocbva;
1628         *modtail = mod;
1629         modtail = &mod->sml_next;
1630
1631         ber_dupbv( &cnbva[0], (struct berval *) &slap_syncrepl_bvc );
1632         assert( si->si_rid < 1000 );
1633         cnbva[0].bv_len = snprintf( cnbva[0].bv_val,
1634                 slap_syncrepl_bvc.bv_len + 1,
1635                 "syncrepl%ld", si->si_rid );
1636         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1637         mod->sml_op = LDAP_MOD_REPLACE;
1638         mod->sml_desc = slap_schema.si_ad_cn;
1639         mod->sml_type = mod->sml_desc->ad_cname;
1640         mod->sml_values = cnbva;
1641         *modtail = mod;
1642         modtail = &mod->sml_next;
1643
1644         if ( scbva[0].bv_val ) ch_free( scbva[0].bv_val );
1645         ber_dupbv( &scbva[0], &si->si_syncCookie.octet_str[0] );
1646         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1647         mod->sml_op = LDAP_MOD_REPLACE;
1648         mod->sml_desc = slap_schema.si_ad_syncreplCookie;
1649         mod->sml_type = mod->sml_desc->ad_cname;
1650         mod->sml_values = scbva;
1651         *modtail = mod;
1652         modtail = &mod->sml_next;
1653
1654         mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1655         mod->sml_op = LDAP_MOD_REPLACE;
1656         mod->sml_desc = slap_schema.si_ad_subtreeSpecification;
1657         mod->sml_type = mod->sml_desc->ad_cname;
1658         mod->sml_values = ssbva;
1659         *modtail = mod;
1660         modtail = &mod->sml_next;
1661
1662         mlnext = mod;
1663
1664         op->o_tag = LDAP_REQ_ADD;
1665         rc = slap_mods_opattrs( op, modlist, modtail,
1666                  &text, txtbuf, textlen );
1667
1668         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
1669                 ml->sml_op = LDAP_MOD_REPLACE;
1670         }
1671
1672         if( rc != LDAP_SUCCESS ) {
1673 #ifdef NEW_LOGGING
1674                 LDAP_LOG( OPERATION, ERR,
1675                         "syncrepl_updateCookie: mods opattrs (%s)\n", text, 0, 0 );
1676 #else
1677                 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods opattrs (%s)\n",
1678                          text, 0, 0 );
1679 #endif
1680         }
1681
1682         e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1683
1684         slap_syncrepl_cn_bv.bv_val = syncrepl_cbuf;
1685         assert( si->si_rid < 1000 );
1686         slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
1687                 slap_syncrepl_cn_bvc.bv_len + 1,
1688                 "cn=syncrepl%ld", si->si_rid );
1689
1690         build_new_dn( &slap_syncrepl_dn_bv, pdn, &slap_syncrepl_cn_bv,
1691                 op->o_tmpmemctx );
1692         ber_dupbv( &e->e_name, &slap_syncrepl_dn_bv );
1693         ber_dupbv( &e->e_nname, &slap_syncrepl_dn_bv );
1694
1695         if ( slap_syncrepl_dn_bv.bv_val ) {
1696                 slap_sl_free( slap_syncrepl_dn_bv.bv_val, op->o_tmpmemctx );
1697         }
1698
1699         e->e_attrs = NULL;
1700
1701         rc = slap_mods2entry( modlist, &e, 1, 1, &text, txtbuf, textlen );
1702
1703         if( rc != LDAP_SUCCESS ) {
1704 #ifdef NEW_LOGGING
1705                 LDAP_LOG( OPERATION, ERR,
1706                         "syncrepl_updateCookie: mods2entry (%s)\n", text, 0, 0 );
1707 #else
1708                 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods2entry (%s)\n",
1709                          text, 0, 0 );
1710 #endif
1711         }
1712
1713         cb.sc_response = null_callback;
1714         cb.sc_private = si;
1715
1716         op->o_callback = &cb;
1717         op->o_req_dn = e->e_name;
1718         op->o_req_ndn = e->e_nname;
1719
1720         /* update persistent cookie */
1721 update_cookie_retry:
1722         op->o_tag = LDAP_REQ_MODIFY;
1723         op->orm_modlist = modlist;
1724         rc = be->be_modify( op, &rs );
1725
1726         if ( rc != LDAP_SUCCESS ) {
1727                 if ( rc == LDAP_REFERRAL ||
1728                          rc == LDAP_NO_SUCH_OBJECT ) {
1729                         op->o_tag = LDAP_REQ_ADD;
1730                         op->ora_e = e;
1731                         rc = be->be_add( op, &rs );
1732                         if ( rc != LDAP_SUCCESS ) {
1733                                 if ( rc == LDAP_ALREADY_EXISTS ) {
1734                                         goto update_cookie_retry;
1735                                 } else if ( rc == LDAP_REFERRAL ||
1736                                                         rc == LDAP_NO_SUCH_OBJECT ) {
1737 #ifdef NEW_LOGGING
1738                                         LDAP_LOG( OPERATION, ERR,
1739                                                 "cookie will be non-persistent\n",
1740                                                 0, 0, 0 );
1741 #else
1742                                         Debug( LDAP_DEBUG_ANY,
1743                                                 "cookie will be non-persistent\n",
1744                                                 0, 0, 0 );
1745 #endif
1746                                 } else {
1747 #ifdef NEW_LOGGING
1748                                         LDAP_LOG( OPERATION, ERR,
1749                                                 "be_add failed (%d)\n",
1750                                                 rc, 0, 0 );
1751 #else
1752                                         Debug( LDAP_DEBUG_ANY,
1753                                                 "be_add failed (%d)\n",
1754                                                 rc, 0, 0 );
1755 #endif
1756                                 }
1757                         } else {
1758                                 be_entry_release_w( op, e );
1759                                 goto done;
1760                         }
1761                 } else {
1762 #ifdef NEW_LOGGING
1763                         LDAP_LOG( OPERATION, ERR,
1764                                 "be_modify failed (%d)\n", rc, 0, 0 );
1765 #else
1766                         Debug( LDAP_DEBUG_ANY,
1767                                 "be_modify failed (%d)\n", rc, 0, 0 );
1768 #endif
1769                 }
1770         }
1771
1772         if ( e != NULL ) {
1773                 entry_free( e );
1774         }
1775
1776 done :
1777
1778         if ( cnbva[0].bv_val ) {
1779                 ch_free( cnbva[0].bv_val );
1780                 cnbva[0].bv_val = NULL;
1781         }
1782         if ( scbva[0].bv_val ) {
1783                 ch_free( scbva[0].bv_val );
1784                 scbva[0].bv_val = NULL;
1785         }
1786
1787         if ( mlnext->sml_next ) {
1788                 slap_mods_free( mlnext->sml_next );
1789                 mlnext->sml_next = NULL;
1790         }
1791
1792         for (ml = modlist ; ml != NULL; ml = mlnext ) {
1793                 mlnext = ml->sml_next;
1794                 free( ml );
1795         }
1796
1797         return;
1798 }
1799
1800 int
1801 syncrepl_isupdate( Operation *op )
1802 {
1803         return ( syncrepl_isupdate_dn( op->o_bd, &op->o_ndn ));
1804 }
1805
1806 int
1807 syncrepl_isupdate_dn(
1808         Backend*                be,
1809         struct berval*  ndn )
1810 {
1811         syncinfo_t*     si;
1812         int                     ret = 0;
1813
1814         if ( !LDAP_STAILQ_EMPTY( &be->be_syncinfo )) {
1815                 LDAP_STAILQ_FOREACH( si, &be->be_syncinfo, si_next ) {
1816                         if ( ( ret = dn_match( &si->si_updatedn, ndn ) ) ) {
1817                                 return ret;
1818                         }
1819                 }
1820         }
1821         return 0;
1822 }
1823
1824 static int
1825 dn_callback(
1826         Operation*      op,
1827         SlapReply*      rs )
1828 {
1829         syncinfo_t *si = op->o_callback->sc_private;
1830
1831         if ( rs->sr_type == REP_SEARCH ) {
1832                 if ( si->si_syncUUID_ndn.bv_val != NULL ) {
1833 #ifdef NEW_LOGGING
1834                         LDAP_LOG( OPERATION, ERR,
1835                                 "dn_callback : multiple entries match dn\n", 0, 0, 0 );
1836 #else
1837                         Debug( LDAP_DEBUG_ANY,
1838                                 "dn_callback : multiple entries match dn\n", 0, 0, 0 );
1839 #endif
1840                 } else {
1841                         ber_dupbv_x( &si->si_syncUUID_ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx );
1842                 }
1843         }
1844
1845         return LDAP_SUCCESS;
1846 }
1847
1848 static int
1849 nonpresent_callback(
1850         Operation*      op,
1851         SlapReply*      rs )
1852 {
1853         syncinfo_t *si = op->o_callback->sc_private;
1854         Attribute *a;
1855         int count = 0;
1856         struct berval* present_uuid = NULL;
1857         struct nonpresent_entry *np_entry;
1858
1859         if ( rs->sr_type == REP_RESULT ) {
1860                 count = avl_free( si->si_presentlist, avl_ber_bvfree );
1861                 si->si_presentlist = NULL;
1862
1863         } else if ( rs->sr_type == REP_SEARCH ) {
1864                 a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
1865
1866                 if ( a == NULL ) return 0;
1867
1868                 present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
1869                         syncuuid_cmp );
1870
1871                 if ( present_uuid == NULL ) {
1872                         np_entry = (struct nonpresent_entry *)
1873                                 ch_calloc( 1, sizeof( struct nonpresent_entry ));
1874                         np_entry->npe_name = ber_dupbv( NULL, &rs->sr_entry->e_name );
1875                         np_entry->npe_nname = ber_dupbv( NULL, &rs->sr_entry->e_nname );
1876                         LDAP_LIST_INSERT_HEAD( &si->si_nonpresentlist, np_entry, npe_link );
1877
1878                 } else {
1879                         avl_delete( &si->si_presentlist,
1880                                         &a->a_nvals[0], syncuuid_cmp );
1881                         ch_free( present_uuid->bv_val );
1882                         ch_free( present_uuid );
1883                 }
1884         }
1885         return LDAP_SUCCESS;
1886 }
1887
1888 static int
1889 null_callback(
1890         Operation*      op,
1891         SlapReply*      rs )
1892 {
1893         if ( rs->sr_err != LDAP_SUCCESS &&
1894                 rs->sr_err != LDAP_REFERRAL &&
1895                 rs->sr_err != LDAP_ALREADY_EXISTS &&
1896                 rs->sr_err != LDAP_NO_SUCH_OBJECT &&
1897                 rs->sr_err != LDAP_NOT_ALLOWED_ON_NONLEAF )
1898         {
1899 #ifdef NEW_LOGGING
1900                 LDAP_LOG( OPERATION, ERR,
1901                         "null_callback : error code 0x%x\n",
1902                         rs->sr_err, 0, 0 );
1903 #else
1904                 Debug( LDAP_DEBUG_ANY,
1905                         "null_callback : error code 0x%x\n",
1906                         rs->sr_err, 0, 0 );
1907 #endif
1908         }
1909         return LDAP_SUCCESS;
1910 }
1911
1912 Entry *
1913 slap_create_syncrepl_entry(
1914         Backend *be,
1915         struct berval *context_csn,
1916         struct berval *rdn,
1917         struct berval *cn )
1918 {
1919         Entry* e;
1920
1921         struct berval bv;
1922
1923         e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1924
1925         attr_merge( e, slap_schema.si_ad_objectClass, ocbva, NULL );
1926
1927         attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
1928                 &ocbva[1], NULL );
1929
1930         attr_merge_one( e, slap_schema.si_ad_cn, cn, NULL );
1931
1932         if ( context_csn ) {
1933                 attr_merge_one( e, slap_schema.si_ad_syncreplCookie,
1934                         context_csn, NULL );
1935         }
1936
1937         bv.bv_val = "{}";
1938         bv.bv_len = sizeof("{}")-1;
1939         attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
1940
1941         build_new_dn( &e->e_name, &be->be_nsuffix[0], rdn, NULL );
1942         ber_dupbv( &e->e_nname, &e->e_name );
1943
1944         return e;
1945 }
1946
1947 struct berval *
1948 slap_uuidstr_from_normalized(
1949         struct berval* uuidstr,
1950         struct berval* normalized,
1951         void *ctx )
1952 {
1953         struct berval *new;
1954         unsigned char nibble;
1955         int i, d = 0;
1956
1957         if ( normalized == NULL ) return NULL;
1958         if ( normalized->bv_len != 16 ) return NULL;
1959
1960         if ( uuidstr ) {
1961                 new = uuidstr;
1962         } else {
1963                 new = (struct berval *)slap_sl_malloc( sizeof(struct berval), ctx );
1964         }
1965
1966         new->bv_len = 36;
1967
1968         if (( new->bv_val = slap_sl_malloc( new->bv_len + 1, ctx )) == NULL) {
1969                 if ( !uuidstr ) slap_sl_free( new, ctx );
1970                 return NULL;
1971         }
1972
1973         for ( i = 0; i < 16; i++ ) {
1974                 if ( i == 4 || i == 6 || i == 8 || i == 10 ) {
1975                         new->bv_val[(i<<1)+d] = '-';
1976                         d += 1;
1977                 }
1978
1979                 nibble = (normalized->bv_val[i] >> 4) & 0xF;
1980                 if ( nibble < 10 ) {
1981                         new->bv_val[(i<<1)+d] = nibble + '0';
1982                 } else {
1983                         new->bv_val[(i<<1)+d] = nibble - 10 + 'a';
1984                 }
1985
1986                 nibble = (normalized->bv_val[i]) & 0xF;
1987                 if ( nibble < 10 ) {
1988                         new->bv_val[(i<<1)+d+1] = nibble + '0';
1989                 } else {
1990                         new->bv_val[(i<<1)+d+1] = nibble - 10 + 'a';
1991                 }
1992         }
1993
1994         new->bv_val[new->bv_len] = '\0';
1995         return new;
1996 }
1997
1998 static int
1999 syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 )
2000 {
2001         const struct berval *uuid1 = v_uuid1;
2002         const struct berval *uuid2 = v_uuid2;
2003         int rc = uuid1->bv_len - uuid2->bv_len;
2004         if ( rc ) return rc;
2005         return ( memcmp( uuid1->bv_val, uuid2->bv_val, uuid1->bv_len ) );
2006 }
2007
2008 static void
2009 avl_ber_bvfree( void *bv )
2010 {
2011         if( bv == NULL ) return;
2012         if ( ((struct berval *)bv)->bv_val != NULL ) {
2013                 ch_free( ((struct berval *)bv)->bv_val );
2014         }
2015         ch_free( (char *) bv );
2016 }