/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- ldb_msg_el_map_local
- ldb_msg_el_partition
- ldb_msg_check_remote
- ldb_msg_partition
- map_add_do_remote
- map_add_do_local
- map_add
- map_modify_do_remote
- map_modify_do_local
- map_modify
- map_delete_do_remote
- map_delete_do_local
- map_delete
- map_rename_do_remote
- map_rename_do_fixup
- map_rename_do_local
- map_rename
1 /*
2 ldb database mapping module
3
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6
7 * NOTICE: this module is NOT released under the GNU LGPL license as
8 * other ldb code. This module is release under the GNU GPL v2 or
9 * later license.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "ldb/include/includes.h"
27
28 #include "ldb/modules/ldb_map.h"
29 #include "ldb/modules/ldb_map_private.h"
30
31
32 /* Mapping message elements
33 * ======================== */
34
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)
/* [<][>][^][v][top][bottom][index][help] */
37 {
38 struct ldb_message_element *el;
39 int i;
40
41 el = talloc_zero(mem_ctx, struct ldb_message_element);
42 if (el == NULL) {
43 map_oom(module);
44 return NULL;
45 }
46
47 el->num_values = old->num_values;
48 el->values = talloc_array(el, struct ldb_val, el->num_values);
49 if (el->values == NULL) {
50 talloc_free(el);
51 map_oom(module);
52 return NULL;
53 }
54
55 el->name = map_attr_map_local(el, map, old->name);
56
57 for (i = 0; i < el->num_values; i++) {
58 el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]);
59 }
60
61 return el;
62 }
63
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)
/* [<][>][^][v][top][bottom][index][help] */
67 {
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
72 /* Unknown attribute: ignore */
73 if (map == NULL) {
74 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
75 "Not mapping attribute '%s': no mapping found\n",
76 old->name);
77 goto local;
78 }
79
80 switch (map->type) {
81 case MAP_IGNORE:
82 goto local;
83
84 case MAP_CONVERT:
85 if (map->u.convert.convert_local == NULL) {
86 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
87 "Not mapping attribute '%s': "
88 "'convert_local' not set\n",
89 map->local_name);
90 goto local;
91 }
92 /* fall through */
93 case MAP_KEEP:
94 case MAP_RENAME:
95 el = ldb_msg_el_map_local(module, remote, map, old);
96 break;
97
98 case MAP_GENERATE:
99 if (map->u.generate.generate_remote == NULL) {
100 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
101 "Not mapping attribute '%s': "
102 "'generate_remote' not set\n",
103 map->local_name);
104 goto local;
105 }
106
107 /* TODO: if this attr requires context:
108 * make sure all context attrs are mappable (in 'names')
109 * make sure all context attrs have already been mapped?
110 * maybe postpone generation until they have been mapped?
111 */
112
113 map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
114 return 0;
115 }
116
117 if (el == NULL) {
118 return -1;
119 }
120
121 return ldb_msg_add(remote, el, old->flags);
122
123 local:
124 el = talloc(local, struct ldb_message_element);
125 if (el == NULL) {
126 map_oom(module);
127 return -1;
128 }
129
130 *el = *old; /* copy the old element */
131
132 return ldb_msg_add(local, el, old->flags);
133 }
134
135 /* Mapping messages
136 * ================ */
137
138 /* Check whether a message will be (partially) mapped into the remote partition. */
139 static BOOL ldb_msg_check_remote(struct ldb_module *module, const struct ldb_message *msg)
/* [<][>][^][v][top][bottom][index][help] */
140 {
141 const struct ldb_map_context *data = map_get_context(module);
142 BOOL ret;
143 int i;
144
145 for (i = 0; i < msg->num_elements; i++) {
146 ret = map_attr_check_remote(data, msg->elements[i].name);
147 if (ret) {
148 return ret;
149 }
150 }
151
152 return False;
153 }
154
155 /* Split message elements that stay in the local partition from those
156 * that are mapped into the remote partition. */
157 static int ldb_msg_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg)
/* [<][>][^][v][top][bottom][index][help] */
158 {
159 /* const char * const names[]; */
160 int i, ret;
161
162 for (i = 0; i < msg->num_elements; i++) {
163 /* Skip 'IS_MAPPED' */
164 if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
165 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
166 "Skipping attribute '%s'\n",
167 msg->elements[i].name);
168 continue;
169 }
170
171 ret = ldb_msg_el_partition(module, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
172 if (ret) {
173 return ret;
174 }
175 }
176
177 return 0;
178 }
179
180
181 /* Inbound requests: add, modify, rename, delete
182 * ============================================= */
183
184 /* Add the remote record. */
185 int map_add_do_remote(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
186 {
187 struct map_context *ac;
188
189 ac = talloc_get_type(handle->private_data, struct map_context);
190
191 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->remote_req);
192
193 ac->step = MAP_ADD_REMOTE;
194
195 handle->state = LDB_ASYNC_INIT;
196 handle->status = LDB_SUCCESS;
197
198 return ldb_next_remote_request(ac->module, ac->remote_req);
199 }
200
201 /* Add the local record. */
202 int map_add_do_local(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
203 {
204 struct map_context *ac;
205
206 ac = talloc_get_type(handle->private_data, struct map_context);
207
208 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->local_req);
209
210 ac->step = MAP_ADD_LOCAL;
211
212 handle->state = LDB_ASYNC_INIT;
213 handle->status = LDB_SUCCESS;
214
215 return ldb_next_request(ac->module, ac->local_req);
216 }
217
218 /* Add a record. */
219 int map_add(struct ldb_module *module, struct ldb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
220 {
221 const struct ldb_message *msg = req->op.add.message;
222 struct ldb_handle *h;
223 struct map_context *ac;
224 struct ldb_message *local, *remote;
225 const char *dn;
226
227 /* Do not manipulate our control entries */
228 if (ldb_dn_is_special(msg->dn)) {
229 return ldb_next_request(module, req);
230 }
231
232 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
233 if (!ldb_dn_check_local(module, msg->dn)) {
234 return ldb_next_request(module, req);
235 }
236
237 /* No mapping needed, fail */
238 if (!ldb_msg_check_remote(module, msg)) {
239 return LDB_ERR_OPERATIONS_ERROR;
240 }
241
242 /* Prepare context and handle */
243 h = map_init_handle(req, module);
244 if (h == NULL) {
245 return LDB_ERR_OPERATIONS_ERROR;
246 }
247 ac = talloc_get_type(h->private_data, struct map_context);
248
249 /* Prepare the local operation */
250 ac->local_req = talloc(ac, struct ldb_request);
251 if (ac->local_req == NULL) {
252 goto oom;
253 }
254
255 *(ac->local_req) = *req; /* copy the request */
256
257 ac->local_req->context = NULL;
258 ac->local_req->callback = NULL;
259
260 /* Prepare the remote operation */
261 ac->remote_req = talloc(ac, struct ldb_request);
262 if (ac->remote_req == NULL) {
263 goto oom;
264 }
265
266 *(ac->remote_req) = *req; /* copy the request */
267
268 ac->remote_req->context = NULL;
269 ac->remote_req->callback = NULL;
270
271 /* Prepare the local message */
272 local = ldb_msg_new(ac->local_req);
273 if (local == NULL) {
274 goto oom;
275 }
276 local->dn = msg->dn;
277
278 /* Prepare the remote message */
279 remote = ldb_msg_new(ac->remote_req);
280 if (remote == NULL) {
281 goto oom;
282 }
283 remote->dn = ldb_dn_map_local(ac->module, remote, msg->dn);
284
285 /* Split local from remote message */
286 ldb_msg_partition(module, local, remote, msg);
287 ac->local_req->op.add.message = local;
288 ac->remote_req->op.add.message = remote;
289
290 if ((local->num_elements == 0) || (!map_check_local_db(ac->module))) {
291 /* No local data or db, just run the remote request */
292 talloc_free(ac->local_req);
293 req->handle = h; /* return our own handle to deal with this call */
294 return map_add_do_remote(h);
295 }
296
297 /* Store remote DN in 'IS_MAPPED' */
298 /* TODO: use GUIDs here instead */
299 dn = ldb_dn_linearize(local, remote->dn);
300 if (ldb_msg_add_string(local, IS_MAPPED, dn) != 0) {
301 goto failed;
302 }
303
304 req->handle = h; /* return our own handle to deal with this call */
305 return map_add_do_local(h);
306
307 oom:
308 map_oom(module);
309 failed:
310 talloc_free(h);
311 return LDB_ERR_OPERATIONS_ERROR;
312 }
313
314 /* Modify the remote record. */
315 int map_modify_do_remote(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
316 {
317 struct map_context *ac;
318
319 ac = talloc_get_type(handle->private_data, struct map_context);
320
321 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->remote_req);
322
323 ac->step = MAP_MODIFY_REMOTE;
324
325 handle->state = LDB_ASYNC_INIT;
326 handle->status = LDB_SUCCESS;
327
328 return ldb_next_remote_request(ac->module, ac->remote_req);
329 }
330
331 /* Modify the local record. */
332 int map_modify_do_local(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
333 {
334 struct map_context *ac;
335 struct ldb_message *msg;
336 char *dn;
337
338 ac = talloc_get_type(handle->private_data, struct map_context);
339
340 if (ac->local_dn == NULL) {
341 /* No local record present, add it instead */
342 msg = discard_const_p(struct ldb_message, ac->local_req->op.mod.message);
343
344 /* Add local 'IS_MAPPED' */
345 /* TODO: use GUIDs here instead */
346 dn = ldb_dn_linearize(msg, ac->remote_req->op.mod.message->dn);
347 if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_ADD, NULL) != 0) {
348 return LDB_ERR_OPERATIONS_ERROR;
349 }
350 if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) {
351 return LDB_ERR_OPERATIONS_ERROR;
352 }
353
354 /* Turn request into 'add' */
355 ac->local_req->operation = LDB_ADD;
356 ac->local_req->op.add.message = msg;
357 /* TODO: Could I just leave msg in there? I think so,
358 * but it looks clearer this way. */
359 }
360
361 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->local_req);
362
363 ac->step = MAP_MODIFY_LOCAL;
364
365 handle->state = LDB_ASYNC_INIT;
366 handle->status = LDB_SUCCESS;
367
368 return ldb_next_request(ac->module, ac->local_req);
369 }
370
371 /* Modify a record. */
372 int map_modify(struct ldb_module *module, struct ldb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
373 {
374 const struct ldb_message *msg = req->op.mod.message;
375 struct ldb_handle *h;
376 struct map_context *ac;
377 struct ldb_message *local, *remote;
378
379 /* Do not manipulate our control entries */
380 if (ldb_dn_is_special(msg->dn)) {
381 return ldb_next_request(module, req);
382 }
383
384 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
385 if (!ldb_dn_check_local(module, msg->dn)) {
386 return ldb_next_request(module, req);
387 }
388
389 /* No mapping needed, skip to next module */
390 /* TODO: What if the remote part exists, the local doesn't,
391 * and this request wants to modify local data and thus
392 * add the local record? */
393 if (!ldb_msg_check_remote(module, msg)) {
394 return LDB_ERR_OPERATIONS_ERROR;
395 }
396
397 /* Prepare context and handle */
398 h = map_init_handle(req, module);
399 if (h == NULL) {
400 return LDB_ERR_OPERATIONS_ERROR;
401 }
402 ac = talloc_get_type(h->private_data, struct map_context);
403
404 /* Prepare the local operation */
405 ac->local_req = talloc(ac, struct ldb_request);
406 if (ac->local_req == NULL) {
407 goto oom;
408 }
409
410 *(ac->local_req) = *req; /* copy the request */
411
412 ac->local_req->context = NULL;
413 ac->local_req->callback = NULL;
414
415 /* Prepare the remote operation */
416 ac->remote_req = talloc(ac, struct ldb_request);
417 if (ac->remote_req == NULL) {
418 goto oom;
419 }
420
421 *(ac->remote_req) = *req; /* copy the request */
422
423 ac->remote_req->context = NULL;
424 ac->remote_req->callback = NULL;
425
426 /* Prepare the local message */
427 local = ldb_msg_new(ac->local_req);
428 if (local == NULL) {
429 goto oom;
430 }
431 local->dn = msg->dn;
432
433 /* Prepare the remote message */
434 remote = ldb_msg_new(ac->remote_req);
435 if (remote == NULL) {
436 goto oom;
437 }
438 remote->dn = ldb_dn_map_local(ac->module, remote, msg->dn);
439
440 /* Split local from remote message */
441 ldb_msg_partition(module, local, remote, msg);
442 ac->local_req->op.mod.message = local;
443 ac->remote_req->op.mod.message = remote;
444
445 if ((local->num_elements == 0) || (!map_check_local_db(ac->module))) {
446 /* No local data or db, just run the remote request */
447 talloc_free(ac->local_req);
448 req->handle = h; /* return our own handle to deal with this call */
449 return map_modify_do_remote(h);
450 }
451
452 /* prepare the search operation */
453 ac->search_req = map_search_self_req(ac, msg->dn);
454 if (ac->search_req == NULL) {
455 goto failed;
456 }
457
458 ac->step = MAP_SEARCH_SELF_MODIFY;
459
460 req->handle = h; /* return our own handle to deal with this call */
461 return ldb_next_request(module, ac->search_req);
462
463 oom:
464 map_oom(module);
465 failed:
466 talloc_free(h);
467 return LDB_ERR_OPERATIONS_ERROR;
468 }
469
470 /* Delete the remote record. */
471 int map_delete_do_remote(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
472 {
473 struct map_context *ac;
474
475 ac = talloc_get_type(handle->private_data, struct map_context);
476
477 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->remote_req);
478
479 ac->step = MAP_DELETE_REMOTE;
480
481 handle->state = LDB_ASYNC_INIT;
482 handle->status = LDB_SUCCESS;
483
484 return ldb_next_remote_request(ac->module, ac->remote_req);
485 }
486
487 /* Delete the local record. */
488 int map_delete_do_local(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
489 {
490 struct map_context *ac;
491
492 ac = talloc_get_type(handle->private_data, struct map_context);
493
494 /* No local record, continue remotely */
495 if (ac->local_dn == NULL) {
496 return map_delete_do_remote(handle);
497 }
498
499 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->local_req);
500
501 ac->step = MAP_DELETE_LOCAL;
502
503 handle->state = LDB_ASYNC_INIT;
504 handle->status = LDB_SUCCESS;
505
506 return ldb_next_request(ac->module, ac->local_req);
507 }
508
509 /* Delete a record. */
510 int map_delete(struct ldb_module *module, struct ldb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
511 {
512 struct ldb_handle *h;
513 struct map_context *ac;
514
515 /* Do not manipulate our control entries */
516 if (ldb_dn_is_special(req->op.del.dn)) {
517 return ldb_next_request(module, req);
518 }
519
520 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
521 if (!ldb_dn_check_local(module, req->op.del.dn)) {
522 return ldb_next_request(module, req);
523 }
524
525 /* Prepare context and handle */
526 h = map_init_handle(req, module);
527 if (h == NULL) {
528 return LDB_ERR_OPERATIONS_ERROR;
529 }
530 ac = talloc_get_type(h->private_data, struct map_context);
531
532 /* Prepare the local operation */
533 ac->local_req = talloc(ac, struct ldb_request);
534 if (ac->local_req == NULL) {
535 goto oom;
536 }
537
538 *(ac->local_req) = *req; /* copy the request */
539 ac->local_req->op.del.dn = req->op.del.dn;
540
541 ac->local_req->context = NULL;
542 ac->local_req->callback = NULL;
543
544 /* Prepare the remote operation */
545 ac->remote_req = talloc(ac, struct ldb_request);
546 if (ac->remote_req == NULL) {
547 goto oom;
548 }
549
550 *(ac->remote_req) = *req; /* copy the request */
551 ac->remote_req->op.del.dn = ldb_dn_map_local(module, ac->remote_req, req->op.del.dn);
552
553 /* No local db, just run the remote request */
554 if (!map_check_local_db(ac->module)) {
555 req->handle = h; /* return our own handle to deal with this call */
556 return map_delete_do_remote(h);
557 }
558
559 ac->remote_req->context = NULL;
560 ac->remote_req->callback = NULL;
561
562 /* Prepare the search operation */
563 ac->search_req = map_search_self_req(ac, req->op.del.dn);
564 if (ac->search_req == NULL) {
565 goto failed;
566 }
567
568 req->handle = h; /* return our own handle to deal with this call */
569
570 ac->step = MAP_SEARCH_SELF_DELETE;
571
572 return ldb_next_request(module, ac->search_req);
573
574 oom:
575 map_oom(module);
576 failed:
577 talloc_free(h);
578 return LDB_ERR_OPERATIONS_ERROR;
579 }
580
581 /* Rename the remote record. */
582 int map_rename_do_remote(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
583 {
584 struct map_context *ac;
585
586 ac = talloc_get_type(handle->private_data, struct map_context);
587
588 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->remote_req);
589
590 ac->step = MAP_RENAME_REMOTE;
591
592 handle->state = LDB_ASYNC_INIT;
593 handle->status = LDB_SUCCESS;
594
595 return ldb_next_remote_request(ac->module, ac->remote_req);
596 }
597
598 /* Update the local 'IS_MAPPED' attribute. */
599 int map_rename_do_fixup(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
600 {
601 struct map_context *ac;
602
603 ac = talloc_get_type(handle->private_data, struct map_context);
604
605 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->down_req);
606
607 ac->step = MAP_RENAME_FIXUP;
608
609 handle->state = LDB_ASYNC_INIT;
610 handle->status = LDB_SUCCESS;
611
612 return ldb_next_request(ac->module, ac->down_req);
613 }
614
615 /* Rename the local record. */
616 int map_rename_do_local(struct ldb_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
617 {
618 struct map_context *ac;
619
620 ac = talloc_get_type(handle->private_data, struct map_context);
621
622 /* No local record, continue remotely */
623 if (ac->local_dn == NULL) {
624 return map_rename_do_remote(handle);
625 }
626
627 ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->local_req);
628
629 ac->step = MAP_RENAME_LOCAL;
630
631 handle->state = LDB_ASYNC_INIT;
632 handle->status = LDB_SUCCESS;
633
634 return ldb_next_request(ac->module, ac->local_req);
635 }
636
637 /* Rename a record. */
638 int map_rename(struct ldb_module *module, struct ldb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
639 {
640 struct ldb_handle *h;
641 struct map_context *ac;
642
643 /* Do not manipulate our control entries */
644 if (ldb_dn_is_special(req->op.rename.olddn)) {
645 return ldb_next_request(module, req);
646 }
647
648 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
649 if ((!ldb_dn_check_local(module, req->op.rename.olddn)) &&
650 (!ldb_dn_check_local(module, req->op.rename.newdn))) {
651 return ldb_next_request(module, req);
652 }
653
654 /* Rename into/out of the mapped partition requested, bail out */
655 if (!ldb_dn_check_local(module, req->op.rename.olddn) ||
656 !ldb_dn_check_local(module, req->op.rename.newdn)) {
657 return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
658 }
659
660 /* Prepare context and handle */
661 h = map_init_handle(req, module);
662 if (h == NULL) {
663 return LDB_ERR_OPERATIONS_ERROR;
664 }
665 ac = talloc_get_type(h->private_data, struct map_context);
666
667 /* Prepare the local operation */
668 ac->local_req = talloc(ac, struct ldb_request);
669 if (ac->local_req == NULL) {
670 goto oom;
671 }
672
673 *(ac->local_req) = *req; /* copy the request */
674 ac->local_req->op.rename.olddn = req->op.rename.olddn;
675 ac->local_req->op.rename.newdn = req->op.rename.newdn;
676
677 ac->local_req->context = NULL;
678 ac->local_req->callback = NULL;
679
680 /* Prepare the remote operation */
681 ac->remote_req = talloc(ac, struct ldb_request);
682 if (ac->remote_req == NULL) {
683 goto oom;
684 }
685
686 *(ac->remote_req) = *req; /* copy the request */
687 ac->remote_req->op.rename.olddn = ldb_dn_map_local(module, ac->remote_req, req->op.rename.olddn);
688 ac->remote_req->op.rename.newdn = ldb_dn_map_local(module, ac->remote_req, req->op.rename.newdn);
689
690 ac->remote_req->context = NULL;
691 ac->remote_req->callback = NULL;
692
693 /* No local db, just run the remote request */
694 if (!map_check_local_db(ac->module)) {
695 req->handle = h; /* return our own handle to deal with this call */
696 return map_rename_do_remote(h);
697 }
698
699 /* Prepare the fixup operation */
700 /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
701 ac->down_req = map_build_fixup_req(ac, req->op.rename.newdn, ac->remote_req->op.rename.newdn);
702 if (ac->down_req == NULL) {
703 goto failed;
704 }
705
706 /* Prepare the search operation */
707 ac->search_req = map_search_self_req(ac, req->op.rename.olddn);
708 if (ac->search_req == NULL) {
709 goto failed;
710 }
711
712 req->handle = h; /* return our own handle to deal with this call */
713
714 ac->step = MAP_SEARCH_SELF_RENAME;
715
716 return ldb_next_request(module, ac->search_req);
717
718 oom:
719 map_oom(module);
720 failed:
721 talloc_free(h);
722 return LDB_ERR_OPERATIONS_ERROR;
723 }