drepl_server: Allow refresh of partitions on UpdateRef
authorGarming Sam <garming@catalyst.net.nz>
Tue, 28 Mar 2017 22:24:50 +0000 (11:24 +1300)
committerGarming Sam <garming@samba.org>
Thu, 13 Apr 2017 05:29:18 +0000 (07:29 +0200)
When we call UpdateRef, the push replication will not begin until the
drepl_server has done its periodic refresh. If UpdateRefs is called, we
should just send an IRPC message to call the refresh.

NOTE: This has the same dependencies and issues as repl_secrets in
auth_sam.c in terms of IRPC implementation.

Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/rpc_server/drsuapi/dcesrv_drsuapi.h
source4/rpc_server/drsuapi/getncchanges.c
source4/rpc_server/drsuapi/updaterefs.c

index d376f7edfb31135f47f9dc9e0d11fccb5c92db23..38375b5ce589f0fa0106f41940931f6ba0286da0 100644 (file)
@@ -40,7 +40,9 @@ struct drsuapi_bind_state {
 
 
 /* prototypes of internal functions */
-WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+WERROR drsuapi_UpdateRefs(struct imessaging_context *msg_ctx,
+                         struct tevent_context *event_ctx,
+                         struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
                          struct drsuapi_DsReplicaUpdateRefsRequest1 *req);
 WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                          struct drsuapi_DsReplicaUpdateRefs *r);
index 3f2ef8d960c93d3bd09da29b195bcb01f1e8b69e..1f02f2c0936ae7b298a6f9176d492015e348f840 100644 (file)
@@ -2933,7 +2933,9 @@ allowed:
                   to send notifies using the GC SPN */
                ureq.options |= (req10->replica_flags & DRSUAPI_DRS_REF_GCSPN);
 
-               werr = drsuapi_UpdateRefs(b_state, mem_ctx, &ureq);
+               werr = drsuapi_UpdateRefs(dce_call->msg_ctx,
+                                         dce_call->event_ctx, b_state,
+                                         mem_ctx, &ureq);
                if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,(__location__ ": Failed UpdateRefs on %s for %s in DsGetNCChanges - %s\n",
                                 drs_ObjectIdentifier_to_string(mem_ctx, ncRoot), ureq.dest_dsa_dns_name,
index 6fdbf2e04bfbd3a3b2ec237b713e533fd0343bf1..457f393fd9d751ae58b0caa764c902e4beea3e16 100644 (file)
@@ -27,6 +27,8 @@
 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
 #include "auth/session.h"
 #include "librpc/gen_ndr/ndr_drsuapi.h"
+#include "librpc/gen_ndr/ndr_irpc_c.h"
+#include "lib/messaging/irpc.h"
 
 struct repsTo {
        uint32_t count;
@@ -121,6 +123,10 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
        return WERR_OK; 
 }
 
+struct drepl_refresh_state {
+       struct dreplsrv_refresh r;
+};
+
 /**
  * @brief Update the references for the given NC and the destination DSA object
  *
@@ -128,6 +134,9 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
  * will validate the request to update reference and then will add/del a repsTo
  * to the specified server referenced by its DSA GUID in the request.
  *
+ * @param[in]       msg_ctx          Messaging context for sending partition
+ *                                   refresh in dreplsrv
+ *
  * @param[in]       b_state          A bind_state object
  *
  * @param[in]       mem_ctx          A talloc context for memory allocation
@@ -139,7 +148,9 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
  * @return                           WERR_OK is success, different error
  *                                   otherwise.
  */
-WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
+WERROR drsuapi_UpdateRefs(struct imessaging_context *msg_ctx,
+                         struct tevent_context *event_ctx,
+                         struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
                          struct drsuapi_DsReplicaUpdateRefsRequest1 *req)
 {
        WERROR werr;
@@ -147,6 +158,10 @@ WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ct
        struct ldb_dn *dn;
        struct ldb_dn *nc_root;
        struct ldb_context *sam_ctx = b_state->sam_ctx_system?b_state->sam_ctx_system:b_state->sam_ctx;
+       struct dcerpc_binding_handle *irpc_handle;
+       struct tevent_req *subreq;
+       struct drepl_refresh_state *state;
+
 
        DEBUG(4,("DsReplicaUpdateRefs for host '%s' with GUID %s options 0x%08x nc=%s\n",
                 req->dest_dsa_dns_name, GUID_string(mem_ctx, &req->dest_dsa_guid),
@@ -201,7 +216,7 @@ WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ct
        if (req->options & DRSUAPI_DRS_ADD_REF) {
                struct repsFromTo1 dest;
                struct repsFromTo1OtherInfo oi;
-               
+
                ZERO_STRUCT(dest);
                ZERO_STRUCT(oi);
 
@@ -222,9 +237,36 @@ WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ct
        if (ldb_transaction_commit(sam_ctx) != LDB_SUCCESS) {
                DEBUG(0,(__location__ ": Failed to commit transaction on samdb: %s\n",
                         ldb_errstring(sam_ctx)));
-               return WERR_DS_DRA_INTERNAL_ERROR;              
+               return WERR_DS_DRA_INTERNAL_ERROR;
        }
 
+       state = talloc_zero(mem_ctx, struct drepl_refresh_state);
+       if (state == NULL) {
+               return WERR_OK;
+       }
+
+       irpc_handle = irpc_binding_handle_by_name(mem_ctx, msg_ctx,
+                                                 "dreplsrv", &ndr_table_irpc);
+       if (irpc_handle == NULL) {
+               /* dreplsrv is not running yet */
+               TALLOC_FREE(state);
+               return WERR_OK;
+       }
+
+        /*
+        * [Taken from auth_sam_trigger_repl_secret in auth_sam.c]
+        *
+         * This seem to rely on the current IRPC implementation,
+         * which delivers the message in the _send function.
+         *
+         * TODO: we need a ONE_WAY IRPC handle and register
+         * a callback and wait for it to be triggered!
+         */
+       subreq = dcerpc_dreplsrv_refresh_r_send(state, event_ctx,
+                                               irpc_handle, &state->r);
+       TALLOC_FREE(subreq);
+       TALLOC_FREE(state);
+
        return WERR_OK;
 
 failed:
@@ -278,7 +320,8 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA
                }
        }
 
-       werr = drsuapi_UpdateRefs(b_state, mem_ctx, req);
+       werr = drsuapi_UpdateRefs(dce_call->msg_ctx, dce_call->event_ctx,
+                                 b_state, mem_ctx, req);
 
 #if 0
        NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsReplicaUpdateRefs, NDR_BOTH, r);