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
, enum ldb_request_type optype
, 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",
85 if (optype
!= LDB_ADD
) {
86 /* do the same as LDB_MAP_RENAME */
87 el
= ldb_msg_el_map_local(module
, remote
, map
, old
);
96 if (map
->u
.convert
.convert_local
== NULL
) {
97 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
98 "Not mapping attribute '%s': "
99 "'convert_local' not set",
107 el
= ldb_msg_el_map_local(module
, remote
, map
, old
);
110 case LDB_MAP_GENERATE
:
111 if (map
->u
.generate
.generate_remote
== NULL
) {
112 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
113 "Not mapping attribute '%s': "
114 "'generate_remote' not set",
119 /* TODO: if this attr requires context:
120 * make sure all context attrs are mappable (in 'names')
121 * make sure all context attrs have already been mapped?
122 * maybe postpone generation until they have been mapped?
125 map
->u
.generate
.generate_remote(module
, map
->local_name
, msg
, remote
, local
);
133 return ldb_msg_add(remote
, el
, old
->flags
);
136 el
= talloc(local
, struct ldb_message_element
);
142 *el
= *old
; /* copy the old element */
144 return ldb_msg_add(local
, el
, old
->flags
);
148 * ================ */
150 /* Check whether a message will be (partially) mapped into the remote partition. */
151 static bool ldb_msg_check_remote(struct ldb_module
*module
, const struct ldb_message
*msg
)
153 const struct ldb_map_context
*data
= map_get_context(module
);
157 for (i
= 0; i
< msg
->num_elements
; i
++) {
158 ret
= map_attr_check_remote(data
, msg
->elements
[i
].name
);
167 /* Split message elements that stay in the local partition from those
168 * that are mapped into the remote partition. */
169 static int ldb_msg_partition(struct ldb_module
*module
, enum ldb_request_type optype
, struct ldb_message
*local
, struct ldb_message
*remote
, const struct ldb_message
*msg
)
171 /* const char * const names[]; */
172 struct ldb_context
*ldb
;
176 ldb
= ldb_module_get_ctx(module
);
178 for (i
= 0; i
< msg
->num_elements
; i
++) {
179 /* Skip 'IS_MAPPED' */
180 if (ldb_attr_cmp(msg
->elements
[i
].name
, IS_MAPPED
) == 0) {
181 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
182 "Skipping attribute '%s'",
183 msg
->elements
[i
].name
);
187 ret
= ldb_msg_el_partition(module
, optype
, local
, remote
, msg
, msg
->elements
[i
].name
, &msg
->elements
[i
]);
197 static int map_add_do_local(struct map_context
*ac
);
198 static int map_modify_do_local(struct map_context
*ac
);
199 static int map_delete_do_local(struct map_context
*ac
);
200 static int map_rename_do_local(struct map_context
*ac
);
201 static int map_rename_do_fixup(struct map_context
*ac
);
202 static int map_rename_local_callback(struct ldb_request
*req
,
203 struct ldb_reply
*ares
);
206 /*****************************************************************************
207 * COMMON INBOUND functions
208 *****************************************************************************/
210 /* Store the DN of a single search result in context. */
211 static int map_search_self_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
213 struct ldb_context
*ldb
;
214 struct map_context
*ac
;
217 ac
= talloc_get_type(req
->context
, struct map_context
);
218 ldb
= ldb_module_get_ctx(ac
->module
);
221 return ldb_module_done(ac
->req
, NULL
, NULL
,
222 LDB_ERR_OPERATIONS_ERROR
);
224 if (ares
->error
!= LDB_SUCCESS
) {
225 return ldb_module_done(ac
->req
, ares
->controls
,
226 ares
->response
, ares
->error
);
229 /* We are interested only in the single reply */
231 case LDB_REPLY_ENTRY
:
232 /* We have already found a remote DN */
234 ldb_set_errstring(ldb
,
235 "Too many results!");
236 return ldb_module_done(ac
->req
, NULL
, NULL
,
237 LDB_ERR_OPERATIONS_ERROR
);
241 ac
->local_dn
= talloc_steal(ac
, ares
->message
->dn
);
246 switch (ac
->req
->operation
) {
248 ret
= map_modify_do_local(ac
);
251 ret
= map_delete_do_local(ac
);
254 ret
= map_rename_do_local(ac
);
257 /* if we get here we have definitely a problem */
258 ret
= LDB_ERR_OPERATIONS_ERROR
;
260 if (ret
!= LDB_SUCCESS
) {
261 return ldb_module_done(ac
->req
, NULL
, NULL
,
262 LDB_ERR_OPERATIONS_ERROR
);
267 /* ignore referrals */
275 /* Build a request to search the local record by its DN. */
276 static int map_search_self_req(struct ldb_request
**req
,
277 struct map_context
*ac
,
280 /* attrs[] is returned from this function in
281 * ac->search_req->op.search.attrs, so it must be static, as
282 * otherwise the compiler can put it on the stack */
283 static const char * const attrs
[] = { IS_MAPPED
, NULL
};
284 struct ldb_parse_tree
*tree
;
286 /* Limit search to records with 'IS_MAPPED' present */
287 tree
= ldb_parse_tree(ac
, "(" IS_MAPPED
"=*)");
290 return LDB_ERR_OPERATIONS_ERROR
;
293 *req
= map_search_base_req(ac
, dn
, attrs
, tree
,
294 ac
, map_search_self_callback
);
296 return LDB_ERR_OPERATIONS_ERROR
;
302 static int map_op_local_callback(struct ldb_request
*req
,
303 struct ldb_reply
*ares
)
305 struct ldb_context
*ldb
;
306 struct map_context
*ac
;
309 ac
= talloc_get_type(req
->context
, struct map_context
);
310 ldb
= ldb_module_get_ctx(ac
->module
);
313 return ldb_module_done(ac
->req
, NULL
, NULL
,
314 LDB_ERR_OPERATIONS_ERROR
);
316 if (ares
->error
!= LDB_SUCCESS
) {
317 return ldb_module_done(ac
->req
, ares
->controls
,
318 ares
->response
, ares
->error
);
321 if (ares
->type
!= LDB_REPLY_DONE
) {
322 ldb_asprintf_errstring(ldb
, "Invalid LDB reply type %d", ares
->type
);
323 return ldb_module_done(ac
->req
, NULL
, NULL
,
324 LDB_ERR_OPERATIONS_ERROR
);
327 /* Do the remote request. */
328 ret
= ldb_next_remote_request(ac
->module
, ac
->remote_req
);
329 if (ret
!= LDB_SUCCESS
) {
330 return ldb_module_done(ac
->req
, NULL
, NULL
,
331 LDB_ERR_OPERATIONS_ERROR
);
337 static int map_op_remote_callback(struct ldb_request
*req
,
338 struct ldb_reply
*ares
)
340 struct ldb_context
*ldb
;
341 struct map_context
*ac
;
343 ac
= talloc_get_type(req
->context
, struct map_context
);
344 ldb
= ldb_module_get_ctx(ac
->module
);
347 return ldb_module_done(ac
->req
, NULL
, NULL
,
348 LDB_ERR_OPERATIONS_ERROR
);
350 if (ares
->error
!= LDB_SUCCESS
) {
351 return ldb_module_done(ac
->req
, ares
->controls
,
352 ares
->response
, ares
->error
);
355 if (ares
->type
!= LDB_REPLY_DONE
) {
356 ldb_asprintf_errstring(ldb
, "Invalid LDB reply type %d", ares
->type
);
357 return ldb_module_done(ac
->req
, NULL
, NULL
,
358 LDB_ERR_OPERATIONS_ERROR
);
361 return ldb_module_done(ac
->req
, ares
->controls
,
362 ares
->response
, ares
->error
);
366 /*****************************************************************************
368 *****************************************************************************/
372 int ldb_map_add(struct ldb_module
*module
, struct ldb_request
*req
)
374 const struct ldb_message
*msg
= req
->op
.add
.message
;
375 struct ldb_context
*ldb
;
376 struct map_context
*ac
;
377 struct ldb_message
*remote_msg
;
380 ldb
= ldb_module_get_ctx(module
);
382 /* Do not manipulate our control entries */
383 if (ldb_dn_is_special(msg
->dn
)) {
384 return ldb_next_request(module
, req
);
387 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
388 if (!ldb_dn_check_local(module
, msg
->dn
)) {
389 return ldb_next_request(module
, req
);
392 /* No mapping needed, fail */
393 if (!ldb_msg_check_remote(module
, msg
)) {
394 return LDB_ERR_OPERATIONS_ERROR
;
397 /* Prepare context and handle */
398 ac
= map_init_context(module
, req
);
400 return LDB_ERR_OPERATIONS_ERROR
;
404 /* Prepare the local message */
405 ac
->local_msg
= ldb_msg_new(ac
);
406 if (ac
->local_msg
== NULL
) {
408 return LDB_ERR_OPERATIONS_ERROR
;
410 ac
->local_msg
->dn
= msg
->dn
;
412 /* Prepare the remote message */
413 remote_msg
= ldb_msg_new(ac
);
414 if (remote_msg
== NULL
) {
416 return LDB_ERR_OPERATIONS_ERROR
;
418 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
420 /* Split local from remote message */
421 ldb_msg_partition(module
, req
->operation
, ac
->local_msg
, remote_msg
, msg
);
423 /* Prepare the remote operation */
424 ret
= ldb_build_add_req(&ac
->remote_req
, ldb
,
427 ac
, map_op_remote_callback
,
429 LDB_REQ_SET_LOCATION(ac
->remote_req
);
430 if (ret
!= LDB_SUCCESS
) {
431 return LDB_ERR_OPERATIONS_ERROR
;
434 if ((ac
->local_msg
->num_elements
== 0) ||
435 ( ! map_check_local_db(ac
->module
))) {
436 /* No local data or db, just run the remote request */
437 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
440 /* Store remote DN in 'IS_MAPPED' */
441 /* TODO: use GUIDs here instead */
442 ret
= ldb_msg_add_linearized_dn(ac
->local_msg
, IS_MAPPED
,
444 if (ret
!= LDB_SUCCESS
) {
445 return LDB_ERR_OPERATIONS_ERROR
;
448 return map_add_do_local(ac
);
451 /* Add the local record. */
452 static int map_add_do_local(struct map_context
*ac
)
454 struct ldb_request
*local_req
;
455 struct ldb_context
*ldb
;
458 ldb
= ldb_module_get_ctx(ac
->module
);
460 /* Prepare the local operation */
461 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
465 map_op_local_callback
,
467 LDB_REQ_SET_LOCATION(local_req
);
468 if (ret
!= LDB_SUCCESS
) {
469 return LDB_ERR_OPERATIONS_ERROR
;
471 return ldb_next_request(ac
->module
, local_req
);
474 /*****************************************************************************
476 *****************************************************************************/
478 /* Modify a record. */
479 int ldb_map_modify(struct ldb_module
*module
, struct ldb_request
*req
)
481 const struct ldb_message
*msg
= req
->op
.mod
.message
;
482 struct ldb_request
*search_req
= NULL
;
483 struct ldb_message
*remote_msg
;
484 struct ldb_context
*ldb
;
485 struct map_context
*ac
;
488 ldb
= ldb_module_get_ctx(module
);
490 /* Do not manipulate our control entries */
491 if (ldb_dn_is_special(msg
->dn
)) {
492 return ldb_next_request(module
, req
);
495 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
496 if (!ldb_dn_check_local(module
, msg
->dn
)) {
497 return ldb_next_request(module
, req
);
500 /* No mapping needed, skip to next module */
501 /* TODO: What if the remote part exists, the local doesn't,
502 * and this request wants to modify local data and thus
503 * add the local record? */
504 if (!ldb_msg_check_remote(module
, msg
)) {
505 return LDB_ERR_OPERATIONS_ERROR
;
508 /* Prepare context and handle */
509 ac
= map_init_context(module
, req
);
511 return LDB_ERR_OPERATIONS_ERROR
;
514 /* Prepare the local message */
515 ac
->local_msg
= ldb_msg_new(ac
);
516 if (ac
->local_msg
== NULL
) {
518 return LDB_ERR_OPERATIONS_ERROR
;
520 ac
->local_msg
->dn
= msg
->dn
;
522 /* Prepare the remote message */
523 remote_msg
= ldb_msg_new(ac
->remote_req
);
524 if (remote_msg
== NULL
) {
526 return LDB_ERR_OPERATIONS_ERROR
;
528 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
530 /* Split local from remote message */
531 ldb_msg_partition(module
, req
->operation
, ac
->local_msg
, remote_msg
, msg
);
533 /* Prepare the remote operation */
534 ret
= ldb_build_mod_req(&ac
->remote_req
, ldb
,
537 ac
, map_op_remote_callback
,
539 LDB_REQ_SET_LOCATION(ac
->remote_req
);
540 if (ret
!= LDB_SUCCESS
) {
541 return LDB_ERR_OPERATIONS_ERROR
;
544 if ((ac
->local_msg
->num_elements
== 0) ||
545 ( ! map_check_local_db(ac
->module
))) {
546 /* No local data or db, just run the remote request */
547 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
550 /* prepare the search operation */
551 ret
= map_search_self_req(&search_req
, ac
, msg
->dn
);
552 if (ret
!= LDB_SUCCESS
) {
553 return LDB_ERR_OPERATIONS_ERROR
;
556 return ldb_next_request(module
, search_req
);
559 /* Modify the local record. */
560 static int map_modify_do_local(struct map_context
*ac
)
562 struct ldb_request
*local_req
;
563 struct ldb_context
*ldb
;
566 ldb
= ldb_module_get_ctx(ac
->module
);
568 if (ac
->local_dn
== NULL
) {
569 /* No local record present, add it instead */
570 /* Add local 'IS_MAPPED' */
571 /* TODO: use GUIDs here instead */
572 ret
= ldb_msg_append_linearized_dn(ac
->local_msg
, IS_MAPPED
,
573 ac
->remote_req
->op
.mod
.message
->dn
,
576 return LDB_ERR_OPERATIONS_ERROR
;
579 /* Prepare the local operation */
580 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
584 map_op_local_callback
,
586 LDB_REQ_SET_LOCATION(local_req
);
587 if (ret
!= LDB_SUCCESS
) {
588 return LDB_ERR_OPERATIONS_ERROR
;
591 /* Prepare the local operation */
592 ret
= ldb_build_mod_req(&local_req
, ldb
, ac
,
596 map_op_local_callback
,
598 LDB_REQ_SET_LOCATION(local_req
);
599 if (ret
!= LDB_SUCCESS
) {
600 return LDB_ERR_OPERATIONS_ERROR
;
604 return ldb_next_request(ac
->module
, local_req
);
607 /*****************************************************************************
609 *****************************************************************************/
611 /* Delete a record. */
612 int ldb_map_delete(struct ldb_module
*module
, struct ldb_request
*req
)
614 struct ldb_request
*search_req
;
615 struct ldb_context
*ldb
;
616 struct map_context
*ac
;
619 ldb
= ldb_module_get_ctx(module
);
621 /* Do not manipulate our control entries */
622 if (ldb_dn_is_special(req
->op
.del
.dn
)) {
623 return ldb_next_request(module
, req
);
626 /* No mapping requested (perhaps no DN mapping specified).
627 * Skip to next module */
628 if (!ldb_dn_check_local(module
, req
->op
.del
.dn
)) {
629 return ldb_next_request(module
, req
);
632 /* Prepare context and handle */
633 ac
= map_init_context(module
, req
);
635 return LDB_ERR_OPERATIONS_ERROR
;
638 /* Prepare the remote operation */
639 ret
= ldb_build_del_req(&ac
->remote_req
, ldb
, ac
,
640 ldb_dn_map_local(module
, ac
, req
->op
.del
.dn
),
643 map_op_remote_callback
,
645 LDB_REQ_SET_LOCATION(ac
->remote_req
);
646 if (ret
!= LDB_SUCCESS
) {
647 return LDB_ERR_OPERATIONS_ERROR
;
650 /* No local db, just run the remote request */
651 if (!map_check_local_db(ac
->module
)) {
652 /* Do the remote request. */
653 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
656 /* Prepare the search operation */
657 ret
= map_search_self_req(&search_req
, ac
, req
->op
.del
.dn
);
658 if (ret
!= LDB_SUCCESS
) {
660 return LDB_ERR_OPERATIONS_ERROR
;
663 return ldb_next_request(module
, search_req
);
666 /* Delete the local record. */
667 static int map_delete_do_local(struct map_context
*ac
)
669 struct ldb_request
*local_req
;
670 struct ldb_context
*ldb
;
673 ldb
= ldb_module_get_ctx(ac
->module
);
675 /* No local record, continue remotely */
676 if (ac
->local_dn
== NULL
) {
677 /* Do the remote request. */
678 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
681 /* Prepare the local operation */
682 ret
= ldb_build_del_req(&local_req
, ldb
, ac
,
686 map_op_local_callback
,
688 LDB_REQ_SET_LOCATION(local_req
);
689 if (ret
!= LDB_SUCCESS
) {
690 return LDB_ERR_OPERATIONS_ERROR
;
692 return ldb_next_request(ac
->module
, local_req
);
695 /*****************************************************************************
697 *****************************************************************************/
699 /* Rename a record. */
700 int ldb_map_rename(struct ldb_module
*module
, struct ldb_request
*req
)
702 struct ldb_request
*search_req
= NULL
;
703 struct ldb_context
*ldb
;
704 struct map_context
*ac
;
707 ldb
= ldb_module_get_ctx(module
);
709 /* Do not manipulate our control entries */
710 if (ldb_dn_is_special(req
->op
.rename
.olddn
)) {
711 return ldb_next_request(module
, req
);
714 /* No mapping requested (perhaps no DN mapping specified).
715 * Skip to next module */
716 if ((!ldb_dn_check_local(module
, req
->op
.rename
.olddn
)) &&
717 (!ldb_dn_check_local(module
, req
->op
.rename
.newdn
))) {
718 return ldb_next_request(module
, req
);
721 /* Rename into/out of the mapped partition requested, bail out */
722 if (!ldb_dn_check_local(module
, req
->op
.rename
.olddn
) ||
723 !ldb_dn_check_local(module
, req
->op
.rename
.newdn
)) {
724 return LDB_ERR_AFFECTS_MULTIPLE_DSAS
;
727 /* Prepare context and handle */
728 ac
= map_init_context(module
, req
);
730 return LDB_ERR_OPERATIONS_ERROR
;
733 /* Prepare the remote operation */
734 ret
= ldb_build_rename_req(&ac
->remote_req
, ldb
, ac
,
735 ldb_dn_map_local(module
, ac
, req
->op
.rename
.olddn
),
736 ldb_dn_map_local(module
, ac
, req
->op
.rename
.newdn
),
738 ac
, map_op_remote_callback
,
740 LDB_REQ_SET_LOCATION(ac
->remote_req
);
741 if (ret
!= LDB_SUCCESS
) {
742 return LDB_ERR_OPERATIONS_ERROR
;
745 /* No local db, just run the remote request */
746 if (!map_check_local_db(ac
->module
)) {
747 /* Do the remote request. */
748 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
751 /* Prepare the search operation */
752 ret
= map_search_self_req(&search_req
, ac
, req
->op
.rename
.olddn
);
753 if (ret
!= LDB_SUCCESS
) {
755 return LDB_ERR_OPERATIONS_ERROR
;
758 return ldb_next_request(module
, search_req
);
761 /* Rename the local record. */
762 static int map_rename_do_local(struct map_context
*ac
)
764 struct ldb_request
*local_req
;
765 struct ldb_context
*ldb
;
768 ldb
= ldb_module_get_ctx(ac
->module
);
770 /* No local record, continue remotely */
771 if (ac
->local_dn
== NULL
) {
772 /* Do the remote request. */
773 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
776 /* Prepare the local operation */
777 ret
= ldb_build_rename_req(&local_req
, ldb
, ac
,
778 ac
->req
->op
.rename
.olddn
,
779 ac
->req
->op
.rename
.newdn
,
782 map_rename_local_callback
,
784 LDB_REQ_SET_LOCATION(local_req
);
785 if (ret
!= LDB_SUCCESS
) {
786 return LDB_ERR_OPERATIONS_ERROR
;
789 return ldb_next_request(ac
->module
, local_req
);
792 static int map_rename_local_callback(struct ldb_request
*req
,
793 struct ldb_reply
*ares
)
795 struct ldb_context
*ldb
;
796 struct map_context
*ac
;
799 ac
= talloc_get_type(req
->context
, struct map_context
);
800 ldb
= ldb_module_get_ctx(ac
->module
);
803 return ldb_module_done(ac
->req
, NULL
, NULL
,
804 LDB_ERR_OPERATIONS_ERROR
);
806 if (ares
->error
!= LDB_SUCCESS
) {
807 return ldb_module_done(ac
->req
, ares
->controls
,
808 ares
->response
, ares
->error
);
811 if (ares
->type
!= LDB_REPLY_DONE
) {
812 ldb_asprintf_errstring(ldb
, "Invalid LDB reply type %d", ares
->type
);
813 return ldb_module_done(ac
->req
, NULL
, NULL
,
814 LDB_ERR_OPERATIONS_ERROR
);
817 /* proceed with next step */
818 ret
= map_rename_do_fixup(ac
);
819 if (ret
!= LDB_SUCCESS
) {
820 return ldb_module_done(ac
->req
, NULL
, NULL
,
821 LDB_ERR_OPERATIONS_ERROR
);
827 /* Update the local 'IS_MAPPED' attribute. */
828 static int map_rename_do_fixup(struct map_context
*ac
)
830 struct ldb_request
*local_req
;
832 /* Prepare the fixup operation */
833 /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
834 local_req
= map_build_fixup_req(ac
,
835 ac
->req
->op
.rename
.newdn
,
836 ac
->remote_req
->op
.rename
.newdn
,
838 map_op_local_callback
);
839 if (local_req
== NULL
) {
840 return LDB_ERR_OPERATIONS_ERROR
;
843 return ldb_next_request(ac
->module
, local_req
);