4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * Component: ldb partitions module
26 * Description: Implement LDAP partitions
28 * Author: Andrew Bartlett
29 * Author: Stefan Metzmacher
32 #include "dsdb/samdb/ldb_modules/partition.h"
35 struct ldb_module *module;
36 struct ldb_request *req;
39 struct partition_context {
40 struct ldb_module *module;
41 struct ldb_request *req;
43 struct part_request *part_req;
44 unsigned int num_requests;
45 unsigned int finished_requests;
47 const char **referrals;
50 static struct partition_context *partition_init_ctx(struct ldb_module *module, struct ldb_request *req)
52 struct partition_context *ac;
54 ac = talloc_zero(req, struct partition_context);
56 ldb_set_errstring(ldb_module_get_ctx(module), "Out of Memory");
67 * helper functions to call the next module in chain
69 int partition_request(struct ldb_module *module, struct ldb_request *request)
71 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { \
72 const struct dsdb_control_current_partition *partition = NULL;
73 struct ldb_control *partition_ctrl = ldb_request_get_control(request, DSDB_CONTROL_CURRENT_PARTITION_OID);
75 partition = talloc_get_type(partition_ctrl->data,
76 struct dsdb_control_current_partition);
79 if (partition != NULL) {
80 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_request() -> %s",
81 ldb_dn_get_linearized(partition->dn));
83 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_request() -> (metadata partition)");
87 return ldb_next_request(module, request);
90 static struct dsdb_partition *find_partition(struct partition_private_data *data,
92 struct ldb_request *req)
95 struct ldb_control *partition_ctrl;
97 /* see if the request has the partition DN specified in a
98 * control. The repl_meta_data module can specify this to
99 * ensure that replication happens to the right partition
101 partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
102 if (partition_ctrl) {
103 const struct dsdb_control_current_partition *partition;
104 partition = talloc_get_type(partition_ctrl->data,
105 struct dsdb_control_current_partition);
106 if (partition != NULL) {
115 /* Look at base DN */
116 /* Figure out which partition it is under */
117 /* Skip the lot if 'data' isn't here yet (initialisation) */
118 for (i=0; data && data->partitions && data->partitions[i]; i++) {
119 if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn, dn) == 0) {
120 return data->partitions[i];
128 * fire the caller's callback for every entry, but only send 'done' once.
130 static int partition_req_callback(struct ldb_request *req,
131 struct ldb_reply *ares)
133 struct partition_context *ac;
134 struct ldb_module *module;
135 struct ldb_request *nreq;
137 struct ldb_control *partition_ctrl;
139 ac = talloc_get_type(req->context, struct partition_context);
142 return ldb_module_done(ac->req, NULL, NULL,
143 LDB_ERR_OPERATIONS_ERROR);
146 partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
147 if (partition_ctrl && (ac->num_requests == 1 || ares->type == LDB_REPLY_ENTRY)) {
148 /* If we didn't fan this request out to mulitple partitions,
149 * or this is an individual search result, we can
150 * deterministically tell the caller what partition this was
151 * written to (repl_meta_data likes to know) */
152 ret = ldb_reply_add_control(ares,
153 DSDB_CONTROL_CURRENT_PARTITION_OID,
154 false, partition_ctrl->data);
155 if (ret != LDB_SUCCESS) {
156 return ldb_module_done(ac->req, NULL, NULL,
161 if (ares->error != LDB_SUCCESS) {
162 return ldb_module_done(ac->req, ares->controls,
163 ares->response, ares->error);
166 switch (ares->type) {
167 case LDB_REPLY_REFERRAL:
168 return ldb_module_send_referral(ac->req, ares->referral);
170 case LDB_REPLY_ENTRY:
171 if (ac->req->operation != LDB_SEARCH) {
172 ldb_set_errstring(ldb_module_get_ctx(ac->module),
173 "partition_req_callback:"
174 " Unsupported reply type for this request");
175 return ldb_module_done(ac->req, NULL, NULL,
176 LDB_ERR_OPERATIONS_ERROR);
179 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
182 if (ac->req->operation == LDB_EXTENDED) {
183 /* FIXME: check for ares->response, replmd does not fill it ! */
184 if (ares->response) {
185 if (strcmp(ares->response->oid, LDB_EXTENDED_START_TLS_OID) != 0) {
186 ldb_set_errstring(ldb_module_get_ctx(ac->module),
187 "partition_req_callback:"
188 " Unknown extended reply, "
189 "only supports START_TLS");
191 return ldb_module_done(ac->req, NULL, NULL,
192 LDB_ERR_OPERATIONS_ERROR);
197 ac->finished_requests++;
198 if (ac->finished_requests == ac->num_requests) {
199 /* Send back referrals if they do exist (search ops) */
200 if (ac->referrals != NULL) {
202 for (ref = ac->referrals; *ref != NULL; ++ref) {
203 ret = ldb_module_send_referral(ac->req,
204 talloc_strdup(ac->req, *ref));
205 if (ret != LDB_SUCCESS) {
206 return ldb_module_done(ac->req, NULL, NULL,
212 /* this was the last one, call callback */
213 return ldb_module_done(ac->req, ares->controls,
218 /* not the last, now call the next one */
219 module = ac->part_req[ac->finished_requests].module;
220 nreq = ac->part_req[ac->finished_requests].req;
222 ret = partition_request(module, nreq);
223 if (ret != LDB_SUCCESS) {
225 return ldb_module_done(ac->req, NULL, NULL, ret);
235 static int partition_prep_request(struct partition_context *ac,
236 struct dsdb_partition *partition)
239 struct ldb_request *req;
240 struct ldb_control *partition_ctrl = NULL;
242 ac->part_req = talloc_realloc(ac, ac->part_req,
244 ac->num_requests + 1);
245 if (ac->part_req == NULL) {
246 return ldb_oom(ldb_module_get_ctx(ac->module));
249 switch (ac->req->operation) {
251 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(ac->module),
253 ac->req->op.search.base,
254 ac->req->op.search.scope,
255 ac->req->op.search.tree,
256 ac->req->op.search.attrs,
258 ac, partition_req_callback,
260 LDB_REQ_SET_LOCATION(req);
263 ret = ldb_build_add_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
264 ac->req->op.add.message,
266 ac, partition_req_callback,
268 LDB_REQ_SET_LOCATION(req);
271 ret = ldb_build_mod_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
272 ac->req->op.mod.message,
274 ac, partition_req_callback,
276 LDB_REQ_SET_LOCATION(req);
279 ret = ldb_build_del_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
282 ac, partition_req_callback,
284 LDB_REQ_SET_LOCATION(req);
287 ret = ldb_build_rename_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
288 ac->req->op.rename.olddn,
289 ac->req->op.rename.newdn,
291 ac, partition_req_callback,
293 LDB_REQ_SET_LOCATION(req);
296 ret = ldb_build_extended_req(&req, ldb_module_get_ctx(ac->module),
298 ac->req->op.extended.oid,
299 ac->req->op.extended.data,
301 ac, partition_req_callback,
303 LDB_REQ_SET_LOCATION(req);
306 ldb_set_errstring(ldb_module_get_ctx(ac->module),
307 "Unsupported request type!");
308 ret = LDB_ERR_UNWILLING_TO_PERFORM;
311 if (ret != LDB_SUCCESS) {
315 ac->part_req[ac->num_requests].req = req;
317 if (ac->req->controls) {
318 /* Duplicate everything beside the current partition control */
319 partition_ctrl = ldb_request_get_control(ac->req,
320 DSDB_CONTROL_CURRENT_PARTITION_OID);
321 if (!ldb_save_controls(partition_ctrl, req, NULL)) {
322 return ldb_module_oom(ac->module);
327 void *part_data = partition->ctrl;
329 ac->part_req[ac->num_requests].module = partition->module;
331 if (partition_ctrl != NULL) {
332 if (partition_ctrl->data != NULL) {
333 part_data = partition_ctrl->data;
337 * If the provided current partition control is without
338 * data then use the calculated one.
340 ret = ldb_request_add_control(req,
341 DSDB_CONTROL_CURRENT_PARTITION_OID,
343 if (ret != LDB_SUCCESS) {
348 if (req->operation == LDB_SEARCH) {
349 /* If the search is for 'more' than this partition,
350 * then change the basedn, so a remote LDAP server
352 if (ldb_dn_compare_base(partition->ctrl->dn,
353 req->op.search.base) != 0) {
354 req->op.search.base = partition->ctrl->dn;
359 /* make sure you put the module here, or
360 * or ldb_next_request() will skip a module */
361 ac->part_req[ac->num_requests].module = ac->module;
369 static int partition_call_first(struct partition_context *ac)
371 return partition_request(ac->part_req[0].module, ac->part_req[0].req);
375 * Send a request down to all the partitions (but not the sam.ldb file)
377 static int partition_send_all(struct ldb_module *module,
378 struct partition_context *ac,
379 struct ldb_request *req)
382 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
383 struct partition_private_data);
386 for (i=0; data && data->partitions && data->partitions[i]; i++) {
387 ret = partition_prep_request(ac, data->partitions[i]);
388 if (ret != LDB_SUCCESS) {
393 /* fire the first one */
394 return partition_call_first(ac);
397 struct partition_copy_context {
398 struct ldb_module *module;
399 struct partition_context *partition_context;
400 struct ldb_request *request;
405 * A special DN has been updated in the primary partition. Now propagate those
406 * changes to the remaining partitions.
408 * Note: that the operations are asynchronous and this function is called
409 * from partition_copy_all_callback_handler in response to an async
412 static int partition_copy_all_callback_action(
413 struct ldb_module *module,
414 struct partition_context *ac,
415 struct ldb_request *req,
421 struct partition_private_data *data =
423 ldb_module_get_private(module),
424 struct partition_private_data);
426 struct ldb_result *res;
427 /* now fetch the resulting object, and then copy it to all the
428 * other partitions. We need this approach to cope with the
429 * partitions getting out of sync. If for example the
430 * @ATTRIBUTES object exists on one partition but not the
431 * others then just doing each of the partitions in turn will
434 search_ret = dsdb_module_search_dn(module, ac, &res, dn, NULL, DSDB_FLAG_NEXT_MODULE, req);
435 if (search_ret != LDB_SUCCESS) {
439 /* now delete the object in the other partitions, if requried
441 if (search_ret == LDB_ERR_NO_SUCH_OBJECT) {
442 for (i=0; data->partitions && data->partitions[i]; i++) {
444 pret = dsdb_module_del(data->partitions[i]->module,
446 DSDB_FLAG_NEXT_MODULE,
448 if (pret != LDB_SUCCESS && pret != LDB_ERR_NO_SUCH_OBJECT) {
449 /* we should only get success or no
450 such object from the other partitions */
455 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
458 /* now add/modify in the other partitions */
459 for (i=0; data->partitions && data->partitions[i]; i++) {
460 struct ldb_message *modify_msg = NULL;
464 pret = dsdb_module_add(data->partitions[i]->module,
466 DSDB_FLAG_NEXT_MODULE,
468 if (pret == LDB_SUCCESS) {
472 if (pret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
476 modify_msg = ldb_msg_copy(req, res->msgs[0]);
477 if (modify_msg == NULL) {
478 return ldb_module_oom(module);
482 * mark all the message elements as
483 * LDB_FLAG_MOD_REPLACE
486 el_idx < modify_msg->num_elements;
488 modify_msg->elements[el_idx].flags
489 = LDB_FLAG_MOD_REPLACE;
492 if (req->operation == LDB_MODIFY) {
493 const struct ldb_message *req_msg = req->op.mod.message;
495 * mark elements to be removed, if there were
496 * deleted entirely above we need to delete
499 for (el_idx=0; el_idx < req_msg->num_elements; el_idx++) {
500 if (req_msg->elements[el_idx].flags & LDB_FLAG_MOD_DELETE
501 || ((req_msg->elements[el_idx].flags & LDB_FLAG_MOD_REPLACE) &&
502 req_msg->elements[el_idx].num_values == 0)) {
503 if (ldb_msg_find_element(modify_msg,
504 req_msg->elements[el_idx].name) != NULL) {
507 pret = ldb_msg_add_empty(
509 req_msg->elements[el_idx].name,
510 LDB_FLAG_MOD_REPLACE,
512 if (pret != LDB_SUCCESS) {
519 pret = dsdb_module_modify(data->partitions[i]->module,
521 DSDB_FLAG_NEXT_MODULE,
524 if (pret != LDB_SUCCESS) {
529 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
534 * @brief call back function for the ldb operations on special DN's.
536 * As the LDB operations are async, and we wish to use the result
537 * the operations, a callback needs to be registered to process the results
538 * of the LDB operations.
540 * @param req the ldb request
541 * @param res the result of the operation
543 * @return the LDB_STATUS
545 static int partition_copy_all_callback_handler(
546 struct ldb_request *req,
547 struct ldb_reply *ares)
549 struct partition_copy_context *ac = NULL;
551 ac = talloc_get_type(
553 struct partition_copy_context);
556 return ldb_module_done(
560 LDB_ERR_OPERATIONS_ERROR);
563 /* pass on to the callback */
564 switch (ares->type) {
565 case LDB_REPLY_ENTRY:
566 return ldb_module_send_entry(
571 case LDB_REPLY_REFERRAL:
572 return ldb_module_send_referral(
576 case LDB_REPLY_DONE: {
577 int error = ares->error;
578 if (error == LDB_SUCCESS) {
579 error = partition_copy_all_callback_action(
581 ac->partition_context,
585 return ldb_module_done(
594 return LDB_ERR_OPERATIONS_ERROR;
599 * send an operation to the top partition, then copy the resulting
600 * object to all other partitions.
602 static int partition_copy_all(
603 struct ldb_module *module,
604 struct partition_context *partition_context,
605 struct ldb_request *req,
608 struct ldb_request *new_req = NULL;
609 struct ldb_context *ldb = NULL;
610 struct partition_copy_context *context = NULL;
614 ldb = ldb_module_get_ctx(module);
616 context = talloc_zero(req, struct partition_copy_context);
617 if (context == NULL) {
620 context->module = module;
621 context->request = req;
623 context->partition_context = partition_context;
625 switch (req->operation) {
627 ret = ldb_build_add_req(
634 partition_copy_all_callback_handler,
638 ret = ldb_build_mod_req(
645 partition_copy_all_callback_handler,
649 ret = ldb_build_del_req(
656 partition_copy_all_callback_handler,
660 ret = ldb_build_rename_req(
664 req->op.rename.olddn,
665 req->op.rename.newdn,
668 partition_copy_all_callback_handler,
678 "Unexpected operation type (%d)\n", req->operation);
679 ret = LDB_ERR_OPERATIONS_ERROR;
682 if (ret != LDB_SUCCESS) {
685 return ldb_next_request(module, new_req);
688 * Figure out which backend a request needs to be aimed at. Some
689 * requests must be replicated to all backends
691 static int partition_replicate(struct ldb_module *module, struct ldb_request *req, struct ldb_dn *dn)
693 struct partition_context *ac;
696 struct dsdb_partition *partition;
697 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
698 struct partition_private_data);
700 /* if we aren't initialised yet go further */
701 if (!data || !data->partitions) {
702 return ldb_next_request(module, req);
705 if (ldb_dn_is_special(dn)) {
706 /* Is this a special DN, we need to replicate to every backend? */
707 for (i=0; data->replicate && data->replicate[i]; i++) {
708 if (ldb_dn_compare(data->replicate[i],
711 ac = partition_init_ctx(module, req);
713 return ldb_operr(ldb_module_get_ctx(module));
716 return partition_copy_all(module, ac, req, dn);
721 /* Otherwise, we need to find the partition to fire it to */
724 partition = find_partition(data, dn, req);
727 * if we haven't found a matching partition
728 * pass the request to the main ldb
730 * TODO: we should maybe return an error here
731 * if it's not a special dn
734 return ldb_next_request(module, req);
737 ac = partition_init_ctx(module, req);
739 return ldb_operr(ldb_module_get_ctx(module));
742 /* we need to add a control but we never touch the original request */
743 ret = partition_prep_request(ac, partition);
744 if (ret != LDB_SUCCESS) {
748 /* fire the first one */
749 return partition_call_first(ac);
753 static int partition_search(struct ldb_module *module, struct ldb_request *req)
755 struct ldb_control **saved_controls;
757 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
758 struct partition_private_data);
759 struct partition_context *ac;
760 struct ldb_context *ldb;
761 struct loadparm_context *lp_ctx;
763 struct ldb_control *search_control = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID);
764 struct ldb_control *domain_scope_control = ldb_request_get_control(req, LDB_CONTROL_DOMAIN_SCOPE_OID);
765 struct ldb_control *no_gc_control = ldb_request_get_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG);
767 struct ldb_search_options_control *search_options = NULL;
768 struct dsdb_partition *p;
771 bool domain_scope = false, phantom_root = false;
773 p = find_partition(data, NULL, req);
775 /* the caller specified what partition they want the
776 * search - just pass it on
778 return ldb_next_request(p->module, req);
781 /* Get back the search options from the search control, and mark it as
782 * non-critical (to make backends and also dcpromo happy).
784 if (search_control) {
785 search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
786 search_control->critical = 0;
790 /* Remove the "domain_scope" control, so we don't confuse a backend
792 if (domain_scope_control && !ldb_save_controls(domain_scope_control, req, &saved_controls)) {
793 return ldb_oom(ldb_module_get_ctx(module));
796 /* if we aren't initialised yet go further */
797 if (!data || !data->partitions) {
798 return ldb_next_request(module, req);
801 /* Special DNs without specified partition should go further */
802 if (ldb_dn_is_special(req->op.search.base)) {
803 return ldb_next_request(module, req);
806 /* Locate the options */
807 domain_scope = (search_options
808 && (search_options->search_options & LDB_SEARCH_OPTION_DOMAIN_SCOPE))
809 || domain_scope_control;
810 phantom_root = search_options
811 && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT);
813 /* Remove handled options from the search control flag */
814 if (search_options) {
815 search_options->search_options = search_options->search_options
816 & ~LDB_SEARCH_OPTION_DOMAIN_SCOPE
817 & ~LDB_SEARCH_OPTION_PHANTOM_ROOT;
820 ac = partition_init_ctx(module, req);
822 return ldb_operr(ldb_module_get_ctx(module));
825 ldb = ldb_module_get_ctx(ac->module);
826 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
827 struct loadparm_context);
829 /* Search from the base DN */
830 if (ldb_dn_is_null(req->op.search.base)) {
832 return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, "empty base DN");
834 return partition_send_all(module, ac, req);
837 for (i=0; data->partitions[i]; i++) {
838 bool match = false, stop = false;
840 if (data->partitions[i]->partial_replica && no_gc_control != NULL) {
841 if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn,
842 req->op.search.base) == 0) {
843 /* base DN is in a partial replica
844 with the NO_GLOBAL_CATALOG
845 control. This partition is invisible */
846 /* DEBUG(0,("DENYING NON-GC OP: %s\n", ldb_module_call_chain(req, req))); */
852 /* Phantom root: Find all partitions under the
853 * search base. We match if:
855 * 1) the DN we are looking for exactly matches a
856 * certain partition and always stop
857 * 2) the DN we are looking for is a parent of certain
858 * partitions and it isn't a scope base search
859 * 3) the DN we are looking for is a child of a certain
860 * partition and always stop
861 * - we don't need to go any further up in the
864 if (ldb_dn_compare(data->partitions[i]->ctrl->dn,
865 req->op.search.base) == 0) {
870 (ldb_dn_compare_base(req->op.search.base,
871 data->partitions[i]->ctrl->dn) == 0 &&
872 req->op.search.scope != LDB_SCOPE_BASE)) {
876 ldb_dn_compare_base(data->partitions[i]->ctrl->dn,
877 req->op.search.base) == 0) {
879 stop = true; /* note that this relies on partition ordering */
882 /* Domain scope: Find all partitions under the search
885 * We generate referral candidates if we haven't
886 * specified the domain scope control, haven't a base
887 * search* scope and the DN we are looking for is a real
888 * predecessor of certain partitions. When a new
889 * referral candidate is nearer to the DN than an
890 * existing one delete the latter (we want to have only
891 * the closest ones). When we checked this for all
892 * candidates we have the final referrals.
894 * We match if the DN we are looking for is a child of
895 * a certain partition or the partition
896 * DN itself - we don't need to go any further
897 * up in the hierarchy!
899 if ((!domain_scope) &&
900 (req->op.search.scope != LDB_SCOPE_BASE) &&
901 (ldb_dn_compare_base(req->op.search.base,
902 data->partitions[i]->ctrl->dn) == 0) &&
903 (ldb_dn_compare(req->op.search.base,
904 data->partitions[i]->ctrl->dn) != 0)) {
905 char *ref = talloc_asprintf(ac,
907 lpcfg_dnsdomain(lp_ctx),
908 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn),
909 req->op.search.scope == LDB_SCOPE_ONELEVEL ? "??base" : "");
915 /* Initialise the referrals list */
916 if (ac->referrals == NULL) {
917 char **l = str_list_make_empty(ac);
918 ac->referrals = discard_const_p(const char *, l);
919 if (ac->referrals == NULL) {
924 /* Check if the new referral candidate is
925 * closer to the base DN than already
926 * saved ones and delete the latters */
928 while (ac->referrals[j] != NULL) {
929 if (strstr(ac->referrals[j],
930 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn)) != NULL) {
931 str_list_remove(ac->referrals,
938 /* Add our new candidate */
939 ac->referrals = str_list_add(ac->referrals, ref);
943 if (ac->referrals == NULL) {
947 if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) {
949 stop = true; /* note that this relies on partition ordering */
954 ret = partition_prep_request(ac, data->partitions[i]);
955 if (ret != LDB_SUCCESS) {
963 /* Perhaps we didn't match any partitions. Try the main partition */
964 if (ac->num_requests == 0) {
966 return ldb_next_request(module, req);
969 /* fire the first one */
970 return partition_call_first(ac);
974 static int partition_add(struct ldb_module *module, struct ldb_request *req)
976 return partition_replicate(module, req, req->op.add.message->dn);
980 static int partition_modify(struct ldb_module *module, struct ldb_request *req)
982 return partition_replicate(module, req, req->op.mod.message->dn);
986 static int partition_delete(struct ldb_module *module, struct ldb_request *req)
988 return partition_replicate(module, req, req->op.del.dn);
992 static int partition_rename(struct ldb_module *module, struct ldb_request *req)
995 struct dsdb_partition *backend, *backend2;
997 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
998 struct partition_private_data);
1000 /* Skip the lot if 'data' isn't here yet (initialisation) */
1002 return ldb_operr(ldb_module_get_ctx(module));
1005 backend = find_partition(data, req->op.rename.olddn, req);
1006 backend2 = find_partition(data, req->op.rename.newdn, req);
1008 if ((backend && !backend2) || (!backend && backend2)) {
1009 return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
1012 if (backend != backend2) {
1013 ldb_asprintf_errstring(ldb_module_get_ctx(module),
1014 "Cannot rename from %s in %s to %s in %s: %s",
1015 ldb_dn_get_linearized(req->op.rename.olddn),
1016 ldb_dn_get_linearized(backend->ctrl->dn),
1017 ldb_dn_get_linearized(req->op.rename.newdn),
1018 ldb_dn_get_linearized(backend2->ctrl->dn),
1019 ldb_strerror(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
1020 return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
1023 return partition_replicate(module, req, req->op.rename.olddn);
1026 /* start a transaction */
1027 int partition_start_trans(struct ldb_module *module)
1031 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1032 struct partition_private_data);
1033 /* Look at base DN */
1034 /* Figure out which partition it is under */
1035 /* Skip the lot if 'data' isn't here yet (initialization) */
1036 if (ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING) {
1037 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> (metadata partition)");
1040 /* This order must match that in prepare_commit() and read_lock() */
1041 ret = ldb_next_start_trans(module);
1042 if (ret != LDB_SUCCESS) {
1046 ret = partition_reload_if_required(module, data, NULL);
1047 if (ret != LDB_SUCCESS) {
1048 ldb_next_del_trans(module);
1052 for (i=0; data && data->partitions && data->partitions[i]; i++) {
1053 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1054 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> %s",
1055 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn));
1057 ret = ldb_next_start_trans(data->partitions[i]->module);
1058 if (ret != LDB_SUCCESS) {
1059 /* Back it out, if it fails on one */
1060 for (i--; i >= 0; i--) {
1061 ldb_next_del_trans(data->partitions[i]->module);
1063 ldb_next_del_trans(module);
1064 partition_metadata_del_trans(module);
1070 * Because in prepare_commit this must come last, to ensure
1071 * lock ordering we have to do this last here also
1073 ret = partition_metadata_start_trans(module);
1074 if (ret != LDB_SUCCESS) {
1075 /* Back it out, if it fails on one */
1076 for (i--; i >= 0; i--) {
1077 ldb_next_del_trans(data->partitions[i]->module);
1079 ldb_next_del_trans(module);
1083 data->in_transaction++;
1088 /* prepare for a commit */
1089 int partition_prepare_commit(struct ldb_module *module)
1092 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1093 struct partition_private_data);
1096 ret = ldb_next_prepare_commit(module);
1097 if (ret != LDB_SUCCESS) {
1101 for (i=0; data && data->partitions && data->partitions[i]; i++) {
1102 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1103 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> %s",
1104 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn));
1106 ret = ldb_next_prepare_commit(data->partitions[i]->module);
1107 if (ret != LDB_SUCCESS) {
1108 ldb_asprintf_errstring(ldb_module_get_ctx(module), "prepare_commit error on %s: %s",
1109 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn),
1110 ldb_errstring(ldb_module_get_ctx(module)));
1115 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1116 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> (metadata partition)");
1119 /* metadata prepare commit must come last, as other partitions could modify
1120 * the database inside the prepare commit method of a module */
1121 return partition_metadata_prepare_commit(module);
1125 /* end a transaction */
1126 int partition_end_trans(struct ldb_module *module)
1130 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1131 struct partition_private_data);
1135 if (data->in_transaction == 0) {
1136 DEBUG(0,("partition end transaction mismatch\n"));
1137 ret = LDB_ERR_OPERATIONS_ERROR;
1139 data->in_transaction--;
1143 for (i=0; data && data->partitions && data->partitions[i]; i++) {
1144 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1145 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_end_trans() -> %s",
1146 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn));
1148 ret2 = ldb_next_end_trans(data->partitions[i]->module);
1149 if (ret2 != LDB_SUCCESS) {
1150 ldb_asprintf_errstring(ldb_module_get_ctx(module), "end_trans error on %s: %s",
1151 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn),
1152 ldb_errstring(ldb_module_get_ctx(module)));
1157 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1158 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_end_trans() -> (metadata partition)");
1160 ret2 = ldb_next_end_trans(module);
1161 if (ret2 != LDB_SUCCESS) {
1165 ret2 = partition_metadata_end_trans(module);
1166 if (ret2 != LDB_SUCCESS) {
1173 /* delete a transaction */
1174 int partition_del_trans(struct ldb_module *module)
1176 int ret, final_ret = LDB_SUCCESS;
1178 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1179 struct partition_private_data);
1181 for (i=0; data && data->partitions && data->partitions[i]; i++) {
1182 if (ldb_module_flags(ldb_module_get_ctx(module)) &
1183 LDB_FLG_ENABLE_TRACING) {
1184 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_del_trans() -> %s",
1185 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn));
1187 ret = ldb_next_del_trans(data->partitions[i]->module);
1188 if (ret != LDB_SUCCESS) {
1189 ldb_asprintf_errstring(ldb_module_get_ctx(module), "del_trans error on %s: %s",
1190 ldb_dn_get_linearized(data->partitions[i]->ctrl->dn),
1191 ldb_errstring(ldb_module_get_ctx(module)));
1196 if (data->in_transaction == 0) {
1197 DEBUG(0,("partition del transaction mismatch\n"));
1198 return ldb_operr(ldb_module_get_ctx(module));
1200 data->in_transaction--;
1202 if (ldb_module_flags(ldb_module_get_ctx(module)) &
1203 LDB_FLG_ENABLE_TRACING) {
1204 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_del_trans() -> (metadata partition)");
1206 ret = ldb_next_del_trans(module);
1207 if (ret != LDB_SUCCESS) {
1211 ret = partition_metadata_del_trans(module);
1212 if (ret != LDB_SUCCESS) {
1219 int partition_primary_sequence_number(struct ldb_module *module, TALLOC_CTX *mem_ctx,
1220 uint64_t *seq_number,
1221 struct ldb_request *parent)
1224 struct ldb_result *res;
1225 struct ldb_seqnum_request *tseq;
1226 struct ldb_seqnum_result *seqr;
1228 tseq = talloc_zero(mem_ctx, struct ldb_seqnum_request);
1230 return ldb_oom(ldb_module_get_ctx(module));
1232 tseq->type = LDB_SEQ_HIGHEST_SEQ;
1234 ret = dsdb_module_extended(module, tseq, &res,
1235 LDB_EXTENDED_SEQUENCE_NUMBER,
1237 DSDB_FLAG_NEXT_MODULE,
1239 if (ret != LDB_SUCCESS) {
1244 seqr = talloc_get_type_abort(res->extended->data,
1245 struct ldb_seqnum_result);
1246 if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
1248 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
1249 "Primary backend in partition module returned a timestamp based seq");
1252 *seq_number = seqr->seq_num;
1259 * Older version of sequence number as sum of sequence numbers for each partition
1261 int partition_sequence_number_from_partitions(struct ldb_module *module,
1266 uint64_t seq_number = 0;
1267 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1268 struct partition_private_data);
1270 ret = partition_primary_sequence_number(module, data, &seq_number, NULL);
1271 if (ret != LDB_SUCCESS) {
1275 /* Skip the lot if 'data' isn't here yet (initialisation) */
1276 for (i=0; data && data->partitions && data->partitions[i]; i++) {
1277 struct ldb_seqnum_request *tseq;
1278 struct ldb_seqnum_result *tseqr;
1279 struct ldb_request *treq;
1280 struct ldb_result *res = talloc_zero(data, struct ldb_result);
1282 return ldb_oom(ldb_module_get_ctx(module));
1284 tseq = talloc_zero(res, struct ldb_seqnum_request);
1287 return ldb_oom(ldb_module_get_ctx(module));
1289 tseq->type = LDB_SEQ_HIGHEST_SEQ;
1291 ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res,
1292 LDB_EXTENDED_SEQUENCE_NUMBER,
1296 ldb_extended_default_callback,
1298 LDB_REQ_SET_LOCATION(treq);
1299 if (ret != LDB_SUCCESS) {
1304 ret = partition_request(data->partitions[i]->module, treq);
1305 if (ret != LDB_SUCCESS) {
1309 ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
1310 if (ret != LDB_SUCCESS) {
1314 tseqr = talloc_get_type(res->extended->data,
1315 struct ldb_seqnum_result);
1316 seq_number += tseqr->seq_num;
1326 * Newer version of sequence number using metadata tdb
1328 static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
1330 struct ldb_extended *ext;
1331 struct ldb_seqnum_request *seq;
1332 struct ldb_seqnum_result *seqr;
1333 uint64_t seq_number;
1336 seq = talloc_get_type_abort(req->op.extended.data, struct ldb_seqnum_request);
1337 switch (seq->type) {
1339 ret = partition_metadata_sequence_number_increment(module, &seq_number);
1340 if (ret != LDB_SUCCESS) {
1345 case LDB_SEQ_HIGHEST_SEQ:
1346 ret = partition_metadata_sequence_number(module, &seq_number);
1347 if (ret != LDB_SUCCESS) {
1352 case LDB_SEQ_HIGHEST_TIMESTAMP:
1353 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
1354 "LDB_SEQ_HIGHEST_TIMESTAMP not supported");
1357 ext = talloc_zero(req, struct ldb_extended);
1359 return ldb_module_oom(module);
1361 seqr = talloc_zero(ext, struct ldb_seqnum_result);
1364 return ldb_module_oom(module);
1366 ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
1369 seqr->seq_num = seq_number;
1370 seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
1372 /* send request done */
1373 return ldb_module_done(req, NULL, ext, LDB_SUCCESS);
1376 /* lock all the backends */
1377 int partition_read_lock(struct ldb_module *module)
1382 struct ldb_context *ldb = ldb_module_get_ctx(module);
1383 struct partition_private_data *data = \
1384 talloc_get_type(ldb_module_get_private(module),
1385 struct partition_private_data);
1387 if (ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING) {
1388 ldb_debug(ldb, LDB_DEBUG_TRACE,
1389 "partition_read_lock() -> (metadata partition)");
1393 * It is important to only do this for LOCK because:
1394 * - we don't want to unlock what we did not lock
1396 * - we don't want to make a new lock on the sam.ldb
1397 * (triggered inside this routine due to the seq num check)
1398 * during an unlock phase as that will violate the lock
1403 TALLOC_CTX *mem_ctx = talloc_new(module);
1405 data = talloc_zero(mem_ctx, struct partition_private_data);
1407 talloc_free(mem_ctx);
1408 return ldb_operr(ldb);
1412 * When used from Samba4, this message is set by the
1413 * samba4 module, as a fixed value not read from the
1414 * DB. This avoids listing modules in the DB
1416 data->forced_module_msg = talloc_get_type(
1418 DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME),
1419 struct ldb_message);
1421 ldb_module_set_private(module, talloc_steal(module,
1423 talloc_free(mem_ctx);
1427 * This will lock the metadata partition (sam.ldb) and
1428 * will also call event loops, so we do it before we
1429 * get the whole db lock.
1431 ret = partition_reload_if_required(module, data, NULL);
1432 if (ret != LDB_SUCCESS) {
1437 * This order must match that in prepare_commit(), start with
1438 * the metadata partition (sam.ldb) lock
1440 ret = ldb_next_read_lock(module);
1441 if (ret != LDB_SUCCESS) {
1444 "Failed to lock db: %s / %s for metadata partition",
1452 * The metadata partition (sam.ldb) lock is not
1453 * enough to block another process in prepare_commit(),
1454 * because prepare_commit() is a no-op, if nothing
1455 * was changed in the specific backend.
1457 * That means the following per partition locks are required.
1459 for (i=0; data && data->partitions && data->partitions[i]; i++) {
1460 if ((module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING)) {
1461 ldb_debug(ldb, LDB_DEBUG_TRACE,
1462 "partition_read_lock() -> %s",
1463 ldb_dn_get_linearized(
1464 data->partitions[i]->ctrl->dn));
1466 ret = ldb_next_read_lock(data->partitions[i]->module);
1467 if (ret == LDB_SUCCESS) {
1473 "Failed to lock db: %s / %s for %s",
1476 ldb_dn_get_linearized(
1477 data->partitions[i]->ctrl->dn));
1479 /* Back it out, if it fails on one */
1480 for (i--; i >= 0; i--) {
1481 ret2 = ldb_next_read_unlock(data->partitions[i]->module);
1482 if (ret2 != LDB_SUCCESS) {
1485 "Failed to unlock db: %s / %s",
1487 ldb_strerror(ret2));
1490 ret2 = ldb_next_read_unlock(module);
1491 if (ret2 != LDB_SUCCESS) {
1494 "Failed to unlock db: %s / %s",
1496 ldb_strerror(ret2));
1504 /* unlock all the backends */
1505 int partition_read_unlock(struct ldb_module *module)
1508 int ret = LDB_SUCCESS;
1510 struct ldb_context *ldb = ldb_module_get_ctx(module);
1511 struct partition_private_data *data = \
1512 talloc_get_type(ldb_module_get_private(module),
1513 struct partition_private_data);
1516 * This order must be similar to partition_{end,del}_trans()
1517 * the metadata partition (sam.ldb) unlock must be at the end.
1520 for (i=0; data && data->partitions && data->partitions[i]; i++) {
1521 if ((module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING)) {
1522 ldb_debug(ldb, LDB_DEBUG_TRACE,
1523 "partition_read_unlock() -> %s",
1524 ldb_dn_get_linearized(
1525 data->partitions[i]->ctrl->dn));
1527 ret2 = ldb_next_read_unlock(data->partitions[i]->module);
1528 if (ret2 != LDB_SUCCESS) {
1531 "Failed to lock db: %s / %s for %s",
1534 ldb_dn_get_linearized(
1535 data->partitions[i]->ctrl->dn));
1538 * Don't overwrite the original failure code
1541 if (ret == LDB_SUCCESS) {
1547 if (ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING) {
1548 ldb_debug(ldb, LDB_DEBUG_TRACE,
1549 "partition_read_unlock() -> (metadata partition)");
1552 ret2 = ldb_next_read_unlock(module);
1553 if (ret2 != LDB_SUCCESS) {
1556 "Failed to unlock db: %s / %s for metadata partition",
1558 ldb_strerror(ret2));
1561 * Don't overwrite the original failure code
1564 if (ret == LDB_SUCCESS) {
1573 static int partition_extended(struct ldb_module *module, struct ldb_request *req)
1575 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1576 struct partition_private_data);
1577 struct partition_context *ac;
1580 /* if we aren't initialised yet go further */
1582 return ldb_next_request(module, req);
1585 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) {
1586 /* Update the metadata.tdb to increment the schema version if needed*/
1587 DEBUG(10, ("Incrementing the sequence_number after schema_update_now\n"));
1588 ret = partition_metadata_inc_schema_sequence(module);
1589 return ldb_module_done(req, NULL, NULL, ret);
1592 if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
1593 return partition_sequence_number(module, req);
1596 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_CREATE_PARTITION_OID) == 0) {
1597 return partition_create(module, req);
1601 * as the extended operation has no dn
1602 * we need to send it to all partitions
1605 ac = partition_init_ctx(module, req);
1607 return ldb_operr(ldb_module_get_ctx(module));
1610 return partition_send_all(module, ac, req);
1613 static const struct ldb_module_ops ldb_partition_module_ops = {
1614 .name = "partition",
1615 .init_context = partition_init,
1616 .search = partition_search,
1617 .add = partition_add,
1618 .modify = partition_modify,
1619 .del = partition_delete,
1620 .rename = partition_rename,
1621 .extended = partition_extended,
1622 .start_transaction = partition_start_trans,
1623 .prepare_commit = partition_prepare_commit,
1624 .end_transaction = partition_end_trans,
1625 .del_transaction = partition_del_trans,
1626 .read_lock = partition_read_lock,
1627 .read_unlock = partition_read_unlock
1630 int ldb_partition_module_init(const char *version)
1632 LDB_MODULE_CHECK_VERSION(version);
1633 return ldb_register_module(&ldb_partition_module_ops);