diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-10-13 13:09:07 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-10-13 13:09:07 +1100 |
commit | 4423173b08ebba1ff8494a4997e46e28525c1d7a (patch) | |
tree | fb5f1e291d841ba604d258ac9ca318d13b7886c9 | |
parent | ae507f620ae34b69c5df86980ea6e374c9c1e548 (diff) | |
download | samba-4423173b08ebba1ff8494a4997e46e28525c1d7a.tar.gz samba-4423173b08ebba1ff8494a4997e46e28525c1d7a.tar.xz samba-4423173b08ebba1ff8494a4997e46e28525c1d7a.zip |
s4-repl: check that a DsGetNCChanges is a continuation, and fix sorting
When we indicate that a getncchanges request is not complete, we set
the more_data flag to true in the response. The client usually then
asks for the next block of data. If the client decides it wants to
skip that replication and do a different replication then we need to
make sure that the next call is in fact a continuation of the existing
call, and not a new call.
This relies on returning the results sorted by uSNChanged, as the
client uses the tmp_highest_usn in each result to see if progress is
being made.
-rw-r--r-- | source4/rpc_server/drsuapi/drsutil.c | 2 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/getncchanges.c | 19 |
2 files changed, 17 insertions, 4 deletions
diff --git a/source4/rpc_server/drsuapi/drsutil.c b/source4/rpc_server/drsuapi/drsutil.c index 1b4c28c4ab..752861cc26 100644 --- a/source4/rpc_server/drsuapi/drsutil.c +++ b/source4/rpc_server/drsuapi/drsutil.c @@ -98,7 +98,7 @@ int drsuapi_search_with_extended_dn(struct ldb_context *ldb, sort_control[0] = talloc(req, struct ldb_server_sort_control); sort_control[0]->attributeName = sort_attrib; sort_control[0]->orderingRule = NULL; - sort_control[0]->reverse = 1; + sort_control[0]->reverse = 0; sort_control[1] = NULL; ret = ldb_request_add_control(req, LDB_CONTROL_SERVER_SORT_OID, true, sort_control); diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 5713d41f84..ae1b2e61eb 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -411,7 +411,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ search_filter = talloc_asprintf(mem_ctx, "(uSNChanged>=%llu)", (unsigned long long)(getnc_state->min_usn+1)); - + if (r->in.req->req8.replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_CRITICAL_ONLY) { search_filter = talloc_asprintf(mem_ctx, "(&%s(isCriticalSystemObject=TRUE))", @@ -427,11 +427,24 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ ldb_dn_get_linearized(getnc_state->ncRoot_dn), search_filter)); ret = drsuapi_search_with_extended_dn(b_state->sam_ctx, getnc_state, &getnc_state->site_res, getnc_state->ncRoot_dn, scope, attrs, - "distinguishedName", + "uSNChanged", search_filter); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; } + } else { + /* check that this request is for the same NC as the previous one */ + struct ldb_dn *dn; + dn = ldb_dn_new(getnc_state, b_state->sam_ctx, ncRoot->dn); + if (!dn) { + return WERR_NOMEM; + } + if (ldb_dn_compare(dn, getnc_state->ncRoot_dn) != 0) { + DEBUG(0,(__location__ ": DsGetNCChanges 2nd replication on different DN %s %s\n", + ldb_dn_get_linearized(dn), + ldb_dn_get_linearized(getnc_state->ncRoot_dn))); + return WERR_DS_DRA_BAD_NC; + } } /* Prefix mapping */ @@ -525,7 +538,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ b_state->getncchanges_state = NULL; } - DEBUG(3,("DsGetNCChanges with uSNChanged >= %llu on %s gave %u objects\n", + DEBUG(2,("DsGetNCChanges with uSNChanged >= %llu on %s gave %u objects\n", (unsigned long long)(r->in.req->req8.highwatermark.highest_usn+1), ncRoot->dn, r->out.ctr->ctr6.object_count)); |