s3-winbindd: Listen on IRPC and do forwarded DNS updates on an RODC
[Samba/wip.git] / source3 / winbindd / winbindd_dual_srv.c
blob721d293c4d01adad1a2ac63873a7646f2ea31449
1 /*
2 Unix SMB/CIFS implementation.
4 In-Child server implementation of the routines defined in wbint.idl
6 Copyright (C) Volker Lendecke 2009
7 Copyright (C) Guenther Deschner 2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "winbindd/winbindd.h"
25 #include "winbindd/winbindd_proto.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "ntdomain.h"
28 #include "librpc/gen_ndr/srv_wbint.h"
29 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "idmap.h"
31 #include "../libcli/security/security.h"
32 #include "../libcli/auth/netlogon_creds_cli.h"
34 void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
36 *r->out.out_data = r->in.in_data;
39 static bool reset_cm_connection_on_error(struct winbindd_domain *domain,
40 NTSTATUS status)
42 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
43 invalidate_cm_connection(&domain->conn);
44 /* We invalidated the connection. */
45 return true;
47 return false;
50 NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r)
52 struct winbindd_domain *domain = wb_child_domain();
53 char *dom_name;
54 char *name;
55 enum lsa_SidType type;
56 NTSTATUS status;
58 if (domain == NULL) {
59 return NT_STATUS_REQUEST_NOT_ACCEPTED;
62 status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
63 &dom_name, &name, &type);
64 reset_cm_connection_on_error(domain, status);
65 if (!NT_STATUS_IS_OK(status)) {
66 return status;
69 *r->out.domain = dom_name;
70 *r->out.name = name;
71 *r->out.type = type;
72 return NT_STATUS_OK;
75 NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r)
77 struct winbindd_domain *domain = wb_child_domain();
78 struct lsa_RefDomainList *domains = r->out.domains;
79 NTSTATUS status;
81 if (domain == NULL) {
82 return NT_STATUS_REQUEST_NOT_ACCEPTED;
86 * This breaks the winbindd_domain->methods abstraction: This
87 * is only called for remote domains, and both winbindd_msrpc
88 * and winbindd_ad call into lsa_lookupsids anyway. Caching is
89 * done at the wbint RPC layer.
91 status = rpc_lookup_sids(p->mem_ctx, domain, r->in.sids,
92 &domains, &r->out.names);
94 if (domains != NULL) {
95 r->out.domains = domains;
98 reset_cm_connection_on_error(domain, status);
99 return status;
102 NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
104 struct winbindd_domain *domain = wb_child_domain();
105 NTSTATUS status;
107 if (domain == NULL) {
108 return NT_STATUS_REQUEST_NOT_ACCEPTED;
111 status = domain->methods->name_to_sid(
112 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
113 r->out.sid, r->out.type);
114 reset_cm_connection_on_error(domain, status);
115 return status;
118 NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
119 struct wbint_Sids2UnixIDs *r)
121 uint32_t i, j;
122 struct id_map *ids = NULL;
123 struct id_map **id_ptrs = NULL;
124 struct dom_sid *sids = NULL;
125 uint32_t *id_idx = NULL;
126 NTSTATUS status = NT_STATUS_NO_MEMORY;
128 for (i=0; i<r->in.domains->count; i++) {
129 struct lsa_DomainInfo *d = &r->in.domains->domains[i];
130 struct idmap_domain *dom;
131 uint32_t num_ids;
133 dom = idmap_find_domain_with_sid(d->name.string, d->sid);
134 if (dom == NULL) {
135 DEBUG(10, ("idmap domain %s:%s not found\n",
136 d->name.string, sid_string_dbg(d->sid)));
137 continue;
140 num_ids = 0;
142 for (j=0; j<r->in.ids->num_ids; j++) {
143 if (r->in.ids->ids[j].domain_index == i) {
144 num_ids += 1;
148 ids = talloc_realloc(talloc_tos(), ids,
149 struct id_map, num_ids);
150 if (ids == NULL) {
151 goto nomem;
153 id_ptrs = talloc_realloc(talloc_tos(), id_ptrs,
154 struct id_map *, num_ids+1);
155 if (id_ptrs == NULL) {
156 goto nomem;
158 id_idx = talloc_realloc(talloc_tos(), id_idx,
159 uint32_t, num_ids);
160 if (id_idx == NULL) {
161 goto nomem;
163 sids = talloc_realloc(talloc_tos(), sids,
164 struct dom_sid, num_ids);
165 if (sids == NULL) {
166 goto nomem;
169 num_ids = 0;
172 * Convert the input data into a list of
173 * id_map structs suitable for handing in
174 * to the idmap sids_to_unixids method.
176 for (j=0; j<r->in.ids->num_ids; j++) {
177 struct wbint_TransID *id = &r->in.ids->ids[j];
179 if (id->domain_index != i) {
180 continue;
182 id_idx[num_ids] = j;
183 id_ptrs[num_ids] = &ids[num_ids];
185 ids[num_ids].sid = &sids[num_ids];
186 sid_compose(ids[num_ids].sid, d->sid, id->rid);
187 ids[num_ids].xid.type = id->type;
188 ids[num_ids].status = ID_UNKNOWN;
189 num_ids += 1;
191 id_ptrs[num_ids] = NULL;
193 status = dom->methods->sids_to_unixids(dom, id_ptrs);
194 DEBUG(10, ("sids_to_unixids returned %s\n",
195 nt_errstr(status)));
198 * Extract the results for handing them back to the caller.
200 for (j=0; j<num_ids; j++) {
201 struct wbint_TransID *id = &r->in.ids->ids[id_idx[j]];
203 if (ids[j].status != ID_MAPPED) {
204 id->xid.id = UINT32_MAX;
205 id->xid.type = ID_TYPE_NOT_SPECIFIED;
206 continue;
209 id->xid = ids[j].xid;
212 status = NT_STATUS_OK;
213 nomem:
214 TALLOC_FREE(ids);
215 TALLOC_FREE(id_ptrs);
216 TALLOC_FREE(id_idx);
217 TALLOC_FREE(sids);
218 return status;
221 NTSTATUS _wbint_Uid2Sid(struct pipes_struct *p, struct wbint_Uid2Sid *r)
223 return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
224 r->out.sid, r->in.uid);
227 NTSTATUS _wbint_Gid2Sid(struct pipes_struct *p, struct wbint_Gid2Sid *r)
229 return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
230 r->out.sid, r->in.gid);
233 NTSTATUS _wbint_AllocateUid(struct pipes_struct *p, struct wbint_AllocateUid *r)
235 struct unixid xid;
236 NTSTATUS status;
238 status = idmap_allocate_uid(&xid);
239 if (!NT_STATUS_IS_OK(status)) {
240 return status;
242 *r->out.uid = xid.id;
243 return NT_STATUS_OK;
246 NTSTATUS _wbint_AllocateGid(struct pipes_struct *p, struct wbint_AllocateGid *r)
248 struct unixid xid;
249 NTSTATUS status;
251 status = idmap_allocate_gid(&xid);
252 if (!NT_STATUS_IS_OK(status)) {
253 return status;
255 *r->out.gid = xid.id;
256 return NT_STATUS_OK;
259 NTSTATUS _wbint_QueryUser(struct pipes_struct *p, struct wbint_QueryUser *r)
261 struct winbindd_domain *domain = wb_child_domain();
262 NTSTATUS status;
264 if (domain == NULL) {
265 return NT_STATUS_REQUEST_NOT_ACCEPTED;
268 status = domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
269 r->out.info);
270 reset_cm_connection_on_error(domain, status);
271 return status;
274 NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
275 struct wbint_LookupUserAliases *r)
277 struct winbindd_domain *domain = wb_child_domain();
278 NTSTATUS status;
280 if (domain == NULL) {
281 return NT_STATUS_REQUEST_NOT_ACCEPTED;
284 status = domain->methods->lookup_useraliases(
285 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
286 &r->out.rids->num_rids, &r->out.rids->rids);
287 reset_cm_connection_on_error(domain, status);
288 return status;
291 NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
292 struct wbint_LookupUserGroups *r)
294 struct winbindd_domain *domain = wb_child_domain();
295 NTSTATUS status;
297 if (domain == NULL) {
298 return NT_STATUS_REQUEST_NOT_ACCEPTED;
301 status = domain->methods->lookup_usergroups(
302 domain, p->mem_ctx, r->in.sid,
303 &r->out.sids->num_sids, &r->out.sids->sids);
304 reset_cm_connection_on_error(domain, status);
305 return status;
308 NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
309 struct wbint_QuerySequenceNumber *r)
311 struct winbindd_domain *domain = wb_child_domain();
312 NTSTATUS status;
314 if (domain == NULL) {
315 return NT_STATUS_REQUEST_NOT_ACCEPTED;
318 status = domain->methods->sequence_number(domain, r->out.sequence);
319 reset_cm_connection_on_error(domain, status);
320 return status;
323 NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p,
324 struct wbint_LookupGroupMembers *r)
326 struct winbindd_domain *domain = wb_child_domain();
327 uint32_t i, num_names;
328 struct dom_sid *sid_mem;
329 char **names;
330 uint32_t *name_types;
331 NTSTATUS status;
333 if (domain == NULL) {
334 return NT_STATUS_REQUEST_NOT_ACCEPTED;
337 status = domain->methods->lookup_groupmem(
338 domain, p->mem_ctx, r->in.sid, r->in.type,
339 &num_names, &sid_mem, &names, &name_types);
340 reset_cm_connection_on_error(domain, status);
341 if (!NT_STATUS_IS_OK(status)) {
342 return status;
345 r->out.members->num_principals = num_names;
346 r->out.members->principals = talloc_array(
347 r->out.members, struct wbint_Principal, num_names);
348 if (r->out.members->principals == NULL) {
349 return NT_STATUS_NO_MEMORY;
352 for (i=0; i<num_names; i++) {
353 struct wbint_Principal *m = &r->out.members->principals[i];
354 sid_copy(&m->sid, &sid_mem[i]);
355 m->name = talloc_move(r->out.members->principals, &names[i]);
356 m->type = (enum lsa_SidType)name_types[i];
359 return NT_STATUS_OK;
362 NTSTATUS _wbint_QueryUserList(struct pipes_struct *p,
363 struct wbint_QueryUserList *r)
365 struct winbindd_domain *domain = wb_child_domain();
366 NTSTATUS status;
368 if (domain == NULL) {
369 return NT_STATUS_REQUEST_NOT_ACCEPTED;
372 status = domain->methods->query_user_list(
373 domain, p->mem_ctx, &r->out.users->num_userinfos,
374 &r->out.users->userinfos);
375 reset_cm_connection_on_error(domain, status);
376 return status;
379 NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p,
380 struct wbint_QueryGroupList *r)
382 struct winbindd_domain *domain = wb_child_domain();
383 uint32_t i, num_groups;
384 struct wb_acct_info *groups;
385 struct wbint_Principal *result;
386 NTSTATUS status;
388 if (domain == NULL) {
389 return NT_STATUS_REQUEST_NOT_ACCEPTED;
392 status = domain->methods->enum_dom_groups(domain, talloc_tos(),
393 &num_groups, &groups);
394 reset_cm_connection_on_error(domain, status);
395 if (!NT_STATUS_IS_OK(status)) {
396 return status;
399 result = talloc_array(r->out.groups, struct wbint_Principal,
400 num_groups);
401 if (result == NULL) {
402 return NT_STATUS_NO_MEMORY;
405 for (i=0; i<num_groups; i++) {
406 sid_compose(&result[i].sid, &domain->sid, groups[i].rid);
407 result[i].type = SID_NAME_DOM_GRP;
408 result[i].name = talloc_strdup(result, groups[i].acct_name);
409 if (result[i].name == NULL) {
410 TALLOC_FREE(result);
411 TALLOC_FREE(groups);
412 return NT_STATUS_NO_MEMORY;
416 r->out.groups->num_principals = num_groups;
417 r->out.groups->principals = result;
419 TALLOC_FREE(groups);
420 return NT_STATUS_OK;
423 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
425 struct winbindd_domain *domain = wb_child_domain();
426 struct rpc_pipe_client *netlogon_pipe;
427 struct netr_DsRGetDCNameInfo *dc_info;
428 NTSTATUS status;
429 WERROR werr;
430 unsigned int orig_timeout;
431 struct dcerpc_binding_handle *b;
433 if (domain == NULL) {
434 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
435 r->in.domain_name, r->in.domain_guid,
436 r->in.site_name ? r->in.site_name : "",
437 r->in.flags,
438 r->out.dc_info);
441 status = cm_connect_netlogon(domain, &netlogon_pipe);
443 reset_cm_connection_on_error(domain, status);
444 if (!NT_STATUS_IS_OK(status)) {
445 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
446 return status;
449 b = netlogon_pipe->binding_handle;
451 /* This call can take a long time - allow the server to time out.
452 35 seconds should do it. */
454 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
456 if (domain->active_directory) {
457 status = dcerpc_netr_DsRGetDCName(b,
458 p->mem_ctx, domain->dcname,
459 r->in.domain_name, NULL, r->in.domain_guid,
460 r->in.flags, r->out.dc_info, &werr);
461 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
462 goto done;
464 if (reset_cm_connection_on_error(domain, status)) {
465 /* Re-initialize. */
466 status = cm_connect_netlogon(domain, &netlogon_pipe);
468 reset_cm_connection_on_error(domain, status);
469 if (!NT_STATUS_IS_OK(status)) {
470 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
471 return status;
474 b = netlogon_pipe->binding_handle;
476 /* This call can take a long time - allow the server to time out.
477 35 seconds should do it. */
479 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
484 * Fallback to less capable methods
487 dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
488 if (dc_info == NULL) {
489 status = NT_STATUS_NO_MEMORY;
490 goto done;
493 if (r->in.flags & DS_PDC_REQUIRED) {
494 status = dcerpc_netr_GetDcName(b,
495 p->mem_ctx, domain->dcname,
496 r->in.domain_name, &dc_info->dc_unc, &werr);
497 } else {
498 status = dcerpc_netr_GetAnyDCName(b,
499 p->mem_ctx, domain->dcname,
500 r->in.domain_name, &dc_info->dc_unc, &werr);
503 reset_cm_connection_on_error(domain, status);
504 if (!NT_STATUS_IS_OK(status)) {
505 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
506 nt_errstr(status)));
507 goto done;
509 if (!W_ERROR_IS_OK(werr)) {
510 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
511 win_errstr(werr)));
512 status = werror_to_ntstatus(werr);
513 goto done;
516 *r->out.dc_info = dc_info;
517 status = NT_STATUS_OK;
519 done:
520 /* And restore our original timeout. */
521 rpccli_set_timeout(netlogon_pipe, orig_timeout);
523 return status;
526 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
528 struct winbindd_domain *domain = wb_child_domain();
529 char *domain_name;
530 char **names;
531 enum lsa_SidType *types;
532 struct wbint_Principal *result;
533 NTSTATUS status;
534 int i;
536 if (domain == NULL) {
537 return NT_STATUS_REQUEST_NOT_ACCEPTED;
540 status = domain->methods->rids_to_names(
541 domain, talloc_tos(), r->in.domain_sid, r->in.rids->rids,
542 r->in.rids->num_rids, &domain_name, &names, &types);
543 reset_cm_connection_on_error(domain, status);
544 if (!NT_STATUS_IS_OK(status)) {
545 return status;
548 *r->out.domain_name = talloc_move(r->out.domain_name, &domain_name);
550 result = talloc_array(p->mem_ctx, struct wbint_Principal,
551 r->in.rids->num_rids);
552 if (result == NULL) {
553 return NT_STATUS_NO_MEMORY;
556 for (i=0; i<r->in.rids->num_rids; i++) {
557 sid_compose(&result[i].sid, r->in.domain_sid,
558 r->in.rids->rids[i]);
559 result[i].type = types[i];
560 result[i].name = talloc_move(result, &names[i]);
562 TALLOC_FREE(types);
563 TALLOC_FREE(names);
565 r->out.names->num_principals = r->in.rids->num_rids;
566 r->out.names->principals = result;
567 return NT_STATUS_OK;
570 NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
571 struct wbint_CheckMachineAccount *r)
573 struct winbindd_domain *domain;
574 int num_retries = 0;
575 NTSTATUS status;
577 domain = wb_child_domain();
578 if (domain == NULL) {
579 return NT_STATUS_REQUEST_NOT_ACCEPTED;
582 again:
583 invalidate_cm_connection(&domain->conn);
584 domain->conn.netlogon_force_reauth = true;
587 struct rpc_pipe_client *netlogon_pipe;
588 status = cm_connect_netlogon(domain, &netlogon_pipe);
591 /* There is a race condition between fetching the trust account
592 password and the periodic machine password change. So it's
593 possible that the trust account password has been changed on us.
594 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
596 #define MAX_RETRIES 3
598 if ((num_retries < MAX_RETRIES)
599 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
600 num_retries++;
601 goto again;
604 if (!NT_STATUS_IS_OK(status)) {
605 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
606 goto done;
609 /* Pass back result code - zero for success, other values for
610 specific failures. */
612 DEBUG(3,("domain %s secret is %s\n", domain->name,
613 NT_STATUS_IS_OK(status) ? "good" : "bad"));
615 done:
616 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
617 ("Checking the trust account password for domain %s returned %s\n",
618 domain->name, nt_errstr(status)));
620 return status;
623 NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
624 struct wbint_ChangeMachineAccount *r)
626 struct messaging_context *msg_ctx = winbind_messaging_context();
627 struct winbindd_domain *domain;
628 NTSTATUS status;
629 struct rpc_pipe_client *netlogon_pipe;
631 domain = wb_child_domain();
632 if (domain == NULL) {
633 return NT_STATUS_REQUEST_NOT_ACCEPTED;
636 status = cm_connect_netlogon(domain, &netlogon_pipe);
637 if (!NT_STATUS_IS_OK(status)) {
638 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
639 goto done;
642 status = trust_pw_change(domain->conn.netlogon_creds,
643 msg_ctx,
644 netlogon_pipe->binding_handle,
645 domain->name,
646 true); /* force */
648 /* Pass back result code - zero for success, other values for
649 specific failures. */
651 DEBUG(3,("domain %s secret %s\n", domain->name,
652 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
654 done:
655 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
656 ("Changing the trust account password for domain %s returned %s\n",
657 domain->name, nt_errstr(status)));
659 return status;
662 NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
664 NTSTATUS status;
665 struct winbindd_domain *domain;
666 struct rpc_pipe_client *netlogon_pipe;
667 union netr_CONTROL_QUERY_INFORMATION info;
668 WERROR werr;
669 fstring logon_server;
670 struct dcerpc_binding_handle *b;
672 domain = wb_child_domain();
673 if (domain == NULL) {
674 return NT_STATUS_REQUEST_NOT_ACCEPTED;
677 status = cm_connect_netlogon(domain, &netlogon_pipe);
678 reset_cm_connection_on_error(domain, status);
679 if (!NT_STATUS_IS_OK(status)) {
680 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
681 nt_errstr(status)));
682 return status;
685 b = netlogon_pipe->binding_handle;
687 fstr_sprintf(logon_server, "\\\\%s", domain->dcname);
688 *r->out.dcname = talloc_strdup(p->mem_ctx, domain->dcname);
689 if (*r->out.dcname == NULL) {
690 DEBUG(2, ("Could not allocate memory\n"));
691 return NT_STATUS_NO_MEMORY;
695 * This provokes a WERR_NOT_SUPPORTED error message. This is
696 * documented in the wspp docs. I could not get a successful
697 * call to work, but the main point here is testing that the
698 * netlogon pipe works.
700 status = dcerpc_netr_LogonControl(b, p->mem_ctx,
701 logon_server, NETLOGON_CONTROL_QUERY,
702 2, &info, &werr);
704 reset_cm_connection_on_error(domain, status);
705 if (!NT_STATUS_IS_OK(status)) {
706 DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n",
707 nt_errstr(status)));
708 return status;
711 if (!W_ERROR_EQUAL(werr, WERR_NOT_SUPPORTED)) {
712 DEBUG(2, ("dcerpc_netr_LogonControl returned %s, expected "
713 "WERR_NOT_SUPPORTED\n",
714 win_errstr(werr)));
715 return werror_to_ntstatus(werr);
718 DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
719 return NT_STATUS_OK;
722 NTSTATUS _wbint_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p,
723 struct wbint_DsrUpdateReadOnlyServerDnsRecords *r)
725 struct winbindd_domain *domain;
726 NTSTATUS status;
727 struct rpc_pipe_client *netlogon_pipe;
729 domain = wb_child_domain();
730 if (domain == NULL) {
731 return NT_STATUS_REQUEST_NOT_ACCEPTED;
734 status = cm_connect_netlogon(domain, &netlogon_pipe);
735 if (!NT_STATUS_IS_OK(status)) {
736 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
737 goto done;
740 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(domain->conn.netlogon_creds,
741 netlogon_pipe->binding_handle,
742 r->in.site_name,
743 r->in.dns_ttl,
744 r->in.dns_names);
746 /* Pass back result code - zero for success, other values for
747 specific failures. */
749 DEBUG(3,("DNS records for domain %s %s\n", domain->name,
750 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
752 done:
753 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
754 ("Update of DNS records via RW DC %s returned %s\n",
755 domain->name, nt_errstr(status)));
757 return status;