static int replmd_check_target_exists(struct ldb_module *module,
				      struct dsdb_dn *dsdb_dn,
				      struct la_entry *la_entry,
				      struct ldb_dn *source_dn,
				      bool is_obj_commit,
				      struct GUID *guid,
				      bool *ignore_link)
{
	struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_result *target_res;
	TALLOC_CTX *tmp_ctx = talloc_new(la_entry);
	const char *attrs[] = { "isDeleted", "isRecycled", NULL };
	NTSTATUS ntstatus;
	int ret;
	enum deletion_state target_deletion_state = OBJECT_REMOVED;
	bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) ? true : false;

	*ignore_link = false;
	ntstatus = dsdb_get_extended_dn_guid(dsdb_dn->dn, guid, "GUID");

	if (!NT_STATUS_IS_OK(ntstatus) && !active) {

		/*
		 * This strange behaviour (allowing a NULL/missing
		 * GUID) originally comes from:
		 *
		 * commit e3054ce0fe0f8f62d2f5b2a77893e7a1479128bd
		 * Author: Andrew Tridgell <tridge@samba.org>
		 * Date:   Mon Dec 21 21:21:55 2009 +1100
		 *
		 *  s4-drs: cope better with NULL GUIDS from DRS
		 *
		 *  It is valid to get a NULL GUID over DRS for a deleted forward link. We
		 *  need to match by DN if possible when seeing if we should update an
		 *  existing link.
		 *
		 *  Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
		 */
		ret = dsdb_module_search_dn(module, tmp_ctx, &target_res,
					    dsdb_dn->dn, attrs,
					    DSDB_FLAG_NEXT_MODULE |
					    DSDB_SEARCH_SHOW_RECYCLED |
					    DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
					    DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
					    NULL);
	} else if (!NT_STATUS_IS_OK(ntstatus)) {
		ldb_asprintf_errstring(ldb, "Failed to find GUID in linked attribute 0x%x blob for %s from %s",
				       la->attid,
				       ldb_dn_get_linearized(dsdb_dn->dn),
				       ldb_dn_get_linearized(source_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	} else {
		ret = dsdb_module_search(module, tmp_ctx, &target_res,
					 NULL, LDB_SCOPE_SUBTREE,
					 attrs,
					 DSDB_FLAG_NEXT_MODULE |
					 DSDB_SEARCH_SHOW_RECYCLED |
					 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
					 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
					 NULL,
					 "objectGUID=%s",
					 GUID_string(tmp_ctx, guid));
	}

	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to re-resolve GUID %s: %s\n",
				       GUID_string(tmp_ctx, guid),
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	if (target_res->count == 0) {

		/*
		 * target object is unknown. Check whether to ignore the link,
		 * fail the replication, or add a partial link
		 */
		ret = replmd_allow_missing_target(module, tmp_ctx, dsdb_dn->dn,
						  source_dn, is_obj_commit, guid,
						  la_entry->dsdb_repl_flags,
						  ignore_link, "Unknown");

	} else if (target_res->count != 1) {
		ldb_asprintf_errstring(ldb, "More than one object found matching objectGUID %s\n",
				       GUID_string(tmp_ctx, guid));
		ret = LDB_ERR_OPERATIONS_ERROR;
	} else {
		struct ldb_message *target_msg = target_res->msgs[0];

		dsdb_dn->dn = talloc_steal(dsdb_dn, target_msg->dn);

		/* Get the object's state (i.e. Not Deleted, Tombstone, etc) */
		replmd_deletion_state(module, target_msg,
				      &target_deletion_state, NULL);

		/*
		 * Check for deleted objects as per MS-DRSR 4.1.10.6.14
		 * ProcessLinkValue(). Link updates should not be sent for
		 * recycled and tombstone objects (deleting the links should
		 * happen when we delete the object). This probably means our
		 * copy of the target object isn't up to date.
		 */
		if (target_deletion_state >= OBJECT_RECYCLED) {

			/*
			 * target object is deleted. Check whether to ignore the
			 * link, fail the replication, or add a partial link
			 */
			ret = replmd_allow_missing_target(module, tmp_ctx,
							  dsdb_dn->dn, source_dn,
							  is_obj_commit, guid,
							  la_entry->dsdb_repl_flags,
							  ignore_link, "Deleted");
		}
	}

	talloc_free(tmp_ctx);
	return ret;
}
static int replmd_check_target_exists(struct ldb_module *module,
				      struct dsdb_dn *dsdb_dn,
				      struct la_entry *la_entry,
				      struct ldb_dn *source_dn,
				      bool is_obj_commit,
				      struct GUID *guid,
				      bool *ignore_link)
{
	struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_result *target_res;
	TALLOC_CTX *tmp_ctx = talloc_new(la_entry);
	const char *attrs[] = { "isDeleted", "isRecycled", NULL };
	NTSTATUS ntstatus;
	int ret;
	enum deletion_state target_deletion_state = OBJECT_REMOVED;
	bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) ? true : false;

	*ignore_link = false;
	ntstatus = dsdb_get_extended_dn_guid(dsdb_dn->dn, guid, "GUID");

	if (!NT_STATUS_IS_OK(ntstatus) && !active) {

		 
		ret = dsdb_module_search_dn(module, tmp_ctx, &target_res,
					    dsdb_dn->dn, attrs,
					    DSDB_FLAG_NEXT_MODULE |
					    DSDB_SEARCH_SHOW_RECYCLED |
					    DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
					    DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
					    NULL);
	} else if (!NT_STATUS_IS_OK(ntstatus)) {
		ldb_asprintf_errstring(ldb, "Failed to find GUID in linked attribute 0x%x blob for %s from %s",
				       la->attid,
				       ldb_dn_get_linearized(dsdb_dn->dn),
				       ldb_dn_get_linearized(source_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	} else {
		ret = dsdb_module_search(module, tmp_ctx, &target_res,
					 NULL, LDB_SCOPE_SUBTREE,
					 attrs,
					 DSDB_FLAG_NEXT_MODULE |
					 DSDB_SEARCH_SHOW_RECYCLED |
					 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
					 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
					 NULL,
					 "objectGUID=%s",
					 GUID_string(tmp_ctx, guid));
	}

	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to re-resolve GUID %s: %s\n",
				       GUID_string(tmp_ctx, guid),
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	if (target_res->count == 0) {

		 
		ret = replmd_allow_missing_target(module, tmp_ctx, dsdb_dn->dn,
						  source_dn, is_obj_commit, guid,
						  la_entry->dsdb_repl_flags,
						  ignore_link, "Unknown");

	} else if (target_res->count != 1) {
		ldb_asprintf_errstring(ldb, "More than one object found matching objectGUID %s\n",
				       GUID_string(tmp_ctx, guid));
		ret = LDB_ERR_OPERATIONS_ERROR;
	} else {
		struct ldb_message *target_msg = target_res->msgs[0];

		dsdb_dn->dn = talloc_steal(dsdb_dn, target_msg->dn);

		 
		replmd_deletion_state(module, target_msg,
				      &target_deletion_state, NULL);

		 
		if (target_deletion_state >= OBJECT_RECYCLED) {

			 
			ret = replmd_allow_missing_target(module, tmp_ctx,
							  dsdb_dn->dn, source_dn,
							  is_obj_commit, guid,
							  la_entry->dsdb_repl_flags,
							  ignore_link, "Deleted");
		}
	}

	talloc_free(tmp_ctx);
	return ret;
}