diff options
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index bd037066ca..614431c563 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -205,11 +205,13 @@ error: } -static int partition_send_request(struct partition_context *ac, struct dsdb_control_current_partition *partition) +static int partition_send_request(struct partition_context *ac, struct ldb_control *remove_control, + struct dsdb_control_current_partition *partition) { int ret; struct ldb_module *backend; struct ldb_request *req; + struct ldb_control **saved_controls; if (partition) { backend = make_module_for_next_request(ac, ac->module->ldb, partition->module); @@ -231,7 +233,7 @@ static int partition_send_request(struct partition_context *ac, struct dsdb_cont *req = *ac->orig_req; /* copy the request */ - if (ac->orig_req->controls) { + if (req->controls) { req->controls = talloc_memdup(req, ac->orig_req->controls, talloc_get_size(ac->orig_req->controls)); @@ -259,6 +261,12 @@ static int partition_send_request(struct partition_context *ac, struct dsdb_cont req->context = ac; } + /* Remove a control, so we don't confuse a backend server */ + if (remove_control && !save_controls(remove_control, req, &saved_controls)) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + if (partition) { ret = ldb_request_add_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID, false, partition); if (ret != LDB_SUCCESS) { @@ -278,17 +286,19 @@ static int partition_send_request(struct partition_context *ac, struct dsdb_cont /* Send a request down to all the partitions */ static int partition_send_all(struct ldb_module *module, - struct partition_context *ac, struct ldb_request *req) + struct partition_context *ac, + struct ldb_control *remove_control, + struct ldb_request *req) { int i; struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); - int ret = partition_send_request(ac, NULL); + int ret = partition_send_request(ac, remove_control, NULL); if (ret != LDB_SUCCESS) { return ret; } for (i=0; data && data->partitions && data->partitions[i]; i++) { - ret = partition_send_request(ac, data->partitions[i]); + ret = partition_send_request(ac, remove_control, data->partitions[i]); if (ret != LDB_SUCCESS) { return ret; } @@ -307,18 +317,20 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); - /* Is this a special DN, we need to replicate to every backend? */ - for (i=0; data->replicate && data->replicate[i]; i++) { - if (ldb_dn_compare(data->replicate[i], - dn) == 0) { - struct partition_context *ac; - - ac = partition_init_handle(req, module); - if (!ac) { - return LDB_ERR_OPERATIONS_ERROR; + if (req->operation != LDB_SEARCH) { + /* Is this a special DN, we need to replicate to every backend? */ + for (i=0; data->replicate && data->replicate[i]; i++) { + if (ldb_dn_compare(data->replicate[i], + dn) == 0) { + struct partition_context *ac; + + ac = partition_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return partition_send_all(module, ac, NULL, req); } - - return partition_send_all(module, ac, req); } } @@ -371,7 +383,11 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) if (search_options && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) { int ret, i; struct partition_context *ac; - + struct ldb_control *remove_control = NULL; + if ((search_options->search_options & ~LDB_SEARCH_OPTION_PHANTOM_ROOT) == 0) { + /* We have processed this flag, so we are done with this control now */ + remove_control = search_control; + } ac = partition_init_handle(req, module); if (!ac) { return LDB_ERR_OPERATIONS_ERROR; @@ -379,12 +395,12 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) /* Search from the base DN */ if (!req->op.search.base || ldb_dn_is_null(req->op.search.base)) { - return partition_send_all(module, ac, req); + return partition_send_all(module, ac, remove_control, req); } for (i=0; data && data->partitions && data->partitions[i]; i++) { /* Find all partitions under the search base */ if (ldb_dn_compare_base(req->op.search.base, data->partitions[i]->dn) == 0) { - ret = partition_send_request(ac, data->partitions[i]); + ret = partition_send_request(ac, remove_control, data->partitions[i]); if (ret != LDB_SUCCESS) { return ret; } @@ -399,9 +415,8 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) return LDB_SUCCESS; } else { - struct ldb_module *backend = find_backend(module, req, req->op.search.base); - - return ldb_next_request(backend, req); + /* Handle this like all other requests */ + return partition_replicate(module, req, req->op.search.base); } } @@ -672,7 +687,7 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req return LDB_ERR_OPERATIONS_ERROR; } - return partition_send_all(module, ac, req); + return partition_send_all(module, ac, NULL, req); } static int sort_compare(void *void1, |