2 ldb database mapping module
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
7 * NOTICE: this module is NOT released under the GNU LGPL license as
8 * other ldb code. This module is release under the GNU GPL v2 or
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "ldb/include/includes.h"
29 #include "ldb/modules/ldb_map.h"
30 #include "ldb/modules/ldb_map_private.h"
34 * ================== */
36 /* Select attributes that stay in the local partition. */
37 static const char **map_attrs_select_local(struct ldb_module
*module
, void *mem_ctx
, const char * const *attrs
)
39 const struct ldb_map_context
*data
= map_get_context(module
);
47 result
= talloc_array(mem_ctx
, const char *, 1);
53 for (i
= 0; attrs
[i
]; i
++) {
54 /* Wildcards and ignored attributes are kept locally */
55 if ((ldb_attr_cmp(attrs
[i
], "*") == 0) ||
56 (!map_attr_check_remote(data
, attrs
[i
]))) {
57 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
62 result
[last
] = talloc_strdup(result
, attrs
[i
]);
63 result
[last
+1] = NULL
;
76 /* Collect attributes that are mapped into the remote partition. */
77 static const char **map_attrs_collect_remote(struct ldb_module
*module
, void *mem_ctx
, const char * const *attrs
)
79 const struct ldb_map_context
*data
= map_get_context(module
);
81 const struct ldb_map_attribute
*map
;
82 const char *name
=NULL
;
89 result
= talloc_array(mem_ctx
, const char *, 1);
95 for (i
= 0; attrs
[i
]; i
++) {
96 /* Wildcards are kept remotely, too */
97 if (ldb_attr_cmp(attrs
[i
], "*") == 0) {
102 /* Add remote names of mapped attrs */
103 map
= map_attr_find_local(data
, attrs
[i
]);
118 name
= map
->u
.rename
.remote_name
;
122 /* Add all remote names of "generate" attrs */
123 for (j
= 0; map
->u
.generate
.remote_names
[j
]; j
++) {
124 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
125 if (result
== NULL
) {
129 result
[last
] = talloc_strdup(result
, map
->u
.generate
.remote_names
[j
]);
130 result
[last
+1] = NULL
;
136 named
: /* We found a single remote name, add that */
137 result
= talloc_realloc(mem_ctx
, result
, const char *, last
+2);
138 if (result
== NULL
) {
142 result
[last
] = talloc_strdup(result
, name
);
143 result
[last
+1] = NULL
;
155 /* Split attributes that stay in the local partition from those that
156 * are mapped into the remote partition. */
157 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
)
159 *local_attrs
= map_attrs_select_local(module
, local_ctx
, attrs
);
160 *remote_attrs
= map_attrs_collect_remote(module
, remote_ctx
, attrs
);
165 /* Merge two lists of attributes into a single one. */
166 static int map_attrs_merge(struct ldb_module
*module
, void *mem_ctx
, const char ***attrs
, const char * const *more_attrs
)
170 for (i
= 0; (*attrs
)[i
]; i
++) /* noop */ ;
171 for (j
= 0; more_attrs
[j
]; j
++) /* noop */ ;
173 *attrs
= talloc_realloc(mem_ctx
, *attrs
, const char *, i
+j
+1);
174 if (*attrs
== NULL
) {
179 for (k
= 0; k
< j
; k
++) {
180 (*attrs
)[i
+k
] = more_attrs
[k
];
183 (*attrs
)[i
+k
] = NULL
;
188 /* Mapping ldb values
189 * ================== */
191 /* Map an ldb value from a parse tree into the remote partition. */
192 static struct ldb_val
ldb_val_map_subtree(struct ldb_module
*module
, struct ldb_parse_tree
*new, const struct ldb_map_attribute
*map
, const struct ldb_parse_tree
*tree
)
196 /* Extract the old value */
197 switch (tree
->operation
) {
198 case LDB_OP_EQUALITY
:
199 val
= tree
->u
.equality
.value
;
204 val
= tree
->u
.comparison
.value
;
206 case LDB_OP_EXTENDED
:
207 val
= tree
->u
.extended
.value
;
212 return ldb_val_dup(new, &val
);
215 /* Convert to the new value */
216 return ldb_val_map_local(module
, new, map
, val
);
219 /* Mapping message elements
220 * ======================== */
222 /* Add an element to a message, overwriting any old identically named elements. */
223 static int ldb_msg_replace(struct ldb_message
*msg
, const struct ldb_message_element
*el
)
225 struct ldb_message_element
*old
;
227 old
= ldb_msg_find_element(msg
, el
->name
);
229 /* no local result, add as new element */
231 if (ldb_msg_add_empty(msg
, el
->name
, 0) != 0) {
235 old
= ldb_msg_find_element(msg
, el
->name
);
241 *old
= *el
; /* copy new element */
246 /* Map a message element back into the local partition. */
247 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
)
249 struct ldb_message_element
*el
;
252 el
= talloc_zero(mem_ctx
, struct ldb_message_element
);
258 el
->num_values
= old
->num_values
;
259 el
->values
= talloc_array(el
, struct ldb_val
, el
->num_values
);
260 if (el
->values
== NULL
) {
266 el
->name
= map_attr_map_remote(el
, map
, old
->name
);
268 for (i
= 0; i
< el
->num_values
; i
++) {
269 el
->values
[i
] = ldb_val_map_remote(module
, el
->values
, map
, old
->values
[i
]);
275 /* Merge a remote message element into a local message. */
276 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
)
278 const struct ldb_map_context
*data
= map_get_context(module
);
279 const struct ldb_map_attribute
*map
= map_attr_find_remote(data
, attr_name
);
280 struct ldb_message_element
*el
=NULL
;
282 /* Unknown attribute in remote message:
283 * skip, attribute was probably auto-generated */
285 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
286 "Skipping attribute '%s': no mapping found\n",
296 if (map
->u
.convert
.convert_remote
== NULL
) {
297 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
298 "Skipping attribute '%s': "
299 "'convert_remote' not set\n",
306 el
= ldb_msg_el_map_remote(module
, local
, map
, old
);
310 if (map
->u
.generate
.generate_local
== NULL
) {
311 ldb_debug(module
->ldb
, LDB_DEBUG_ERROR
, "ldb_map: "
312 "Skipping attribute '%s': "
313 "'generate_local' not set\n",
318 el
= map
->u
.generate
.generate_local(module
, local
, old
->name
, remote
);
326 return ldb_msg_replace(local
, el
);
330 * ================ */
332 /* Merge two local messages into a single one. */
333 static int ldb_msg_merge_local(struct ldb_module
*module
, struct ldb_message
*msg1
, struct ldb_message
*msg2
)
337 for (i
= 0; i
< msg2
->num_elements
; i
++) {
338 ret
= ldb_msg_replace(msg1
, &msg2
->elements
[i
]);
347 /* Merge a local and a remote message into a single local one. */
348 static int ldb_msg_merge_remote(struct ldb_module
*module
, struct ldb_message
*local
, struct ldb_message
*remote
)
352 /* Try to map each attribute back;
353 * Add to local message is possible,
354 * Overwrite old local attribute if necessary */
355 for (i
= 0; i
< remote
->num_elements
; i
++) {
356 ret
= ldb_msg_el_merge(module
, local
, remote
, remote
->elements
[i
].name
, &remote
->elements
[i
]);
365 /* Mapping search results
366 * ====================== */
368 /* Map a search result back into the local partition. */
369 static int map_reply_remote(struct ldb_module
*module
, struct ldb_reply
*ares
)
371 struct ldb_message
*msg
;
375 /* There is no result message, skip */
376 if (ares
->type
!= LDB_REPLY_ENTRY
) {
380 /* Create a new result message */
381 msg
= ldb_msg_new(ares
);
387 /* Merge remote message into new message */
388 ret
= ldb_msg_merge_remote(module
, msg
, ares
->message
);
394 /* Create corresponding local DN */
395 dn
= ldb_dn_map_rebase_remote(module
, msg
, ares
->message
->dn
);
402 /* Store new message with new DN as the result */
403 talloc_free(ares
->message
);
409 /* Mapping parse trees
410 * =================== */
412 /* Check whether a parse tree can safely be split in two. */
413 static BOOL
ldb_parse_tree_check_splittable(const struct ldb_parse_tree
*tree
)
415 const struct ldb_parse_tree
*subtree
= tree
;
419 switch (subtree
->operation
) {
422 subtree
= subtree
->u
.isnot
.child
;
426 return !negate
; /* if negate: False */
429 return negate
; /* if negate: True */
432 return True
; /* simple parse tree */
436 return True
; /* no parse tree */
439 /* Collect a list of attributes required to match a given parse tree. */
440 static int ldb_parse_tree_collect_attrs(struct ldb_module
*module
, void *mem_ctx
, const char ***attrs
, const struct ldb_parse_tree
*tree
)
442 const char **new_attrs
;
449 switch (tree
->operation
) {
451 case LDB_OP_AND
: /* attributes stored in list of subtrees */
452 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
453 ret
= ldb_parse_tree_collect_attrs(module
, mem_ctx
, attrs
, tree
->u
.list
.elements
[i
]);
460 case LDB_OP_NOT
: /* attributes stored in single subtree */
461 return ldb_parse_tree_collect_attrs(module
, mem_ctx
, attrs
, tree
->u
.isnot
.child
);
463 default: /* single attribute in tree */
464 new_attrs
= ldb_attr_list_copy_add(mem_ctx
, *attrs
, tree
->u
.equality
.attr
);
473 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
475 /* Select a negated subtree that queries attributes in the local partition */
476 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
)
478 struct ldb_parse_tree
*child
;
481 /* Prepare new tree */
482 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
488 /* Generate new subtree */
489 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.isnot
.child
);
495 /* Prune tree without subtree */
502 (*new)->u
.isnot
.child
= child
;
507 /* Select a list of subtrees that query attributes in the local partition */
508 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
)
512 /* Prepare new tree */
513 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
519 /* Prepare list of subtrees */
520 (*new)->u
.list
.num_elements
= 0;
521 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
522 if ((*new)->u
.list
.elements
== NULL
) {
528 /* Generate new list of subtrees */
530 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
531 struct ldb_parse_tree
*child
;
532 ret
= map_subtree_select_local(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
539 (*new)->u
.list
.elements
[j
] = child
;
544 /* Prune tree without subtrees */
551 /* Fix subtree list size */
552 (*new)->u
.list
.num_elements
= j
;
553 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
558 /* Select a simple subtree that queries attributes in the local partition */
559 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
)
561 /* Prepare new tree */
562 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
571 /* Select subtrees that query attributes in the local partition */
572 static int map_subtree_select_local(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
574 const struct ldb_map_context
*data
= map_get_context(module
);
580 if (tree
->operation
== LDB_OP_NOT
) {
581 return map_subtree_select_local_not(module
, mem_ctx
, new, tree
);
584 if (tree
->operation
== LDB_OP_AND
|| tree
->operation
== LDB_OP_OR
) {
585 return map_subtree_select_local_list(module
, mem_ctx
, new, tree
);
588 if (map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
593 return map_subtree_select_local_simple(module
, mem_ctx
, new, tree
);
596 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
);
598 /* Collect a negated subtree that queries attributes in the remote partition */
599 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
)
601 struct ldb_parse_tree
*child
;
604 /* Prepare new tree */
605 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
611 /* Generate new subtree */
612 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.isnot
.child
);
618 /* Prune tree without subtree */
625 (*new)->u
.isnot
.child
= child
;
630 /* Collect a list of subtrees that query attributes in the remote partition */
631 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
)
635 /* Prepare new tree */
636 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
642 /* Prepare list of subtrees */
643 (*new)->u
.list
.num_elements
= 0;
644 (*new)->u
.list
.elements
= talloc_array(*new, struct ldb_parse_tree
*, tree
->u
.list
.num_elements
);
645 if ((*new)->u
.list
.elements
== NULL
) {
651 /* Generate new list of subtrees */
653 for (i
= 0; i
< tree
->u
.list
.num_elements
; i
++) {
654 struct ldb_parse_tree
*child
;
655 ret
= map_subtree_collect_remote(module
, *new, &child
, tree
->u
.list
.elements
[i
]);
662 (*new)->u
.list
.elements
[j
] = child
;
667 /* Prune tree without subtrees */
674 /* Fix subtree list size */
675 (*new)->u
.list
.num_elements
= j
;
676 (*new)->u
.list
.elements
= talloc_realloc(*new, (*new)->u
.list
.elements
, struct ldb_parse_tree
*, (*new)->u
.list
.num_elements
);
681 /* Collect a simple subtree that queries attributes in the remote partition */
682 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
)
687 /* Prepare new tree */
688 *new = talloc_memdup(mem_ctx
, tree
, sizeof(struct ldb_parse_tree
));
694 /* Map attribute and value */
695 attr
= map_attr_map_local(*new, map
, tree
->u
.equality
.attr
);
701 val
= ldb_val_map_subtree(module
, *new, map
, tree
);
703 /* Store attribute and value in new tree */
704 switch (tree
->operation
) {
706 (*new)->u
.present
.attr
= attr
;
708 case LDB_OP_SUBSTRING
:
709 (*new)->u
.substring
.attr
= attr
;
710 (*new)->u
.substring
.chunks
= NULL
; /* FIXME! */
712 case LDB_OP_EQUALITY
:
713 (*new)->u
.equality
.attr
= attr
;
714 (*new)->u
.equality
.value
= val
;
719 (*new)->u
.comparison
.attr
= attr
;
720 (*new)->u
.comparison
.value
= val
;
722 case LDB_OP_EXTENDED
:
723 (*new)->u
.extended
.attr
= attr
;
724 (*new)->u
.extended
.value
= val
;
725 (*new)->u
.extended
.rule_id
= talloc_strdup(*new, tree
->u
.extended
.rule_id
);
727 default: /* unknown kind of simple subtree */
735 /* Collect subtrees that query attributes in the remote partition */
736 static int map_subtree_collect_remote(struct ldb_module
*module
, void *mem_ctx
, struct ldb_parse_tree
**new, const struct ldb_parse_tree
*tree
)
738 const struct ldb_map_context
*data
= map_get_context(module
);
739 const struct ldb_map_attribute
*map
;
745 if (tree
->operation
== LDB_OP_NOT
) {
746 return map_subtree_collect_remote_not(module
, mem_ctx
, new, tree
);
749 if ((tree
->operation
== LDB_OP_AND
) || (tree
->operation
== LDB_OP_OR
)) {
750 return map_subtree_collect_remote_list(module
, mem_ctx
, new, tree
);
753 if (!map_attr_check_remote(data
, tree
->u
.equality
.attr
)) {
758 map
= map_attr_find_local(data
, tree
->u
.equality
.attr
);
759 if (map
->convert_operator
) {
760 return map
->convert_operator(module
, mem_ctx
, new, tree
);
763 if (map
->type
== MAP_GENERATE
) {
764 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
765 "Skipping attribute '%s': "
766 "'convert_operator' not set\n",
767 tree
->u
.equality
.attr
);
772 return map_subtree_collect_remote_simple(module
, mem_ctx
, new, tree
, map
);
775 /* Split subtrees that query attributes in the local partition from
776 * those that query the remote partition. */
777 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
)
784 /* No original tree */
789 /* Generate local tree */
790 ret
= map_subtree_select_local(module
, local_ctx
, local_tree
, tree
);
795 /* Generate remote tree */
796 ret
= map_subtree_collect_remote(module
, remote_ctx
, remote_tree
, tree
);
798 talloc_free(*local_tree
);
805 /* Collect a list of attributes required either explicitly from a
806 * given list or implicitly from a given parse tree; split the
807 * collected list into local and remote parts. */
808 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
)
811 const char **tree_attrs
;
814 /* Clear initial lists of partitioned attributes */
816 *remote_attrs
= NULL
;
818 /* There are no searched attributes, just stick to that */
819 if (search_attrs
== NULL
) {
823 /* There is no tree, just partition the searched attributes */
825 return map_attrs_partition(module
, local_ctx
, remote_ctx
, local_attrs
, remote_attrs
, search_attrs
);
828 /* Create context for temporary memory */
829 tmp_ctx
= talloc_new(local_ctx
);
830 if (tmp_ctx
== NULL
) {
834 /* Prepare list of attributes from tree */
835 tree_attrs
= talloc_array(tmp_ctx
, const char *, 1);
836 if (tree_attrs
== NULL
) {
837 talloc_free(tmp_ctx
);
840 tree_attrs
[0] = NULL
;
842 /* Collect attributes from tree */
843 ret
= ldb_parse_tree_collect_attrs(module
, tmp_ctx
, &tree_attrs
, tree
);
848 /* Merge attributes from search operation */
849 ret
= map_attrs_merge(module
, tmp_ctx
, &tree_attrs
, search_attrs
);
854 /* Split local from remote attributes */
855 ret
= map_attrs_partition(module
, local_ctx
, remote_ctx
, local_attrs
, remote_attrs
, tree_attrs
);
858 /* Free temporary memory */
859 talloc_free(tmp_ctx
);
868 /* Outbound requests: search
869 * ========================= */
871 /* Pass a merged search result up the callback chain. */
872 int map_up_callback(struct ldb_context
*ldb
, const struct ldb_request
*req
, struct ldb_reply
*ares
)
876 /* No callback registered, stop */
877 if (req
->callback
== NULL
) {
881 /* Only records need special treatment */
882 if (ares
->type
!= LDB_REPLY_ENTRY
) {
883 return req
->callback(ldb
, req
->context
, ares
);
886 /* Merged result doesn't match original query, skip */
887 if (!ldb_match_msg(ldb
, ares
->message
, req
->op
.search
.tree
, req
->op
.search
.base
, req
->op
.search
.scope
)) {
888 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "ldb_map: "
889 "Skipping record '%s': "
890 "doesn't match original search\n",
891 ldb_dn_linearize(ldb
, ares
->message
->dn
));
895 /* Limit result to requested attrs */
896 if ((req
->op
.search
.attrs
) && (!ldb_attr_in_list(req
->op
.search
.attrs
, "*"))) {
897 for (i
= 0; i
< ares
->message
->num_elements
; i
++) {
898 const struct ldb_message_element
*el
= &ares
->message
->elements
[i
];
899 if (!ldb_attr_in_list(req
->op
.search
.attrs
, el
->name
)) {
900 ldb_msg_remove_attr(ares
->message
, el
->name
);
905 return req
->callback(ldb
, req
->context
, ares
);
908 /* Merge the remote and local parts of a search result. */
909 int map_local_merge_callback(struct ldb_context
*ldb
, void *context
, struct ldb_reply
*ares
)
911 struct map_search_context
*sc
;
914 if (context
== NULL
|| ares
== NULL
) {
915 ldb_set_errstring(ldb
, talloc_asprintf(ldb
, "ldb_map: "
916 "NULL Context or Result in `map_local_merge_callback`"));
917 return LDB_ERR_OPERATIONS_ERROR
;
920 sc
= talloc_get_type(context
, struct map_search_context
);
922 switch (ares
->type
) {
923 case LDB_REPLY_ENTRY
:
924 /* We have already found a local record */
926 ldb_set_errstring(ldb
, talloc_asprintf(ldb
, "ldb_map: "
927 "Too many results to base search for local entry"));
929 return LDB_ERR_OPERATIONS_ERROR
;
932 /* Store local result */
933 sc
->local_res
= ares
;
935 /* Merge remote into local message */
936 ret
= ldb_msg_merge_local(sc
->ac
->module
, ares
->message
, sc
->remote_res
->message
);
939 return LDB_ERR_OPERATIONS_ERROR
;
942 return map_up_callback(ldb
, sc
->ac
->orig_req
, ares
);
945 /* No local record found, continue with remote record */
946 if (sc
->local_res
== NULL
) {
947 return map_up_callback(ldb
, sc
->ac
->orig_req
, sc
->remote_res
);
952 ldb_set_errstring(ldb
, talloc_asprintf(ldb
, "ldb_map: "
953 "Unexpected result type in base search for local entry"));
955 return LDB_ERR_OPERATIONS_ERROR
;
959 /* Search the local part of a remote search result. */
960 int map_remote_search_callback(struct ldb_context
*ldb
, void *context
, struct ldb_reply
*ares
)
962 struct map_context
*ac
;
963 struct map_search_context
*sc
;
964 struct ldb_request
*req
;
967 if (context
== NULL
|| ares
== NULL
) {
968 ldb_set_errstring(ldb
, talloc_asprintf(ldb
, "ldb_map: "
969 "NULL Context or Result in `map_remote_search_callback`"));
970 return LDB_ERR_OPERATIONS_ERROR
;
973 ac
= talloc_get_type(context
, struct map_context
);
975 /* It's not a record, stop searching */
976 if (ares
->type
!= LDB_REPLY_ENTRY
) {
977 return map_up_callback(ldb
, ac
->orig_req
, ares
);
980 /* Map result record into a local message */
981 ret
= map_reply_remote(ac
->module
, ares
);
984 return LDB_ERR_OPERATIONS_ERROR
;
987 /* There is no local db, stop searching */
988 if (!map_check_local_db(ac
->module
)) {
989 return map_up_callback(ldb
, ac
->orig_req
, ares
);
992 /* Prepare local search context */
993 sc
= map_init_search_context(ac
, ares
);
996 return LDB_ERR_OPERATIONS_ERROR
;
999 /* Prepare local search request */
1000 /* TODO: use GUIDs here instead? */
1002 ac
->search_reqs
= talloc_realloc(ac
, ac
->search_reqs
, struct ldb_request
*, ac
->num_searches
+ 2);
1003 if (ac
->search_reqs
== NULL
) {
1005 return LDB_ERR_OPERATIONS_ERROR
;
1008 ac
->search_reqs
[ac
->num_searches
]
1009 = req
= map_search_base_req(ac
, ares
->message
->dn
,
1010 NULL
, NULL
, sc
, map_local_merge_callback
);
1014 return LDB_ERR_OPERATIONS_ERROR
;
1017 ac
->search_reqs
[ac
->num_searches
] = NULL
;
1019 return ldb_next_request(ac
->module
, req
);
1022 /* Search a record. */
1023 int map_search(struct ldb_module
*module
, struct ldb_request
*req
)
1025 struct ldb_handle
*h
;
1026 struct map_context
*ac
;
1027 struct ldb_parse_tree
*local_tree
, *remote_tree
;
1028 const char **local_attrs
, **remote_attrs
;
1031 /* Do not manipulate our control entries */
1032 if (ldb_dn_is_special(req
->op
.search
.base
))
1033 return ldb_next_request(module
, req
);
1035 /* No mapping requested, skip to next module */
1036 if ((req
->op
.search
.base
) && (!ldb_dn_check_local(module
, req
->op
.search
.base
))) {
1037 return ldb_next_request(module
, req
);
1040 /* TODO: How can we be sure about which partition we are
1041 * targetting when there is no search base? */
1043 /* Prepare context and handle */
1044 h
= map_init_handle(req
, module
);
1046 return LDB_ERR_OPERATIONS_ERROR
;
1048 ac
= talloc_get_type(h
->private_data
, struct map_context
);
1050 ac
->search_reqs
= talloc_array(ac
, struct ldb_request
*, 2);
1051 if (ac
->search_reqs
== NULL
) {
1053 return LDB_ERR_OPERATIONS_ERROR
;
1055 ac
->num_searches
= 1;
1056 ac
->search_reqs
[1] = NULL
;
1058 /* Prepare the remote operation */
1059 ac
->search_reqs
[0] = talloc(ac
, struct ldb_request
);
1060 if (ac
->search_reqs
[0] == NULL
) {
1064 *(ac
->search_reqs
[0]) = *req
; /* copy the request */
1066 ac
->search_reqs
[0]->handle
= h
; /* return our own handle to deal with this call */
1068 ac
->search_reqs
[0]->context
= ac
;
1069 ac
->search_reqs
[0]->callback
= map_remote_search_callback
;
1071 /* Split local from remote attrs */
1072 ret
= map_attrs_collect_and_partition(module
, ac
, ac
->search_reqs
[0], &local_attrs
, &remote_attrs
, req
->op
.search
.attrs
, req
->op
.search
.tree
);
1077 ac
->local_attrs
= local_attrs
;
1078 ac
->search_reqs
[0]->op
.search
.attrs
= remote_attrs
;
1080 /* Split local from remote tree */
1081 ret
= ldb_parse_tree_partition(module
, ac
, ac
->search_reqs
[0], &local_tree
, &remote_tree
, req
->op
.search
.tree
);
1086 if (((local_tree
!= NULL
) && (remote_tree
!= NULL
)) &&
1087 (!ldb_parse_tree_check_splittable(req
->op
.search
.tree
))) {
1088 /* The query can't safely be split, enumerate the remote partition */
1093 if (local_tree
== NULL
) {
1094 /* Construct default local parse tree */
1095 local_tree
= talloc_zero(ac
, struct ldb_parse_tree
);
1096 if (local_tree
== NULL
) {
1097 map_oom(ac
->module
);
1101 local_tree
->operation
= LDB_OP_PRESENT
;
1102 local_tree
->u
.present
.attr
= talloc_strdup(local_tree
, IS_MAPPED
);
1104 if (remote_tree
== NULL
) {
1105 /* Construct default remote parse tree */
1106 remote_tree
= ldb_parse_tree(ac
->search_reqs
[0], NULL
);
1107 if (remote_tree
== NULL
) {
1112 ac
->local_tree
= local_tree
;
1113 ac
->search_reqs
[0]->op
.search
.tree
= remote_tree
;
1115 ldb_set_timeout_from_prev_req(module
->ldb
, req
, ac
->search_reqs
[0]);
1117 h
->state
= LDB_ASYNC_INIT
;
1118 h
->status
= LDB_SUCCESS
;
1120 ac
->step
= MAP_SEARCH_REMOTE
;
1122 ret
= ldb_next_remote_request(module
, ac
->search_reqs
[0]);
1123 if (ret
== LDB_SUCCESS
) {
1132 return LDB_ERR_OPERATIONS_ERROR
;