2 ldb database mapping module
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 Copyright (C) Simo Sorce <idra@samba.org> 2008
8 ** NOTE! The following LGPL license applies to the ldb
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library 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 GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "system/time.h"
31 #include "ldb_map_private.h"
34 /* Mapping message elements
35 * ======================== */
37 /* Map a message element into the remote partition. */
38 static struct ldb_message_element
*ldb_msg_el_map_local(struct ldb_module
*module
, void *mem_ctx
, const struct ldb_map_attribute
*map
, const struct ldb_message_element
*old
)
40 struct ldb_message_element
*el
;
43 el
= talloc_zero(mem_ctx
, struct ldb_message_element
);
49 el
->num_values
= old
->num_values
;
50 el
->values
= talloc_array(el
, struct ldb_val
, el
->num_values
);
51 if (el
->values
== NULL
) {
57 el
->name
= map_attr_map_local(el
, map
, old
->name
);
59 for (i
= 0; i
< el
->num_values
; i
++) {
60 el
->values
[i
] = ldb_val_map_local(module
, el
->values
, map
, &old
->values
[i
]);
66 /* Add a message element either to a local or to a remote message,
67 * depending on whether it goes into the local or remote partition. */
68 static int ldb_msg_el_partition(struct ldb_module
*module
, struct ldb_message
*local
, struct ldb_message
*remote
, const struct ldb_message
*msg
, const char *attr_name
, /* const char * const names[], */ const struct ldb_message_element
*old
)
70 const struct ldb_map_context
*data
= map_get_context(module
);
71 const struct ldb_map_attribute
*map
= map_attr_find_local(data
, attr_name
);
72 struct ldb_message_element
*el
=NULL
;
73 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
75 /* Unknown attribute: ignore */
77 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
78 "Not mapping attribute '%s': no mapping found",
88 if (map
->u
.convert
.convert_local
== NULL
) {
89 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
90 "Not mapping attribute '%s': "
91 "'convert_local' not set",
98 el
= ldb_msg_el_map_local(module
, remote
, map
, old
);
101 case LDB_MAP_GENERATE
:
102 if (map
->u
.generate
.generate_remote
== NULL
) {
103 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
104 "Not mapping attribute '%s': "
105 "'generate_remote' not set",
110 /* TODO: if this attr requires context:
111 * make sure all context attrs are mappable (in 'names')
112 * make sure all context attrs have already been mapped?
113 * maybe postpone generation until they have been mapped?
116 map
->u
.generate
.generate_remote(module
, map
->local_name
, msg
, remote
, local
);
124 return ldb_msg_add(remote
, el
, old
->flags
);
127 el
= talloc(local
, struct ldb_message_element
);
133 *el
= *old
; /* copy the old element */
135 return ldb_msg_add(local
, el
, old
->flags
);
139 * ================ */
141 /* Check whether a message will be (partially) mapped into the remote partition. */
142 static bool ldb_msg_check_remote(struct ldb_module
*module
, const struct ldb_message
*msg
)
144 const struct ldb_map_context
*data
= map_get_context(module
);
148 for (i
= 0; i
< msg
->num_elements
; i
++) {
149 ret
= map_attr_check_remote(data
, msg
->elements
[i
].name
);
158 /* Split message elements that stay in the local partition from those
159 * that are mapped into the remote partition. */
160 static int ldb_msg_partition(struct ldb_module
*module
, struct ldb_message
*local
, struct ldb_message
*remote
, const struct ldb_message
*msg
)
162 /* const char * const names[]; */
163 struct ldb_context
*ldb
;
167 ldb
= ldb_module_get_ctx(module
);
169 for (i
= 0; i
< msg
->num_elements
; i
++) {
170 /* Skip 'IS_MAPPED' */
171 if (ldb_attr_cmp(msg
->elements
[i
].name
, IS_MAPPED
) == 0) {
172 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
173 "Skipping attribute '%s'",
174 msg
->elements
[i
].name
);
178 ret
= ldb_msg_el_partition(module
, local
, remote
, msg
, msg
->elements
[i
].name
, &msg
->elements
[i
]);
188 static int map_add_do_local(struct map_context
*ac
);
189 static int map_modify_do_local(struct map_context
*ac
);
190 static int map_delete_do_local(struct map_context
*ac
);
191 static int map_rename_do_local(struct map_context
*ac
);
192 static int map_rename_do_fixup(struct map_context
*ac
);
193 static int map_rename_local_callback(struct ldb_request
*req
,
194 struct ldb_reply
*ares
);
197 /*****************************************************************************
198 * COMMON INBOUND functions
199 *****************************************************************************/
201 /* Store the DN of a single search result in context. */
202 static int map_search_self_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
204 struct ldb_context
*ldb
;
205 struct map_context
*ac
;
208 ac
= talloc_get_type(req
->context
, struct map_context
);
209 ldb
= ldb_module_get_ctx(ac
->module
);
212 return ldb_module_done(ac
->req
, NULL
, NULL
,
213 LDB_ERR_OPERATIONS_ERROR
);
215 if (ares
->error
!= LDB_SUCCESS
) {
216 return ldb_module_done(ac
->req
, ares
->controls
,
217 ares
->response
, ares
->error
);
220 /* We are interested only in the single reply */
222 case LDB_REPLY_ENTRY
:
223 /* We have already found a remote DN */
225 ldb_set_errstring(ldb
,
226 "Too many results!");
227 return ldb_module_done(ac
->req
, NULL
, NULL
,
228 LDB_ERR_OPERATIONS_ERROR
);
232 ac
->local_dn
= talloc_steal(ac
, ares
->message
->dn
);
237 switch (ac
->req
->operation
) {
239 ret
= map_modify_do_local(ac
);
242 ret
= map_delete_do_local(ac
);
245 ret
= map_rename_do_local(ac
);
248 /* if we get here we have definitely a problem */
249 ret
= LDB_ERR_OPERATIONS_ERROR
;
251 if (ret
!= LDB_SUCCESS
) {
252 return ldb_module_done(ac
->req
, NULL
, NULL
,
253 LDB_ERR_OPERATIONS_ERROR
);
257 /* ignore referrals */
265 /* Build a request to search the local record by its DN. */
266 static int map_search_self_req(struct ldb_request
**req
,
267 struct map_context
*ac
,
270 /* attrs[] is returned from this function in
271 * ac->search_req->op.search.attrs, so it must be static, as
272 * otherwise the compiler can put it on the stack */
273 static const char * const attrs
[] = { IS_MAPPED
, NULL
};
274 struct ldb_parse_tree
*tree
;
276 /* Limit search to records with 'IS_MAPPED' present */
277 tree
= ldb_parse_tree(ac
, "(" IS_MAPPED
"=*)");
280 return LDB_ERR_OPERATIONS_ERROR
;
283 *req
= map_search_base_req(ac
, dn
, attrs
, tree
,
284 ac
, map_search_self_callback
);
286 return LDB_ERR_OPERATIONS_ERROR
;
292 static int map_op_local_callback(struct ldb_request
*req
,
293 struct ldb_reply
*ares
)
295 struct ldb_context
*ldb
;
296 struct map_context
*ac
;
299 ac
= talloc_get_type(req
->context
, struct map_context
);
300 ldb
= ldb_module_get_ctx(ac
->module
);
303 return ldb_module_done(ac
->req
, NULL
, NULL
,
304 LDB_ERR_OPERATIONS_ERROR
);
306 if (ares
->error
!= LDB_SUCCESS
) {
307 return ldb_module_done(ac
->req
, ares
->controls
,
308 ares
->response
, ares
->error
);
311 if (ares
->type
!= LDB_REPLY_DONE
) {
312 ldb_asprintf_errstring(ldb
, "Invalid LDB reply type %d", ares
->type
);
313 return ldb_module_done(ac
->req
, NULL
, NULL
,
314 LDB_ERR_OPERATIONS_ERROR
);
317 /* Do the remote request. */
318 ret
= ldb_next_remote_request(ac
->module
, ac
->remote_req
);
319 if (ret
!= LDB_SUCCESS
) {
320 return ldb_module_done(ac
->req
, NULL
, NULL
,
321 LDB_ERR_OPERATIONS_ERROR
);
327 static int map_op_remote_callback(struct ldb_request
*req
,
328 struct ldb_reply
*ares
)
330 struct ldb_context
*ldb
;
331 struct map_context
*ac
;
333 ac
= talloc_get_type(req
->context
, struct map_context
);
334 ldb
= ldb_module_get_ctx(ac
->module
);
337 return ldb_module_done(ac
->req
, NULL
, NULL
,
338 LDB_ERR_OPERATIONS_ERROR
);
340 if (ares
->error
!= LDB_SUCCESS
) {
341 return ldb_module_done(ac
->req
, ares
->controls
,
342 ares
->response
, ares
->error
);
345 if (ares
->type
!= LDB_REPLY_DONE
) {
346 ldb_asprintf_errstring(ldb
, "Invalid LDB reply type %d", ares
->type
);
347 return ldb_module_done(ac
->req
, NULL
, NULL
,
348 LDB_ERR_OPERATIONS_ERROR
);
351 return ldb_module_done(ac
->req
, ares
->controls
,
352 ares
->response
, ares
->error
);
356 /*****************************************************************************
358 *****************************************************************************/
362 int ldb_map_add(struct ldb_module
*module
, struct ldb_request
*req
)
364 const struct ldb_message
*msg
= req
->op
.add
.message
;
365 struct ldb_context
*ldb
;
366 struct map_context
*ac
;
367 struct ldb_message
*remote_msg
;
370 ldb
= ldb_module_get_ctx(module
);
372 /* Do not manipulate our control entries */
373 if (ldb_dn_is_special(msg
->dn
)) {
374 return ldb_next_request(module
, req
);
377 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
378 if (!ldb_dn_check_local(module
, msg
->dn
)) {
379 return ldb_next_request(module
, req
);
382 /* No mapping needed, fail */
383 if (!ldb_msg_check_remote(module
, msg
)) {
384 return LDB_ERR_OPERATIONS_ERROR
;
387 /* Prepare context and handle */
388 ac
= map_init_context(module
, req
);
390 return LDB_ERR_OPERATIONS_ERROR
;
394 /* Prepare the local message */
395 ac
->local_msg
= ldb_msg_new(ac
);
396 if (ac
->local_msg
== NULL
) {
398 return LDB_ERR_OPERATIONS_ERROR
;
400 ac
->local_msg
->dn
= msg
->dn
;
402 /* Prepare the remote message */
403 remote_msg
= ldb_msg_new(ac
);
404 if (remote_msg
== NULL
) {
406 return LDB_ERR_OPERATIONS_ERROR
;
408 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
410 /* Split local from remote message */
411 ldb_msg_partition(module
, ac
->local_msg
, remote_msg
, msg
);
413 /* Prepare the remote operation */
414 ret
= ldb_build_add_req(&ac
->remote_req
, ldb
,
417 ac
, map_op_remote_callback
,
419 LDB_REQ_SET_LOCATION(ac
->remote_req
);
420 if (ret
!= LDB_SUCCESS
) {
421 return LDB_ERR_OPERATIONS_ERROR
;
424 if ((ac
->local_msg
->num_elements
== 0) ||
425 ( ! map_check_local_db(ac
->module
))) {
426 /* No local data or db, just run the remote request */
427 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
430 /* Store remote DN in 'IS_MAPPED' */
431 /* TODO: use GUIDs here instead */
432 ret
= ldb_msg_add_linearized_dn(ac
->local_msg
, IS_MAPPED
,
434 if (ret
!= LDB_SUCCESS
) {
435 return LDB_ERR_OPERATIONS_ERROR
;
438 return map_add_do_local(ac
);
441 /* Add the local record. */
442 static int map_add_do_local(struct map_context
*ac
)
444 struct ldb_request
*local_req
;
445 struct ldb_context
*ldb
;
448 ldb
= ldb_module_get_ctx(ac
->module
);
450 /* Prepare the local operation */
451 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
455 map_op_local_callback
,
457 LDB_REQ_SET_LOCATION(local_req
);
458 if (ret
!= LDB_SUCCESS
) {
459 return LDB_ERR_OPERATIONS_ERROR
;
461 return ldb_next_request(ac
->module
, local_req
);
464 /*****************************************************************************
466 *****************************************************************************/
468 /* Modify a record. */
469 int ldb_map_modify(struct ldb_module
*module
, struct ldb_request
*req
)
471 const struct ldb_message
*msg
= req
->op
.mod
.message
;
472 struct ldb_request
*search_req
;
473 struct ldb_message
*remote_msg
;
474 struct ldb_context
*ldb
;
475 struct map_context
*ac
;
478 ldb
= ldb_module_get_ctx(module
);
480 /* Do not manipulate our control entries */
481 if (ldb_dn_is_special(msg
->dn
)) {
482 return ldb_next_request(module
, req
);
485 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
486 if (!ldb_dn_check_local(module
, msg
->dn
)) {
487 return ldb_next_request(module
, req
);
490 /* No mapping needed, skip to next module */
491 /* TODO: What if the remote part exists, the local doesn't,
492 * and this request wants to modify local data and thus
493 * add the local record? */
494 if (!ldb_msg_check_remote(module
, msg
)) {
495 return LDB_ERR_OPERATIONS_ERROR
;
498 /* Prepare context and handle */
499 ac
= map_init_context(module
, req
);
501 return LDB_ERR_OPERATIONS_ERROR
;
504 /* Prepare the local message */
505 ac
->local_msg
= ldb_msg_new(ac
);
506 if (ac
->local_msg
== NULL
) {
508 return LDB_ERR_OPERATIONS_ERROR
;
510 ac
->local_msg
->dn
= msg
->dn
;
512 /* Prepare the remote message */
513 remote_msg
= ldb_msg_new(ac
->remote_req
);
514 if (remote_msg
== NULL
) {
516 return LDB_ERR_OPERATIONS_ERROR
;
518 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
520 /* Split local from remote message */
521 ldb_msg_partition(module
, ac
->local_msg
, remote_msg
, msg
);
523 /* Prepare the remote operation */
524 ret
= ldb_build_mod_req(&ac
->remote_req
, ldb
,
527 ac
, map_op_remote_callback
,
529 LDB_REQ_SET_LOCATION(ac
->remote_req
);
530 if (ret
!= LDB_SUCCESS
) {
531 return LDB_ERR_OPERATIONS_ERROR
;
534 if ((ac
->local_msg
->num_elements
== 0) ||
535 ( ! map_check_local_db(ac
->module
))) {
536 /* No local data or db, just run the remote request */
537 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
540 /* prepare the search operation */
541 ret
= map_search_self_req(&search_req
, ac
, msg
->dn
);
542 if (ret
!= LDB_SUCCESS
) {
543 return LDB_ERR_OPERATIONS_ERROR
;
546 return ldb_next_request(module
, search_req
);
549 /* Modify the local record. */
550 static int map_modify_do_local(struct map_context
*ac
)
552 struct ldb_request
*local_req
;
553 struct ldb_context
*ldb
;
556 ldb
= ldb_module_get_ctx(ac
->module
);
558 if (ac
->local_dn
== NULL
) {
559 /* No local record present, add it instead */
560 /* Add local 'IS_MAPPED' */
561 /* TODO: use GUIDs here instead */
562 if (ldb_msg_add_empty(ac
->local_msg
, IS_MAPPED
,
563 LDB_FLAG_MOD_ADD
, NULL
) != 0) {
564 return LDB_ERR_OPERATIONS_ERROR
;
566 ret
= ldb_msg_add_linearized_dn(ac
->local_msg
, IS_MAPPED
,
567 ac
->remote_req
->op
.mod
.message
->dn
);
569 return LDB_ERR_OPERATIONS_ERROR
;
572 /* Prepare the local operation */
573 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
577 map_op_local_callback
,
579 LDB_REQ_SET_LOCATION(local_req
);
580 if (ret
!= LDB_SUCCESS
) {
581 return LDB_ERR_OPERATIONS_ERROR
;
584 /* Prepare the local operation */
585 ret
= ldb_build_mod_req(&local_req
, ldb
, ac
,
589 map_op_local_callback
,
591 LDB_REQ_SET_LOCATION(local_req
);
592 if (ret
!= LDB_SUCCESS
) {
593 return LDB_ERR_OPERATIONS_ERROR
;
597 return ldb_next_request(ac
->module
, local_req
);
600 /*****************************************************************************
602 *****************************************************************************/
604 /* Delete a record. */
605 int ldb_map_delete(struct ldb_module
*module
, struct ldb_request
*req
)
607 struct ldb_request
*search_req
;
608 struct ldb_context
*ldb
;
609 struct map_context
*ac
;
612 ldb
= ldb_module_get_ctx(module
);
614 /* Do not manipulate our control entries */
615 if (ldb_dn_is_special(req
->op
.del
.dn
)) {
616 return ldb_next_request(module
, req
);
619 /* No mapping requested (perhaps no DN mapping specified).
620 * Skip to next module */
621 if (!ldb_dn_check_local(module
, req
->op
.del
.dn
)) {
622 return ldb_next_request(module
, req
);
625 /* Prepare context and handle */
626 ac
= map_init_context(module
, req
);
628 return LDB_ERR_OPERATIONS_ERROR
;
631 /* Prepare the remote operation */
632 ret
= ldb_build_del_req(&ac
->remote_req
, ldb
, ac
,
633 ldb_dn_map_local(module
, ac
, req
->op
.del
.dn
),
636 map_op_remote_callback
,
638 LDB_REQ_SET_LOCATION(ac
->remote_req
);
639 if (ret
!= LDB_SUCCESS
) {
640 return LDB_ERR_OPERATIONS_ERROR
;
643 /* No local db, just run the remote request */
644 if (!map_check_local_db(ac
->module
)) {
645 /* Do the remote request. */
646 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
649 /* Prepare the search operation */
650 ret
= map_search_self_req(&search_req
, ac
, req
->op
.del
.dn
);
651 if (ret
!= LDB_SUCCESS
) {
653 return LDB_ERR_OPERATIONS_ERROR
;
656 return ldb_next_request(module
, search_req
);
659 /* Delete the local record. */
660 static int map_delete_do_local(struct map_context
*ac
)
662 struct ldb_request
*local_req
;
663 struct ldb_context
*ldb
;
666 ldb
= ldb_module_get_ctx(ac
->module
);
668 /* No local record, continue remotely */
669 if (ac
->local_dn
== NULL
) {
670 /* Do the remote request. */
671 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
674 /* Prepare the local operation */
675 ret
= ldb_build_del_req(&local_req
, ldb
, ac
,
679 map_op_local_callback
,
681 LDB_REQ_SET_LOCATION(local_req
);
682 if (ret
!= LDB_SUCCESS
) {
683 return LDB_ERR_OPERATIONS_ERROR
;
685 return ldb_next_request(ac
->module
, local_req
);
688 /*****************************************************************************
690 *****************************************************************************/
692 /* Rename a record. */
693 int ldb_map_rename(struct ldb_module
*module
, struct ldb_request
*req
)
695 struct ldb_request
*search_req
;
696 struct ldb_context
*ldb
;
697 struct map_context
*ac
;
700 ldb
= ldb_module_get_ctx(module
);
702 /* Do not manipulate our control entries */
703 if (ldb_dn_is_special(req
->op
.rename
.olddn
)) {
704 return ldb_next_request(module
, req
);
707 /* No mapping requested (perhaps no DN mapping specified).
708 * Skip to next module */
709 if ((!ldb_dn_check_local(module
, req
->op
.rename
.olddn
)) &&
710 (!ldb_dn_check_local(module
, req
->op
.rename
.newdn
))) {
711 return ldb_next_request(module
, req
);
714 /* Rename into/out of the mapped partition requested, bail out */
715 if (!ldb_dn_check_local(module
, req
->op
.rename
.olddn
) ||
716 !ldb_dn_check_local(module
, req
->op
.rename
.newdn
)) {
717 return LDB_ERR_AFFECTS_MULTIPLE_DSAS
;
720 /* Prepare context and handle */
721 ac
= map_init_context(module
, req
);
723 return LDB_ERR_OPERATIONS_ERROR
;
726 /* Prepare the remote operation */
727 ret
= ldb_build_rename_req(&ac
->remote_req
, ldb
, ac
,
728 ldb_dn_map_local(module
, ac
, req
->op
.rename
.olddn
),
729 ldb_dn_map_local(module
, ac
, req
->op
.rename
.newdn
),
731 ac
, map_op_remote_callback
,
733 LDB_REQ_SET_LOCATION(ac
->remote_req
);
734 if (ret
!= LDB_SUCCESS
) {
735 return LDB_ERR_OPERATIONS_ERROR
;
738 /* No local db, just run the remote request */
739 if (!map_check_local_db(ac
->module
)) {
740 /* Do the remote request. */
741 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
744 /* Prepare the search operation */
745 ret
= map_search_self_req(&search_req
, ac
, req
->op
.rename
.olddn
);
746 if (ret
!= LDB_SUCCESS
) {
748 return LDB_ERR_OPERATIONS_ERROR
;
751 return ldb_next_request(module
, search_req
);
754 /* Rename the local record. */
755 static int map_rename_do_local(struct map_context
*ac
)
757 struct ldb_request
*local_req
;
758 struct ldb_context
*ldb
;
761 ldb
= ldb_module_get_ctx(ac
->module
);
763 /* No local record, continue remotely */
764 if (ac
->local_dn
== NULL
) {
765 /* Do the remote request. */
766 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
769 /* Prepare the local operation */
770 ret
= ldb_build_rename_req(&local_req
, ldb
, ac
,
771 ac
->req
->op
.rename
.olddn
,
772 ac
->req
->op
.rename
.newdn
,
775 map_rename_local_callback
,
777 LDB_REQ_SET_LOCATION(local_req
);
778 if (ret
!= LDB_SUCCESS
) {
779 return LDB_ERR_OPERATIONS_ERROR
;
782 return ldb_next_request(ac
->module
, local_req
);
785 static int map_rename_local_callback(struct ldb_request
*req
,
786 struct ldb_reply
*ares
)
788 struct ldb_context
*ldb
;
789 struct map_context
*ac
;
792 ac
= talloc_get_type(req
->context
, struct map_context
);
793 ldb
= ldb_module_get_ctx(ac
->module
);
796 return ldb_module_done(ac
->req
, NULL
, NULL
,
797 LDB_ERR_OPERATIONS_ERROR
);
799 if (ares
->error
!= LDB_SUCCESS
) {
800 return ldb_module_done(ac
->req
, ares
->controls
,
801 ares
->response
, ares
->error
);
804 if (ares
->type
!= LDB_REPLY_DONE
) {
805 ldb_asprintf_errstring(ldb
, "Invalid LDB reply type %d", ares
->type
);
806 return ldb_module_done(ac
->req
, NULL
, NULL
,
807 LDB_ERR_OPERATIONS_ERROR
);
810 /* proceed with next step */
811 ret
= map_rename_do_fixup(ac
);
812 if (ret
!= LDB_SUCCESS
) {
813 return ldb_module_done(ac
->req
, NULL
, NULL
,
814 LDB_ERR_OPERATIONS_ERROR
);
820 /* Update the local 'IS_MAPPED' attribute. */
821 static int map_rename_do_fixup(struct map_context
*ac
)
823 struct ldb_request
*local_req
;
825 /* Prepare the fixup operation */
826 /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
827 local_req
= map_build_fixup_req(ac
,
828 ac
->req
->op
.rename
.newdn
,
829 ac
->remote_req
->op
.rename
.newdn
,
831 map_op_local_callback
);
832 if (local_req
== NULL
) {
833 return LDB_ERR_OPERATIONS_ERROR
;
836 return ldb_next_request(ac
->module
, local_req
);