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);