s4:dsdb:ridalloc: use ridalloc_ridset_values infrastructure in ridalloc_allocate_rid_...
[Samba/ita.git] / source4 / dsdb / samdb / ldb_modules / ridalloc.c
blob2b0c4b9fa8a1a7256143c958a08aa4c80d565584
1 /*
2 RID allocation helper functions
4 Copyright (C) Andrew Bartlett 2010
5 Copyright (C) Andrew Tridgell 2010
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/>.
22 * Name: ldb
24 * Component: RID allocation logic
26 * Description: manage RID Set and RID Manager objects
30 #include "includes.h"
31 #include "ldb_module.h"
32 #include "dsdb/samdb/samdb.h"
33 #include "dsdb/samdb/ldb_modules/util.h"
34 #include "lib/messaging/irpc.h"
35 #include "param/param.h"
36 #include "librpc/gen_ndr/ndr_misc.h"
39 Note: the RID allocation attributes in AD are very badly named. Here
40 is what we think they really do:
42 in RID Set object:
43 - rIDPreviousAllocationPool: the pool which a DC is currently
44 pulling RIDs from. Managed by client DC
46 - rIDAllocationPool: the pool that the DC will switch to next,
47 when rIDPreviousAllocationPool is exhausted. Managed by RID Manager.
49 - rIDNextRID: the last RID allocated by this DC. Managed by client DC
51 in RID Manager object:
52 - rIDAvailablePool: the pool where the RID Manager gets new rID
53 pools from when it gets a EXOP_RID_ALLOC getncchanges call (or
54 locally when the DC is the RID Manager)
59 make a IRPC call to the drepl task to ask it to get the RID
60 Manager to give us another RID pool.
62 This function just sends the message to the drepl task then
63 returns immediately. It should be called well before we
64 completely run out of RIDs
66 static void ridalloc_poke_rid_manager(struct ldb_module *module)
68 struct messaging_context *msg;
69 struct server_id *server;
70 struct ldb_context *ldb = ldb_module_get_ctx(module);
71 struct loadparm_context *lp_ctx =
72 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
73 TALLOC_CTX *tmp_ctx = talloc_new(module);
75 msg = messaging_client_init(tmp_ctx, lp_messaging_path(tmp_ctx, lp_ctx),
76 ldb_get_event_context(ldb));
77 if (!msg) {
78 DEBUG(3,(__location__ ": Failed to create messaging context\n"));
79 talloc_free(tmp_ctx);
80 return;
83 server = irpc_servers_byname(msg, msg, "dreplsrv");
84 if (!server) {
85 /* this means the drepl service is not running */
86 talloc_free(tmp_ctx);
87 return;
90 messaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);
92 /* we don't care if the message got through */
93 talloc_free(tmp_ctx);
97 static const char * const ridalloc_ridset_attrs[] = {
98 "rIDAllocationPool",
99 "rIDPreviousAllocationPool",
100 "rIDNextRID",
101 "rIDUsedPool",
102 NULL
105 struct ridalloc_ridset_values {
106 uint64_t alloc_pool;
107 uint64_t prev_pool;
108 uint32_t next_rid;
109 uint32_t used_pool;
112 static void ridalloc_get_ridset_values(struct ldb_message *msg, struct ridalloc_ridset_values *v)
114 v->alloc_pool = ldb_msg_find_attr_as_uint64(msg, "rIDAllocationPool", UINT64_MAX);
115 v->prev_pool = ldb_msg_find_attr_as_uint64(msg, "rIDPreviousAllocationPool", UINT64_MAX);
116 v->next_rid = ldb_msg_find_attr_as_uint(msg, "rIDNextRID", UINT32_MAX);
117 v->used_pool = ldb_msg_find_attr_as_uint(msg, "rIDUsedPool", UINT32_MAX);
120 static int ridalloc_set_ridset_values(struct ldb_module *module,
121 struct ldb_message *msg,
122 const struct ridalloc_ridset_values *o,
123 const struct ridalloc_ridset_values *n)
125 const uint32_t *o32, *n32;
126 const uint64_t *o64, *n64;
127 int ret;
129 #define SETUP_PTRS(field, optr, nptr, max) do { \
130 optr = &o->field; \
131 nptr = &n->field; \
132 if (o->field == max) { \
133 optr = NULL; \
135 if (n->field == max) { \
136 nptr = NULL; \
138 if (o->field == n->field) { \
139 optr = NULL; \
140 nptr = NULL; \
142 } while(0)
144 SETUP_PTRS(alloc_pool, o64, n64, UINT64_MAX);
145 ret = dsdb_msg_constrainted_update_uint64(module, msg,
146 "rIDAllocationPool",
147 o64, n64);
148 if (ret != LDB_SUCCESS) {
149 return ret;
152 SETUP_PTRS(prev_pool, o64, n64, UINT64_MAX);
153 ret = dsdb_msg_constrainted_update_uint64(module, msg,
154 "rIDPreviousAllocationPool",
155 o64, n64);
156 if (ret != LDB_SUCCESS) {
157 return ret;
160 SETUP_PTRS(next_rid, o32, n32, UINT32_MAX);
161 ret = dsdb_msg_constrainted_update_uint32(module, msg,
162 "rIDNextRID",
163 o32, n32);
164 if (ret != LDB_SUCCESS) {
165 return ret;
168 SETUP_PTRS(used_pool, o32, n32, UINT32_MAX);
169 ret = dsdb_msg_constrainted_update_uint32(module, msg,
170 "rIDUsedPool",
171 o32, n32);
172 if (ret != LDB_SUCCESS) {
173 return ret;
175 #undef SETUP_PTRS
177 return LDB_SUCCESS;
181 allocate a new range of RIDs in the RID Manager object
183 static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool)
185 int ret;
186 TALLOC_CTX *tmp_ctx = talloc_new(module);
187 const char *attrs[] = { "rIDAvailablePool", NULL };
188 uint64_t rid_pool, new_rid_pool, dc_pool;
189 uint32_t rid_pool_lo, rid_pool_hi;
190 struct ldb_result *res;
191 struct ldb_context *ldb = ldb_module_get_ctx(module);
192 const unsigned alloc_size = 500;
194 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn,
195 attrs, DSDB_FLAG_NEXT_MODULE);
196 if (ret != LDB_SUCCESS) {
197 ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
198 ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
199 talloc_free(tmp_ctx);
200 return ret;
203 rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
204 rid_pool_lo = rid_pool & 0xFFFFFFFF;
205 rid_pool_hi = rid_pool >> 32;
206 if (rid_pool_lo >= rid_pool_hi) {
207 ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
208 rid_pool_lo, rid_pool_hi);
209 talloc_free(tmp_ctx);
210 return ret;
213 /* lower part of new pool is the low part of the rIDAvailablePool */
214 dc_pool = rid_pool_lo;
216 /* allocate 500 RIDs to this DC */
217 rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
219 /* work out upper part of new pool */
220 dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
222 /* and new rIDAvailablePool value */
223 new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
225 ret = dsdb_module_constrainted_update_uint64(module, rid_manager_dn, "rIDAvailablePool",
226 &rid_pool, &new_rid_pool);
227 if (ret != LDB_SUCCESS) {
228 ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
229 ldb_errstring(ldb));
230 talloc_free(tmp_ctx);
231 return ret;
234 (*new_pool) = dc_pool;
235 talloc_free(tmp_ctx);
236 return LDB_SUCCESS;
240 create a RID Set object for the specified DC
242 static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
243 struct ldb_dn *rid_manager_dn,
244 struct ldb_dn *ntds_dn, struct ldb_dn **dn)
246 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
247 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
248 int ret;
249 struct ldb_message *msg;
250 struct ldb_context *ldb = ldb_module_get_ctx(module);
251 static const struct ridalloc_ridset_values o = {
252 .alloc_pool = UINT64_MAX,
253 .prev_pool = UINT64_MAX,
254 .next_rid = UINT32_MAX,
255 .used_pool = UINT32_MAX,
257 struct ridalloc_ridset_values n = {
258 .alloc_pool = 0,
259 .prev_pool = 0,
260 .next_rid = 0,
261 .used_pool = 0,
265 steps:
267 find the machine object for the DC
268 construct the RID Set DN
269 load rIDAvailablePool to find next available set
270 modify RID Manager object to update rIDAvailablePool
271 add the RID Set object
272 link to the RID Set object in machine object
275 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
276 if (!server_dn) {
277 talloc_free(tmp_ctx);
278 return ldb_module_oom(module);
281 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
282 if (ret != LDB_SUCCESS) {
283 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
284 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
285 talloc_free(tmp_ctx);
286 return ret;
289 rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
290 if (rid_set_dn == NULL) {
291 talloc_free(tmp_ctx);
292 return ldb_module_oom(module);
295 if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
296 talloc_free(tmp_ctx);
297 return ldb_module_oom(module);
300 /* grab a pool from the RID Manager object */
301 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool);
302 if (ret != LDB_SUCCESS) {
303 talloc_free(tmp_ctx);
304 return ret;
307 /* create the RID Set object */
308 msg = ldb_msg_new(tmp_ctx);
309 msg->dn = rid_set_dn;
311 ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
312 if (ret != LDB_SUCCESS) {
313 talloc_free(tmp_ctx);
314 return ret;
317 ret = ridalloc_set_ridset_values(module, msg, &o, &n);
318 if (ret != LDB_SUCCESS) {
319 talloc_free(tmp_ctx);
320 return ret;
323 /* we need this to go all the way to the top of the module
324 * stack, as we need all the extra attributes added (including
325 * complex ones like ntsecuritydescriptor) */
326 ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX);
327 if (ret != LDB_SUCCESS) {
328 ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
329 ldb_dn_get_linearized(msg->dn),
330 ldb_errstring(ldb));
331 talloc_free(tmp_ctx);
332 return ret;
335 /* add the rIDSetReferences link */
336 msg = ldb_msg_new(tmp_ctx);
337 msg->dn = machine_dn;
339 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
340 if (ret != LDB_SUCCESS) {
341 talloc_free(tmp_ctx);
342 return ret;
344 msg->elements[0].flags = LDB_FLAG_MOD_ADD;
346 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
347 if (ret != LDB_SUCCESS) {
348 ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
349 ldb_dn_get_linearized(msg->dn),
350 ldb_errstring(ldb));
351 talloc_free(tmp_ctx);
352 return ret;
355 (*dn) = talloc_steal(mem_ctx, rid_set_dn);
357 talloc_free(tmp_ctx);
358 return LDB_SUCCESS;
363 create a RID Set object for this DC
365 static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
366 struct ldb_dn **dn)
368 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
369 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
370 int ret;
371 struct ldb_context *ldb = ldb_module_get_ctx(module);
373 /* work out who is the RID Manager */
374 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
375 if (ret != LDB_SUCCESS) {
376 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
377 ldb_errstring(ldb));
378 talloc_free(tmp_ctx);
379 return ret;
382 /* find the DN of the RID Manager */
383 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
384 if (ret != LDB_SUCCESS) {
385 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
386 ldb_errstring(ldb));
387 talloc_free(tmp_ctx);
388 return ret;
391 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
392 ridalloc_poke_rid_manager(module);
393 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
394 talloc_free(tmp_ctx);
395 return LDB_ERR_UNWILLING_TO_PERFORM;
398 ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn);
399 talloc_free(tmp_ctx);
400 return ret;
404 get a new RID pool for ourselves
405 also returns the first rid for the new pool
407 static int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool)
409 TALLOC_CTX *tmp_ctx = talloc_new(module);
410 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
411 int ret;
412 struct ldb_context *ldb = ldb_module_get_ctx(module);
414 /* work out who is the RID Manager */
415 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
416 if (ret != LDB_SUCCESS) {
417 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
418 ldb_errstring(ldb));
419 talloc_free(tmp_ctx);
420 return ret;
423 /* find the DN of the RID Manager */
424 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
425 if (ret != LDB_SUCCESS) {
426 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
427 ldb_errstring(ldb));
428 talloc_free(tmp_ctx);
429 return ret;
432 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
433 ridalloc_poke_rid_manager(module);
434 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
435 talloc_free(tmp_ctx);
436 return LDB_ERR_UNWILLING_TO_PERFORM;
439 /* grab a pool from the RID Manager object */
440 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool);
441 if (ret != LDB_SUCCESS) {
442 talloc_free(tmp_ctx);
443 return ret;
446 talloc_free(tmp_ctx);
447 return ret;
451 /* allocate a RID using our RID Set
452 If we run out of RIDs then allocate a new pool
453 either locally or by contacting the RID Manager
455 int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
457 struct ldb_context *ldb;
458 int ret;
459 struct ldb_dn *rid_set_dn;
460 struct ldb_result *res;
461 struct ldb_message *msg;
462 struct ridalloc_ridset_values oridset;
463 struct ridalloc_ridset_values nridset;
464 uint32_t prev_pool_lo, prev_pool_hi;
465 TALLOC_CTX *tmp_ctx = talloc_new(module);
467 (*rid) = 0;
468 ldb = ldb_module_get_ctx(module);
470 ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
471 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
472 ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn);
474 if (ret != LDB_SUCCESS) {
475 ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
476 ldb_errstring(ldb));
477 talloc_free(tmp_ctx);
478 return ret;
481 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
482 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE);
483 if (ret != LDB_SUCCESS) {
484 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
485 ldb_dn_get_linearized(rid_set_dn));
486 talloc_free(tmp_ctx);
487 return ret;
490 ridalloc_get_ridset_values(res->msgs[0], &oridset);
491 if (oridset.alloc_pool == UINT64_MAX) {
492 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
493 ldb_dn_get_linearized(rid_set_dn));
494 talloc_free(tmp_ctx);
495 return LDB_ERR_OPERATIONS_ERROR;
498 nridset = oridset;
501 * If we never used a pool, setup out first pool
503 if (nridset.prev_pool == UINT64_MAX ||
504 nridset.next_rid == UINT32_MAX) {
505 nridset.prev_pool = nridset.alloc_pool;
506 nridset.next_rid = nridset.prev_pool & 0xFFFFFFFF;
510 * Now check if our current pool is still usable
512 nridset.next_rid += 1;
513 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
514 prev_pool_hi = nridset.prev_pool >> 32;
515 if (nridset.next_rid > prev_pool_hi) {
517 * We need a new pool, check if we already have a new one
518 * Otherwise we need to get a new pool.
520 if (nridset.alloc_pool == nridset.prev_pool) {
522 * if we are the RID Manager,
523 * we can get a new pool localy.
524 * Otherwise we fail the operation and
525 * ask async for a new pool.
527 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool);
528 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
529 ridalloc_poke_rid_manager(module);
530 talloc_free(tmp_ctx);
531 return ret;
533 if (ret != LDB_SUCCESS) {
534 talloc_free(tmp_ctx);
535 return ret;
540 * increment the rIDUsedPool attribute
542 * Note: w2k8r2 doesn't update this attribute,
543 * at least if it's itself the rid master.
545 nridset.used_pool += 1;
547 /* now use the new pool */
548 nridset.prev_pool = nridset.alloc_pool;
549 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
550 prev_pool_hi = nridset.prev_pool >> 32;
551 nridset.next_rid = prev_pool_lo;
554 if (nridset.next_rid < prev_pool_lo || nridset.next_rid > prev_pool_hi) {
555 ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
556 (unsigned)nridset.next_rid,
557 (unsigned)prev_pool_lo,
558 (unsigned)prev_pool_hi);
559 talloc_free(tmp_ctx);
560 return LDB_ERR_OPERATIONS_ERROR;
564 * if we are half-exhausted then try to get a new pool.
566 if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2) {
568 * if we are the RID Manager,
569 * we can get a new pool localy.
570 * Otherwise we fail the operation and
571 * ask async for a new pool.
573 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool);
574 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
575 ridalloc_poke_rid_manager(module);
576 ret = LDB_SUCCESS;
578 if (ret != LDB_SUCCESS) {
579 talloc_free(tmp_ctx);
580 return ret;
585 * update the values
587 msg = ldb_msg_new(tmp_ctx);
588 if (msg == NULL) {
589 return ldb_module_oom(module);
591 msg->dn = rid_set_dn;
593 ret = ridalloc_set_ridset_values(module, msg,
594 &oridset, &nridset);
595 if (ret != LDB_SUCCESS) {
596 talloc_free(tmp_ctx);
597 return ret;
600 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
601 if (ret != LDB_SUCCESS) {
602 talloc_free(tmp_ctx);
603 return ret;
606 talloc_free(tmp_ctx);
607 *rid = nridset.next_rid;
608 return LDB_SUCCESS;
613 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
615 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop)
617 struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
618 struct ldb_dn *rid_manager_dn;
619 TALLOC_CTX *tmp_ctx = talloc_new(module);
620 int ret;
621 struct ldb_context *ldb = ldb_module_get_ctx(module);
622 struct ldb_result *res;
623 struct ldb_message *msg;
624 struct ridalloc_ridset_values oridset, nridset;
626 ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn);
627 if (ret != LDB_SUCCESS) {
628 ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
629 GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
630 talloc_free(tmp_ctx);
631 return ret;
634 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
635 if (!server_dn) {
636 talloc_free(tmp_ctx);
637 return ldb_module_oom(module);
640 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
641 if (ret != LDB_SUCCESS) {
642 ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
643 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
644 talloc_free(tmp_ctx);
645 return ret;
648 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
649 if (ret != LDB_SUCCESS) {
650 ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
651 ldb_errstring(ldb));
652 talloc_free(tmp_ctx);
653 return ret;
656 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
657 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
658 ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn);
659 talloc_free(tmp_ctx);
660 return ret;
663 if (ret != LDB_SUCCESS) {
664 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
665 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
666 talloc_free(tmp_ctx);
667 return ret;
670 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
671 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE);
672 if (ret != LDB_SUCCESS) {
673 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
674 ldb_dn_get_linearized(rid_set_dn));
675 talloc_free(tmp_ctx);
676 return ret;
679 ridalloc_get_ridset_values(res->msgs[0], &oridset);
680 if (oridset.alloc_pool == UINT64_MAX) {
681 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
682 ldb_dn_get_linearized(rid_set_dn));
683 talloc_free(tmp_ctx);
684 return LDB_ERR_OPERATIONS_ERROR;
687 nridset = oridset;
689 if (exop->fsmo_info != 0) {
691 if (nridset.alloc_pool != exop->fsmo_info) {
692 /* it has already been updated */
693 DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
694 (unsigned long long)exop->fsmo_info,
695 (unsigned long long)nridset.alloc_pool));
696 talloc_free(tmp_ctx);
697 return LDB_SUCCESS;
701 /* grab a pool from the RID Manager object */
702 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &nridset.alloc_pool);
703 if (ret != LDB_SUCCESS) {
704 talloc_free(tmp_ctx);
705 return ret;
709 * update the values
711 msg = ldb_msg_new(tmp_ctx);
712 if (msg == NULL) {
713 return ldb_module_oom(module);
715 msg->dn = rid_set_dn;
717 ret = ridalloc_set_ridset_values(module, msg,
718 &oridset, &nridset);
719 if (ret != LDB_SUCCESS) {
720 talloc_free(tmp_ctx);
721 return ret;
724 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
725 if (ret != LDB_SUCCESS) {
726 ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
727 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
728 talloc_free(tmp_ctx);
729 return ret;
732 talloc_free(tmp_ctx);
733 return LDB_SUCCESS;