diff options
author | Nadezhda Ivanova <nivanova@samba.org> | 2010-08-25 00:22:16 +0300 |
---|---|---|
committer | Kamen Mazdrashki <kamenim@samba.org> | 2010-09-10 13:08:17 +0300 |
commit | 657b7039c38e97af9dbacafb5ab7a5966f52eaea (patch) | |
tree | fbd25f4c9914089ec4975882de98f1c3366a6bf9 /source4/dsdb | |
parent | c8794d2625e81b8c11dec7726a42e632854472af (diff) | |
download | samba-657b7039c38e97af9dbacafb5ab7a5966f52eaea.tar.gz samba-657b7039c38e97af9dbacafb5ab7a5966f52eaea.tar.bz2 samba-657b7039c38e97af9dbacafb5ab7a5966f52eaea.zip |
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.atanasov@postpath.com> who
kindly helped to debug it.
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/config.mk | 3 | ||||
-rw-r--r-- | source4/dsdb/repl/drepl_fsmo.c | 151 | ||||
-rw-r--r-- | source4/dsdb/wscript_build | 2 |
3 files changed, 154 insertions, 2 deletions
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk index 1ab0cb2102..e12193d524 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 0000000000..8719967d16 --- /dev/null +++ b/source4/dsdb/repl/drepl_fsmo.c @@ -0,0 +1,151 @@ +/* + 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)) { + return drepl_request_extended_op(service, + role_owner_dn, + fsmo_role_dn, + DRSUAPI_EXOP_FSMO_REQ_ROLE, + alloc_pool, + drepl_role_callback); + } + 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/wscript_build b/source4/dsdb/wscript_build index d3961f52d5..426b12dc7f 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', |