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/>.
27 #include "ldb_includes.h"
29 #include "ldb_map_private.h"
32 /* Mapping message elements
33 * ======================== */
35 /* Map a message element into the remote partition. */
36 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
)
38 struct ldb_message_element
*el
;
41 el
= talloc_zero(mem_ctx
, struct ldb_message_element
);
47 el
->num_values
= old
->num_values
;
48 el
->values
= talloc_array(el
, struct ldb_val
, el
->num_values
);
49 if (el
->values
== NULL
) {
55 el
->name
= map_attr_map_local(el
, map
, old
->name
);
57 for (i
= 0; i
< el
->num_values
; i
++) {
58 el
->values
[i
] = ldb_val_map_local(module
, el
->values
, map
, &old
->values
[i
]);
64 /* Add a message element either to a local or to a remote message,
65 * depending on whether it goes into the local or remote partition. */
66 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
)
68 const struct ldb_map_context
*data
= map_get_context(module
);
69 const struct ldb_map_attribute
*map
= map_attr_find_local(data
, attr_name
);
70 struct ldb_message_element
*el
=NULL
;
71 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
73 /* Unknown attribute: ignore */
75 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
76 "Not mapping attribute '%s': no mapping found\n",
86 if (map
->u
.convert
.convert_local
== NULL
) {
87 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
88 "Not mapping attribute '%s': "
89 "'convert_local' not set\n",
96 el
= ldb_msg_el_map_local(module
, remote
, map
, old
);
100 if (map
->u
.generate
.generate_remote
== NULL
) {
101 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
102 "Not mapping attribute '%s': "
103 "'generate_remote' not set\n",
108 /* TODO: if this attr requires context:
109 * make sure all context attrs are mappable (in 'names')
110 * make sure all context attrs have already been mapped?
111 * maybe postpone generation until they have been mapped?
114 map
->u
.generate
.generate_remote(module
, map
->local_name
, msg
, remote
, local
);
122 return ldb_msg_add(remote
, el
, old
->flags
);
125 el
= talloc(local
, struct ldb_message_element
);
131 *el
= *old
; /* copy the old element */
133 return ldb_msg_add(local
, el
, old
->flags
);
137 * ================ */
139 /* Check whether a message will be (partially) mapped into the remote partition. */
140 static bool ldb_msg_check_remote(struct ldb_module
*module
, const struct ldb_message
*msg
)
142 const struct ldb_map_context
*data
= map_get_context(module
);
146 for (i
= 0; i
< msg
->num_elements
; i
++) {
147 ret
= map_attr_check_remote(data
, msg
->elements
[i
].name
);
156 /* Split message elements that stay in the local partition from those
157 * that are mapped into the remote partition. */
158 static int ldb_msg_partition(struct ldb_module
*module
, struct ldb_message
*local
, struct ldb_message
*remote
, const struct ldb_message
*msg
)
160 /* const char * const names[]; */
161 struct ldb_context
*ldb
;
164 ldb
= ldb_module_get_ctx(module
);
166 for (i
= 0; i
< msg
->num_elements
; i
++) {
167 /* Skip 'IS_MAPPED' */
168 if (ldb_attr_cmp(msg
->elements
[i
].name
, IS_MAPPED
) == 0) {
169 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
170 "Skipping attribute '%s'\n",
171 msg
->elements
[i
].name
);
175 ret
= ldb_msg_el_partition(module
, local
, remote
, msg
, msg
->elements
[i
].name
, &msg
->elements
[i
]);
185 static int map_add_do_local(struct map_context
*ac
);
186 static int map_modify_do_local(struct map_context
*ac
);
187 static int map_delete_do_local(struct map_context
*ac
);
188 static int map_rename_do_local(struct map_context
*ac
);
189 static int map_rename_do_fixup(struct map_context
*ac
);
190 static int map_rename_local_callback(struct ldb_request
*req
,
191 struct ldb_reply
*ares
);
194 /*****************************************************************************
195 * COMMON INBOUND functions
196 *****************************************************************************/
198 /* Store the DN of a single search result in context. */
199 static int map_search_self_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
201 struct ldb_context
*ldb
;
202 struct map_context
*ac
;
205 ac
= talloc_get_type(req
->context
, struct map_context
);
206 ldb
= ldb_module_get_ctx(ac
->module
);
209 return ldb_module_done(ac
->req
, NULL
, NULL
,
210 LDB_ERR_OPERATIONS_ERROR
);
212 if (ares
->error
!= LDB_SUCCESS
) {
213 return ldb_module_done(ac
->req
, ares
->controls
,
214 ares
->response
, ares
->error
);
217 /* We are interested only in the single reply */
219 case LDB_REPLY_ENTRY
:
220 /* We have already found a remote DN */
222 ldb_set_errstring(ldb
,
223 "Too many results!");
224 return ldb_module_done(ac
->req
, NULL
, NULL
,
225 LDB_ERR_OPERATIONS_ERROR
);
229 ac
->local_dn
= talloc_steal(ac
, ares
->message
->dn
);
234 switch (ac
->req
->operation
) {
236 ret
= map_modify_do_local(ac
);
239 ret
= map_delete_do_local(ac
);
242 ret
= map_rename_do_local(ac
);
245 /* if we get here we have definitely a problem */
246 ret
= LDB_ERR_OPERATIONS_ERROR
;
248 if (ret
!= LDB_SUCCESS
) {
249 return ldb_module_done(ac
->req
, NULL
, NULL
,
250 LDB_ERR_OPERATIONS_ERROR
);
254 /* ignore referrals */
262 /* Build a request to search the local record by its DN. */
263 static int map_search_self_req(struct ldb_request
**req
,
264 struct map_context
*ac
,
267 /* attrs[] is returned from this function in
268 * ac->search_req->op.search.attrs, so it must be static, as
269 * otherwise the compiler can put it on the stack */
270 static const char * const attrs
[] = { IS_MAPPED
, NULL
};
271 struct ldb_parse_tree
*tree
;
273 /* Limit search to records with 'IS_MAPPED' present */
274 tree
= ldb_parse_tree(ac
, "(" IS_MAPPED
"=*)");
277 return LDB_ERR_OPERATIONS_ERROR
;
280 *req
= map_search_base_req(ac
, dn
, attrs
, tree
,
281 ac
, map_search_self_callback
);
283 return LDB_ERR_OPERATIONS_ERROR
;
289 static int map_op_local_callback(struct ldb_request
*req
,
290 struct ldb_reply
*ares
)
292 struct ldb_context
*ldb
;
293 struct map_context
*ac
;
296 ac
= talloc_get_type(req
->context
, struct map_context
);
297 ldb
= ldb_module_get_ctx(ac
->module
);
300 return ldb_module_done(ac
->req
, NULL
, NULL
,
301 LDB_ERR_OPERATIONS_ERROR
);
303 if (ares
->error
!= LDB_SUCCESS
) {
304 return ldb_module_done(ac
->req
, ares
->controls
,
305 ares
->response
, ares
->error
);
308 if (ares
->type
!= LDB_REPLY_DONE
) {
309 ldb_set_errstring(ldb
, "Invalid reply type!");
310 return ldb_module_done(ac
->req
, NULL
, NULL
,
311 LDB_ERR_OPERATIONS_ERROR
);
314 /* Do the remote request. */
315 ret
= ldb_next_remote_request(ac
->module
, ac
->remote_req
);
316 if (ret
!= LDB_SUCCESS
) {
317 return ldb_module_done(ac
->req
, NULL
, NULL
,
318 LDB_ERR_OPERATIONS_ERROR
);
324 static int map_op_remote_callback(struct ldb_request
*req
,
325 struct ldb_reply
*ares
)
327 struct ldb_context
*ldb
;
328 struct map_context
*ac
;
330 ac
= talloc_get_type(req
->context
, struct map_context
);
331 ldb
= ldb_module_get_ctx(ac
->module
);
334 return ldb_module_done(ac
->req
, NULL
, NULL
,
335 LDB_ERR_OPERATIONS_ERROR
);
337 if (ares
->error
!= LDB_SUCCESS
) {
338 return ldb_module_done(ac
->req
, ares
->controls
,
339 ares
->response
, ares
->error
);
342 if (ares
->type
!= LDB_REPLY_DONE
) {
343 ldb_set_errstring(ldb
, "Invalid reply type!");
344 return ldb_module_done(ac
->req
, NULL
, NULL
,
345 LDB_ERR_OPERATIONS_ERROR
);
348 return ldb_module_done(ac
->req
, ares
->controls
,
349 ares
->response
, ares
->error
);
353 /*****************************************************************************
355 *****************************************************************************/
359 int map_add(struct ldb_module
*module
, struct ldb_request
*req
)
361 const struct ldb_message
*msg
= req
->op
.add
.message
;
362 struct ldb_context
*ldb
;
363 struct map_context
*ac
;
364 struct ldb_message
*remote_msg
;
368 ldb
= ldb_module_get_ctx(module
);
370 /* Do not manipulate our control entries */
371 if (ldb_dn_is_special(msg
->dn
)) {
372 return ldb_next_request(module
, req
);
375 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
376 if (!ldb_dn_check_local(module
, msg
->dn
)) {
377 return ldb_next_request(module
, req
);
380 /* No mapping needed, fail */
381 if (!ldb_msg_check_remote(module
, msg
)) {
382 return LDB_ERR_OPERATIONS_ERROR
;
385 /* Prepare context and handle */
386 ac
= map_init_context(module
, req
);
388 return LDB_ERR_OPERATIONS_ERROR
;
392 /* Prepare the local message */
393 ac
->local_msg
= ldb_msg_new(ac
);
394 if (ac
->local_msg
== NULL
) {
396 return LDB_ERR_OPERATIONS_ERROR
;
398 ac
->local_msg
->dn
= msg
->dn
;
400 /* Prepare the remote message */
401 remote_msg
= ldb_msg_new(ac
);
402 if (remote_msg
== NULL
) {
404 return LDB_ERR_OPERATIONS_ERROR
;
406 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
408 /* Split local from remote message */
409 ldb_msg_partition(module
, ac
->local_msg
, remote_msg
, msg
);
411 /* Prepare the remote operation */
412 ret
= ldb_build_add_req(&ac
->remote_req
, ldb
,
415 ac
, map_op_remote_callback
,
417 if (ret
!= LDB_SUCCESS
) {
418 return LDB_ERR_OPERATIONS_ERROR
;
421 if ((ac
->local_msg
->num_elements
== 0) ||
422 ( ! map_check_local_db(ac
->module
))) {
423 /* No local data or db, just run the remote request */
424 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
427 /* Store remote DN in 'IS_MAPPED' */
428 /* TODO: use GUIDs here instead */
429 dn
= ldb_dn_alloc_linearized(ac
->local_msg
, remote_msg
->dn
);
430 if (ldb_msg_add_string(ac
->local_msg
, IS_MAPPED
, dn
) != 0) {
431 return LDB_ERR_OPERATIONS_ERROR
;
434 return map_add_do_local(ac
);
437 /* Add the local record. */
438 static int map_add_do_local(struct map_context
*ac
)
440 struct ldb_request
*local_req
;
441 struct ldb_context
*ldb
;
444 ldb
= ldb_module_get_ctx(ac
->module
);
446 /* Prepare the local operation */
447 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
451 map_op_local_callback
,
453 if (ret
!= LDB_SUCCESS
) {
454 return LDB_ERR_OPERATIONS_ERROR
;
456 return ldb_next_request(ac
->module
, local_req
);
459 /*****************************************************************************
461 *****************************************************************************/
463 /* Modify a record. */
464 int map_modify(struct ldb_module
*module
, struct ldb_request
*req
)
466 const struct ldb_message
*msg
= req
->op
.mod
.message
;
467 struct ldb_request
*search_req
;
468 struct ldb_message
*remote_msg
;
469 struct ldb_context
*ldb
;
470 struct map_context
*ac
;
473 ldb
= ldb_module_get_ctx(module
);
475 /* Do not manipulate our control entries */
476 if (ldb_dn_is_special(msg
->dn
)) {
477 return ldb_next_request(module
, req
);
480 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
481 if (!ldb_dn_check_local(module
, msg
->dn
)) {
482 return ldb_next_request(module
, req
);
485 /* No mapping needed, skip to next module */
486 /* TODO: What if the remote part exists, the local doesn't,
487 * and this request wants to modify local data and thus
488 * add the local record? */
489 if (!ldb_msg_check_remote(module
, msg
)) {
490 return LDB_ERR_OPERATIONS_ERROR
;
493 /* Prepare context and handle */
494 ac
= map_init_context(module
, req
);
496 return LDB_ERR_OPERATIONS_ERROR
;
499 /* Prepare the local message */
500 ac
->local_msg
= ldb_msg_new(ac
);
501 if (ac
->local_msg
== NULL
) {
503 return LDB_ERR_OPERATIONS_ERROR
;
505 ac
->local_msg
->dn
= msg
->dn
;
507 /* Prepare the remote message */
508 remote_msg
= ldb_msg_new(ac
->remote_req
);
509 if (remote_msg
== NULL
) {
511 return LDB_ERR_OPERATIONS_ERROR
;
513 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
515 /* Split local from remote message */
516 ldb_msg_partition(module
, ac
->local_msg
, remote_msg
, msg
);
518 /* Prepare the remote operation */
519 ret
= ldb_build_mod_req(&ac
->remote_req
, ldb
,
522 ac
, map_op_remote_callback
,
524 if (ret
!= LDB_SUCCESS
) {
525 return LDB_ERR_OPERATIONS_ERROR
;
528 if ((ac
->local_msg
->num_elements
== 0) ||
529 ( ! map_check_local_db(ac
->module
))) {
530 /* No local data or db, just run the remote request */
531 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
534 /* prepare the search operation */
535 ret
= map_search_self_req(&search_req
, ac
, msg
->dn
);
536 if (ret
!= LDB_SUCCESS
) {
537 return LDB_ERR_OPERATIONS_ERROR
;
540 return ldb_next_request(module
, search_req
);
543 /* Modify the local record. */
544 static int map_modify_do_local(struct map_context
*ac
)
546 struct ldb_request
*local_req
;
547 struct ldb_context
*ldb
;
551 ldb
= ldb_module_get_ctx(ac
->module
);
553 if (ac
->local_dn
== NULL
) {
554 /* No local record present, add it instead */
555 /* Add local 'IS_MAPPED' */
556 /* TODO: use GUIDs here instead */
557 if (ldb_msg_add_empty(ac
->local_msg
, IS_MAPPED
,
558 LDB_FLAG_MOD_ADD
, NULL
) != 0) {
559 return LDB_ERR_OPERATIONS_ERROR
;
561 dn
= ldb_dn_alloc_linearized(ac
->local_msg
,
562 ac
->remote_req
->op
.mod
.message
->dn
);
563 if (ldb_msg_add_string(ac
->local_msg
, IS_MAPPED
, dn
) != 0) {
564 return LDB_ERR_OPERATIONS_ERROR
;
567 /* Prepare the local operation */
568 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
572 map_op_local_callback
,
574 if (ret
!= LDB_SUCCESS
) {
575 return LDB_ERR_OPERATIONS_ERROR
;
578 /* Prepare the local operation */
579 ret
= ldb_build_mod_req(&local_req
, ldb
, ac
,
583 map_op_local_callback
,
585 if (ret
!= LDB_SUCCESS
) {
586 return LDB_ERR_OPERATIONS_ERROR
;
590 return ldb_next_request(ac
->module
, local_req
);
593 /*****************************************************************************
595 *****************************************************************************/
597 /* Delete a record. */
598 int map_delete(struct ldb_module
*module
, struct ldb_request
*req
)
600 struct ldb_request
*search_req
;
601 struct ldb_context
*ldb
;
602 struct map_context
*ac
;
605 ldb
= ldb_module_get_ctx(module
);
607 /* Do not manipulate our control entries */
608 if (ldb_dn_is_special(req
->op
.del
.dn
)) {
609 return ldb_next_request(module
, req
);
612 /* No mapping requested (perhaps no DN mapping specified).
613 * Skip to next module */
614 if (!ldb_dn_check_local(module
, req
->op
.del
.dn
)) {
615 return ldb_next_request(module
, req
);
618 /* Prepare context and handle */
619 ac
= map_init_context(module
, req
);
621 return LDB_ERR_OPERATIONS_ERROR
;
624 /* Prepare the remote operation */
625 ret
= ldb_build_del_req(&ac
->remote_req
, ldb
, ac
,
626 ldb_dn_map_local(module
, ac
, req
->op
.del
.dn
),
629 map_op_remote_callback
,
631 if (ret
!= LDB_SUCCESS
) {
632 return LDB_ERR_OPERATIONS_ERROR
;
635 /* No local db, just run the remote request */
636 if (!map_check_local_db(ac
->module
)) {
637 /* Do the remote request. */
638 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
641 /* Prepare the search operation */
642 ret
= map_search_self_req(&search_req
, ac
, req
->op
.del
.dn
);
643 if (ret
!= LDB_SUCCESS
) {
645 return LDB_ERR_OPERATIONS_ERROR
;
648 return ldb_next_request(module
, search_req
);
651 /* Delete the local record. */
652 static int map_delete_do_local(struct map_context
*ac
)
654 struct ldb_request
*local_req
;
655 struct ldb_context
*ldb
;
658 ldb
= ldb_module_get_ctx(ac
->module
);
660 /* No local record, continue remotely */
661 if (ac
->local_dn
== NULL
) {
662 /* Do the remote request. */
663 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
666 /* Prepare the local operation */
667 ret
= ldb_build_del_req(&local_req
, ldb
, ac
,
671 map_op_local_callback
,
673 if (ret
!= LDB_SUCCESS
) {
674 return LDB_ERR_OPERATIONS_ERROR
;
676 return ldb_next_request(ac
->module
, local_req
);
679 /*****************************************************************************
681 *****************************************************************************/
683 /* Rename a record. */
684 int map_rename(struct ldb_module
*module
, struct ldb_request
*req
)
686 struct ldb_request
*search_req
;
687 struct ldb_context
*ldb
;
688 struct map_context
*ac
;
691 ldb
= ldb_module_get_ctx(module
);
693 /* Do not manipulate our control entries */
694 if (ldb_dn_is_special(req
->op
.rename
.olddn
)) {
695 return ldb_next_request(module
, req
);
698 /* No mapping requested (perhaps no DN mapping specified).
699 * Skip to next module */
700 if ((!ldb_dn_check_local(module
, req
->op
.rename
.olddn
)) &&
701 (!ldb_dn_check_local(module
, req
->op
.rename
.newdn
))) {
702 return ldb_next_request(module
, req
);
705 /* Rename into/out of the mapped partition requested, bail out */
706 if (!ldb_dn_check_local(module
, req
->op
.rename
.olddn
) ||
707 !ldb_dn_check_local(module
, req
->op
.rename
.newdn
)) {
708 return LDB_ERR_AFFECTS_MULTIPLE_DSAS
;
711 /* Prepare context and handle */
712 ac
= map_init_context(module
, req
);
714 return LDB_ERR_OPERATIONS_ERROR
;
717 /* Prepare the remote operation */
718 ret
= ldb_build_rename_req(&ac
->remote_req
, ldb
, ac
,
719 ldb_dn_map_local(module
, ac
, req
->op
.rename
.olddn
),
720 ldb_dn_map_local(module
, ac
, req
->op
.rename
.newdn
),
722 ac
, map_op_remote_callback
,
724 if (ret
!= LDB_SUCCESS
) {
725 return LDB_ERR_OPERATIONS_ERROR
;
728 /* No local db, just run the remote request */
729 if (!map_check_local_db(ac
->module
)) {
730 /* Do the remote request. */
731 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
734 /* Prepare the search operation */
735 ret
= map_search_self_req(&search_req
, ac
, req
->op
.rename
.olddn
);
736 if (ret
!= LDB_SUCCESS
) {
738 return LDB_ERR_OPERATIONS_ERROR
;
741 return ldb_next_request(module
, search_req
);
744 /* Rename the local record. */
745 static int map_rename_do_local(struct map_context
*ac
)
747 struct ldb_request
*local_req
;
748 struct ldb_context
*ldb
;
751 ldb
= ldb_module_get_ctx(ac
->module
);
753 /* No local record, continue remotely */
754 if (ac
->local_dn
== NULL
) {
755 /* Do the remote request. */
756 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
759 /* Prepare the local operation */
760 ret
= ldb_build_rename_req(&local_req
, ldb
, ac
,
761 ac
->req
->op
.rename
.olddn
,
762 ac
->req
->op
.rename
.newdn
,
765 map_rename_local_callback
,
767 if (ret
!= LDB_SUCCESS
) {
768 return LDB_ERR_OPERATIONS_ERROR
;
771 return ldb_next_request(ac
->module
, local_req
);
774 static int map_rename_local_callback(struct ldb_request
*req
,
775 struct ldb_reply
*ares
)
777 struct ldb_context
*ldb
;
778 struct map_context
*ac
;
781 ac
= talloc_get_type(req
->context
, struct map_context
);
782 ldb
= ldb_module_get_ctx(ac
->module
);
785 return ldb_module_done(ac
->req
, NULL
, NULL
,
786 LDB_ERR_OPERATIONS_ERROR
);
788 if (ares
->error
!= LDB_SUCCESS
) {
789 return ldb_module_done(ac
->req
, ares
->controls
,
790 ares
->response
, ares
->error
);
793 if (ares
->type
!= LDB_REPLY_DONE
) {
794 ldb_set_errstring(ldb
, "Invalid reply type!");
795 return ldb_module_done(ac
->req
, NULL
, NULL
,
796 LDB_ERR_OPERATIONS_ERROR
);
799 /* proceed with next step */
800 ret
= map_rename_do_fixup(ac
);
801 if (ret
!= LDB_SUCCESS
) {
802 return ldb_module_done(ac
->req
, NULL
, NULL
,
803 LDB_ERR_OPERATIONS_ERROR
);
809 /* Update the local 'IS_MAPPED' attribute. */
810 static int map_rename_do_fixup(struct map_context
*ac
)
812 struct ldb_request
*local_req
;
814 /* Prepare the fixup operation */
815 /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
816 local_req
= map_build_fixup_req(ac
,
817 ac
->req
->op
.rename
.newdn
,
818 ac
->remote_req
->op
.rename
.newdn
,
820 map_op_local_callback
);
821 if (local_req
== NULL
) {
822 return LDB_ERR_OPERATIONS_ERROR
;
825 return ldb_next_request(ac
->module
, local_req
);