diff --git a/include/ldap.h b/include/ldap.h index 10bad7f894..73b8efe152 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -200,6 +200,7 @@ typedef struct ldapcontrol { #ifdef LDAP_DEVEL #define LDAP_CLIENT_UPDATE 1 #define LDAP_SYNC 2 +#define LDAP_SYNCREPL 1 #endif #ifdef LDAP_CLIENT_UPDATE diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 8266bcb5c1..45f3ccad9c 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -18,9 +18,9 @@ SRCS = main.c globals.c config.c daemon.c \ repl.c lock.c controls.c extended.c kerberos.c passwd.c \ schema.c schema_check.c schema_init.c schema_prep.c \ schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \ - oidm.c starttls.c index.c sets.c referral.c \ - root_dse.c sasl.c module.c mra.c mods.c sl_malloc.c \ - limits.c backglue.c operational.c matchedValues.c cancel.c \ + oidm.c starttls.c index.c sets.c referral.c root_dse.c \ + sasl.c module.c mra.c mods.c sl_malloc.c limits.c \ + backglue.c operational.c matchedValues.c cancel.c syncrepl.c \ $(@PLAT@_SRCS) OBJS = main.o globals.o config.o daemon.o \ @@ -32,9 +32,9 @@ OBJS = main.o globals.o config.o daemon.o \ repl.o lock.o controls.o extended.o kerberos.o passwd.o \ schema.o schema_check.o schema_init.o schema_prep.o \ schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \ - oidm.o starttls.o index.o sets.o referral.o \ - root_dse.o sasl.o module.o mra.o mods.o sl_malloc.o \ - limits.o backglue.o operational.o matchedValues.o cancel.o \ + oidm.o starttls.o index.o sets.o referral.o root_dse.o \ + sasl.o module.o mra.o mods.o sl_malloc.o limits.o \ + backglue.o operational.o matchedValues.o cancel.o syncrepl.o \ $(@PLAT@_OBJS) LDAP_INCDIR= ../../include -I$(srcdir)/slapi diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 1ff6ed0cc6..d63b92c49d 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -243,7 +243,12 @@ do_add( Operation *op, SlapReply *rs ) if ( op->o_bd->be_add ) { /* do the update here */ int repl_user = be_isupdate(op->o_bd, &op->o_ndn ); -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo && + ( !op->o_bd->be_update_ndn.bv_len || repl_user )) +#elif defined(LDAP_SYNCREPL) && defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo ) /* LDAP_SYNCREPL overrides MM */ +#elif !defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) #endif { @@ -252,7 +257,7 @@ do_add( Operation *op, SlapReply *rs ) size_t textlen = sizeof textbuf; rs->sr_err = slap_mods_check( modlist, update, &rs->sr_text, - textbuf, textlen, NULL ); + textbuf, textlen, NULL ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); @@ -306,9 +311,9 @@ do_add( Operation *op, SlapReply *rs ) e = NULL; } -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) || !defined(SLAPD_MULTIMASTER) } else { - BerVarray defref; + BerVarray defref = NULL; #ifdef LDAP_SLAPI /* * SLAPI_ADD_ENTRY will be empty, but this may be acceptable @@ -321,8 +326,16 @@ do_add( Operation *op, SlapReply *rs ) } #endif /* LDAP_SLAPI */ - defref = op->o_bd->be_update_refs - ? op->o_bd->be_update_refs : default_referral; +#ifdef LDAP_SYNCREPL + if ( op->o_bd->syncinfo ) { + defref = op->o_bd->syncinfo->master_bv; + } else +#endif + { + defref = op->o_bd->be_update_refs + ? op->o_bd->be_update_refs : default_referral; + } + if ( defref != NULL ) { rs->sr_ref = referral_rewrite( defref, NULL, &e->e_name, LDAP_SCOPE_DEFAULT ); diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index bd789d43cb..64bc55c547 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -14,6 +14,10 @@ LDAP_BEGIN_DECL +#ifdef LDAP_SYNCREPL +#define BDB_SUBENTRIES 1 +#endif + #define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX #define DN_ONE_PREFIX '%' #define DN_SUBTREE_PREFIX '@' diff --git a/servers/slapd/config.c b/servers/slapd/config.c index 2c69d43a67..869db21541 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -2727,8 +2727,9 @@ add_syncrepl( #define GOT_TYPE 0x0200 #define GOT_INTERVAL 0x0400 #define GOT_LASTMOD 0x0800 +#define GOT_UPDATEDN 0x1000 -#define GOT_ALL 0x0FFF +#define GOT_ALL 0x1FFF static int parse_syncrepl_line( @@ -2772,6 +2773,11 @@ parse_syncrepl_line( si->masterport = 0; } si->mastername = strdup( val ); + si->master_bv = (BerVarray) ch_calloc( 2, sizeof (struct berval )); + ber_str2bv( si->masteruri, strlen(si->masteruri), 0, + &si->master_bv[0] ); + si->master_bv[1].bv_len = 0; + si->master_bv[1].bv_val = NULL; gots |= GOT_HOST; } else if ( !strncasecmp( cargv[ i ], TLSSTR, sizeof( TLSSTR ) - 1 ) ) { val = cargv[ i ] + sizeof( TLSSTR ); @@ -2781,7 +2787,18 @@ parse_syncrepl_line( si->tls = TLS_ON; } } else if ( !strncasecmp( cargv[ i ], - "binddn", sizeof( BINDDNSTR ) - 1 ) ) { + UPDATEDNSTR, sizeof( UPDATEDNSTR ) - 1 ) ) { + char *str; + struct berval updatedn = {0, NULL}; + val = cargv[ i ] + sizeof( UPDATEDNSTR ); + str = strdup( val ); + ber_str2bv( str, strlen(str), 1, &updatedn ); + dnNormalize( 0, NULL, NULL, &updatedn, &si->updatedn, NULL ); + ch_free( str ); + ch_free( updatedn.bv_val ); + gots |= GOT_UPDATEDN; + } else if ( !strncasecmp( cargv[ i ], + BINDDNSTR, sizeof( BINDDNSTR ) - 1 ) ) { val = cargv[ i ] + sizeof( BINDDNSTR ); si->binddn = strdup( val ); gots |= GOT_DN; @@ -2934,6 +2951,7 @@ parse_syncrepl_line( } else if ( !strncasecmp( val, "refreshAndPersist", sizeof( "refreshAndPersist" ) - 1 )) { gots |= GOT_INTERVAL; si->type = LDAP_SYNC_REFRESH_AND_PERSIST; + si->interval = 0; } else { fprintf( stderr, "Error: parse_syncrepl_line: " "unknown sync type \"%s\"\n", val); @@ -2943,8 +2961,11 @@ parse_syncrepl_line( INTERVALSTR, sizeof( INTERVALSTR ) - 1 ) ) { val = cargv[ i ] + sizeof( INTERVALSTR ); gots |= GOT_INTERVAL; - si->interval = atoi( val ); - if ( si->interval <= 0 ) { + if ( gots & GOT_TYPE && si->type == LDAP_SYNC_REFRESH_AND_PERSIST ) + si->interval = 0; + else + si->interval = atoi( val ); + if ( si->interval < 0 ) { fprintf( stderr, "Error: parse_syncrepl_line: " "invalid interval \"%d\"\n", si->interval); return 1; diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c index 30e1294a69..6f39f82e71 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -190,7 +190,11 @@ do_delete( if ( op->o_bd->be_delete ) { /* do the update here */ int repl_user = be_isupdate( op->o_bd, &op->o_ndn ); -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo && ( !op->o_bd->be_update_ndn.bv_len || repl_user )) +#elif defined(LDAP_SYNCREPL) && defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo ) /* LDAP_SYNCREPL overrides MM */ +#elif !defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) #endif { @@ -202,12 +206,20 @@ do_delete( replog( op ); } } -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) || !defined(SLAPD_MULTIMASTER) } else { - BerVarray defref = op->o_bd->be_update_refs - ? op->o_bd->be_update_refs : default_referral; + BerVarray defref = NULL; +#ifdef LDAP_SYNCREPL + if ( op->o_bd->syncinfo ) { + defref = op->o_bd->syncinfo->master_bv; + } else +#endif + { + defref = op->o_bd->be_update_refs + ? op->o_bd->be_update_refs : default_referral; + } if ( defref != NULL ) { - rs->sr_ref = referral_rewrite( default_referral, + rs->sr_ref = referral_rewrite( defref, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); if (!rs->sr_ref) rs->sr_ref = defref; rs->sr_err = LDAP_REFERRAL; diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index f8b1d7b872..1405ca9c72 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -391,10 +391,16 @@ do_modify( if ( op->o_bd->be_modify ) { /* do the update here */ int repl_user = be_isupdate( op->o_bd, &op->o_ndn ); -#ifndef SLAPD_MULTIMASTER + /* Multimaster slapd does not have to check for replicator dn * because it accepts each modify request */ +#if defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo && + ( !op->o_bd->be_update_ndn.bv_len || repl_user )) +#elif defined(LDAP_SYNCREPL) && defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo ) /* LDAP_SYNCREPL overrides MM */ +#elif !defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) #endif { @@ -436,11 +442,19 @@ do_modify( replog( op ); } -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) || !defined(SLAPD_MULTIMASTER) /* send a referral */ } else { - BerVarray defref = op->o_bd->be_update_refs - ? op->o_bd->be_update_refs : default_referral; + BerVarray defref = NULL; +#ifdef LDAP_SYNCREPL + if ( op->o_bd->syncinfo ) { + defref = op->o_bd->syncinfo->master_bv; + } else +#endif + { + defref = op->o_bd->be_update_refs + ? op->o_bd->be_update_refs : default_referral; + } if ( defref != NULL ) { rs->sr_ref = referral_rewrite( defref, NULL, &op->o_req_dn, diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index 6babf195a6..3f542adb4b 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -353,7 +353,12 @@ do_modrdn( if ( op->o_bd->be_modrdn ) { /* do the update here */ int repl_user = be_isupdate( op->o_bd, &op->o_ndn ); -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo && + ( !op->o_bd->be_update_ndn.bv_len || repl_user )) +#elif defined(LDAP_SYNCREPL) && defined(SLAPD_MULTIMASTER) + if ( !op->o_bd->syncinfo ) /* LDAP_SYNCREPL overrides MM */ +#elif !defined(LDAP_SYNCREPL) && !defined(SLAPD_MULTIMASTER) if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) #endif { @@ -365,10 +370,18 @@ do_modrdn( ) { replog( op ); } -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) || !defined(SLAPD_MULTIMASTER) } else { - BerVarray defref = op->o_bd->be_update_refs - ? op->o_bd->be_update_refs : default_referral; + BerVarray defref = NULL; +#ifdef LDAP_SYNCREPL + if ( op->o_bd->syncinfo ) { + defref = op->o_bd->syncinfo->master_bv; + } else +#endif + { + defref = op->o_bd->be_update_refs + ? op->o_bd->be_update_refs : default_referral; + } if ( defref != NULL ) { rs->sr_ref = referral_rewrite( defref, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); diff --git a/servers/slapd/passwd.c b/servers/slapd/passwd.c index c2e3275a43..b10bbe4b33 100644 --- a/servers/slapd/passwd.c +++ b/servers/slapd/passwd.c @@ -52,13 +52,22 @@ int passwd_extop( rs->sr_err = LDAP_OTHER; #endif -#ifndef SLAPD_MULTIMASTER +#if defined(LDAP_SYNCREPL) || !defined(SLAPD_MULTIMASTER) /* This does not apply to multi-master case */ } else if( op->o_bd->be_update_ndn.bv_len ) { /* we SHOULD return a referral in this case */ - rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs, - NULL, NULL, LDAP_SCOPE_DEFAULT ); - rs->sr_err = LDAP_REFERRAL; + BerVarray defref = NULL; +#ifdef LDAP_SYNCREPL + if ( op->o_bd->syncinfo ) { + defref = op->o_bd->syncinfo->master_bv; + } else +#endif + { + defref = referral_rewrite( op->o_bd->be_update_refs, + NULL, NULL, LDAP_SCOPE_DEFAULT ); + } + rs->sr_ref = defref; + rs->sr_err = LDAP_REFERRAL; #endif /* !SLAPD_MULTIMASTER */ } else { diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 918e193e96..eb4690bb34 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1286,9 +1286,11 @@ typedef struct syncinfo_s { void *ctx; int id; char *masteruri; + struct berval *master_bv; char *mastername; int masterport; int type; + struct berval updatedn; char *binddn; int bindmethod; char *passwd; @@ -1298,7 +1300,7 @@ typedef struct syncinfo_s { char *authzId; char *srvtab; char *saslmech; - int interval; + time_t interval; char *base; int scope; int deref; @@ -1327,6 +1329,7 @@ typedef struct syncinfo_s { #define IDSTR "id" #define MASTERSTR "master" #define SUFFIXSTR "suffix" +#define UPDATEDNSTR "updatedn" #define BINDDNSTR "binddn" #define BINDMETHSTR "bindmethod" #define SIMPLESTR "simple" diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index a89fe518cf..bebbef620e 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -320,8 +320,8 @@ do_syncrepl( op.o_tmpmemctx = NULL; /* FIXME : to use per-thread mem context */ 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;