s4-fsmo: make rootDSE modify for FSMO transfer async
authorAndrew Tridgell <tridge@samba.org>
Mon, 28 Mar 2011 05:20:47 +0000 (16:20 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 28 Mar 2011 22:00:22 +0000 (00:00 +0200)
this gives the ldap client the error code from the transfer

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>

source4/dsdb/samdb/ldb_modules/rootdse.c

index 050cf5e0623d0beb8669db8bcf8f0f3365091004..0fd65f4795cfae41489ade25054060621acda794 100644 (file)
@@ -1159,22 +1159,53 @@ static int rootdse_add(struct ldb_module *module, struct ldb_request *req)
        return LDB_ERR_NAMING_VIOLATION;
 }
 
+struct fsmo_transfer_state {
+       struct ldb_context *ldb;
+       struct ldb_request *req;
+};
+
+/*
+  called when a FSMO transfer operation has completed
+ */
+static void rootdse_fsmo_transfer_callback(struct tevent_req *treq)
+{
+       struct fsmo_transfer_state *fsmo = tevent_req_callback_data(treq, struct fsmo_transfer_state);
+       NTSTATUS status;
+       WERROR werr;
+       struct ldb_request *req = fsmo->req;
+       struct ldb_context *ldb = fsmo->ldb;
+
+       status = dcerpc_drepl_takeFSMORole_recv(treq, fsmo, &werr);
+       talloc_free(fsmo);
+       if (!NT_STATUS_IS_OK(status)) {
+               ldb_asprintf_errstring(ldb, "Failed FSMO transfer: %s", nt_errstr(status));
+               ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE);
+               return;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               ldb_asprintf_errstring(ldb, "Failed FSMO transfer: %s", win_errstr(werr));
+               ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE);
+               return;
+       }
+
+       ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+}
+
 static int rootdse_become_master(struct ldb_module *module,
                                 struct ldb_request *req,
                                 enum drepl_role_master 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;
-       WERROR status_fn;
        bool am_rodc;
        struct dcerpc_binding_handle *irpc_handle;
        int ret;
        struct auth_session_info *session_info;
        enum security_user_level level;
+       struct fsmo_transfer_state *fsmo;
+       struct tevent_req *treq;
 
        session_info = (struct auth_session_info *)ldb_get_opaque(ldb_module_get_ctx(module), "sessionInfo");
        level = security_session_user_level(session_info, NULL);
@@ -1204,17 +1235,24 @@ static int rootdse_become_master(struct ldb_module *module,
        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_error(ldb, LDB_ERR_OPERATIONS_ERROR, nt_errstr(status_call));
+       fsmo = talloc_zero(req, struct fsmo_transfer_state);
+       if (fsmo == NULL) {
+               return ldb_oom(ldb);
        }
-       status_fn = r.out.result;
-       if (!W_ERROR_IS_OK(status_fn)) {
-               return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, win_errstr(status_fn));
+       fsmo->ldb = ldb;
+       fsmo->req = req;
+
+       /* we send the call asynchronously, as the ldap client is
+        * expecting to get an error back if the role transfer fails
+        */
+
+       treq = dcerpc_drepl_takeFSMORole_send(req, ldb_get_event_context(ldb), irpc_handle, role);
+       if (treq == NULL) {
+               return ldb_oom(ldb);
        }
-       return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+
+       tevent_req_set_callback(treq, rootdse_fsmo_transfer_callback, fsmo);
+       return LDB_SUCCESS;
 }
 
 static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)