struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_context *ldb;
	struct ldb_dn *newdn;
	const struct ldb_map_attribute *map;
	enum ldb_map_attr_type map_type;
	const char *name;
	struct ldb_val value;
	int i, ret;

	if (dn == NULL) {
		return NULL;
	}

	ldb = ldb_module_get_ctx(module);

	newdn = ldb_dn_copy(mem_ctx, dn);
	if (newdn == NULL) {
		map_oom(module);
		return NULL;
	}

	/* For each RDN, map the component name and possibly the value */
	for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) {
		map = map_attr_find_remote(data, ldb_dn_get_component_name(dn, i));

		/* Unknown attribute - leave this RDN as is and hope the best... */
		if (map == NULL) {
			map_type = LDB_MAP_KEEP;
		} else {
			map_type = map->type;
		}

		switch (map_type) {
		case LDB_MAP_IGNORE:
		case LDB_MAP_GENERATE:
			ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
				  "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' "
				  "used in DN!", ldb_dn_get_component_name(dn, i));
			goto failed;

		case LDB_MAP_CONVERT:
			if (map->u.convert.convert_remote == NULL) {
				ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
					  "'convert_remote' not set for attribute '%s' "
					  "used in DN!", ldb_dn_get_component_name(dn, i));
				goto failed;
			}

			FALL_THROUGH;
		case LDB_MAP_KEEP:
		case LDB_MAP_RENAME:
		case LDB_MAP_RENDROP:
			name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i));
			if (name == NULL) goto failed;

			value = ldb_val_map_remote(module, newdn, map, ldb_dn_get_component_val(dn, i));
			if (value.data == NULL) goto failed;

			ret = ldb_dn_set_component(newdn, i, name, value);
			if (ret != LDB_SUCCESS) {
				goto failed;
			}

			break;
		}
	}

	return newdn;

failed:
	talloc_free(newdn);
	return NULL;
}
struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, struct ldb_dn *dn)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_context *ldb;
	struct ldb_dn *newdn;
	const struct ldb_map_attribute *map;
	enum ldb_map_attr_type map_type;
	const char *name;
	struct ldb_val value;
	int i, ret;

	if (dn == NULL) {
		return NULL;
	}

	ldb = ldb_module_get_ctx(module);

	newdn = ldb_dn_copy(mem_ctx, dn);
	if (newdn == NULL) {
		map_oom(module);
		return NULL;
	}

	 
	for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) {
		map = map_attr_find_remote(data, ldb_dn_get_component_name(dn, i));

		 
		if (map == NULL) {
			map_type = LDB_MAP_KEEP;
		} else {
			map_type = map->type;
		}

		switch (map_type) {
		case LDB_MAP_IGNORE:
		case LDB_MAP_GENERATE:
			ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
				  "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' "
				  "used in DN!", ldb_dn_get_component_name(dn, i));
			goto failed;

		case LDB_MAP_CONVERT:
			if (map->u.convert.convert_remote == NULL) {
				ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
					  "'convert_remote' not set for attribute '%s' "
					  "used in DN!", ldb_dn_get_component_name(dn, i));
				goto failed;
			}

			FALL_THROUGH;
		case LDB_MAP_KEEP:
		case LDB_MAP_RENAME:
		case LDB_MAP_RENDROP:
			name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i));
			if (name == NULL) goto failed;

			value = ldb_val_map_remote(module, newdn, map, ldb_dn_get_component_val(dn, i));
			if (value.data == NULL) goto failed;

			ret = ldb_dn_set_component(newdn, i, name, value);
			if (ret != LDB_SUCCESS) {
				goto failed;
			}

			break;
		}
	}

	return newdn;

failed:
	talloc_free(newdn);
	return NULL;
}