X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fsyncrepl.c;h=6ddc6d1c58ac616af90a4e91b77a7e49b18a0c74;hb=6e602b549420181bfe6ad55d863963a5b11544d1;hp=f4f105b0b9e9edfdf2627b538665693703af2b7f;hpb=e9bd75ae9b396abd79c5edce3ac0470dce61d844;p=openldap diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index f4f105b0b9..6ddc6d1c58 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -35,38 +35,30 @@ #ifdef LDAP_SYNCREPL -static Entry* -syncrepl_message_to_entry ( LDAP *, Operation *, LDAPMessage *, Modifications *, - int*, struct berval *, struct berval * ); - -static int -syncrepl_entry( LDAP *, Operation*, Entry*, Modifications*, - int, struct berval*, struct berval*, int ); - -static int -syncrepl_del_nonpresent( LDAP *, Operation * ); +#include "ldap_rq.h" static void -syncrepl_add_glue( LDAP *, Operation*, Entry*, Modifications*, int, - struct berval*, struct berval* ); +syncrepl_del_nonpresent( syncinfo_t *, LDAP *, Operation * ); static void -syncrepl_updateCookie( LDAP *, Operation *, struct berval *, struct berval * ); +syncrepl_add_glue( syncinfo_t *, LDAP *, Operation*, Entry*, Modifications*, + int, struct berval*, struct berval* ); static int -slap_mods_check_syncrepl( Operation *, Modifications **, +slap_mods_check_syncrepl( syncinfo_t *, Operation *, Modifications **, const char **, char *, size_t, void *ctx ); static int -slap_mods_opattrs_syncrepl( Operation *, Modifications *, Modifications **, - const char **, char *, size_t ); +slap_mods_opattrs_syncrepl( syncinfo_t *, Operation *, Modifications *, + Modifications **, const char **, char *, size_t ); static int -slap_mods2entry_syncrepl( Modifications *, Entry **, int, - const char **, char *, size_t ); +slap_mods2entry_syncrepl( syncinfo_t *, Modifications *, Entry **, int, + const char **, char *, size_t ); /* callback functions */ static int cookie_callback( struct slap_op *, struct slap_rep * ); +static int dn_callback( struct slap_op *, struct slap_rep * ); static int nonpresent_callback( struct slap_op *, struct slap_rep * ); static int null_callback( struct slap_op *, struct slap_rep * ); @@ -75,6 +67,8 @@ static AttributeDescription **add_descs_lastmod; static AttributeDescription **del_descs; static AttributeDescription **del_descs_lastmod; +struct runqueue_s syncrepl_rq; + void init_syncrepl() { @@ -109,25 +103,99 @@ init_syncrepl() del_descs_lastmod[3] = NULL; } +int +ldap_sync_search( + syncinfo_t *si, + LDAP *ld, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int timelimit; + ber_int_t id; + + int rc; + BerElement *sync_ber = NULL; + struct berval *sync_bvalp = NULL; + LDAPControl c[2]; + LDAPControl **ctrls; + int err; + + /* setup LDAP SYNC control */ + sync_ber = ber_alloc_t( LBER_USE_DER ); + ber_set_option( sync_ber, LBER_OPT_BER_MEMCTX, NULL ); + + if ( si->syncCookie ) { + ber_printf( sync_ber, "{eO}", abs(si->type), si->syncCookie ); + } else { + ber_printf( sync_ber, "{e}", abs(si->type) ); + } + + if ( ber_flatten( sync_ber, &sync_bvalp ) == LBER_ERROR ) { + ber_free( sync_ber, 1 ); + return LBER_ERROR; + } + ber_free( sync_ber, 1 ); + + ctrls = (LDAPControl**) sl_calloc( 3, sizeof(LDAPControl*), NULL ); + + c[0].ldctl_oid = LDAP_CONTROL_SYNC; + c[0].ldctl_value = (*sync_bvalp); + c[0].ldctl_iscritical = si->type < 0; + ctrls[0] = &c[0]; + + if ( si->authzId ) { + c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; + c[1].ldctl_value.bv_val = si->authzId; + c[1].ldctl_value.bv_len = strlen( si->authzId ); + c[1].ldctl_iscritical = 1; + ctrls[1] = &c[1]; + } else { + ctrls[1] = NULL; + } + + ctrls[2] = NULL; + + err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls ); + + ber_bvfree( sync_bvalp ); + ch_free( ctrls ); + + if ( err != LDAP_OPT_SUCCESS ) + fprintf( stderr, "Could not set controls : %d\n", err ); + + rc = ldap_search_ext( ld, si->base, si->scope, si->filterstr, + si->attrs, si->attrsonly, sctrls, cctrls, + si->tlimit, si->slimit, msgidp ); + + return rc; +} + void * do_syncrepl( void *ctx, void *arg ) { - Backend *be = arg; - syncinfo_t *si = ( syncinfo_t * ) be->syncinfo; + struct re_s* rtask = arg; + syncinfo_t *si = ( syncinfo_t * ) rtask->arg; + Backend *be = si->be; SlapReply rs = {REP_RESULT}; - LDAPControl c[2], **sctrls = NULL, **rctrls = NULL, *rctrlp; - BerElement *sync_ber; - struct berval *sync_bvalp; + LDAPControl c[2]; + LDAPControl **sctrls = NULL; + LDAPControl **rctrls = NULL; + LDAPControl *rctrlp = NULL; + BerElement *sync_ber = NULL; + struct berval *sync_bvalp = NULL; - BerElement *ctrl_ber; - BerElement *res_ber; + BerElement *ctrl_ber = NULL; + BerElement *res_ber = NULL; LDAP *ld = NULL; - LDAPMessage *res = NULL, *msg; + LDAPMessage *res = NULL; + LDAPMessage *msg = NULL; ber_int_t msgid; @@ -139,11 +207,11 @@ do_syncrepl( struct berval *retdata = NULL; int sync_info_arrived = 0; - Entry *entry; + Entry *entry = NULL; int syncstate; - struct berval syncUUID; - struct berval syncCookie; + struct berval syncUUID = { 0, NULL }; + struct berval syncCookie = { 0, NULL }; int rc; int err; @@ -151,14 +219,14 @@ do_syncrepl( int syncinfo_arrived = 0; int cancel_response = 0; - char **tmp; - AttributeDescription** descs; + char **tmp = NULL; + AttributeDescription** descs = NULL; Connection conn; Operation op = {0}; slap_callback cb; - void *memctx; + void *memctx = NULL; ber_len_t memsiz; int i, j, k, n; @@ -173,8 +241,9 @@ do_syncrepl( struct berval psub = { 0, NULL }; struct berval nsub = { 0, NULL }; char substr[64]; - Modifications *modlist; - char *def_filter_str; + Modifications *modlist = NULL; + Modifications *ml, *mlnext; + char *def_filter_str = NULL; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, "do_syncrepl\n", 0, 0, 0 ); @@ -192,32 +261,17 @@ do_syncrepl( /* Init connection to master */ - if ( ldap_is_ldap_url( si->masteruri )) { - rc = ldap_initialize( &ld, si->masteruri ); - if ( rc != LDAP_SUCCESS ) { -#ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, "do_syncrepl: " - "ldap_initialize failed (%s)\n", - si->masteruri, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, "do_syncrepl: " - "ldap_initialize failed (%s)\n", - si->masteruri, 0, 0 ); -#endif - } - } else { - ld = ldap_init( si->mastername, si->masterport ); - if ( ld == NULL ) { + rc = ldap_initialize( &ld, si->masteruri ); + if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, "do_syncrepl: " - "ldap_init failed (%s:%s)\n", - si->mastername, si->masterport, 0 ); + LDAP_LOG( OPERATION, ERR, "do_syncrepl: " + "ldap_initialize failed (%s)\n", + si->masteruri, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "do_syncrepl: " - "ldap_init failed (%s:%s)\n", - si->mastername, si->masterport, 0 ); + Debug( LDAP_DEBUG_ANY, "do_syncrepl: " + "ldap_initialize failed (%s)\n", + si->masteruri, 0, 0 ); #endif - } } op.o_protocol = LDAP_VERSION3; @@ -311,12 +365,24 @@ do_syncrepl( } } + /* set thread context in syncinfo */ si->ctx = ctx; - op.o_tmpmemctx = NULL; /* FIXME : to use per-thread mem context */ + /* set memory context */ +#if 0 +#define SLAB_SIZE 1048576 + memsiz = SLAB_SIZE; + memctx = sl_mem_create( memsiz, ctx ); + op.o_tmpmemctx = memctx; + op.o_tmpmfuncs = &sl_mfuncs; +#else + op.o_tmpmemctx = NULL; + op.o_tmpmfuncs = &ch_mfuncs; +#endif + op.o_tag = LDAP_REQ_SEARCH; - op.o_dn = be->be_rootdn; - op.o_ndn = be->be_rootndn; + op.o_dn = si->updatedn; + op.o_ndn = si->updatedn; op.o_callback = &cb; op.o_time = slap_get_time(); op.o_managedsait = 1; @@ -372,49 +438,6 @@ do_syncrepl( psub = be->be_nsuffix[0]; - /* setup LDAP SYNC control */ - sync_ber = ber_alloc_t( LBER_USE_DER ); - ber_set_option( sync_ber, LBER_OPT_BER_MEMCTX, op.o_tmpmemctx ); - - if ( si->syncCookie ) { - ber_printf( sync_ber, "{eO}", abs(si->type), si->syncCookie ); - } else { - ber_printf( sync_ber, "{e}", abs(si->type) ); - } - - if ( ber_flatten( sync_ber, &sync_bvalp ) == LBER_ERROR ) { - ber_free( sync_ber, 1 ); - return NULL; - } - ber_free( sync_ber, 1 ); - - sctrls = (LDAPControl**) sl_calloc( 3, sizeof(LDAPControl*), op.o_tmpmemctx ); - - c[0].ldctl_oid = LDAP_CONTROL_SYNC; - c[0].ldctl_value = (*sync_bvalp); - c[0].ldctl_iscritical = si->type < 0; - sctrls[0] = &c[0]; - - if ( si->authzId ) { - c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; - c[1].ldctl_value.bv_val = si->authzId; - c[1].ldctl_value.bv_len = strlen( si->authzId ); - c[1].ldctl_iscritical = 1; - sctrls[1] = &c[1]; - } else { - sctrls[1] = NULL; - } - - sctrls[2] = NULL; - - err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, sctrls ); - - ber_bvfree( sync_bvalp ); - ch_free( sctrls ); - - if ( err != LDAP_OPT_SUCCESS ) - fprintf( stderr, "Could not set controls : %d\n", err ); - /* Delete Attributes */ if ( si->lastmod == LASTMOD_REQ ) { descs = del_descs_lastmod; @@ -454,21 +477,15 @@ do_syncrepl( #endif } si->attrs = tmp; - si->attrs[ n++ ] = ( char * ) strndup( descs[i]->ad_cname.bv_val, - descs[i]->ad_cname.bv_len ); + si->attrs[ n++ ] = ch_strdup ( descs[i]->ad_cname.bv_val ); si->attrs[ n ] = NULL; } - /* Send LDAP SYNC search */ - - rc = ldap_search_ext( ld, si->base, si->scope, si->filterstr, - si->attrs, si->attrsonly, NULL, NULL, - NULL, -1, &msgid ); - - if( rc != LDAP_SUCCESS ) { - fprintf( stderr, "syncrepl: ldap_search_ext (%d)\n", - ldap_err2string( rc ), rc ); - return NULL; + rc = ldap_sync_search( si, ld, NULL, NULL, &msgid ); + if( rc != LDAP_SUCCESS ) { + fprintf( stderr, "syncrepl: ldap_search_ext: %s (%d)\n", + ldap_err2string( rc ), rc ); + return NULL; } while (( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) > 0 ) { @@ -479,20 +496,19 @@ do_syncrepl( { switch( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: - entry = syncrepl_message_to_entry( ld, &op, msg, - modlist, &syncstate, &syncUUID, &syncCookie ); - rc_efree = syncrepl_entry( ld, &op, entry, modlist, - syncstate, &syncUUID, - &syncCookie, - !syncinfo_arrived ); + entry = syncrepl_message_to_entry( si, ld, &op, msg, + &modlist, &syncstate, &syncUUID, &syncCookie ); + rc_efree = syncrepl_entry( si, ld, &op, entry, modlist, + syncstate, &syncUUID, &syncCookie, !syncinfo_arrived ); if ( syncCookie.bv_len ) { - syncrepl_updateCookie( ld, &op, &psub, - &syncCookie ); + syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie ); } - if ( modlist != NULL ) - slap_mods_free( modlist ); if ( rc_efree ) entry_free( entry ); + for ( ml = modlist; ml != NULL; ml = mlnext ) { + mlnext = ml->sml_next; + ber_memfree( ml ); + } break; case LDAP_RES_SEARCH_REFERENCE: @@ -510,48 +526,51 @@ do_syncrepl( if ( rctrls ) { rctrlp = *rctrls; ctrl_ber = ber_alloc_t( LBER_USE_DER ); - ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, op.o_tmpmemctx ); + ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, &op.o_tmpmemctx ); ber_write( ctrl_ber, rctrlp->ldctl_value.bv_val, rctrlp->ldctl_value.bv_len, 0 ); ber_reset( ctrl_ber, 1 ); - ber_scanf( ctrl_ber, "{" ); + ber_scanf( ctrl_ber, "{" /*"}"*/); if ( ber_peek_tag( ctrl_ber, &len ) == LDAP_SYNC_TAG_COOKIE ) { - ber_scanf( ctrl_ber, "m", &syncCookie ); + ber_scanf( ctrl_ber, "o", &syncCookie ); } - ber_free( ctrl_ber, 1 ); } if (si->type == LDAP_SYNC_REFRESH_AND_PERSIST) { if ( cancel_response ) { if ( syncCookie.bv_len ) { - ber_bvfree( si->syncCookie ); - si->syncCookie = ber_dupbv( NULL, &syncCookie ); + syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie ); } + if ( ctrl_ber ) + ber_free( ctrl_ber, 1 ); goto done; } - else + else { + if ( ctrl_ber ) + ber_free( ctrl_ber, 1 ); break; + } } else { if ( syncCookie.bv_len ) { - syncrepl_updateCookie( ld, - &op, &psub, - &syncCookie ); + syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie); } - goto restart; + syncrepl_del_nonpresent( si, ld, &op ); + if ( ctrl_ber ) + ber_free( ctrl_ber, 1 ); + goto done; } -restart_loop: break; - case LDAP_RES_INTERMEDIATE_RESP: - ldap_parse_intermediate_resp_result( ld, msg, - &retoid, &retdata, 0 ); - if ( !strcmp( retoid, LDAP_SYNC_INFO ) ) { + case LDAP_RES_INTERMEDIATE: + rc = ldap_parse_intermediate( ld, msg, + &retoid, &retdata, NULL, 0 ); + if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) { sync_info_arrived = 1; res_ber = ber_init( retdata ); - ber_scanf( res_ber, "{e", &syncstate ); + ber_scanf( res_ber, "{e" /*"}"*/, &syncstate ); if ( syncstate == LDAP_SYNC_REFRESH_DONE ) { - syncrepl_del_nonpresent( ld, &op ); + syncrepl_del_nonpresent( si, ld, &op ); } else if ( syncstate != LDAP_SYNC_NEW_COOKIE ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, @@ -563,11 +582,10 @@ restart_loop: } if ( ber_peek_tag( res_ber, &len ) - == LDAP_SYNC_TAG_COOKIE ) { - ber_scanf( res_ber, "m}", &syncCookie ); + == LDAP_SYNC_TAG_COOKIE ) { + ber_scanf( res_ber, /*"{"*/ "o}", &syncCookie ); if ( syncCookie.bv_len ) { - ber_bvfree( si->syncCookie ); - si->syncCookie = ber_dupbv( NULL, &syncCookie ); + syncrepl_updateCookie( si, ld, &op, &psub, &syncCookie); } } else { if ( syncstate == LDAP_SYNC_NEW_COOKIE ) { @@ -592,8 +610,8 @@ restart_loop: "response\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_syncrepl : " - "unknown intermediate " - "response\n", 0, 0, 0 ); + "unknown intermediate response (%d)\n", + rc, 0, 0 ); #endif ldap_memfree( retoid ); ber_bvfree( retdata ); @@ -623,29 +641,37 @@ restart_loop: Debug( LDAP_DEBUG_ANY, "do_syncrepl : unknown result\n", 0, 0, 0 ); #endif - return NULL; } -restart: - sleep(si->interval * 60); - goto restart_loop; -// set alarm clock to send signal to slapd -// should set the signal handler beforehand -// the signal handler re execute do_syncrepl() - done: + if ( syncCookie.bv_val ) + ch_free( syncCookie.bv_val ); + if ( syncUUID.bv_val ) + ch_free( syncUUID.bv_val ); + if ( res ) ldap_msgfree( res ); ldap_unbind( ld ); + + ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex ); + ldap_pvt_runqueue_stoptask( &syncrepl_rq, rtask ); + if ( si->type == LDAP_SYNC_REFRESH_ONLY ) { + ldap_pvt_runqueue_resched( &syncrepl_rq, rtask ); + } else { + ldap_pvt_runqueue_remove( &syncrepl_rq, rtask ); + } + ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex ); + return NULL; } -static Entry* +Entry* syncrepl_message_to_entry( + syncinfo_t *si, LDAP *ld, Operation *op, LDAPMessage *msg, - Modifications *modlist, + Modifications **modlist, int *syncstate, struct berval *syncUUID, struct berval *syncCookie @@ -654,32 +680,32 @@ syncrepl_message_to_entry( Entry *e; BerElement *ber = NULL; BerElement *tmpber; - struct berval bv; + struct berval bv = {0, NULL}; Modifications tmp; Modifications *mod; - Modifications **modtail = &modlist; + Modifications **modtail = modlist; Backend *be = op->o_bd; const char *text; char txtbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof txtbuf; - struct berval **bvals; + struct berval **bvals = NULL; char *dn; - struct berval bdn; + struct berval bdn = {0, NULL}; Attribute *attr; struct berval empty_bv = { 0, NULL }; int rc; char *a; - syncinfo_t *si = ( syncinfo_t * ) be->syncinfo; - ber_len_t len; LDAPControl* rctrlp; LDAPControl** rctrls = NULL; BerElement* ctrl_ber; - modlist = NULL; + ber_tag_t tag; + + *modlist = NULL; if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) { #ifdef NEW_LOGGING @@ -712,15 +738,15 @@ syncrepl_message_to_entry( e->e_attrs = NULL; - for ( rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues); - rc == LDAP_SUCCESS; - rc = ldap_get_attribute_ber( ld, msg, ber, &tmp.sml_type, &tmp.sml_bvalues)) - { + while ( ber_remaining( ber ) ) { + tag = ber_scanf( ber, "{mW}", &tmp.sml_type, &tmp.sml_values ); + + if ( tag == LBER_ERROR ) break; if ( tmp.sml_type.bv_val == NULL ) break; - mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + mod = (Modifications *) ch_malloc( sizeof( Modifications )); - mod->sml_op = LDAP_MOD_ADD; + mod->sml_op = LDAP_MOD_REPLACE; mod->sml_next = NULL; mod->sml_desc = NULL; mod->sml_type = tmp.sml_type; @@ -731,16 +757,16 @@ syncrepl_message_to_entry( modtail = &mod->sml_next; } - if ( ber_scanf( ber, "}") == LBER_ERROR ) { + if ( ber_scanf( ber, "}") == LBER_ERROR ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_message_to_entry: ber_scanf failed\n", 0, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_message_to_entry: ber_scanf failed\n", 0, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: ber_scanf failed\n", - 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: ber_scanf failed\n", + 0, 0, 0 ); #endif return NULL; - } + } ber_free( ber, 0 ); tmpber = ldap_get_message_ber( msg ); @@ -764,12 +790,12 @@ syncrepl_message_to_entry( if ( rctrls ) { rctrlp = *rctrls; ctrl_ber = ber_alloc_t( LBER_USE_DER ); - ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, op->o_tmpmemctx ); + ber_set_option( ctrl_ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); ber_write( ctrl_ber, rctrlp->ldctl_value.bv_val, rctrlp->ldctl_value.bv_len, 0 ); ber_reset( ctrl_ber, 1 ); - ber_scanf( ctrl_ber, "{em", syncstate, syncUUID ); + ber_scanf( ctrl_ber, "{eo", syncstate, syncUUID ); if ( ber_peek_tag( ctrl_ber, &len ) == LDAP_SYNC_TAG_COOKIE ) { - ber_scanf( ctrl_ber, "m}", syncCookie ); + ber_scanf( ctrl_ber, "o}", syncCookie ); } ber_free( ctrl_ber, 1 ); } else { @@ -785,53 +811,56 @@ syncrepl_message_to_entry( if ( *syncstate == LDAP_SYNC_PRESENT ) { e = NULL; goto done; + } else if ( *syncstate == LDAP_SYNC_DELETE ) { + goto done; } - if ( modlist == NULL ) { + if ( *modlist == NULL ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_message_to_entry: no attributes\n", 0, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_message_to_entry: no attributes\n", 0, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: no attributes\n", - 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: no attributes\n", + 0, 0, 0 ); #endif - } + } - rc = slap_mods_check_syncrepl( op, &modlist, &text, txtbuf, textlen, NULL ); + rc = slap_mods_check_syncrepl( si, op, modlist, + &text, txtbuf, textlen, NULL ); if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_message_to_entry: mods check (%s)\n", text, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_message_to_entry: mods check (%s)\n", text, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods check (%s)\n", - text, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods check (%s)\n", + text, 0, 0 ); #endif return NULL; } - rc = slap_mods_opattrs_syncrepl( op, modlist, modtail, - &text,txtbuf, textlen ); + rc = slap_mods_opattrs_syncrepl( si, op, *modlist, modtail, + &text,txtbuf, textlen ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_message_to_entry: mods opattrs (%s)\n", text, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_message_to_entry: mods opattrs (%s)\n", text, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods opattrs (%s)\n", - text, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods opattrs (%s)\n", + text, 0, 0 ); #endif return NULL; } - rc = slap_mods2entry_syncrepl( modlist, &e, 1, &text, txtbuf, textlen ); + rc = slap_mods2entry_syncrepl( si, *modlist, &e, 1, &text, txtbuf, textlen); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_message_to_entry: mods2entry (%s)\n", text, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_message_to_entry: mods2entry (%s)\n", text, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods2entry (%s)\n", - text, 0, 0 ); + Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_entry: mods2entry (%s)\n", + text, 0, 0 ); #endif } @@ -842,7 +871,7 @@ done: return e; } -int +int syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 ) { const struct berval *uuid1 = v_uuid1; @@ -852,8 +881,9 @@ syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 ) return ( strcmp( uuid1->bv_val, uuid2->bv_val ) ); } -static int +int syncrepl_entry( + syncinfo_t* si, LDAP *ld, Operation *op, Entry* e, @@ -865,111 +895,140 @@ syncrepl_entry( ) { Backend *be = op->o_bd; - syncinfo_t *si = ( syncinfo_t * ) be->syncinfo; slap_callback cb; struct berval csn_bv = {0, NULL}; struct berval *syncuuid_bv = NULL; char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; SlapReply rs = {REP_RESULT}; - int rc; + int rc = LDAP_SUCCESS; + + struct berval base_bv = {0, NULL}; -#if 0 /* FIXME : UUID search required first */ char *filterstr; - struct berval filterstr_bv; Filter *filter; -#endif Attribute *a; - if ( syncstate == LDAP_SYNC_PRESENT ) { + if ( refresh && + ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD )) { syncuuid_bv = ber_dupbv( NULL, syncUUID ); avl_insert( &si->presentlist, (caddr_t) syncuuid_bv, - syncuuid_cmp, avl_dup_error ); - return 1; + syncuuid_cmp, avl_dup_error ); } - if ( !attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )) { - attr_merge_one( e, slap_schema.si_ad_entryUUID, syncUUID, syncUUID ); + if ( syncstate == LDAP_SYNC_PRESENT ) { + if ( e ) + return 1; + else + return 0; } -#if 0 /* FIXME : UUID search required first */ - filterstr = (char *) ch_malloc( strlen("entryUUID=") + syncUUID->bv_len + 1 ); + filterstr = (char *) sl_malloc( strlen("entryUUID=") + syncUUID->bv_len + 1, + op->o_tmpmemctx ); strcpy( filterstr, "entryUUID=" ); strcat( filterstr, syncUUID->bv_val ); -#endif si->e = e; si->syncUUID = syncUUID; + si->syncUUID_ndn = NULL; -#if 0 /* FIXME : UUID search required first */ filter = str2filter( filterstr ); - ber_str2bv( filterstr, strlen(filterstr), 1, &filterstr_bv ); + ber_str2bv( filterstr, strlen(filterstr), 1, &op->ors_filterstr ); ch_free( filterstr ); -#endif + op->ors_filter = filter; + op->ors_scope = LDAP_SCOPE_SUBTREE; - op->o_req_dn = e->e_name; - op->o_req_ndn = e->e_nname; + /* get syncrepl cookie of shadow replica from subentry */ + ber_str2bv( si->base, strlen(si->base), 1, &base_bv ); + dnPrettyNormal( 0, &base_bv, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); + ch_free( base_bv.bv_val ); + /* set callback function */ op->o_callback = &cb; + cb.sc_response = dn_callback; + cb.sc_private = si; + + be->be_search( op, &rs ); + + ch_free( op->o_req_dn.bv_val ); + ch_free( op->o_req_ndn.bv_val ); + filter_free( op->ors_filter ); + ch_free( op->ors_filterstr.bv_val ); + cb.sc_response = null_callback; cb.sc_private = si; + rc = LDAP_SUCCESS; + + if ( si->syncUUID_ndn ) { + op->o_req_dn = *si->syncUUID_ndn; + op->o_req_ndn = *si->syncUUID_ndn; + op->o_tag = LDAP_REQ_DELETE; + rc = be->be_delete( op, &rs ); + } + switch ( syncstate ) { case LDAP_SYNC_ADD : case LDAP_SYNC_MODIFY : -sync_add_retry: - op->o_tag = LDAP_REQ_MODIFY; - op->orm_modlist = modlist; - rc = be->be_modify( op, &rs ); - if ( rc != LDAP_SUCCESS ) { - if ( rc == LDAP_REFERRAL || - rc == LDAP_NO_SUCH_OBJECT || - rc == DB_NOTFOUND ) { - op->o_tag = LDAP_REQ_ADD; - op->ora_e = e; - rc = be->be_add( op, &rs ); - if ( rc != LDAP_SUCCESS ) { - if ( rc == LDAP_ALREADY_EXISTS ) { - goto sync_add_retry; - } else if ( rc == LDAP_REFERRAL || - rc == LDAP_NO_SUCH_OBJECT || - rc == DB_NOTFOUND ) { - syncrepl_add_glue(ld, op, e, - modlist, syncstate, - syncUUID, syncCookie); - } else { + + if ( rc == LDAP_SUCCESS || + rc == LDAP_REFERRAL || + rc == LDAP_NO_SUCH_OBJECT ) { + + if ( !attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )) { + attr_merge_one( e, slap_schema.si_ad_entryUUID, syncUUID, syncUUID ); + } + + op->o_tag = LDAP_REQ_ADD; + op->ora_e = e; + op->o_req_dn = e->e_name; + op->o_req_ndn = e->e_nname; + rc = be->be_add( op, &rs ); + + if ( rc != LDAP_SUCCESS ) { + if ( rc == LDAP_ALREADY_EXISTS ) { + op->o_tag = LDAP_REQ_MODIFY; + op->orm_modlist = modlist; + op->o_req_dn = e->e_name; + op->o_req_ndn = e->e_nname; + rc = be->be_modify( op, &rs ); + } else if ( rc == LDAP_REFERRAL || + rc == LDAP_NO_SUCH_OBJECT ) { + syncrepl_add_glue( si, ld, op, e, + modlist, syncstate, + syncUUID, syncCookie); + } else { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "be_add failed (%d)\n", - rc, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "be_modify failed (%d)\n", + rc, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, - "be_add failed (%d)\n", - rc, 0, 0 ); + Debug( LDAP_DEBUG_ANY, + "be_modify failed (%d)\n", + rc, 0, 0 ); #endif - } - } else { - return 0; } } else { + return 0; + } + } else { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "be_modify failed (%d)\n", rc, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "be_modify/be_delete failed (%d)\n", rc, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, - "be_modify failed (%d)\n", rc, 0, 0 ); + Debug( LDAP_DEBUG_ANY, + "be_modify/be_delete failed (%d)\n", rc, 0, 0 ); #endif - } } si->e = NULL; return 1; + case LDAP_SYNC_DELETE : - op->o_tag = LDAP_REQ_DELETE; - be->be_delete( op, &rs ); - si->e = NULL; + /* Already deleted */ return 1; + default : #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, @@ -982,19 +1041,20 @@ sync_add_retry: } } -static int +static void syncrepl_del_nonpresent( + syncinfo_t *si, LDAP *ld, Operation *op ) { Backend* be = op->o_bd; - syncinfo_t *si = ( syncinfo_t * ) be->syncinfo; slap_callback cb; struct berval base_bv = {0, NULL}; Filter *filter; SlapReply rs = {REP_RESULT}; - struct berval filterstr_bv; + struct berval filterstr_bv = {0, NULL}; + struct nonpresent_entry *np_list, *np_prev; ber_str2bv( si->base, strlen(si->base), 1, &base_bv ); dnPrettyNormal(0, &base_bv, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); @@ -1007,7 +1067,7 @@ syncrepl_del_nonpresent( op->o_callback = &cb; op->o_tag = LDAP_REQ_SEARCH; - op->ors_scope = LDAP_SCOPE_BASE; + op->ors_scope = si->scope; op->ors_deref = LDAP_DEREF_NEVER; op->ors_slimit = -1; op->ors_tlimit = -1; @@ -1018,15 +1078,41 @@ syncrepl_del_nonpresent( be->be_search( op, &rs ); - ch_free( op->o_req_dn.bv_val ); - ch_free( op->o_req_ndn.bv_val ); + if ( !LDAP_LIST_EMPTY( &si->nonpresentlist ) ) { + np_list = LDAP_LIST_FIRST( &si->nonpresentlist ); + while ( np_list != NULL ) { + LDAP_LIST_REMOVE( np_list, np_link ); + np_prev = np_list; + np_list = LDAP_LIST_NEXT( np_list, np_link ); + op->o_tag = LDAP_REQ_DELETE; + op->o_callback = &cb; + cb.sc_response = null_callback; + cb.sc_private = si; + op->o_req_dn = *np_prev->dn; + op->o_req_ndn = *np_prev->ndn; + op->o_bd->be_delete( op, &rs ); + ber_bvfree( np_prev->dn ); + ber_bvfree( np_prev->ndn ); + op->o_req_dn.bv_val = NULL; + op->o_req_ndn.bv_val = NULL; + ch_free( np_prev ); + } + } + + if ( op->o_req_dn.bv_val ) + ch_free( op->o_req_dn.bv_val ); + if ( op->o_req_ndn.bv_val ) + ch_free( op->o_req_ndn.bv_val ); filter_free( op->ors_filter ); ch_free( op->ors_filterstr.bv_val ); + + return; } static void syncrepl_add_glue( + syncinfo_t *si, LDAP *ld, Operation* op, Entry *e, @@ -1037,7 +1123,6 @@ syncrepl_add_glue( ) { Backend *be = op->o_bd; - syncinfo_t *si = op->o_callback->sc_private; struct berval uuid_bv = {0, NULL}; slap_callback cb; Attribute *a; @@ -1134,8 +1219,9 @@ syncrepl_add_glue( return; } -static void +void syncrepl_updateCookie( + syncinfo_t *si, LDAP *ld, Operation *op, struct berval *pdn, @@ -1143,15 +1229,16 @@ syncrepl_updateCookie( ) { Backend *be = op->o_bd; - syncinfo_t *si = ( syncinfo_t * ) be->syncinfo; + Modifications *ml; + Modifications *mlnext; Modifications *mod; Modifications *modlist; Modifications **modtail = &modlist; - struct berval* ocbva; - struct berval* cnbva; - struct berval* ssbva; - struct berval* scbva; + struct berval* ocbva = NULL; + struct berval* cnbva = NULL; + struct berval* ssbva = NULL; + struct berval* scbva = NULL; char substr[64]; char rdnstr[67]; @@ -1225,7 +1312,7 @@ syncrepl_updateCookie( *modtail = mod; modtail = &mod->sml_next; - ber_str2bv( " ", 1, 1, &ssbva[0] ); + ber_str2bv( "{}", strlen("{}"), 1, &ssbva[0] ); ssbva[1].bv_len = 0; ssbva[1].bv_val = NULL; mod = (Modifications *) ch_malloc( sizeof( Modifications )); @@ -1239,27 +1326,29 @@ syncrepl_updateCookie( *modtail = mod; modtail = &mod->sml_next; - rc = slap_mods_check_syncrepl( op, &modlist, &text, txtbuf, textlen, NULL ); + rc = slap_mods_check_syncrepl( si, op, &modlist, + &text, txtbuf, textlen, NULL ); if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_updateCookie: mods check (%s)\n", text, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_updateCookie: mods check (%s)\n", text, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods check (%s)\n", + Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods check (%s)\n", text, 0, 0 ); #endif } op->o_tag = LDAP_REQ_ADD; - rc = slap_mods_opattrs_syncrepl( op, modlist, modtail, &text,txtbuf, textlen ); + rc = slap_mods_opattrs_syncrepl( si, op, modlist, modtail, + &text,txtbuf, textlen ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_updateCookie: mods opattrs (%s)\n", text, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_updateCookie: mods opattrs (%s)\n", text, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods opattrs (%s)\n", + Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods opattrs (%s)\n", text, 0, 0 ); #endif } @@ -1273,14 +1362,14 @@ syncrepl_updateCookie( e->e_attrs = NULL; - rc = slap_mods2entry_syncrepl( modlist, &e, 1, &text, txtbuf, textlen ); + rc = slap_mods2entry_syncrepl( si, modlist, &e, 1, &text, txtbuf, textlen ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "syncrepl_updateCookie: mods2entry (%s)\n", text, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "syncrepl_updateCookie: mods2entry (%s)\n", text, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods2entry (%s)\n", + Debug( LDAP_DEBUG_ANY, "syncrepl_updateCookie: mods2entry (%s)\n", text, 0, 0 ); #endif } @@ -1299,8 +1388,7 @@ update_cookie_retry: rc = be->be_modify( op, &rs ); if ( rc != LDAP_SUCCESS ) { if ( rc == LDAP_REFERRAL || - rc == LDAP_NO_SUCH_OBJECT || - rc == DB_NOTFOUND ) { + rc == LDAP_NO_SUCH_OBJECT ) { op->o_tag = LDAP_REQ_ADD; op->ora_e = e; rc = be->be_add( op, &rs ); @@ -1308,8 +1396,7 @@ update_cookie_retry: if ( rc == LDAP_ALREADY_EXISTS ) { goto update_cookie_retry; } else if ( rc == LDAP_REFERRAL || - rc == LDAP_NO_SUCH_OBJECT || - rc == DB_NOTFOUND ) { + rc == LDAP_NO_SUCH_OBJECT ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "cookie will be non-persistent\n", @@ -1331,7 +1418,7 @@ update_cookie_retry: #endif } } else { - return; + goto done; } } else { #ifdef NEW_LOGGING @@ -1343,25 +1430,33 @@ update_cookie_retry: #endif } } + if ( e != NULL ) entry_free( e ); - if ( modlist != NULL ) - slap_mods_free( modlist ); + +done : + + for ( ml = modlist; ml != NULL; ml = mlnext ) { + mlnext = ml->sml_next; + free( ml ); + } + + return; } static int slap_mods_check_syncrepl( + syncinfo_t* si, Operation *op, - Modifications **mlp, - const char **text, - char *textbuf, - size_t textlen, + Modifications **mlp, + const char **text, + char *textbuf, + size_t textlen, void *ctx ) { - int rc; + int rc; Backend *be = op->o_bd; - syncinfo_t *si = ( syncinfo_t * ) be->syncinfo; AttributeDescription** descs; int i; Modifications *prevml = NULL; @@ -1369,19 +1464,19 @@ int slap_mods_check_syncrepl( Modifications *ml = *mlp; while ( ml != NULL ) { - AttributeDescription *ad = NULL; + AttributeDescription *ad = NULL; - /* convert to attribute description */ - rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text ); + /* convert to attribute description */ + rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text ); - if( rc != LDAP_SUCCESS ) { - snprintf( textbuf, textlen, "%s: %s", - ml->sml_type.bv_val, *text ); - *text = textbuf; - return rc; - } + if( rc != LDAP_SUCCESS ) { + snprintf( textbuf, textlen, "%s: %s", + ml->sml_type.bv_val, *text ); + *text = textbuf; + return rc; + } - ad = ml->sml_desc; + ad = ml->sml_desc; if ( si->lastmod == LASTMOD_REQ ) { descs = del_descs_lastmod; @@ -1405,316 +1500,304 @@ int slap_mods_check_syncrepl( } } - if( slap_syntax_is_binary( ad->ad_type->sat_syntax ) - && !slap_ad_is_binary( ad )) - { - /* attribute requires binary transfer */ - snprintf( textbuf, textlen, - "%s: requires ;binary transfer", - ml->sml_type.bv_val ); - *text = textbuf; - return LDAP_UNDEFINED_TYPE; - } - - if( !slap_syntax_is_binary( ad->ad_type->sat_syntax ) - && slap_ad_is_binary( ad )) - { - /* attribute requires binary transfer */ - snprintf( textbuf, textlen, - "%s: disallows ;binary transfer", - ml->sml_type.bv_val ); - *text = textbuf; - return LDAP_UNDEFINED_TYPE; - } - - if( slap_ad_is_tag_range( ad )) { - /* attribute requires binary transfer */ - snprintf( textbuf, textlen, - "%s: inappropriate use of tag range option", - ml->sml_type.bv_val ); - *text = textbuf; - return LDAP_UNDEFINED_TYPE; - } - - if ( is_at_obsolete( ad->ad_type ) && - ( ml->sml_op == LDAP_MOD_ADD || ml->sml_values != NULL ) ) - { - /* - * attribute is obsolete, - * only allow replace/delete with no values - */ - snprintf( textbuf, textlen, - "%s: attribute is obsolete", - ml->sml_type.bv_val ); - *text = textbuf; - return LDAP_CONSTRAINT_VIOLATION; - } - - /* - * check values - */ - if( ml->sml_values != NULL ) { - ber_len_t nvals; - slap_syntax_validate_func *validate = - ad->ad_type->sat_syntax->ssyn_validate; - slap_syntax_transform_func *pretty = - ad->ad_type->sat_syntax->ssyn_pretty; - - if( !pretty && !validate ) { - *text = "no validator for syntax"; - snprintf( textbuf, textlen, - "%s: no validator for syntax %s", - ml->sml_type.bv_val, - ad->ad_type->sat_syntax->ssyn_oid ); - *text = textbuf; - return LDAP_INVALID_SYNTAX; - } - - /* - * check that each value is valid per syntax - * and pretty if appropriate - */ - for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) { - struct berval pval; - if( pretty ) { - rc = pretty( ad->ad_type->sat_syntax, - &ml->sml_values[nvals], &pval, - ctx ); - } else { - rc = validate( ad->ad_type->sat_syntax, - &ml->sml_values[nvals] ); - } - - if( rc != 0 ) { - snprintf( textbuf, textlen, - "%s: value #%ld invalid per syntax", - ml->sml_type.bv_val, (long) nvals ); - *text = textbuf; - return LDAP_INVALID_SYNTAX; - } - - if( pretty ) { - ber_memfree( ml->sml_values[nvals].bv_val ); - ml->sml_values[nvals] = pval; - } - } - - /* - * a rough single value check... an additional check is needed - * to catch add of single value to existing single valued attribute - */ - if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE) - && nvals > 1 && is_at_single_value( ad->ad_type )) - { - snprintf( textbuf, textlen, - "%s: multiple values provided", - ml->sml_type.bv_val ); - *text = textbuf; - return LDAP_CONSTRAINT_VIOLATION; - } - - if( nvals && ad->ad_type->sat_equality && - ad->ad_type->sat_equality->smr_normalize ) - { - ml->sml_nvalues = ch_malloc( (nvals+1)*sizeof(struct berval) ); - for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) { - rc = ad->ad_type->sat_equality->smr_normalize( - 0, - ad->ad_type->sat_syntax, - ad->ad_type->sat_equality, - &ml->sml_values[nvals], &ml->sml_nvalues[nvals], - ctx ); - if( rc ) { + if( slap_syntax_is_binary( ad->ad_type->sat_syntax ) + && !slap_ad_is_binary( ad )) { + /* attribute requires binary transfer */ + snprintf( textbuf, textlen, + "%s: requires ;binary transfer", + ml->sml_type.bv_val ); + *text = textbuf; + return LDAP_UNDEFINED_TYPE; + } + + if( !slap_syntax_is_binary( ad->ad_type->sat_syntax ) + && slap_ad_is_binary( ad )) { + /* attribute requires binary transfer */ + snprintf( textbuf, textlen, + "%s: disallows ;binary transfer", + ml->sml_type.bv_val ); + *text = textbuf; + return LDAP_UNDEFINED_TYPE; + } + + if( slap_ad_is_tag_range( ad )) { + /* attribute requires binary transfer */ + snprintf( textbuf, textlen, + "%s: inappropriate use of tag range option", + ml->sml_type.bv_val ); + *text = textbuf; + return LDAP_UNDEFINED_TYPE; + } + + if ( is_at_obsolete( ad->ad_type ) && + ( ml->sml_op == LDAP_MOD_ADD || ml->sml_values != NULL ) ) { + /* + * attribute is obsolete, + * only allow replace/delete with no values + */ + snprintf( textbuf, textlen, + "%s: attribute is obsolete", + ml->sml_type.bv_val ); + *text = textbuf; + return LDAP_CONSTRAINT_VIOLATION; + } + + /* + * check values + */ + if( ml->sml_values != NULL ) { + ber_len_t nvals; + slap_syntax_validate_func *validate = + ad->ad_type->sat_syntax->ssyn_validate; + slap_syntax_transform_func *pretty = + ad->ad_type->sat_syntax->ssyn_pretty; + + if( !pretty && !validate ) { + *text = "no validator for syntax"; + snprintf( textbuf, textlen, + "%s: no validator for syntax %s", + ml->sml_type.bv_val, + ad->ad_type->sat_syntax->ssyn_oid ); + *text = textbuf; + return LDAP_INVALID_SYNTAX; + } + + /* + * check that each value is valid per syntax + * and pretty if appropriate + */ + for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) { + struct berval pval = {0, NULL}; + if( pretty ) { + rc = pretty( ad->ad_type->sat_syntax, + &ml->sml_values[nvals], &pval, ctx ); + } else { + rc = validate( ad->ad_type->sat_syntax, + &ml->sml_values[nvals] ); + } + + if( rc != 0 ) { + snprintf( textbuf, textlen, + "%s: value #%ld invalid per syntax", + ml->sml_type.bv_val, (long) nvals ); + *text = textbuf; + return LDAP_INVALID_SYNTAX; + } + + if( pretty ) { + ber_memfree( ml->sml_values[nvals].bv_val ); + ml->sml_values[nvals] = pval; + } + } + + /* + * a rough single value check... an additional check is needed + * to catch add of single value to existing single valued attribute + */ + if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE) + && nvals > 1 && is_at_single_value( ad->ad_type )) { + snprintf( textbuf, textlen, + "%s: multiple values provided", + ml->sml_type.bv_val ); + *text = textbuf; + return LDAP_CONSTRAINT_VIOLATION; + } + + if( nvals && ad->ad_type->sat_equality && + ad->ad_type->sat_equality->smr_normalize ) { + ml->sml_nvalues = ch_malloc( (nvals+1)*sizeof(struct berval) ); + for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) { + rc = ad->ad_type->sat_equality->smr_normalize( 0, + ad->ad_type->sat_syntax, ad->ad_type->sat_equality, + &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx ); + if( rc ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, DETAIL1, - "str2entry: NULL (ssyn_normalize %d)\n", - rc, 0, 0 ); + LDAP_LOG( OPERATION, DETAIL1, + "str2entry: NULL (ssyn_normalize %d)\n", rc, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, - "<= str2entry NULL (ssyn_normalize %d)\n", - rc, 0, 0 ); + Debug( LDAP_DEBUG_ANY, + "<= str2entry NULL (ssyn_normalize %d)\n", rc, 0, 0 ); #endif - snprintf( textbuf, textlen, - "%s: value #%ld normalization failed", - ml->sml_type.bv_val, (long) nvals ); - *text = textbuf; - return rc; - } - } - ml->sml_nvalues[nvals].bv_val = NULL; - ml->sml_nvalues[nvals].bv_len = 0; - } - } + snprintf( textbuf, textlen, + "%s: value #%ld normalization failed", + ml->sml_type.bv_val, (long) nvals ); + *text = textbuf; + return rc; + } + } + ml->sml_nvalues[nvals].bv_val = NULL; + ml->sml_nvalues[nvals].bv_len = 0; + } + } prevml = ml; ml = ml->sml_next; - } + } - return LDAP_SUCCESS; + return LDAP_SUCCESS; } static int slap_mods_opattrs_syncrepl( - Operation *op, - Modifications *mods, - Modifications **modtail, - const char **text, - char *textbuf, size_t textlen ) + syncinfo_t *si, + Operation *op, + Modifications *mods, + Modifications **modtail, + const char **text, + char *textbuf, size_t textlen ) { - struct berval name, timestamp, csn; - struct berval nname; - char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; - char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; - Modifications *mod; + struct berval name = {0, NULL}; + struct berval timestamp = {0, NULL}; + struct berval csn = {0, NULL}; + struct berval nname = {0, NULL}; + char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; + char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; + Modifications *mod; Backend *be = op->o_bd; - syncinfo_t *si = ( syncinfo_t * ) be->syncinfo; int mop = LDAP_MOD_REPLACE; - assert( modtail != NULL ); - assert( *modtail == NULL ); - - if( si->lastmod == LASTMOD_GEN ) { - struct tm *ltm; - time_t now = slap_get_time(); - - ldap_pvt_thread_mutex_lock( &gmtime_mutex ); - ltm = gmtime( &now ); - lutil_gentime( timebuf, sizeof(timebuf), ltm ); - - csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), 0, 0 ); - ldap_pvt_thread_mutex_unlock( &gmtime_mutex ); - csn.bv_val = csnbuf; - - timestamp.bv_val = timebuf; - timestamp.bv_len = strlen(timebuf); - - if( op->o_dn.bv_len == 0 ) { - name.bv_val = SLAPD_ANONYMOUS; - name.bv_len = sizeof(SLAPD_ANONYMOUS)-1; - nname = name; - } else { - name = op->o_dn; - nname = op->o_ndn; - } - } - - if( op->o_tag == LDAP_REQ_ADD ) { - struct berval tmpval; - - if( global_schemacheck ) { - int rc = mods_structural_class( mods, &tmpval, - text, textbuf, textlen ); - if( rc != LDAP_SUCCESS ) { - return rc; - } - - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); + assert( modtail != NULL ); + assert( *modtail == NULL ); + + if( si->lastmod == LASTMOD_GEN ) { + struct tm *ltm; + time_t now = slap_get_time(); + + ldap_pvt_thread_mutex_lock( &gmtime_mutex ); + ltm = gmtime( &now ); + lutil_gentime( timebuf, sizeof(timebuf), ltm ); + + csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), 0, 0 ); + ldap_pvt_thread_mutex_unlock( &gmtime_mutex ); + csn.bv_val = csnbuf; + + timestamp.bv_val = timebuf; + timestamp.bv_len = strlen(timebuf); + + if( op->o_dn.bv_len == 0 ) { + name.bv_val = SLAPD_ANONYMOUS; + name.bv_len = sizeof(SLAPD_ANONYMOUS)-1; + nname = name; + } else { + name = op->o_dn; + nname = op->o_ndn; + } + } + + if( op->o_tag == LDAP_REQ_ADD ) { + struct berval tmpval = {0, NULL}; + + if( global_schemacheck ) { + int rc = mods_structural_class( mods, &tmpval, + text, textbuf, textlen ); + if( rc != LDAP_SUCCESS ) { + return rc; + } + + mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); + mod->sml_op = mop; + mod->sml_type.bv_val = NULL; + mod->sml_desc = slap_schema.si_ad_structuralObjectClass; + mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_values[0], &tmpval ); + mod->sml_values[1].bv_len = 0; + mod->sml_values[1].bv_val = NULL; + assert( mod->sml_values[0].bv_val ); + mod->sml_nvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_nvalues[0], &tmpval ); + mod->sml_nvalues[1].bv_len = 0; + mod->sml_nvalues[1].bv_val = NULL; + assert( mod->sml_nvalues[0].bv_val ); + *modtail = mod; + modtail = &mod->sml_next; + } + + if( si->lastmod == LASTMOD_GEN ) { + mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); + mod->sml_op = mop; + mod->sml_type.bv_val = NULL; + mod->sml_desc = slap_schema.si_ad_creatorsName; + mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_values[0], &name ); + mod->sml_values[1].bv_len = 0; + mod->sml_values[1].bv_val = NULL; + assert( mod->sml_values[0].bv_val ); + mod->sml_nvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_nvalues[0], &nname ); + mod->sml_nvalues[1].bv_len = 0; + mod->sml_nvalues[1].bv_val = NULL; + assert( mod->sml_nvalues[0].bv_val ); + *modtail = mod; + modtail = &mod->sml_next; + + mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); mod->sml_op = mop; - mod->sml_type.bv_val = NULL; - mod->sml_desc = slap_schema.si_ad_structuralObjectClass; - mod->sml_values = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], &tmpval ); - mod->sml_values[1].bv_len = 0; - mod->sml_values[1].bv_val = NULL; - assert( mod->sml_values[0].bv_val ); - mod->sml_nvalues = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_nvalues[0], &tmpval ); - mod->sml_nvalues[1].bv_len = 0; - mod->sml_nvalues[1].bv_val = NULL; - assert( mod->sml_nvalues[0].bv_val ); - *modtail = mod; - modtail = &mod->sml_next; - } - - if( si->lastmod == LASTMOD_GEN ) { - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_type.bv_val = NULL; - mod->sml_desc = slap_schema.si_ad_creatorsName; - mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], &name ); - mod->sml_values[1].bv_len = 0; - mod->sml_values[1].bv_val = NULL; - assert( mod->sml_values[0].bv_val ); - mod->sml_nvalues = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_nvalues[0], &nname ); - mod->sml_nvalues[1].bv_len = 0; - mod->sml_nvalues[1].bv_val = NULL; - assert( mod->sml_nvalues[0].bv_val ); - *modtail = mod; - modtail = &mod->sml_next; - - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_type.bv_val = NULL; - mod->sml_desc = slap_schema.si_ad_createTimestamp; - mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], ×tamp ); - mod->sml_values[1].bv_len = 0; - mod->sml_values[1].bv_val = NULL; - assert( mod->sml_values[0].bv_val ); - mod->sml_nvalues = NULL; - *modtail = mod; - modtail = &mod->sml_next; - } - } - - if( si->lastmod == LASTMOD_GEN ) { - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_type.bv_val = NULL; - mod->sml_desc = slap_schema.si_ad_entryCSN; - mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], &csn ); - mod->sml_values[1].bv_len = 0; - mod->sml_values[1].bv_val = NULL; - assert( mod->sml_values[0].bv_val ); - mod->sml_nvalues = NULL; - *modtail = mod; - modtail = &mod->sml_next; - - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_type.bv_val = NULL; - mod->sml_desc = slap_schema.si_ad_modifiersName; - mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], &name ); - mod->sml_values[1].bv_len = 0; - mod->sml_values[1].bv_val = NULL; - assert( mod->sml_values[0].bv_val ); - mod->sml_nvalues = - (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_nvalues[0], &nname ); - mod->sml_nvalues[1].bv_len = 0; - mod->sml_nvalues[1].bv_val = NULL; - assert( mod->sml_nvalues[0].bv_val ); - *modtail = mod; - modtail = &mod->sml_next; - - mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); - mod->sml_op = mop; - mod->sml_type.bv_val = NULL; - mod->sml_desc = slap_schema.si_ad_modifyTimestamp; - mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod->sml_values[0], ×tamp ); - mod->sml_values[1].bv_len = 0; - mod->sml_values[1].bv_val = NULL; - assert( mod->sml_values[0].bv_val ); - mod->sml_nvalues = NULL; - *modtail = mod; - modtail = &mod->sml_next; - } - - *modtail = NULL; - return LDAP_SUCCESS; + mod->sml_type.bv_val = NULL; + mod->sml_desc = slap_schema.si_ad_createTimestamp; + mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_values[0], ×tamp ); + mod->sml_values[1].bv_len = 0; + mod->sml_values[1].bv_val = NULL; + assert( mod->sml_values[0].bv_val ); + mod->sml_nvalues = NULL; + *modtail = mod; + modtail = &mod->sml_next; + } + } + + if( si->lastmod == LASTMOD_GEN ) { + mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); + mod->sml_op = mop; + mod->sml_type.bv_val = NULL; + mod->sml_desc = slap_schema.si_ad_entryCSN; + mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_values[0], &csn ); + mod->sml_values[1].bv_len = 0; + mod->sml_values[1].bv_val = NULL; + assert( mod->sml_values[0].bv_val ); + mod->sml_nvalues = NULL; + *modtail = mod; + modtail = &mod->sml_next; + + mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); + mod->sml_op = mop; + mod->sml_type.bv_val = NULL; + mod->sml_desc = slap_schema.si_ad_modifiersName; + mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_values[0], &name ); + mod->sml_values[1].bv_len = 0; + mod->sml_values[1].bv_val = NULL; + assert( mod->sml_values[0].bv_val ); + mod->sml_nvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_nvalues[0], &nname ); + mod->sml_nvalues[1].bv_len = 0; + mod->sml_nvalues[1].bv_val = NULL; + assert( mod->sml_nvalues[0].bv_val ); + *modtail = mod; + modtail = &mod->sml_next; + + mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); + mod->sml_op = mop; + mod->sml_type.bv_val = NULL; + mod->sml_desc = slap_schema.si_ad_modifyTimestamp; + mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); + ber_dupbv( &mod->sml_values[0], ×tamp ); + mod->sml_values[1].bv_len = 0; + mod->sml_values[1].bv_val = NULL; + assert( mod->sml_values[0].bv_val ); + mod->sml_nvalues = NULL; + *modtail = mod; + modtail = &mod->sml_next; + } + + *modtail = NULL; + return LDAP_SUCCESS; } static int slap_mods2entry_syncrepl( + syncinfo_t *si, Modifications *mods, Entry **e, int repl_user, @@ -1869,6 +1952,21 @@ cookie_callback( return LDAP_SUCCESS; } +static int +dn_callback( + Operation* op, + SlapReply* rs +) +{ + syncinfo_t *si = op->o_callback->sc_private; + + if ( rs->sr_type == REP_SEARCH ) { + si->syncUUID_ndn = &rs->sr_entry->e_nname; + } + + return LDAP_SUCCESS; +} + static int nonpresent_callback( Operation* op, @@ -1881,6 +1979,7 @@ nonpresent_callback( struct berval* present_uuid = NULL; slap_callback cb; SlapReply rs_cb = {REP_RESULT}; + struct nonpresent_entry *np_entry; if ( rs->sr_type == REP_RESULT ) { count = avl_free( si->presentlist, avl_ber_bvfree ); @@ -1891,17 +1990,14 @@ nonpresent_callback( if ( a == NULL ) return 0; - present_uuid = avl_find( si->presentlist, - &a->a_vals[0], syncuuid_cmp ); - + present_uuid = avl_find( si->presentlist, &a->a_vals[0], syncuuid_cmp ); + if ( present_uuid == NULL ) { - op->o_tag = LDAP_REQ_DELETE; - op->o_callback = &cb; - cb.sc_response = null_callback; - cb.sc_private = si; - op->o_req_dn = rs->sr_entry->e_name; - op->o_req_ndn = rs->sr_entry->e_nname; - op->o_bd->be_delete( op, &rs_cb ); + np_entry = (struct nonpresent_entry *) + ch_calloc( 1, sizeof( struct nonpresent_entry )); + np_entry->dn = ber_dupbv( NULL, &rs->sr_entry->e_name ); + np_entry->ndn = ber_dupbv( NULL, &rs->sr_entry->e_nname ); + LDAP_LIST_INSERT_HEAD( &si->nonpresentlist, np_entry, np_link ); } else { avl_delete( &si->presentlist, &a->a_vals[0], syncuuid_cmp ); @@ -1919,11 +2015,12 @@ null_callback( SlapReply* rs ) { + syncinfo_t *si = op->o_callback->sc_private; + if ( rs->sr_err != LDAP_SUCCESS && - rs->sr_err != LDAP_REFERRAL && - rs->sr_err != LDAP_ALREADY_EXISTS && - rs->sr_err != LDAP_NO_SUCH_OBJECT && - rs->sr_err != DB_NOTFOUND ) { + rs->sr_err != LDAP_REFERRAL && + rs->sr_err != LDAP_ALREADY_EXISTS && + rs->sr_err != LDAP_NO_SUCH_OBJECT ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "null_callback : error code 0x%x\n", @@ -1931,10 +2028,50 @@ null_callback( #else Debug( LDAP_DEBUG_ANY, "null_callback : error code 0x%x\n", - rs->sr_err, 0, 0 ); + rs->sr_err, 0, 0 ); #endif } return LDAP_SUCCESS; } + +char ** +str2clist( char **out, char *in, const char *brkstr ) +{ + char *str; + char *s; + char *lasts; + int i, j; + const char *text; + char **new; + + /* find last element in list */ + for (i = 0; out && out[i]; i++); + + /* protect the input string from strtok */ + str = ch_strdup( in ); + + /* Count words in string */ + j=1; + for ( s = str; *s; s++ ) { + if ( strchr( brkstr, *s ) != NULL ) { + j++; + } + } + + out = ch_realloc( out, ( i + j + 1 ) * sizeof( char * ) ); + new = out + i; + for ( s = ldap_pvt_strtok( str, brkstr, &lasts ); + s != NULL; + s = ldap_pvt_strtok( NULL, brkstr, &lasts ) ) + { + *new = ch_strdup( s ); + new++; + } + + *new = NULL; + free( str ); + return( out ); +} + #endif