drepl_server: Allow refresh of partitions on UpdateRef
[ambi/samba-autobuild/.git] / source4 / rpc_server / drsuapi / updaterefs.c
index ae87117d656f7842670b11956c63cb373b7c024f..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;
@@ -50,8 +52,8 @@ static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
        }
 
        for (i=0; i<reps.count; i++) {
-               if (GUID_compare(&dest->source_dsa_obj_guid, 
-                                &reps.r[i].ctr.ctr1.source_dsa_obj_guid) == 0) {
+               if (GUID_equal(&dest->source_dsa_obj_guid,
+                              &reps.r[i].ctr.ctr1.source_dsa_obj_guid)) {
                        if (options & DRSUAPI_DRS_GETCHG_CHECK) {
                                return WERR_OK;
                        } else {
@@ -97,7 +99,8 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
        }
 
        for (i=0; i<reps.count; i++) {
-               if (GUID_compare(dest_guid, &reps.r[i].ctr.ctr1.source_dsa_obj_guid) == 0) {
+               if (GUID_equal(dest_guid,
+                              &reps.r[i].ctr.ctr1.source_dsa_obj_guid)) {
                        if (i+1 < reps.count) {
                                memmove(&reps.r[i], &reps.r[i+1], sizeof(reps.r[i])*(reps.count-(i+1)));
                        }
@@ -120,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
  *
@@ -127,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
@@ -138,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;
@@ -146,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),
@@ -200,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);
 
@@ -221,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:
@@ -277,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);