Fix the mess with ldb includes.
[Samba/ekacnet.git] / source4 / lib / ldb / ldb_map / ldb_map_inbound.c
blobe915a5f46a38fe073c51f37010ca8dddd896917b
1 /*
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
10 ** under the LGPL
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_module.h"
29 #include "ldb_map.h"
30 #include "ldb_map_private.h"
33 /* Mapping message elements
34 * ======================== */
36 /* Map a message element into the remote partition. */
37 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)
39 struct ldb_message_element *el;
40 int i;
42 el = talloc_zero(mem_ctx, struct ldb_message_element);
43 if (el == NULL) {
44 map_oom(module);
45 return NULL;
48 el->num_values = old->num_values;
49 el->values = talloc_array(el, struct ldb_val, el->num_values);
50 if (el->values == NULL) {
51 talloc_free(el);
52 map_oom(module);
53 return NULL;
56 el->name = map_attr_map_local(el, map, old->name);
58 for (i = 0; i < el->num_values; i++) {
59 el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]);
62 return el;
65 /* Add a message element either to a local or to a remote message,
66 * depending on whether it goes into the local or remote partition. */
67 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)
69 const struct ldb_map_context *data = map_get_context(module);
70 const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name);
71 struct ldb_message_element *el=NULL;
72 struct ldb_context *ldb = ldb_module_get_ctx(module);
74 /* Unknown attribute: ignore */
75 if (map == NULL) {
76 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
77 "Not mapping attribute '%s': no mapping found\n",
78 old->name);
79 goto local;
82 switch (map->type) {
83 case MAP_IGNORE:
84 goto local;
86 case MAP_CONVERT:
87 if (map->u.convert.convert_local == NULL) {
88 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
89 "Not mapping attribute '%s': "
90 "'convert_local' not set\n",
91 map->local_name);
92 goto local;
94 /* fall through */
95 case MAP_KEEP:
96 case MAP_RENAME:
97 el = ldb_msg_el_map_local(module, remote, map, old);
98 break;
100 case MAP_GENERATE:
101 if (map->u.generate.generate_remote == NULL) {
102 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
103 "Not mapping attribute '%s': "
104 "'generate_remote' not set\n",
105 map->local_name);
106 goto local;
109 /* TODO: if this attr requires context:
110 * make sure all context attrs are mappable (in 'names')
111 * make sure all context attrs have already been mapped?
112 * maybe postpone generation until they have been mapped?
115 map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
116 return 0;
119 if (el == NULL) {
120 return -1;
123 return ldb_msg_add(remote, el, old->flags);
125 local:
126 el = talloc(local, struct ldb_message_element);
127 if (el == NULL) {
128 map_oom(module);
129 return -1;
132 *el = *old; /* copy the old element */
134 return ldb_msg_add(local, el, old->flags);
137 /* Mapping messages
138 * ================ */
140 /* Check whether a message will be (partially) mapped into the remote partition. */
141 static bool ldb_msg_check_remote(struct ldb_module *module, const struct ldb_message *msg)
143 const struct ldb_map_context *data = map_get_context(module);
144 bool ret;
145 int i;
147 for (i = 0; i < msg->num_elements; i++) {
148 ret = map_attr_check_remote(data, msg->elements[i].name);
149 if (ret) {
150 return ret;
154 return false;
157 /* Split message elements that stay in the local partition from those
158 * that are mapped into the remote partition. */
159 static int ldb_msg_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg)
161 /* const char * const names[]; */
162 struct ldb_context *ldb;
163 int i, ret;
165 ldb = ldb_module_get_ctx(module);
167 for (i = 0; i < msg->num_elements; i++) {
168 /* Skip 'IS_MAPPED' */
169 if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
170 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
171 "Skipping attribute '%s'\n",
172 msg->elements[i].name);
173 continue;
176 ret = ldb_msg_el_partition(module, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
177 if (ret) {
178 return ret;
182 return 0;
186 static int map_add_do_local(struct map_context *ac);
187 static int map_modify_do_local(struct map_context *ac);
188 static int map_delete_do_local(struct map_context *ac);
189 static int map_rename_do_local(struct map_context *ac);
190 static int map_rename_do_fixup(struct map_context *ac);
191 static int map_rename_local_callback(struct ldb_request *req,
192 struct ldb_reply *ares);
195 /*****************************************************************************
196 * COMMON INBOUND functions
197 *****************************************************************************/
199 /* Store the DN of a single search result in context. */
200 static int map_search_self_callback(struct ldb_request *req, struct ldb_reply *ares)
202 struct ldb_context *ldb;
203 struct map_context *ac;
204 int ret;
206 ac = talloc_get_type(req->context, struct map_context);
207 ldb = ldb_module_get_ctx(ac->module);
209 if (!ares) {
210 return ldb_module_done(ac->req, NULL, NULL,
211 LDB_ERR_OPERATIONS_ERROR);
213 if (ares->error != LDB_SUCCESS) {
214 return ldb_module_done(ac->req, ares->controls,
215 ares->response, ares->error);
218 /* We are interested only in the single reply */
219 switch(ares->type) {
220 case LDB_REPLY_ENTRY:
221 /* We have already found a remote DN */
222 if (ac->local_dn) {
223 ldb_set_errstring(ldb,
224 "Too many results!");
225 return ldb_module_done(ac->req, NULL, NULL,
226 LDB_ERR_OPERATIONS_ERROR);
229 /* Store local DN */
230 ac->local_dn = talloc_steal(ac, ares->message->dn);
231 break;
233 case LDB_REPLY_DONE:
235 switch (ac->req->operation) {
236 case LDB_MODIFY:
237 ret = map_modify_do_local(ac);
238 break;
239 case LDB_DELETE:
240 ret = map_delete_do_local(ac);
241 break;
242 case LDB_RENAME:
243 ret = map_rename_do_local(ac);
244 break;
245 default:
246 /* if we get here we have definitely a problem */
247 ret = LDB_ERR_OPERATIONS_ERROR;
249 if (ret != LDB_SUCCESS) {
250 return ldb_module_done(ac->req, NULL, NULL,
251 LDB_ERR_OPERATIONS_ERROR);
254 default:
255 /* ignore referrals */
256 break;
259 talloc_free(ares);
260 return LDB_SUCCESS;
263 /* Build a request to search the local record by its DN. */
264 static int map_search_self_req(struct ldb_request **req,
265 struct map_context *ac,
266 struct ldb_dn *dn)
268 /* attrs[] is returned from this function in
269 * ac->search_req->op.search.attrs, so it must be static, as
270 * otherwise the compiler can put it on the stack */
271 static const char * const attrs[] = { IS_MAPPED, NULL };
272 struct ldb_parse_tree *tree;
274 /* Limit search to records with 'IS_MAPPED' present */
275 tree = ldb_parse_tree(ac, "(" IS_MAPPED "=*)");
276 if (tree == NULL) {
277 map_oom(ac->module);
278 return LDB_ERR_OPERATIONS_ERROR;
281 *req = map_search_base_req(ac, dn, attrs, tree,
282 ac, map_search_self_callback);
283 if (*req == NULL) {
284 return LDB_ERR_OPERATIONS_ERROR;
287 return LDB_SUCCESS;
290 static int map_op_local_callback(struct ldb_request *req,
291 struct ldb_reply *ares)
293 struct ldb_context *ldb;
294 struct map_context *ac;
295 int ret;
297 ac = talloc_get_type(req->context, struct map_context);
298 ldb = ldb_module_get_ctx(ac->module);
300 if (!ares) {
301 return ldb_module_done(ac->req, NULL, NULL,
302 LDB_ERR_OPERATIONS_ERROR);
304 if (ares->error != LDB_SUCCESS) {
305 return ldb_module_done(ac->req, ares->controls,
306 ares->response, ares->error);
309 if (ares->type != LDB_REPLY_DONE) {
310 ldb_set_errstring(ldb, "Invalid reply type!");
311 return ldb_module_done(ac->req, NULL, NULL,
312 LDB_ERR_OPERATIONS_ERROR);
315 /* Do the remote request. */
316 ret = ldb_next_remote_request(ac->module, ac->remote_req);
317 if (ret != LDB_SUCCESS) {
318 return ldb_module_done(ac->req, NULL, NULL,
319 LDB_ERR_OPERATIONS_ERROR);
322 return LDB_SUCCESS;
325 static int map_op_remote_callback(struct ldb_request *req,
326 struct ldb_reply *ares)
328 struct ldb_context *ldb;
329 struct map_context *ac;
331 ac = talloc_get_type(req->context, struct map_context);
332 ldb = ldb_module_get_ctx(ac->module);
334 if (!ares) {
335 return ldb_module_done(ac->req, NULL, NULL,
336 LDB_ERR_OPERATIONS_ERROR);
338 if (ares->error != LDB_SUCCESS) {
339 return ldb_module_done(ac->req, ares->controls,
340 ares->response, ares->error);
343 if (ares->type != LDB_REPLY_DONE) {
344 ldb_set_errstring(ldb, "Invalid reply type!");
345 return ldb_module_done(ac->req, NULL, NULL,
346 LDB_ERR_OPERATIONS_ERROR);
349 return ldb_module_done(ac->req, ares->controls,
350 ares->response, ares->error);
354 /*****************************************************************************
355 * ADD operations
356 *****************************************************************************/
359 /* Add a record. */
360 int map_add(struct ldb_module *module, struct ldb_request *req)
362 const struct ldb_message *msg = req->op.add.message;
363 struct ldb_context *ldb;
364 struct map_context *ac;
365 struct ldb_message *remote_msg;
366 const char *dn;
367 int ret;
369 ldb = ldb_module_get_ctx(module);
371 /* Do not manipulate our control entries */
372 if (ldb_dn_is_special(msg->dn)) {
373 return ldb_next_request(module, req);
376 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
377 if (!ldb_dn_check_local(module, msg->dn)) {
378 return ldb_next_request(module, req);
381 /* No mapping needed, fail */
382 if (!ldb_msg_check_remote(module, msg)) {
383 return LDB_ERR_OPERATIONS_ERROR;
386 /* Prepare context and handle */
387 ac = map_init_context(module, req);
388 if (ac == NULL) {
389 return LDB_ERR_OPERATIONS_ERROR;
393 /* Prepare the local message */
394 ac->local_msg = ldb_msg_new(ac);
395 if (ac->local_msg == NULL) {
396 map_oom(module);
397 return LDB_ERR_OPERATIONS_ERROR;
399 ac->local_msg->dn = msg->dn;
401 /* Prepare the remote message */
402 remote_msg = ldb_msg_new(ac);
403 if (remote_msg == NULL) {
404 map_oom(module);
405 return LDB_ERR_OPERATIONS_ERROR;
407 remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
409 /* Split local from remote message */
410 ldb_msg_partition(module, ac->local_msg, remote_msg, msg);
412 /* Prepare the remote operation */
413 ret = ldb_build_add_req(&ac->remote_req, ldb,
414 ac, remote_msg,
415 req->controls,
416 ac, map_op_remote_callback,
417 req);
418 if (ret != LDB_SUCCESS) {
419 return LDB_ERR_OPERATIONS_ERROR;
422 if ((ac->local_msg->num_elements == 0) ||
423 ( ! map_check_local_db(ac->module))) {
424 /* No local data or db, just run the remote request */
425 return ldb_next_remote_request(ac->module, ac->remote_req);
428 /* Store remote DN in 'IS_MAPPED' */
429 /* TODO: use GUIDs here instead */
430 dn = ldb_dn_alloc_linearized(ac->local_msg, remote_msg->dn);
431 if (ldb_msg_add_string(ac->local_msg, IS_MAPPED, dn) != 0) {
432 return LDB_ERR_OPERATIONS_ERROR;
435 return map_add_do_local(ac);
438 /* Add the local record. */
439 static int map_add_do_local(struct map_context *ac)
441 struct ldb_request *local_req;
442 struct ldb_context *ldb;
443 int ret;
445 ldb = ldb_module_get_ctx(ac->module);
447 /* Prepare the local operation */
448 ret = ldb_build_add_req(&local_req, ldb, ac,
449 ac->local_msg,
450 ac->req->controls,
452 map_op_local_callback,
453 ac->req);
454 if (ret != LDB_SUCCESS) {
455 return LDB_ERR_OPERATIONS_ERROR;
457 return ldb_next_request(ac->module, local_req);
460 /*****************************************************************************
461 * MODIFY operations
462 *****************************************************************************/
464 /* Modify a record. */
465 int map_modify(struct ldb_module *module, struct ldb_request *req)
467 const struct ldb_message *msg = req->op.mod.message;
468 struct ldb_request *search_req;
469 struct ldb_message *remote_msg;
470 struct ldb_context *ldb;
471 struct map_context *ac;
472 int ret;
474 ldb = ldb_module_get_ctx(module);
476 /* Do not manipulate our control entries */
477 if (ldb_dn_is_special(msg->dn)) {
478 return ldb_next_request(module, req);
481 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
482 if (!ldb_dn_check_local(module, msg->dn)) {
483 return ldb_next_request(module, req);
486 /* No mapping needed, skip to next module */
487 /* TODO: What if the remote part exists, the local doesn't,
488 * and this request wants to modify local data and thus
489 * add the local record? */
490 if (!ldb_msg_check_remote(module, msg)) {
491 return LDB_ERR_OPERATIONS_ERROR;
494 /* Prepare context and handle */
495 ac = map_init_context(module, req);
496 if (ac == NULL) {
497 return LDB_ERR_OPERATIONS_ERROR;
500 /* Prepare the local message */
501 ac->local_msg = ldb_msg_new(ac);
502 if (ac->local_msg == NULL) {
503 map_oom(module);
504 return LDB_ERR_OPERATIONS_ERROR;
506 ac->local_msg->dn = msg->dn;
508 /* Prepare the remote message */
509 remote_msg = ldb_msg_new(ac->remote_req);
510 if (remote_msg == NULL) {
511 map_oom(module);
512 return LDB_ERR_OPERATIONS_ERROR;
514 remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
516 /* Split local from remote message */
517 ldb_msg_partition(module, ac->local_msg, remote_msg, msg);
519 /* Prepare the remote operation */
520 ret = ldb_build_mod_req(&ac->remote_req, ldb,
521 ac, remote_msg,
522 req->controls,
523 ac, map_op_remote_callback,
524 req);
525 if (ret != LDB_SUCCESS) {
526 return LDB_ERR_OPERATIONS_ERROR;
529 if ((ac->local_msg->num_elements == 0) ||
530 ( ! map_check_local_db(ac->module))) {
531 /* No local data or db, just run the remote request */
532 return ldb_next_remote_request(ac->module, ac->remote_req);
535 /* prepare the search operation */
536 ret = map_search_self_req(&search_req, ac, msg->dn);
537 if (ret != LDB_SUCCESS) {
538 return LDB_ERR_OPERATIONS_ERROR;
541 return ldb_next_request(module, search_req);
544 /* Modify the local record. */
545 static int map_modify_do_local(struct map_context *ac)
547 struct ldb_request *local_req;
548 struct ldb_context *ldb;
549 char *dn;
550 int ret;
552 ldb = ldb_module_get_ctx(ac->module);
554 if (ac->local_dn == NULL) {
555 /* No local record present, add it instead */
556 /* Add local 'IS_MAPPED' */
557 /* TODO: use GUIDs here instead */
558 if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED,
559 LDB_FLAG_MOD_ADD, NULL) != 0) {
560 return LDB_ERR_OPERATIONS_ERROR;
562 dn = ldb_dn_alloc_linearized(ac->local_msg,
563 ac->remote_req->op.mod.message->dn);
564 if (ldb_msg_add_string(ac->local_msg, IS_MAPPED, dn) != 0) {
565 return LDB_ERR_OPERATIONS_ERROR;
568 /* Prepare the local operation */
569 ret = ldb_build_add_req(&local_req, ldb, ac,
570 ac->local_msg,
571 ac->req->controls,
573 map_op_local_callback,
574 ac->req);
575 if (ret != LDB_SUCCESS) {
576 return LDB_ERR_OPERATIONS_ERROR;
578 } else {
579 /* Prepare the local operation */
580 ret = ldb_build_mod_req(&local_req, ldb, ac,
581 ac->local_msg,
582 ac->req->controls,
584 map_op_local_callback,
585 ac->req);
586 if (ret != LDB_SUCCESS) {
587 return LDB_ERR_OPERATIONS_ERROR;
591 return ldb_next_request(ac->module, local_req);
594 /*****************************************************************************
595 * DELETE operations
596 *****************************************************************************/
598 /* Delete a record. */
599 int map_delete(struct ldb_module *module, struct ldb_request *req)
601 struct ldb_request *search_req;
602 struct ldb_context *ldb;
603 struct map_context *ac;
604 int ret;
606 ldb = ldb_module_get_ctx(module);
608 /* Do not manipulate our control entries */
609 if (ldb_dn_is_special(req->op.del.dn)) {
610 return ldb_next_request(module, req);
613 /* No mapping requested (perhaps no DN mapping specified).
614 * Skip to next module */
615 if (!ldb_dn_check_local(module, req->op.del.dn)) {
616 return ldb_next_request(module, req);
619 /* Prepare context and handle */
620 ac = map_init_context(module, req);
621 if (ac == NULL) {
622 return LDB_ERR_OPERATIONS_ERROR;
625 /* Prepare the remote operation */
626 ret = ldb_build_del_req(&ac->remote_req, ldb, ac,
627 ldb_dn_map_local(module, ac, req->op.del.dn),
628 req->controls,
630 map_op_remote_callback,
631 req);
632 if (ret != LDB_SUCCESS) {
633 return LDB_ERR_OPERATIONS_ERROR;
636 /* No local db, just run the remote request */
637 if (!map_check_local_db(ac->module)) {
638 /* Do the remote request. */
639 return ldb_next_remote_request(ac->module, ac->remote_req);
642 /* Prepare the search operation */
643 ret = map_search_self_req(&search_req, ac, req->op.del.dn);
644 if (ret != LDB_SUCCESS) {
645 map_oom(module);
646 return LDB_ERR_OPERATIONS_ERROR;
649 return ldb_next_request(module, search_req);
652 /* Delete the local record. */
653 static int map_delete_do_local(struct map_context *ac)
655 struct ldb_request *local_req;
656 struct ldb_context *ldb;
657 int ret;
659 ldb = ldb_module_get_ctx(ac->module);
661 /* No local record, continue remotely */
662 if (ac->local_dn == NULL) {
663 /* Do the remote request. */
664 return ldb_next_remote_request(ac->module, ac->remote_req);
667 /* Prepare the local operation */
668 ret = ldb_build_del_req(&local_req, ldb, ac,
669 ac->req->op.del.dn,
670 ac->req->controls,
672 map_op_local_callback,
673 ac->req);
674 if (ret != LDB_SUCCESS) {
675 return LDB_ERR_OPERATIONS_ERROR;
677 return ldb_next_request(ac->module, local_req);
680 /*****************************************************************************
681 * RENAME operations
682 *****************************************************************************/
684 /* Rename a record. */
685 int map_rename(struct ldb_module *module, struct ldb_request *req)
687 struct ldb_request *search_req;
688 struct ldb_context *ldb;
689 struct map_context *ac;
690 int ret;
692 ldb = ldb_module_get_ctx(module);
694 /* Do not manipulate our control entries */
695 if (ldb_dn_is_special(req->op.rename.olddn)) {
696 return ldb_next_request(module, req);
699 /* No mapping requested (perhaps no DN mapping specified).
700 * Skip to next module */
701 if ((!ldb_dn_check_local(module, req->op.rename.olddn)) &&
702 (!ldb_dn_check_local(module, req->op.rename.newdn))) {
703 return ldb_next_request(module, req);
706 /* Rename into/out of the mapped partition requested, bail out */
707 if (!ldb_dn_check_local(module, req->op.rename.olddn) ||
708 !ldb_dn_check_local(module, req->op.rename.newdn)) {
709 return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
712 /* Prepare context and handle */
713 ac = map_init_context(module, req);
714 if (ac == NULL) {
715 return LDB_ERR_OPERATIONS_ERROR;
718 /* Prepare the remote operation */
719 ret = ldb_build_rename_req(&ac->remote_req, ldb, ac,
720 ldb_dn_map_local(module, ac, req->op.rename.olddn),
721 ldb_dn_map_local(module, ac, req->op.rename.newdn),
722 req->controls,
723 ac, map_op_remote_callback,
724 req);
725 if (ret != LDB_SUCCESS) {
726 return LDB_ERR_OPERATIONS_ERROR;
729 /* No local db, just run the remote request */
730 if (!map_check_local_db(ac->module)) {
731 /* Do the remote request. */
732 return ldb_next_remote_request(ac->module, ac->remote_req);
735 /* Prepare the search operation */
736 ret = map_search_self_req(&search_req, ac, req->op.rename.olddn);
737 if (ret != LDB_SUCCESS) {
738 map_oom(module);
739 return LDB_ERR_OPERATIONS_ERROR;
742 return ldb_next_request(module, search_req);
745 /* Rename the local record. */
746 static int map_rename_do_local(struct map_context *ac)
748 struct ldb_request *local_req;
749 struct ldb_context *ldb;
750 int ret;
752 ldb = ldb_module_get_ctx(ac->module);
754 /* No local record, continue remotely */
755 if (ac->local_dn == NULL) {
756 /* Do the remote request. */
757 return ldb_next_remote_request(ac->module, ac->remote_req);
760 /* Prepare the local operation */
761 ret = ldb_build_rename_req(&local_req, ldb, ac,
762 ac->req->op.rename.olddn,
763 ac->req->op.rename.newdn,
764 ac->req->controls,
766 map_rename_local_callback,
767 ac->req);
768 if (ret != LDB_SUCCESS) {
769 return LDB_ERR_OPERATIONS_ERROR;
772 return ldb_next_request(ac->module, local_req);
775 static int map_rename_local_callback(struct ldb_request *req,
776 struct ldb_reply *ares)
778 struct ldb_context *ldb;
779 struct map_context *ac;
780 int ret;
782 ac = talloc_get_type(req->context, struct map_context);
783 ldb = ldb_module_get_ctx(ac->module);
785 if (!ares) {
786 return ldb_module_done(ac->req, NULL, NULL,
787 LDB_ERR_OPERATIONS_ERROR);
789 if (ares->error != LDB_SUCCESS) {
790 return ldb_module_done(ac->req, ares->controls,
791 ares->response, ares->error);
794 if (ares->type != LDB_REPLY_DONE) {
795 ldb_set_errstring(ldb, "Invalid reply type!");
796 return ldb_module_done(ac->req, NULL, NULL,
797 LDB_ERR_OPERATIONS_ERROR);
800 /* proceed with next step */
801 ret = map_rename_do_fixup(ac);
802 if (ret != LDB_SUCCESS) {
803 return ldb_module_done(ac->req, NULL, NULL,
804 LDB_ERR_OPERATIONS_ERROR);
807 return LDB_SUCCESS;
810 /* Update the local 'IS_MAPPED' attribute. */
811 static int map_rename_do_fixup(struct map_context *ac)
813 struct ldb_request *local_req;
815 /* Prepare the fixup operation */
816 /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
817 local_req = map_build_fixup_req(ac,
818 ac->req->op.rename.newdn,
819 ac->remote_req->op.rename.newdn,
821 map_op_local_callback);
822 if (local_req == NULL) {
823 return LDB_ERR_OPERATIONS_ERROR;
826 return ldb_next_request(ac->module, local_req);