]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:dsdb/repl: avoid recursion after fetching schema changes.
authorStefan Metzmacher <metze@samba.org>
Fri, 5 Aug 2016 09:05:37 +0000 (11:05 +0200)
committerJeremy Allison <jra@samba.org>
Wed, 10 Aug 2016 22:49:14 +0000 (00:49 +0200)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12115

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source4/dsdb/repl/drepl_out_helpers.c
source4/dsdb/repl/drepl_service.h

index 2a74cb73b2c09397538b4ad55e7fe38945e53ddc..9fe8c3bfeb0c8db98dc5c31e8c21c94a889bf1c6 100644 (file)
@@ -241,6 +241,13 @@ struct dreplsrv_op_pull_source_state {
        struct tevent_context *ev;
        struct dreplsrv_out_operation *op;
        void *ndr_struct_ptr;
+       /*
+        * Used when we have to re-try with a different NC, eg for
+        * EXOP retry or to get a current schema first
+        */
+       struct dreplsrv_partition_source_dsa *source_dsa_retry;
+       enum drsuapi_DsExtendedOperation extended_op_retry;
+       bool retry_started;
 };
 
 static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq);
@@ -785,10 +792,17 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
                                                 dsdb_repl_flags,
                                                 state, &objects);
 
-       if (W_ERROR_EQUAL(status, WERR_DS_DRA_SCHEMA_MISMATCH)
-           && state->op->source_dsa_retry == NULL) {
+       if (W_ERROR_EQUAL(status, WERR_DS_DRA_SCHEMA_MISMATCH)) {
                struct dreplsrv_partition *p;
 
+               if (state->retry_started) {
+                       nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+                       DEBUG(0,("Failed to convert objects after retry: %s/%s\n",
+                                 win_errstr(status), nt_errstr(nt_status)));
+                       tevent_req_nterror(req, nt_status);
+                       return;
+               }
+
                /*
                 * Change info sync or extended operation into a fetch
                 * of the schema partition, so we get all the schema
@@ -802,14 +816,14 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
 
 
                if (state->op->extended_op == DRSUAPI_EXOP_REPL_SECRET) {
-                       state->op->extended_op_retry = state->op->extended_op;
+                       state->extended_op_retry = state->op->extended_op;
                } else {
-                       state->op->extended_op_retry = DRSUAPI_EXOP_NONE;
+                       state->extended_op_retry = DRSUAPI_EXOP_NONE;
                }
                state->op->extended_op = DRSUAPI_EXOP_NONE;
 
                if (ldb_dn_compare(nc_root, partition->dn) == 0) {
-                       state->op->source_dsa_retry = state->op->source_dsa;
+                       state->source_dsa_retry = state->op->source_dsa;
                } else {
                        status = dreplsrv_partition_find_for_nc(service,
                                                                NULL, NULL,
@@ -825,7 +839,7 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
                        }
                        status = dreplsrv_partition_source_dsa_by_guid(p,
                                                                       &state->op->source_dsa->repsFrom1->source_dsa_obj_guid,
-                                                                      &state->op->source_dsa_retry);
+                                                                      &state->source_dsa_retry);
 
                        if (!W_ERROR_IS_OK(status)) {
                                struct GUID_txt_buf str;
@@ -867,6 +881,7 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
                }
                DEBUG(4,("Wrong schema when applying reply GetNCChanges, retrying\n"));
 
+               state->retry_started = true;
                dreplsrv_op_pull_source_get_changes_trigger(req);
                return;
 
@@ -930,10 +945,10 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
         * pulling the schema, then go back and do the original
         * operation once we are done.
         */
-       if (state->op->source_dsa_retry != NULL) {
-               state->op->source_dsa = state->op->source_dsa_retry;
-               state->op->extended_op = state->op->extended_op_retry;
-               state->op->source_dsa_retry = NULL;
+       if (state->source_dsa_retry != NULL) {
+               state->op->source_dsa = state->source_dsa_retry;
+               state->op->extended_op = state->extended_op_retry;
+               state->source_dsa_retry = NULL;
                dreplsrv_op_pull_source_get_changes_trigger(req);
                return;
        }
index 317fa87ee62bb87f2b3391c52ad73d65f88e0f5f..edba4c4a49b5c47b9fb124d6fe67b4603e495142 100644 (file)
@@ -130,13 +130,6 @@ struct dreplsrv_out_operation {
        enum drsuapi_DsExtendedError extended_ret;
        dreplsrv_extended_callback_t callback;
        void *cb_data;
-
-       /*
-        * Used when we have to re-try with a different NC, eg for
-        * EXOP retry or to get a current schema first
-        */
-       struct dreplsrv_partition_source_dsa *source_dsa_retry;
-       enum drsuapi_DsExtendedOperation extended_op_retry;
 };
 
 struct dreplsrv_notify_operation {