2 ldb database mapping module
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
8 * NOTICE: this module is NOT released under the GNU LGPL license as
9 * other ldb code. This module is release under the GNU GPL v2 or
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include "ldb/include/includes.h"
30 #include "ldb/modules/ldb_map.h"
31 #include "ldb/modules/ldb_map_private.h"
35 * ================== */
37 /* Select attributes that stay in the local partition. */
38 static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
40 const struct ldb_map_context *data = map_get_context(module);
48 result = talloc_array(mem_ctx, const char *, 1);
54 for (i = 0; attrs[i]; i++) {
55 /* Wildcards and ignored attributes are kept locally */
56 if ((ldb_attr_cmp(attrs[i], "*") == 0) ||
57 (!map_attr_check_remote(data, attrs[i]))) {
58 result = talloc_realloc(mem_ctx, result, const char *, last+2);
63 result[last] = talloc_strdup(result, attrs[i]);
64 result[last+1] = NULL;
77 /* Collect attributes that are mapped into the remote partition. */
78 static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx, const char * const *attrs)
80 const struct ldb_map_context *data = map_get_context(module);
82 const struct ldb_map_attribute *map;
83 const char *name=NULL;
88 result = talloc_array(mem_ctx, const char *, 1);
94 for (i = 0; attrs[i]; i++) {
95 /* Wildcards are kept remotely, too */
96 if (ldb_attr_cmp(attrs[i], "*") == 0) {
97 const char **new_attrs = NULL;
98 ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs);
99 if (ret != LDB_SUCCESS) {
102 ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes);
103 if (ret != LDB_SUCCESS) {
112 for (i = 0; attrs[i]; i++) {
113 /* Wildcards are kept remotely, too */
114 if (ldb_attr_cmp(attrs[i], "*") == 0) {
115 /* Add all 'include in wildcard' attributes */
120 /* Add remote names of mapped attrs */
121 map = map_attr_find_local(data, attrs[i]);
136 name = map->u.rename.remote_name;
140 /* Add all remote names of "generate" attrs */
141 for (j = 0; map->u.generate.remote_names[j]; j++) {
142 result = talloc_realloc(mem_ctx, result, const char *, last+2);
143 if (result == NULL) {
147 result[last] = talloc_strdup(result, map->u.generate.remote_names[j]);
148 result[last+1] = NULL;
154 named: /* We found a single remote name, add that */
155 result = talloc_realloc(mem_ctx, result, const char *, last+2);
156 if (result == NULL) {
160 result[last] = talloc_strdup(result, name);
161 result[last+1] = NULL;
173 /* Split attributes that stay in the local partition from those that
174 * are mapped into the remote partition. */
175 static int map_attrs_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs)
177 *local_attrs = map_attrs_select_local(module, local_ctx, attrs);
178 *remote_attrs = map_attrs_collect_remote(module, remote_ctx, attrs);
183 /* Mapping message elements
184 * ======================== */
186 /* Add an element to a message, overwriting any old identically named elements. */
187 static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
189 struct ldb_message_element *old;
191 old = ldb_msg_find_element(msg, el->name);
193 /* no local result, add as new element */
195 if (ldb_msg_add_empty(msg, el->name, 0) != 0) {
199 old = ldb_msg_find_element(msg, el->name);
205 /* copy new element */
208 /* and make sure we reference the contents */
209 if (!talloc_reference(msg->elements, el->name)) {
212 if (!talloc_reference(msg->elements, el->values)) {
219 /* Map a message element back into the local partition. */
220 static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_message_element *old)
222 struct ldb_message_element *el;
225 el = talloc_zero(mem_ctx, struct ldb_message_element);
231 el->num_values = old->num_values;
232 el->values = talloc_array(el, struct ldb_val, el->num_values);
233 if (el->values == NULL) {
239 el->name = map_attr_map_remote(el, map, old->name);
241 for (i = 0; i < el->num_values; i++) {
242 el->values[i] = ldb_val_map_remote(module, el->values, map, old->values[i]);
248 /* Merge a remote message element into a local message. */
249 static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const char *attr_name, const struct ldb_message_element *old)
251 const struct ldb_map_context *data = map_get_context(module);
252 const struct ldb_map_attribute *map = map_attr_find_remote(data, attr_name);
253 struct ldb_message_element *el=NULL;
255 /* Unknown attribute in remote message:
256 * skip, attribute was probably auto-generated */
258 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
259 "Skipping attribute '%s': no mapping found\n",
269 if (map->u.convert.convert_remote == NULL) {
270 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
271 "Skipping attribute '%s': "
272 "'convert_remote' not set\n",
279 el = ldb_msg_el_map_remote(module, local, map, old);
283 if (map->u.generate.generate_local == NULL) {
284 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
285 "Skipping attribute '%s': "
286 "'generate_local' not set\n",
291 el = map->u.generate.generate_local(module, local, old->name, remote);
299 return ldb_msg_replace(local, el);
303 * ================ */
305 /* Merge two local messages into a single one. */
306 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2)
310 for (i = 0; i < msg2->num_elements; i++) {
311 ret = ldb_msg_replace(msg1, &msg2->elements[i]);
320 /* Merge a local and a remote message into a single local one. */
321 static int ldb_msg_merge_remote(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote)
325 /* Try to map each attribute back;
326 * Add to local message is possible,
327 * Overwrite old local attribute if necessary */
328 for (i = 0; i < remote->num_elements; i++) {
329 ret = ldb_msg_el_merge(module, local, remote, remote->elements[i].name, &remote->elements[i]);
338 /* Mapping search results
339 * ====================== */
341 /* Map a search result back into the local partition. */
342 static int map_reply_remote(struct ldb_module *module, struct ldb_reply *ares)
344 struct ldb_message *msg;
348 /* There is no result message, skip */
349 if (ares->type != LDB_REPLY_ENTRY) {
353 /* Create a new result message */
354 msg = ldb_msg_new(ares);
360 /* Merge remote message into new message */
361 ret = ldb_msg_merge_remote(module, msg, ares->message);
367 /* Create corresponding local DN */
368 dn = ldb_dn_map_rebase_remote(module, msg, ares->message->dn);
375 /* Store new message with new DN as the result */
376 talloc_free(ares->message);
382 /* Mapping parse trees
383 * =================== */
385 /* Check whether a parse tree can safely be split in two. */
386 static BOOL ldb_parse_tree_check_splittable(const struct ldb_parse_tree *tree)
388 const struct ldb_parse_tree *subtree = tree;
392 switch (subtree->operation) {
395 subtree = subtree->u.isnot.child;
399 return !negate; /* if negate: False */
402 return negate; /* if negate: True */
405 return True; /* simple parse tree */
409 return True; /* no parse tree */
412 /* Collect a list of attributes required to match a given parse tree. */
413 static int ldb_parse_tree_collect_attrs(struct ldb_module *module, void *mem_ctx, const char ***attrs, const struct ldb_parse_tree *tree)
415 const char **new_attrs;
422 switch (tree->operation) {
424 case LDB_OP_AND: /* attributes stored in list of subtrees */
425 for (i = 0; i < tree->u.list.num_elements; i++) {
426 ret = ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.list.elements[i]);
433 case LDB_OP_NOT: /* attributes stored in single subtree */
434 return ldb_parse_tree_collect_attrs(module, mem_ctx, attrs, tree->u.isnot.child);
436 default: /* single attribute in tree */
437 new_attrs = ldb_attr_list_copy_add(mem_ctx, *attrs, tree->u.equality.attr);
446 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
448 /* Select a negated subtree that queries attributes in the local partition */
449 static int map_subtree_select_local_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
451 struct ldb_parse_tree *child;
454 /* Prepare new tree */
455 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
461 /* Generate new subtree */
462 ret = map_subtree_select_local(module, *new, &child, tree->u.isnot.child);
468 /* Prune tree without subtree */
475 (*new)->u.isnot.child = child;
480 /* Select a list of subtrees that query attributes in the local partition */
481 static int map_subtree_select_local_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
485 /* Prepare new tree */
486 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
492 /* Prepare list of subtrees */
493 (*new)->u.list.num_elements = 0;
494 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
495 if ((*new)->u.list.elements == NULL) {
501 /* Generate new list of subtrees */
503 for (i = 0; i < tree->u.list.num_elements; i++) {
504 struct ldb_parse_tree *child;
505 ret = map_subtree_select_local(module, *new, &child, tree->u.list.elements[i]);
512 (*new)->u.list.elements[j] = child;
517 /* Prune tree without subtrees */
524 /* Fix subtree list size */
525 (*new)->u.list.num_elements = j;
526 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
531 /* Select a simple subtree that queries attributes in the local partition */
532 static int map_subtree_select_local_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
534 /* Prepare new tree */
535 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
544 /* Select subtrees that query attributes in the local partition */
545 static int map_subtree_select_local(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
547 const struct ldb_map_context *data = map_get_context(module);
553 if (tree->operation == LDB_OP_NOT) {
554 return map_subtree_select_local_not(module, mem_ctx, new, tree);
557 if (tree->operation == LDB_OP_AND || tree->operation == LDB_OP_OR) {
558 return map_subtree_select_local_list(module, mem_ctx, new, tree);
561 if (map_attr_check_remote(data, tree->u.equality.attr)) {
566 return map_subtree_select_local_simple(module, mem_ctx, new, tree);
569 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree);
571 /* Collect a negated subtree that queries attributes in the remote partition */
572 static int map_subtree_collect_remote_not(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
574 struct ldb_parse_tree *child;
577 /* Prepare new tree */
578 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
584 /* Generate new subtree */
585 ret = map_subtree_collect_remote(module, *new, &child, tree->u.isnot.child);
591 /* Prune tree without subtree */
598 (*new)->u.isnot.child = child;
603 /* Collect a list of subtrees that query attributes in the remote partition */
604 static int map_subtree_collect_remote_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
608 /* Prepare new tree */
609 *new = talloc_memdup(mem_ctx, tree, sizeof(struct ldb_parse_tree));
615 /* Prepare list of subtrees */
616 (*new)->u.list.num_elements = 0;
617 (*new)->u.list.elements = talloc_array(*new, struct ldb_parse_tree *, tree->u.list.num_elements);
618 if ((*new)->u.list.elements == NULL) {
624 /* Generate new list of subtrees */
626 for (i = 0; i < tree->u.list.num_elements; i++) {
627 struct ldb_parse_tree *child;
628 ret = map_subtree_collect_remote(module, *new, &child, tree->u.list.elements[i]);
635 (*new)->u.list.elements[j] = child;
640 /* Prune tree without subtrees */
647 /* Fix subtree list size */
648 (*new)->u.list.num_elements = j;
649 (*new)->u.list.elements = talloc_realloc(*new, (*new)->u.list.elements, struct ldb_parse_tree *, (*new)->u.list.num_elements);
654 /* Collect a simple subtree that queries attributes in the remote partition */
655 int map_subtree_collect_remote_simple(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree, const struct ldb_map_attribute *map)
659 /* Prepare new tree */
660 *new = talloc(mem_ctx, struct ldb_parse_tree);
667 if (map->type == MAP_KEEP) {
668 /* Nothing to do here */
672 /* Store attribute and value in new tree */
673 switch (tree->operation) {
675 attr = map_attr_map_local(*new, map, tree->u.present.attr);
676 (*new)->u.present.attr = attr;
678 case LDB_OP_SUBSTRING:
680 attr = map_attr_map_local(*new, map, tree->u.substring.attr);
681 (*new)->u.substring.attr = attr;
684 case LDB_OP_EQUALITY:
685 attr = map_attr_map_local(*new, map, tree->u.equality.attr);
686 (*new)->u.equality.attr = attr;
691 attr = map_attr_map_local(*new, map, tree->u.comparison.attr);
692 (*new)->u.comparison.attr = attr;
694 case LDB_OP_EXTENDED:
695 attr = map_attr_map_local(*new, map, tree->u.extended.attr);
696 (*new)->u.extended.attr = attr;
698 default: /* unknown kind of simple subtree */
709 if (map->type == MAP_RENAME) {
710 /* Nothing more to do here, the attribute has been renamed */
714 /* Store attribute and value in new tree */
715 switch (tree->operation) {
718 case LDB_OP_SUBSTRING:
722 (*new)->u.substring.chunks = NULL;
723 for (i=0; tree->u.substring.chunks[i]; i++) {
724 (*new)->u.substring.chunks = talloc_realloc(*new, (*new)->u.substring.chunks, struct ldb_val *, i+2);
725 if (!(*new)->u.substring.chunks) {
730 (*new)->u.substring.chunks[i] = talloc(*new, struct ldb_val);
731 if (!(*new)->u.substring.chunks[i]) {
736 *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, *tree->u.substring.chunks[i]);
737 (*new)->u.substring.chunks[i+1] = NULL;
741 case LDB_OP_EQUALITY:
742 (*new)->u.equality.value = ldb_val_map_local(module, *new, map, tree->u.equality.value);
747 (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, tree->u.comparison.value);
749 case LDB_OP_EXTENDED:
750 (*new)->u.extended.value = ldb_val_map_local(module, *new, map, tree->u.extended.value);
751 (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
753 default: /* unknown kind of simple subtree */
761 /* Collect subtrees that query attributes in the remote partition */
762 static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree)
764 const struct ldb_map_context *data = map_get_context(module);
765 const struct ldb_map_attribute *map;
771 if (tree->operation == LDB_OP_NOT) {
772 return map_subtree_collect_remote_not(module, mem_ctx, new, tree);
775 if ((tree->operation == LDB_OP_AND) || (tree->operation == LDB_OP_OR)) {
776 return map_subtree_collect_remote_list(module, mem_ctx, new, tree);
779 if (!map_attr_check_remote(data, tree->u.equality.attr)) {
784 map = map_attr_find_local(data, tree->u.equality.attr);
785 if (map->convert_operator) {
786 return map->convert_operator(module, mem_ctx, new, tree);
789 if (map->type == MAP_GENERATE) {
790 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
791 "Skipping attribute '%s': "
792 "'convert_operator' not set\n",
793 tree->u.equality.attr);
798 return map_subtree_collect_remote_simple(module, mem_ctx, new, tree, map);
801 /* Split subtrees that query attributes in the local partition from
802 * those that query the remote partition. */
803 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)
810 /* No original tree */
815 /* Generate local tree */
816 ret = map_subtree_select_local(module, local_ctx, local_tree, tree);
821 /* Generate remote tree */
822 ret = map_subtree_collect_remote(module, remote_ctx, remote_tree, tree);
824 talloc_free(*local_tree);
831 /* Collect a list of attributes required either explicitly from a
832 * given list or implicitly from a given parse tree; split the
833 * collected list into local and remote parts. */
834 static int map_attrs_collect_and_partition(struct ldb_module *module, void *local_ctx, void *remote_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *search_attrs, const struct ldb_parse_tree *tree)
837 const char **tree_attrs;
840 /* Clear initial lists of partitioned attributes */
842 *remote_attrs = NULL;
844 /* There is no tree, just partition the searched attributes */
846 return map_attrs_partition(module, local_ctx, remote_ctx, local_attrs, remote_attrs, search_attrs);
849 /* Create context for temporary memory */
850 tmp_ctx = talloc_new(local_ctx);
851 if (tmp_ctx == NULL) {
855 /* Prepare list of attributes from tree */
856 tree_attrs = talloc_array(tmp_ctx, const char *, 1);
857 if (tree_attrs == NULL) {
858 talloc_free(tmp_ctx);
861 tree_attrs[0] = NULL;
863 /* Collect attributes from tree */
864 ret = ldb_parse_tree_collect_attrs(module, tmp_ctx, &tree_attrs, tree);
869 /* Merge attributes from search operation */
870 ret = map_attrs_merge(module, tmp_ctx, &tree_attrs, search_attrs);
875 /* Split local from remote attributes */
876 ret = map_attrs_partition(module, local_ctx, remote_ctx, local_attrs, remote_attrs, tree_attrs);
879 /* Free temporary memory */
880 talloc_free(tmp_ctx);
889 /* Outbound requests: search
890 * ========================= */
892 /* Pass a merged search result up the callback chain. */
893 int map_up_callback(struct ldb_context *ldb, const struct ldb_request *req, struct ldb_reply *ares)
897 /* No callback registered, stop */
898 if (req->callback == NULL) {
902 /* Only records need special treatment */
903 if (ares->type != LDB_REPLY_ENTRY) {
904 return req->callback(ldb, req->context, ares);
907 /* Merged result doesn't match original query, skip */
908 if (!ldb_match_msg(ldb, ares->message, req->op.search.tree, req->op.search.base, req->op.search.scope)) {
909 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
910 "Skipping record '%s': "
911 "doesn't match original search\n",
912 ldb_dn_linearize(ldb, ares->message->dn));
916 /* Limit result to requested attrs */
917 if ((req->op.search.attrs) && (!ldb_attr_in_list(req->op.search.attrs, "*"))) {
918 for (i = 0; i < ares->message->num_elements; i++) {
919 const struct ldb_message_element *el = &ares->message->elements[i];
920 if (!ldb_attr_in_list(req->op.search.attrs, el->name)) {
921 ldb_msg_remove_attr(ares->message, el->name);
926 return req->callback(ldb, req->context, ares);
929 /* Merge the remote and local parts of a search result. */
930 int map_local_merge_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
932 struct map_search_context *sc;
935 if (context == NULL || ares == NULL) {
936 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
937 "NULL Context or Result in `map_local_merge_callback`"));
938 return LDB_ERR_OPERATIONS_ERROR;
941 sc = talloc_get_type(context, struct map_search_context);
943 switch (ares->type) {
944 case LDB_REPLY_ENTRY:
945 /* We have already found a local record */
947 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
948 "Too many results to base search for local entry"));
950 return LDB_ERR_OPERATIONS_ERROR;
953 /* Store local result */
954 sc->local_res = ares;
956 /* Merge remote into local message */
957 ret = ldb_msg_merge_local(sc->ac->module, ares->message, sc->remote_res->message);
960 return LDB_ERR_OPERATIONS_ERROR;
963 return map_up_callback(ldb, sc->ac->orig_req, ares);
966 /* No local record found, continue with remote record */
967 if (sc->local_res == NULL) {
968 return map_up_callback(ldb, sc->ac->orig_req, sc->remote_res);
973 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
974 "Unexpected result type in base search for local entry"));
976 return LDB_ERR_OPERATIONS_ERROR;
980 /* Search the local part of a remote search result. */
981 int map_remote_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
983 struct map_context *ac;
984 struct map_search_context *sc;
985 struct ldb_request *req;
988 if (context == NULL || ares == NULL) {
989 ldb_set_errstring(ldb, talloc_asprintf(ldb, "ldb_map: "
990 "NULL Context or Result in `map_remote_search_callback`"));
991 return LDB_ERR_OPERATIONS_ERROR;
994 ac = talloc_get_type(context, struct map_context);
996 /* It's not a record, stop searching */
997 if (ares->type != LDB_REPLY_ENTRY) {
998 return map_up_callback(ldb, ac->orig_req, ares);
1001 /* Map result record into a local message */
1002 ret = map_reply_remote(ac->module, ares);
1005 return LDB_ERR_OPERATIONS_ERROR;
1008 /* There is no local db, stop searching */
1009 if (!map_check_local_db(ac->module)) {
1010 return map_up_callback(ldb, ac->orig_req, ares);
1013 /* Prepare local search context */
1014 sc = map_init_search_context(ac, ares);
1017 return LDB_ERR_OPERATIONS_ERROR;
1020 /* Prepare local search request */
1021 /* TODO: use GUIDs here instead? */
1023 ac->search_reqs = talloc_realloc(ac, ac->search_reqs, struct ldb_request *, ac->num_searches + 2);
1024 if (ac->search_reqs == NULL) {
1026 return LDB_ERR_OPERATIONS_ERROR;
1029 ac->search_reqs[ac->num_searches]
1030 = req = map_search_base_req(ac, ares->message->dn,
1031 NULL, NULL, sc, map_local_merge_callback);
1035 return LDB_ERR_OPERATIONS_ERROR;
1038 ac->search_reqs[ac->num_searches] = NULL;
1040 return ldb_next_request(ac->module, req);
1043 /* Search a record. */
1044 int map_search(struct ldb_module *module, struct ldb_request *req)
1046 struct ldb_handle *h;
1047 struct map_context *ac;
1048 struct ldb_parse_tree *local_tree, *remote_tree;
1049 const char **local_attrs, **remote_attrs;
1052 const char *wildcard[] = { "*", NULL };
1053 const char * const *attrs;
1055 /* Do not manipulate our control entries */
1056 if (ldb_dn_is_special(req->op.search.base))
1057 return ldb_next_request(module, req);
1059 /* No mapping requested, skip to next module */
1060 if ((req->op.search.base) && (!ldb_dn_check_local(module, req->op.search.base))) {
1061 return ldb_next_request(module, req);
1064 /* TODO: How can we be sure about which partition we are
1065 * targetting when there is no search base? */
1067 /* Prepare context and handle */
1068 h = map_init_handle(req, module);
1070 return LDB_ERR_OPERATIONS_ERROR;
1072 ac = talloc_get_type(h->private_data, struct map_context);
1074 ac->search_reqs = talloc_array(ac, struct ldb_request *, 2);
1075 if (ac->search_reqs == NULL) {
1077 return LDB_ERR_OPERATIONS_ERROR;
1079 ac->num_searches = 1;
1080 ac->search_reqs[1] = NULL;
1082 /* Prepare the remote operation */
1083 ac->search_reqs[0] = talloc(ac, struct ldb_request);
1084 if (ac->search_reqs[0] == NULL) {
1088 *(ac->search_reqs[0]) = *req; /* copy the request */
1090 ac->search_reqs[0]->handle = h; /* return our own handle to deal with this call */
1092 ac->search_reqs[0]->context = ac;
1093 ac->search_reqs[0]->callback = map_remote_search_callback;
1095 /* It is easier to deal with the two different ways of
1096 * expressing the wildcard in the same codepath */
1097 attrs = req->op.search.attrs;
1098 if (attrs == NULL) {
1102 /* Split local from remote attrs */
1103 ret = map_attrs_collect_and_partition(module, ac, ac->search_reqs[0], &local_attrs, &remote_attrs, attrs, req->op.search.tree);
1108 ac->local_attrs = local_attrs;
1109 ac->search_reqs[0]->op.search.attrs = remote_attrs;
1111 /* Split local from remote tree */
1112 ret = ldb_parse_tree_partition(module, ac, ac->search_reqs[0], &local_tree, &remote_tree, req->op.search.tree);
1117 if (((local_tree != NULL) && (remote_tree != NULL)) &&
1118 (!ldb_parse_tree_check_splittable(req->op.search.tree))) {
1119 /* The query can't safely be split, enumerate the remote partition */
1124 if (local_tree == NULL) {
1125 /* Construct default local parse tree */
1126 local_tree = talloc_zero(ac, struct ldb_parse_tree);
1127 if (local_tree == NULL) {
1128 map_oom(ac->module);
1132 local_tree->operation = LDB_OP_PRESENT;
1133 local_tree->u.present.attr = talloc_strdup(local_tree, IS_MAPPED);
1135 if (remote_tree == NULL) {
1136 /* Construct default remote parse tree */
1137 remote_tree = ldb_parse_tree(ac->search_reqs[0], NULL);
1138 if (remote_tree == NULL) {
1143 ac->local_tree = local_tree;
1144 ac->search_reqs[0]->op.search.tree = remote_tree;
1146 ldb_set_timeout_from_prev_req(module->ldb, req, ac->search_reqs[0]);
1148 h->state = LDB_ASYNC_INIT;
1149 h->status = LDB_SUCCESS;
1151 ac->step = MAP_SEARCH_REMOTE;
1153 ret = ldb_next_remote_request(module, ac->search_reqs[0]);
1154 if (ret == LDB_SUCCESS) {
1163 return LDB_ERR_OPERATIONS_ERROR;