mirror of
https://github.com/samba-team/samba.git
synced 2025-02-03 13:47:25 +03:00
s4/dsdb/replmd: add a helper for common calculations
We currently do exactly this work, in exactly these words (ignoring formatting) in two different places. The next two commits will make those places use this helper function. We do this over three commits so that we can more easily compare the next two and be sure they are doing the same thing. Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
e7a6c70953
commit
5d75ab3ebf
@ -5192,6 +5192,130 @@ static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_re
|
||||
return replmd_op_callback(req, ares);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A helper for replmd_op_possible_conflict_callback() and
|
||||
* replmd_replicated_handle_rename()
|
||||
*/
|
||||
static int incoming_dn_should_be_renamed(TALLOC_CTX *mem_ctx,
|
||||
struct replmd_replicated_request *ar,
|
||||
struct ldb_dn *conflict_dn,
|
||||
struct ldb_result **res,
|
||||
bool *rename_incoming_record)
|
||||
{
|
||||
int ret;
|
||||
bool rodc;
|
||||
enum ndr_err_code ndr_err;
|
||||
const struct ldb_val *omd_value = NULL;
|
||||
struct replPropertyMetaDataBlob omd, *rmd = NULL;
|
||||
struct ldb_context *ldb = ldb_module_get_ctx(ar->module);
|
||||
const char *attrs[] = { "replPropertyMetaData", "objectGUID", NULL };
|
||||
struct replPropertyMetaData1 *omd_name = NULL;
|
||||
struct replPropertyMetaData1 *rmd_name = NULL;
|
||||
struct ldb_message *msg = NULL;
|
||||
|
||||
ret = samdb_rodc(ldb, &rodc);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
ldb_asprintf_errstring(
|
||||
ldb,
|
||||
"Failed to determine if we are an RODC when attempting "
|
||||
"to form conflict DN: %s",
|
||||
ldb_errstring(ldb));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
if (rodc) {
|
||||
/*
|
||||
* We are on an RODC, or were a GC for this
|
||||
* partition, so we have to fail this until
|
||||
* someone who owns the partition sorts it
|
||||
* out
|
||||
*/
|
||||
ldb_asprintf_errstring(
|
||||
ldb,
|
||||
"Conflict adding object '%s' from incoming replication "
|
||||
"but we are read only for the partition. \n"
|
||||
" - We must fail the operation until a master for this "
|
||||
"partition resolves the conflict",
|
||||
ldb_dn_get_linearized(conflict_dn));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* first we need the replPropertyMetaData attribute from the
|
||||
* old record
|
||||
*/
|
||||
ret = dsdb_module_search_dn(ar->module, mem_ctx, res, conflict_dn,
|
||||
attrs,
|
||||
DSDB_FLAG_NEXT_MODULE |
|
||||
DSDB_SEARCH_SHOW_DELETED |
|
||||
DSDB_SEARCH_SHOW_RECYCLED, ar->req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
DBG_ERR(__location__
|
||||
": Unable to find object for conflicting record '%s'\n",
|
||||
ldb_dn_get_linearized(conflict_dn));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
msg = (*res)->msgs[0];
|
||||
omd_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData");
|
||||
if (omd_value == NULL) {
|
||||
DBG_ERR(__location__
|
||||
": Unable to find replPropertyMetaData for conflicting "
|
||||
"record '%s'\n",
|
||||
ldb_dn_get_linearized(conflict_dn));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
ndr_err = ndr_pull_struct_blob(
|
||||
omd_value, msg, &omd,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
DBG_ERR(__location__
|
||||
": Failed to parse old replPropertyMetaData for %s\n",
|
||||
ldb_dn_get_linearized(conflict_dn));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
rmd = ar->objs->objects[ar->index_current].meta_data;
|
||||
|
||||
/*
|
||||
* we decide which is newer based on the RPMD on the name
|
||||
* attribute. See [MS-DRSR] ResolveNameConflict.
|
||||
*
|
||||
* We expect omd_name to be present, as this is from a local
|
||||
* search, but while rmd_name should have been given to us by
|
||||
* the remote server, if it is missing we just prefer the
|
||||
* local name in
|
||||
* replmd_replPropertyMetaData1_new_should_be_taken()
|
||||
*/
|
||||
rmd_name = replmd_replPropertyMetaData1_find_attid(rmd,
|
||||
DRSUAPI_ATTID_name);
|
||||
omd_name = replmd_replPropertyMetaData1_find_attid(&omd,
|
||||
DRSUAPI_ATTID_name);
|
||||
if (!omd_name) {
|
||||
DBG_ERR(__location__
|
||||
": Failed to find name attribute in "
|
||||
"local LDB replPropertyMetaData for %s\n",
|
||||
ldb_dn_get_linearized(conflict_dn));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Should we preserve the current record, and so rename the
|
||||
* incoming record to be a conflict?
|
||||
*/
|
||||
*rename_incoming_record =
|
||||
!replmd_replPropertyMetaData1_new_should_be_taken(
|
||||
(ar->objs->dsdb_repl_flags &
|
||||
DSDB_REPL_FLAG_PRIORITISE_INCOMING),
|
||||
omd_name, rmd_name);
|
||||
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
callback for replmd_replicated_apply_add()
|
||||
This copes with the creation of conflict records in the case where
|
||||
|
Loading…
x
Reference in New Issue
Block a user