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 int slap_mods_check_syncrepl( Backend *, Modifications **,
53 const char **, char *, size_t );
54 int slap_mods_opattrs_syncrepl( Backend *, Operation *, Modifications *,
55 Modifications **, const char **, char *, size_t );
56 int slap_mods2entry_syncrepl( Modifications *, Entry **, int, const char **,
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;
155 struct berval base_bv = { 0, NULL };
156 struct berval pbase = { 0, NULL };
157 struct berval nbase = { 0, NULL };
158 struct berval sub_bv = { 0, NULL };
159 struct berval psubrdn = { 0, NULL };
160 struct berval nsubrdn = { 0, NULL };
161 struct berval psub = { 0, NULL };
162 struct berval nsub = { 0, NULL };
164 Modifications *modlist;
166 char *def_filter_str;
167 struct berval def_filter_bv = { 0, NULL };
170 LDAP_LOG ( OPERATION, DETAIL1, "do_syncrepl\n", 0, 0, 0 );
172 Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl\n", 0, 0, 0 );
178 if ( abs(si->type) != LDAP_SYNC_REFRESH_ONLY &&
179 abs(si->type) != LDAP_SYNC_REFRESH_AND_PERSIST ) {
183 /* Init connection to master */
185 if ( ldap_is_ldap_url( si->masteruri )) {
186 rc = ldap_initialize( &ld, si->masteruri );
187 if ( rc != LDAP_SUCCESS ) {
189 LDAP_LOG( OPERATION, ERR, "do_syncrepl: "
190 "ldap_initialize failed (%s)\n",
191 si->masteruri, 0, 0 );
193 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
194 "ldap_initialize failed (%s)\n",
195 si->masteruri, 0, 0 );
199 ld = ldap_init( si->mastername, si->masterport );
202 LDAP_LOG( OPERATION, ERR, "do_syncrepl: "
203 "ldap_init failed (%s:%s)\n",
204 si->mastername, si->masterport, 0 );
206 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
207 "ldap_init failed (%s:%s)\n",
208 si->mastername, si->masterport, 0 );
213 protocol = LDAP_VERSION3;
214 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol );
219 rc = ldap_start_tls_s( ld, NULL, NULL );
220 if( rc != LDAP_SUCCESS ) {
222 LDAP_LOG ( OPERATION, ERR, "do_syncrepl: "
223 "%s: ldap_start_tls failed (%d)\n",
224 si->tls == TLS_CRITICAL ? "Error" : "Warning",
227 Debug( LDAP_DEBUG_ANY,
228 "%s: ldap_start_tls failed (%d)\n",
229 si->tls == TLS_CRITICAL ? "Error" : "Warning",
232 if( si->tls == TLS_CRITICAL )
237 if ( si->bindmethod == LDAP_AUTH_SASL ) {
238 #ifdef HAVE_CYRUS_SASL
241 if ( si->secprops != NULL ) {
242 int err = ldap_set_option( ld,
243 LDAP_OPT_X_SASL_SECPROPS, si->secprops);
245 if( err != LDAP_OPT_SUCCESS ) {
247 LDAP_LOG ( OPERATION, ERR, "do_bind: Error: "
248 "ldap_set_option(%s,SECPROPS,\"%s\") failed!\n",
249 si->mastername, si->secprops, 0 );
251 Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
252 "(%s,SECPROPS,\"%s\") failed!\n",
253 si->mastername, si->secprops, NULL );
259 defaults = lutil_sasl_defaults( ld,
266 rc = ldap_sasl_interactive_bind_s( ld,
274 if ( rc != LDAP_SUCCESS ) {
276 LDAP_LOG ( OPERATION, ERR, "do_syncrepl: "
277 "ldap_sasl_interactive_bind_s failed (%d)\n",
280 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
281 "ldap_sasl_interactive_bind_s failed (%d)\n",
286 #else /* HAVE_CYRUS_SASL */
287 fprintf( stderr, "not compiled with SASL support\n" );
291 rc = ldap_bind_s( ld, si->binddn, si->passwd, si->bindmethod );
292 if ( rc != LDAP_SUCCESS ) {
294 LDAP_LOG ( OPERATION, ERR, "do_syncrepl: "
295 "ldap_bind_s failed (%d)\n", rc, 0, 0 );
297 Debug( LDAP_DEBUG_ANY, "do_syncrepl: "
298 "ldap_bind_s failed (%d)\n", rc, 0, 0 );
305 conn.c_send_ldap_result = slap_send_ldap_result;
306 conn.c_send_search_entry = slap_send_search_entry;
307 conn.c_send_search_result = slap_send_search_result;
308 conn.c_send_search_reference = slap_send_search_reference;
312 /* get syncrepl cookie of shadow replica from subentry */
313 ber_str2bv( si->base, strlen(si->base), 1, &base_bv );
314 dnPrettyNormal(0, &base_bv, &pbase, &nbase);
316 sprintf( substr, "cn=syncrepl%d", si->id );
317 ber_str2bv( substr, strlen(substr), 1, &sub_bv );
318 dnPrettyNormal( 0, &sub_bv, &psubrdn, &nsubrdn );
320 build_new_dn( &op.o_req_dn, &pbase, &psubrdn );
321 build_new_dn( &op.o_req_ndn, &nbase, &nsubrdn );
323 op.o_tag = LDAP_REQ_SEARCH;
324 op.o_protocol = LDAP_VERSION3;
325 ber_dupbv( &op.o_ndn, &be->be_rootndn );
327 op.o_time = slap_get_time();
328 op.o_managedsait = 1;
329 op.o_threadctx = si->ctx;
331 /* set callback function */
332 cb.sc_response = cookie_callback;
335 /* search subentry to retrieve cookie */
336 si->syncCookie = NULL;
338 op.ors_scope = LDAP_SCOPE_BASE;
339 op.ors_deref = LDAP_DEREF_NEVER;
342 op.ors_attrsonly = 0;
344 op.ors_filter = str2filter( def_filter_str = "(objectClass=*)" );
345 ber_str2bv( def_filter_str, strlen( def_filter_str ), 1,
348 be->be_search( &op, &rs );
350 /* setup LDAP SYNC control */
351 sync_ber = ber_alloc_t( LBER_USE_DER );
353 if ( si->syncCookie ) {
354 ber_printf( sync_ber, "{eO}", abs(si->type), si->syncCookie );
356 ber_printf( sync_ber, "{e}", abs(si->type) );
359 if ( ber_flatten( sync_ber, &sync_bvalp ) == LBER_ERROR ) {
360 ber_free( sync_ber, 1 );
363 ber_free( sync_ber, 1 );
365 sctrls = (LDAPControl**) ch_calloc( 3, sizeof(LDAPControl*) );
367 c[0].ldctl_oid = LDAP_CONTROL_SYNC;
368 c[0].ldctl_value = (*sync_bvalp);
369 c[0].ldctl_iscritical = si->type < 0;
373 c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
374 c[1].ldctl_value.bv_val = si->authzId;
375 c[1].ldctl_value.bv_len = strlen( si->authzId );
376 c[1].ldctl_iscritical = 1;
384 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, sctrls );
386 ber_bvfree( sync_bvalp );
389 if ( err != LDAP_OPT_SUCCESS )
390 fprintf( stderr, "Could not set controls : %d\n", err );
392 /* Delete Attributes */
393 if ( si->lastmod == LASTMOD_REQ ) {
394 descs = del_descs_lastmod;
399 for ( i = 0; descs[i] != NULL; i++ ) {
400 for ( j = 0; si->attrs[j] != NULL; j++ ) {
401 if ( !strcmp( si->attrs[j], descs[i]->ad_cname.bv_val )) {
402 ch_free( si->attrs[j] );
403 for ( k = j; si->attrs[k] != NULL; k++ ) {
404 si->attrs[k] = si->attrs[k+1];
412 for ( n = 0; si->attrs[ n ] != NULL; n++ )
415 if ( si->lastmod == LASTMOD_REQ ) {
416 descs = add_descs_lastmod;
421 for ( i = 0; descs[i] != NULL; i++ ) {
422 tmp = ( char ** ) ch_realloc( si->attrs,
423 ( n + 2 ) * sizeof( char * ));
426 LDAP_LOG( OPERATION, ERR, "out of memory\n", 0,0,0 );
428 Debug( LDAP_DEBUG_ANY, "out of memory\n", 0,0,0 );
432 si->attrs[ n++ ] = strndup( descs[i]->ad_cname.bv_val,
433 descs[i]->ad_cname.bv_len );
434 si->attrs[ n ] = NULL;
437 /* Send LDAP SYNC search */
439 rc = ldap_search_ext( ld, si->base, si->scope, si->filterstr,
440 si->attrs, si->attrsonly, NULL, NULL,
443 if( rc != LDAP_SUCCESS ) {
444 fprintf( stderr, "syncrepl: ldap_search_ext (%d)\n",
445 ldap_err2string( rc ), rc );
449 while (( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) > 0 ) {
451 for ( msg = ldap_first_message( ld, res );
453 msg = ldap_next_message( ld, msg ) )
455 switch( ldap_msgtype( msg ) ) {
456 case LDAP_RES_SEARCH_ENTRY:
457 entry = syncrepl_message_to_entry( ld, be, msg, modlist, &syncstate, &syncUUID, &syncCookie );
461 ctrl_ber = ber_init( &rctrlp->ldctl_value );
462 ber_scanf( ctrl_ber, "{em",
465 if ( ber_peek_tag( ctrl_ber, &len )
466 == LDAP_SYNC_TAG_COOKIE ) {
467 ber_scanf( ctrl_ber, "m}", &syncCookie );
471 LDAP_LOG( OPERATION, ERR,"do_syncrepl: "
475 Debug( LDAP_DEBUG_ANY, "do_syncrepl :"
482 syncrepl_entry( ld, be, entry, modlist,
483 syncstate, &syncUUID,
486 if ( syncCookie.bv_len ) {
487 syncrepl_updateCookie( ld, be, &psub,
490 ber_free( ctrl_ber, 1 );
493 case LDAP_RES_SEARCH_REFERENCE:
495 LDAP_LOG( OPERATION, ERR,
496 "do_syncrepl : reference received\n", 0, 0, 0 );
498 Debug( LDAP_DEBUG_ANY,
499 "do_syncrepl : reference received\n", 0, 0, 0 );
503 case LDAP_RES_SEARCH_RESULT:
504 ldap_parse_result( ld, msg, &err, NULL, NULL, NULL, &rctrls, 0 );
507 ctrl_ber = ber_init( &rctrlp->ldctl_value );
508 ber_scanf( ctrl_ber, "{" );
509 if ( ber_peek_tag( ctrl_ber, &len )
510 == LDAP_SYNC_TAG_COOKIE ) {
511 ber_scanf( ctrl_ber, "m", &syncCookie );
514 if (si->type == LDAP_SYNC_REFRESH_AND_PERSIST) {
515 if ( cancel_response ) {
516 if ( syncCookie.bv_len ) {
517 ber_bvfree( si->syncCookie );
518 si->syncCookie = ber_dupbv( NULL, &syncCookie );
525 if ( syncCookie.bv_len ) {
526 syncrepl_updateCookie( ld,
535 case LDAP_RES_INTERMEDIATE_RESP:
536 ldap_parse_intermediate_resp_result( ld, msg,
537 &retoid, &retdata, 0 );
538 if ( !strcmp( retoid, LDAP_SYNC_INFO ) ) {
539 sync_info_arrived = 1;
540 res_ber = ber_init( retdata );
541 ber_scanf( res_ber, "{e", &syncstate );
543 if ( syncstate == LDAP_SYNC_REFRESH_DONE ) {
544 syncrepl_del_nonpresent( ld, be );
545 } else if ( syncstate != LDAP_SYNC_NEW_COOKIE ) {
547 LDAP_LOG( OPERATION, ERR,
548 "do_syncrepl : unknown sync info\n", 0, 0, 0 );
550 Debug( LDAP_DEBUG_ANY,
551 "do_syncrepl : unknown sync info\n", 0, 0, 0 );
555 if ( ber_peek_tag( res_ber, &len )
556 == LDAP_SYNC_TAG_COOKIE ) {
557 ber_scanf( res_ber, "m}", &syncCookie );
558 if ( syncCookie.bv_len ) {
559 ber_bvfree( si->syncCookie );
560 si->syncCookie = ber_dupbv( NULL, &syncCookie );
563 if ( syncstate == LDAP_SYNC_NEW_COOKIE ) {
565 LDAP_LOG( OPERATION, ERR,
566 "do_syncrepl : cookie required\n", 0, 0, 0 );
568 Debug( LDAP_DEBUG_ANY,
569 "do_syncrepl : cookie required\n", 0, 0, 0 );
574 ldap_memfree( retoid );
575 ber_bvfree( retdata );
576 ber_free( res_ber, 1 );
580 LDAP_LOG( OPERATION, ERR,"do_syncrepl :"
581 " unknown intermediate "
582 "response\n", 0, 0, 0 );
584 Debug( LDAP_DEBUG_ANY, "do_syncrepl : "
585 "unknown intermediate "
586 "response\n", 0, 0, 0 );
588 ldap_memfree( retoid );
589 ber_bvfree( retdata );
595 LDAP_LOG( OPERATION, ERR, "do_syncrepl : "
596 "unknown message\n", 0, 0, 0 );
598 Debug( LDAP_DEBUG_ANY, "do_syncrepl : "
599 "unknown message\n", 0, 0, 0 );
610 LDAP_LOG( OPERATION, ERR,
611 "do_syncrepl : unknown result\n", 0, 0, 0 );
613 Debug( LDAP_DEBUG_ANY,
614 "do_syncrepl : unknown result\n", 0, 0, 0 );
620 sleep(si->interval * 60);
622 // set alarm clock to send signal to slapd
623 // should set the signal handler beforehand
624 // the signal handler re execute do_syncrepl()
634 syncrepl_message_to_entry(
638 Modifications *modlist,
640 struct berval *syncUUID,
641 struct berval *syncCookie
645 BerElement *ber = NULL;
649 Modifications **modtail = &modlist;
652 char txtbuf[SLAP_TEXT_BUFLEN];
653 size_t textlen = sizeof txtbuf;
655 struct berval **bvals;
659 struct berval empty_bv = { 0, NULL };
664 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
668 LDAPControl** rctrls = NULL;
669 BerElement* ctrl_ber;
673 if ( msg->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) {
675 LDAP_LOG( OPERATION, ERR,
676 "Message type should be entry (%d)", msg->lm_msgtype, 0, 0 );
678 Debug( LDAP_DEBUG_ANY,
679 "Message type should be entry (%d)", msg->lm_msgtype, 0, 0 );
684 op.o_tag = LDAP_REQ_ADD;
685 ber_dupbv( &op.o_ndn, &be->be_rootndn );
687 rc = ldap_get_dn_ber( ld, msg, &ber, &bdn );
689 if ( rc != LDAP_SUCCESS ) {
691 LDAP_LOG( OPERATION, ERR,
692 "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
694 Debug( LDAP_DEBUG_ANY,
695 "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
700 e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
701 dnPrettyNormal( NULL, &bdn, &e->e_name, &e->e_nname );
705 for ( rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues);
707 rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues))
709 if ( tmp.sml_type.bv_val == NULL ) break;
711 mod = (Modifications *) ch_malloc( sizeof(Modifications) );
713 mod->sml_op = LDAP_MOD_ADD;
714 mod->sml_next = NULL;
715 mod->sml_desc = NULL;
716 mod->sml_type = tmp.sml_type;
717 mod->sml_bvalues = tmp.sml_bvalues;
720 modtail = &mod->sml_next;
723 if ( ber_scanf( ber, "}") == LBER_ERROR ) {
725 LDAP_LOG( OPERATION, ERR,
726 "syncrepl_message_to_entry: ber_scanf failed\n", 0, 0, 0 );
728 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: ber_scanf failed\n",
735 ber_scanf( ber, "{xx" );
737 rc = ldap_int_get_controls( ber, &rctrls );
739 if ( rc != LDAP_SUCCESS ) {
741 LDAP_LOG( OPERATION, ERR,
742 "syncrepl_message_to_entry : control get failed (%d)", rc, 0, 0 );
744 Debug( LDAP_DEBUG_ANY,
745 "syncrepl_message_to_entry : control get failed (%d)", rc, 0, 0 );
752 ctrl_ber = ber_init( &rctrlp->ldctl_value );
753 ber_scanf( ctrl_ber, "{em", syncstate, syncUUID );
754 if ( ber_peek_tag( ctrl_ber, &len ) == LDAP_SYNC_TAG_COOKIE ) {
755 ber_scanf( ctrl_ber, "m}", syncCookie );
759 LDAP_LOG( OPERATION, ERR,"syncrepl_message_to_entry : "
760 " rctrls absent\n", 0, 0, 0 );
762 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry :"
763 " rctrls absent\n", 0, 0, 0 );
767 if ( *syncstate == LDAP_SYNC_PRESENT ) {
772 if ( modlist == NULL ) {
774 LDAP_LOG( OPERATION, ERR,
775 "syncrepl_message_to_entry: no attributes\n", 0, 0, 0 );
777 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: no attributes\n",
782 rc = slap_mods_check_syncrepl( be, &modlist, &text, txtbuf, textlen );
784 if ( rc != LDAP_SUCCESS ) {
786 LDAP_LOG( OPERATION, ERR,
787 "syncrepl_message_to_entry: mods check (%s)\n", text, 0, 0 );
789 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods check (%s)\n",
795 rc = slap_mods_opattrs_syncrepl( be, &op, modlist, modtail,
796 &text,txtbuf, textlen );
798 if( rc != LDAP_SUCCESS ) {
800 LDAP_LOG( OPERATION, ERR,
801 "syncrepl_message_to_entry: mods opattrs (%s)\n", text, 0, 0 );
803 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods opattrs (%s)\n",
809 rc = slap_mods2entry_syncrepl( modlist, &e, 1, &text, txtbuf, textlen );
810 if( rc != LDAP_SUCCESS ) {
812 LDAP_LOG( OPERATION, ERR,
813 "syncrepl_message_to_entry: mods2entry (%s)\n", text, 0, 0 );
815 Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods2entry (%s)\n",
828 syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 )
830 const struct berval *uuid1 = v_uuid1;
831 const struct berval *uuid2 = v_uuid2;
832 int rc = uuid1->bv_len - uuid2->bv_len;
834 return ( strcmp( uuid1->bv_val, uuid2->bv_val ) );
842 Modifications* modlist,
844 struct berval* syncUUID,
845 struct berval* syncCookie,
849 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
851 struct berval normdn = {0, NULL};
852 struct berval prettydn = {0, NULL};
853 struct berval pbase = {0, NULL};
854 struct berval nbase = {0, NULL};
855 struct berval base_bv = {0, NULL};
856 struct berval csn_bv = {0, NULL};
857 struct berval *syncuuid_bv = NULL;
858 char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
861 SlapReply rs = {REP_RESULT};
865 struct berval filterstr_bv;
870 if ( syncstate == LDAP_SYNC_PRESENT ) {
871 syncuuid_bv = ber_dupbv( NULL, syncUUID );
872 avl_insert( &si->presentlist, (caddr_t) syncuuid_bv,
873 syncuuid_cmp, avl_dup_error );
877 if ( !attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )) {
878 attr_merge_one( e, slap_schema.si_ad_entryUUID, syncUUID );
881 filterstr = (char *) ch_malloc( strlen("entryUUID=") + syncUUID->bv_len + 1 );
882 strcpy( filterstr, "entryUUID=" );
883 strcat( filterstr, syncUUID->bv_val );
886 si->syncUUID = syncUUID;
888 filter = str2filter( filterstr );
889 ber_str2bv( filterstr, strlen(filterstr), 1, &filterstr_bv );
890 ch_free( filterstr );
892 dnPrettyNormal(0, &(e->e_name), &prettydn, &normdn);
894 free(e->e_name.bv_val);
895 free(e->e_nname.bv_val);
896 e->e_name = prettydn;
898 op.o_req_dn = e->e_name;
899 op.o_req_ndn = e->e_nname;
901 ber_str2bv( si->base, strlen(si->base), 1, &base_bv );
902 dnPrettyNormal(0, &base_bv, &pbase, &nbase);
904 op.o_protocol = LDAP_VERSION3;
905 ber_dupbv( &op.o_ndn, &be->be_rootndn );
907 op.o_time = slap_get_time();
908 op.o_managedsait = 1;
909 op.o_threadctx = si->ctx;
911 cb.sc_response = null_callback;
914 switch ( syncstate ) {
916 case LDAP_SYNC_MODIFY :
918 op.o_tag = LDAP_REQ_MODIFY;
919 op.orm_modlist = modlist;
920 rc = be->be_modify( op, rs );
921 if ( rc != LDAP_SUCCESS ) {
922 if ( rc == LDAP_REFERRAL || rc == LDAP_NO_SUCH_OBJECT || rc == DB_NOTFOUND ) {
923 op.o_tag = LDAP_REQ_ADD;
925 rc = be->be_add( &op, rs );
926 if ( rc != LDAP_SUCCESS ) {
927 if ( rc == LDAP_ALREADY_EXISTS ) {
929 } else if ( rc == LDAP_REFERRAL || rc == LDAP_NO_SUCH_OBJECT || rc == DB_NOTFOUND ) {
930 syncrepl_add_glue(ld, si->conn,
933 syncUUID, syncCookie);
936 LDAP_LOG( OPERATION, ERR,
937 "be_add failed (%d)\n",
940 Debug( LDAP_DEBUG_ANY,
941 "be_add failed (%d)\n",
948 LDAP_LOG( OPERATION, ERR,
949 "be_modify failed (%d)\n", rc, 0, 0 );
951 Debug( LDAP_DEBUG_ANY,
952 "be_modify failed (%d)\n", rc, 0, 0 );
959 case LDAP_SYNC_DELETE :
960 be->be_delete( &op, &rs );
966 LDAP_LOG( OPERATION, ERR,
967 "unknown syncstate\n", 0, 0, 0 );
969 Debug( LDAP_DEBUG_ANY,
970 "unknown syncstate\n", 0, 0, 0 );
977 syncrepl_del_nonpresent(
982 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
984 struct berval base_bv = {0, NULL};
987 SlapReply rs = {REP_RESULT};
988 struct berval filterstr_bv;
990 ber_str2bv( si->base, strlen(si->base), 1, &base_bv );
991 dnPrettyNormal(0, &base_bv, &op.o_req_dn, &op.o_req_ndn );
993 filter = str2filter( si->filterstr );
995 op.o_tag = LDAP_REQ_SEARCH;
996 op.o_protocol = LDAP_VERSION3;
997 ber_dupbv( &op.o_ndn, &be->be_rootndn );
999 op.o_time = slap_get_time();
1000 op.o_managedsait = 1;
1001 op.o_threadctx = si->ctx;
1003 cb.sc_response = nonpresent_callback;
1006 op.ors_scope = LDAP_SCOPE_BASE;
1007 op.ors_deref = LDAP_DEREF_NEVER;
1010 op.ors_attrsonly = 0;
1011 op.ors_attrs = NULL;
1012 op.ors_filter = str2filter( si->filterstr );
1013 ber_str2bv( si->filterstr, strlen( si->filterstr ),
1014 1, &op.ors_filterstr );
1016 be->be_search( &op, &rs );
1027 Modifications* modlist,
1029 struct berval* syncUUID,
1030 struct berval* syncCookie
1033 syncinfo_t *si = op->o_callback->sc_private;
1034 struct berval uuid_bv = {0, NULL};
1038 char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
1041 struct berval dn = {0, NULL};
1042 struct berval pdn = {0, NULL};
1043 struct berval ndn = {0, NULL};
1044 struct berval rdn = {0, NULL};
1046 SlapReply rs = {REP_RESULT};
1048 op->o_tag = LDAP_REQ_ADD;
1049 op->o_callback = &cb;
1050 cb.sc_response = null_callback;
1053 ber_dupbv( &dn, &e->e_nname );
1054 ber_dupbv( &pdn, &e->e_nname );
1055 while ( !be_issuffix ( be, &pdn )) {
1056 dnParent( &dn, &pdn );
1057 ber_dupbv( &dn, &pdn );
1061 for ( i = 0; i <= levels; i++ ) {
1062 glue = (Entry*) ch_calloc( 1, sizeof(Entry) );
1063 ber_dupbv( &dn, &e->e_nname );
1064 ber_dupbv( &pdn, &e->e_nname );
1066 for ( k = 0; k < j; k++ ) {
1067 dnParent( &dn, &pdn );
1068 ber_dupbv( &dn, &pdn );
1071 dnPrettyNormal(0, &dn, &pdn, &ndn);
1072 ber_dupbv( &glue->e_name, &pdn);
1073 ber_dupbv( &glue->e_nname, &ndn);
1075 a = ch_calloc( 1, sizeof( Attribute ));
1076 a->a_desc = slap_schema.si_ad_objectClass;
1077 a->a_vals = ch_calloc( 3, sizeof( struct berval ));
1078 ber_str2bv( "top", strlen("top"), 1, &a->a_vals[0] );
1079 ber_str2bv( "glue", strlen("glue"), 1, &a->a_vals[1] );
1080 a->a_vals[2].bv_len = 0;
1081 a->a_vals[2].bv_val = NULL;
1082 a->a_next = glue->e_attrs;
1085 a = ch_calloc( 1, sizeof( Attribute ));
1086 a->a_desc = slap_schema.si_ad_structuralObjectClass;
1087 a->a_vals = ch_calloc( 2, sizeof( struct berval ));
1088 ber_str2bv( "glue", strlen("glue"), 1, &a->a_vals[0] );
1089 a->a_vals[1].bv_len = 0;
1090 a->a_vals[1].bv_val = NULL;
1091 a->a_next = glue->e_attrs;
1094 if ( !strcmp( e->e_nname.bv_val, glue->e_nname.bv_val )) {
1095 op.o_req_dn = e->e_name;
1096 op.o_req_ndn = e->e_nname;
1098 rc = be->be_add ( op, &rs );
1099 if ( rc == LDAP_SUCCESS )
1100 be_entry_release_w( be, conn, op, e );
1105 op.o_req_dn = glue->e_name;
1106 op.o_req_ndn = glue->e_nname;
1108 rc = be->be_add ( op, &rs );
1109 if ( rc == LDAP_SUCCESS )
1110 be_entry_release_w( be, conn, op, glue );
1120 syncrepl_updateCookie(
1124 struct berval *syncCookie
1127 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
1129 Modifications *modlist;
1130 Modifications **modtail = &modlist;
1132 struct berval* ocbva;
1133 struct berval* cnbva;
1134 struct berval* ssbva;
1135 struct berval* scbva;
1139 char txtbuf[SLAP_TEXT_BUFLEN];
1140 size_t textlen = sizeof txtbuf;
1147 SlapReply rs = {REP_RESULT};
1149 ocbva = ( struct berval * ) ch_calloc( 4, sizeof( struct berval ));
1150 cnbva = ( struct berval * ) ch_calloc( 2, sizeof( struct berval ));
1151 ssbva = ( struct berval * ) ch_calloc( 2, sizeof( struct berval ));
1152 scbva = ( struct berval * ) ch_calloc( 2, sizeof( struct berval ));
1153 substr = ( char * ) ch_calloc( 64, sizeof( char ));
1155 /* update in memory cookie */
1156 if ( si->syncCookie != NULL ) {
1157 ber_bvfree( si->syncCookie );
1159 si->syncCookie = ber_dupbv( NULL, syncCookie );
1160 ber_str2bv( "top", strlen("top"), 0, &ocbva[0] );
1161 ber_str2bv( "subentry", strlen("subentry"), 0, &ocbva[1] );
1162 ber_str2bv( "syncConsumerSubentry",
1163 strlen("syncConsumerSubentry"), 0, &ocbva[2] );
1164 ocbva[3].bv_len = 0;
1165 ocbva[3].bv_val = NULL;
1167 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1168 mod->sml_op = LDAP_MOD_REPLACE;
1169 mod->sml_next = NULL;
1170 mod->sml_desc = NULL;
1171 ber_str2bv( "objectClass", strlen("objectClass"), 0, &mod->sml_type );
1172 mod->sml_bvalues = ocbva;
1174 modtail = &mod->sml_next;
1176 sprintf( substr, "syncrepl%d", si->id );
1177 ber_str2bv( substr, strlen( substr ), 1, &cnbva[0] );
1179 cnbva[1].bv_len = 0;
1180 cnbva[1].bv_val = NULL;
1181 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1182 mod->sml_op = LDAP_MOD_REPLACE;
1183 mod->sml_next = NULL;
1184 mod->sml_desc = NULL;
1185 ber_str2bv( "cn", strlen("cn"), 0, &mod->sml_type );
1186 mod->sml_bvalues = cnbva;
1188 modtail = &mod->sml_next;
1190 ber_dupbv( &scbva[0], si->syncCookie );
1191 scbva[1].bv_len = 0;
1192 scbva[1].bv_val = NULL;
1193 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1194 mod->sml_op = LDAP_MOD_REPLACE;
1195 mod->sml_next = NULL;
1196 mod->sml_desc = NULL;
1197 ber_str2bv( "syncreplCookie", strlen("syncreplCookie"),
1198 0, &mod->sml_type );
1199 mod->sml_bvalues = scbva;
1201 modtail = &mod->sml_next;
1203 ber_str2bv( " ", 1, 1, &ssbva[0] );
1204 ssbva[1].bv_len = 0;
1205 ssbva[1].bv_val = NULL;
1206 mod = (Modifications *) ch_malloc( sizeof( Modifications ));
1207 mod->sml_op = LDAP_MOD_REPLACE;
1208 mod->sml_next = NULL;
1209 mod->sml_desc = NULL;
1210 ber_str2bv( "subtreeSpecification",
1211 strlen("subtreeSpecification"), 0, &mod->sml_type );
1212 mod->sml_bvalues = ssbva;
1214 modtail = &mod->sml_next;
1216 rc = slap_mods_check_syncrepl( be, &modlist, &text, txtbuf, textlen );
1218 if ( rc != LDAP_SUCCESS ) {
1220 LDAP_LOG( OPERATION, ERR,
1221 "syncrepl_updateCookie: mods check (%s)\n", text, 0, 0 );
1223 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods check (%s)\n",
1228 op.o_tag = LDAP_REQ_ADD;
1229 rc = slap_mods_opattrs_syncrepl( be, &op, modlist, modtail,
1230 &text,txtbuf, textlen );
1232 if( rc != LDAP_SUCCESS ) {
1234 LDAP_LOG( OPERATION, ERR,
1235 "syncrepl_updateCookie: mods opattrs (%s)\n", text, 0, 0 );
1237 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods opattrs (%s)\n",
1242 e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
1243 dnPrettyNormal( NULL, pdn, &e->e_name, &e->e_nname );
1247 rc = slap_mods2entry_syncrepl( modlist, &e, 1, &text, txtbuf, textlen );
1249 if( rc != LDAP_SUCCESS ) {
1251 LDAP_LOG( OPERATION, ERR,
1252 "syncrepl_updateCookie: mods2entry (%s)\n", text, 0, 0 );
1254 Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods2entry (%s)\n",
1259 op.o_protocol = LDAP_VERSION3;
1260 ber_dupbv( &op.o_ndn, &be->be_rootndn );
1261 op.o_callback = &cb;
1262 op.o_time = slap_get_time();
1263 op.o_managedsait = 1;
1264 op.o_threadctx = si->ctx;
1266 cb.sc_response = null_callback;
1269 op.o_req_dn = e->e_name;
1270 op.o_req_ndn = e->e_nname;
1273 for( mod = modlist; mod != NULL; mod = mod->sml_next ) {
1274 mod->sml_op = LDAP_MOD_REPLACE;
1278 /* update persistent cookie */
1279 update_cookie_retry:
1280 op.o_tag = LDAP_REQ_MODIFY;
1281 op.orm_modlist = modlist;
1282 rc = be->be_modify( &op, &rs );
1283 if ( rc != LDAP_SUCCESS ) {
1284 if ( rc == LDAP_REFERRAL ||
1285 rc == LDAP_NO_SUCH_OBJECT ||
1286 rc == DB_NOTFOUND ) {
1287 op.o_tag = LDAP_REQ_ADD;
1289 rc = be->be_add( &op, &rs );
1290 if ( rc != LDAP_SUCCESS ) {
1291 if ( rc == LDAP_ALREADY_EXISTS ) {
1292 goto update_cookie_retry;
1293 } else if ( rc == LDAP_REFERRAL ||
1294 rc == LDAP_NO_SUCH_OBJECT ||
1295 rc == DB_NOTFOUND ) {
1297 LDAP_LOG( OPERATION, ERR,
1298 "cookie will be non-persistent\n",
1301 Debug( LDAP_DEBUG_ANY,
1302 "cookie will be non-persistent\n",
1307 LDAP_LOG( OPERATION, ERR,
1308 "be_add failed (%d)\n",
1311 Debug( LDAP_DEBUG_ANY,
1312 "be_add failed (%d)\n",
1319 LDAP_LOG( OPERATION, ERR,
1320 "be_modify failed (%d)\n", rc, 0, 0 );
1322 Debug( LDAP_DEBUG_ANY,
1323 "be_modify failed (%d)\n", rc, 0, 0 );
1330 int slap_mods_check_syncrepl(
1332 Modifications **mlp,
1338 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
1339 AttributeDescription** descs;
1341 Modifications *prevml = NULL;
1342 Modifications *nextml = NULL;
1343 Modifications *ml = *mlp;
1345 while ( ml != NULL ) {
1346 AttributeDescription *ad = NULL;
1348 /* convert to attribute description */
1349 rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text );
1351 if( rc != LDAP_SUCCESS ) {
1352 snprintf( textbuf, textlen, "%s: %s",
1353 ml->sml_type.bv_val, *text );
1360 if ( si->lastmod == LASTMOD_REQ ) {
1361 descs = del_descs_lastmod;
1366 for ( i = 0; descs[i] != NULL; i++ ) {
1367 if ( ad == descs[i] ) {
1368 if ( prevml == NULL ) {
1369 mlp = &ml->sml_next;
1372 prevml->sml_next = ml->sml_next;
1374 slap_mod_free( &ml->sml_mod, 0 );
1375 nextml = ml->sml_next;
1382 if( slap_syntax_is_binary( ad->ad_type->sat_syntax )
1383 && !slap_ad_is_binary( ad ))
1385 /* attribute requires binary transfer */
1386 snprintf( textbuf, textlen,
1387 "%s: requires ;binary transfer",
1388 ml->sml_type.bv_val );
1390 return LDAP_UNDEFINED_TYPE;
1393 if( !slap_syntax_is_binary( ad->ad_type->sat_syntax )
1394 && slap_ad_is_binary( ad ))
1396 /* attribute requires binary transfer */
1397 snprintf( textbuf, textlen,
1398 "%s: disallows ;binary transfer",
1399 ml->sml_type.bv_val );
1401 return LDAP_UNDEFINED_TYPE;
1404 if( slap_ad_is_tag_range( ad )) {
1405 /* attribute requires binary transfer */
1406 snprintf( textbuf, textlen,
1407 "%s: inappropriate use of tag range option",
1408 ml->sml_type.bv_val );
1410 return LDAP_UNDEFINED_TYPE;
1413 if ( is_at_obsolete( ad->ad_type ) &&
1414 ( ml->sml_op == LDAP_MOD_ADD || ml->sml_values != NULL ) )
1417 * attribute is obsolete,
1418 * only allow replace/delete with no values
1420 snprintf( textbuf, textlen,
1421 "%s: attribute is obsolete",
1422 ml->sml_type.bv_val );
1424 return LDAP_CONSTRAINT_VIOLATION;
1430 if( ml->sml_values != NULL ) {
1432 slap_syntax_validate_func *validate =
1433 ad->ad_type->sat_syntax->ssyn_validate;
1434 slap_syntax_transform_func *pretty =
1435 ad->ad_type->sat_syntax->ssyn_pretty;
1437 if( !pretty && !validate ) {
1438 *text = "no validator for syntax";
1439 snprintf( textbuf, textlen,
1440 "%s: no validator for syntax %s",
1441 ml->sml_type.bv_val,
1442 ad->ad_type->sat_syntax->ssyn_oid );
1444 return LDAP_INVALID_SYNTAX;
1448 * check that each value is valid per syntax
1449 * and pretty if appropriate
1451 for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {
1454 rc = pretty( ad->ad_type->sat_syntax,
1455 &ml->sml_values[nvals], &pval );
1457 rc = validate( ad->ad_type->sat_syntax,
1458 &ml->sml_values[nvals] );
1462 snprintf( textbuf, textlen,
1463 "%s: value #%ld invalid per syntax",
1464 ml->sml_type.bv_val, (long) nvals );
1466 return LDAP_INVALID_SYNTAX;
1470 ber_memfree( ml->sml_values[nvals].bv_val );
1471 ml->sml_values[nvals] = pval;
1476 * a rough single value check... an additional check is needed
1477 * to catch add of single value to existing single valued attribute
1479 if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE)
1480 && nvals > 1 && is_at_single_value( ad->ad_type ))
1482 snprintf( textbuf, textlen,
1483 "%s: multiple values provided",
1484 ml->sml_type.bv_val );
1486 return LDAP_CONSTRAINT_VIOLATION;
1489 if( nvals && ad->ad_type->sat_equality &&
1490 ad->ad_type->sat_equality->smr_normalize )
1492 ml->sml_nvalues = ch_malloc( (nvals+1)*sizeof(struct berval) );
1493 for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {
1494 rc = ad->ad_type->sat_equality->smr_normalize(
1496 ad->ad_type->sat_syntax,
1497 ad->ad_type->sat_equality,
1498 &ml->sml_values[nvals], &ml->sml_nvalues[nvals] );
1501 LDAP_LOG( OPERATION, DETAIL1,
1502 "str2entry: NULL (ssyn_normalize %d)\n",
1505 Debug( LDAP_DEBUG_ANY,
1506 "<= str2entry NULL (ssyn_normalize %d)\n",
1509 snprintf( textbuf, textlen,
1510 "%s: value #%ld normalization failed",
1511 ml->sml_type.bv_val, (long) nvals );
1516 ml->sml_nvalues[nvals].bv_val = NULL;
1517 ml->sml_nvalues[nvals].bv_len = 0;
1524 return LDAP_SUCCESS;
1527 int slap_mods_opattrs_syncrepl(
1530 Modifications *mods,
1531 Modifications **modtail,
1533 char *textbuf, size_t textlen )
1535 struct berval name, timestamp, csn;
1536 struct berval nname;
1537 char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
1538 char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
1540 syncinfo_t *si = ( syncinfo_t * ) be->syncinfo;
1542 int mop = op->o_tag == LDAP_REQ_ADD
1543 ? LDAP_MOD_ADD : LDAP_MOD_REPLACE;
1545 assert( modtail != NULL );
1546 assert( *modtail == NULL );
1548 if( si->lastmod == LASTMOD_GEN ) {
1550 time_t now = slap_get_time();
1552 ldap_pvt_thread_mutex_lock( &gmtime_mutex );
1553 ltm = gmtime( &now );
1554 lutil_gentime( timebuf, sizeof(timebuf), ltm );
1556 csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), 0, 0 );
1557 ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
1558 csn.bv_val = csnbuf;
1560 timestamp.bv_val = timebuf;
1561 timestamp.bv_len = strlen(timebuf);
1563 if( op->o_dn.bv_len == 0 ) {
1564 name.bv_val = SLAPD_ANONYMOUS;
1565 name.bv_len = sizeof(SLAPD_ANONYMOUS)-1;
1573 if( op->o_tag == LDAP_REQ_ADD ) {
1574 struct berval tmpval;
1576 if( global_schemacheck ) {
1577 int rc = mods_structural_class( mods, &tmpval,
1578 text, textbuf, textlen );
1579 if( rc != LDAP_SUCCESS ) {
1583 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1585 mod->sml_type.bv_val = NULL;
1586 mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
1588 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1589 ber_dupbv( &mod->sml_values[0], &tmpval );
1590 mod->sml_values[1].bv_len = 0;
1591 mod->sml_values[1].bv_val = NULL;
1592 assert( mod->sml_values[0].bv_val );
1594 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1595 ber_dupbv( &mod->sml_nvalues[0], &tmpval );
1596 mod->sml_nvalues[1].bv_len = 0;
1597 mod->sml_nvalues[1].bv_val = NULL;
1598 assert( mod->sml_nvalues[0].bv_val );
1600 modtail = &mod->sml_next;
1603 if( si->lastmod == LASTMOD_GEN ) {
1604 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1606 mod->sml_type.bv_val = NULL;
1607 mod->sml_desc = slap_schema.si_ad_creatorsName;
1608 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1609 ber_dupbv( &mod->sml_values[0], &name );
1610 mod->sml_values[1].bv_len = 0;
1611 mod->sml_values[1].bv_val = NULL;
1612 assert( mod->sml_values[0].bv_val );
1614 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1615 ber_dupbv( &mod->sml_nvalues[0], &nname );
1616 mod->sml_nvalues[1].bv_len = 0;
1617 mod->sml_nvalues[1].bv_val = NULL;
1618 assert( mod->sml_nvalues[0].bv_val );
1620 modtail = &mod->sml_next;
1622 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1624 mod->sml_type.bv_val = NULL;
1625 mod->sml_desc = slap_schema.si_ad_createTimestamp;
1626 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1627 ber_dupbv( &mod->sml_values[0], ×tamp );
1628 mod->sml_values[1].bv_len = 0;
1629 mod->sml_values[1].bv_val = NULL;
1630 assert( mod->sml_values[0].bv_val );
1631 mod->sml_nvalues = NULL;
1633 modtail = &mod->sml_next;
1637 if( si->lastmod == LASTMOD_GEN ) {
1638 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1640 mod->sml_type.bv_val = NULL;
1641 mod->sml_desc = slap_schema.si_ad_entryCSN;
1642 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1643 ber_dupbv( &mod->sml_values[0], &csn );
1644 mod->sml_values[1].bv_len = 0;
1645 mod->sml_values[1].bv_val = NULL;
1646 assert( mod->sml_values[0].bv_val );
1647 mod->sml_nvalues = NULL;
1649 modtail = &mod->sml_next;
1651 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1653 mod->sml_type.bv_val = NULL;
1654 mod->sml_desc = slap_schema.si_ad_modifiersName;
1655 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1656 ber_dupbv( &mod->sml_values[0], &name );
1657 mod->sml_values[1].bv_len = 0;
1658 mod->sml_values[1].bv_val = NULL;
1659 assert( mod->sml_values[0].bv_val );
1661 (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1662 ber_dupbv( &mod->sml_nvalues[0], &nname );
1663 mod->sml_nvalues[1].bv_len = 0;
1664 mod->sml_nvalues[1].bv_val = NULL;
1665 assert( mod->sml_nvalues[0].bv_val );
1667 modtail = &mod->sml_next;
1669 mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
1671 mod->sml_type.bv_val = NULL;
1672 mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
1673 mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
1674 ber_dupbv( &mod->sml_values[0], ×tamp );
1675 mod->sml_values[1].bv_len = 0;
1676 mod->sml_values[1].bv_val = NULL;
1677 assert( mod->sml_values[0].bv_val );
1678 mod->sml_nvalues = NULL;
1680 modtail = &mod->sml_next;
1684 return LDAP_SUCCESS;
1689 slap_mods2entry_syncrepl(
1690 Modifications *mods,
1694 char *textbuf, size_t textlen )
1696 Attribute **tail = &(*e)->e_attrs;
1697 assert( *tail == NULL );
1701 for( ; mods != NULL; mods = mods->sml_next ) {
1704 assert( mods->sml_desc != NULL );
1706 attr = attr_find( (*e)->e_attrs, mods->sml_desc );
1708 if( attr != NULL ) {
1709 #define SLURPD_FRIENDLY
1710 #ifdef SLURPD_FRIENDLY
1714 snprintf( textbuf, textlen,
1715 "attribute '%s' provided more than once",
1716 mods->sml_desc->ad_cname.bv_val );
1717 return LDAP_TYPE_OR_VALUE_EXISTS;
1720 for( i=0; attr->a_vals[i].bv_val; i++ ) {
1723 for( j=0; mods->sml_values[j].bv_val; j++ ) {
1728 attr->a_vals = ch_realloc( attr->a_vals,
1729 sizeof( struct berval ) * (i+j) );
1731 /* should check for duplicates */
1733 AC_MEMCPY( &attr->a_vals[i], mods->sml_values,
1734 sizeof( struct berval ) * j );
1736 if( attr->a_nvals ) {
1737 attr->a_nvals = ch_realloc( attr->a_nvals,
1738 sizeof( struct berval ) * (i+j) );
1740 AC_MEMCPY( &attr->a_nvals[i], mods->sml_nvalues,
1741 sizeof( struct berval ) * j );
1743 /* trim the mods array */
1744 ch_free( mods->sml_nvalues );
1745 mods->sml_nvalues = NULL;
1750 snprintf( textbuf, textlen,
1751 "attribute '%s' provided more than once",
1752 mods->sml_desc->ad_cname.bv_val );
1753 return LDAP_TYPE_OR_VALUE_EXISTS;
1757 if( mods->sml_values[1].bv_val != NULL ) {
1758 /* check for duplicates */
1760 MatchingRule *mr = mods->sml_desc->ad_type->sat_equality;
1762 /* check if the values we're adding already exist */
1763 if( mr == NULL || !mr->smr_match ) {
1764 for ( i = 0; mods->sml_bvalues[i].bv_val != NULL; i++ ) {
1765 /* test asserted values against themselves */
1766 for( j = 0; j < i; j++ ) {
1767 if ( bvmatch( &mods->sml_bvalues[i],
1768 &mods->sml_bvalues[j] ) ) {
1769 /* value exists already */
1770 snprintf( textbuf, textlen,
1771 "%s: value #%d provided more than once",
1772 mods->sml_desc->ad_cname.bv_val, j );
1773 return LDAP_TYPE_OR_VALUE_EXISTS;
1780 const char *text = NULL;
1781 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
1783 rc = modify_check_duplicates( mods->sml_desc, mr,
1784 NULL, mods->sml_bvalues, 0,
1785 &text, textbuf, sizeof( textbuf ) );
1787 if ( rc != LDAP_SUCCESS ) {
1793 attr = ch_calloc( 1, sizeof(Attribute) );
1795 /* move ad to attr structure */
1796 attr->a_desc = mods->sml_desc;
1798 /* move values to attr structure */
1799 /* should check for duplicates */
1800 attr->a_vals = mods->sml_values;
1802 attr->a_nvals = mods->sml_nvalues;
1805 tail = &attr->a_next;
1808 return LDAP_SUCCESS;
1812 avl_ber_bvfree( void *bv )
1817 if ( ((struct berval *)bv)->bv_val != NULL ) {
1818 LBER_FREE( ((struct berval *)bv)->bv_val );
1820 LBER_FREE( (char *) bv );
1829 syncinfo_t *si = op->o_callback->sc_private;
1832 if ( rs->sr_type != REP_SEARCH ) return LDAP_SUCCESS;
1834 a = attr_find( e->e_attrs, slap_schema.si_ad_syncreplCookie );
1837 si->syncCookie = NULL;
1839 si->syncCookie = ber_dupbv( NULL, &a->a_vals[0] );
1841 return LDAP_SUCCESS;
1845 nonpresent_callback(
1850 syncinfo_t *si = op->o_callback->sc_private;
1853 struct berval* present_uuid = NULL;
1855 SlapReply rs_cb = {REP_RESULT};
1857 if ( rs->sr_type == REP_RESULT ) {
1858 count = avl_free( si->presentlist, avl_ber_bvfree );
1859 return LDAP_SUCCESS;
1860 } else if ( rs->sr_type == REP_SEARCH ) {
1861 a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
1866 present_uuid = avl_find( si->presentlist,
1867 &a->a_vals[0], syncuuid_cmp );
1869 if ( present_uuid == NULL ) {
1870 op->o_tag = LDAP_REQ_DELETE;
1871 op->o_callback = &cb;
1872 cb.sc_response = null_callback;
1874 op->o_req_dn = e->e_name;
1875 op->o_req_ndn = e->e_nname;
1876 be->be_delete( op, &rs_cb );
1878 avl_delete( &si->presentlist,
1879 &a->a_vals[0], syncuuid_cmp );
1881 return LDAP_SUCCESS;
1883 return LDAP_SUCCESS;
1889 null_entry_callback(
1894 if ( rs->sr_err != LDAP_SUCCESS &&
1895 rs->sr_err != LDAP_REFERRAL &&
1896 rs->sr_err != LDAP_ALREADY_EXISTS &&
1897 rs->sr_err != LDAP_NO_SUCH_OBJECT &&
1898 rs->sr_err != DB_NOTFOUND ) {
1900 LDAP_LOG( OPERATION, ERR,
1901 "null_entry_callback : error code 0x%x\n",
1904 Debug( LDAP_DEBUG_ANY,
1905 "null_entry_callback : error code 0x%x\n",
1909 return LDAP_SUCCESS;