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

Reply via email to