summaryrefslogtreecommitdiff
path: root/source4/dsdb/repl/drepl_out_helpers.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2015-12-09 17:05:56 +1300
committerAndrew Bartlett <abartlet@samba.org>2016-06-06 16:36:22 +0200
commit449271defc25d66bf84afa7f9b3c9591bbc762bf (patch)
tree63716efa479b9002ded6db981fe2860f7eccafb6 /source4/dsdb/repl/drepl_out_helpers.c
parent2d67128814f27731d1cd7d137e822c894ab87a4b (diff)
downloadsamba-449271defc25d66bf84afa7f9b3c9591bbc762bf.tar.gz
repl: Enforce that we have parent objects for all replicated objects
The creating of replicated objects without their parent object allows database corruption as they can end up under the wrong object. We need to re-try the replication with the DRSUAPI_DRS_GET_ANC flag set to get the objects in tree order. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'source4/dsdb/repl/drepl_out_helpers.c')
-rw-r--r--source4/dsdb/repl/drepl_out_helpers.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index 54f44c60f7e..6493c1ea498 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -458,6 +458,10 @@ static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req)
replica_flags = rf1->replica_flags;
highwatermark = rf1->highwatermark;
+ if (state->op->options & DRSUAPI_DRS_GET_ANC) {
+ replica_flags |= DRSUAPI_DRS_GET_ANC;
+ }
+
if (partition->partial_replica) {
status = dreplsrv_get_gc_partial_attribute_set(service, r, &pas);
if (!NT_STATUS_IS_OK(status)) {
@@ -873,7 +877,27 @@ static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req
talloc_free(objects);
if (!W_ERROR_IS_OK(status)) {
- nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+
+ /*
+ * If we failed to apply the records due to a missing
+ * parent, try again after asking for the parent
+ * records first. Because we don't update the
+ * highwatermark, we start this part of the cycle
+ * again.
+ */
+ if (((state->op->options & DRSUAPI_DRS_GET_ANC) == 0)
+ && W_ERROR_EQUAL(status, WERR_DS_DRA_MISSING_PARENT)) {
+ state->op->options |= DRSUAPI_DRS_GET_ANC;
+ DEBUG(4,("Missing parent object when we didn't set the DRSUAPI_DRS_GET_ANC flag, retrying\n"));
+ dreplsrv_op_pull_source_get_changes_trigger(req);
+ return;
+ } else if (((state->op->options & DRSUAPI_DRS_GET_ANC))
+ && W_ERROR_EQUAL(status, WERR_DS_DRA_MISSING_PARENT)) {
+ DEBUG(1,("Missing parent object despite setting DRSUAPI_DRS_GET_ANC flag\n"));
+ nt_status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+ } else {
+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+ }
DEBUG(0,("Failed to commit objects: %s/%s\n",
win_errstr(status), nt_errstr(nt_status)));
tevent_req_nterror(req, nt_status);