46
47
struct drsuapi_DsBind bind_r;
49
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq);
50
static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq);
51
struct composite_context *dreplsrv_out_drsuapi_send(struct dreplsrv_out_connection *conn)
52
struct tevent_req *dreplsrv_out_drsuapi_send(TALLOC_CTX *mem_ctx,
53
struct tevent_context *ev,
54
struct dreplsrv_out_connection *conn)
53
struct composite_context *c;
56
struct tevent_req *req;
57
struct dreplsrv_out_drsuapi_state *state;
54
58
struct composite_context *creq;
55
struct dreplsrv_out_drsuapi_state *st;
57
c = composite_create(conn, conn->service->task->event_ctx);
58
if (c == NULL) return NULL;
60
st = talloc_zero(c, struct dreplsrv_out_drsuapi_state);
61
if (composite_nomem(st, c)) return c;
67
st->drsuapi = conn->drsuapi;
69
if (st->drsuapi && !st->drsuapi->pipe->conn->dead) {
72
} else if (st->drsuapi && st->drsuapi->pipe->conn->dead) {
73
talloc_free(st->drsuapi);
60
req = tevent_req_create(mem_ctx, &state,
61
struct dreplsrv_out_drsuapi_state);
68
state->drsuapi = conn->drsuapi;
70
if (state->drsuapi && !state->drsuapi->pipe->conn->dead) {
72
return tevent_req_post(req, ev);
75
if (state->drsuapi && state->drsuapi->pipe->conn->dead) {
76
talloc_free(state->drsuapi);
74
77
conn->drsuapi = NULL;
77
st->drsuapi = talloc_zero(st, struct dreplsrv_drsuapi_connection);
78
if (composite_nomem(st->drsuapi, c)) return c;
80
state->drsuapi = talloc_zero(state, struct dreplsrv_drsuapi_connection);
81
if (tevent_req_nomem(state->drsuapi, req)) {
82
return tevent_req_post(req, ev);
80
creq = dcerpc_pipe_connect_b_send(st, conn->binding, &ndr_table_drsuapi,
85
creq = dcerpc_pipe_connect_b_send(state, conn->binding, &ndr_table_drsuapi,
81
86
conn->service->system_session_info->credentials,
82
c->event_ctx, conn->service->task->lp_ctx);
83
composite_continue(c, creq, dreplsrv_out_drsuapi_connect_recv, st);
88
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st);
90
static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq)
92
struct dreplsrv_out_drsuapi_state *st = talloc_get_type(creq->async.private_data,
93
struct dreplsrv_out_drsuapi_state);
94
struct composite_context *c = st->creq;
96
c->status = dcerpc_pipe_connect_b_recv(creq, st->drsuapi, &st->drsuapi->pipe);
97
if (!composite_is_ok(c)) return;
99
c->status = gensec_session_key(st->drsuapi->pipe->conn->security_state.generic_state,
100
&st->drsuapi->gensec_skey);
101
if (!composite_is_ok(c)) return;
103
dreplsrv_out_drsuapi_bind_send(st);
106
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req);
108
static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st)
110
struct composite_context *c = st->creq;
111
struct rpc_request *req;
113
st->bind_info_ctr.length = 28;
114
st->bind_info_ctr.info.info28 = st->conn->service->bind_info28;
116
st->bind_r.in.bind_guid = &st->conn->service->ntds_guid;
117
st->bind_r.in.bind_info = &st->bind_info_ctr;
118
st->bind_r.out.bind_handle = &st->drsuapi->bind_handle;
120
req = dcerpc_drsuapi_DsBind_send(st->drsuapi->pipe, st, &st->bind_r);
121
composite_continue_rpc(c, req, dreplsrv_out_drsuapi_bind_recv, st);
124
static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req)
126
struct dreplsrv_out_drsuapi_state *st = talloc_get_type(req->async.private_data,
127
struct dreplsrv_out_drsuapi_state);
128
struct composite_context *c = st->creq;
130
c->status = dcerpc_ndr_request_recv(req);
131
if (!composite_is_ok(c)) return;
133
if (!W_ERROR_IS_OK(st->bind_r.out.result)) {
134
composite_error(c, werror_to_ntstatus(st->bind_r.out.result));
138
ZERO_STRUCT(st->drsuapi->remote_info28);
139
if (st->bind_r.out.bind_info) {
140
switch (st->bind_r.out.bind_info->length) {
87
ev, conn->service->task->lp_ctx);
88
if (tevent_req_nomem(creq, req)) {
89
return tevent_req_post(req, ev);
91
composite_continue(NULL, creq, dreplsrv_out_drsuapi_connect_done, req);
96
static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq);
98
static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq)
100
struct tevent_req *req = talloc_get_type(creq->async.private_data,
102
struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
103
struct dreplsrv_out_drsuapi_state);
105
struct tevent_req *subreq;
107
status = dcerpc_pipe_connect_b_recv(creq,
109
&state->drsuapi->pipe);
110
if (tevent_req_nterror(req, status)) {
114
state->drsuapi->drsuapi_handle = state->drsuapi->pipe->binding_handle;
116
status = gensec_session_key(state->drsuapi->pipe->conn->security_state.generic_state,
117
&state->drsuapi->gensec_skey);
118
if (tevent_req_nterror(req, status)) {
122
state->bind_info_ctr.length = 28;
123
state->bind_info_ctr.info.info28 = state->conn->service->bind_info28;
125
state->bind_r.in.bind_guid = &state->conn->service->ntds_guid;
126
state->bind_r.in.bind_info = &state->bind_info_ctr;
127
state->bind_r.out.bind_handle = &state->drsuapi->bind_handle;
129
subreq = dcerpc_drsuapi_DsBind_r_send(state,
131
state->drsuapi->drsuapi_handle,
133
if (tevent_req_nomem(subreq, req)) {
136
tevent_req_set_callback(subreq, dreplsrv_out_drsuapi_bind_done, req);
139
static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq)
141
struct tevent_req *req = tevent_req_callback_data(subreq,
143
struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
144
struct dreplsrv_out_drsuapi_state);
147
status = dcerpc_drsuapi_DsBind_r_recv(subreq, state);
149
if (tevent_req_nterror(req, status)) {
153
if (!W_ERROR_IS_OK(state->bind_r.out.result)) {
154
status = werror_to_ntstatus(state->bind_r.out.result);
155
tevent_req_nterror(req, status);
159
ZERO_STRUCT(state->drsuapi->remote_info28);
160
if (state->bind_r.out.bind_info) {
161
struct drsuapi_DsBindInfo28 *info28;
162
info28 = &state->drsuapi->remote_info28;
164
switch (state->bind_r.out.bind_info->length) {
142
166
struct drsuapi_DsBindInfo24 *info24;
143
info24 = &st->bind_r.out.bind_info->info.info24;
144
st->drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
145
st->drsuapi->remote_info28.site_guid = info24->site_guid;
146
st->drsuapi->remote_info28.pid = info24->pid;
147
st->drsuapi->remote_info28.repl_epoch = 0;
167
info24 = &state->bind_r.out.bind_info->info.info24;
169
info28->supported_extensions = info24->supported_extensions;
170
info28->site_guid = info24->site_guid;
171
info28->pid = info24->pid;
172
info28->repl_epoch = 0;
151
176
struct drsuapi_DsBindInfo48 *info48;
152
info48 = &st->bind_r.out.bind_info->info.info48;
153
st->drsuapi->remote_info28.supported_extensions = info48->supported_extensions;
154
st->drsuapi->remote_info28.site_guid = info48->site_guid;
155
st->drsuapi->remote_info28.pid = info48->pid;
156
st->drsuapi->remote_info28.repl_epoch = info48->repl_epoch;
177
info48 = &state->bind_r.out.bind_info->info.info48;
179
info28->supported_extensions = info48->supported_extensions;
180
info28->site_guid = info48->site_guid;
181
info28->pid = info48->pid;
182
info28->repl_epoch = info48->repl_epoch;
160
st->drsuapi->remote_info28 = st->bind_r.out.bind_info->info.info28;
186
*info28 = state->bind_r.out.bind_info->info.info28;
191
tevent_req_done(req);
168
NTSTATUS dreplsrv_out_drsuapi_recv(struct composite_context *c)
194
NTSTATUS dreplsrv_out_drsuapi_recv(struct tevent_req *req)
196
struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req,
197
struct dreplsrv_out_drsuapi_state);
171
struct dreplsrv_out_drsuapi_state *st = talloc_get_type(c->private_data,
172
struct dreplsrv_out_drsuapi_state);
174
status = composite_wait(c);
176
if (NT_STATUS_IS_OK(status)) {
177
st->conn->drsuapi = talloc_steal(st->conn, st->drsuapi);
200
if (tevent_req_is_nterror(req, &status)) {
201
tevent_req_received(req);
205
state->conn->drsuapi = talloc_move(state->conn, &state->drsuapi);
207
tevent_req_received(req);
184
211
struct dreplsrv_op_pull_source_state {
185
struct composite_context *creq;
212
struct tevent_context *ev;
187
213
struct dreplsrv_out_operation *op;
189
struct dreplsrv_drsuapi_connection *drsuapi;
194
struct drsuapi_DsGetNCChangesCtr1 *ctr1;
195
struct drsuapi_DsGetNCChangesCtr6 *ctr6;
214
void *ndr_struct_ptr;
198
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq);
200
struct composite_context *dreplsrv_op_pull_source_send(struct dreplsrv_out_operation *op)
202
struct composite_context *c;
203
struct composite_context *creq;
204
struct dreplsrv_op_pull_source_state *st;
206
c = composite_create(op, op->service->task->event_ctx);
207
if (c == NULL) return NULL;
209
st = talloc_zero(c, struct dreplsrv_op_pull_source_state);
210
if (composite_nomem(st, c)) return c;
215
creq = dreplsrv_out_drsuapi_send(op->source_dsa->conn);
216
composite_continue(c, creq, dreplsrv_op_pull_source_connect_recv, st);
221
static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st);
223
static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq)
225
struct dreplsrv_op_pull_source_state *st = talloc_get_type(creq->async.private_data,
226
struct dreplsrv_op_pull_source_state);
227
struct composite_context *c = st->creq;
229
c->status = dreplsrv_out_drsuapi_recv(creq);
230
if (!composite_is_ok(c)) return;
232
dreplsrv_op_pull_source_get_changes_send(st);
235
static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req);
237
static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st)
239
struct composite_context *c = st->creq;
240
struct repsFromTo1 *rf1 = st->op->source_dsa->repsFrom1;
241
struct dreplsrv_service *service = st->op->service;
242
struct dreplsrv_partition *partition = st->op->source_dsa->partition;
243
struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
244
struct rpc_request *req;
217
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq);
219
struct tevent_req *dreplsrv_op_pull_source_send(TALLOC_CTX *mem_ctx,
220
struct tevent_context *ev,
221
struct dreplsrv_out_operation *op)
223
struct tevent_req *req;
224
struct dreplsrv_op_pull_source_state *state;
225
struct tevent_req *subreq;
227
req = tevent_req_create(mem_ctx, &state,
228
struct dreplsrv_op_pull_source_state);
235
subreq = dreplsrv_out_drsuapi_send(state, ev, op->source_dsa->conn);
236
if (tevent_req_nomem(subreq, req)) {
237
return tevent_req_post(req, ev);
239
tevent_req_set_callback(subreq, dreplsrv_op_pull_source_connect_done, req);
244
static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req);
246
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq)
248
struct tevent_req *req = tevent_req_callback_data(subreq,
252
status = dreplsrv_out_drsuapi_recv(subreq);
254
if (tevent_req_nterror(req, status)) {
258
dreplsrv_op_pull_source_get_changes_trigger(req);
261
static void dreplsrv_op_pull_source_get_changes_done(struct tevent_req *subreq);
264
get a partial attribute set for a replication call
266
static NTSTATUS dreplsrv_get_rodc_partial_attribute_set(struct dreplsrv_service *service,
268
struct drsuapi_DsPartialAttributeSet **_pas,
271
struct drsuapi_DsPartialAttributeSet *pas;
272
struct dsdb_schema *schema;
275
pas = talloc_zero(mem_ctx, struct drsuapi_DsPartialAttributeSet);
276
NT_STATUS_HAVE_NO_MEMORY(pas);
278
schema = dsdb_get_schema(service->samdb, NULL);
281
pas->attids = talloc_array(pas, enum drsuapi_DsAttributeId, schema->num_attributes);
282
NT_STATUS_HAVE_NO_MEMORY_AND_FREE(pas->attids, pas);
284
for (i=0; i<schema->num_attributes; i++) {
285
struct dsdb_attribute *a;
286
a = schema->attributes_by_attributeID_id[i];
287
if (a->systemFlags & (DS_FLAG_ATTR_NOT_REPLICATED | DS_FLAG_ATTR_IS_CONSTRUCTED)) {
290
if (a->searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE) {
293
pas->attids[pas->num_attids] = dsdb_attribute_get_attid(a, for_schema);
301
convert from one udv format to the other
303
static WERROR udv_convert(TALLOC_CTX *mem_ctx,
304
const struct replUpToDateVectorCtr2 *udv,
305
struct drsuapi_DsReplicaCursorCtrEx *udv_ex)
310
udv_ex->reserved1 = 0;
311
udv_ex->reserved2 = 0;
312
udv_ex->count = udv->count;
313
udv_ex->cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, udv->count);
314
W_ERROR_HAVE_NO_MEMORY(udv_ex->cursors);
316
for (i=0; i<udv->count; i++) {
317
udv_ex->cursors[i].source_dsa_invocation_id = udv->cursors[i].source_dsa_invocation_id;
318
udv_ex->cursors[i].highest_usn = udv->cursors[i].highest_usn;
325
static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req)
327
struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
328
struct dreplsrv_op_pull_source_state);
329
struct repsFromTo1 *rf1 = state->op->source_dsa->repsFrom1;
330
struct dreplsrv_service *service = state->op->service;
331
struct dreplsrv_partition *partition = state->op->source_dsa->partition;
332
struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
245
333
struct drsuapi_DsGetNCChanges *r;
247
r = talloc(st, struct drsuapi_DsGetNCChanges);
248
if (composite_nomem(r, c)) return;
250
r->out.level_out = talloc(r, int32_t);
251
if (composite_nomem(r->out.level_out, c)) return;
334
struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector;
335
struct tevent_req *subreq;
336
struct drsuapi_DsPartialAttributeSet *pas = NULL;
338
uint32_t replica_flags;
340
r = talloc(state, struct drsuapi_DsGetNCChanges);
341
if (tevent_req_nomem(r, req)) {
345
r->out.level_out = talloc(r, uint32_t);
346
if (tevent_req_nomem(r->out.level_out, req)) {
252
349
r->in.req = talloc(r, union drsuapi_DsGetNCChangesRequest);
253
if (composite_nomem(r->in.req, c)) return;
350
if (tevent_req_nomem(r->in.req, req)) {
254
353
r->out.ctr = talloc(r, union drsuapi_DsGetNCChangesCtr);
255
if (composite_nomem(r->out.ctr, c)) return;
354
if (tevent_req_nomem(r->out.ctr, req)) {
358
if (partition->uptodatevector.count != 0 &&
359
partition->uptodatevector_ex.count == 0) {
361
werr = udv_convert(partition, &partition->uptodatevector, &partition->uptodatevector_ex);
362
if (!W_ERROR_IS_OK(werr)) {
363
DEBUG(0,(__location__ ": Failed to convert UDV for %s : %s\n",
364
ldb_dn_get_linearized(partition->dn), win_errstr(werr)));
368
if (partition->uptodatevector_ex.count == 0) {
369
uptodateness_vector = NULL;
371
uptodateness_vector = &partition->uptodatevector_ex;
374
replica_flags = rf1->replica_flags;
376
if (service->am_rodc) {
377
bool for_schema = false;
378
if (ldb_dn_compare_base(ldb_get_schema_basedn(service->samdb), partition->dn) == 0) {
382
status = dreplsrv_get_rodc_partial_attribute_set(service, r, &pas, for_schema);
383
if (!NT_STATUS_IS_OK(status)) {
384
DEBUG(0,(__location__ ": Failed to construct partial attribute set : %s\n", nt_errstr(status)));
387
if (state->op->extended_op == DRSUAPI_EXOP_REPL_SECRET) {
388
replica_flags &= ~DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING;
257
392
r->in.bind_handle = &drsuapi->bind_handle;
258
393
if (drsuapi->remote_info28.supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
277
412
r->in.req->req5.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
278
413
r->in.req->req5.naming_context = &partition->nc;
279
414
r->in.req->req5.highwatermark = rf1->highwatermark;
280
r->in.req->req5.uptodateness_vector = NULL;/*&partition->uptodatevector_ex;*/
281
r->in.req->req5.replica_flags = rf1->replica_flags;
415
r->in.req->req5.uptodateness_vector = uptodateness_vector;
416
r->in.req->req5.replica_flags = replica_flags;
282
417
r->in.req->req5.max_object_count = 133;
283
418
r->in.req->req5.max_ndr_size = 1336770;
284
r->in.req->req5.extended_op = DRSUAPI_EXOP_NONE;
285
r->in.req->req5.fsmo_info = 0;
288
req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi->pipe, r, r);
289
composite_continue_rpc(c, req, dreplsrv_op_pull_source_get_changes_recv, st);
419
r->in.req->req5.extended_op = state->op->extended_op;
420
r->in.req->req5.fsmo_info = state->op->fsmo_info;
424
NDR_PRINT_IN_DEBUG(drsuapi_DsGetNCChanges, r);
427
state->ndr_struct_ptr = r;
428
subreq = dcerpc_drsuapi_DsGetNCChanges_r_send(state,
430
drsuapi->drsuapi_handle,
432
if (tevent_req_nomem(subreq, req)) {
435
tevent_req_set_callback(subreq, dreplsrv_op_pull_source_get_changes_done, req);
292
static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st,
293
struct drsuapi_DsGetNCChanges *r,
295
struct drsuapi_DsGetNCChangesCtr1 *ctr1,
296
struct drsuapi_DsGetNCChangesCtr6 *ctr6);
438
static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req,
439
struct drsuapi_DsGetNCChanges *r,
441
struct drsuapi_DsGetNCChangesCtr1 *ctr1,
442
struct drsuapi_DsGetNCChangesCtr6 *ctr6);
298
static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req)
444
static void dreplsrv_op_pull_source_get_changes_done(struct tevent_req *subreq)
300
struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data,
301
struct dreplsrv_op_pull_source_state);
302
struct composite_context *c = st->creq;
303
struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
446
struct tevent_req *req = tevent_req_callback_data(subreq,
448
struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
449
struct dreplsrv_op_pull_source_state);
451
struct drsuapi_DsGetNCChanges *r = talloc_get_type(state->ndr_struct_ptr,
304
452
struct drsuapi_DsGetNCChanges);
305
453
uint32_t ctr_level = 0;
306
454
struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
307
455
struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
456
enum drsuapi_DsExtendedError extended_ret;
457
state->ndr_struct_ptr = NULL;
309
c->status = dcerpc_ndr_request_recv(req);
310
if (!composite_is_ok(c)) return;
459
status = dcerpc_drsuapi_DsGetNCChanges_r_recv(subreq, r);
461
if (tevent_req_nterror(req, status)) {
312
465
if (!W_ERROR_IS_OK(r->out.result)) {
313
composite_error(c, werror_to_ntstatus(r->out.result));
466
status = werror_to_ntstatus(r->out.result);
467
tevent_req_nterror(req, status);
439
674
we join the domain, but they quickly expire. We do it here
440
675
so we can use the already established DRSUAPI pipe
442
dreplsrv_update_refs_send(st);
445
WERROR dreplsrv_op_pull_source_recv(struct composite_context *c)
449
status = composite_wait(c);
452
return ntstatus_to_werror(status);
456
receive a UpdateRefs reply
458
static void dreplsrv_update_refs_recv(struct rpc_request *req)
460
struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data,
461
struct dreplsrv_op_pull_source_state);
462
struct composite_context *c = st->creq;
463
struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
464
struct drsuapi_DsReplicaUpdateRefs);
466
c->status = dcerpc_ndr_request_recv(req);
467
if (!composite_is_ok(c)) {
468
DEBUG(0,("UpdateRefs failed with %s\n",
469
nt_errstr(c->status)));
473
if (!W_ERROR_IS_OK(r->out.result)) {
474
DEBUG(0,("UpdateRefs failed with %s for %s %s\n",
475
win_errstr(r->out.result),
476
r->in.req.req1.dest_dsa_dns_name,
477
r->in.req.req1.naming_context->dn));
478
composite_error(c, werror_to_ntstatus(r->out.result));
482
DEBUG(4,("UpdateRefs OK for %s %s\n",
483
r->in.req.req1.dest_dsa_dns_name,
484
r->in.req.req1.naming_context->dn));
677
dreplsrv_update_refs_trigger(req);
680
static void dreplsrv_update_refs_done(struct tevent_req *subreq);
490
683
send a UpdateRefs request to refresh our repsTo record on the server
492
static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st)
685
static void dreplsrv_update_refs_trigger(struct tevent_req *req)
494
struct composite_context *c = st->creq;
495
struct dreplsrv_service *service = st->op->service;
496
struct dreplsrv_partition *partition = st->op->source_dsa->partition;
497
struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
498
struct rpc_request *req;
687
struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
688
struct dreplsrv_op_pull_source_state);
689
struct dreplsrv_service *service = state->op->service;
690
struct dreplsrv_partition *partition = state->op->source_dsa->partition;
691
struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
499
692
struct drsuapi_DsReplicaUpdateRefs *r;
500
693
char *ntds_guid_str;
501
694
char *ntds_dns_name;
695
struct tevent_req *subreq;
503
r = talloc(st, struct drsuapi_DsReplicaUpdateRefs);
504
if (composite_nomem(r, c)) return;
697
r = talloc(state, struct drsuapi_DsReplicaUpdateRefs);
698
if (tevent_req_nomem(r, req)) {
506
702
ntds_guid_str = GUID_string(r, &service->ntds_guid);
507
if (composite_nomem(ntds_guid_str, c)) return;
703
if (tevent_req_nomem(ntds_guid_str, req)) {
509
/* lp_realm() is not really right here */
510
707
ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
512
lp_realm(service->task->lp_ctx));
513
if (composite_nomem(ntds_dns_name, c)) return;
709
lpcfg_dnsdomain(service->task->lp_ctx));
710
if (tevent_req_nomem(ntds_dns_name, req)) {
515
714
r->in.bind_handle = &drsuapi->bind_handle;
517
716
r->in.req.req1.naming_context = &partition->nc;
518
717
r->in.req.req1.dest_dsa_dns_name = ntds_dns_name;
519
718
r->in.req.req1.dest_dsa_guid = service->ntds_guid;
520
r->in.req.req1.options =
521
DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE |
522
DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE;
523
if (!lp_parm_bool(service->task->lp_ctx, NULL, "repl", "RODC", false)) {
524
r->in.req.req1.options |= DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE;
527
req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
528
composite_continue_rpc(c, req, dreplsrv_update_refs_recv, st);
719
r->in.req.req1.options = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF;
720
if (!service->am_rodc) {
721
r->in.req.req1.options |= DRSUAPI_DRS_WRIT_REP;
724
state->ndr_struct_ptr = r;
725
subreq = dcerpc_drsuapi_DsReplicaUpdateRefs_r_send(state,
727
drsuapi->drsuapi_handle,
729
if (tevent_req_nomem(subreq, req)) {
732
tevent_req_set_callback(subreq, dreplsrv_update_refs_done, req);
736
receive a UpdateRefs reply
738
static void dreplsrv_update_refs_done(struct tevent_req *subreq)
740
struct tevent_req *req = tevent_req_callback_data(subreq,
742
struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
743
struct dreplsrv_op_pull_source_state);
744
struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(state->ndr_struct_ptr,
745
struct drsuapi_DsReplicaUpdateRefs);
748
state->ndr_struct_ptr = NULL;
750
status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv(subreq, r);
752
if (!NT_STATUS_IS_OK(status)) {
753
DEBUG(0,("UpdateRefs failed with %s\n",
755
tevent_req_nterror(req, status);
759
if (!W_ERROR_IS_OK(r->out.result)) {
760
status = werror_to_ntstatus(r->out.result);
761
DEBUG(0,("UpdateRefs failed with %s/%s for %s %s\n",
762
win_errstr(r->out.result),
764
r->in.req.req1.dest_dsa_dns_name,
765
r->in.req.req1.naming_context->dn));
766
tevent_req_nterror(req, status);
770
DEBUG(4,("UpdateRefs OK for %s %s\n",
771
r->in.req.req1.dest_dsa_dns_name,
772
r->in.req.req1.naming_context->dn));
774
tevent_req_done(req);
777
WERROR dreplsrv_op_pull_source_recv(struct tevent_req *req)
781
if (tevent_req_is_nterror(req, &status)) {
782
tevent_req_received(req);
783
return ntstatus_to_werror(status);
786
tevent_req_received(req);