1 /* syncrepl.c -- Replication Engine which uses the LDAP Sync protocol */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2004 The OpenLDAP Foundation.
6 * Portions Copyright 2003 by IBM Corporation.
7 * Portions Copyright 2003 by Howard Chu, Symas Corporation.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
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>.
23 #include <ac/string.h>
24 #include <ac/socket.h>
28 #include "lutil_ldap.h"
32 #define SYNCREPL_STR "syncreplxxx"
35 static const struct berval slap_syncrepl_bvc = BER_BVC(SYNCREPL_STR);
36 static const struct berval slap_syncrepl_cn_bvc = BER_BVC(CN_STR SYNCREPL_STR);
38 static int syncuuid_cmp( const void *, const void * );
39 static void avl_ber_bvfree( void * );
40 static void syncrepl_del_nonpresent( Operation *, syncinfo_t * );
42 /* callback functions */
43 static int dn_callback( struct slap_op *, struct slap_rep * );
44 static int nonpresent_callback( struct slap_op *, struct slap_rep * );
45 static int null_callback( struct slap_op *, struct slap_rep * );
47 static AttributeDescription *sync_descs[4];
50 init_syncrepl(syncinfo_t *si)
53 char **attrs, **exattrs;
56 if ( !sync_descs[0] ) {
57 sync_descs[0] = slap_schema.si_ad_objectClass;
58 sync_descs[1] = slap_schema.si_ad_structuralObjectClass;
59 sync_descs[2] = slap_schema.si_ad_entryCSN;
63 if ( si->si_allattrs && si->si_allopattrs )
66 attrs = anlist2attrs( si->si_anlist );
69 if ( si->si_allattrs ) {
72 if ( !is_at_operational( at_find( attrs[i] ))) {
73 for ( j = i; attrs[j] != NULL; j++ ) {
76 attrs[j] = attrs[j+1];
82 attrs = ( char ** ) ch_realloc( attrs, (i + 2)*sizeof( char * ) );
83 attrs[i] = ch_strdup("*");
86 } else if ( si->si_allopattrs ) {
89 if ( is_at_operational( at_find( attrs[i] ))) {
90 for ( j = i; attrs[j] != NULL; j++ ) {
93 attrs[j] = attrs[j+1];
99 attrs = ( char ** ) ch_realloc( attrs, (i + 2)*sizeof( char * ) );
100 attrs[i] = ch_strdup("+");
104 if ( !si->si_allopattrs ) {
105 for ( i = 0; sync_descs[i] != NULL; i++ ) {
108 if ( !strcmp( attrs[j], sync_descs[i]->ad_cname.bv_val )) {
109 for ( k = j; attrs[k] != NULL; k++ ) {
112 attrs[k] = attrs[k+1];
120 for ( n = 0; attrs[ n ] != NULL; n++ ) /* empty */;
121 attrs = ( char ** ) ch_realloc( attrs, (n + 4)*sizeof( char * ));
122 if ( attrs == NULL ) {
123 Debug( LDAP_DEBUG_ANY, "out of memory\n", 0,0,0 );
127 for ( i = 0; sync_descs[ i ] != NULL; i++ ) {
128 attrs[ n++ ] = ch_strdup ( sync_descs[i]->ad_cname.bv_val );
134 for ( n = 0; sync_descs[ n ] != NULL; n++ ) ;
136 attrs = ( char ** ) ch_malloc((
137 (si->si_allattrs ? 1 : ( si->si_allopattrs ? 0 : 1)) +
138 (si->si_allopattrs ? 1 : ( si->si_allattrs ? n : 1))
139 + 1 ) * sizeof( char * ) );
140 if ( attrs == NULL ) {
141 Debug( LDAP_DEBUG_ANY, "out of memory\n", 0, 0, 0 );
145 if ( si->si_allattrs ) {
146 attrs[i++] = ch_strdup( "*" );
149 if ( si->si_allopattrs ) {
150 attrs[i++] = ch_strdup( "+" );
152 for ( j = 0; sync_descs[ j ] != NULL; j++ ) {
153 attrs[ i++ ] = ch_strdup ( sync_descs[j]->ad_cname.bv_val );
158 if ( !si->si_allattrs && !si->si_allopattrs ) {
159 attrs[0] = ch_strdup( "*" );
160 attrs[1] = ch_strdup( "+" );
165 si->si_attrs = attrs;
167 exattrs = anlist2attrs( si->si_exanlist );
170 for ( n = 0; exattrs[n] != NULL; n++ ) ;
172 for ( i = 0; sync_descs[i] != NULL; i++ ) {
174 while ( exattrs[j] != NULL ) {
175 if ( !strcmp( exattrs[j], sync_descs[i]->ad_cname.bv_val )) {
176 for ( k = j; exattrs[k] != NULL; k++ ) {
178 ch_free( exattrs[k] );
179 exattrs[k] = exattrs[k+1];
187 for ( i = 0; exattrs[i] != NULL; i++ ) {
188 for ( j = 0; si->si_anlist[j].an_name.bv_val; j++ ) {
189 if ( oc = si->si_anlist[j].an_oc ) {
191 while ( oc->soc_required[k] ) {
192 if ( !strcmp( exattrs[i],
193 oc->soc_required[k]->sat_cname.bv_val )) {
194 for ( l = i; exattrs[l]; l++ ) {
196 ch_free( exattrs[i] );
197 exattrs[l] = exattrs[l+1];
207 for ( i = 0; exattrs[i] != NULL; i++ ) ;
210 exattrs = (char **) ch_realloc( exattrs, (i + 1)*sizeof(char *));
213 si->si_exattrs = exattrs;
221 BerElementBuffer berbuf;
222 BerElement *ber = (BerElement *)&berbuf;
223 LDAPControl c[2], *ctrls[3];
224 struct timeval timeout;
228 /* setup LDAP SYNC control */
229 ber_init2( ber, NULL, LBER_USE_DER );
230 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &ctx );
232 if ( si->si_syncCookie.octet_str &&
233 !BER_BVISNULL( &si->si_syncCookie.octet_str[0] ) )
235 ber_printf( ber, "{eO}",
237 &si->si_syncCookie.octet_str[0] );
239 ber_printf( ber, "{e}",
243 if ( (rc = ber_flatten2( ber, &c[0].ldctl_value, 0 )) == LBER_ERROR ) {
248 c[0].ldctl_oid = LDAP_CONTROL_SYNC;
249 c[0].ldctl_iscritical = si->si_type < 0;
252 if ( si->si_authzId ) {
253 c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
254 ber_str2bv( si->si_authzId, 0, 0, &c[1].ldctl_value );
255 c[1].ldctl_iscritical = 1;
262 timeout.tv_sec = si->si_tlimit;
265 rc = ldap_search_ext( si->si_ld, si->si_base.bv_val, si->si_scope,
266 si->si_filterstr.bv_val, si->si_attrs, si->si_attrsonly,
267 ctrls, NULL, si->si_tlimit > 0 ? &timeout : NULL,
268 si->si_slimit, &msgid );
279 int cmdline_cookie_found = 0;
281 char syncrepl_cbuf[sizeof(CN_STR SYNCREPL_STR)];
282 struct berval syncrepl_cn_bv;
283 struct sync_cookie *sc = NULL;
284 struct sync_cookie syncCookie = { NULL, -1, NULL };
290 psub = &si->si_be->be_nsuffix[0];
292 /* Init connection to master */
293 rc = ldap_initialize( &si->si_ld, si->si_provideruri );
294 if ( rc != LDAP_SUCCESS ) {
295 Debug( LDAP_DEBUG_ANY,
296 "do_syncrep1: ldap_initialize failed (%s)\n",
297 si->si_provideruri, 0, 0 );
301 op->o_protocol = LDAP_VERSION3;
302 ldap_set_option( si->si_ld, LDAP_OPT_PROTOCOL_VERSION, &op->o_protocol );
307 rc = ldap_start_tls_s( si->si_ld, NULL, NULL );
308 if( rc != LDAP_SUCCESS ) {
309 Debug( LDAP_DEBUG_ANY,
310 "%s: ldap_start_tls failed (%d)\n",
311 si->si_tls == SYNCINFO_TLS_CRITICAL ? "Error" : "Warning",
313 if( si->si_tls == SYNCINFO_TLS_CRITICAL ) goto done;
317 if ( si->si_bindmethod == LDAP_AUTH_SASL ) {
318 #ifdef HAVE_CYRUS_SASL
321 if ( si->si_secprops != NULL ) {
322 rc = ldap_set_option( si->si_ld,
323 LDAP_OPT_X_SASL_SECPROPS, si->si_secprops);
325 if( rc != LDAP_OPT_SUCCESS ) {
326 Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
327 "(%s,SECPROPS,\"%s\") failed!\n",
328 si->si_provideruri, si->si_secprops, 0 );
333 defaults = lutil_sasl_defaults( si->si_ld, si->si_saslmech,
334 si->si_realm, si->si_authcId, si->si_passwd, si->si_authzId );
336 rc = ldap_sasl_interactive_bind_s( si->si_ld,
344 lutil_sasl_freedefs( defaults );
346 /* FIXME: different error behaviors according to
348 * 2) on err policy : exit, retry, backoff ...
350 if ( rc != LDAP_SUCCESS ) {
351 Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
352 "ldap_sasl_interactive_bind_s failed (%d)\n",
355 /* FIXME (see above comment) */
356 /* if Kerberos credentials cache is not active, retry */
357 if ( strcmp( si->si_saslmech, "GSSAPI" ) == 0 &&
358 rc == LDAP_LOCAL_ERROR )
360 rc = LDAP_SERVER_DOWN;
365 #else /* HAVE_CYRUS_SASL */
366 /* Should never get here, we trapped this at config time */
368 fprintf( stderr, "not compiled with SASL support\n" );
374 rc = ldap_bind_s( si->si_ld,
375 si->si_binddn, si->si_passwd, si->si_bindmethod );
376 if ( rc != LDAP_SUCCESS ) {
377 Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
378 "ldap_bind_s failed (%d)\n", rc, 0, 0 );
383 /* Set SSF to strongest of TLS, SASL SSFs */
386 op->o_transport_ssf = 0;
388 if ( ldap_get_option( si->si_ld, LDAP_OPT_X_TLS_SSL_CTX, &ssl )
389 == LDAP_SUCCESS && ssl != NULL )
391 op->o_tls_ssf = ldap_pvt_tls_get_strength( ssl );
393 #endif /* HAVE_TLS */
394 ldap_get_option( si->si_ld, LDAP_OPT_X_SASL_SSF, &op->o_sasl_ssf );
395 op->o_ssf = ( op->o_sasl_ssf > op->o_tls_ssf )
396 ? op->o_sasl_ssf : op->o_tls_ssf;
398 /* get syncrepl cookie of shadow replica from subentry */
399 assert( si->si_rid < 1000 );
400 syncrepl_cn_bv.bv_val = syncrepl_cbuf;
401 syncrepl_cn_bv.bv_len = snprintf( syncrepl_cbuf, sizeof(syncrepl_cbuf),
402 CN_STR "syncrepl%ld", si->si_rid );
403 build_new_dn( &op->o_req_ndn, psub, &syncrepl_cn_bv, op->o_tmpmemctx );
404 op->o_req_dn = op->o_req_ndn;
406 LDAP_STAILQ_FOREACH( sc, &SLAPD_GLOBAL(sync_cookie), sc_next ) {
407 if ( si->si_rid == sc->rid ) {
408 cmdline_cookie_found = 1;
413 if ( cmdline_cookie_found ) {
414 /* cookie is supplied in the command line */
415 BerVarray cookie = NULL;
416 struct berval cookie_bv;
418 LDAP_STAILQ_REMOVE( &SLAPD_GLOBAL(sync_cookie), sc, sync_cookie, sc_next );
419 slap_sync_cookie_free( &si->si_syncCookie, 0 );
421 /* read stored cookie if it exists */
422 backend_attribute( op, NULL, &op->o_req_ndn,
423 slap_schema.si_ad_syncreplCookie, &cookie, ACL_READ );
426 /* no stored cookie */
427 if ( sc->ctxcsn == NULL ||
428 BER_BVISNULL( sc->ctxcsn ) ) {
429 /* if cmdline cookie does not have ctxcsn */
430 /* component, set it to an initial value */
431 slap_init_sync_cookie_ctxcsn( sc );
433 slap_dup_sync_cookie( &si->si_syncCookie, sc );
434 slap_sync_cookie_free( sc, 1 );
439 struct berval newcookie = BER_BVNULL;
440 ber_dupbv( &cookie_bv, &cookie[0] );
441 ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv );
442 slap_parse_sync_cookie( &si->si_syncCookie );
443 ber_bvarray_free( si->si_syncCookie.octet_str );
444 si->si_syncCookie.octet_str = NULL;
445 ber_bvarray_free_x( cookie, op->o_tmpmemctx );
446 if ( sc->sid != -1 ) {
447 /* command line cookie wins */
448 si->si_syncCookie.sid = sc->sid;
450 if ( sc->ctxcsn != NULL ) {
451 /* command line cookie wins */
452 if ( si->si_syncCookie.ctxcsn ) {
453 ber_bvarray_free( si->si_syncCookie.ctxcsn );
454 si->si_syncCookie.ctxcsn = NULL;
456 ber_dupbv( &cookie_bv, &sc->ctxcsn[0] );
457 ber_bvarray_add( &si->si_syncCookie.ctxcsn, &cookie_bv );
459 if ( sc->rid != -1 ) {
460 /* command line cookie wins */
461 si->si_syncCookie.rid = sc->rid;
463 slap_sync_cookie_free( sc, 1 );
465 slap_compose_sync_cookie( NULL, &newcookie,
466 &si->si_syncCookie.ctxcsn[0],
467 si->si_syncCookie.sid, si->si_syncCookie.rid );
468 ber_bvarray_add( &si->si_syncCookie.octet_str, &newcookie );
472 /* no command line cookie is specified */
473 if ( si->si_syncCookie.octet_str == NULL ) {
474 BerVarray cookie = NULL;
475 struct berval cookie_bv;
476 /* try to read stored cookie */
477 backend_attribute( op, NULL, &op->o_req_ndn,
478 slap_schema.si_ad_syncreplCookie, &cookie, ACL_READ );
480 ber_dupbv( &cookie_bv, &cookie[0] );
481 ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv );
482 slap_parse_sync_cookie( &si->si_syncCookie );
483 ber_bvarray_free_x( cookie, op->o_tmpmemctx );
488 rc = ldap_sync_search( si, op->o_tmpmemctx );
490 if( rc != LDAP_SUCCESS ) {
491 Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
492 "ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 );
498 ldap_unbind( si->si_ld );
503 slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx );
513 LDAPControl **rctrls = NULL;
516 BerElementBuffer berbuf;
517 BerElement *ber = (BerElement *)&berbuf;
519 LDAPMessage *res = NULL;
520 LDAPMessage *msg = NULL;
523 struct berval *retdata = NULL;
528 struct berval syncUUID = BER_BVNULL;
529 struct sync_cookie syncCookie = { NULL, -1, NULL };
530 struct sync_cookie syncCookie_req = { NULL, -1, NULL };
531 struct berval cookie = BER_BVNULL;
539 Modifications *modlist = NULL;
544 struct timeval *tout_p = NULL;
545 struct timeval tout = { 0, 0 };
547 int refreshDeletes = 0;
549 BerVarray syncUUIDs = NULL;
552 if ( SLAPD_GLOBAL(shutdown) ) {
557 ber_init2( ber, NULL, LBER_USE_DER );
558 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
560 Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2\n", 0, 0, 0 );
562 psub = &si->si_be->be_nsuffix[0];
564 slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie );
566 if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
572 while (( rc = ldap_result( si->si_ld, LDAP_RES_ANY, LDAP_MSG_ONE,
573 tout_p, &res )) > 0 )
575 if ( SLAPD_GLOBAL(shutdown) ) {
579 for( msg = ldap_first_message( si->si_ld, res );
581 msg = ldap_next_message( si->si_ld, msg ) )
583 switch( ldap_msgtype( msg ) ) {
584 case LDAP_RES_SEARCH_ENTRY:
585 ldap_get_entry_controls( si->si_ld, msg, &rctrls );
586 /* we can't work without the control */
588 Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
589 "got search entry without "
590 "control\n", 0, 0, 0 );
595 ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
596 ber_scanf( ber, "{em" /*"}"*/, &syncstate, &syncUUID );
597 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
598 ber_scanf( ber, /*"{"*/ "m}", &cookie );
599 if ( !BER_BVISNULL( &cookie ) ) {
600 struct berval tmp_bv;
601 ber_dupbv( &tmp_bv, &cookie );
602 ber_bvarray_add( &syncCookie.octet_str, &tmp_bv );
604 if ( syncCookie.octet_str &&
605 !BER_BVISNULL( &syncCookie.octet_str[0] ) )
607 slap_parse_sync_cookie( &syncCookie );
610 if ( syncrepl_message_to_entry( si, op, msg,
611 &modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
612 rc_efree = syncrepl_entry( si, op, entry, modlist,
613 syncstate, &syncUUID, &syncCookie_req );
614 if ( syncCookie.octet_str &&
615 !BER_BVISNULL( &syncCookie.octet_str[0] ) )
617 syncrepl_updateCookie( si, op, psub, &syncCookie );
620 ldap_controls_free( rctrls );
622 slap_mods_free( modlist );
624 if ( rc_efree && entry ) {
630 case LDAP_RES_SEARCH_REFERENCE:
631 Debug( LDAP_DEBUG_ANY,
632 "do_syncrep2 : reference received\n", 0, 0, 0 );
635 case LDAP_RES_SEARCH_RESULT:
636 ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL,
640 ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
642 ber_scanf( ber, "{" /*"}"*/);
643 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
644 ber_scanf( ber, "m", &cookie );
645 if ( !BER_BVISNULL( &cookie ) ) {
646 struct berval tmp_bv;
647 ber_dupbv( &tmp_bv, &cookie );
648 ber_bvarray_add( &syncCookie.octet_str, &tmp_bv);
650 if ( syncCookie.octet_str &&
651 !BER_BVISNULL( &syncCookie.octet_str[0] ) )
653 slap_parse_sync_cookie( &syncCookie );
656 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES )
658 ber_scanf( ber, "b", &refreshDeletes );
660 ber_scanf( ber, /*"{"*/ "}" );
662 if ( syncCookie_req.ctxcsn == NULL ) {
664 } else if ( syncCookie.ctxcsn == NULL ) {
667 value_match( &match, slap_schema.si_ad_entryCSN,
668 slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
669 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
670 &syncCookie_req.ctxcsn[0], &syncCookie.ctxcsn[0],
673 if ( syncCookie.octet_str && !BER_BVISNULL( syncCookie.octet_str ) &&
674 match < 0 && err == LDAP_SUCCESS )
676 syncrepl_updateCookie( si, op, psub, &syncCookie );
679 ldap_controls_free( rctrls );
681 if (si->si_type != LDAP_SYNC_REFRESH_AND_PERSIST) {
682 /* FIXME : different error behaviors according to
683 * 1) err code : LDAP_BUSY ...
684 * 2) on err policy : stop service, stop sync, retry
686 if ( refreshDeletes == 0 && match < 0 &&
687 err == LDAP_SUCCESS )
689 syncrepl_del_nonpresent( op, si );
691 avl_free( si->si_presentlist, avl_ber_bvfree );
692 si->si_presentlist = NULL;
699 case LDAP_RES_INTERMEDIATE:
700 rc = ldap_parse_intermediate( si->si_ld, msg,
701 &retoid, &retdata, NULL, 0 );
702 if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) {
703 int si_refreshDelete = 0;
704 int si_refreshPresent = 0;
705 ber_init2( ber, retdata, LBER_USE_DER );
707 switch ( si_tag = ber_peek_tag( ber, &len )) {
709 case LDAP_TAG_SYNC_NEW_COOKIE:
710 ber_scanf( ber, "tm", &tag, &cookie );
712 case LDAP_TAG_SYNC_REFRESH_DELETE:
713 si_refreshDelete = 1;
714 case LDAP_TAG_SYNC_REFRESH_PRESENT:
715 si_refreshPresent = 1;
716 ber_scanf( ber, "t{" /*"}"*/, &tag );
717 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE )
719 ber_scanf( ber, "m", &cookie );
720 if ( !BER_BVISNULL( &cookie ) ) {
721 struct berval tmp_bv;
722 ber_dupbv( &tmp_bv, &cookie );
723 ber_bvarray_add( &syncCookie.octet_str,
726 if ( syncCookie.octet_str &&
727 !BER_BVISNULL( &syncCookie.octet_str[0] ) )
729 slap_parse_sync_cookie( &syncCookie );
732 if ( ber_peek_tag( ber, &len ) ==
733 LDAP_TAG_REFRESHDONE )
735 ber_scanf( ber, "b", &refreshDone );
737 ber_scanf( ber, /*"{"*/ "}" );
739 case LDAP_TAG_SYNC_ID_SET:
740 ber_scanf( ber, "t{" /*"}"*/, &tag );
741 if ( ber_peek_tag( ber, &len ) ==
742 LDAP_TAG_SYNC_COOKIE )
744 ber_scanf( ber, "m", &cookie );
745 if ( !BER_BVISNULL( &cookie ) ) {
746 struct berval tmp_bv;
747 ber_dupbv( &tmp_bv, &cookie );
748 ber_bvarray_add( &syncCookie.octet_str,
751 if ( syncCookie.octet_str &&
752 !BER_BVISNULL( &syncCookie.octet_str[0] ) )
754 slap_parse_sync_cookie( &syncCookie );
757 if ( ber_peek_tag( ber, &len ) ==
758 LDAP_TAG_REFRESHDELETES )
760 ber_scanf( ber, "b", &refreshDeletes );
762 ber_scanf( ber, "[W]", &syncUUIDs );
763 ber_scanf( ber, /*"{"*/ "}" );
764 for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) {
765 struct berval *syncuuid_bv;
766 syncuuid_bv = ber_dupbv( NULL, &syncUUIDs[i] );
767 slap_sl_free( syncUUIDs[i].bv_val,op->o_tmpmemctx );
768 avl_insert( &si->si_presentlist,
769 (caddr_t) syncuuid_bv,
770 syncuuid_cmp, avl_dup_error );
772 slap_sl_free( syncUUIDs, op->o_tmpmemctx );
775 Debug( LDAP_DEBUG_ANY,
776 "do_syncrep2 : unknown syncinfo tag (%ld)\n",
777 (long) si_tag, 0, 0 );
778 ldap_memfree( retoid );
779 ber_bvfree( retdata );
783 if ( syncCookie_req.ctxcsn == NULL ) {
785 } else if ( syncCookie.ctxcsn == NULL ) {
788 value_match( &match, slap_schema.si_ad_entryCSN,
789 slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
790 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
791 &syncCookie_req.ctxcsn[0],
792 &syncCookie.ctxcsn[0], &text );
795 if ( syncCookie.ctxcsn && !BER_BVISNULL( &syncCookie.ctxcsn[0] ) &&
798 syncrepl_updateCookie( si, op, psub, &syncCookie);
801 if ( si_refreshPresent == 1 ) {
803 syncrepl_del_nonpresent( op, si );
807 ldap_memfree( retoid );
808 ber_bvfree( retdata );
812 Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
813 "unknown intermediate response (%d)\n",
815 ldap_memfree( retoid );
816 ber_bvfree( retdata );
822 Debug( LDAP_DEBUG_ANY, "do_syncrep2 : "
823 "unknown message\n", 0, 0, 0 );
827 if ( syncCookie.octet_str ) {
828 slap_sync_cookie_free( &syncCookie_req, 0 );
829 slap_dup_sync_cookie( &syncCookie_req, &syncCookie );
830 slap_sync_cookie_free( &syncCookie, 0 );
840 ldap_get_option( si->si_ld, LDAP_OPT_ERROR_NUMBER, &rc );
841 errstr = ldap_err2string( rc );
843 Debug( LDAP_DEBUG_ANY,
844 "do_syncrep2 : %s\n", errstr, 0, 0 );
848 slap_sync_cookie_free( &syncCookie, 0 );
849 slap_sync_cookie_free( &syncCookie_req, 0 );
851 if ( res ) ldap_msgfree( res );
853 if ( rc && si->si_ld ) {
854 ldap_unbind( si->si_ld );
866 struct re_s* rtask = arg;
867 syncinfo_t *si = ( syncinfo_t * ) rtask->arg;
868 Connection conn = {0};
870 int rc = LDAP_SUCCESS;
877 Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl\n", 0, 0, 0 );
882 switch( abs( si->si_type )) {
883 case LDAP_SYNC_REFRESH_ONLY:
884 case LDAP_SYNC_REFRESH_AND_PERSIST:
890 if ( SLAPD_GLOBAL(shutdown) && si->si_ld ) {
891 ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s );
892 connection_client_stop( s );
893 ldap_unbind( si->si_ld );
898 connection_fake_init( &conn, &op, ctx );
900 /* use global malloc for now */
901 op.o_tmpmemctx = NULL;
902 op.o_tmpmfuncs = &ch_mfuncs;
904 op.o_dn = si->si_updatedn;
905 op.o_ndn = si->si_updatedn;
906 op.o_managedsait = 1;
907 op.o_bd = be = si->si_be;
909 op.o_sync_state.ctxcsn = NULL;
910 op.o_sync_state.sid = -1;
911 op.o_sync_state.octet_str = NULL;
912 op.o_sync_slog_size = -1;
913 LDAP_STAILQ_FIRST( &op.o_sync_slog_list ) = NULL;
914 op.o_sync_slog_list.stqh_last = &LDAP_STAILQ_FIRST(&op.o_sync_slog_list);
916 /* Establish session, do search */
919 rc = do_syncrep1( &op, si );
922 /* Process results */
923 if ( rc == LDAP_SUCCESS ) {
924 ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s );
926 rc = do_syncrep2( &op, si );
928 if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
929 /* If we succeeded, enable the connection for further listening.
930 * If we failed, tear down the connection and reschedule.
932 if ( rc == LDAP_SUCCESS ) {
934 rc = connection_client_setup( s, do_syncrepl, arg );
936 connection_client_enable( s );
938 } else if ( !first ) {
942 if ( rc == -2 ) rc = 0;
946 /* At this point, we have 4 cases:
947 * 1) for any hard failure, give up and remove this task
948 * 2) for ServerDown, reschedule this task to run
949 * 3) for Refresh and Success, reschedule to run
950 * 4) for Persist and Success, reschedule to defer
952 ldap_pvt_thread_mutex_lock( &SLAPD_GLOBAL(runqueue).rq_mutex );
954 if ( ldap_pvt_runqueue_isrunning( &SLAPD_GLOBAL(runqueue), rtask )) {
955 ldap_pvt_runqueue_stoptask( &SLAPD_GLOBAL(runqueue), rtask );
959 connection_client_stop( s );
962 if ( rc == LDAP_SUCCESS ) {
963 if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
966 rtask->interval.tv_sec = si->si_interval;
967 ldap_pvt_runqueue_resched( &SLAPD_GLOBAL(runqueue), rtask, defer );
968 if ( si->si_retrynum ) {
969 for ( i = 0; si->si_retrynum_init[i] != -2; i++ ) {
970 si->si_retrynum[i] = si->si_retrynum_init[i];
972 si->si_retrynum[i] = -2;
975 for ( i = 0; si->si_retrynum && si->si_retrynum[i] <= 0; i++ ) {
976 if ( si->si_retrynum[i] == -1 || si->si_retrynum[i] == -2 )
980 if ( !si->si_retrynum || si->si_retrynum[i] == -2 ) {
981 ldap_pvt_runqueue_remove( &SLAPD_GLOBAL(runqueue), rtask );
982 LDAP_STAILQ_REMOVE( &be->be_syncinfo, si, syncinfo_s, si_next );
984 } else if ( si->si_retrynum[i] >= -1 ) {
985 if ( si->si_retrynum[i] > 0 )
986 si->si_retrynum[i]--;
987 rtask->interval.tv_sec = si->si_retryinterval[i];
988 ldap_pvt_runqueue_resched( &SLAPD_GLOBAL(runqueue), rtask, 0 );
989 slap_wake_listener();
993 ldap_pvt_thread_mutex_unlock( &SLAPD_GLOBAL(runqueue).rq_mutex );
999 syncrepl_message_to_entry(
1003 Modifications **modlist,
1009 BerElement *ber = NULL;
1012 Modifications **modtail = modlist;
1015 char txtbuf[SLAP_TEXT_BUFLEN];
1016 size_t textlen = sizeof txtbuf;
1018 struct berval bdn = {0, NULL}, dn, ndn;
1023 if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
1024 Debug( LDAP_DEBUG_ANY,
1025 "Message type should be entry (%d)", ldap_msgtype( msg ), 0, 0 );
1029 op->o_tag = LDAP_REQ_ADD;
1031 rc = ldap_get_dn_ber( si->si_ld, msg, &ber, &bdn );
1033 if ( rc != LDAP_SUCCESS ) {
1034 Debug( LDAP_DEBUG_ANY,
1035 "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
1039 dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
1040 ber_dupbv( &op->o_req_dn, &dn );
1041 ber_dupbv( &op->o_req_ndn, &ndn );
1042 slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
1043 slap_sl_free( dn.bv_val, op->o_tmpmemctx );
1045 if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE ) {
1048 return LDAP_SUCCESS;
1051 if ( entry == NULL ) {
1055 e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
1057 e->e_name = op->o_req_dn;
1058 e->e_nname = op->o_req_ndn;
1060 while ( ber_remaining( ber ) ) {
1061 if ( (ber_scanf( ber, "{mW}", &tmp.sml_type, &tmp.sml_values ) ==
1062 LBER_ERROR ) || BER_BVISNULL( &tmp.sml_type ) )
1067 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1069 mod->sml_op = LDAP_MOD_REPLACE;
1070 mod->sml_next = NULL;
1071 mod->sml_desc = NULL;
1072 mod->sml_type = tmp.sml_type;
1073 mod->sml_values = tmp.sml_values;
1074 mod->sml_nvalues = NULL;
1077 modtail = &mod->sml_next;
1080 if ( *modlist == NULL ) {
1081 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: no attributes\n",
1087 rc = slap_mods_check( *modlist, 1, &text, txtbuf, textlen, NULL );
1089 if ( rc != LDAP_SUCCESS ) {
1090 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods check (%s)\n",
1095 /* Strip out dynamically generated attrs */
1096 for ( modtail = modlist; *modtail ; ) {
1098 if ( mod->sml_desc->ad_type->sat_flags & SLAP_AT_DYNAMIC ) {
1099 *modtail = mod->sml_next;
1100 slap_mod_free( &mod->sml_mod, 0 );
1103 modtail = &mod->sml_next;
1107 /* Strip out attrs in exattrs list */
1108 for ( modtail = modlist; *modtail ; ) {
1110 if ( ldap_charray_inlist( si->si_exattrs,
1111 mod->sml_desc->ad_type->sat_cname.bv_val )) {
1112 *modtail = mod->sml_next;
1113 slap_mod_free( &mod->sml_mod, 0 );
1116 modtail = &mod->sml_next;
1120 rc = slap_mods2entry( *modlist, &e, 1, 1, &text, txtbuf, textlen);
1121 if( rc != LDAP_SUCCESS ) {
1122 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods2entry (%s)\n",
1127 ber_free ( ber, 0 );
1128 if ( rc != LDAP_SUCCESS ) {
1143 Modifications* modlist,
1145 struct berval* syncUUID,
1146 struct sync_cookie* syncCookie_req )
1148 Backend *be = op->o_bd;
1149 slap_callback cb = { NULL };
1150 struct berval *syncuuid_bv = NULL;
1151 struct berval syncUUID_strrep = BER_BVNULL;
1152 struct berval uuid_bv = BER_BVNULL;
1154 SlapReply rs_search = {REP_RESULT};
1155 SlapReply rs_delete = {REP_RESULT};
1156 SlapReply rs_add = {REP_RESULT};
1157 SlapReply rs_modify = {REP_RESULT};
1159 AttributeAssertion ava = {0};
1160 int rc = LDAP_SUCCESS;
1161 int ret = LDAP_SUCCESS;
1164 struct berval pdn = BER_BVNULL;
1165 struct berval org_req_dn = BER_BVNULL;
1166 struct berval org_req_ndn = BER_BVNULL;
1167 struct berval org_dn = BER_BVNULL;
1168 struct berval org_ndn = BER_BVNULL;
1169 int org_managedsait;
1171 if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD )) {
1172 syncuuid_bv = ber_dupbv( NULL, syncUUID );
1173 avl_insert( &si->si_presentlist, (caddr_t) syncuuid_bv,
1174 syncuuid_cmp, avl_dup_error );
1177 if ( syncstate == LDAP_SYNC_PRESENT ) {
1179 } else if ( syncstate != LDAP_SYNC_DELETE ) {
1180 if ( entry == NULL ) {
1185 f.f_choice = LDAP_FILTER_EQUALITY;
1187 ava.aa_desc = slap_schema.si_ad_entryUUID;
1188 (void)slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
1189 ava.aa_value = *syncUUID;
1190 op->ors_filter = &f;
1192 op->ors_filterstr.bv_len = STRLENOF( "entryUUID=" ) + syncUUID->bv_len;
1193 op->ors_filterstr.bv_val = (char *) slap_sl_malloc(
1194 op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
1195 AC_MEMCPY( op->ors_filterstr.bv_val, "entryUUID=", STRLENOF( "entryUUID=" ) );
1196 AC_MEMCPY( &op->ors_filterstr.bv_val[STRLENOF( "entryUUID=" )],
1197 syncUUID->bv_val, syncUUID->bv_len );
1198 op->ors_filterstr.bv_val[op->ors_filterstr.bv_len] = '\0';
1200 op->o_tag = LDAP_REQ_SEARCH;
1201 op->ors_scope = LDAP_SCOPE_SUBTREE;
1203 /* get syncrepl cookie of shadow replica from subentry */
1204 op->o_req_dn = si->si_base;
1205 op->o_req_ndn = si->si_base;
1207 op->o_time = slap_get_time();
1208 op->ors_tlimit = SLAP_NO_LIMIT;
1211 op->ors_attrs = slap_anlist_no_attrs;
1212 op->ors_attrsonly = 1;
1214 /* set callback function */
1215 op->o_callback = &cb;
1216 cb.sc_response = dn_callback;
1219 BER_BVZERO( &si->si_syncUUID_ndn );
1221 if ( limits_check( op, &rs_search ) == 0 ) {
1222 rc = be->be_search( op, &rs_search );
1225 if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
1226 slap_sl_free( op->ors_filterstr.bv_val, op->o_tmpmemctx );
1229 cb.sc_response = null_callback;
1232 if ( rs_search.sr_err == LDAP_SUCCESS && !BER_BVISNULL( &si->si_syncUUID_ndn ) )
1236 if ( syncstate != LDAP_SYNC_DELETE ) {
1237 op->o_no_psearch = 1;
1240 ber_dupbv( &op->o_sync_csn, syncCookie_req->ctxcsn );
1241 if ( !BER_BVISNULL( &op->o_sync_csn ) ) {
1242 subseq_ptr = strstr( op->o_sync_csn.bv_val, "#0000" );
1247 op->o_req_dn = si->si_syncUUID_ndn;
1248 op->o_req_ndn = si->si_syncUUID_ndn;
1249 op->o_tag = LDAP_REQ_DELETE;
1250 rc = be->be_delete( op, &rs_delete );
1252 org_req_dn = op->o_req_dn;
1253 org_req_ndn = op->o_req_ndn;
1255 org_ndn = op->o_ndn;
1256 org_managedsait = get_manageDSAit( op );
1257 op->o_dn = op->o_bd->be_rootdn;
1258 op->o_ndn = op->o_bd->be_rootndn;
1259 op->o_managedsait = 1;
1261 while ( rs_delete.sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) {
1262 op->o_delete_glue_parent = 0;
1263 if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
1264 slap_callback cb = { NULL };
1265 cb.sc_response = slap_null_cb;
1266 dnParent( &op->o_req_ndn, &pdn );
1268 op->o_req_ndn = pdn;
1269 op->o_callback = &cb;
1270 op->o_bd->be_delete( op, &rs_delete );
1276 op->o_managedsait = org_managedsait;
1278 op->o_ndn = org_ndn;
1279 op->o_req_dn = org_req_dn;
1280 op->o_req_ndn = org_req_ndn;
1281 op->o_delete_glue_parent = 0;
1283 op->o_no_psearch = 0;
1286 switch ( syncstate ) {
1288 case LDAP_SYNC_MODIFY:
1289 if ( rs_search.sr_err == LDAP_SUCCESS ||
1290 rs_search.sr_err == LDAP_REFERRAL ||
1291 rs_search.sr_err == LDAP_NO_SUCH_OBJECT ||
1292 rs_search.sr_err == LDAP_NOT_ALLOWED_ON_NONLEAF )
1294 attr_delete( &entry->e_attrs, slap_schema.si_ad_entryUUID );
1295 attr_merge_one( entry, slap_schema.si_ad_entryUUID,
1296 &syncUUID_strrep, syncUUID );
1298 op->o_tag = LDAP_REQ_ADD;
1300 op->o_req_dn = entry->e_name;
1301 op->o_req_ndn = entry->e_nname;
1303 rc = be->be_add( op, &rs_add );
1305 if ( rs_add.sr_err != LDAP_SUCCESS ) {
1306 if ( rs_add.sr_err == LDAP_ALREADY_EXISTS &&
1307 rs_search.sr_err != LDAP_NO_SUCH_OBJECT ) {
1309 Modifications *modtail = modlist;
1313 for ( mod = modlist; mod != NULL; mod = mod->sml_next ) {
1317 mod = (Modifications *)ch_calloc(1, sizeof(Modifications));
1318 ber_dupbv( &uuid_bv, syncUUID );
1319 mod->sml_op = LDAP_MOD_REPLACE;
1320 mod->sml_desc = slap_schema.si_ad_entryUUID;
1321 mod->sml_type = mod->sml_desc->ad_cname;
1322 ber_bvarray_add( &mod->sml_values, &uuid_bv );
1323 modtail->sml_next = mod;
1325 op->o_tag = LDAP_REQ_MODIFY;
1326 op->orm_modlist = modlist;
1327 op->o_req_dn = entry->e_name;
1328 op->o_req_ndn = entry->e_nname;
1330 rc = be->be_modify( op, &rs_modify );
1331 if ( rs_modify.sr_err != LDAP_SUCCESS ) {
1332 Debug( LDAP_DEBUG_ANY,
1333 "syncrepl_entry : be_modify failed (%d)\n",
1334 rs_modify.sr_err, 0, 0 );
1338 } else if ( rs_modify.sr_err == LDAP_REFERRAL ||
1339 rs_modify.sr_err == LDAP_NO_SUCH_OBJECT ) {
1340 syncrepl_add_glue( op, entry );
1344 Debug( LDAP_DEBUG_ANY,
1345 "syncrepl_entry : be_add failed (%d)\n",
1346 rs_add.sr_err, 0, 0 );
1351 be_entry_release_w( op, entry );
1356 Debug( LDAP_DEBUG_ANY,
1357 "syncrepl_entry : be_search failed (%d)\n",
1358 rs_search.sr_err, 0, 0 );
1363 case LDAP_SYNC_DELETE :
1364 /* Already deleted */
1369 Debug( LDAP_DEBUG_ANY,
1370 "syncrepl_entry : unknown syncstate\n", 0, 0, 0 );
1377 if ( !BER_BVISNULL( &syncUUID_strrep ) ) {
1378 slap_sl_free( syncUUID_strrep.bv_val, op->o_tmpmemctx );
1379 BER_BVZERO( &syncUUID_strrep );
1381 if ( !BER_BVISNULL( &si->si_syncUUID_ndn ) ) {
1382 ch_free( si->si_syncUUID_ndn.bv_val );
1383 BER_BVZERO( &si->si_syncUUID_ndn );
1388 static struct berval gcbva[] = {
1395 syncrepl_del_nonpresent(
1399 Backend* be = op->o_bd;
1400 slap_callback cb = { NULL };
1401 SlapReply rs_search = {REP_RESULT};
1402 SlapReply rs_delete = {REP_RESULT};
1403 SlapReply rs_modify = {REP_RESULT};
1404 struct nonpresent_entry *np_list, *np_prev;
1407 Modifications *mlnext;
1409 Modifications *modlist = NULL;
1410 Modifications **modtail = &modlist;
1412 AttributeName an[2];
1414 struct berval pdn = BER_BVNULL;
1415 struct berval org_req_dn = BER_BVNULL;
1416 struct berval org_req_ndn = BER_BVNULL;
1417 struct berval org_dn = BER_BVNULL;
1418 struct berval org_ndn = BER_BVNULL;
1419 int org_managedsait;
1421 op->o_req_dn = si->si_base;
1422 op->o_req_ndn = si->si_base;
1424 cb.sc_response = nonpresent_callback;
1427 op->o_callback = &cb;
1428 op->o_tag = LDAP_REQ_SEARCH;
1429 op->ors_scope = si->si_scope;
1430 op->ors_deref = LDAP_DEREF_NEVER;
1431 op->o_time = slap_get_time();
1432 op->ors_tlimit = SLAP_NO_LIMIT;
1433 op->ors_slimit = SLAP_NO_LIMIT;
1435 memset( &an[0], 0, 2 * sizeof( AttributeName ) );
1436 an[0].an_name = slap_schema.si_ad_entryUUID->ad_cname;
1437 an[0].an_desc = slap_schema.si_ad_entryUUID;
1440 op->ors_attrsonly = 0;
1441 op->ors_filter = str2filter_x( op, si->si_filterstr.bv_val );
1442 op->ors_filterstr = si->si_filterstr;
1444 op->o_nocaching = 1;
1445 op->o_managedsait = 0;
1447 if ( limits_check( op, &rs_search ) == 0 ) {
1448 rc = be->be_search( op, &rs_search );
1451 op->o_managedsait = 1;
1452 op->o_nocaching = 0;
1454 if ( op->ors_filter ) filter_free_x( op, op->ors_filter );
1456 if ( !LDAP_LIST_EMPTY( &si->si_nonpresentlist ) ) {
1457 np_list = LDAP_LIST_FIRST( &si->si_nonpresentlist );
1458 while ( np_list != NULL ) {
1459 LDAP_LIST_REMOVE( np_list, npe_link );
1461 np_list = LDAP_LIST_NEXT( np_list, npe_link );
1462 op->o_tag = LDAP_REQ_DELETE;
1463 op->o_callback = &cb;
1464 cb.sc_response = null_callback;
1466 op->o_req_dn = *np_prev->npe_name;
1467 op->o_req_ndn = *np_prev->npe_nname;
1468 rc = op->o_bd->be_delete( op, &rs_delete );
1470 if ( rs_delete.sr_err == LDAP_NOT_ALLOWED_ON_NONLEAF ) {
1471 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1472 mod->sml_op = LDAP_MOD_REPLACE;
1473 mod->sml_desc = slap_schema.si_ad_objectClass;
1474 mod->sml_type = mod->sml_desc->ad_cname;
1475 mod->sml_values = &gcbva[0];
1477 modtail = &mod->sml_next;
1479 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1480 mod->sml_op = LDAP_MOD_REPLACE;
1481 mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
1482 mod->sml_type = mod->sml_desc->ad_cname;
1483 mod->sml_values = &gcbva[1];
1485 modtail = &mod->sml_next;
1487 op->o_tag = LDAP_REQ_MODIFY;
1488 op->orm_modlist = modlist;
1490 rc = be->be_modify( op, &rs_modify );
1492 for ( ml = modlist; ml != NULL; ml = mlnext ) {
1493 mlnext = ml->sml_next;
1498 org_req_dn = op->o_req_dn;
1499 org_req_ndn = op->o_req_ndn;
1501 org_ndn = op->o_ndn;
1502 org_managedsait = get_manageDSAit( op );
1503 op->o_dn = op->o_bd->be_rootdn;
1504 op->o_ndn = op->o_bd->be_rootndn;
1505 op->o_managedsait = 1;
1507 while ( rs_delete.sr_err == LDAP_SUCCESS &&
1508 op->o_delete_glue_parent ) {
1509 op->o_delete_glue_parent = 0;
1510 if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
1511 slap_callback cb = { NULL };
1512 cb.sc_response = slap_null_cb;
1513 dnParent( &op->o_req_ndn, &pdn );
1515 op->o_req_ndn = pdn;
1516 op->o_callback = &cb;
1517 /* give it a root privil ? */
1518 op->o_bd->be_delete( op, &rs_delete );
1524 op->o_managedsait = org_managedsait;
1526 op->o_ndn = org_ndn;
1527 op->o_req_dn = org_req_dn;
1528 op->o_req_ndn = org_req_ndn;
1529 op->o_delete_glue_parent = 0;
1531 ber_bvfree( np_prev->npe_name );
1532 ber_bvfree( np_prev->npe_nname );
1533 BER_BVZERO( &op->o_req_dn );
1534 BER_BVZERO( &op->o_req_ndn );
1547 Backend *be = op->o_bd;
1548 slap_callback cb = { NULL };
1553 struct berval dn = {0, NULL};
1554 struct berval ndn = {0, NULL};
1556 SlapReply rs_add = {REP_RESULT};
1559 op->o_tag = LDAP_REQ_ADD;
1560 op->o_callback = &cb;
1561 cb.sc_response = null_callback;
1562 cb.sc_private = NULL;
1567 /* count RDNs in suffix */
1568 if ( !BER_BVISEMPTY( &be->be_nsuffix[0] ) ) {
1569 for ( i = 0, ptr = be->be_nsuffix[0].bv_val; ptr; ptr = strchr( ptr, ',' ) ) {
1579 /* Start with BE suffix */
1580 for ( i = 0, ptr = NULL; i < suffrdns; i++ ) {
1581 comma = strrchr( dn.bv_val, ',' );
1582 if ( ptr ) *ptr = ',';
1583 if ( comma ) *comma = '\0';
1588 dn.bv_len -= ptr - dn.bv_val;
1591 /* the normalizedDNs are always the same length, no counting
1594 if ( ndn.bv_len > be->be_nsuffix[0].bv_len ) {
1595 ndn.bv_val += ndn.bv_len - be->be_nsuffix[0].bv_len;
1596 ndn.bv_len = be->be_nsuffix[0].bv_len;
1599 while ( ndn.bv_val > e->e_nname.bv_val ) {
1600 glue = (Entry *) ch_calloc( 1, sizeof(Entry) );
1601 ber_dupbv( &glue->e_name, &dn );
1602 ber_dupbv( &glue->e_nname, &ndn );
1604 a = ch_calloc( 1, sizeof( Attribute ));
1605 a->a_desc = slap_schema.si_ad_objectClass;
1607 a->a_vals = ch_calloc( 3, sizeof( struct berval ));
1608 ber_dupbv( &a->a_vals[0], &gcbva[0] );
1609 ber_dupbv( &a->a_vals[1], &gcbva[1] );
1610 ber_dupbv( &a->a_vals[2], &gcbva[2] );
1612 a->a_nvals = a->a_vals;
1614 a->a_next = glue->e_attrs;
1617 a = ch_calloc( 1, sizeof( Attribute ));
1618 a->a_desc = slap_schema.si_ad_structuralObjectClass;
1620 a->a_vals = ch_calloc( 2, sizeof( struct berval ));
1621 ber_dupbv( &a->a_vals[0], &gcbva[1] );
1622 ber_dupbv( &a->a_vals[1], &gcbva[2] );
1624 a->a_nvals = a->a_vals;
1626 a->a_next = glue->e_attrs;
1629 op->o_req_dn = glue->e_name;
1630 op->o_req_ndn = glue->e_nname;
1632 rc = be->be_add ( op, &rs_add );
1633 if ( rs_add.sr_err == LDAP_SUCCESS ) {
1634 be_entry_release_w( op, glue );
1636 /* incl. ALREADY EXIST */
1640 /* Move to next child */
1641 for (ptr = dn.bv_val-2; ptr > e->e_name.bv_val && *ptr != ','; ptr--) {
1644 if ( ptr == e->e_name.bv_val ) break;
1646 dn.bv_len = e->e_name.bv_len - (ptr-e->e_name.bv_val);
1647 for( ptr = ndn.bv_val-2;
1648 ptr > e->e_nname.bv_val && *ptr != ',';
1654 ndn.bv_len = e->e_nname.bv_len - (ptr-e->e_nname.bv_val);
1657 op->o_req_dn = e->e_name;
1658 op->o_req_ndn = e->e_nname;
1660 rc = be->be_add ( op, &rs_add );
1661 if ( rs_add.sr_err == LDAP_SUCCESS ) {
1662 be_entry_release_w( op, e );
1670 static struct berval ocbva[] = {
1672 BER_BVC("subentry"),
1673 BER_BVC("syncConsumerSubentry"),
1677 static struct berval cnbva[] = {
1682 static struct berval ssbva[] = {
1687 static struct berval scbva[] = {
1693 syncrepl_updateCookie(
1697 struct sync_cookie *syncCookie )
1699 Backend *be = op->o_bd;
1701 Modifications *mlnext;
1703 Modifications *modlist = NULL;
1704 Modifications **modtail = &modlist;
1707 char txtbuf[SLAP_TEXT_BUFLEN];
1708 size_t textlen = sizeof txtbuf;
1713 char syncrepl_cbuf[sizeof(CN_STR SYNCREPL_STR)];
1714 struct berval slap_syncrepl_dn_bv = BER_BVNULL;
1715 struct berval slap_syncrepl_cn_bv = BER_BVNULL;
1717 slap_callback cb = { NULL };
1718 SlapReply rs_add = {REP_RESULT};
1719 SlapReply rs_modify = {REP_RESULT};
1721 slap_sync_cookie_free( &si->si_syncCookie, 0 );
1722 slap_dup_sync_cookie( &si->si_syncCookie, syncCookie );
1724 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1725 mod->sml_op = LDAP_MOD_REPLACE;
1726 mod->sml_desc = slap_schema.si_ad_objectClass;
1727 mod->sml_type = mod->sml_desc->ad_cname;
1728 mod->sml_values = ocbva;
1730 modtail = &mod->sml_next;
1732 ber_dupbv( &cnbva[0], (struct berval *) &slap_syncrepl_bvc );
1733 assert( si->si_rid < 1000 );
1734 cnbva[0].bv_len = snprintf( cnbva[0].bv_val,
1735 slap_syncrepl_bvc.bv_len + 1,
1736 "syncrepl%ld", si->si_rid );
1737 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1738 mod->sml_op = LDAP_MOD_REPLACE;
1739 mod->sml_desc = slap_schema.si_ad_cn;
1740 mod->sml_type = mod->sml_desc->ad_cname;
1741 mod->sml_values = cnbva;
1743 modtail = &mod->sml_next;
1745 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1746 mod->sml_op = LDAP_MOD_REPLACE;
1747 mod->sml_desc = slap_schema.si_ad_subtreeSpecification;
1748 mod->sml_type = mod->sml_desc->ad_cname;
1749 mod->sml_values = ssbva;
1751 modtail = &mod->sml_next;
1753 /* Keep this last, so we can avoid touching the previous
1754 * attributes unnecessarily.
1756 if ( scbva[0].bv_val ) ch_free( scbva[0].bv_val );
1757 ber_dupbv( &scbva[0], &si->si_syncCookie.octet_str[0] );
1758 mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
1759 mod->sml_op = LDAP_MOD_REPLACE;
1760 mod->sml_desc = slap_schema.si_ad_syncreplCookie;
1761 mod->sml_type = mod->sml_desc->ad_cname;
1762 mod->sml_values = scbva;
1764 modtail = &mod->sml_next;
1768 op->o_tag = LDAP_REQ_ADD;
1769 rc = slap_mods_opattrs( op, modlist, modtail,
1770 &text, txtbuf, textlen, 0 );
1772 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
1773 ml->sml_op = LDAP_MOD_REPLACE;
1776 if( rc != LDAP_SUCCESS ) {
1777 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods opattrs (%s)\n",
1781 e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1783 slap_syncrepl_cn_bv.bv_val = syncrepl_cbuf;
1784 assert( si->si_rid < 1000 );
1785 slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
1786 slap_syncrepl_cn_bvc.bv_len + 1,
1787 "cn=syncrepl%ld", si->si_rid );
1789 build_new_dn( &slap_syncrepl_dn_bv, pdn, &slap_syncrepl_cn_bv,
1791 ber_dupbv( &e->e_name, &slap_syncrepl_dn_bv );
1792 ber_dupbv( &e->e_nname, &slap_syncrepl_dn_bv );
1794 if ( !BER_BVISNULL( &slap_syncrepl_dn_bv ) ) {
1795 slap_sl_free( slap_syncrepl_dn_bv.bv_val, op->o_tmpmemctx );
1800 rc = slap_mods2entry( modlist, &e, 1, 1, &text, txtbuf, textlen );
1802 if( rc != LDAP_SUCCESS ) {
1803 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods2entry (%s)\n",
1807 cb.sc_response = null_callback;
1810 op->o_callback = &cb;
1811 op->o_req_dn = e->e_name;
1812 op->o_req_ndn = e->e_nname;
1814 /* update persistent cookie */
1815 update_cookie_retry:
1816 op->o_tag = LDAP_REQ_MODIFY;
1817 /* Just modify the cookie value, not the entire entry */
1818 op->orm_modlist = mod;
1819 rc = be->be_modify( op, &rs_modify );
1821 if ( rs_modify.sr_err != LDAP_SUCCESS ) {
1822 if ( rs_modify.sr_err == LDAP_REFERRAL ||
1823 rs_modify.sr_err == LDAP_NO_SUCH_OBJECT ) {
1824 op->o_tag = LDAP_REQ_ADD;
1826 rc = be->be_add( op, &rs_add );
1827 if ( rs_add.sr_err != LDAP_SUCCESS ) {
1828 if ( rs_add.sr_err == LDAP_ALREADY_EXISTS ) {
1829 goto update_cookie_retry;
1830 } else if ( rs_add.sr_err == LDAP_REFERRAL ||
1831 rs_add.sr_err == LDAP_NO_SUCH_OBJECT ) {
1832 Debug( LDAP_DEBUG_ANY,
1833 "cookie will be non-persistent\n",
1836 Debug( LDAP_DEBUG_ANY,
1837 "be_add failed (%d)\n", rs_add.sr_err, 0, 0 );
1840 be_entry_release_w( op, e );
1844 Debug( LDAP_DEBUG_ANY,
1845 "be_modify failed (%d)\n", rs_modify.sr_err, 0, 0 );
1855 if ( !BER_BVISNULL( &cnbva[0] ) ) {
1856 ch_free( cnbva[0].bv_val );
1857 BER_BVZERO( &cnbva[0] );
1859 if ( !BER_BVISNULL( &scbva[0] ) ) {
1860 ch_free( scbva[0].bv_val );
1861 BER_BVZERO( &scbva[0] );
1864 if ( mlnext->sml_next ) {
1865 slap_mods_free( mlnext->sml_next );
1866 mlnext->sml_next = NULL;
1869 for (ml = modlist ; ml != NULL; ml = mlnext ) {
1870 mlnext = ml->sml_next;
1878 syncrepl_isupdate( Operation *op )
1880 return ( syncrepl_isupdate_dn( op->o_bd, &op->o_ndn ));
1884 syncrepl_isupdate_dn(
1886 struct berval* ndn )
1891 if ( !LDAP_STAILQ_EMPTY( &be->be_syncinfo )) {
1892 LDAP_STAILQ_FOREACH( si, &be->be_syncinfo, si_next ) {
1893 if ( ( ret = dn_match( &si->si_updatedn, ndn ) ) ) {
1906 syncinfo_t *si = op->o_callback->sc_private;
1908 if ( rs->sr_type == REP_SEARCH ) {
1909 if ( !BER_BVISNULL( &si->si_syncUUID_ndn ) ) {
1910 Debug( LDAP_DEBUG_ANY,
1911 "dn_callback : consistency error - "
1912 "entryUUID is not unique\n", 0, 0, 0 );
1914 ber_dupbv_x( &si->si_syncUUID_ndn, &rs->sr_entry->e_nname, NULL );
1916 } else if ( rs->sr_type == REP_RESULT ) {
1917 if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) {
1918 Debug( LDAP_DEBUG_ANY,
1919 "dn_callback : consistency error - "
1920 "entryUUID is not unique\n", 0, 0, 0 );
1924 return LDAP_SUCCESS;
1928 nonpresent_callback(
1932 syncinfo_t *si = op->o_callback->sc_private;
1935 struct berval* present_uuid = NULL;
1936 struct nonpresent_entry *np_entry;
1938 if ( rs->sr_type == REP_RESULT ) {
1939 count = avl_free( si->si_presentlist, avl_ber_bvfree );
1940 si->si_presentlist = NULL;
1942 } else if ( rs->sr_type == REP_SEARCH ) {
1943 a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
1945 if ( a == NULL ) return 0;
1947 present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
1950 if ( present_uuid == NULL ) {
1951 np_entry = (struct nonpresent_entry *)
1952 ch_calloc( 1, sizeof( struct nonpresent_entry ));
1953 np_entry->npe_name = ber_dupbv( NULL, &rs->sr_entry->e_name );
1954 np_entry->npe_nname = ber_dupbv( NULL, &rs->sr_entry->e_nname );
1955 LDAP_LIST_INSERT_HEAD( &si->si_nonpresentlist, np_entry, npe_link );
1958 avl_delete( &si->si_presentlist,
1959 &a->a_nvals[0], syncuuid_cmp );
1960 ch_free( present_uuid->bv_val );
1961 ch_free( present_uuid );
1964 return LDAP_SUCCESS;
1972 if ( rs->sr_err != LDAP_SUCCESS &&
1973 rs->sr_err != LDAP_REFERRAL &&
1974 rs->sr_err != LDAP_ALREADY_EXISTS &&
1975 rs->sr_err != LDAP_NO_SUCH_OBJECT &&
1976 rs->sr_err != LDAP_NOT_ALLOWED_ON_NONLEAF )
1978 Debug( LDAP_DEBUG_ANY,
1979 "null_callback : error code 0x%x\n",
1982 return LDAP_SUCCESS;
1986 slap_create_syncrepl_entry(
1988 struct berval *context_csn,
1996 e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1998 attr_merge( e, slap_schema.si_ad_objectClass, ocbva, NULL );
2000 attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
2003 attr_merge_one( e, slap_schema.si_ad_cn, cn, NULL );
2005 if ( context_csn ) {
2006 attr_merge_one( e, slap_schema.si_ad_syncreplCookie,
2007 context_csn, NULL );
2010 BER_BVSTR( &bv, "{}" );
2011 attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
2013 build_new_dn( &e->e_name, &be->be_nsuffix[0], rdn, NULL );
2014 ber_dupbv( &e->e_nname, &e->e_name );
2020 slap_uuidstr_from_normalized(
2021 struct berval* uuidstr,
2022 struct berval* normalized,
2026 unsigned char nibble;
2029 if ( normalized == NULL ) return NULL;
2030 if ( normalized->bv_len != 16 ) return NULL;
2035 new = (struct berval *)slap_sl_malloc( sizeof(struct berval), ctx );
2036 if ( new == NULL ) {
2043 if ( ( new->bv_val = slap_sl_malloc( new->bv_len + 1, ctx ) ) == NULL ) {
2044 if ( new != uuidstr ) {
2045 slap_sl_free( new, ctx );
2050 for ( i = 0; i < 16; i++ ) {
2051 if ( i == 4 || i == 6 || i == 8 || i == 10 ) {
2052 new->bv_val[(i<<1)+d] = '-';
2056 nibble = (normalized->bv_val[i] >> 4) & 0xF;
2057 if ( nibble < 10 ) {
2058 new->bv_val[(i<<1)+d] = nibble + '0';
2060 new->bv_val[(i<<1)+d] = nibble - 10 + 'a';
2063 nibble = (normalized->bv_val[i]) & 0xF;
2064 if ( nibble < 10 ) {
2065 new->bv_val[(i<<1)+d+1] = nibble + '0';
2067 new->bv_val[(i<<1)+d+1] = nibble - 10 + 'a';
2071 new->bv_val[new->bv_len] = '\0';
2076 syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 )
2078 const struct berval *uuid1 = v_uuid1;
2079 const struct berval *uuid2 = v_uuid2;
2080 int rc = uuid1->bv_len - uuid2->bv_len;
2081 if ( rc ) return rc;
2082 return ( memcmp( uuid1->bv_val, uuid2->bv_val, uuid1->bv_len ) );
2086 avl_ber_bvfree( void *v_bv )
2088 struct berval *bv = (struct berval *)v_bv;
2090 if( v_bv == NULL ) return;
2091 if ( !BER_BVISNULL( bv ) ) {
2092 ch_free( bv->bv_val );
2094 ch_free( (char *) bv );
2098 syncinfo_free( syncinfo_t *sie )
2100 if ( sie->si_provideruri ) {
2101 ch_free( sie->si_provideruri );
2103 if ( sie->si_provideruri_bv ) {
2104 ber_bvarray_free( sie->si_provideruri_bv );
2106 if ( sie->si_updatedn.bv_val ) {
2107 ch_free( sie->si_updatedn.bv_val );
2109 if ( sie->si_binddn ) {
2110 ch_free( sie->si_binddn );
2112 if ( sie->si_passwd ) {
2113 ch_free( sie->si_passwd );
2115 if ( sie->si_saslmech ) {
2116 ch_free( sie->si_saslmech );
2118 if ( sie->si_secprops ) {
2119 ch_free( sie->si_secprops );
2121 if ( sie->si_realm ) {
2122 ch_free( sie->si_realm );
2124 if ( sie->si_authcId ) {
2125 ch_free( sie->si_authcId );
2127 if ( sie->si_authzId ) {
2128 ch_free( sie->si_authzId );
2130 if ( sie->si_filterstr.bv_val ) {
2131 ch_free( sie->si_filterstr.bv_val );
2133 if ( sie->si_base.bv_val ) {
2134 ch_free( sie->si_base.bv_val );
2136 if ( sie->si_attrs ) {
2138 while ( sie->si_attrs[i] != NULL ) {
2139 ch_free( sie->si_attrs[i] );
2142 ch_free( sie->si_attrs );
2144 if ( sie->si_exattrs ) {
2146 while ( sie->si_exattrs[i] != NULL ) {
2147 ch_free( sie->si_exattrs[i] );
2150 ch_free( sie->si_exattrs );
2152 if ( sie->si_anlist ) {
2154 while ( sie->si_anlist[i].an_name.bv_val != NULL ) {
2155 ch_free( sie->si_anlist[i].an_name.bv_val );
2158 ch_free( sie->si_anlist );
2160 if ( sie->si_exanlist ) {
2162 while ( sie->si_exanlist[i].an_name.bv_val != NULL ) {
2163 ch_free( sie->si_exanlist[i].an_name.bv_val );
2166 ch_free( sie->si_exanlist );
2168 if ( sie->si_retryinterval ) {
2169 ch_free( sie->si_retryinterval );
2171 if ( sie->si_retrynum ) {
2172 ch_free( sie->si_retrynum );
2174 if ( sie->si_retrynum_init ) {
2175 ch_free( sie->si_retrynum_init );
2177 slap_sync_cookie_free( &sie->si_syncCookie, 0 );
2178 if ( sie->si_syncUUID_ndn.bv_val ) {
2179 ch_free( sie->si_syncUUID_ndn.bv_val );
2181 if ( sie->si_presentlist ) {
2182 avl_free( sie->si_presentlist, avl_ber_bvfree );
2185 ldap_ld_free( sie->si_ld, 1, NULL, NULL );
2187 while ( !LDAP_LIST_EMPTY( &sie->si_nonpresentlist )) {
2188 struct nonpresent_entry* npe;
2189 npe = LDAP_LIST_FIRST( &sie->si_nonpresentlist );
2190 LDAP_LIST_REMOVE( npe, npe_link );
2191 if ( npe->npe_name ) {
2192 if ( npe->npe_name->bv_val ) {
2193 ch_free( npe->npe_name->bv_val );
2195 ch_free( npe->npe_name );
2197 if ( npe->npe_nname ) {
2198 if ( npe->npe_nname->bv_val ) {
2199 ch_free( npe->npe_nname->bv_val );
2201 ch_free( npe->npe_nname );