static int replmd_store_linked_attributes(struct replmd_replicated_request *ar)
{
	int ret = LDB_SUCCESS;
	uint32_t i;
	struct ldb_module *module = ar->module;
	struct replmd_private *replmd_private =
		talloc_get_type(ldb_module_get_private(module), struct replmd_private);
	struct la_group *la_group = NULL;
	struct ldb_context *ldb;
	TALLOC_CTX *tmp_ctx = NULL;
	struct ldb_message *src_msg = NULL;
	const struct dsdb_attribute *attr = NULL;

	ldb = ldb_module_get_ctx(module);

	DEBUG(4,("linked_attributes_count=%u\n", ar->objs->linked_attributes_count));

	/* save away the linked attributes for the end of the transaction */
	for (i = 0; i < ar->objs->linked_attributes_count; i++) {
		struct la_entry *la_entry;
		bool new_srcobj;

		/* create an entry to store the received link attribute info */
		la_entry = create_la_entry(replmd_private,
					   &ar->objs->linked_attributes[i],
					   ar->objs->dsdb_repl_flags);
		if (la_entry == NULL) {
			ldb_oom(ldb);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		/*
		 * check if we're still dealing with the same source object
		 * as the last link
		 */
		new_srcobj = (la_group == NULL ||
			      !la_entry_matches_group(la_entry, la_group));

		if (new_srcobj) {

			/* get a new mem_ctx to lookup the source object */
			TALLOC_FREE(tmp_ctx);
			tmp_ctx = talloc_new(ar);
			if (tmp_ctx == NULL) {
				ldb_oom(ldb);
				return LDB_ERR_OPERATIONS_ERROR;
			}

			/* verify the link source exists */
			ret = replmd_get_la_entry_source(module, la_entry,
							 tmp_ctx, &attr,
							 &src_msg);

			/*
			 * When we fail to find the source object, the error
			 * code we pass back here is really important. It flags
			 * back to the callers to retry this request with
			 * DRSUAPI_DRS_GET_ANC. This case should never happen
			 * if we're replicating from a Samba DC, but it is
			 * needed to talk to a Windows DC
			 */
			if (ret == LDB_ERR_NO_SUCH_OBJECT) {
				WERROR err = WERR_DS_DRA_MISSING_PARENT;
				ret = replmd_replicated_request_werror(ar,
								       err);
				break;
			}
		}

		ret = replmd_verify_link_target(ar, tmp_ctx, la_entry,
						src_msg->dn, attr);
		if (ret != LDB_SUCCESS) {
			break;
		}

		/* group the links together by source-object for efficiency */
		if (new_srcobj) {
			la_group = talloc_zero(replmd_private->la_ctx,
					       struct la_group);
			if (la_group == NULL) {
				ldb_oom(ldb);
				return LDB_ERR_OPERATIONS_ERROR;
			}
			DLIST_ADD(replmd_private->la_list, la_group);
		}
		DLIST_ADD(la_group->la_entries, la_entry);
		replmd_private->total_links++;
	}

	TALLOC_FREE(tmp_ctx);
	return ret;
}
static int replmd_store_linked_attributes(struct replmd_replicated_request *ar)
{
	int ret = LDB_SUCCESS;
	uint32_t i;
	struct ldb_module *module = ar->module;
	struct replmd_private *replmd_private =
		talloc_get_type(ldb_module_get_private(module), struct replmd_private);
	struct la_group *la_group = NULL;
	struct ldb_context *ldb;
	TALLOC_CTX *tmp_ctx = NULL;
	struct ldb_message *src_msg = NULL;
	const struct dsdb_attribute *attr = NULL;

	ldb = ldb_module_get_ctx(module);

	DEBUG(4,("linked_attributes_count=%u\n", ar->objs->linked_attributes_count));

	 
	for (i = 0; i < ar->objs->linked_attributes_count; i++) {
		struct la_entry *la_entry;
		bool new_srcobj;

		 
		la_entry = create_la_entry(replmd_private,
					   &ar->objs->linked_attributes[i],
					   ar->objs->dsdb_repl_flags);
		if (la_entry == NULL) {
			ldb_oom(ldb);
			return LDB_ERR_OPERATIONS_ERROR;
		}

		 
		new_srcobj = (la_group == NULL ||
			      !la_entry_matches_group(la_entry, la_group));

		if (new_srcobj) {

			 
			TALLOC_FREE(tmp_ctx);
			tmp_ctx = talloc_new(ar);
			if (tmp_ctx == NULL) {
				ldb_oom(ldb);
				return LDB_ERR_OPERATIONS_ERROR;
			}

			 
			ret = replmd_get_la_entry_source(module, la_entry,
							 tmp_ctx, &attr,
							 &src_msg);

			 
			if (ret == LDB_ERR_NO_SUCH_OBJECT) {
				WERROR err = WERR_DS_DRA_MISSING_PARENT;
				ret = replmd_replicated_request_werror(ar,
								       err);
				break;
			}
		}

		ret = replmd_verify_link_target(ar, tmp_ctx, la_entry,
						src_msg->dn, attr);
		if (ret != LDB_SUCCESS) {
			break;
		}

		 
		if (new_srcobj) {
			la_group = talloc_zero(replmd_private->la_ctx,
					       struct la_group);
			if (la_group == NULL) {
				ldb_oom(ldb);
				return LDB_ERR_OPERATIONS_ERROR;
			}
			DLIST_ADD(replmd_private->la_list, la_group);
		}
		DLIST_ADD(la_group->la_entries, la_entry);
		replmd_private->total_links++;
	}

	TALLOC_FREE(tmp_ctx);
	return ret;
}