return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
}
-static WERROR replmd_replicated_modify_vector(struct replmd_replicated_request *ar,
- struct ldb_message *old_msg,
- struct ldb_message *new_msg,
- const struct drsuapi_DsReplicaCursor2CtrEx *ruv,
- const struct GUID *our_invocation_id,
- uint64_t *remote_highest_usn)
+static int replmd_replicated_uptodate_modify(struct replmd_replicated_request *ar)
{
struct ldb_context *ldb;
struct ldb_request *change_req;
struct ldb_message *msg;
struct replUpToDateVectorBlob ouv;
const struct ldb_val *ouv_value;
+ const struct drsuapi_DsReplicaCursor2CtrEx *ruv;
struct replUpToDateVectorBlob nuv;
struct ldb_val nuv_value;
struct ldb_message_element *nuv_el = NULL;
struct ldb_message_element *nrf_el = NULL;
unsigned int i;
uint32_t j,ni=0;
+ bool found = false;
time_t t = time(NULL);
NTTIME now;
int ret;
uint32_t instanceType;
- struct drsuapi_DsReplicaCursor2 *rcur = NULL;
- const struct repsFromTo1 *sdsa = ar->objs->source_dsa;
ldb = ldb_module_get_ctx(ar->module);
+ ruv = ar->objs->uptodateness_vector;
ZERO_STRUCT(ouv);
ouv.version = 2;
ZERO_STRUCT(nuv);
unix_to_nt_time(&now, t);
- if (ruv == NULL) {
- return WERR_OK;
+ /* get our invocation_id if we have one already attached to the ldb */
+ our_invocation_id = samdb_ntds_invocation_id(ldb);
+ if (!our_invocation_id) {
+ /* this happens during an initial vampire while
+ updating the schema */
+ DEBUG(0,("No invocationID - replmd_replicated_uptodate_modify\n"));
+ smb_panic(__location__);
+ return replmd_replicated_request_werror(ar, WERR_INTERNAL_ERROR);
}
- if (ruv->count == 0) {
- return WERR_OK;
+ if (ar->search_msg == NULL) {
+ /* this happens for a REPL_OBJ call where we are
+ creating the target object by replicating it. The
+ subdomain join code does this for the partition DN
+ */
+ DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as no target DN\n"));
+ return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
+ }
+
+ instanceType = ldb_msg_find_attr_as_uint(ar->search_msg, "instanceType", 0);
+ if (! (instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
+ DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as not NC root: %s\n",
+ ldb_dn_get_linearized(ar->search_msg->dn)));
+ return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
}
/*
* first create the new replUpToDateVector
*/
- ouv_value = ldb_msg_find_ldb_val(old_msg, "replUpToDateVector");
+ ouv_value = ldb_msg_find_ldb_val(ar->search_msg, "replUpToDateVector");
if (ouv_value) {
ndr_err = ndr_pull_struct_blob(ouv_value, ar, &ouv,
(ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
- return ntstatus_to_werror(nt_status);
+ return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
}
if (ouv.version != 2) {
- return WERR_DS_DRA_INTERNAL_ERROR;
+ return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
}
}
*
* plus optional values from our old vector and the one from the source_dsa
*/
- nuv.ctr.ctr2.count = 1 + ouv.ctr.ctr2.count;
- nuv.ctr.ctr2.count += ruv->count;
+ nuv.ctr.ctr2.count = ouv.ctr.ctr2.count;
+ if (ruv) nuv.ctr.ctr2.count += ruv->count;
nuv.ctr.ctr2.cursors = talloc_array(ar,
struct drsuapi_DsReplicaCursor2,
nuv.ctr.ctr2.count);
- if (nuv.ctr.ctr2.cursors == NULL) {
- return WERR_NOMEM;
- }
+ if (!nuv.ctr.ctr2.cursors) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
/* first copy the old vector */
for (i=0; i < ouv.ctr.ctr2.count; i++) {
}
/* merge in the source_dsa vector is available */
- for (i=0; i < ruv->count; i++) {
- bool found = false;
+ for (i=0; (ruv && i < ruv->count); i++) {
+ found = false;
if (GUID_equal(&ruv->cursors[i].source_dsa_invocation_id,
- our_invocation_id)) {
+ &ar->our_invocation_id)) {
continue;
}
found = true;
- /*
- * we update only the highest_usn and not the latest_sync_success time,
- * because the last success stands for direct replication
- */
if (ruv->cursors[i].highest_usn > nuv.ctr.ctr2.cursors[j].highest_usn) {
- nuv.ctr.ctr2.cursors[j].highest_usn = ruv->cursors[i].highest_usn;
+ nuv.ctr.ctr2.cursors[j] = ruv->cursors[i];
}
break;
}
- if (found) {
- continue;
- }
+ if (found) continue;
/* if it's not there yet, add it */
nuv.ctr.ctr2.cursors[ni] = ruv->cursors[i];
ni++;
}
- /*
- * merge in the current highwatermark for the source_dsa
- */
- for (j=0; j < ni; j++) {
- if (!GUID_equal(&sdsa->source_dsa_invocation_id,
- &nuv.ctr.ctr2.cursors[j].source_dsa_invocation_id)) {
- continue;
- }
-
- rcur = &nuv.ctr.ctr2.cursors[j];
- break;
- }
- if (rcur = NULL) {
- /* we need a fresh cursor entry */
- rcur = &nuv.ctr.ctr2.cursors[ni];
- ZERO_STRUCTP(rcur);
- ni++;
- }
-
- /*
- * Given the remote high_water_mark and the remote uptodate_vector
- * we need to figure out the highest usn we got from the
- * remote source dsa.
- *
- * For the schema partition it is typically that
- * the highest_usn in the new_highwater_mark stays at
- * a very low level as nothing has changed in the schema,
- * but the highest_usn in the uptodate_vector has the
- * current highest_usn of the remote source dsa.
- */
- if (rcur->highest_usn > *remote_highest_usn) {
- *remote_highest_usn = rcur->highest_usn;
- }
-
- rcur->source_dsa_invocation_id = sdsa->source_dsa_invocation_id;
- rcur->highest_usn = *remote_highest_usn;
- rcur->last_sync_success = now;
-
/*
* finally correct the size of the cursors array
*/
*/
TYPESAFE_QSORT(nuv.ctr.ctr2.cursors, nuv.ctr.ctr2.count, drsuapi_DsReplicaCursor2_compare);
+ /*
+ * create the change ldb_message
+ */
+ msg = ldb_msg_new(ar);
+ if (!msg) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
+ msg->dn = ar->search_msg->dn;
+
ndr_err = ndr_push_struct_blob(&nuv_value, msg, &nuv,
(ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
- return ntstatus_to_werror(nt_status);
+ return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
}
ret = ldb_msg_add_value(msg, "replUpToDateVector", &nuv_value, &nuv_el);
if (ret != LDB_SUCCESS) {
- return WERR_NOMEM;
+ return replmd_replicated_request_error(ar, ret);
}
nuv_el->flags = LDB_FLAG_MOD_REPLACE;
- return WERR_OK;
-}
-
-static int replmd_replicated_uptodate_modify(struct replmd_replicated_request *ar)
-{
- struct ldb_context *ldb;
- struct ldb_request *change_req;
- enum ndr_err_code ndr_err;
- struct ldb_message *msg;
- struct replUpToDateVectorBlob ouv;
- const struct ldb_val *ouv_value;
- const struct drsuapi_DsReplicaCursor2CtrEx *ruv;
- struct replUpToDateVectorBlob nuv;
- struct ldb_val nuv_value;
- struct ldb_message_element *nuv_el = NULL;
- struct ldb_message_element *orf_el = NULL;
- struct repsFromToBlob nrf;
- struct ldb_val *nrf_value = NULL;
- struct ldb_message_element *nrf_el = NULL;
- unsigned int i;
- uint32_t j,ni=0;
- bool found = false;
- time_t t = time(NULL);
- NTTIME now;
- int ret;
- uint32_t instanceType;
- uint64_t remote_highest_usn = 0;
-
- ldb = ldb_module_get_ctx(ar->module);
- ruv = ar->objs->uptodateness_vector;
- ZERO_STRUCT(ouv);
- ouv.version = 2;
- ZERO_STRUCT(nuv);
- nuv.version = 2;
-
- unix_to_nt_time(&now, t);
-
- /* get our invocation_id if we have one already attached to the ldb */
- our_invocation_id = samdb_ntds_invocation_id(ldb);
- if (!our_invocation_id) {
- /* this happens during an initial vampire while
- updating the schema */
- DEBUG(0,("No invocationID - replmd_replicated_uptodate_modify\n"));
- smb_panic(__location__);
- return replmd_replicated_request_werror(ar, WERR_INTERNAL_ERROR);
- }
-
- if (GUID_equal(&ar->objs->source_dsa->source_dsa_invocation_id,
- our_invocation_id))
- {
- werr = WERR_DS_INTERNAL_FAILURE;
- DEBUG(0,("source_dsa_invocation_id[%s] is our own, NTDSA[%s] name[%s]\n",
- GUID_string(ar, our_invocation_id),
- GUID_string(ar, &ar->objs->source_dsa->source_dsa_obj_guid),
- ar->objs->source_dsa->other_info->dns_name));
- return replmd_replicated_request_werror(ar, werr);
- }
-
- if (ar->search_msg == NULL) {
- /* this happens for a REPL_OBJ call where we are
- creating the target object by replicating it. The
- subdomain join code does this for the partition DN
- */
- DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as no target DN\n"));
- return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
- }
-
- instanceType = ldb_msg_find_attr_as_uint(ar->search_msg, "instanceType", 0);
- if (! (instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
- DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as not NC root: %s\n",
- ldb_dn_get_linearized(ar->search_msg->dn)));
- return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
- }
-
- /*
- * create the change ldb_message
- */
- msg = ldb_msg_new(ar);
- if (!msg) return replmd_replicated_request_werror(ar, WERR_NOMEM);
- msg->dn = ar->search_msg->dn;
-
- remote_highest_usn = ar->objs->source_dsa->highwatermark.highest_usn;
-
- status = replmd_replicated_modify_vector(ar, ar->search_msg, msg, &remote_highest_usn);
-
/*
* now create the new repsFrom value from the given repsFromTo1 structure
*/