s4:resolve_oids LDB module - not really a change but a nicer method to call "talloc_r...
[Samba/nascimento.git] / source4 / dsdb / samdb / ldb_modules / ridalloc.c
bloba64062fcdc965c53e2f85346cd0a836571be1689
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 = ldb_get_opaque(ldb, "loadparm");
72 TALLOC_CTX *tmp_ctx = talloc_new(module);
74 msg = messaging_client_init(tmp_ctx, lp_messaging_path(tmp_ctx, lp_ctx),
75 lp_iconv_convenience(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);
98 allocate a new range of RIDs in the RID Manager object
100 static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool)
102 int ret;
103 TALLOC_CTX *tmp_ctx = talloc_new(module);
104 const char *attrs[] = { "rIDAvailablePool", NULL };
105 uint64_t rid_pool, new_rid_pool, dc_pool;
106 uint32_t rid_pool_lo, rid_pool_hi;
107 struct ldb_result *res;
108 struct ldb_context *ldb = ldb_module_get_ctx(module);
109 const unsigned alloc_size = 500;
111 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn, attrs, 0);
112 if (ret != LDB_SUCCESS) {
113 ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
114 ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
115 talloc_free(tmp_ctx);
116 return ret;
119 rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
120 rid_pool_lo = rid_pool & 0xFFFFFFFF;
121 rid_pool_hi = rid_pool >> 32;
122 if (rid_pool_lo >= rid_pool_hi) {
123 ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
124 rid_pool_lo, rid_pool_hi);
125 talloc_free(tmp_ctx);
126 return ret;
129 /* lower part of new pool is the low part of the rIDAvailablePool */
130 dc_pool = rid_pool_lo;
132 /* allocate 500 RIDs to this DC */
133 rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
135 /* work out upper part of new pool */
136 dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
138 /* and new rIDAvailablePool value */
139 new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
141 ret = dsdb_module_constrainted_update_integer(module, rid_manager_dn, "rIDAvailablePool",
142 rid_pool, new_rid_pool);
143 if (ret != LDB_SUCCESS) {
144 ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
145 ldb_errstring(ldb));
146 talloc_free(tmp_ctx);
147 return ret;
150 (*new_pool) = dc_pool;
151 talloc_free(tmp_ctx);
152 return LDB_SUCCESS;
156 create a RID Set object for the specified DC
158 static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
159 struct ldb_dn *rid_manager_dn,
160 struct ldb_dn *ntds_dn, struct ldb_dn **dn)
162 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
163 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
164 int ret;
165 uint64_t dc_pool;
166 struct ldb_message *msg;
167 struct ldb_context *ldb = ldb_module_get_ctx(module);
170 steps:
172 find the machine object for the DC
173 construct the RID Set DN
174 load rIDAvailablePool to find next available set
175 modify RID Manager object to update rIDAvailablePool
176 add the RID Set object
177 link to the RID Set object in machine object
180 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
181 if (!server_dn) {
182 ldb_module_oom(module);
183 talloc_free(tmp_ctx);
184 return LDB_ERR_OPERATIONS_ERROR;
187 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
188 if (ret != LDB_SUCCESS) {
189 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
190 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
191 talloc_free(tmp_ctx);
192 return ret;
195 rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
196 if (rid_set_dn == NULL) {
197 ldb_module_oom(module);
198 return LDB_ERR_OPERATIONS_ERROR;
201 if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
202 ldb_module_oom(module);
203 return LDB_ERR_OPERATIONS_ERROR;
206 /* grab a pool from the RID Manager object */
207 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &dc_pool);
208 if (ret != LDB_SUCCESS) {
209 talloc_free(tmp_ctx);
210 return ret;
213 /* create the RID Set object */
214 msg = ldb_msg_new(tmp_ctx);
215 msg->dn = rid_set_dn;
217 ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
218 if (ret != LDB_SUCCESS) {
219 talloc_free(tmp_ctx);
220 return ret;
222 ret = ldb_msg_add_fmt(msg, "rIDAllocationPool", "%llu", (unsigned long long)dc_pool);
223 if (ret != LDB_SUCCESS) {
224 talloc_free(tmp_ctx);
225 return ret;
228 /* w2k8-r2 sets these to zero when first created */
229 ret = ldb_msg_add_fmt(msg, "rIDPreviousAllocationPool", "0");
230 if (ret != LDB_SUCCESS) {
231 talloc_free(tmp_ctx);
232 return ret;
234 ret = ldb_msg_add_fmt(msg, "rIDUsedPool", "0");
235 if (ret != LDB_SUCCESS) {
236 talloc_free(tmp_ctx);
237 return ret;
239 ret = ldb_msg_add_fmt(msg, "rIDNextRID", "0");
240 if (ret != LDB_SUCCESS) {
241 talloc_free(tmp_ctx);
242 return ret;
245 /* we need this to go all the way to the top of the module
246 * stack, as we need all the extra attributes added (including
247 * complex ones like ntsecuritydescriptor) */
248 ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX);
249 if (ret != LDB_SUCCESS) {
250 ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
251 ldb_dn_get_linearized(msg->dn),
252 ldb_errstring(ldb));
253 talloc_free(tmp_ctx);
254 return ret;
257 /* add the rIDSetReferences link */
258 msg = ldb_msg_new(tmp_ctx);
259 msg->dn = machine_dn;
261 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
262 if (ret != LDB_SUCCESS) {
263 talloc_free(tmp_ctx);
264 return ret;
266 msg->elements[0].flags = LDB_FLAG_MOD_ADD;
268 ret = dsdb_module_modify(module, msg, 0);
269 if (ret != LDB_SUCCESS) {
270 ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
271 ldb_dn_get_linearized(msg->dn),
272 ldb_errstring(ldb));
273 talloc_free(tmp_ctx);
274 return ret;
277 (*dn) = talloc_steal(mem_ctx, rid_set_dn);
279 talloc_free(tmp_ctx);
280 return LDB_SUCCESS;
285 create a RID Set object for this DC
287 static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
288 struct ldb_dn **dn)
290 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
291 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
292 int ret;
293 struct ldb_context *ldb = ldb_module_get_ctx(module);
295 /* work out who is the RID Manager */
296 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
297 if (ret != LDB_SUCCESS) {
298 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
299 ldb_errstring(ldb));
300 talloc_free(tmp_ctx);
301 return ret;
304 /* find the DN of the RID Manager */
305 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
306 if (ret != LDB_SUCCESS) {
307 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
308 ldb_errstring(ldb));
309 talloc_free(tmp_ctx);
310 return ret;
313 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
314 ridalloc_poke_rid_manager(module);
315 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
316 talloc_free(tmp_ctx);
317 return LDB_ERR_UNWILLING_TO_PERFORM;
320 ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn);
321 talloc_free(tmp_ctx);
322 return ret;
326 refresh a RID Set object for the specified DC
327 also returns the first RID for the new pool
329 static int ridalloc_refresh_rid_set_ntds(struct ldb_module *module,
330 struct ldb_dn *rid_manager_dn,
331 struct ldb_dn *ntds_dn, uint64_t *new_pool)
333 TALLOC_CTX *tmp_ctx = talloc_new(module);
334 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
335 struct ldb_context *ldb = ldb_module_get_ctx(module);
336 int ret;
338 /* grab a pool from the RID Manager object */
339 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool);
340 if (ret != LDB_SUCCESS) {
341 talloc_free(tmp_ctx);
342 return ret;
345 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
346 if (!server_dn) {
347 ldb_module_oom(module);
348 talloc_free(tmp_ctx);
349 return LDB_ERR_OPERATIONS_ERROR;
352 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
353 if (ret != LDB_SUCCESS) {
354 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
355 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
356 talloc_free(tmp_ctx);
357 return ret;
360 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
361 if (ret != LDB_SUCCESS) {
362 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
363 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
364 talloc_free(tmp_ctx);
365 return ret;
368 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDAllocationPool", *new_pool);
369 if (ret != LDB_SUCCESS) {
370 ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
371 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
372 talloc_free(tmp_ctx);
373 return ret;
376 talloc_free(tmp_ctx);
377 return LDB_SUCCESS;
382 get a new RID pool for ourselves
383 also returns the first rid for the new pool
385 static int ridalloc_refresh_own_pool(struct ldb_module *module, uint64_t *new_pool)
387 TALLOC_CTX *tmp_ctx = talloc_new(module);
388 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
389 int ret;
390 struct ldb_context *ldb = ldb_module_get_ctx(module);
392 /* work out who is the RID Manager */
393 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
394 if (ret != LDB_SUCCESS) {
395 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
396 ldb_errstring(ldb));
397 talloc_free(tmp_ctx);
398 return ret;
401 /* find the DN of the RID Manager */
402 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
403 if (ret != LDB_SUCCESS) {
404 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
405 ldb_errstring(ldb));
406 talloc_free(tmp_ctx);
407 return ret;
410 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
411 ridalloc_poke_rid_manager(module);
412 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
413 talloc_free(tmp_ctx);
414 return LDB_ERR_UNWILLING_TO_PERFORM;
417 ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, fsmo_role_dn, new_pool);
418 talloc_free(tmp_ctx);
419 return ret;
423 /* allocate a RID using our RID Set
424 If we run out of RIDs then allocate a new pool
425 either locally or by contacting the RID Manager
427 int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
429 struct ldb_context *ldb;
430 static const char * const attrs[] = { "rIDAllocationPool", "rIDPreviousAllocationPool",
431 "rIDNextRID" , "rIDUsedPool", NULL };
432 int ret;
433 struct ldb_dn *rid_set_dn;
434 struct ldb_result *res;
435 uint64_t alloc_pool, prev_alloc_pool;
436 uint32_t prev_alloc_pool_lo, prev_alloc_pool_hi;
437 uint32_t rid_used_pool;
438 int prev_rid;
439 TALLOC_CTX *tmp_ctx = talloc_new(module);
441 (*rid) = 0;
442 ldb = ldb_module_get_ctx(module);
444 ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
445 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
446 ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn);
448 if (ret != LDB_SUCCESS) {
449 ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
450 ldb_errstring(ldb));
451 talloc_free(tmp_ctx);
452 return ret;
455 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
456 if (ret != LDB_SUCCESS) {
457 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
458 ldb_dn_get_linearized(rid_set_dn));
459 talloc_free(tmp_ctx);
460 return ret;
463 prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
464 alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
465 prev_rid = ldb_msg_find_attr_as_int(res->msgs[0], "rIDNextRID", 0);
466 rid_used_pool = ldb_msg_find_attr_as_int(res->msgs[0], "rIDUsedPool", 0);
467 if (alloc_pool == 0) {
468 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
469 ldb_dn_get_linearized(rid_set_dn));
470 talloc_free(tmp_ctx);
471 return LDB_ERR_OPERATIONS_ERROR;
474 prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
475 prev_alloc_pool_hi = prev_alloc_pool >> 32;
476 if (prev_rid >= prev_alloc_pool_hi) {
477 if (prev_alloc_pool == 0) {
478 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDPreviousAllocationPool", alloc_pool);
479 } else {
480 ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
481 prev_alloc_pool, alloc_pool);
483 if (ret != LDB_SUCCESS) {
484 ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
485 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
486 talloc_free(tmp_ctx);
487 return ret;
489 prev_alloc_pool = alloc_pool;
490 prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
491 prev_alloc_pool_hi = prev_alloc_pool >> 32;
493 /* update the rIDUsedPool attribute */
494 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDUsedPool", rid_used_pool+1);
495 if (ret != LDB_SUCCESS) {
496 ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDUsedPool on %s - %s",
497 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
498 talloc_free(tmp_ctx);
499 return ret;
502 (*rid) = prev_alloc_pool_lo;
505 /* see if we are still out of RIDs, and if so then ask
506 the RID Manager to give us more */
507 if (prev_rid >= prev_alloc_pool_hi) {
508 uint64_t new_pool;
509 ret = ridalloc_refresh_own_pool(module, &new_pool);
510 if (ret != LDB_SUCCESS) {
511 return ret;
513 ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
514 prev_alloc_pool, new_pool);
515 if (ret != LDB_SUCCESS) {
516 ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
517 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
518 talloc_free(tmp_ctx);
519 return ret;
521 prev_alloc_pool = new_pool;
522 prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
523 prev_alloc_pool_hi = prev_alloc_pool >> 32;
524 (*rid) = prev_alloc_pool_lo;
525 } else {
526 /* despite the name, rIDNextRID is the value of the last user
527 * added by this DC, not the next available RID */
528 if (*rid == 0) {
529 (*rid) = prev_rid + 1;
533 if (*rid < prev_alloc_pool_lo || *rid > prev_alloc_pool_hi) {
534 ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
535 (unsigned)*rid, (unsigned)prev_alloc_pool_lo,
536 (unsigned)prev_alloc_pool_hi);
537 talloc_free(tmp_ctx);
538 return LDB_ERR_OPERATIONS_ERROR;
541 /* now modify the RID Set to use up this RID using a
542 * constrained delete/add if possible */
543 if (prev_rid == 0) {
544 ret = dsdb_module_set_integer(module, rid_set_dn, "rIDNextRID", *rid);
545 } else {
546 ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDNextRID", prev_rid, *rid);
549 /* if we are half-exhausted then ask the repl task to start
550 * getting another one */
551 if (*rid > (prev_alloc_pool_hi + prev_alloc_pool_lo)/2) {
552 ridalloc_poke_rid_manager(module);
555 talloc_free(tmp_ctx);
557 return ret;
562 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
564 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop)
566 struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
567 struct ldb_dn *rid_manager_dn;
568 TALLOC_CTX *tmp_ctx = talloc_new(module);
569 int ret;
570 struct ldb_context *ldb = ldb_module_get_ctx(module);
571 uint64_t new_pool;
573 ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn);
574 if (ret != LDB_SUCCESS) {
575 ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
576 GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
577 talloc_free(tmp_ctx);
578 return ret;
581 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
582 if (!server_dn) {
583 ldb_module_oom(module);
584 talloc_free(tmp_ctx);
585 return LDB_ERR_OPERATIONS_ERROR;
588 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
589 if (ret != LDB_SUCCESS) {
590 ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
591 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
592 talloc_free(tmp_ctx);
593 return ret;
597 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
598 if (ret != LDB_SUCCESS) {
599 ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
600 ldb_errstring(ldb));
601 talloc_free(tmp_ctx);
602 return ret;
605 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
606 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
607 ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn);
608 talloc_free(tmp_ctx);
609 return ret;
612 if (ret != LDB_SUCCESS) {
613 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
614 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
615 talloc_free(tmp_ctx);
616 return ret;
619 if (exop->fsmo_info != 0) {
620 const char *attrs[] = { "rIDAllocationPool", NULL };
621 struct ldb_result *res;
622 uint64_t alloc_pool;
624 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
625 if (ret != LDB_SUCCESS) {
626 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
627 ldb_dn_get_linearized(rid_set_dn));
628 talloc_free(tmp_ctx);
629 return ret;
632 alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
633 if (alloc_pool != exop->fsmo_info) {
634 /* it has already been updated */
635 DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
636 (unsigned long long)exop->fsmo_info,
637 (unsigned long long)alloc_pool));
638 talloc_free(tmp_ctx);
639 return LDB_SUCCESS;
643 ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, ntds_dn, &new_pool);
644 talloc_free(tmp_ctx);
645 return ret;