📄 ldb_map.c
字号:
/* ldb database mapping module Copyright (C) Jelmer Vernooij 2005 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released ** under the LGPL This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see <http://www.gnu.org/licenses/>.*//* * Name: ldb * * Component: ldb ldb_map module * * Description: Map portions of data into a different format on a * remote partition. * * Author: Jelmer Vernooij, Martin Kuehl */#include "ldb_includes.h"#include "ldb_map.h"#include "ldb_map_private.h"#ifndef _PUBLIC_#define _PUBLIC_#endif/* Description of the provided ldb requests: - special attribute 'isMapped' - search: - if parse tree can be split - search remote records w/ remote attrs and parse tree - otherwise - enumerate all remote records - for each remote result - map remote result to local message - search local result - is present - merge local into remote result - run callback on merged result - otherwise - run callback on remote result - add: - split message into local and remote part - if local message is not empty - add isMapped to local message - add local message - add remote message - modify: - split message into local and remote part - if local message is not empty - add isMapped to local message - search for local record - if present - modify local record - otherwise - add local message - modify remote record - delete: - search for local record - if present - delete local record - delete remote record - rename: - search for local record - if present - rename local record - modify local isMapped - rename remote record*//* Private data structures * ======================= *//* Global private data *//* Extract mappings from private data. */const struct ldb_map_context *map_get_context(struct ldb_module *module){ const struct map_private *data = talloc_get_type(module->private_data, struct map_private); return data->context;}/* Create a generic request context. */static struct map_context *map_init_context(struct ldb_handle *h, struct ldb_request *req){ struct map_context *ac; ac = talloc_zero(h, struct map_context); if (ac == NULL) { map_oom(h->module); return NULL; } ac->module = h->module; ac->orig_req = req; return ac;}/* Create a search request context. */struct map_search_context *map_init_search_context(struct map_context *ac, struct ldb_reply *ares){ struct map_search_context *sc; sc = talloc_zero(ac, struct map_search_context); if (sc == NULL) { map_oom(ac->module); return NULL; } sc->ac = ac; sc->local_res = NULL; sc->remote_res = ares; return sc;}/* Create a request context and handle. */struct ldb_handle *map_init_handle(struct ldb_request *req, struct ldb_module *module){ struct map_context *ac; struct ldb_handle *h; h = talloc_zero(req, struct ldb_handle); if (h == NULL) { map_oom(module); return NULL; } h->module = module; ac = map_init_context(h, req); if (ac == NULL) { talloc_free(h); return NULL; } h->private_data = (void *)ac; h->state = LDB_ASYNC_INIT; h->status = LDB_SUCCESS; return h;}/* Dealing with DNs for different partitions * ========================================= *//* Check whether any data should be stored in the local partition. */bool map_check_local_db(struct ldb_module *module){ const struct ldb_map_context *data = map_get_context(module); if (!data->remote_base_dn || !data->local_base_dn) { return false; } return true;}/* Copy a DN with the base DN of the local partition. */static struct ldb_dn *ldb_dn_rebase_local(void *mem_ctx, const struct ldb_map_context *data, struct ldb_dn *dn){ struct ldb_dn *new_dn; new_dn = ldb_dn_copy(mem_ctx, dn); if ( ! ldb_dn_validate(new_dn)) { talloc_free(new_dn); return NULL; } /* may be we don't need to rebase at all */ if ( ! data->remote_base_dn || ! data->local_base_dn) { return new_dn; } if ( ! ldb_dn_remove_base_components(new_dn, ldb_dn_get_comp_num(data->remote_base_dn))) { talloc_free(new_dn); return NULL; } if ( ! ldb_dn_add_base(new_dn, data->local_base_dn)) { talloc_free(new_dn); return NULL; } return new_dn;}/* Copy a DN with the base DN of the remote partition. */static struct ldb_dn *ldb_dn_rebase_remote(void *mem_ctx, const struct ldb_map_context *data, struct ldb_dn *dn){ struct ldb_dn *new_dn; new_dn = ldb_dn_copy(mem_ctx, dn); if ( ! ldb_dn_validate(new_dn)) { talloc_free(new_dn); return NULL; } /* may be we don't need to rebase at all */ if ( ! data->remote_base_dn || ! data->local_base_dn) { return new_dn; } if ( ! ldb_dn_remove_base_components(new_dn, ldb_dn_get_comp_num(data->local_base_dn))) { talloc_free(new_dn); return NULL; } if ( ! ldb_dn_add_base(new_dn, data->remote_base_dn)) { talloc_free(new_dn); return NULL; } return new_dn;}/* Run a request and make sure it targets the remote partition. *//* TODO: free old DNs and messages? */int ldb_next_remote_request(struct ldb_module *module, struct ldb_request *request){ const struct ldb_map_context *data = map_get_context(module); struct ldb_message *msg; switch (request->operation) { case LDB_SEARCH: if (request->op.search.base) { request->op.search.base = ldb_dn_rebase_remote(request, data, request->op.search.base); } else { request->op.search.base = data->remote_base_dn; /* TODO: adjust scope? */ } break; case LDB_ADD: msg = ldb_msg_copy_shallow(request, request->op.add.message); msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn); request->op.add.message = msg; break; case LDB_MODIFY: msg = ldb_msg_copy_shallow(request, request->op.mod.message); msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn); request->op.mod.message = msg; break; case LDB_DELETE: request->op.del.dn = ldb_dn_rebase_remote(request, data, request->op.del.dn); break; case LDB_RENAME: request->op.rename.olddn = ldb_dn_rebase_remote(request, data, request->op.rename.olddn); request->op.rename.newdn = ldb_dn_rebase_remote(request, data, request->op.rename.newdn); break; default: ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " "Invalid remote request!\n"); return LDB_ERR_OPERATIONS_ERROR; } return ldb_next_request(module, request);}/* Finding mappings for attributes and objectClasses * ================================================= *//* Find an objectClass mapping by the local name. */static const struct ldb_map_objectclass *map_objectclass_find_local(const struct ldb_map_context *data, const char *name){ int i; for (i = 0; data->objectclass_maps && data->objectclass_maps[i].local_name; i++) { if (ldb_attr_cmp(data->objectclass_maps[i].local_name, name) == 0) { return &data->objectclass_maps[i]; } } return NULL;}/* Find an objectClass mapping by the remote name. */static const struct ldb_map_objectclass *map_objectclass_find_remote(const struct ldb_map_context *data, const char *name){ int i; for (i = 0; data->objectclass_maps && data->objectclass_maps[i].remote_name; i++) { if (ldb_attr_cmp(data->objectclass_maps[i].remote_name, name) == 0) { return &data->objectclass_maps[i]; } } return NULL;}/* Find an attribute mapping by the local name. */const struct ldb_map_attribute *map_attr_find_local(const struct ldb_map_context *data, const char *name){ int i; for (i = 0; data->attribute_maps[i].local_name; i++) { if (ldb_attr_cmp(data->attribute_maps[i].local_name, name) == 0) { return &data->attribute_maps[i]; } } for (i = 0; data->attribute_maps[i].local_name; i++) { if (ldb_attr_cmp(data->attribute_maps[i].local_name, "*") == 0) { return &data->attribute_maps[i]; } } return NULL;}/* Find an attribute mapping by the remote name. */const struct ldb_map_attribute *map_attr_find_remote(const struct ldb_map_context *data, const char *name){ const struct ldb_map_attribute *map; const struct ldb_map_attribute *wildcard = NULL; int i, j; for (i = 0; data->attribute_maps[i].local_name; i++) { map = &data->attribute_maps[i]; if (ldb_attr_cmp(map->local_name, "*") == 0) { wildcard = &data->attribute_maps[i]; } switch (map->type) { case MAP_IGNORE: break; case MAP_KEEP: if (ldb_attr_cmp(map->local_name, name) == 0) { return map; } break; case MAP_RENAME: case MAP_CONVERT: if (ldb_attr_cmp(map->u.rename.remote_name, name) == 0) { return map; } break; case MAP_GENERATE: for (j = 0; map->u.generate.remote_names && map->u.generate.remote_names[j]; j++) { if (ldb_attr_cmp(map->u.generate.remote_names[j], name) == 0) { return map; } } break; } } /* We didn't find it, so return the wildcard record if one was configured */ return wildcard;}/* Mapping attributes * ================== *//* Check whether an attribute will be mapped into the remote partition. */bool map_attr_check_remote(const struct ldb_map_context *data, const char *attr){ const struct ldb_map_attribute *map = map_attr_find_local(data, attr); if (map == NULL) { return false; } if (map->type == MAP_IGNORE) { return false; } return true;}/* Map an attribute name into the remote partition. */const char *map_attr_map_local(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr){ if (map == NULL) { return talloc_strdup(mem_ctx, attr); } switch (map->type) { case MAP_KEEP: return talloc_strdup(mem_ctx, attr); case MAP_RENAME: case MAP_CONVERT: return talloc_strdup(mem_ctx, map->u.rename.remote_name); default: return NULL; }}/* Map an attribute name back into the local partition. */const char *map_attr_map_remote(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr){ if (map == NULL) { return talloc_strdup(mem_ctx, attr); } if (map->type == MAP_KEEP) { return talloc_strdup(mem_ctx, attr); } return talloc_strdup(mem_ctx, map->local_name);}/* Merge two lists of attributes into a single one. */int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attrs, const char * const *more_attrs){ int i, j, k; for (i = 0; *attrs && (*attrs)[i]; i++) /* noop */ ; for (j = 0; more_attrs && more_attrs[j]; j++) /* noop */ ; *attrs = talloc_realloc(mem_ctx, *attrs, const char *, i+j+1); if (*attrs == NULL) { map_oom(module); return -1; } for (k = 0; k < j; k++) { (*attrs)[i + k] = more_attrs[k]; } (*attrs)[i+k] = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -