📄 ldb_map_outbound.c
字号:
} return 0;}/* Collect subtrees that query attributes in the remote partition */static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree){ const struct ldb_map_context *data = map_get_context(module); const struct ldb_map_attribute *map; if (tree == NULL) { return 0; } if (tree->operation == LDB_OP_NOT) { return map_subtree_collect_remote_not(module, mem_ctx, new, tree); } if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) { return map_subtree_collect_remote_list(module, mem_ctx, new, tree); } if (!map_attr_check_remote(data, tree->u.equality.attr)) { *new = NULL; return 0; } map = map_attr_find_local(data, tree->u.equality.attr); if (map->convert_operator) { return map->convert_operator(module, mem_ctx, new, tree); } if (map->type == MAP_GENERATE) { ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: " "Skipping attribute '%s': " "'convert_operator' not set\n", tree->u.equality.attr); *new = NULL; return 0; } return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);}/* Split subtrees that query attributes in the local partition from * those that query the remote partition. */static int ldb_parse_tree_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, struct ldb_parse_tree **local_tree, struct ldb_parse_tree **remote_tree, const struct ldb_parse_tree *tree){ int ret; *local_tree = NULL; *remote_tree = NULL; /* No original tree */ if (tree == NULL) { return 0; } /* Generate local tree */ ret = map_subtree_select_local(module, local_ctx, local_tree, tree); if (ret) { return ret; } /* Generate remote tree */ ret = map_subtree_collect_remote(module, remote_ctx, remote_tree, tree); if (ret) { talloc_free(*local_tree); return ret; } return 0;}/* Collect a list of attributes required either explicitly from a * given list or implicitly from a given parse tree; split the * collected list into local and remote parts. */static int map_attrs_collect_and_partition(struct ldb_module *module, struct map_context *ac, const char * const *search_attrs, const struct ldb_parse_tree *tree){ void *tmp_ctx; const char **tree_attrs; const char **remote_attrs; const char **local_attrs; int ret; /* There is no tree, just partition the searched attributes */ if (tree == NULL) { ret = map_attrs_partition(module, ac, &local_attrs, &remote_attrs, search_attrs); if (ret == 0) { ac->local_attrs = local_attrs; ac->remote_attrs = remote_attrs; ac->all_attrs = search_attrs; } return ret; } /* Create context for temporary memory */ tmp_ctx = talloc_new(ac); if (tmp_ctx == NULL) { goto oom; } /* Prepare list of attributes from tree */ tree_attrs = talloc_array(tmp_ctx, const char *, 1); if (tree_attrs == NULL) { talloc_free(tmp_ctx); goto oom; } tree_attrs[0] = NULL; /* Collect attributes from tree */ ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree); if (ret) { goto done; } /* Merge attributes from search operation */ ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs); if (ret) { goto done; } /* Split local from remote attributes */ ret = map_attrs_partition(module, ac, &local_attrs, &remote_attrs, tree_attrs); if (ret == 0) { ac->local_attrs = local_attrs; ac->remote_attrs = remote_attrs; talloc_steal(ac, tree_attrs); ac->all_attrs = tree_attrs; }done: /* Free temporary memory */ talloc_free(tmp_ctx); return ret;oom: map_oom(module); return -1;}/* Outbound requests: search * ========================= *//* Pass a merged search result up the callback chain. */int map_up_callback(struct ldb_context *ldb, const struct ldb_request *req, struct ldb_reply *ares){ int i; /* No callback registered, stop */ if (req->callback == NULL) { return LDB_SUCCESS; } /* Only records need special treatment */ if (ares->type != LDB_REPLY_ENTRY) { return req->callback(ldb, req->context, ares); } /* Merged result doesn't match original query, skip */ if (!ldb_match_msg(ldb, ares->message, req->op.search.tree, req->op.search.base, req->op.search.scope)) { ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: " "Skipping record '%s': " "doesn't match original search\n", ldb_dn_get_linearized(ares->message->dn)); return LDB_SUCCESS; } /* Limit result to requested attrs */ if ((req->op.search.attrs) && (!ldb_attr_in_list(req->op.search.attrs, "*"))) { for (i = 0; i < ares->message->num_elements; ) { struct ldb_message_element *el = &ares->message->elements[i]; if (!ldb_attr_in_list(req->op.search.attrs, el->name)) { ldb_msg_remove_element(ares->message, el); } else { i++; } } } return req->callback(ldb, req->context, ares);}/* Merge the remote and local parts of a search result. */int map_local_merge_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares){ struct map_search_context *sc; int ret; if (context == NULL || ares == NULL) { ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: " "NULL Context or Result in `map_local_merge_callback`")); return LDB_ERR_OPERATIONS_ERROR; } sc = talloc_get_type(context, struct map_search_context); switch (ares->type) { case LDB_REPLY_ENTRY: /* We have already found a local record */ if (sc->local_res) { ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: " "Too many results to base search for local entry")); talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } /* Store local result */ sc->local_res = ares; /* Merge remote into local message */ ret = ldb_msg_merge_local(sc->ac->module, ares->message, sc->remote_res->message); if (ret) { talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } return map_up_callback(ldb, sc->ac->orig_req, ares); case LDB_REPLY_DONE: /* No local record found, continue with remote record */ if (sc->local_res == NULL) { return map_up_callback(ldb, sc->ac->orig_req, sc->remote_res); } return LDB_SUCCESS; default: ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: " "Unexpected result type in base search for local entry")); talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; }}/* Search the local part of a remote search result. */int map_remote_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares){ struct map_context *ac; struct map_search_context *sc; struct ldb_request *req; int ret; if (context == NULL || ares == NULL) { ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: " "NULL Context or Result in `map_remote_search_callback`")); return LDB_ERR_OPERATIONS_ERROR; } ac = talloc_get_type(context, struct map_context); /* It's not a record, stop searching */ if (ares->type != LDB_REPLY_ENTRY) { return map_up_callback(ldb, ac->orig_req, ares); } /* Map result record into a local message */ ret = map_reply_remote(ac, ares); if (ret) { talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } /* There is no local db, stop searching */ if (!map_check_local_db(ac->module)) { return map_up_callback(ldb, ac->orig_req, ares); } /* Prepare local search context */ sc = map_init_search_context(ac, ares); if (sc == NULL) { talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } /* Prepare local search request */ /* TODO: use GUIDs here instead? */ ac->search_reqs = talloc_realloc(ac, ac->search_reqs, struct ldb_request *, ac->num_searches + 2); if (ac->search_reqs == NULL) { talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } ac->search_reqs[ac->num_searches] = req = map_search_base_req(ac, ares->message->dn, NULL, NULL, sc, map_local_merge_callback); if (req == NULL) { talloc_free(sc); talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } ac->num_searches++; ac->search_reqs[ac->num_searches] = NULL; return ldb_next_request(ac->module, req);}/* Search a record. */int map_search(struct ldb_module *module, struct ldb_request *req){ struct ldb_handle *h; struct map_context *ac; struct ldb_parse_tree *local_tree, *remote_tree; int ret; const char *wildcard[] = { "*", NULL }; const char * const *attrs; if (!module->private_data) /* if we're not yet initialized, go to the next module */ return ldb_next_request(module, req); /* Do not manipulate our control entries */ if (ldb_dn_is_special(req->op.search.base)) return ldb_next_request(module, req); /* No mapping requested, skip to next module */ if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) { return ldb_next_request(module, req); } /* TODO: How can we be sure about which partition we are * targetting when there is no search base? */ /* Prepare context and handle */ h = map_init_handle(req, module); if (h == NULL) { return LDB_ERR_OPERATIONS_ERROR; } ac = talloc_get_type(h->private_data, struct map_context); ac->search_reqs = talloc_array(ac, struct ldb_request *, 2); if (ac->search_reqs == NULL) { talloc_free(h); return LDB_ERR_OPERATIONS_ERROR; } ac->num_searches = 1; ac->search_reqs[1] = NULL; /* Prepare the remote operation */ ac->search_reqs[0] = talloc(ac, struct ldb_request); if (ac->search_reqs[0] == NULL) { goto oom; } *(ac->search_reqs[0]) = *req; /* copy the request */ ac->search_reqs[0]->handle = h; /* return our own handle to deal with this call */ ac->search_reqs[0]->context = ac; ac->search_reqs[0]->callback = map_remote_search_callback; /* It is easier to deal with the two different ways of * expressing the wildcard in the same codepath */ attrs = req->op.search.attrs; if (attrs == NULL) { attrs = wildcard; } /* Split local from remote attrs */ ret = map_attrs_collect_and_partition(module, ac, attrs, req->op.search.tree); if (ret) { goto failed; } ac->search_reqs[0]->op.search.attrs = ac->remote_attrs; /* Split local from remote tree */ ret = ldb_parse_tree_partition(module, ac, ac->search_reqs[0], &local_tree, &remote_tree, req->op.search.tree); if (ret) { goto failed; } if (((local_tree != NULL) && (remote_tree != NULL)) && (!ldb_parse_tree_check_splittable(req->op.search.tree))) { /* The query can't safely be split, enumerate the remote partition */ local_tree = NULL; remote_tree = NULL; } if (local_tree == NULL) { /* Construct default local parse tree */ local_tree = talloc_zero(ac, struct ldb_parse_tree); if (local_tree == NULL) { map_oom(ac->module); goto failed; } local_tree->operation = LDB_OP_PRESENT; local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED); } if (remote_tree == NULL) { /* Construct default remote parse tree */ remote_tree = ldb_parse_tree(ac->search_reqs[0], NULL); if (remote_tree == NULL) { goto failed; } } ac->local_tree = local_tree; ac->search_reqs[0]->op.search.tree = remote_tree; ldb_set_timeout_from_prev_req(module->ldb, req, ac->search_reqs[0]); h->state = LDB_ASYNC_INIT; h->status = LDB_SUCCESS; ac->step = MAP_SEARCH_REMOTE; ret = ldb_next_remote_request(module, ac->search_reqs[0]); if (ret == LDB_SUCCESS) { req->handle = h; } return ret;oom: map_oom(module);failed: talloc_free(h); return LDB_ERR_OPERATIONS_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -