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/>.
24 * Component: RID allocation logic
26 * Description: manage RID Set and RID Manager objects
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:
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
));
78 DEBUG(3,(__location__
": Failed to create messaging context\n"));
83 server
= irpc_servers_byname(msg
, msg
, "dreplsrv");
85 /* this means the drepl service is not running */
90 messaging_send(msg
, server
[0], MSG_DREPL_ALLOCATE_RID
, NULL
);
92 /* we don't care if the message got through */
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
)
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
,
112 attrs
, DSDB_FLAG_NEXT_MODULE
);
113 if (ret
!= LDB_SUCCESS
) {
114 ldb_asprintf_errstring(ldb
, "Failed to find rIDAvailablePool in %s - %s",
115 ldb_dn_get_linearized(rid_manager_dn
), ldb_errstring(ldb
));
116 talloc_free(tmp_ctx
);
120 rid_pool
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "rIDAvailablePool", 0);
121 rid_pool_lo
= rid_pool
& 0xFFFFFFFF;
122 rid_pool_hi
= rid_pool
>> 32;
123 if (rid_pool_lo
>= rid_pool_hi
) {
124 ldb_asprintf_errstring(ldb
, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
125 rid_pool_lo
, rid_pool_hi
);
126 talloc_free(tmp_ctx
);
130 /* lower part of new pool is the low part of the rIDAvailablePool */
131 dc_pool
= rid_pool_lo
;
133 /* allocate 500 RIDs to this DC */
134 rid_pool_lo
= MIN(rid_pool_hi
, rid_pool_lo
+ alloc_size
);
136 /* work out upper part of new pool */
137 dc_pool
|= (((uint64_t)rid_pool_lo
-1)<<32);
139 /* and new rIDAvailablePool value */
140 new_rid_pool
= rid_pool_lo
| (((uint64_t)rid_pool_hi
)<<32);
142 ret
= dsdb_module_constrainted_update_integer(module
, rid_manager_dn
, "rIDAvailablePool",
143 rid_pool
, new_rid_pool
);
144 if (ret
!= LDB_SUCCESS
) {
145 ldb_asprintf_errstring(ldb
, "Failed to update rIDAvailablePool - %s",
147 talloc_free(tmp_ctx
);
151 (*new_pool
) = dc_pool
;
152 talloc_free(tmp_ctx
);
157 create a RID Set object for the specified DC
159 static int ridalloc_create_rid_set_ntds(struct ldb_module
*module
, TALLOC_CTX
*mem_ctx
,
160 struct ldb_dn
*rid_manager_dn
,
161 struct ldb_dn
*ntds_dn
, struct ldb_dn
**dn
)
163 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
164 struct ldb_dn
*server_dn
, *machine_dn
, *rid_set_dn
;
167 struct ldb_message
*msg
;
168 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
173 find the machine object for the DC
174 construct the RID Set DN
175 load rIDAvailablePool to find next available set
176 modify RID Manager object to update rIDAvailablePool
177 add the RID Set object
178 link to the RID Set object in machine object
181 server_dn
= ldb_dn_get_parent(tmp_ctx
, ntds_dn
);
183 talloc_free(tmp_ctx
);
184 return ldb_module_oom(module
);
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
);
195 rid_set_dn
= ldb_dn_copy(tmp_ctx
, machine_dn
);
196 if (rid_set_dn
== NULL
) {
197 talloc_free(tmp_ctx
);
198 return ldb_module_oom(module
);
201 if (! ldb_dn_add_child_fmt(rid_set_dn
, "CN=RID Set")) {
202 talloc_free(tmp_ctx
);
203 return ldb_module_oom(module
);
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
);
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
);
222 ret
= ldb_msg_add_fmt(msg
, "rIDAllocationPool", "%llu", (unsigned long long)dc_pool
);
223 if (ret
!= LDB_SUCCESS
) {
224 talloc_free(tmp_ctx
);
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
);
234 ret
= ldb_msg_add_fmt(msg
, "rIDUsedPool", "0");
235 if (ret
!= LDB_SUCCESS
) {
236 talloc_free(tmp_ctx
);
239 ret
= ldb_msg_add_fmt(msg
, "rIDNextRID", "0");
240 if (ret
!= LDB_SUCCESS
) {
241 talloc_free(tmp_ctx
);
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
),
253 talloc_free(tmp_ctx
);
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
);
266 msg
->elements
[0].flags
= LDB_FLAG_MOD_ADD
;
268 ret
= dsdb_module_modify(module
, msg
, DSDB_FLAG_NEXT_MODULE
);
269 if (ret
!= LDB_SUCCESS
) {
270 ldb_asprintf_errstring(ldb
, "Failed to add rIDSetReferences to %s - %s",
271 ldb_dn_get_linearized(msg
->dn
),
273 talloc_free(tmp_ctx
);
277 (*dn
) = talloc_steal(mem_ctx
, rid_set_dn
);
279 talloc_free(tmp_ctx
);
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
,
290 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
291 struct ldb_dn
*rid_manager_dn
, *fsmo_role_dn
;
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",
300 talloc_free(tmp_ctx
);
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",
309 talloc_free(tmp_ctx
);
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
);
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
);
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
);
345 server_dn
= ldb_dn_get_parent(tmp_ctx
, ntds_dn
);
347 talloc_free(tmp_ctx
);
348 return ldb_module_oom(module
);
351 ret
= dsdb_module_reference_dn(module
, tmp_ctx
, server_dn
, "serverReference", &machine_dn
);
352 if (ret
!= LDB_SUCCESS
) {
353 ldb_asprintf_errstring(ldb
, "Failed to find serverReference in %s - %s",
354 ldb_dn_get_linearized(server_dn
), ldb_errstring(ldb
));
355 talloc_free(tmp_ctx
);
359 ret
= dsdb_module_reference_dn(module
, tmp_ctx
, machine_dn
, "rIDSetReferences", &rid_set_dn
);
360 if (ret
!= LDB_SUCCESS
) {
361 ldb_asprintf_errstring(ldb
, "Failed to find rIDSetReferences in %s - %s",
362 ldb_dn_get_linearized(machine_dn
), ldb_errstring(ldb
));
363 talloc_free(tmp_ctx
);
367 ret
= dsdb_module_set_integer(module
, rid_set_dn
, "rIDAllocationPool", *new_pool
);
368 if (ret
!= LDB_SUCCESS
) {
369 ldb_asprintf_errstring(ldb
, "Failed to modify RID Set object %s - %s",
370 ldb_dn_get_linearized(rid_set_dn
), ldb_errstring(ldb
));
371 talloc_free(tmp_ctx
);
375 talloc_free(tmp_ctx
);
381 get a new RID pool for ourselves
382 also returns the first rid for the new pool
384 static int ridalloc_refresh_own_pool(struct ldb_module
*module
, uint64_t *new_pool
)
386 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
387 struct ldb_dn
*rid_manager_dn
, *fsmo_role_dn
;
389 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
391 /* work out who is the RID Manager */
392 ret
= dsdb_module_rid_manager_dn(module
, tmp_ctx
, &rid_manager_dn
);
393 if (ret
!= LDB_SUCCESS
) {
394 ldb_asprintf_errstring(ldb
, "Failed to find RID Manager object - %s",
396 talloc_free(tmp_ctx
);
400 /* find the DN of the RID Manager */
401 ret
= dsdb_module_reference_dn(module
, tmp_ctx
, rid_manager_dn
, "fSMORoleOwner", &fsmo_role_dn
);
402 if (ret
!= LDB_SUCCESS
) {
403 ldb_asprintf_errstring(ldb
, "Failed to find fSMORoleOwner in RID Manager object - %s",
405 talloc_free(tmp_ctx
);
409 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb
), fsmo_role_dn
) != 0) {
410 ridalloc_poke_rid_manager(module
);
411 ldb_asprintf_errstring(ldb
, "Remote RID Set allocation needs refresh");
412 talloc_free(tmp_ctx
);
413 return LDB_ERR_UNWILLING_TO_PERFORM
;
416 ret
= ridalloc_refresh_rid_set_ntds(module
, rid_manager_dn
, fsmo_role_dn
, new_pool
);
417 talloc_free(tmp_ctx
);
422 /* allocate a RID using our RID Set
423 If we run out of RIDs then allocate a new pool
424 either locally or by contacting the RID Manager
426 int ridalloc_allocate_rid(struct ldb_module
*module
, uint32_t *rid
)
428 struct ldb_context
*ldb
;
429 static const char * const attrs
[] = { "rIDAllocationPool", "rIDPreviousAllocationPool",
430 "rIDNextRID" , "rIDUsedPool", NULL
};
432 struct ldb_dn
*rid_set_dn
;
433 struct ldb_result
*res
;
434 uint64_t alloc_pool
, prev_alloc_pool
;
435 uint32_t prev_alloc_pool_lo
, prev_alloc_pool_hi
;
436 uint32_t rid_used_pool
;
438 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
441 ldb
= ldb_module_get_ctx(module
);
443 ret
= samdb_rid_set_dn(ldb
, tmp_ctx
, &rid_set_dn
);
444 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
445 ret
= ridalloc_create_own_rid_set(module
, tmp_ctx
, &rid_set_dn
);
447 if (ret
!= LDB_SUCCESS
) {
448 ldb_asprintf_errstring(ldb
, __location__
": No RID Set DN - %s",
450 talloc_free(tmp_ctx
);
454 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
, rid_set_dn
,
455 attrs
, DSDB_FLAG_NEXT_MODULE
);
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
);
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
);
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
);
489 prev_alloc_pool
= alloc_pool
;
490 prev_alloc_pool_lo
= prev_alloc_pool
& 0xFFFFFFFF;
491 prev_alloc_pool_hi
= prev_alloc_pool
>> 32;
494 * update the rIDUsedPool attribute
496 * Note: w2k8r2 doesn't update this attribute,
497 * at least if it's itself the rid master.
499 ret
= dsdb_module_set_integer(module
, rid_set_dn
, "rIDUsedPool", rid_used_pool
+1);
500 if (ret
!= LDB_SUCCESS
) {
501 ldb_asprintf_errstring(ldb
, __location__
": Failed to update rIDUsedPool on %s - %s",
502 ldb_dn_get_linearized(rid_set_dn
), ldb_errstring(ldb
));
503 talloc_free(tmp_ctx
);
507 (*rid
) = prev_alloc_pool_lo
;
510 /* see if we are still out of RIDs, and if so then ask
511 the RID Manager to give us more */
512 if (prev_rid
>= prev_alloc_pool_hi
) {
514 ret
= ridalloc_refresh_own_pool(module
, &new_pool
);
515 if (ret
!= LDB_SUCCESS
) {
516 talloc_free(tmp_ctx
);
519 ret
= dsdb_module_constrainted_update_integer(module
, rid_set_dn
, "rIDPreviousAllocationPool",
520 prev_alloc_pool
, new_pool
);
521 if (ret
!= LDB_SUCCESS
) {
522 ldb_asprintf_errstring(ldb
, __location__
": Failed to update rIDPreviousAllocationPool on %s - %s",
523 ldb_dn_get_linearized(rid_set_dn
), ldb_errstring(ldb
));
524 talloc_free(tmp_ctx
);
527 prev_alloc_pool
= new_pool
;
528 prev_alloc_pool_lo
= prev_alloc_pool
& 0xFFFFFFFF;
529 prev_alloc_pool_hi
= prev_alloc_pool
>> 32;
530 (*rid
) = prev_alloc_pool_lo
;
532 /* despite the name, rIDNextRID is the value of the last user
533 * added by this DC, not the next available RID */
535 (*rid
) = prev_rid
+ 1;
539 if (*rid
< prev_alloc_pool_lo
|| *rid
> prev_alloc_pool_hi
) {
540 ldb_asprintf_errstring(ldb
, __location__
": Bad rid chosen %u from range %u-%u",
541 (unsigned)*rid
, (unsigned)prev_alloc_pool_lo
,
542 (unsigned)prev_alloc_pool_hi
);
543 talloc_free(tmp_ctx
);
544 return LDB_ERR_OPERATIONS_ERROR
;
547 /* now modify the RID Set to use up this RID using a
548 * constrained delete/add if possible */
550 ret
= dsdb_module_set_integer(module
, rid_set_dn
, "rIDNextRID", *rid
);
552 ret
= dsdb_module_constrainted_update_integer(module
, rid_set_dn
, "rIDNextRID", prev_rid
, *rid
);
555 /* if we are half-exhausted then ask the repl task to start
556 * getting another one */
557 if (*rid
> (prev_alloc_pool_hi
+ prev_alloc_pool_lo
)/2) {
558 ridalloc_poke_rid_manager(module
);
561 talloc_free(tmp_ctx
);
568 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
570 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module
*module
, struct dsdb_fsmo_extended_op
*exop
)
572 struct ldb_dn
*ntds_dn
, *server_dn
, *machine_dn
, *rid_set_dn
;
573 struct ldb_dn
*rid_manager_dn
;
574 TALLOC_CTX
*tmp_ctx
= talloc_new(module
);
576 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
579 ret
= dsdb_module_dn_by_guid(module
, tmp_ctx
, &exop
->destination_dsa_guid
, &ntds_dn
);
580 if (ret
!= LDB_SUCCESS
) {
581 ldb_asprintf_errstring(ldb
, __location__
": Unable to find NTDS object for guid %s - %s\n",
582 GUID_string(tmp_ctx
, &exop
->destination_dsa_guid
), ldb_errstring(ldb
));
583 talloc_free(tmp_ctx
);
587 server_dn
= ldb_dn_get_parent(tmp_ctx
, ntds_dn
);
589 talloc_free(tmp_ctx
);
590 return ldb_module_oom(module
);
593 ret
= dsdb_module_reference_dn(module
, tmp_ctx
, server_dn
, "serverReference", &machine_dn
);
594 if (ret
!= LDB_SUCCESS
) {
595 ldb_asprintf_errstring(ldb
, __location__
": Failed to find serverReference in %s - %s",
596 ldb_dn_get_linearized(server_dn
), ldb_errstring(ldb
));
597 talloc_free(tmp_ctx
);
602 ret
= dsdb_module_rid_manager_dn(module
, tmp_ctx
, &rid_manager_dn
);
603 if (ret
!= LDB_SUCCESS
) {
604 ldb_asprintf_errstring(ldb
, __location__
": Failed to find RID Manager object - %s",
606 talloc_free(tmp_ctx
);
610 ret
= dsdb_module_reference_dn(module
, tmp_ctx
, machine_dn
, "rIDSetReferences", &rid_set_dn
);
611 if (ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
612 ret
= ridalloc_create_rid_set_ntds(module
, tmp_ctx
, rid_manager_dn
, ntds_dn
, &rid_set_dn
);
613 talloc_free(tmp_ctx
);
617 if (ret
!= LDB_SUCCESS
) {
618 ldb_asprintf_errstring(ldb
, "Failed to find rIDSetReferences in %s - %s",
619 ldb_dn_get_linearized(machine_dn
), ldb_errstring(ldb
));
620 talloc_free(tmp_ctx
);
624 if (exop
->fsmo_info
!= 0) {
625 const char *attrs
[] = { "rIDAllocationPool", NULL
};
626 struct ldb_result
*res
;
629 ret
= dsdb_module_search_dn(module
, tmp_ctx
, &res
, rid_set_dn
,
630 attrs
, DSDB_FLAG_NEXT_MODULE
);
631 if (ret
!= LDB_SUCCESS
) {
632 ldb_asprintf_errstring(ldb
, __location__
": No RID Set %s",
633 ldb_dn_get_linearized(rid_set_dn
));
634 talloc_free(tmp_ctx
);
638 alloc_pool
= ldb_msg_find_attr_as_uint64(res
->msgs
[0], "rIDAllocationPool", 0);
639 if (alloc_pool
!= exop
->fsmo_info
) {
640 /* it has already been updated */
641 DEBUG(2,(__location__
": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
642 (unsigned long long)exop
->fsmo_info
,
643 (unsigned long long)alloc_pool
));
644 talloc_free(tmp_ctx
);
649 ret
= ridalloc_refresh_rid_set_ntds(module
, rid_manager_dn
, ntds_dn
, &new_pool
);
650 talloc_free(tmp_ctx
);