static int replmd_process_backlink(struct ldb_module *module, struct la_backlink *bl, struct ldb_request *parent)
{
	struct ldb_dn *target_dn, *source_dn;
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_message *msg;
	TALLOC_CTX *frame = talloc_stackframe();
	char *dn_string;

	/*
	  - find DN of target
	  - find DN of source
	  - construct ldb_message
              - either an add or a delete
	 */
	ret = dsdb_module_dn_by_guid(module, frame, &bl->target_guid, &target_dn, parent);
	if (ret != LDB_SUCCESS) {
		struct GUID_txt_buf guid_str;
		DBG_WARNING("Failed to find target DN for linked attribute with GUID %s\n",
			    GUID_buf_string(&bl->target_guid, &guid_str));
		DBG_WARNING("Please run 'samba-tool dbcheck' to resolve any missing backlinks.\n");
		talloc_free(frame);
		return LDB_SUCCESS;
	}

	msg = ldb_msg_new(frame);
	if (msg == NULL) {
		ldb_module_oom(module);
		talloc_free(frame);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	source_dn = ldb_dn_copy(frame, bl->forward_dn);
	if (!source_dn) {
		ldb_module_oom(module);
		talloc_free(frame);
		return LDB_ERR_OPERATIONS_ERROR;
	} else {
		/* Filter down to the attributes we want in the backlink */
		const char *accept[] = { "GUID", "SID", NULL };
		ldb_dn_extended_filter(source_dn, accept);
	}

	/* construct a ldb_message for adding/deleting the backlink */
	msg->dn = target_dn;
	dn_string = ldb_dn_get_extended_linearized(frame, bl->forward_dn, 1);
	if (!dn_string) {
		ldb_module_oom(module);
		talloc_free(frame);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ret = ldb_msg_add_steal_string(msg, bl->attr_name, dn_string);
	if (ret != LDB_SUCCESS) {
		talloc_free(frame);
		return ret;
	}
	msg->elements[0].flags = bl->active?LDB_FLAG_MOD_ADD:LDB_FLAG_MOD_DELETE;

	/* a backlink should never be single valued. Unfortunately the
	   exchange schema has a attribute
	   msExchBridgeheadedLocalConnectorsDNBL which is single
	   valued and a backlink. We need to cope with that by
	   ignoring the single value flag */
	msg->elements[0].flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && !bl->active) {
		/* we allow LDB_ERR_NO_SUCH_ATTRIBUTE as success to
		   cope with possible corruption where the backlink has
		   already been removed */
		DEBUG(3,("WARNING: backlink from %s already removed from %s - %s\n",
			 ldb_dn_get_linearized(target_dn),
			 ldb_dn_get_linearized(source_dn),
			 ldb_errstring(ldb)));
		ret = LDB_SUCCESS;
	} else if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to %s backlink from %s to %s - %s",
				       bl->active?"add":"remove",
				       ldb_dn_get_linearized(source_dn),
				       ldb_dn_get_linearized(target_dn),
				       ldb_errstring(ldb));
		talloc_free(frame);
		return ret;
	}
	talloc_free(frame);
	return ret;
}
static int replmd_process_backlink(struct ldb_module *module, struct la_backlink *bl, struct ldb_request *parent)
{
	struct ldb_dn *target_dn, *source_dn;
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_message *msg;
	TALLOC_CTX *frame = talloc_stackframe();
	char *dn_string;

	 
	ret = dsdb_module_dn_by_guid(module, frame, &bl->target_guid, &target_dn, parent);
	if (ret != LDB_SUCCESS) {
		struct GUID_txt_buf guid_str;
		DBG_WARNING("Failed to find target DN for linked attribute with GUID %s\n",
			    GUID_buf_string(&bl->target_guid, &guid_str));
		DBG_WARNING("Please run 'samba-tool dbcheck' to resolve any missing backlinks.\n");
		talloc_free(frame);
		return LDB_SUCCESS;
	}

	msg = ldb_msg_new(frame);
	if (msg == NULL) {
		ldb_module_oom(module);
		talloc_free(frame);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	source_dn = ldb_dn_copy(frame, bl->forward_dn);
	if (!source_dn) {
		ldb_module_oom(module);
		talloc_free(frame);
		return LDB_ERR_OPERATIONS_ERROR;
	} else {
		 
		const char *accept[] = { "GUID", "SID", NULL };
		ldb_dn_extended_filter(source_dn, accept);
	}

	 
	msg->dn = target_dn;
	dn_string = ldb_dn_get_extended_linearized(frame, bl->forward_dn, 1);
	if (!dn_string) {
		ldb_module_oom(module);
		talloc_free(frame);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ret = ldb_msg_add_steal_string(msg, bl->attr_name, dn_string);
	if (ret != LDB_SUCCESS) {
		talloc_free(frame);
		return ret;
	}
	msg->elements[0].flags = bl->active?LDB_FLAG_MOD_ADD:LDB_FLAG_MOD_DELETE;

	 
	msg->elements[0].flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && !bl->active) {
		 
		DEBUG(3,("WARNING: backlink from %s already removed from %s - %s\n",
			 ldb_dn_get_linearized(target_dn),
			 ldb_dn_get_linearized(source_dn),
			 ldb_errstring(ldb)));
		ret = LDB_SUCCESS;
	} else if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to %s backlink from %s to %s - %s",
				       bl->active?"add":"remove",
				       ldb_dn_get_linearized(source_dn),
				       ldb_dn_get_linearized(target_dn),
				       ldb_errstring(ldb));
		talloc_free(frame);
		return ret;
	}
	talloc_free(frame);
	return ret;
}