Correct "enought" typo.
[nivanova/samba-autobuild/.git] / source4 / dsdb / repl / drepl_service.c
index ae765a597998c5cd518df0955d0154368ce1d04a..c0ea1f2ba23ffa7eea626d78a5985b508e1ce268 100644 (file)
 #include "auth/auth.h"
 #include "smbd/service.h"
 #include "lib/events/events.h"
-#include "lib/messaging/irpc.h"
 #include "dsdb/repl/drepl_service.h"
-#include "lib/ldb/include/ldb_errors.h"
+#include <ldb_errors.h>
 #include "../lib/util/dlinklist.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "librpc/gen_ndr/ndr_drsuapi.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
 #include "librpc/gen_ndr/ndr_irpc.h"
 #include "param/param.h"
+#include "libds/common/roles.h"
 
 /**
  * Call-back data for _drepl_replica_sync_done_cb()
@@ -54,7 +54,7 @@ static WERROR dreplsrv_init_creds(struct dreplsrv_service *service)
 {
        service->system_session_info = system_session(service->task->lp_ctx);
        if (service->system_session_info == NULL) {
-               return WERR_NOMEM;
+               return WERR_NOT_ENOUGH_MEMORY;
        }
 
        return WERR_OK;
@@ -65,7 +65,7 @@ static WERROR dreplsrv_connect_samdb(struct dreplsrv_service *service, struct lo
        const struct GUID *ntds_guid;
        struct drsuapi_DsBindInfo28 *bind_info28;
 
-       service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info);
+       service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info, 0);
        if (!service->samdb) {
                return WERR_DS_UNAVAILABLE;
        }
@@ -76,6 +76,11 @@ static WERROR dreplsrv_connect_samdb(struct dreplsrv_service *service, struct lo
        }
        service->ntds_guid = *ntds_guid;
 
+       if (samdb_rodc(service->samdb, &service->am_rodc) != LDB_SUCCESS) {
+               DEBUG(0,(__location__ ": Failed to determine RODC status\n"));
+               return WERR_DS_UNAVAILABLE;
+       }
+
        bind_info28                             = &service->bind_info28;
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
@@ -141,7 +146,7 @@ static void _drepl_replica_sync_done_cb(struct dreplsrv_service *service,
        struct drsuapi_DsReplicaSync *r = data->r;
 
        /* store last bad result */
-       if (W_ERROR_IS_OK(werr)) {
+       if (!W_ERROR_IS_OK(werr)) {
                data->werr_last_failure = werr;
        }
 
@@ -166,6 +171,7 @@ static void _drepl_replica_sync_done_cb(struct dreplsrv_service *service,
 static WERROR _drepl_schedule_replication(struct dreplsrv_service *service,
                                          struct dreplsrv_partition_source_dsa *dsa,
                                          struct drsuapi_DsReplicaObjectIdentifier *nc,
+                                         uint32_t rep_options,
                                          struct drepl_replica_sync_cb_data *data,
                                          TALLOC_CTX *mem_ctx)
 {
@@ -177,7 +183,7 @@ static WERROR _drepl_schedule_replication(struct dreplsrv_service *service,
        }
 
        /* schedule replication item */
-       werr = dreplsrv_schedule_partition_pull_source(service, dsa,
+       werr = dreplsrv_schedule_partition_pull_source(service, dsa, rep_options,
                                                       DRSUAPI_EXOP_NONE, 0,
                                                       fn_callback, data);
        if (!W_ERROR_IS_OK(werr)) {
@@ -221,7 +227,7 @@ static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
                                                           struct dreplsrv_service);
 
 #define REPLICA_SYNC_FAIL(_msg, _werr) do {\
-               if (!W_ERROR_IS_OK(werr)) { \
+               if (!W_ERROR_IS_OK(_werr)) { \
                        DEBUG(0,(__location__ ": Failure - %s. werr = %s\n", \
                                 _msg, win_errstr(_werr))); \
                        NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaSync, r); \
@@ -260,7 +266,7 @@ static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
        } else {
                cb_data = talloc_zero(msg, struct drepl_replica_sync_cb_data);
                if (!cb_data) {
-                       REPLICA_SYNC_FAIL("Not enought memory",
+                       REPLICA_SYNC_FAIL("Not enough memory",
                                          WERR_DS_DRA_INTERNAL_ERROR);
                }
 
@@ -273,7 +279,8 @@ static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
        if (req1->options & DRSUAPI_DRS_SYNC_ALL) {
                for (dsa = p->sources; dsa; dsa = dsa->next) {
                        /* schedule replication item */
-                       werr = _drepl_schedule_replication(service, dsa, nc, cb_data, msg);
+                       werr = _drepl_schedule_replication(service, dsa, nc,
+                                                          req1->options, cb_data, msg);
                        if (!W_ERROR_IS_OK(werr)) {
                                REPLICA_SYNC_FAIL("_drepl_schedule_replication() failed",
                                                  werr);
@@ -300,14 +307,25 @@ static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
                        werr = dreplsrv_partition_source_dsa_by_guid(p,
                                                                     &req1->source_dsa_guid,
                                                                     &dsa);
+                       if (W_ERROR_EQUAL(werr, WERR_DS_DRA_NO_REPLICA)) {
+                               /* we don't have this source setup as
+                                  a replication partner. Create a
+                                  temporary dsa structure for this
+                                  replication */
+                               werr = dreplsrv_partition_source_dsa_temporary(p,
+                                                                              msg,
+                                                                              &req1->source_dsa_guid,
+                                                                              &dsa);
+                       }
                }
                if (!W_ERROR_IS_OK(werr)) {
                        REPLICA_SYNC_FAIL("Failed to locate source DSA for given NC",
-                                         WERR_DS_DRA_NO_REPLICA);
+                                         werr);
                }
 
                /* schedule replication item */
-               werr = _drepl_schedule_replication(service, dsa, nc, cb_data, msg);
+               werr = _drepl_schedule_replication(service, dsa, nc,
+                                                  req1->options, cb_data, msg);
                if (!W_ERROR_IS_OK(werr)) {
                        REPLICA_SYNC_FAIL("_drepl_schedule_replication() failed",
                                          werr);
@@ -317,8 +335,11 @@ static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
        /* if we got here, everything is OK */
        r->out.result = WERR_OK;
 
-       /* force execution of scheduled replications */
-       dreplsrv_run_pending_ops(service);
+       /*
+        * schedule replication event to force
+        * replication as soon as possible
+        */
+       dreplsrv_pendingops_schedule(service, 0);
 
 done:
        return NT_STATUS_OK;
@@ -342,15 +363,6 @@ 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 = dreplsrv_fsmo_role_check(service, r->in.role);
-       return NT_STATUS_OK;
-}
-
 /**
  * Called when the auth code wants us to try and replicate
  * a users secrets
@@ -371,6 +383,40 @@ static NTSTATUS drepl_trigger_repl_secret(struct irpc_message *msg,
 }
 
 
+/*
+  DsReplicaAdd messages from the DRSUAPI server are forwarded here
+ */
+static NTSTATUS dreplsrv_replica_add(struct irpc_message *msg,
+                                 struct drsuapi_DsReplicaAdd *r)
+{
+       struct dreplsrv_service *service = talloc_get_type(msg->private_data,
+                                                          struct dreplsrv_service);
+       return drepl_replica_add(service, r);
+}
+
+/*
+  DsReplicaDel messages from the DRSUAPI server are forwarded here
+ */
+static NTSTATUS dreplsrv_replica_del(struct irpc_message *msg,
+                                 struct drsuapi_DsReplicaDel *r)
+{
+       struct dreplsrv_service *service = talloc_get_type(msg->private_data,
+                                                          struct dreplsrv_service);
+       return drepl_replica_del(service, r);
+}
+
+/*
+  DsReplicaMod messages from the DRSUAPI server are forwarded here
+ */
+static NTSTATUS dreplsrv_replica_mod(struct irpc_message *msg,
+                                 struct drsuapi_DsReplicaMod *r)
+{
+       struct dreplsrv_service *service = talloc_get_type(msg->private_data,
+                                                          struct dreplsrv_service);
+       return drepl_replica_mod(service, r);
+}
+
+
 /*
   startup the dsdb replicator service task
 */
@@ -379,8 +425,6 @@ static void dreplsrv_task_init(struct task_server *task)
        WERROR status;
        struct dreplsrv_service *service;
        uint32_t periodic_startup_interval;
-       bool am_rodc;
-       int ret;
 
        switch (lpcfg_server_role(task->lp_ctx)) {
        case ROLE_STANDALONE:
@@ -391,7 +435,7 @@ static void dreplsrv_task_init(struct task_server *task)
                task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration",
                                      false);
                return;
-       case ROLE_DOMAIN_CONTROLLER:
+       case ROLE_ACTIVE_DIRECTORY_DC:
                /* Yes, we want DSDB replication */
                break;
        }
@@ -443,8 +487,7 @@ static void dreplsrv_task_init(struct task_server *task)
        }
 
        /* if we are a RODC then we do not send DSReplicaSync*/
-       ret = samdb_rodc(service->samdb, &am_rodc);
-       if (ret == LDB_SUCCESS && !am_rodc) {
+       if (!service->am_rodc) {
                service->notify.interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv",
                                                           "notify_interval", 5); /* in seconds */
                status = dreplsrv_notify_schedule(service, service->notify.interval);
@@ -460,9 +503,12 @@ 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, drsuapi, DRSUAPI_DSREPLICAADD, dreplsrv_replica_add, service);
+       IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICADEL, dreplsrv_replica_del, service);
+       IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAMOD, dreplsrv_replica_mod, service);
        IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TAKEFSMOROLE, drepl_take_FSMO_role, service);
        IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TRIGGER_REPL_SECRET, drepl_trigger_repl_secret, service);
-       messaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid);
+       imessaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid);
 }
 
 /*