s3-libads: Print the debug string of a failed call with LDAP_OTHER.
[Samba/bjacke.git] / lib / ldb / ldb_map / ldb_map_inbound.c
blob38dd5ac066d714e2d7661af592ef64120075ff38
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 "replace.h"
28 #include "system/filesys.h"
29 #include "system/time.h"
30 #include "ldb_map.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;
41 unsigned int i;
43 el = talloc_zero(mem_ctx, struct ldb_message_element);
44 if (el == NULL) {
45 map_oom(module);
46 return NULL;
49 el->num_values = old->num_values;
50 el->values = talloc_array(el, struct ldb_val, el->num_values);
51 if (el->values == NULL) {
52 talloc_free(el);
53 map_oom(module);
54 return 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]);
63 return el;
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 */
76 if (map == NULL) {
77 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
78 "Not mapping attribute '%s': no mapping found",
79 old->name);
80 goto local;
83 switch (map->type) {
84 case LDB_MAP_IGNORE:
85 goto local;
87 case LDB_MAP_CONVERT:
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",
92 map->local_name);
93 goto local;
95 /* fall through */
96 case LDB_MAP_KEEP:
97 case LDB_MAP_RENAME:
98 el = ldb_msg_el_map_local(module, remote, map, old);
99 break;
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",
106 map->local_name);
107 goto local;
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);
117 return 0;
120 if (el == NULL) {
121 return -1;
124 return ldb_msg_add(remote, el, old->flags);
126 local:
127 el = talloc(local, struct ldb_message_element);
128 if (el == NULL) {
129 map_oom(module);
130 return -1;
133 *el = *old; /* copy the old element */
135 return ldb_msg_add(local, el, old->flags);
138 /* Mapping messages
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);
145 bool ret;
146 unsigned int i;
148 for (i = 0; i < msg->num_elements; i++) {
149 ret = map_attr_check_remote(data, msg->elements[i].name);
150 if (ret) {
151 return ret;
155 return false;
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;
164 unsigned int i;
165 int ret;
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);
175 continue;
178 ret = ldb_msg_el_partition(module, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
179 if (ret) {
180 return ret;
184 return 0;
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;
206 int ret;
208 ac = talloc_get_type(req->context, struct map_context);
209 ldb = ldb_module_get_ctx(ac->module);
211 if (!ares) {
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 */
221 switch(ares->type) {
222 case LDB_REPLY_ENTRY:
223 /* We have already found a remote DN */
224 if (ac->local_dn) {
225 ldb_set_errstring(ldb,
226 "Too many results!");
227 return ldb_module_done(ac->req, NULL, NULL,
228 LDB_ERR_OPERATIONS_ERROR);
231 /* Store local DN */
232 ac->local_dn = talloc_steal(ac, ares->message->dn);
233 break;
235 case LDB_REPLY_DONE:
237 switch (ac->req->operation) {
238 case LDB_MODIFY:
239 ret = map_modify_do_local(ac);
240 break;
241 case LDB_DELETE:
242 ret = map_delete_do_local(ac);
243 break;
244 case LDB_RENAME:
245 ret = map_rename_do_local(ac);
246 break;
247 default:
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);
256 default:
257 /* ignore referrals */
258 break;
261 talloc_free(ares);
262 return LDB_SUCCESS;
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,
268 struct ldb_dn *dn)
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 "=*)");
278 if (tree == NULL) {
279 map_oom(ac->module);
280 return LDB_ERR_OPERATIONS_ERROR;
283 *req = map_search_base_req(ac, dn, attrs, tree,
284 ac, map_search_self_callback);
285 if (*req == NULL) {
286 return LDB_ERR_OPERATIONS_ERROR;
289 return LDB_SUCCESS;
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;
297 int ret;
299 ac = talloc_get_type(req->context, struct map_context);
300 ldb = ldb_module_get_ctx(ac->module);
302 if (!ares) {
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);
324 return LDB_SUCCESS;
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);
336 if (!ares) {
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 /*****************************************************************************
357 * ADD operations
358 *****************************************************************************/
361 /* Add a record. */
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;
368 int ret;
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);
389 if (ac == NULL) {
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) {
397 map_oom(module);
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) {
405 map_oom(module);
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,
415 ac, remote_msg,
416 req->controls,
417 ac, map_op_remote_callback,
418 req);
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,
433 remote_msg->dn);
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;
446 int ret;
448 ldb = ldb_module_get_ctx(ac->module);
450 /* Prepare the local operation */
451 ret = ldb_build_add_req(&local_req, ldb, ac,
452 ac->local_msg,
453 ac->req->controls,
455 map_op_local_callback,
456 ac->req);
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 /*****************************************************************************
465 * MODIFY operations
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;
476 int ret;
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);
500 if (ac == NULL) {
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) {
507 map_oom(module);
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) {
515 map_oom(module);
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,
525 ac, remote_msg,
526 req->controls,
527 ac, map_op_remote_callback,
528 req);
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;
554 int ret;
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);
568 if (ret != 0) {
569 return LDB_ERR_OPERATIONS_ERROR;
572 /* Prepare the local operation */
573 ret = ldb_build_add_req(&local_req, ldb, ac,
574 ac->local_msg,
575 ac->req->controls,
577 map_op_local_callback,
578 ac->req);
579 LDB_REQ_SET_LOCATION(local_req);
580 if (ret != LDB_SUCCESS) {
581 return LDB_ERR_OPERATIONS_ERROR;
583 } else {
584 /* Prepare the local operation */
585 ret = ldb_build_mod_req(&local_req, ldb, ac,
586 ac->local_msg,
587 ac->req->controls,
589 map_op_local_callback,
590 ac->req);
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 /*****************************************************************************
601 * DELETE operations
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;
610 int ret;
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);
627 if (ac == NULL) {
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),
634 req->controls,
636 map_op_remote_callback,
637 req);
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) {
652 map_oom(module);
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;
664 int ret;
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,
676 ac->req->op.del.dn,
677 ac->req->controls,
679 map_op_local_callback,
680 ac->req);
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 /*****************************************************************************
689 * RENAME operations
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;
698 int ret;
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);
722 if (ac == NULL) {
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),
730 req->controls,
731 ac, map_op_remote_callback,
732 req);
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) {
747 map_oom(module);
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;
759 int ret;
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,
773 ac->req->controls,
775 map_rename_local_callback,
776 ac->req);
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;
790 int ret;
792 ac = talloc_get_type(req->context, struct map_context);
793 ldb = ldb_module_get_ctx(ac->module);
795 if (!ares) {
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);
817 return LDB_SUCCESS;
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);