dsdb: Ensure to sort replPropertyMetaData as UNSIGNED, not SIGNED quantities
[Samba.git] / source4 / dsdb / samdb / ldb_modules / new_partition.c
blobeaf7d43b167cc33fe18284d0a97cf505bb4ee02a
1 /*
2 ldb database library
4 Copyright (C) Simo Sorce 2004-2008
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * Name: ldb
26 * Component: ldb new partition module
28 * Description: Handle the add of new partitions
30 * Author: Andrew Bartlett
33 #include "includes.h"
34 #include "ldb.h"
35 #include "ldb_module.h"
36 #include "librpc/gen_ndr/ndr_misc.h"
37 #include "dsdb/samdb/samdb.h"
38 #include "../libds/common/flags.h"
39 #include "dsdb/common/util.h"
41 struct np_context {
42 struct ldb_module *module;
43 struct ldb_request *req;
44 struct ldb_request *search_req;
45 struct ldb_request *part_add;
48 static int np_part_mod_callback(struct ldb_request *req, struct ldb_reply *ares)
50 struct ldb_context *ldb;
51 struct np_context *ac;
53 ac = talloc_get_type(req->context, struct np_context);
54 ldb = ldb_module_get_ctx(ac->module);
56 if (!ares) {
57 return ldb_module_done(ac->req, NULL, NULL,
58 LDB_ERR_OPERATIONS_ERROR);
61 /* We just want to update the @PARTITIONS record if the value does not exist */
62 if (ares->error != LDB_SUCCESS && ares->error != LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
63 return ldb_module_done(ac->req, ares->controls,
64 ares->response, ares->error);
67 if (ares->type != LDB_REPLY_DONE) {
68 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
69 return ldb_module_done(ac->req, NULL, NULL,
70 LDB_ERR_OPERATIONS_ERROR);
73 ldb_reset_err_string(ldb);
75 /* Do the original add */
76 return ldb_next_request(ac->module, ac->req);
79 static int np_part_search_callback(struct ldb_request *req, struct ldb_reply *ares)
81 struct ldb_context *ldb;
82 struct np_context *ac;
83 struct dsdb_create_partition_exop *ex_op;
84 int ret;
86 ac = talloc_get_type(req->context, struct np_context);
87 ldb = ldb_module_get_ctx(ac->module);
89 if (!ares) {
90 return ldb_module_done(ac->req, NULL, NULL,
91 LDB_ERR_OPERATIONS_ERROR);
94 /* If this already exists, we really don't want to create a
95 * partition - it would allow a duplicate entry to be
96 * created */
97 if (ares->error != LDB_ERR_NO_SUCH_OBJECT) {
98 if (ares->error == LDB_SUCCESS) {
99 return ldb_module_done(ac->req, ares->controls,
100 ares->response, LDB_ERR_ENTRY_ALREADY_EXISTS);
101 } else {
102 return ldb_module_done(ac->req, ares->controls,
103 ares->response, ares->error);
107 if (ares->type != LDB_REPLY_DONE) {
108 ldb_set_errstring(ldb, "Invalid reply type - we must not get a result here!");
109 return ldb_module_done(ac->req, NULL, NULL,
110 LDB_ERR_OPERATIONS_ERROR);
113 ldb_reset_err_string(ldb);
115 /* Now that we know it does not exist, we can try and create the partition */
116 ex_op = talloc(ac, struct dsdb_create_partition_exop);
117 if (ex_op == NULL) {
118 return ldb_oom(ldb);
121 ex_op->new_dn = ac->req->op.add.message->dn;
123 ret = ldb_build_extended_req(&ac->part_add,
124 ldb, ac, DSDB_EXTENDED_CREATE_PARTITION_OID, ex_op,
125 NULL, ac, np_part_mod_callback, req);
127 /* if the parent was asking for a partial replica, then we
128 * need the extended operation to also ask for a partial
129 * replica */
130 if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) {
131 ret = dsdb_request_add_controls(ac->part_add, DSDB_MODIFY_PARTIAL_REPLICA);
132 if (ret != LDB_SUCCESS) {
133 return ret;
138 LDB_REQ_SET_LOCATION(ac->part_add);
139 if (ret != LDB_SUCCESS) {
140 return ret;
143 return ldb_next_request(ac->module, ac->part_add);
146 /* add_record: add instancetype attribute */
147 static int new_partition_add(struct ldb_module *module, struct ldb_request *req)
149 struct ldb_context *ldb;
150 struct np_context *ac;
151 int ret;
153 ldb = ldb_module_get_ctx(module);
155 ldb_debug(ldb, LDB_DEBUG_TRACE, "new_partition_add\n");
157 /* do not manipulate our control entries */
158 if (ldb_dn_is_special(req->op.add.message->dn)) {
159 return ldb_next_request(module, req);
162 if (ldb_msg_find_element(req->op.add.message, "instanceType")) {
163 /* This needs to be 'static' to ensure it does not move, and is not on the stack */
164 static const char *no_attrs[] = { NULL };
165 uint32_t instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0);
167 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
168 return ldb_next_request(module, req);
171 if (ldb_msg_find_attr_as_bool(req->op.add.message, "isDeleted", false)) {
172 DEBUG(0,(__location__ ": Skipping deleted partition %s\n",
173 ldb_dn_get_linearized(req->op.add.message->dn)));
174 return ldb_next_request(module, req);
177 /* Create an @PARTITIONS record for this partition -
178 * by asking the partitions module to do so via an
179 * extended operation, after first checking if the
180 * record already exists */
181 ac = talloc(req, struct np_context);
182 if (ac == NULL) {
183 return ldb_oom(ldb);
185 ac->module = module;
186 ac->req = req;
188 ret = ldb_build_search_req(&ac->search_req, ldb, ac, req->op.add.message->dn,
189 LDB_SCOPE_BASE, NULL, no_attrs, req->controls, ac,
190 np_part_search_callback,
191 req);
192 LDB_REQ_SET_LOCATION(ac->search_req);
193 if (ret != LDB_SUCCESS) {
194 return ret;
197 return ldb_next_request(module, ac->search_req);
200 /* go on with the call chain */
201 return ldb_next_request(module, req);
204 static const struct ldb_module_ops ldb_new_partition_module_ops = {
205 .name = "new_partition",
206 .add = new_partition_add,
209 int ldb_new_partition_module_init(const char *version)
211 LDB_MODULE_CHECK_VERSION(version);
212 return ldb_register_module(&ldb_new_partition_module_ops);