static int replmd_replicated_handle_rename(struct replmd_replicated_request *ar,
					   struct ldb_message *msg,
					   struct ldb_request *parent,
					   bool *renamed_to_conflict)
{
	int ret;
	TALLOC_CTX *tmp_ctx = talloc_new(msg);
	struct ldb_result *res;
	struct ldb_dn *conflict_dn;
	bool rename_incoming_record;
	struct ldb_dn *new_dn;
	struct GUID guid;

	DEBUG(4,("replmd_replicated_request rename %s => %s\n",
		 ldb_dn_get_linearized(ar->search_msg->dn),
		 ldb_dn_get_linearized(msg->dn)));


	ret = dsdb_module_rename(ar->module, ar->search_msg->dn, msg->dn,
				 DSDB_FLAG_NEXT_MODULE, ar->req);
	if (ret == LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	if (ret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
		talloc_free(tmp_ctx);
		ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote rename from %s to %s: %s",
				       ldb_dn_get_linearized(ar->search_msg->dn),
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb_module_get_ctx(ar->module)));
		return ret;
	}

	conflict_dn = msg->dn;


	ret = incoming_dn_should_be_renamed(tmp_ctx, ar, conflict_dn, &res,
					    &rename_incoming_record);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}

	if (rename_incoming_record) {

		new_dn = replmd_conflict_dn(msg,
					    ldb_module_get_ctx(ar->module),
					    msg->dn,
					    &ar->objs->objects[ar->index_current].object_guid);
		if (new_dn == NULL) {
			ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
								  "Failed to form conflict DN for %s\n",
								  ldb_dn_get_linearized(msg->dn));

			talloc_free(tmp_ctx);
			return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
		}

		ret = dsdb_module_rename(ar->module, ar->search_msg->dn, new_dn,
					 DSDB_FLAG_NEXT_MODULE, ar->req);
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
					       "Failed to rename incoming conflicting dn '%s' (was '%s') to '%s' - %s\n",
					       ldb_dn_get_linearized(conflict_dn),
					       ldb_dn_get_linearized(ar->search_msg->dn),
					       ldb_dn_get_linearized(new_dn),
					       ldb_errstring(ldb_module_get_ctx(ar->module)));
			talloc_free(tmp_ctx);
			return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
		}

		msg->dn = new_dn;
		*renamed_to_conflict = true;
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	/* we are renaming the existing record */

	guid = samdb_result_guid(res->msgs[0], "objectGUID");
	if (GUID_all_zero(&guid)) {
		DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n",
			 ldb_dn_get_linearized(conflict_dn)));
		goto failed;
	}

	new_dn = replmd_conflict_dn(tmp_ctx,
				    ldb_module_get_ctx(ar->module),
				    conflict_dn, &guid);
	if (new_dn == NULL) {
		DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
			 ldb_dn_get_linearized(conflict_dn)));
		goto failed;
	}

	DEBUG(2,(__location__ ": Resolving conflict record via existing-record rename '%s' -> '%s'\n",
		 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));

	ret = dsdb_module_rename(ar->module, conflict_dn, new_dn,
				 DSDB_FLAG_OWN_MODULE, ar->req);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n",
			 ldb_dn_get_linearized(conflict_dn),
			 ldb_dn_get_linearized(new_dn),
			 ldb_errstring(ldb_module_get_ctx(ar->module))));
		goto failed;
	}

	/*
	 * now we need to ensure that the rename is seen as an
	 * originating update. We do that with a modify.
	 */
	ret = replmd_name_modify(ar, ar->req, new_dn);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}

	DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated rename '%s' -> '%s'\n",
		 ldb_dn_get_linearized(ar->search_msg->dn),
		 ldb_dn_get_linearized(msg->dn)));

	/*
	 * With the other record out of the way, do the rename we had
	 * at the top again
	 */
	ret = dsdb_module_rename(ar->module, ar->search_msg->dn, msg->dn,
				 DSDB_FLAG_NEXT_MODULE, ar->req);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": After conflict resolution, failed to rename dn '%s' to '%s' - %s\n",
			 ldb_dn_get_linearized(ar->search_msg->dn),
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb_module_get_ctx(ar->module))));
			goto failed;
	}

	talloc_free(tmp_ctx);
	return ret;
failed:
	/*
	 * On failure make the caller get the error
	 * This means replication will stop with an error,
	 * but there is not much else we can do.  In the
	 * LDB_ERR_ENTRY_ALREADY_EXISTS case this is exactly what is
	 * needed.
	 */
	if (ret == LDB_SUCCESS) {
		ret = LDB_ERR_OPERATIONS_ERROR;
	}

	talloc_free(tmp_ctx);
	return ret;
}