2 Unix SMB/CIFS mplementation.
3 DSDB replication service helper function for outgoing traffic
5 Copyright (C) Stefan Metzmacher 2007
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/>.
23 #include "dsdb/samdb/samdb.h"
24 #include "auth/auth.h"
25 #include "smbd/service.h"
26 #include "lib/events/events.h"
27 #include "lib/messaging/irpc.h"
28 #include "dsdb/repl/drepl_service.h"
29 #include "lib/ldb/include/ldb_errors.h"
30 #include "../lib/util/dlinklist.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "librpc/gen_ndr/ndr_drsuapi.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "libcli/composite/composite.h"
35 #include "auth/gensec/gensec.h"
36 #include "param/param.h"
37 #include "../lib/util/tevent_ntstatus.h"
39 struct dreplsrv_out_drsuapi_state {
40 struct tevent_context *ev;
42 struct dreplsrv_out_connection *conn;
44 struct dreplsrv_drsuapi_connection *drsuapi;
46 struct drsuapi_DsBindInfoCtr bind_info_ctr;
47 struct drsuapi_DsBind bind_r;
50 static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq);
52 struct tevent_req *dreplsrv_out_drsuapi_send(TALLOC_CTX *mem_ctx,
53 struct tevent_context *ev,
54 struct dreplsrv_out_connection *conn)
56 struct tevent_req *req;
57 struct dreplsrv_out_drsuapi_state *state;
58 struct composite_context *creq;
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);
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);
85 creq = dcerpc_pipe_connect_b_send(state, conn->binding, &ndr_table_drsuapi,
86 conn->service->system_session_info->credentials,
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) {
166 struct drsuapi_DsBindInfo24 *info24;
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;
176 struct drsuapi_DsBindInfo48 *info48;
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;
186 *info28 = state->bind_r.out.bind_info->info.info28;
191 tevent_req_done(req);
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);
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);
211 struct dreplsrv_op_pull_source_state {
212 struct tevent_context *ev;
213 struct dreplsrv_out_operation *op;
214 void *ndr_struct_ptr;
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;
333 struct drsuapi_DsGetNCChanges *r;
334 struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector;
335 struct tevent_req *subreq;
336 struct drsuapi_DsPartialAttributeSet *pas = NULL;
338 uint32_t replica_flags;
340 if ((rf1->replica_flags & DRSUAPI_DRS_WRIT_REP) == 0 &&
341 state->op->extended_op == DRSUAPI_EXOP_NONE) {
345 r = talloc(state, struct drsuapi_DsGetNCChanges);
346 if (tevent_req_nomem(r, req)) {
350 r->out.level_out = talloc(r, uint32_t);
351 if (tevent_req_nomem(r->out.level_out, req)) {
354 r->in.req = talloc(r, union drsuapi_DsGetNCChangesRequest);
355 if (tevent_req_nomem(r->in.req, req)) {
358 r->out.ctr = talloc(r, union drsuapi_DsGetNCChangesCtr);
359 if (tevent_req_nomem(r->out.ctr, req)) {
363 if (partition->uptodatevector.count != 0 &&
364 partition->uptodatevector_ex.count == 0) {
366 werr = udv_convert(partition, &partition->uptodatevector, &partition->uptodatevector_ex);
367 if (!W_ERROR_IS_OK(werr)) {
368 DEBUG(0,(__location__ ": Failed to convert UDV for %s : %s\n",
369 ldb_dn_get_linearized(partition->dn), nt_errstr(status)));
373 if (partition->uptodatevector_ex.count == 0) {
374 uptodateness_vector = NULL;
376 uptodateness_vector = &partition->uptodatevector_ex;
379 replica_flags = rf1->replica_flags;
381 if (service->am_rodc) {
382 bool for_schema = false;
383 if (ldb_dn_compare_base(ldb_get_schema_basedn(service->samdb), partition->dn) == 0) {
387 status = dreplsrv_get_rodc_partial_attribute_set(service, r, &pas, for_schema);
388 if (!NT_STATUS_IS_OK(status)) {
389 DEBUG(0,(__location__ ": Failed to construct partial attribute set : %s\n", nt_errstr(status)));
393 replica_flags &= ~DRSUAPI_DRS_WRIT_REP;
396 r->in.bind_handle = &drsuapi->bind_handle;
397 if (drsuapi->remote_info28.supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
399 r->in.req->req8.destination_dsa_guid = service->ntds_guid;
400 r->in.req->req8.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
401 r->in.req->req8.naming_context = &partition->nc;
402 r->in.req->req8.highwatermark = rf1->highwatermark;
403 r->in.req->req8.uptodateness_vector = uptodateness_vector;
404 r->in.req->req8.replica_flags = replica_flags;
405 r->in.req->req8.max_object_count = 133;
406 r->in.req->req8.max_ndr_size = 1336811;
407 r->in.req->req8.extended_op = state->op->extended_op;
408 r->in.req->req8.fsmo_info = state->op->fsmo_info;
409 r->in.req->req8.partial_attribute_set = pas;
410 r->in.req->req8.partial_attribute_set_ex= NULL;
411 r->in.req->req8.mapping_ctr.num_mappings= 0;
412 r->in.req->req8.mapping_ctr.mappings = NULL;
415 r->in.req->req5.destination_dsa_guid = service->ntds_guid;
416 r->in.req->req5.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
417 r->in.req->req5.naming_context = &partition->nc;
418 r->in.req->req5.highwatermark = rf1->highwatermark;
419 r->in.req->req5.uptodateness_vector = uptodateness_vector;
420 r->in.req->req5.replica_flags = replica_flags;
421 r->in.req->req5.max_object_count = 133;
422 r->in.req->req5.max_ndr_size = 1336770;
423 r->in.req->req5.extended_op = state->op->extended_op;
424 r->in.req->req5.fsmo_info = state->op->fsmo_info;
428 NDR_PRINT_IN_DEBUG(drsuapi_DsGetNCChanges, r);
431 state->ndr_struct_ptr = r;
432 subreq = dcerpc_drsuapi_DsGetNCChanges_r_send(state,
434 drsuapi->drsuapi_handle,
436 if (tevent_req_nomem(subreq, req)) {
439 tevent_req_set_callback(subreq, dreplsrv_op_pull_source_get_changes_done, req);
442 static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req,
443 struct drsuapi_DsGetNCChanges *r,
445 struct drsuapi_DsGetNCChangesCtr1 *ctr1,
446 struct drsuapi_DsGetNCChangesCtr6 *ctr6);
448 static void dreplsrv_op_pull_source_get_changes_done(struct tevent_req *subreq)
450 struct tevent_req *req = tevent_req_callback_data(subreq,
452 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
453 struct dreplsrv_op_pull_source_state);
455 struct drsuapi_DsGetNCChanges *r = talloc_get_type(state->ndr_struct_ptr,
456 struct drsuapi_DsGetNCChanges);
457 uint32_t ctr_level = 0;
458 struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
459 struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
460 enum drsuapi_DsExtendedError extended_ret;
461 state->ndr_struct_ptr = NULL;
463 status = dcerpc_drsuapi_DsGetNCChanges_r_recv(subreq, r);
465 if (tevent_req_nterror(req, status)) {
469 if (!W_ERROR_IS_OK(r->out.result)) {
470 status = werror_to_ntstatus(r->out.result);
471 tevent_req_nterror(req, status);
475 if (*r->out.level_out == 1) {
477 ctr1 = &r->out.ctr->ctr1;
478 } else if (*r->out.level_out == 2 &&
479 r->out.ctr->ctr2.mszip1.ts) {
481 ctr1 = &r->out.ctr->ctr2.mszip1.ts->ctr1;
482 } else if (*r->out.level_out == 6) {
484 ctr6 = &r->out.ctr->ctr6;
485 } else if (*r->out.level_out == 7 &&
486 r->out.ctr->ctr7.level == 6 &&
487 r->out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP &&
488 r->out.ctr->ctr7.ctr.mszip6.ts) {
490 ctr6 = &r->out.ctr->ctr7.ctr.mszip6.ts->ctr6;
491 } else if (*r->out.level_out == 7 &&
492 r->out.ctr->ctr7.level == 6 &&
493 r->out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS &&
494 r->out.ctr->ctr7.ctr.xpress6.ts) {
496 ctr6 = &r->out.ctr->ctr7.ctr.xpress6.ts->ctr6;
498 status = werror_to_ntstatus(WERR_BAD_NET_RESP);
499 tevent_req_nterror(req, status);
503 if (!ctr1 && !ctr6) {
504 status = werror_to_ntstatus(WERR_BAD_NET_RESP);
505 tevent_req_nterror(req, status);
509 if (ctr_level == 6) {
510 if (!W_ERROR_IS_OK(ctr6->drs_error)) {
511 status = werror_to_ntstatus(ctr6->drs_error);
512 tevent_req_nterror(req, status);
515 extended_ret = ctr6->extended_ret;
518 if (ctr_level == 1) {
519 extended_ret = ctr1->extended_ret;
522 if (state->op->extended_op != DRSUAPI_EXOP_NONE) {
523 state->op->extended_ret = extended_ret;
525 if (extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) {
526 status = NT_STATUS_UNSUCCESSFUL;
527 tevent_req_nterror(req, status);
532 dreplsrv_op_pull_source_apply_changes_trigger(req, r, ctr_level, ctr1, ctr6);
535 static void dreplsrv_update_refs_trigger(struct tevent_req *req);
537 static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req,
538 struct drsuapi_DsGetNCChanges *r,
540 struct drsuapi_DsGetNCChangesCtr1 *ctr1,
541 struct drsuapi_DsGetNCChangesCtr6 *ctr6)
543 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
544 struct dreplsrv_op_pull_source_state);
545 struct repsFromTo1 rf1 = *state->op->source_dsa->repsFrom1;
546 struct dreplsrv_service *service = state->op->service;
547 struct dreplsrv_partition *partition = state->op->source_dsa->partition;
548 struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
549 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
550 uint32_t object_count;
551 struct drsuapi_DsReplicaObjectListItemEx *first_object;
552 uint32_t linked_attributes_count;
553 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
554 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
555 struct dsdb_extended_replicated_objects *objects;
556 bool more_data = false;
562 mapping_ctr = &ctr1->mapping_ctr;
563 object_count = ctr1->object_count;
564 first_object = ctr1->first_object;
565 linked_attributes_count = 0;
566 linked_attributes = NULL;
567 rf1.highwatermark = ctr1->new_highwatermark;
568 uptodateness_vector = NULL; /* TODO: map it */
569 more_data = ctr1->more_data;
572 mapping_ctr = &ctr6->mapping_ctr;
573 object_count = ctr6->object_count;
574 first_object = ctr6->first_object;
575 linked_attributes_count = ctr6->linked_attributes_count;
576 linked_attributes = ctr6->linked_attributes;
577 rf1.highwatermark = ctr6->new_highwatermark;
578 uptodateness_vector = ctr6->uptodateness_vector;
579 more_data = ctr6->more_data;
582 nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
583 tevent_req_nterror(req, nt_status);
587 status = dsdb_extended_replicated_objects_convert(service->samdb,
592 linked_attributes_count,
596 &drsuapi->gensec_skey,
598 if (!W_ERROR_IS_OK(status)) {
599 nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
600 DEBUG(0,("Failed to convert objects: %s/%s\n",
601 win_errstr(status), nt_errstr(nt_status)));
602 tevent_req_nterror(req, nt_status);
606 status = dsdb_extended_replicated_objects_commit(service->samdb,
608 &state->op->source_dsa->notify_uSN);
609 talloc_free(objects);
610 if (!W_ERROR_IS_OK(status)) {
611 nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
612 DEBUG(0,("Failed to commit objects: %s/%s\n",
613 win_errstr(status), nt_errstr(nt_status)));
614 tevent_req_nterror(req, nt_status);
617 if (state->op->extended_op == DRSUAPI_EXOP_NONE) {
618 /* if it applied fine, we need to update the highwatermark */
619 *state->op->source_dsa->repsFrom1 = rf1;
622 * TODO: update our uptodatevector!
625 /* we don't need this maybe very large structure anymore */
629 dreplsrv_op_pull_source_get_changes_trigger(req);
633 /* now we need to update the repsTo record for this partition
634 on the server. These records are initially established when
635 we join the domain, but they quickly expire. We do it here
636 so we can use the already established DRSUAPI pipe
638 if (state->op->extended_op == DRSUAPI_EXOP_NONE) {
639 dreplsrv_update_refs_trigger(req);
641 tevent_req_done(req);
645 static void dreplsrv_update_refs_done(struct tevent_req *subreq);
648 send a UpdateRefs request to refresh our repsTo record on the server
650 static void dreplsrv_update_refs_trigger(struct tevent_req *req)
652 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
653 struct dreplsrv_op_pull_source_state);
654 struct dreplsrv_service *service = state->op->service;
655 struct dreplsrv_partition *partition = state->op->source_dsa->partition;
656 struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
657 struct drsuapi_DsReplicaUpdateRefs *r;
660 struct tevent_req *subreq;
662 r = talloc(state, struct drsuapi_DsReplicaUpdateRefs);
663 if (tevent_req_nomem(r, req)) {
667 ntds_guid_str = GUID_string(r, &service->ntds_guid);
668 if (tevent_req_nomem(ntds_guid_str, req)) {
672 ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
674 lpcfg_dnsdomain(service->task->lp_ctx));
675 if (tevent_req_nomem(ntds_dns_name, req)) {
679 r->in.bind_handle = &drsuapi->bind_handle;
681 r->in.req.req1.naming_context = &partition->nc;
682 r->in.req.req1.dest_dsa_dns_name = ntds_dns_name;
683 r->in.req.req1.dest_dsa_guid = service->ntds_guid;
684 r->in.req.req1.options = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF;
685 if (!service->am_rodc) {
686 r->in.req.req1.options |= DRSUAPI_DRS_WRIT_REP;
689 state->ndr_struct_ptr = r;
690 subreq = dcerpc_drsuapi_DsReplicaUpdateRefs_r_send(state,
692 drsuapi->drsuapi_handle,
694 if (tevent_req_nomem(subreq, req)) {
697 tevent_req_set_callback(subreq, dreplsrv_update_refs_done, req);
701 receive a UpdateRefs reply
703 static void dreplsrv_update_refs_done(struct tevent_req *subreq)
705 struct tevent_req *req = tevent_req_callback_data(subreq,
707 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
708 struct dreplsrv_op_pull_source_state);
709 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(state->ndr_struct_ptr,
710 struct drsuapi_DsReplicaUpdateRefs);
713 state->ndr_struct_ptr = NULL;
715 status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv(subreq, r);
717 if (!NT_STATUS_IS_OK(status)) {
718 DEBUG(0,("UpdateRefs failed with %s\n",
720 tevent_req_nterror(req, status);
724 if (!W_ERROR_IS_OK(r->out.result)) {
725 status = werror_to_ntstatus(r->out.result);
726 DEBUG(0,("UpdateRefs failed with %s/%s for %s %s\n",
727 win_errstr(r->out.result),
729 r->in.req.req1.dest_dsa_dns_name,
730 r->in.req.req1.naming_context->dn));
731 tevent_req_nterror(req, status);
735 DEBUG(4,("UpdateRefs OK for %s %s\n",
736 r->in.req.req1.dest_dsa_dns_name,
737 r->in.req.req1.naming_context->dn));
739 tevent_req_done(req);
742 WERROR dreplsrv_op_pull_source_recv(struct tevent_req *req)
746 if (tevent_req_is_nterror(req, &status)) {
747 tevent_req_received(req);
748 return ntstatus_to_werror(status);
751 tevent_req_received(req);