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, lpcfg_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 */
97 static const char * const ridalloc_ridset_attrs[] = {
99 "rIDPreviousAllocationPool",
105 struct ridalloc_ridset_values {
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;
129 #define SETUP_PTRS(field, optr, nptr, max) do { \
132 if (o->field == max) { \
135 if (n->field == max) { \
138 if (o->field == n->field) { \
144 SETUP_PTRS(alloc_pool, o64, n64, UINT64_MAX);
145 ret = dsdb_msg_constrainted_update_uint64(module, msg,
148 if (ret != LDB_SUCCESS) {
152 SETUP_PTRS(prev_pool, o64, n64, UINT64_MAX);
153 ret = dsdb_msg_constrainted_update_uint64(module, msg,
154 "rIDPreviousAllocationPool",
156 if (ret != LDB_SUCCESS) {
160 SETUP_PTRS(next_rid, o32, n32, UINT32_MAX);
161 ret = dsdb_msg_constrainted_update_uint32(module, msg,
164 if (ret != LDB_SUCCESS) {
168 SETUP_PTRS(used_pool, o32, n32, UINT32_MAX);
169 ret = dsdb_msg_constrainted_update_uint32(module, msg,
172 if (ret != 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,
184 struct ldb_request *parent)
187 TALLOC_CTX *tmp_ctx = talloc_new(module);
188 const char *attrs[] = { "rIDAvailablePool", NULL };
189 uint64_t rid_pool, new_rid_pool, dc_pool;
190 uint32_t rid_pool_lo, rid_pool_hi;
191 struct ldb_result *res;
192 struct ldb_context *ldb = ldb_module_get_ctx(module);
193 const unsigned alloc_size = 500;
195 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn,
196 attrs, DSDB_FLAG_NEXT_MODULE, parent);
197 if (ret != LDB_SUCCESS) {
198 ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
199 ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
200 talloc_free(tmp_ctx);
204 rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
205 rid_pool_lo = rid_pool & 0xFFFFFFFF;
206 rid_pool_hi = rid_pool >> 32;
207 if (rid_pool_lo >= rid_pool_hi) {
208 ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
209 rid_pool_lo, rid_pool_hi);
210 talloc_free(tmp_ctx);
214 /* lower part of new pool is the low part of the rIDAvailablePool */
215 dc_pool = rid_pool_lo;
217 /* allocate 500 RIDs to this DC */
218 rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
220 /* work out upper part of new pool */
221 dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
223 /* and new rIDAvailablePool value */
224 new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
226 ret = dsdb_module_constrainted_update_uint64(module, rid_manager_dn, "rIDAvailablePool",
227 &rid_pool, &new_rid_pool, parent);
228 if (ret != LDB_SUCCESS) {
229 ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
231 talloc_free(tmp_ctx);
235 (*new_pool) = dc_pool;
236 talloc_free(tmp_ctx);
241 create a RID Set object for the specified DC
243 static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
244 struct ldb_dn *rid_manager_dn,
245 struct ldb_dn *ntds_dn, struct ldb_dn **dn,
246 struct ldb_request *parent)
248 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
249 struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
251 struct ldb_message *msg;
252 struct ldb_context *ldb = ldb_module_get_ctx(module);
253 static const struct ridalloc_ridset_values o = {
254 .alloc_pool = UINT64_MAX,
255 .prev_pool = UINT64_MAX,
256 .next_rid = UINT32_MAX,
257 .used_pool = UINT32_MAX,
259 struct ridalloc_ridset_values n = {
269 find the machine object for the DC
270 construct the RID Set DN
271 load rIDAvailablePool to find next available set
272 modify RID Manager object to update rIDAvailablePool
273 add the RID Set object
274 link to the RID Set object in machine object
277 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
279 talloc_free(tmp_ctx);
280 return ldb_module_oom(module);
283 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
284 if (ret != LDB_SUCCESS) {
285 ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
286 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
287 talloc_free(tmp_ctx);
291 rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
292 if (rid_set_dn == NULL) {
293 talloc_free(tmp_ctx);
294 return ldb_module_oom(module);
297 if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
298 talloc_free(tmp_ctx);
299 return ldb_module_oom(module);
302 /* grab a pool from the RID Manager object */
303 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent);
304 if (ret != LDB_SUCCESS) {
305 talloc_free(tmp_ctx);
309 /* create the RID Set object */
310 msg = ldb_msg_new(tmp_ctx);
311 msg->dn = rid_set_dn;
313 ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
314 if (ret != LDB_SUCCESS) {
315 talloc_free(tmp_ctx);
319 ret = ridalloc_set_ridset_values(module, msg, &o, &n);
320 if (ret != LDB_SUCCESS) {
321 talloc_free(tmp_ctx);
325 /* we need this to go all the way to the top of the module
326 * stack, as we need all the extra attributes added (including
327 * complex ones like ntsecuritydescriptor) */
328 ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent);
329 if (ret != LDB_SUCCESS) {
330 ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
331 ldb_dn_get_linearized(msg->dn),
333 talloc_free(tmp_ctx);
337 /* add the rIDSetReferences link */
338 msg = ldb_msg_new(tmp_ctx);
339 msg->dn = machine_dn;
341 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
342 if (ret != LDB_SUCCESS) {
343 talloc_free(tmp_ctx);
346 msg->elements[0].flags = LDB_FLAG_MOD_ADD;
348 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
349 if (ret != LDB_SUCCESS) {
350 ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
351 ldb_dn_get_linearized(msg->dn),
353 talloc_free(tmp_ctx);
357 (*dn) = talloc_steal(mem_ctx, rid_set_dn);
359 talloc_free(tmp_ctx);
365 create a RID Set object for this DC
367 static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
368 struct ldb_dn **dn, struct ldb_request *parent)
370 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
371 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
373 struct ldb_context *ldb = ldb_module_get_ctx(module);
375 /* work out who is the RID Manager */
376 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
377 if (ret != LDB_SUCCESS) {
378 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
380 talloc_free(tmp_ctx);
384 /* find the DN of the RID Manager */
385 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
386 if (ret != LDB_SUCCESS) {
387 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
389 talloc_free(tmp_ctx);
393 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
394 ridalloc_poke_rid_manager(module);
395 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
396 talloc_free(tmp_ctx);
397 return LDB_ERR_UNWILLING_TO_PERFORM;
400 ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent);
401 talloc_free(tmp_ctx);
406 get a new RID pool for ourselves
407 also returns the first rid for the new pool
409 static int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent)
411 TALLOC_CTX *tmp_ctx = talloc_new(module);
412 struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
414 struct ldb_context *ldb = ldb_module_get_ctx(module);
416 /* work out who is the RID Manager */
417 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
418 if (ret != LDB_SUCCESS) {
419 ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
421 talloc_free(tmp_ctx);
425 /* find the DN of the RID Manager */
426 ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
427 if (ret != LDB_SUCCESS) {
428 ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
430 talloc_free(tmp_ctx);
434 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
435 ridalloc_poke_rid_manager(module);
436 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
437 talloc_free(tmp_ctx);
438 return LDB_ERR_UNWILLING_TO_PERFORM;
441 /* grab a pool from the RID Manager object */
442 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool, parent);
443 if (ret != LDB_SUCCESS) {
444 talloc_free(tmp_ctx);
448 talloc_free(tmp_ctx);
453 /* allocate a RID using our RID Set
454 If we run out of RIDs then allocate a new pool
455 either locally or by contacting the RID Manager
457 int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_request *parent)
459 struct ldb_context *ldb;
461 struct ldb_dn *rid_set_dn;
462 struct ldb_result *res;
463 struct ldb_message *msg;
464 struct ridalloc_ridset_values oridset;
465 struct ridalloc_ridset_values nridset;
466 uint32_t prev_pool_lo, prev_pool_hi;
467 TALLOC_CTX *tmp_ctx = talloc_new(module);
470 ldb = ldb_module_get_ctx(module);
472 ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
473 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
474 ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn, parent);
476 if (ret != LDB_SUCCESS) {
477 ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
479 talloc_free(tmp_ctx);
483 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
484 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
485 if (ret != LDB_SUCCESS) {
486 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
487 ldb_dn_get_linearized(rid_set_dn));
488 talloc_free(tmp_ctx);
492 ridalloc_get_ridset_values(res->msgs[0], &oridset);
493 if (oridset.alloc_pool == UINT64_MAX) {
494 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
495 ldb_dn_get_linearized(rid_set_dn));
496 talloc_free(tmp_ctx);
497 return LDB_ERR_OPERATIONS_ERROR;
503 * If we never used a pool, setup out first pool
505 if (nridset.prev_pool == UINT64_MAX ||
506 nridset.next_rid == UINT32_MAX) {
507 nridset.prev_pool = nridset.alloc_pool;
508 nridset.next_rid = nridset.prev_pool & 0xFFFFFFFF;
512 * Now check if our current pool is still usable
514 nridset.next_rid += 1;
515 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
516 prev_pool_hi = nridset.prev_pool >> 32;
517 if (nridset.next_rid > prev_pool_hi) {
519 * We need a new pool, check if we already have a new one
520 * Otherwise we need to get a new pool.
522 if (nridset.alloc_pool == nridset.prev_pool) {
524 * if we are the RID Manager,
525 * we can get a new pool localy.
526 * Otherwise we fail the operation and
527 * ask async for a new pool.
529 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
530 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
531 ridalloc_poke_rid_manager(module);
532 talloc_free(tmp_ctx);
535 if (ret != LDB_SUCCESS) {
536 talloc_free(tmp_ctx);
542 * increment the rIDUsedPool attribute
544 * Note: w2k8r2 doesn't update this attribute,
545 * at least if it's itself the rid master.
547 nridset.used_pool += 1;
549 /* now use the new pool */
550 nridset.prev_pool = nridset.alloc_pool;
551 prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
552 prev_pool_hi = nridset.prev_pool >> 32;
553 nridset.next_rid = prev_pool_lo;
556 if (nridset.next_rid < prev_pool_lo || nridset.next_rid > prev_pool_hi) {
557 ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
558 (unsigned)nridset.next_rid,
559 (unsigned)prev_pool_lo,
560 (unsigned)prev_pool_hi);
561 talloc_free(tmp_ctx);
562 return LDB_ERR_OPERATIONS_ERROR;
566 * if we are half-exhausted then try to get a new pool.
568 if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2) {
570 * if we are the RID Manager,
571 * we can get a new pool localy.
572 * Otherwise we fail the operation and
573 * ask async for a new pool.
575 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
576 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
577 ridalloc_poke_rid_manager(module);
580 if (ret != LDB_SUCCESS) {
581 talloc_free(tmp_ctx);
589 msg = ldb_msg_new(tmp_ctx);
591 return ldb_module_oom(module);
593 msg->dn = rid_set_dn;
595 ret = ridalloc_set_ridset_values(module, msg,
597 if (ret != LDB_SUCCESS) {
598 talloc_free(tmp_ctx);
602 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
603 if (ret != LDB_SUCCESS) {
604 talloc_free(tmp_ctx);
608 talloc_free(tmp_ctx);
609 *rid = nridset.next_rid;
615 called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
617 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop,
618 struct ldb_request *parent)
620 struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
621 struct ldb_dn *rid_manager_dn;
622 TALLOC_CTX *tmp_ctx = talloc_new(module);
624 struct ldb_context *ldb = ldb_module_get_ctx(module);
625 struct ldb_result *res;
626 struct ldb_message *msg;
627 struct ridalloc_ridset_values oridset, nridset;
629 ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn, parent);
630 if (ret != LDB_SUCCESS) {
631 ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
632 GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
633 talloc_free(tmp_ctx);
637 server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
639 talloc_free(tmp_ctx);
640 return ldb_module_oom(module);
643 ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
644 if (ret != LDB_SUCCESS) {
645 ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
646 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
647 talloc_free(tmp_ctx);
651 ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
652 if (ret != LDB_SUCCESS) {
653 ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
655 talloc_free(tmp_ctx);
659 ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn, parent);
660 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
661 ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn, parent);
662 talloc_free(tmp_ctx);
666 if (ret != LDB_SUCCESS) {
667 ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
668 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
669 talloc_free(tmp_ctx);
673 ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
674 ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
675 if (ret != LDB_SUCCESS) {
676 ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
677 ldb_dn_get_linearized(rid_set_dn));
678 talloc_free(tmp_ctx);
682 ridalloc_get_ridset_values(res->msgs[0], &oridset);
683 if (oridset.alloc_pool == UINT64_MAX) {
684 ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
685 ldb_dn_get_linearized(rid_set_dn));
686 talloc_free(tmp_ctx);
687 return LDB_ERR_OPERATIONS_ERROR;
692 if (exop->fsmo_info != 0) {
694 if (nridset.alloc_pool != exop->fsmo_info) {
695 /* it has already been updated */
696 DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
697 (unsigned long long)exop->fsmo_info,
698 (unsigned long long)nridset.alloc_pool));
699 talloc_free(tmp_ctx);
704 /* grab a pool from the RID Manager object */
705 ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &nridset.alloc_pool, parent);
706 if (ret != LDB_SUCCESS) {
707 talloc_free(tmp_ctx);
714 msg = ldb_msg_new(tmp_ctx);
716 return ldb_module_oom(module);
718 msg->dn = rid_set_dn;
720 ret = ridalloc_set_ridset_values(module, msg,
722 if (ret != LDB_SUCCESS) {
723 talloc_free(tmp_ctx);
727 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
728 if (ret != LDB_SUCCESS) {
729 ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
730 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
731 talloc_free(tmp_ctx);
735 talloc_free(tmp_ctx);