summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules/partition.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules/partition.c')
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
new file mode 100644
index 0000000000..6d3d42c23a
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -0,0 +1,297 @@
+/*
+ Partitions ldb module
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
+
+ * NOTICE: this module is NOT released under the GNU LGPL license as
+ * other ldb code. This module is release under the GNU GPL v2 or
+ * later license.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldb partitions module
+ *
+ * Description: Implement LDAP partitions
+ *
+ * Author: Andrew Bartlett
+ */
+
+#include "includes.h"
+#include "ldb/include/includes.h"
+
+struct partition {
+ struct ldb_module *module;
+ const char *backend;
+ struct ldb_dn *dn;
+};
+struct partition_private_data {
+ struct partition **partitions;
+};
+
+struct ldb_module *find_backend(struct ldb_module *module, struct ldb_request *req, const struct ldb_dn *dn)
+{
+ int i;
+ struct partition_private_data *data = talloc_get_type(module->private_data,
+ struct partition_private_data);
+ /* Look at base DN */
+ /* Figure out which partition it is under */
+ /* Skip the lot if 'data' isn't here yet (initialistion) */
+ for (i=0; data && data->partitions && data->partitions[i]; i++) {
+ if (ldb_dn_compare_base(module->ldb,
+ data->partitions[i]->dn,
+ dn) == 0) {
+ struct ldb_module *current;
+ static const struct ldb_module_ops ops; /* zero */
+ current = talloc_zero(req, struct ldb_module);
+ if (current == NULL) {
+ return module;
+ }
+
+ current->ldb = module->ldb;
+ current->ops = &ops;
+ current->prev = module;
+ current->next = data->partitions[i]->module;
+ return current;
+ }
+ }
+
+ return module;
+};
+
+/* search */
+static int partition_search(struct ldb_module *module, struct ldb_request *req)
+{
+ /* Find backend */
+ struct ldb_module *backend = find_backend(module, req, req->op.search.base);
+
+ /* issue request */
+
+ /* (later) consider if we should be searching multiple
+ * partitions (for 'invisible' partition behaviour */
+ return ldb_next_request(backend, req);
+}
+
+/* add */
+static int partition_add(struct ldb_module *module, struct ldb_request *req)
+{
+ /* Find backend */
+ struct ldb_module *backend = find_backend(module, req, req->op.add.message->dn);
+
+ /* issue request */
+
+ return ldb_next_request(backend, req);
+}
+
+/* modify */
+static int partition_modify(struct ldb_module *module, struct ldb_request *req)
+{
+ /* Find backend */
+ struct ldb_module *backend = find_backend(module, req, req->op.mod.message->dn);
+
+ /* issue request */
+
+ return ldb_next_request(backend, req);
+}
+
+/* delete */
+static int partition_delete(struct ldb_module *module, struct ldb_request *req)
+{
+ /* Find backend */
+ struct ldb_module *backend = find_backend(module, req, req->op.del.dn);
+
+ /* issue request */
+
+ return ldb_next_request(backend, req);
+}
+
+/* rename */
+static int partition_rename(struct ldb_module *module, struct ldb_request *req)
+{
+ /* Find backend */
+ struct ldb_module *backend = find_backend(module, req, req->op.rename.olddn);
+ struct ldb_module *backend2 = find_backend(module, req, req->op.rename.newdn);
+
+ if (backend->next != backend2->next) {
+ return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
+ }
+
+ /* issue request */
+
+ /* (later) consider if we should be searching multiple partitions */
+ return ldb_next_request(backend, req);
+}
+
+#if 0
+/* We should do this over the entire list of partitions */
+
+/* start a transaction */
+static int partition_start_trans(struct ldb_module *module)
+{
+ return ldb_next_start_trans(module);
+}
+
+/* end a transaction */
+static int partition_end_trans(struct ldb_module *module)
+{
+ return ldb_next_end_trans(module);
+}
+
+/* delete a transaction */
+static int partition_del_trans(struct ldb_module *module)
+{
+ return ldb_next_del_trans(module);
+}
+#endif
+
+static int partition_init(struct ldb_module *module)
+{
+ int ret, i;
+ TALLOC_CTX *mem_ctx = talloc_new(module);
+ static const char *attrs[] = { "partition", NULL };
+ struct ldb_result *res;
+ struct ldb_message *msg;
+ struct ldb_message_element *partition_attributes;
+
+ struct partition_private_data *data;
+
+ if (!mem_ctx) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ data = talloc(mem_ctx, struct partition_private_data);
+ if (data == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_search(module->ldb, ldb_dn_explode(mem_ctx, "@PARTITION"),
+ LDB_SCOPE_BASE,
+ NULL, attrs,
+ &res);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+ talloc_steal(mem_ctx, res);
+ if (res->count == 0) {
+ talloc_free(mem_ctx);
+ return ldb_next_init(module);
+ }
+
+ if (res->count > 1) {
+ talloc_free(mem_ctx);
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ msg = res->msgs[0];
+
+ partition_attributes = ldb_msg_find_element(msg, "partition");
+ if (!partition_attributes) {
+ ldb_set_errstring(module->ldb,
+ talloc_asprintf(module, "partition_init: "
+ "no partitions specified"));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ data->partitions = talloc_array(data, struct partition *, partition_attributes->num_values + 1);
+ if (!data->partitions) {
+ talloc_free(mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ for (i=0; i < partition_attributes->num_values; i++) {
+ struct ldb_request *req;
+
+ char *base = talloc_strdup(data->partitions, (char *)partition_attributes->values[i].data);
+ char *p = strchr(base, ':');
+ if (!p) {
+ ldb_set_errstring(module->ldb,
+ talloc_asprintf(module, "partition_init: "
+ "invalid form for partition record (missing ':'): %s", base));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ p[0] = '\0';
+ p++;
+ if (!p[0]) {
+ ldb_set_errstring(module->ldb,
+ talloc_asprintf(module, "partition_init: "
+ "invalid form for partition record (missing backend database): %s", base));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ data->partitions[i] = talloc(data->partitions, struct partition);
+ if (!data->partitions[i]) {
+ talloc_free(mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ data->partitions[i]->dn = ldb_dn_explode(data->partitions[i], base);
+ if (!data->partitions[i]->dn) {
+ ldb_set_errstring(module->ldb,
+ talloc_asprintf(module, "partition_init: "
+ "invalid DN in partition record: %s", base));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ data->partitions[i]->backend = private_path(data->partitions[i], p);
+ ret = ldb_connect_backend(module->ldb, data->partitions[i]->backend, 0, NULL, &data->partitions[i]->module);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ req = talloc_zero(mem_ctx, struct ldb_request);
+ if (req == NULL) {
+ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "partition: Out of memory!\n");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ req->operation = LDB_REQ_REGISTER_PARTITION;
+ req->op.reg_partition.dn = data->partitions[i]->dn;
+
+ ret = ldb_request(module->ldb, req);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "partition: Unable to register partition with rootdse!\n");
+ return LDB_ERR_OTHER;
+ }
+ talloc_free(req);
+ }
+ data->partitions[i] = NULL;
+
+ module->private_data = data;
+ talloc_steal(module, data);
+
+ talloc_free(mem_ctx);
+ return ldb_next_init(module);
+}
+
+static const struct ldb_module_ops partition_ops = {
+ .name = "partition",
+ .init_context = partition_init,
+ .search = partition_search,
+ .add = partition_add,
+ .modify = partition_modify,
+ .del = partition_delete,
+ .rename = partition_rename,
+#if 0
+ .start_transaction = partition_start_trans,
+ .end_transaction = partition_end_trans,
+ .del_transaction = partition_del_trans,
+#endif
+};
+
+int ldb_partition_init(void)
+{
+ return ldb_register_module(&partition_ops);
+}