3 * Replication Engine which uses the LDAP Sync protocol
5 /* Copyright (c) 2003 by International Business Machines, Inc.
7 * International Business Machines, Inc. (hereinafter called IBM) grants
8 * permission under its copyrights to use, copy, modify, and distribute this
9 * Software with or without fee, provided that the above copyright notice and
10 * all paragraphs of this notice appear in all copies, and that the name of IBM
11 * not be used in connection with the marketing of any product incorporating
12 * the Software or modifications thereof, without specific, written prior
15 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
18 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
19 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
20 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
27 #include <ac/string.h>
28 #include <ac/socket.h>
34 #include "lutil_ldap.h"
36 /* This is for accessing ld->def_conn */
37 #define LDAP_R_COMPILE
38 #include "../../../libraries/libldap/ldap-int.h"
42 static Entry* syncrepl_message_to_entry( LDAP *, Backend*, LDAPMessage *,
43 Modifications *, int*, struct berval *, struct berval * );
44 static int syncrepl_entry( LDAP *, Backend*, Entry*, Modifications*, int,
45 struct berval*, struct berval*, int );
46 static int syncrepl_del_nonpresent( LDAP *, Backend * );
47 static void syncrepl_add_glue( LDAP *, Connection*, Operation*, Backend*,
48 Entry*, Modifications*, int,
49 struct berval*, struct berval* );
50 static void syncrepl_updateCookie( LDAP *, Backend *, struct berval *,
52 static int slap_mods_check_syncrepl( Backend *, Modifications **,
53 const char **, char *, size_t, void *ctx );
54 static int slap_mods_opattrs_syncrepl( Backend *, Operation *, Modifications *,
55 Modifications **, const char **, char *, size_t );
56 static int slap_mods2entry_syncrepl( Modifications *, Entry **, int,
57 const char **, char *, size_t );
59 /* callback functions */
60 static int cookie_callback( struct slap_op *, struct slap_rep * );
61 static int nonpresent_callback( struct slap_op *, struct slap_rep * );
62 static int null_callback( struct slap_op *, struct slap_rep * );
64 static AttributeDescription **add_descs;
65 static AttributeDescription **add_descs_lastmod;
66 static AttributeDescription **del_descs;
67 static AttributeDescription **del_descs_lastmod;
72 add_descs = ch_malloc( 2 * sizeof( AttributeDescription * ));
73 add_descs[0] = slap_schema.si_ad_objectClass;
76 add_descs_lastmod = ch_malloc( 7 * sizeof( AttributeDescription * ));
77 add_descs_lastmod[0] = slap_schema.si_ad_objectClass;
78 add_descs_lastmod[1] = slap_schema.si_ad_creatorsName;
79 add_descs_lastmod[2] = slap_schema.si_ad_modifiersName;
80 add_descs_lastmod[3] = slap_schema.si_ad_createTimestamp;
81 add_descs_lastmod[4] = slap_schema.si_ad_modifyTimestamp;
82 add_descs_lastmod[5] = slap_schema.si_ad_entryCSN;
83 add_descs_lastmod[6] = NULL;
85 del_descs = ch_malloc( 9 * sizeof( AttributeDescription * ));
86 del_descs[0] = slap_schema.si_ad_structuralObjectClass;
87 del_descs[1] = slap_schema.si_ad_subschemaSubentry;
88 del_descs[2] = slap_schema.si_ad_hasSubordinates;
89 del_descs[3] = slap_schema.si_ad_creatorsName;
90 del_descs[4] = slap_schema.si_ad_modifiersName;
91 del_descs[5] = slap_schema.si_ad_createTimestamp;
92 del_descs[6] = slap_schema.si_ad_modifyTimestamp;
93 del_descs[7] = slap_schema.si_ad_entryCSN;
96 del_descs_lastmod = ch_malloc( 4 * sizeof( AttributeDescription * ));
97 del_descs_lastmod[0] = slap_schema.si_ad_structuralObjectClass;
98 del_descs_lastmod[1] = slap_schema.si_ad_subschemaSubentry;
99 del_descs_lastmod[2] = slap_schema.si_ad_hasSubordinates;
100 del_descs_lastmod[3] = NULL;
109 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
111 SlapReply rs = {REP_RESULT};
113 LDAPControl c[2], **sctrls = NULL, **rctrls = NULL, *rctrlp;
114 BerElement *sync_ber;
115 struct berval *sync_bvalp;
117 BerElement *ctrl_ber;
121 LDAPMessage *res = NULL, *msg;
125 int nresponses, nreferences, nextended, npartial;
126 int nresponses_psearch;
128 int cancel_msgid = -1;
130 struct berval *retdata = NULL;
132 int sync_info_arrived = 0;
136 struct berval syncUUID;
137 struct berval syncCookie;
143 int syncinfo_arrived = 0;
144 int cancel_response = 0;
147 AttributeDescription** descs;
158 struct berval base_bv = { 0, NULL };
159 struct berval pbase = { 0, NULL };
160 struct berval nbase = { 0, NULL };
161 struct berval sub_bv = { 0, NULL };
162 struct berval psubrdn = { 0, NULL };
163 struct berval nsubrdn = { 0, NULL };
164 struct berval psub = { 0, NULL };
165 struct berval nsub = { 0, NULL };
167 Modifications *modlist;
169 char *def_filter_str;
170 struct berval def_filter_bv = { 0, NULL };
173 LDAP_LOG ( OPERATION, DETAIL1, "do_syncrepl\n", 0, 0, 0 );
175 Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl\n", 0, 0, 0 );
181 if ( abs(si->type) != LDAP_SYNC_REFRESH_ONLY &&
182 abs(si->type) != LDAP_SYNC_REFRESH_AND_PERSIST ) {
186 /* Init connection to master */
188 if ( ldap_is_ldap_url( si->masteruri )) {
189 rc = ldap_initialize( &ld, si->masteruri );
190 if ( rc != LDAP_SUCCESS ) {
192 LDAP_LOG( OPERATION, ERR, "do_syncrepl: "
193 "ldap_initialize failed (%s)\n",
194 si->masteruri, 0, 0 );
196 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
197 "ldap_initialize failed (%s)\n",
198 si->masteruri, 0, 0 );
202 ld = ldap_init( si->mastername, si->masterport );
205 LDAP_LOG( OPERATION, ERR, "do_syncrepl: "
206 "ldap_init failed (%s:%s)\n",
207 si->mastername, si->masterport, 0 );
209 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
210 "ldap_init failed (%s:%s)\n",
211 si->mastername, si->masterport, 0 );
216 protocol = LDAP_VERSION3;
217 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol );
222 rc = ldap_start_tls_s( ld, NULL, NULL );
223 if( rc != LDAP_SUCCESS ) {
225 LDAP_LOG ( OPERATION, ERR, "do_syncrepl: "
226 "%s: ldap_start_tls failed (%d)\n",
227 si->tls == TLS_CRITICAL ? "Error" : "Warning",
230 Debug( LDAP_DEBUG_ANY,
231 "%s: ldap_start_tls failed (%d)\n",
232 si->tls == TLS_CRITICAL ? "Error" : "Warning",
235 if( si->tls == TLS_CRITICAL )
240 if ( si->bindmethod == LDAP_AUTH_SASL ) {
241 #ifdef HAVE_CYRUS_SASL
244 if ( si->secprops != NULL ) {
245 int err = ldap_set_option( ld,
246 LDAP_OPT_X_SASL_SECPROPS, si->secprops);
248 if( err != LDAP_OPT_SUCCESS ) {
250 LDAP_LOG ( OPERATION, ERR, "do_bind: Error: "
251 "ldap_set_option(%s,SECPROPS,\"%s\") failed!\n",
252 si->mastername, si->secprops, 0 );
254 Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
255 "(%s,SECPROPS,\"%s\") failed!\n",
256 si->mastername, si->secprops, NULL );
262 defaults = lutil_sasl_defaults( ld,
269 rc = ldap_sasl_interactive_bind_s( ld,
277 if ( rc != LDAP_SUCCESS ) {
279 LDAP_LOG ( OPERATION, ERR, "do_syncrepl: "
280 "ldap_sasl_interactive_bind_s failed (%d)\n",
283 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
284 "ldap_sasl_interactive_bind_s failed (%d)\n",
289 #else /* HAVE_CYRUS_SASL */
290 fprintf( stderr, "not compiled with SASL support\n" );
294 rc = ldap_bind_s( ld, si->binddn, si->passwd, si->bindmethod );
295 if ( rc != LDAP_SUCCESS ) {
297 LDAP_LOG ( OPERATION, ERR, "do_syncrepl: "
298 "ldap_bind_s failed (%d)\n", rc, 0, 0 );
300 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
301 "ldap_bind_s failed (%d)\n", rc, 0, 0 );
308 conn.c_send_ldap_result = slap_send_ldap_result;
309 conn.c_send_search_entry = slap_send_search_entry;
310 conn.c_send_search_reference = slap_send_search_reference;
314 /* get syncrepl cookie of shadow replica from subentry */
315 ber_str2bv( si->base, strlen(si->base), 1, &base_bv );
316 dnPrettyNormal( 0, &base_bv, &pbase, &nbase, op.o_tmpmemctx );
318 sprintf( substr, "cn=syncrepl%d", si->id );
319 ber_str2bv( substr, strlen(substr), 1, &sub_bv );
320 dnPrettyNormal( 0, &sub_bv, &psubrdn, &nsubrdn, op.o_tmpmemctx );
322 build_new_dn( &op.o_req_dn, &pbase, &psubrdn );
323 build_new_dn( &op.o_req_ndn, &nbase, &nsubrdn );
325 op.o_tag = LDAP_REQ_SEARCH;
326 op.o_protocol = LDAP_VERSION3;
327 ber_dupbv( &op.o_ndn, &be->be_rootndn );
329 op.o_time = slap_get_time();
330 op.o_managedsait = 1;
331 op.o_threadctx = si->ctx;
333 /* set callback function */
334 cb.sc_response = cookie_callback;
337 /* search subentry to retrieve cookie */
338 si->syncCookie = NULL;
340 op.ors_scope = LDAP_SCOPE_BASE;
341 op.ors_deref = LDAP_DEREF_NEVER;
344 op.ors_attrsonly = 0;
346 op.ors_filter = str2filter( def_filter_str = "(objectClass=*)" );
347 ber_str2bv( def_filter_str, strlen( def_filter_str ), 1,
350 be->be_search( &op, &rs );
352 /* setup LDAP SYNC control */
353 sync_ber = ber_alloc_t( LBER_USE_DER );
355 if ( si->syncCookie ) {
356 ber_printf( sync_ber, "{eO}", abs(si->type), si->syncCookie );
358 ber_printf( sync_ber, "{e}", abs(si->type) );
361 if ( ber_flatten( sync_ber, &sync_bvalp ) == LBER_ERROR ) {
362 ber_free( sync_ber, 1 );
365 ber_free( sync_ber, 1 );
367 sctrls = (LDAPControl**) ch_calloc( 3, sizeof(LDAPControl*) );
369 c[0].ldctl_oid = LDAP_CONTROL_SYNC;
370 c[0].ldctl_value = (*sync_bvalp);
371 c[0].ldctl_iscritical = si->type < 0;
375 c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
376 c[1].ldctl_value.bv_val = si->authzId;
377 c[1].ldctl_value.bv_len = strlen( si->authzId );
378 c[1].ldctl_iscritical = 1;
386 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, sctrls );
388 ber_bvfree( sync_bvalp );
391 if ( err != LDAP_OPT_SUCCESS )
392 fprintf( stderr, "Could not set controls : %d\n", err );
394 /* Delete Attributes */
395 if ( si->lastmod == LASTMOD_REQ ) {
396 descs = del_descs_lastmod;
401 for ( i = 0; descs[i] != NULL; i++ ) {
402 for ( j = 0; si->attrs[j] != NULL; j++ ) {
403 if ( !strcmp( si->attrs[j], descs[i]->ad_cname.bv_val )) {
404 ch_free( si->attrs[j] );
405 for ( k = j; si->attrs[k] != NULL; k++ ) {
406 si->attrs[k] = si->attrs[k+1];
414 for ( n = 0; si->attrs[ n ] != NULL; n++ )
417 if ( si->lastmod == LASTMOD_REQ ) {
418 descs = add_descs_lastmod;
423 for ( i = 0; descs[i] != NULL; i++ ) {
424 tmp = ( char ** ) ch_realloc( si->attrs,
425 ( n + 2 ) * sizeof( char * ));
428 LDAP_LOG( OPERATION, ERR, "out of memory\n", 0,0,0 );
430 Debug( LDAP_DEBUG_ANY, "out of memory\n", 0,0,0 );
434 si->attrs[ n++ ] = strndup( descs[i]->ad_cname.bv_val,
435 descs[i]->ad_cname.bv_len );
436 si->attrs[ n ] = NULL;
439 /* Send LDAP SYNC search */
441 rc = ldap_search_ext( ld, si->base, si->scope, si->filterstr,
442 si->attrs, si->attrsonly, NULL, NULL,
445 if( rc != LDAP_SUCCESS ) {
446 fprintf( stderr, "syncrepl: ldap_search_ext (%d)\n",
447 ldap_err2string( rc ), rc );
451 while (( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) > 0 ) {
453 for ( msg = ldap_first_message( ld, res );
455 msg = ldap_next_message( ld, msg ) )
457 switch( ldap_msgtype( msg ) ) {
458 case LDAP_RES_SEARCH_ENTRY:
459 entry = syncrepl_message_to_entry( ld, be, msg, modlist, &syncstate, &syncUUID, &syncCookie );
463 ctrl_ber = ber_init( &rctrlp->ldctl_value );
464 ber_scanf( ctrl_ber, "{em",
467 if ( ber_peek_tag( ctrl_ber, &len )
468 == LDAP_SYNC_TAG_COOKIE ) {
469 ber_scanf( ctrl_ber, "m}", &syncCookie );
473 LDAP_LOG( OPERATION, ERR,"do_syncrepl: "
477 Debug( LDAP_DEBUG_ANY, "do_syncrepl :"
484 syncrepl_entry( ld, be, entry, modlist,
485 syncstate, &syncUUID,
488 if ( syncCookie.bv_len ) {
489 syncrepl_updateCookie( ld, be, &psub,
492 ber_free( ctrl_ber, 1 );
495 case LDAP_RES_SEARCH_REFERENCE:
497 LDAP_LOG( OPERATION, ERR,
498 "do_syncrepl : reference received\n", 0, 0, 0 );
500 Debug( LDAP_DEBUG_ANY,
501 "do_syncrepl : reference received\n", 0, 0, 0 );
505 case LDAP_RES_SEARCH_RESULT:
506 ldap_parse_result( ld, msg, &err, NULL, NULL, NULL, &rctrls, 0 );
509 ctrl_ber = ber_init( &rctrlp->ldctl_value );
510 ber_scanf( ctrl_ber, "{" );
511 if ( ber_peek_tag( ctrl_ber, &len )
512 == LDAP_SYNC_TAG_COOKIE ) {
513 ber_scanf( ctrl_ber, "m", &syncCookie );
516 if (si->type == LDAP_SYNC_REFRESH_AND_PERSIST) {
517 if ( cancel_response ) {
518 if ( syncCookie.bv_len ) {
519 ber_bvfree( si->syncCookie );
520 si->syncCookie = ber_dupbv( NULL, &syncCookie );
527 if ( syncCookie.bv_len ) {
528 syncrepl_updateCookie( ld,
537 case LDAP_RES_INTERMEDIATE_RESP:
538 ldap_parse_intermediate_resp_result( ld, msg,
539 &retoid, &retdata, 0 );
540 if ( !strcmp( retoid, LDAP_SYNC_INFO ) ) {
541 sync_info_arrived = 1;
542 res_ber = ber_init( retdata );
543 ber_scanf( res_ber, "{e", &syncstate );
545 if ( syncstate == LDAP_SYNC_REFRESH_DONE ) {
546 syncrepl_del_nonpresent( ld, be );
547 } else if ( syncstate != LDAP_SYNC_NEW_COOKIE ) {
549 LDAP_LOG( OPERATION, ERR,
550 "do_syncrepl : unknown sync info\n", 0, 0, 0 );
552 Debug( LDAP_DEBUG_ANY,
553 "do_syncrepl : unknown sync info\n", 0, 0, 0 );
557 if ( ber_peek_tag( res_ber, &len )
558 == LDAP_SYNC_TAG_COOKIE ) {
559 ber_scanf( res_ber, "m}", &syncCookie );
560 if ( syncCookie.bv_len ) {
561 ber_bvfree( si->syncCookie );
562 si->syncCookie = ber_dupbv( NULL, &syncCookie );
565 if ( syncstate == LDAP_SYNC_NEW_COOKIE ) {
567 LDAP_LOG( OPERATION, ERR,
568 "do_syncrepl : cookie required\n", 0, 0, 0 );
570 Debug( LDAP_DEBUG_ANY,
571 "do_syncrepl : cookie required\n", 0, 0, 0 );
576 ldap_memfree( retoid );
577 ber_bvfree( retdata );
578 ber_free( res_ber, 1 );
582 LDAP_LOG( OPERATION, ERR,"do_syncrepl :"
583 " unknown intermediate "
584 "response\n", 0, 0, 0 );
586 Debug( LDAP_DEBUG_ANY, "do_syncrepl : "
587 "unknown intermediate "
588 "response\n", 0, 0, 0 );
590 ldap_memfree( retoid );
591 ber_bvfree( retdata );
597 LDAP_LOG( OPERATION, ERR, "do_syncrepl : "
598 "unknown message\n", 0, 0, 0 );
600 Debug( LDAP_DEBUG_ANY, "do_syncrepl : "
601 "unknown message\n", 0, 0, 0 );
612 LDAP_LOG( OPERATION, ERR,
613 "do_syncrepl : unknown result\n", 0, 0, 0 );
615 Debug( LDAP_DEBUG_ANY,
616 "do_syncrepl : unknown result\n", 0, 0, 0 );
622 sleep(si->interval * 60);
624 // set alarm clock to send signal to slapd
625 // should set the signal handler beforehand
626 // the signal handler re execute do_syncrepl()
636 syncrepl_message_to_entry(
640 Modifications *modlist,
642 struct berval *syncUUID,
643 struct berval *syncCookie
647 BerElement *ber = NULL;
651 Modifications **modtail = &modlist;
654 char txtbuf[SLAP_TEXT_BUFLEN];
655 size_t textlen = sizeof txtbuf;
657 struct berval **bvals;
661 struct berval empty_bv = { 0, NULL };
666 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
670 LDAPControl** rctrls = NULL;
671 BerElement* ctrl_ber;
675 if ( msg->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) {
677 LDAP_LOG( OPERATION, ERR,
678 "Message type should be entry (%d)", msg->lm_msgtype, 0, 0 );
680 Debug( LDAP_DEBUG_ANY,
681 "Message type should be entry (%d)", msg->lm_msgtype, 0, 0 );
686 op.o_tag = LDAP_REQ_ADD;
687 ber_dupbv( &op.o_ndn, &be->be_rootndn );
689 rc = ldap_get_dn_ber( ld, msg, &ber, &bdn );
691 if ( rc != LDAP_SUCCESS ) {
693 LDAP_LOG( OPERATION, ERR,
694 "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
696 Debug( LDAP_DEBUG_ANY,
697 "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
702 e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
703 dnPrettyNormal( NULL, &bdn, &e->e_name, &e->e_nname, NULL );
707 for ( rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues);
709 rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues))
711 if ( tmp.sml_type.bv_val == NULL ) break;
713 mod = (Modifications *) ch_malloc( sizeof(Modifications) );
715 mod->sml_op = LDAP_MOD_ADD;
716 mod->sml_next = NULL;
717 mod->sml_desc = NULL;
718 mod->sml_type = tmp.sml_type;
719 mod->sml_bvalues = tmp.sml_bvalues;
722 modtail = &mod->sml_next;
725 if ( ber_scanf( ber, "}") == LBER_ERROR ) {
727 LDAP_LOG( OPERATION, ERR,
728 "syncrepl_message_to_entry: ber_scanf failed\n", 0, 0, 0 );
730 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: ber_scanf failed\n",
737 ber_scanf( ber, "{xx" );
739 rc = ldap_int_get_controls( ber, &rctrls );
741 if ( rc != LDAP_SUCCESS ) {
743 LDAP_LOG( OPERATION, ERR,
744 "syncrepl_message_to_entry : control get failed (%d)", rc, 0, 0 );
746 Debug( LDAP_DEBUG_ANY,
747 "syncrepl_message_to_entry : control get failed (%d)", rc, 0, 0 );
754 ctrl_ber = ber_init( &rctrlp->ldctl_value );
755 ber_scanf( ctrl_ber, "{em", syncstate, syncUUID );
756 if ( ber_peek_tag( ctrl_ber, &len ) == LDAP_SYNC_TAG_COOKIE ) {
757 ber_scanf( ctrl_ber, "m}", syncCookie );
761 LDAP_LOG( OPERATION, ERR,"syncrepl_message_to_entry : "
762 " rctrls absent\n", 0, 0, 0 );
764 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry :"
765 " rctrls absent\n", 0, 0, 0 );
769 if ( *syncstate == LDAP_SYNC_PRESENT ) {
774 if ( modlist == NULL ) {
776 LDAP_LOG( OPERATION, ERR,
777 "syncrepl_message_to_entry: no attributes\n", 0, 0, 0 );
779 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: no attributes\n",
784 rc = slap_mods_check_syncrepl( be, &modlist, &text, txtbuf, textlen, NULL );
786 if ( rc != LDAP_SUCCESS ) {
788 LDAP_LOG( OPERATION, ERR,
789 "syncrepl_message_to_entry: mods check (%s)\n", text, 0, 0 );
791 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods check (%s)\n",
797 rc = slap_mods_opattrs_syncrepl( be, &op, modlist, modtail,
798 &text,txtbuf, textlen );
800 if( rc != LDAP_SUCCESS ) {
802 LDAP_LOG( OPERATION, ERR,
803 "syncrepl_message_to_entry: mods opattrs (%s)\n", text, 0, 0 );
805 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods opattrs (%s)\n",
811 rc = slap_mods2entry_syncrepl( modlist, &e, 1, &text, txtbuf, textlen );
812 if( rc != LDAP_SUCCESS ) {
814 LDAP_LOG( OPERATION, ERR,
815 "syncrepl_message_to_entry: mods2entry (%s)\n", text, 0, 0 );
817 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods2entry (%s)\n",
830 syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 )
832 const struct berval *uuid1 = v_uuid1;
833 const struct berval *uuid2 = v_uuid2;
834 int rc = uuid1->bv_len - uuid2->bv_len;
836 return ( strcmp( uuid1->bv_val, uuid2->bv_val ) );
844 Modifications* modlist,
846 struct berval* syncUUID,
847 struct berval* syncCookie,
851 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
853 struct berval normdn = {0, NULL};
854 struct berval prettydn = {0, NULL};
855 struct berval pbase = {0, NULL};
856 struct berval nbase = {0, NULL};
857 struct berval base_bv = {0, NULL};
858 struct berval csn_bv = {0, NULL};
859 struct berval *syncuuid_bv = NULL;
860 char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
863 SlapReply rs = {REP_RESULT};
867 struct berval filterstr_bv;
872 if ( syncstate == LDAP_SYNC_PRESENT ) {
873 syncuuid_bv = ber_dupbv( NULL, syncUUID );
874 avl_insert( &si->presentlist, (caddr_t) syncuuid_bv,
875 syncuuid_cmp, avl_dup_error );
879 if ( !attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )) {
880 attr_merge_one( e, slap_schema.si_ad_entryUUID, syncUUID, syncUUID );
883 filterstr = (char *) ch_malloc( strlen("entryUUID=") + syncUUID->bv_len + 1 );
884 strcpy( filterstr, "entryUUID=" );
885 strcat( filterstr, syncUUID->bv_val );
888 si->syncUUID = syncUUID;
890 filter = str2filter( filterstr );
891 ber_str2bv( filterstr, strlen(filterstr), 1, &filterstr_bv );
892 ch_free( filterstr );
894 dnPrettyNormal( 0, &(e->e_name), &prettydn, &normdn, NULL );
896 free(e->e_name.bv_val);
897 free(e->e_nname.bv_val);
898 e->e_name = prettydn;
900 op.o_req_dn = e->e_name;
901 op.o_req_ndn = e->e_nname;
903 ber_str2bv( si->base, strlen(si->base), 1, &base_bv );
904 dnPrettyNormal( 0, &base_bv, &pbase, &nbase, NULL );
906 op.o_protocol = LDAP_VERSION3;
907 ber_dupbv( &op.o_ndn, &be->be_rootndn );
909 op.o_time = slap_get_time();
910 op.o_managedsait = 1;
911 op.o_threadctx = si->ctx;
913 cb.sc_response = null_callback;
916 switch ( syncstate ) {
918 case LDAP_SYNC_MODIFY :
920 op.o_tag = LDAP_REQ_MODIFY;
921 op.orm_modlist = modlist;
922 rc = be->be_modify( &op, &rs );
923 if ( rc != LDAP_SUCCESS ) {
924 if ( rc == LDAP_REFERRAL || rc == LDAP_NO_SUCH_OBJECT || rc == DB_NOTFOUND ) {
925 op.o_tag = LDAP_REQ_ADD;
927 rc = be->be_add( &op, &rs );
928 if ( rc != LDAP_SUCCESS ) {
929 if ( rc == LDAP_ALREADY_EXISTS ) {
931 } else if ( rc == LDAP_REFERRAL || rc == LDAP_NO_SUCH_OBJECT || rc == DB_NOTFOUND ) {
932 syncrepl_add_glue(ld, si->conn,
935 syncUUID, syncCookie);
938 LDAP_LOG( OPERATION, ERR,
939 "be_add failed (%d)\n",
942 Debug( LDAP_DEBUG_ANY,
943 "be_add failed (%d)\n",
950 LDAP_LOG( OPERATION, ERR,
951 "be_modify failed (%d)\n", rc, 0, 0 );
953 Debug( LDAP_DEBUG_ANY,
954 "be_modify failed (%d)\n", rc, 0, 0 );
961 case LDAP_SYNC_DELETE :
962 be->be_delete( &op, &rs );
968 LDAP_LOG( OPERATION, ERR,
969 "unknown syncstate\n", 0, 0, 0 );
971 Debug( LDAP_DEBUG_ANY,
972 "unknown syncstate\n", 0, 0, 0 );
979 syncrepl_del_nonpresent(
984 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
986 struct berval base_bv = {0, NULL};
989 SlapReply rs = {REP_RESULT};
990 struct berval filterstr_bv;
992 ber_str2bv( si->base, strlen(si->base), 1, &base_bv );
993 dnPrettyNormal(0, &base_bv, &op.o_req_dn, &op.o_req_ndn, NULL );
995 filter = str2filter( si->filterstr );
997 op.o_tag = LDAP_REQ_SEARCH;
998 op.o_protocol = LDAP_VERSION3;
999 ber_dupbv( &op.o_ndn, &be->be_rootndn );
1000 op.o_callback = &cb;
1001 op.o_time = slap_get_time();
1002 op.o_managedsait = 1;
1003 op.o_threadctx = si->ctx;
1005 cb.sc_response = nonpresent_callback;
1008 op.ors_scope = LDAP_SCOPE_BASE;
1009 op.ors_deref = LDAP_DEREF_NEVER;
1012 op.ors_attrsonly = 0;
1013 op.ors_attrs = NULL;
1014 op.ors_filter = str2filter( si->filterstr );
1015 ber_str2bv( si->filterstr, strlen( si->filterstr ),
1016 1, &op.ors_filterstr );
1018 be->be_search( &op, &rs );
1029 Modifications* modlist,
1031 struct berval* syncUUID,
1032 struct berval* syncCookie
1035 syncinfo_t *si = op->o_callback->sc_private;
1036 struct berval uuid_bv = {0, NULL};
1040 char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
1043 struct berval dn = {0, NULL};
1044 struct berval pdn = {0, NULL};
1045 struct berval ndn = {0, NULL};
1046 struct berval rdn = {0, NULL};
1048 SlapReply rs = {REP_RESULT};
1050 op->o_tag = LDAP_REQ_ADD;
1051 op->o_callback = &cb;
1052 cb.sc_response = null_callback;
1055 ber_dupbv( &dn, &e->e_nname );
1056 ber_dupbv( &pdn, &e->e_nname );
1057 while ( !be_issuffix ( be, &pdn )) {
1058 dnParent( &dn, &pdn );
1059 ber_dupbv( &dn, &pdn );
1063 for ( i = 0; i <= levels; i++ ) {
1064 glue = (Entry*) ch_calloc( 1, sizeof(Entry) );
1065 ber_dupbv( &dn, &e->e_nname );
1066 ber_dupbv( &pdn, &e->e_nname );
1068 for ( k = 0; k < j; k++ ) {
1069 dnParent( &dn, &pdn );
1070 ber_dupbv( &dn, &pdn );
1073 dnPrettyNormal( 0, &dn, &pdn, &ndn, NULL );
1074 ber_dupbv( &glue->e_name, &pdn );
1075 ber_dupbv( &glue->e_nname, &ndn );
1077 a = ch_calloc( 1, sizeof( Attribute ));
1078 a->a_desc = slap_schema.si_ad_objectClass;
1079 a->a_vals = ch_calloc( 3, sizeof( struct berval ));
1080 ber_str2bv( "top", strlen("top"), 1, &a->a_vals[0] );
1081 ber_str2bv( "glue", strlen("glue"), 1, &a->a_vals[1] );
1082 a->a_vals[2].bv_len = 0;
1083 a->a_vals[2].bv_val = NULL;
1084 a->a_next = glue->e_attrs;
1087 a = ch_calloc( 1, sizeof( Attribute ));
1088 a->a_desc = slap_schema.si_ad_structuralObjectClass;
1089 a->a_vals = ch_calloc( 2, sizeof( struct berval ));
1090 ber_str2bv( "glue", strlen("glue"), 1, &a->a_vals[0] );
1091 a->a_vals[1].bv_len = 0;
1092 a->a_vals[1].bv_val = NULL;
1093 a->a_next = glue->e_attrs;
1096 if ( !strcmp( e->e_nname.bv_val, glue->e_nname.bv_val )) {
1097 op->o_req_dn = e->e_name;
1098 op->o_req_ndn = e->e_nname;
1100 rc = be->be_add ( op, &rs );
1101 if ( rc == LDAP_SUCCESS )
1102 be_entry_release_w( op, e );
1107 op->o_req_dn = glue->e_name;
1108 op->o_req_ndn = glue->e_nname;
1110 rc = be->be_add ( op, &rs );
1111 if ( rc == LDAP_SUCCESS )
1112 be_entry_release_w( op, glue );
1122 syncrepl_updateCookie(
1126 struct berval *syncCookie
1129 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
1131 Modifications *modlist;
1132 Modifications **modtail = &modlist;
1134 struct berval* ocbva;
1135 struct berval* cnbva;
1136 struct berval* ssbva;
1137 struct berval* scbva;
1141 char txtbuf[SLAP_TEXT_BUFLEN];
1142 size_t textlen = sizeof txtbuf;
1149 SlapReply rs = {REP_RESULT};
1151 ocbva = ( struct berval * ) ch_calloc( 4, sizeof( struct berval ));
1152 cnbva = ( struct berval * ) ch_calloc( 2, sizeof( struct berval ));
1153 ssbva = ( struct berval * ) ch_calloc( 2, sizeof( struct berval ));
1154 scbva = ( struct berval * ) ch_calloc( 2, sizeof( struct berval ));
1155 substr = ( char * ) ch_calloc( 64, sizeof( char ));
1157 /* update in memory cookie */
1158 if ( si->syncCookie != NULL ) {
1159 ber_bvfree( si->syncCookie );
1161 si->syncCookie = ber_dupbv( NULL, syncCookie );
1162 ber_str2bv( "top", strlen("top"), 0, &ocbva[0] );
1163 ber_str2bv( "subentry", strlen("subentry"), 0, &ocbva[1] );
1164 ber_str2bv( "syncConsumerSubentry",
1165 strlen("syncConsumerSubentry"), 0, &ocbva[2] );
1166 ocbva[3].bv_len = 0;
1167 ocbva[3].bv_val = NULL;
1169 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1170 mod->sml_op = LDAP_MOD_REPLACE;
1171 mod->sml_next = NULL;
1172 mod->sml_desc = NULL;
1173 ber_str2bv( "objectClass", strlen("objectClass"), 0, &mod->sml_type );
1174 mod->sml_bvalues = ocbva;
1176 modtail = &mod->sml_next;
1178 sprintf( substr, "syncrepl%d", si->id );
1179 ber_str2bv( substr, strlen( substr ), 1, &cnbva[0] );
1181 cnbva[1].bv_len = 0;
1182 cnbva[1].bv_val = NULL;
1183 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1184 mod->sml_op = LDAP_MOD_REPLACE;
1185 mod->sml_next = NULL;
1186 mod->sml_desc = NULL;
1187 ber_str2bv( "cn", strlen("cn"), 0, &mod->sml_type );
1188 mod->sml_bvalues = cnbva;
1190 modtail = &mod->sml_next;
1192 ber_dupbv( &scbva[0], si->syncCookie );
1193 scbva[1].bv_len = 0;
1194 scbva[1].bv_val = NULL;
1195 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1196 mod->sml_op = LDAP_MOD_REPLACE;
1197 mod->sml_next = NULL;
1198 mod->sml_desc = NULL;
1199 ber_str2bv( "syncreplCookie", strlen("syncreplCookie"),
1200 0, &mod->sml_type );
1201 mod->sml_bvalues = scbva;
1203 modtail = &mod->sml_next;
1205 ber_str2bv( " ", 1, 1, &ssbva[0] );
1206 ssbva[1].bv_len = 0;
1207 ssbva[1].bv_val = NULL;
1208 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1209 mod->sml_op = LDAP_MOD_REPLACE;
1210 mod->sml_next = NULL;
1211 mod->sml_desc = NULL;
1212 ber_str2bv( "subtreeSpecification",
1213 strlen("subtreeSpecification"), 0, &mod->sml_type );
1214 mod->sml_bvalues = ssbva;
1216 modtail = &mod->sml_next;
1218 rc = slap_mods_check_syncrepl( be, &modlist, &text, txtbuf, textlen, NULL );
1220 if ( rc != LDAP_SUCCESS ) {
1222 LDAP_LOG( OPERATION, ERR,
1223 "syncrepl_updateCookie: mods check (%s)\n", text, 0, 0 );
1225 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods check (%s)\n",
1230 op.o_tag = LDAP_REQ_ADD;
1231 rc = slap_mods_opattrs_syncrepl( be, &op, modlist, modtail,
1232 &text,txtbuf, textlen );
1234 if( rc != LDAP_SUCCESS ) {
1236 LDAP_LOG( OPERATION, ERR,
1237 "syncrepl_updateCookie: mods opattrs (%s)\n", text, 0, 0 );
1239 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods opattrs (%s)\n",
1244 e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1245 dnPrettyNormal( NULL, pdn, &e->e_name, &e->e_nname, NULL );
1249 rc = slap_mods2entry_syncrepl( modlist, &e, 1, &text, txtbuf, textlen );
1251 if( rc != LDAP_SUCCESS ) {
1253 LDAP_LOG( OPERATION, ERR,
1254 "syncrepl_updateCookie: mods2entry (%s)\n", text, 0, 0 );
1256 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods2entry (%s)\n",
1261 op.o_protocol = LDAP_VERSION3;
1262 ber_dupbv( &op.o_ndn, &be->be_rootndn );
1263 op.o_callback = &cb;
1264 op.o_time = slap_get_time();
1265 op.o_managedsait = 1;
1266 op.o_threadctx = si->ctx;
1268 cb.sc_response = null_callback;
1271 op.o_req_dn = e->e_name;
1272 op.o_req_ndn = e->e_nname;
1275 for( mod = modlist; mod != NULL; mod = mod->sml_next ) {
1276 mod->sml_op = LDAP_MOD_REPLACE;
1280 /* update persistent cookie */
1281 update_cookie_retry:
1282 op.o_tag = LDAP_REQ_MODIFY;
1283 op.orm_modlist = modlist;
1284 rc = be->be_modify( &op, &rs );
1285 if ( rc != LDAP_SUCCESS ) {
1286 if ( rc == LDAP_REFERRAL ||
1287 rc == LDAP_NO_SUCH_OBJECT ||
1288 rc == DB_NOTFOUND ) {
1289 op.o_tag = LDAP_REQ_ADD;
1291 rc = be->be_add( &op, &rs );
1292 if ( rc != LDAP_SUCCESS ) {
1293 if ( rc == LDAP_ALREADY_EXISTS ) {
1294 goto update_cookie_retry;
1295 } else if ( rc == LDAP_REFERRAL ||
1296 rc == LDAP_NO_SUCH_OBJECT ||
1297 rc == DB_NOTFOUND ) {
1299 LDAP_LOG( OPERATION, ERR,
1300 "cookie will be non-persistent\n",
1303 Debug( LDAP_DEBUG_ANY,
1304 "cookie will be non-persistent\n",
1309 LDAP_LOG( OPERATION, ERR,
1310 "be_add failed (%d)\n",
1313 Debug( LDAP_DEBUG_ANY,
1314 "be_add failed (%d)\n",
1321 LDAP_LOG( OPERATION, ERR,
1322 "be_modify failed (%d)\n", rc, 0, 0 );
1324 Debug( LDAP_DEBUG_ANY,
1325 "be_modify failed (%d)\n", rc, 0, 0 );
1333 int slap_mods_check_syncrepl(
1335 Modifications **mlp,
1342 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
1343 AttributeDescription** descs;
1345 Modifications *prevml = NULL;
1346 Modifications *nextml = NULL;
1347 Modifications *ml = *mlp;
1349 while ( ml != NULL ) {
1350 AttributeDescription *ad = NULL;
1352 /* convert to attribute description */
1353 rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text );
1355 if( rc != LDAP_SUCCESS ) {
1356 snprintf( textbuf, textlen, "%s: %s",
1357 ml->sml_type.bv_val, *text );
1364 if ( si->lastmod == LASTMOD_REQ ) {
1365 descs = del_descs_lastmod;
1370 for ( i = 0; descs[i] != NULL; i++ ) {
1371 if ( ad == descs[i] ) {
1372 if ( prevml == NULL ) {
1373 mlp = &ml->sml_next;
1376 prevml->sml_next = ml->sml_next;
1378 slap_mod_free( &ml->sml_mod, 0 );
1379 nextml = ml->sml_next;
1386 if( slap_syntax_is_binary( ad->ad_type->sat_syntax )
1387 && !slap_ad_is_binary( ad ))
1389 /* attribute requires binary transfer */
1390 snprintf( textbuf, textlen,
1391 "%s: requires ;binary transfer",
1392 ml->sml_type.bv_val );
1394 return LDAP_UNDEFINED_TYPE;
1397 if( !slap_syntax_is_binary( ad->ad_type->sat_syntax )
1398 && slap_ad_is_binary( ad ))
1400 /* attribute requires binary transfer */
1401 snprintf( textbuf, textlen,
1402 "%s: disallows ;binary transfer",
1403 ml->sml_type.bv_val );
1405 return LDAP_UNDEFINED_TYPE;
1408 if( slap_ad_is_tag_range( ad )) {
1409 /* attribute requires binary transfer */
1410 snprintf( textbuf, textlen,
1411 "%s: inappropriate use of tag range option",
1412 ml->sml_type.bv_val );
1414 return LDAP_UNDEFINED_TYPE;
1417 if ( is_at_obsolete( ad->ad_type ) &&
1418 ( ml->sml_op == LDAP_MOD_ADD || ml->sml_values != NULL ) )
1421 * attribute is obsolete,
1422 * only allow replace/delete with no values
1424 snprintf( textbuf, textlen,
1425 "%s: attribute is obsolete",
1426 ml->sml_type.bv_val );
1428 return LDAP_CONSTRAINT_VIOLATION;
1434 if( ml->sml_values != NULL ) {
1436 slap_syntax_validate_func *validate =
1437 ad->ad_type->sat_syntax->ssyn_validate;
1438 slap_syntax_transform_func *pretty =
1439 ad->ad_type->sat_syntax->ssyn_pretty;
1441 if( !pretty && !validate ) {
1442 *text = "no validator for syntax";
1443 snprintf( textbuf, textlen,
1444 "%s: no validator for syntax %s",
1445 ml->sml_type.bv_val,
1446 ad->ad_type->sat_syntax->ssyn_oid );
1448 return LDAP_INVALID_SYNTAX;
1452 * check that each value is valid per syntax
1453 * and pretty if appropriate
1455 for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {
1458 rc = pretty( ad->ad_type->sat_syntax,
1459 &ml->sml_values[nvals], &pval,
1462 rc = validate( ad->ad_type->sat_syntax,
1463 &ml->sml_values[nvals] );
1467 snprintf( textbuf, textlen,
1468 "%s: value #%ld invalid per syntax",
1469 ml->sml_type.bv_val, (long) nvals );
1471 return LDAP_INVALID_SYNTAX;
1475 ber_memfree( ml->sml_values[nvals].bv_val );
1476 ml->sml_values[nvals] = pval;
1481 * a rough single value check... an additional check is needed
1482 * to catch add of single value to existing single valued attribute
1484 if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE)
1485 && nvals > 1 && is_at_single_value( ad->ad_type ))
1487 snprintf( textbuf, textlen,
1488 "%s: multiple values provided",
1489 ml->sml_type.bv_val );
1491 return LDAP_CONSTRAINT_VIOLATION;
1494 if( nvals && ad->ad_type->sat_equality &&
1495 ad->ad_type->sat_equality->smr_normalize )
1497 ml->sml_nvalues = ch_malloc( (nvals+1)*sizeof(struct berval) );
1498 for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {
1499 rc = ad->ad_type->sat_equality->smr_normalize(
1501 ad->ad_type->sat_syntax,
1502 ad->ad_type->sat_equality,
1503 &ml->sml_values[nvals], &ml->sml_nvalues[nvals],
1507 LDAP_LOG( OPERATION, DETAIL1,
1508 "str2entry: NULL (ssyn_normalize %d)\n",
1511 Debug( LDAP_DEBUG_ANY,
1512 "<= str2entry NULL (ssyn_normalize %d)\n",
1515 snprintf( textbuf, textlen,
1516 "%s: value #%ld normalization failed",
1517 ml->sml_type.bv_val, (long) nvals );
1522 ml->sml_nvalues[nvals].bv_val = NULL;
1523 ml->sml_nvalues[nvals].bv_len = 0;
1530 return LDAP_SUCCESS;
1534 int slap_mods_opattrs_syncrepl(
1537 Modifications *mods,
1538 Modifications **modtail,
1540 char *textbuf, size_t textlen )
1542 struct berval name, timestamp, csn;
1543 struct berval nname;
1544 char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
1545 char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
1547 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
1549 int mop = op->o_tag == LDAP_REQ_ADD
1550 ? LDAP_MOD_ADD : LDAP_MOD_REPLACE;
1552 assert( modtail != NULL );
1553 assert( *modtail == NULL );
1555 if( si->lastmod == LASTMOD_GEN ) {
1557 time_t now = slap_get_time();
1559 ldap_pvt_thread_mutex_lock( &gmtime_mutex );
1560 ltm = gmtime( &now );
1561 lutil_gentime( timebuf, sizeof(timebuf), ltm );
1563 csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), 0, 0 );
1564 ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
1565 csn.bv_val = csnbuf;
1567 timestamp.bv_val = timebuf;
1568 timestamp.bv_len = strlen(timebuf);
1570 if( op->o_dn.bv_len == 0 ) {
1571 name.bv_val = SLAPD_ANONYMOUS;
1572 name.bv_len = sizeof(SLAPD_ANONYMOUS)-1;
1580 if( op->o_tag == LDAP_REQ_ADD ) {
1581 struct berval tmpval;
1583 if( global_schemacheck ) {
1584 int rc = mods_structural_class( mods, &tmpval,
1585 text, textbuf, textlen );
1586 if( rc != LDAP_SUCCESS ) {
1590 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1592 mod->sml_type.bv_val = NULL;
1593 mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
1595 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1596 ber_dupbv( &mod->sml_values[0], &tmpval );
1597 mod->sml_values[1].bv_len = 0;
1598 mod->sml_values[1].bv_val = NULL;
1599 assert( mod->sml_values[0].bv_val );
1601 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1602 ber_dupbv( &mod->sml_nvalues[0], &tmpval );
1603 mod->sml_nvalues[1].bv_len = 0;
1604 mod->sml_nvalues[1].bv_val = NULL;
1605 assert( mod->sml_nvalues[0].bv_val );
1607 modtail = &mod->sml_next;
1610 if( si->lastmod == LASTMOD_GEN ) {
1611 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1613 mod->sml_type.bv_val = NULL;
1614 mod->sml_desc = slap_schema.si_ad_creatorsName;
1615 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1616 ber_dupbv( &mod->sml_values[0], &name );
1617 mod->sml_values[1].bv_len = 0;
1618 mod->sml_values[1].bv_val = NULL;
1619 assert( mod->sml_values[0].bv_val );
1621 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1622 ber_dupbv( &mod->sml_nvalues[0], &nname );
1623 mod->sml_nvalues[1].bv_len = 0;
1624 mod->sml_nvalues[1].bv_val = NULL;
1625 assert( mod->sml_nvalues[0].bv_val );
1627 modtail = &mod->sml_next;
1629 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1631 mod->sml_type.bv_val = NULL;
1632 mod->sml_desc = slap_schema.si_ad_createTimestamp;
1633 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1634 ber_dupbv( &mod->sml_values[0], ×tamp );
1635 mod->sml_values[1].bv_len = 0;
1636 mod->sml_values[1].bv_val = NULL;
1637 assert( mod->sml_values[0].bv_val );
1638 mod->sml_nvalues = NULL;
1640 modtail = &mod->sml_next;
1644 if( si->lastmod == LASTMOD_GEN ) {
1645 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1647 mod->sml_type.bv_val = NULL;
1648 mod->sml_desc = slap_schema.si_ad_entryCSN;
1649 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1650 ber_dupbv( &mod->sml_values[0], &csn );
1651 mod->sml_values[1].bv_len = 0;
1652 mod->sml_values[1].bv_val = NULL;
1653 assert( mod->sml_values[0].bv_val );
1654 mod->sml_nvalues = NULL;
1656 modtail = &mod->sml_next;
1658 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1660 mod->sml_type.bv_val = NULL;
1661 mod->sml_desc = slap_schema.si_ad_modifiersName;
1662 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1663 ber_dupbv( &mod->sml_values[0], &name );
1664 mod->sml_values[1].bv_len = 0;
1665 mod->sml_values[1].bv_val = NULL;
1666 assert( mod->sml_values[0].bv_val );
1668 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1669 ber_dupbv( &mod->sml_nvalues[0], &nname );
1670 mod->sml_nvalues[1].bv_len = 0;
1671 mod->sml_nvalues[1].bv_val = NULL;
1672 assert( mod->sml_nvalues[0].bv_val );
1674 modtail = &mod->sml_next;
1676 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1678 mod->sml_type.bv_val = NULL;
1679 mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
1680 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1681 ber_dupbv( &mod->sml_values[0], ×tamp );
1682 mod->sml_values[1].bv_len = 0;
1683 mod->sml_values[1].bv_val = NULL;
1684 assert( mod->sml_values[0].bv_val );
1685 mod->sml_nvalues = NULL;
1687 modtail = &mod->sml_next;
1691 return LDAP_SUCCESS;
1696 int slap_mods2entry_syncrepl(
1697 Modifications *mods,
1701 char *textbuf, size_t textlen )
1703 Attribute **tail = &(*e)->e_attrs;
1704 assert( *tail == NULL );
1708 for( ; mods != NULL; mods = mods->sml_next ) {
1711 assert( mods->sml_desc != NULL );
1713 attr = attr_find( (*e)->e_attrs, mods->sml_desc );
1715 if( attr != NULL ) {
1716 #define SLURPD_FRIENDLY
1717 #ifdef SLURPD_FRIENDLY
1721 snprintf( textbuf, textlen,
1722 "attribute '%s' provided more than once",
1723 mods->sml_desc->ad_cname.bv_val );
1724 return LDAP_TYPE_OR_VALUE_EXISTS;
1727 for( i=0; attr->a_vals[i].bv_val; i++ ) {
1730 for( j=0; mods->sml_values[j].bv_val; j++ ) {
1735 attr->a_vals = ch_realloc( attr->a_vals,
1736 sizeof( struct berval ) * (i+j) );
1738 /* should check for duplicates */
1740 AC_MEMCPY( &attr->a_vals[i], mods->sml_values,
1741 sizeof( struct berval ) * j );
1743 if( attr->a_nvals ) {
1744 attr->a_nvals = ch_realloc( attr->a_nvals,
1745 sizeof( struct berval ) * (i+j) );
1747 AC_MEMCPY( &attr->a_nvals[i], mods->sml_nvalues,
1748 sizeof( struct berval ) * j );
1750 /* trim the mods array */
1751 ch_free( mods->sml_nvalues );
1752 mods->sml_nvalues = NULL;
1757 snprintf( textbuf, textlen,
1758 "attribute '%s' provided more than once",
1759 mods->sml_desc->ad_cname.bv_val );
1760 return LDAP_TYPE_OR_VALUE_EXISTS;
1764 if( mods->sml_values[1].bv_val != NULL ) {
1765 /* check for duplicates */
1767 MatchingRule *mr = mods->sml_desc->ad_type->sat_equality;
1769 /* check if the values we're adding already exist */
1770 if( mr == NULL || !mr->smr_match ) {
1771 for ( i = 0; mods->sml_bvalues[i].bv_val != NULL; i++ ) {
1772 /* test asserted values against themselves */
1773 for( j = 0; j < i; j++ ) {
1774 if ( bvmatch( &mods->sml_bvalues[i],
1775 &mods->sml_bvalues[j] ) ) {
1776 /* value exists already */
1777 snprintf( textbuf, textlen,
1778 "%s: value #%d provided more than once",
1779 mods->sml_desc->ad_cname.bv_val, j );
1780 return LDAP_TYPE_OR_VALUE_EXISTS;
1787 const char *text = NULL;
1788 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
1790 rc = modify_check_duplicates( mods->sml_desc, mr,
1791 NULL, mods->sml_bvalues, 0,
1792 &text, textbuf, sizeof( textbuf ) );
1794 if ( rc != LDAP_SUCCESS ) {
1800 attr = ch_calloc( 1, sizeof(Attribute) );
1802 /* move ad to attr structure */
1803 attr->a_desc = mods->sml_desc;
1805 /* move values to attr structure */
1806 /* should check for duplicates */
1807 attr->a_vals = mods->sml_values;
1809 attr->a_nvals = mods->sml_nvalues;
1812 tail = &attr->a_next;
1815 return LDAP_SUCCESS;
1819 avl_ber_bvfree( void *bv )
1824 if ( ((struct berval *)bv)->bv_val != NULL ) {
1825 LBER_FREE( ((struct berval *)bv)->bv_val );
1827 LBER_FREE( (char *) bv );
1836 syncinfo_t *si = op->o_callback->sc_private;
1839 if ( rs->sr_type != REP_SEARCH ) return LDAP_SUCCESS;
1841 a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_syncreplCookie );
1844 si->syncCookie = NULL;
1846 si->syncCookie = ber_dupbv( NULL, &a->a_vals[0] );
1848 return LDAP_SUCCESS;
1852 nonpresent_callback(
1857 syncinfo_t *si = op->o_callback->sc_private;
1860 struct berval* present_uuid = NULL;
1862 SlapReply rs_cb = {REP_RESULT};
1864 if ( rs->sr_type == REP_RESULT ) {
1865 count = avl_free( si->presentlist, avl_ber_bvfree );
1866 return LDAP_SUCCESS;
1867 } else if ( rs->sr_type == REP_SEARCH ) {
1868 a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
1873 present_uuid = avl_find( si->presentlist,
1874 &a->a_vals[0], syncuuid_cmp );
1876 if ( present_uuid == NULL ) {
1877 op->o_tag = LDAP_REQ_DELETE;
1878 op->o_callback = &cb;
1879 cb.sc_response = null_callback;
1881 op->o_req_dn = rs->sr_entry->e_name;
1882 op->o_req_ndn = rs->sr_entry->e_nname;
1883 op->o_bd->be_delete( op, &rs_cb );
1885 avl_delete( &si->presentlist,
1886 &a->a_vals[0], syncuuid_cmp );
1888 return LDAP_SUCCESS;
1890 return LDAP_SUCCESS;
1901 if ( rs->sr_err != LDAP_SUCCESS &&
1902 rs->sr_err != LDAP_REFERRAL &&
1903 rs->sr_err != LDAP_ALREADY_EXISTS &&
1904 rs->sr_err != LDAP_NO_SUCH_OBJECT &&
1905 rs->sr_err != DB_NOTFOUND ) {
1907 LDAP_LOG( OPERATION, ERR,
1908 "null_callback : error code 0x%x\n",
1911 Debug( LDAP_DEBUG_ANY,
1912 "null_callback : error code 0x%x\n",
1916 return LDAP_SUCCESS;