The branch, master has been updated via 25dd9fa s4-drs: return DRSUAPI_EXOP_ERR_SUCCESS in extended_ret via 611cd51 s4-drs: Hanlde extended operations only once via d08439d s4-dreplsrv: fix 'dn' for partition object being created via 750300a s4-drs-fsmo: try to dispatch ops in queue as soon as possible via 62b5274 s4/fsmo: Added python tests for schema master transfer op via c34cae8 s4-fsmo: update FSMO changes for recent IRPC work via ab01ce6 s4/drs: update repsFrom only when we are not in getncchanges extended op via 36e663a s4-ldap: Added support for FSMO role transfer via LDAP by modify on rootDSE via 5ba2858 s4-rpc: Added handling of fsmo role transfer to GetNCChanges via 0229ac4 s4-irpc: Added internal rpc call DREPL_TAKEFSMOROLE via 657b703 s4-drs: Implementation of GetNCChanges extended op 6 - fsmo role transfer via c8794d2 s4-drs: Refactored drepl_service and send_ridalloc_request so that the structures can be used for other extended ops from 19a3633 s4/torture: use time_mono for deltas in lock test
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 25dd9fae66f4dd65692b8161da499aaca104f434 Author: Kamen Mazdrashki <kame...@samba.org> Date: Fri Sep 10 02:05:27 2010 +0300 s4-drs: return DRSUAPI_EXOP_ERR_SUCCESS in extended_ret in case we are handling extended operation. It seems that windows accept both DRSUAPI_EXOP_ERR_SUCCESS and DRSUAPI_EXOP_ERR_NONE, but Samba is a little bit more picky on this. commit 611cd51096a8de8fdf43d0c9b639314bd7ebd2c2 Author: Kamen Mazdrashki <kame...@samba.org> Date: Fri Sep 10 02:02:56 2010 +0300 s4-drs: Hanlde extended operations only once Most of extended operations I know of work like: 1. do extended operation 2. collect a set of objects to return and start replication cycle 3. continue returning object as we have no more to give This way we ensure we are doing 1. only once commit d08439d42b4a04279e74bc3625cb672eb22007fe Author: Kamen Mazdrashki <kame...@samba.org> Date: Fri Sep 10 01:59:21 2010 +0300 s4-dreplsrv: fix 'dn' for partition object being created commit 750300aedf0bd59b704e222f82ff1d114d2b5da7 Author: Kamen Mazdrashki <kame...@samba.org> Date: Fri Sep 10 01:58:07 2010 +0300 s4-drs-fsmo: try to dispatch ops in queue as soon as possible In most cases this will transfer of schema master role to look like a synchronous operation. commit 62b52748273b6d02d9acb3efe4956db4735b4322 Author: Anatoliy Atanasov <anatoliy.atana...@postpath.com> Date: Wed Sep 8 10:25:54 2010 +0300 s4/fsmo: Added python tests for schema master transfer op commit c34cae81fee5e3b68746f9da97496bf056ff9d55 Author: Andrew Tridgell <tri...@samba.org> Date: Thu Sep 9 16:16:05 2010 +1000 s4-fsmo: update FSMO changes for recent IRPC work the IRPC API has changed Pair-Programmed-With: Andrew Bartlett <abart...@samba.org> commit ab01ce6e963b8251bdd3200bcfcf2a37068d3319 Author: Anatoliy Atanasov <anatoliy.atana...@postpath.com> Date: Thu Aug 26 11:19:24 2010 +0300 s4/drs: update repsFrom only when we are not in getncchanges extended op commit 36e663ad712c062805f6b17c45c2ae7fa5141dd9 Author: Nadezhda Ivanova <nivan...@samba.org> Date: Thu Aug 26 11:09:58 2010 +0300 s4-ldap: Added support for FSMO role transfer via LDAP by modify on rootDSE GetNCChanges with the corresponding extended operation is initiated and added to the queue when a modify request is received on becomeSchemaMaster, becomeRidMaster, becomeNamingMaster, becomeInfrastructureMaster and becomePDC attributes in rootDSE. commit 5ba2858b0271feecf3f7bc5bee7577d0e181563d Author: Nadezhda Ivanova <nivan...@samba.org> Date: Thu Aug 26 10:59:02 2010 +0300 s4-rpc: Added handling of fsmo role transfer to GetNCChanges This adds support for DRSUAPI_EXOP_FSMO_REQ_ROLE, DRSUAPI_EXOP_FSMO_RID_REQ_ROLE and DRSUAPI_EXOP_FSMO_REQ_PDC. Developed in collaboration with Anatoliy Atanasov <anatoliy.atana...@postpath.com> commit 0229ac455dbe3125d72c0371d03c592b460526f3 Author: Nadezhda Ivanova <nivan...@samba.org> Date: Wed Aug 25 00:26:28 2010 +0300 s4-irpc: Added internal rpc call DREPL_TAKEFSMOROLE It schedules a getncchanges with extended op 6, to be used when a modify request on becomeROLEMaster atteibute on rootDSE is received. commit 657b7039c38e97af9dbacafb5ab7a5966f52eaea Author: Nadezhda Ivanova <nivan...@samba.org> Date: Wed Aug 25 00:22:16 2010 +0300 s4-drs: Implementation of GetNCChanges extended op 6 - fsmo role transfer Basically the candidate owner makes a getncchanges call with extended op 6 when they want to become the new owner. The current owner then updates the corresponding fSMORoleOwner attribute in its database with the new owner, and replicates the change to the candidate, who then becomes the owner. The patch was made in cooperation with Anatoliy Atanasov <anatoliy.atana...@postpath.com> who kindly helped to debug it. commit c8794d2625e81b8c11dec7726a42e632854472af Author: Nadezhda Ivanova <nivan...@samba.org> Date: Tue Aug 24 23:01:43 2010 +0300 s4-drs: Refactored drepl_service and send_ridalloc_request so that the structures can be used for other extended ops ----------------------------------------------------------------------- Summary of changes: source4/dsdb/config.mk | 3 +- source4/dsdb/repl/drepl_fsmo.c | 159 +++++++++++++++++++++++++++ source4/dsdb/repl/drepl_out_helpers.c | 8 +- source4/dsdb/repl/drepl_ridalloc.c | 83 ++++++++++----- source4/dsdb/repl/drepl_service.c | 11 ++- source4/dsdb/repl/drepl_service.h | 4 +- source4/dsdb/samdb/ldb_modules/rootdse.c | 53 +++++++++- source4/dsdb/wscript_build | 2 +- source4/librpc/idl/irpc.idl | 16 +++ source4/rpc_server/drsuapi/getncchanges.c | 170 ++++++++++++++++++++++++----- source4/selftest/tests.sh | 1 + source4/torture/drs/python/fsmo.py | 152 ++++++++++++++++++++++++++ 12 files changed, 597 insertions(+), 65 deletions(-) create mode 100644 source4/dsdb/repl/drepl_fsmo.c create mode 100644 source4/torture/drs/python/fsmo.py Changeset truncated at 500 lines: diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk index 1ab0cb2..e12193d 100644 --- a/source4/dsdb/config.mk +++ b/source4/dsdb/config.mk @@ -68,7 +68,8 @@ DREPL_SRV_OBJ_FILES = $(addprefix $(dsdbsrcdir)/repl/, \ drepl_out_pull.o \ drepl_out_helpers.o \ drepl_notify.o \ - drepl_ridalloc.o) + drepl_ridalloc.o \ + drepl_fsmo.o) $(eval $(call proto_header_template,$(dsdbsrcdir)/repl/drepl_service_proto.h,$(DREPL_SRV_OBJ_FILES:.o=.c))) diff --git a/source4/dsdb/repl/drepl_fsmo.c b/source4/dsdb/repl/drepl_fsmo.c new file mode 100644 index 0000000..941ad67 --- /dev/null +++ b/source4/dsdb/repl/drepl_fsmo.c @@ -0,0 +1,159 @@ +/* + Unix SMB/CIFS mplementation. + + DSDB replication service - FSMO role change + + Copyright (C) Nadezhda Ivanova 2010 + Copyright (C) Andrew Tridgell 2010 + Copyright (C) Andrew Bartlett 2010 + + based on drepl_ridalloc.c + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "includes.h" +#include "dsdb/samdb/samdb.h" +#include "smbd/service.h" +#include "dsdb/repl/drepl_service.h" +#include "param/param.h" +#include "lib/messaging/irpc.h" +#include "librpc/gen_ndr/ndr_irpc.h" + +static void drepl_role_callback(struct dreplsrv_service *service, + WERROR werr, + enum drsuapi_DsExtendedError ext_err) +{ + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,(__location__ ": Failed role transfer - %s - extended_ret[0x%X]\n", + win_errstr(werr), ext_err)); + } else { + DEBUG(0,(__location__ ": Successful role transfer\n")); + } + talloc_free(service->ncchanges_extended.role_owner_source_dsa); + service->ncchanges_extended.role_owner_source_dsa = NULL; + service->ncchanges_extended.in_progress = false; +} + +static bool fsmo_master_cmp(struct ldb_dn *ntds_dn, struct ldb_dn *fsmo_role_dn) +{ + if (ldb_dn_compare(ntds_dn, fsmo_role_dn) == 0) { + DEBUG(0,("\nWe are the FSMO master.\n")); + return true; + } + return false; +} + +/* + see which role is we are asked to assume, initialize data and send request + */ +WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service, + uint32_t role) +{ + struct ldb_dn *role_owner_dn, *fsmo_role_dn, *ntds_dn; + TALLOC_CTX *tmp_ctx = talloc_new(service); + struct ldb_context *ldb = service->samdb; + int ret; + uint64_t alloc_pool = 0; + + if (service->ncchanges_extended.in_progress) { + talloc_free(tmp_ctx); + return WERR_OK; + } + + ntds_dn = samdb_ntds_settings_dn(ldb); + if (!ntds_dn) { + return WERR_DS_DRA_INTERNAL_ERROR; + } + /* work out who is the current owner */ + switch (role) { + case DREPL_NAMING_MASTER: + role_owner_dn = samdb_partitions_dn(ldb, tmp_ctx), + ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + case DREPL_INFRASTRUCTURE_MASTER: + role_owner_dn = samdb_infrastructure_dn(ldb, tmp_ctx); + ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + case DREPL_RID_MASTER: + ret = samdb_rid_manager_dn(ldb, tmp_ctx, &role_owner_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + /* find the DN of the RID Manager */ + ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + case DREPL_SCHEMA_MASTER: + role_owner_dn = ldb_get_schema_basedn(ldb); + ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + if (!fsmo_master_cmp(ntds_dn, fsmo_role_dn)) { + WERROR werr; + werr = drepl_request_extended_op(service, + role_owner_dn, + fsmo_role_dn, + DRSUAPI_EXOP_FSMO_REQ_ROLE, + alloc_pool, + drepl_role_callback); + if (W_ERROR_IS_OK(werr)) { + dreplsrv_run_pending_ops(service); + } else { + DEBUG(0,("%s: drepl_request_extended_op() failed with %s", + __FUNCTION__, win_errstr(werr))); + } + return werr; + } + break; + case DREPL_PDC_MASTER: + role_owner_dn = ldb_get_default_basedn(ldb); + ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s", + ldb_errstring(ldb))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + break; + default: + return WERR_DS_DRA_INTERNAL_ERROR; + } + return WERR_OK; +} diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c index 8ce9d0f..8ffa832 100644 --- a/source4/dsdb/repl/drepl_out_helpers.c +++ b/source4/dsdb/repl/drepl_out_helpers.c @@ -522,10 +522,10 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req tevent_req_nterror(req, nt_status); return; } - - /* if it applied fine, we need to update the highwatermark */ - *state->op->source_dsa->repsFrom1 = rf1; - + if (state->op->extended_op == DRSUAPI_EXOP_NONE) { + /* if it applied fine, we need to update the highwatermark */ + *state->op->source_dsa->repsFrom1 = rf1; + } /* * TODO: update our uptodatevector! */ diff --git a/source4/dsdb/repl/drepl_ridalloc.c b/source4/dsdb/repl/drepl_ridalloc.c index 6d4b0da..e394071 100644 --- a/source4/dsdb/repl/drepl_ridalloc.c +++ b/source4/dsdb/repl/drepl_ridalloc.c @@ -32,10 +32,11 @@ /* - create the RID manager source dsa structure + create the role owner source dsa structure */ -static WERROR drepl_create_rid_manager_source_dsa(struct dreplsrv_service *service, - struct ldb_dn *rid_manager_dn, struct ldb_dn *fsmo_role_dn) + +WERROR drepl_create_role_owner_source_dsa(struct dreplsrv_service *service, + struct ldb_dn *role_owner_dn, struct ldb_dn *fsmo_role_dn) { struct dreplsrv_partition_source_dsa *sdsa; struct ldb_context *ldb = service->samdb; @@ -51,12 +52,20 @@ static WERROR drepl_create_rid_manager_source_dsa(struct dreplsrv_service *servi return WERR_NOMEM; } - sdsa->partition->dn = ldb_get_default_basedn(ldb); - sdsa->partition->nc.dn = ldb_dn_alloc_linearized(sdsa->partition, rid_manager_dn); - ret = dsdb_find_guid_by_dn(ldb, rid_manager_dn, &sdsa->partition->nc.guid); + sdsa->partition->dn = ldb_dn_copy(sdsa->partition, role_owner_dn); + if (!sdsa->partition->dn) { + talloc_free(sdsa); + return WERR_NOMEM; + } + sdsa->partition->nc.dn = ldb_dn_alloc_linearized(sdsa->partition, role_owner_dn); + if (!sdsa->partition->nc.dn) { + talloc_free(sdsa); + return WERR_NOMEM; + } + ret = dsdb_find_guid_by_dn(ldb, role_owner_dn, &sdsa->partition->nc.guid); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed to find GUID for %s\n", - ldb_dn_get_linearized(rid_manager_dn))); + ldb_dn_get_linearized(role_owner_dn))); talloc_free(sdsa); return WERR_DS_DRA_INTERNAL_ERROR; } @@ -88,16 +97,44 @@ static WERROR drepl_create_rid_manager_source_dsa(struct dreplsrv_service *servi werr = dreplsrv_out_connection_attach(service, sdsa->repsFrom1, &sdsa->conn); if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,(__location__ ": Failed to attach to RID manager connection\n")); + DEBUG(0,(__location__ ": Failed to attach connection to %s\n", + ldb_dn_get_linearized(role_owner_dn))); talloc_free(sdsa); return werr; } - service->ridalloc.rid_manager_source_dsa = sdsa; + service->ncchanges_extended.role_owner_source_dsa = sdsa; return WERR_OK; } /* + schedule a getncchanges request to the role owner for an extended operation + */ +WERROR drepl_request_extended_op(struct dreplsrv_service *service, + struct ldb_dn *role_owner_dn, + struct ldb_dn *fsmo_role_dn, + enum drsuapi_DsExtendedOperation extended_op, + uint64_t alloc_pool, + dreplsrv_fsmo_callback_t callback) +{ + WERROR werr; + + if (service->ncchanges_extended.role_owner_source_dsa == NULL) { + /* we need to establish a connection to the RID + Manager */ + werr = drepl_create_role_owner_source_dsa(service, role_owner_dn, fsmo_role_dn); + W_ERROR_NOT_OK_RETURN(werr); + } + + service->ncchanges_extended.in_progress = true; + + werr = dreplsrv_schedule_partition_pull_source(service, service->ncchanges_extended.role_owner_source_dsa, + extended_op, alloc_pool, + callback, NULL); + return werr; +} + +/* called when a rid allocation request has completed */ static void drepl_new_rid_pool_callback(struct dreplsrv_service *service, @@ -113,10 +150,10 @@ static void drepl_new_rid_pool_callback(struct dreplsrv_service *service, } /* don't keep the connection open to the RID Manager */ - talloc_free(service->ridalloc.rid_manager_source_dsa); - service->ridalloc.rid_manager_source_dsa = NULL; + talloc_free(service->ncchanges_extended.role_owner_source_dsa); + service->ncchanges_extended.role_owner_source_dsa = NULL; - service->ridalloc.in_progress = false; + service->ncchanges_extended.in_progress = false; } /* @@ -127,20 +164,12 @@ static WERROR drepl_request_new_rid_pool(struct dreplsrv_service *service, struct ldb_dn *rid_manager_dn, struct ldb_dn *fsmo_role_dn, uint64_t alloc_pool) { - WERROR werr; - - if (service->ridalloc.rid_manager_source_dsa == NULL) { - /* we need to establish a connection to the RID - Manager */ - werr = drepl_create_rid_manager_source_dsa(service, rid_manager_dn, fsmo_role_dn); - W_ERROR_NOT_OK_RETURN(werr); - } - - service->ridalloc.in_progress = true; - - werr = dreplsrv_schedule_partition_pull_source(service, service->ridalloc.rid_manager_source_dsa, - DRSUAPI_EXOP_FSMO_RID_ALLOC, alloc_pool, - drepl_new_rid_pool_callback, NULL); + WERROR werr = drepl_request_extended_op(service, + rid_manager_dn, + fsmo_role_dn, + DRSUAPI_EXOP_FSMO_RID_ALLOC, + alloc_pool, + drepl_new_rid_pool_callback); return werr; } @@ -244,7 +273,7 @@ WERROR dreplsrv_ridalloc_check_rid_pool(struct dreplsrv_service *service) int ret; uint64_t alloc_pool; - if (service->ridalloc.in_progress) { + if (service->ncchanges_extended.in_progress) { talloc_free(tmp_ctx); return WERR_OK; } diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c index da0d9e5..1423827 100644 --- a/source4/dsdb/repl/drepl_service.c +++ b/source4/dsdb/repl/drepl_service.c @@ -74,7 +74,6 @@ static WERROR dreplsrv_connect_samdb(struct dreplsrv_service *service, struct lo if (!ntds_guid) { return WERR_DS_UNAVAILABLE; } - service->ntds_guid = *ntds_guid; bind_info28 = &service->bind_info28; @@ -343,6 +342,15 @@ static NTSTATUS dreplsrv_refresh(struct irpc_message *msg, return NT_STATUS_OK; } +static NTSTATUS drepl_take_FSMO_role(struct irpc_message *msg, + struct drepl_takeFSMORole *r) +{ + struct dreplsrv_service *service = talloc_get_type(msg->private_data, + struct dreplsrv_service); + r->out.result = werror_to_ntstatus(dreplsrv_fsmo_role_check(service, r->in.role)); + return NT_STATUS_OK; +} + /* startup the dsdb replicator service task */ @@ -432,6 +440,7 @@ static void dreplsrv_task_init(struct task_server *task) IRPC_REGISTER(task->msg_ctx, irpc, DREPLSRV_REFRESH, dreplsrv_refresh, service); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICASYNC, drepl_replica_sync, service); + IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TAKEFSMOROLE, drepl_take_FSMO_role, service); messaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid); } diff --git a/source4/dsdb/repl/drepl_service.h b/source4/dsdb/repl/drepl_service.h index 00fd3bf..dba9a37 100644 --- a/source4/dsdb/repl/drepl_service.h +++ b/source4/dsdb/repl/drepl_service.h @@ -218,8 +218,8 @@ struct dreplsrv_service { struct { bool in_progress; - struct dreplsrv_partition_source_dsa *rid_manager_source_dsa; - } ridalloc; + struct dreplsrv_partition_source_dsa *role_owner_source_dsa; + } ncchanges_extended; bool syncall_workaround; }; diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 0949b83..3397d60 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -30,6 +30,9 @@ #include "libcli/security/security.h" #include "librpc/ndr/libndr.h" #include "auth/auth.h" +#include "param/param.h" +#include "lib/messaging/irpc.h" +#include "librpc/gen_ndr/ndr_irpc_c.h" struct private_data { unsigned int num_controls; @@ -971,6 +974,40 @@ static int rootdse_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_NAMING_VIOLATION; } +static int rootdse_become_master(struct ldb_module *module, + struct ldb_request *req, + uint32_t role) +{ + struct drepl_takeFSMORole r; + struct messaging_context *msg; + struct ldb_context *ldb = ldb_module_get_ctx(module); + TALLOC_CTX *tmp_ctx = talloc_new(req); + struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm"); + NTSTATUS status_call, status_fn; + struct dcerpc_binding_handle *irpc_handle; + + msg = messaging_client_init(tmp_ctx, lpcfg_messaging_path(tmp_ctx, lp_ctx), + ldb_get_event_context(ldb)); + + irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg, + "dreplsrv", + &ndr_table_irpc); + if (irpc_handle == NULL) { + return ldb_oom(ldb); + } + r.in.role = role; + + status_call = dcerpc_drepl_takeFSMORole_r(irpc_handle, tmp_ctx, &r); + if (!NT_STATUS_IS_OK(status_call)) { + return LDB_ERR_OPERATIONS_ERROR; + } + status_fn = r.out.result; + if (!NT_STATUS_IS_OK(status_fn)) { + return LDB_ERR_OPERATIONS_ERROR; + } + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); +} + static int rootdse_modify(struct ldb_module *module, struct ldb_request *req) { struct ldb_context *ldb = ldb_module_get_ctx(module); @@ -989,7 +1026,21 @@ static int rootdse_modify(struct ldb_module *module, struct ldb_request *req) if (ldb_msg_find_element(req->op.mod.message, "schemaUpdateNow")) { return rootdse_schemaupdatenow(module, req); } - + if (ldb_msg_find_element(req->op.mod.message, "becomeDomainMaster")) { + return rootdse_become_master(module, req, DREPL_NAMING_MASTER); + } + if (ldb_msg_find_element(req->op.mod.message, "becomeInfrastructureMaster")) { + return rootdse_become_master(module, req, DREPL_INFRASTRUCTURE_MASTER); + } + if (ldb_msg_find_element(req->op.mod.message, "becomeRidMaster")) { + return rootdse_become_master(module, req, DREPL_RID_MASTER); + } + if (ldb_msg_find_element(req->op.mod.message, "becomeSchemaMaster")) { + return rootdse_become_master(module, req, DREPL_SCHEMA_MASTER); + } + if (ldb_msg_find_element(req->op.mod.message, "becomePdc")) { + return rootdse_become_master(module, req, DREPL_PDC_MASTER); + } if (ldb_msg_find_element(req->op.mod.message, "enableOptionalFeature")) { return rootdse_enableoptionalfeature(module, req); } diff --git a/source4/dsdb/wscript_build b/source4/dsdb/wscript_build index d3961f5..426b12d 100644 --- a/source4/dsdb/wscript_build +++ b/source4/dsdb/wscript_build @@ -25,7 +25,7 @@ bld.SAMBA_SUBSYSTEM('SAMDB_SCHEMA', bld.SAMBA_MODULE('DREPL_SRV', - source='repl/drepl_service.c repl/drepl_periodic.c repl/drepl_partitions.c repl/drepl_out_pull.c repl/drepl_out_helpers.c repl/drepl_notify.c repl/drepl_ridalloc.c', + source='repl/drepl_service.c repl/drepl_periodic.c repl/drepl_partitions.c repl/drepl_out_pull.c repl/drepl_out_helpers.c repl/drepl_notify.c repl/drepl_ridalloc.c repl/drepl_fsmo.c', autoproto='repl/drepl_service_proto.h', subsystem='service', init_function='server_service_drepl_init', diff --git a/source4/librpc/idl/irpc.idl b/source4/librpc/idl/irpc.idl index 35204db..2b88dc7 100644 --- a/source4/librpc/idl/irpc.idl +++ b/source4/librpc/idl/irpc.idl @@ -157,4 +157,20 @@ import "misc.idl", "security.idl", "nbt.idl"; * If empy/NULL, refresh all partitions. */ WERROR dreplsrv_refresh(); + + /* + called when role transfer is requested via LDAP + */ + typedef [v1_enum] enum { + DREPL_SCHEMA_MASTER, + DREPL_RID_MASTER, + DREPL_INFRASTRUCTURE_MASTER, + DREPL_NAMING_MASTER, + DREPL_PDC_MASTER + } drepl_role_master; -- Samba Shared Repository