root/source3/lib/ldb/modules/ldb_map_inbound.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ldb_msg_el_map_local
  2. ldb_msg_el_partition
  3. ldb_msg_check_remote
  4. ldb_msg_partition
  5. map_add_do_remote
  6. map_add_do_local
  7. map_add
  8. map_modify_do_remote
  9. map_modify_do_local
  10. map_modify
  11. map_delete_do_remote
  12. map_delete_do_local
  13. map_delete
  14. map_rename_do_remote
  15. map_rename_do_fixup
  16. map_rename_do_local
  17. 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 }

/* [<][>][^][v][top][bottom][index][help] */