2 Samba Unix/Linux SMB client library
3 net ads dns internal functions
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
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/>.
24 #include "utils/net.h"
25 #include "../lib/addns/dnsquery.h"
27 #include "utils/net_dns.h"
28 #include "lib/util/string_wrappers.h"
32 /*******************************************************************
33 Send a DNS update request
34 *******************************************************************/
36 #if defined(HAVE_KRB5)
37 #include "../lib/addns/dns.h"
39 static NTSTATUS
net_update_dns_internal(struct net_context
*c
,
42 struct cli_credentials
*creds
,
43 const char *machine_name
,
44 const struct sockaddr_storage
*addrs
,
45 int num_addrs
, bool remove_host
)
47 struct dns_rr_ns
*nameservers
= NULL
;
48 size_t ns_count
= 0, i
;
49 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
52 const char *dnsdomain
= NULL
;
53 char *root_domain
= NULL
;
56 if (c
->opt_dns_ttl
> 0) {
57 ttl
= MIN(c
->opt_dns_ttl
, UINT32_MAX
);
60 if ( (dnsdomain
= strchr_m( machine_name
, '.')) == NULL
) {
61 d_printf(_("No DNS domain configured for %s. "
62 "Unable to perform DNS Update.\n"), machine_name
);
63 status
= NT_STATUS_INVALID_PARAMETER
;
68 status
= ads_dns_lookup_ns(ctx
,
72 if ( !NT_STATUS_IS_OK(status
) || (ns_count
== 0)) {
73 /* Child domains often do not have NS records. Look
74 for the NS record for the forest root domain
75 (rootDomainNamingContext in therootDSE) */
77 const char *rootname_attrs
[] = { "rootDomainNamingContext", NULL
};
78 LDAPMessage
*msg
= NULL
;
80 ADS_STATUS ads_status
;
82 if ( !ads
->ldap
.ld
) {
83 ads_status
= ads_connect_creds(ads
, creds
);
84 if ( !ADS_ERR_OK(ads_status
) ) {
85 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
86 status
= ads_ntstatus(ads_status
);
91 ads_status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
,
92 "(objectclass=*)", rootname_attrs
, &msg
);
93 if (!ADS_ERR_OK(ads_status
)) {
94 status
= ads_ntstatus(ads_status
);
98 root_dn
= ads_pull_string(ads
, ctx
, msg
, "rootDomainNamingContext");
100 ads_msgfree( ads
, msg
);
101 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
105 root_domain
= ads_build_domain( root_dn
);
108 ads_msgfree( ads
, msg
);
110 /* try again for NS servers */
112 status
= ads_dns_lookup_ns(ctx
,
117 if ( !NT_STATUS_IS_OK(status
) || (ns_count
== 0)) {
118 DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
119 "realm\n", ads
->config
.realm
));
121 status
= NT_STATUS_UNSUCCESSFUL
;
126 dnsdomain
= root_domain
;
130 for (i
=0; i
< ns_count
; i
++) {
132 uint32_t flags
= DNS_UPDATE_SIGNED
|
133 DNS_UPDATE_UNSIGNED
|
134 DNS_UPDATE_UNSIGNED_SUFFICIENT
|
136 DNS_UPDATE_PROBE_SUFFICIENT
;
139 flags
&= ~DNS_UPDATE_PROBE_SUFFICIENT
;
140 flags
&= ~DNS_UPDATE_UNSIGNED_SUFFICIENT
;
144 * Do not return after PROBE completion if this function
145 * is called for DNS removal.
148 flags
&= ~DNS_UPDATE_PROBE_SUFFICIENT
;
151 status
= NT_STATUS_UNSUCCESSFUL
;
153 /* Now perform the dns update - we'll try non-secure and if we fail,
154 we'll follow it up with a secure update */
156 fstrcpy( dns_server
, nameservers
[i
].hostname
);
158 dns_err
= DoDNSUpdate(dns_server
,
167 if (ERR_DNS_IS_OK(dns_err
)) {
168 status
= NT_STATUS_OK
;
172 if (ERR_DNS_EQUAL(dns_err
, ERROR_DNS_INVALID_NAME_SERVER
) ||
173 ERR_DNS_EQUAL(dns_err
, ERROR_DNS_CONNECTION_FAILED
) ||
174 ERR_DNS_EQUAL(dns_err
, ERROR_DNS_SOCKET_ERROR
)) {
175 DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
176 dns_errstr(dns_err
)));
180 d_printf(_("DNS Update for %s failed: %s\n"),
181 machine_name
, dns_errstr(dns_err
));
182 status
= NT_STATUS_UNSUCCESSFUL
;
188 SAFE_FREE( root_domain
);
193 NTSTATUS
net_update_dns_ext(struct net_context
*c
,
196 struct cli_credentials
*creds
,
197 const char *hostname
,
198 struct sockaddr_storage
*iplist
,
199 int num_addrs
, bool remove_host
)
201 struct sockaddr_storage
*iplist_alloc
= NULL
;
202 fstring machine_name
;
206 fstrcpy(machine_name
, hostname
);
208 const char *dns_hostname
= lp_dns_hostname();
209 if (dns_hostname
== NULL
) {
210 return NT_STATUS_NO_MEMORY
;
212 fstrcpy(machine_name
, lp_dns_hostname());
214 if (!strlower_m( machine_name
)) {
215 return NT_STATUS_INVALID_PARAMETER
;
219 * If remove_host is true, then remove all IP addresses associated with
220 * this hostname from the AD server.
222 if (!remove_host
&& (num_addrs
== 0 || iplist
== NULL
)) {
225 * (not the 127.0.0.x address but a real ip address)
227 num_addrs
= get_my_ip_address(&iplist_alloc
);
228 if ( num_addrs
<= 0 ) {
229 DEBUG(4, ("net_update_dns_ext: Failed to find my "
230 "non-loopback IP addresses!\n"));
231 return NT_STATUS_INVALID_PARAMETER
;
233 iplist
= iplist_alloc
;
236 status
= net_update_dns_internal(c
,
245 SAFE_FREE(iplist_alloc
);
251 void net_ads_join_dns_updates(struct net_context
*c
, TALLOC_CTX
*ctx
, struct libnet_JoinCtx
*r
)
253 #if defined(HAVE_KRB5)
254 ADS_STRUCT
*ads_dns
= NULL
;
255 struct cli_credentials
*creds
= NULL
;
259 * In a clustered environment, don't do dynamic dns updates:
260 * Registering the set of ip addresses that are assigned to
261 * the interfaces of the node that performs the join does usually
262 * not have the desired effect, since the local interfaces do not
263 * carry the complete set of the cluster's public IP addresses.
264 * And it can also contain internal addresses that should not
265 * be visible to the outside at all.
266 * In order to do dns updates in a clustererd setup, use
267 * net ads dns register.
269 if (lp_clustering()) {
270 d_fprintf(stderr
, _("Not doing automatic DNS update in a "
271 "clustered setup.\n"));
275 if (!r
->out
.domain_is_ad
) {
280 * We enter this block with user creds.
281 * kinit with the machine password to do dns update.
284 ads_dns
= ads_init(ctx
,
289 if (ads_dns
== NULL
) {
290 d_fprintf(stderr
, _("DNS update failed: out of memory!\n"));
294 status
= pdb_get_trust_credentials(ads_dns
->server
.workgroup
,
295 ads_dns
->server
.realm
,
298 if (!NT_STATUS_IS_OK(status
)) {
299 d_fprintf(stderr
, "pdb_get_trust_credentials() failed: %s\n",
304 status
= net_update_dns_ext(c
,
312 if (!NT_STATUS_IS_OK(status
)) {
313 d_fprintf( stderr
, _("DNS update failed: %s\n"),
318 TALLOC_FREE(ads_dns
);
324 #endif /* HAVE_ADS */