ctdb-server: Clean up connection tracking functions
[samba4-gss.git] / source3 / utils / net_ads_join_dns.c
blob88287963dcfdb956065c4d14bd73c26d0e39a201
1 /*
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/>.
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "../lib/addns/dnsquery.h"
26 #include "passdb.h"
27 #include "utils/net_dns.h"
28 #include "lib/util/string_wrappers.h"
30 #ifdef HAVE_ADS
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,
40 TALLOC_CTX *ctx,
41 ADS_STRUCT *ads,
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;
50 DNS_ERROR dns_err;
51 fstring dns_server;
52 const char *dnsdomain = NULL;
53 char *root_domain = NULL;
54 uint32_t ttl = 3600;
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;
64 goto done;
66 dnsdomain++;
68 status = ads_dns_lookup_ns(ctx,
69 dnsdomain,
70 &nameservers,
71 &ns_count);
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;
79 char *root_dn;
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);
87 goto done;
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);
95 goto done;
98 root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
99 if ( !root_dn ) {
100 ads_msgfree( ads, msg );
101 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
102 goto done;
105 root_domain = ads_build_domain( root_dn );
107 /* cleanup */
108 ads_msgfree( ads, msg );
110 /* try again for NS servers */
112 status = ads_dns_lookup_ns(ctx,
113 root_domain,
114 &nameservers,
115 &ns_count);
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));
120 if (ns_count == 0) {
121 status = NT_STATUS_UNSUCCESSFUL;
123 goto done;
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 |
135 DNS_UPDATE_PROBE |
136 DNS_UPDATE_PROBE_SUFFICIENT;
138 if (c->opt_force) {
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.
147 if (remove_host) {
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,
159 dnsdomain,
160 machine_name,
161 creds,
162 addrs,
163 num_addrs,
164 flags,
165 ttl,
166 remove_host);
167 if (ERR_DNS_IS_OK(dns_err)) {
168 status = NT_STATUS_OK;
169 goto done;
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)));
177 continue;
180 d_printf(_("DNS Update for %s failed: %s\n"),
181 machine_name, dns_errstr(dns_err));
182 status = NT_STATUS_UNSUCCESSFUL;
183 goto done;
186 done:
188 SAFE_FREE( root_domain );
190 return status;
193 NTSTATUS net_update_dns_ext(struct net_context *c,
194 TALLOC_CTX *mem_ctx,
195 ADS_STRUCT *ads,
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;
203 NTSTATUS status;
205 if (hostname) {
206 fstrcpy(machine_name, hostname);
207 } else {
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)) {
224 * Get our ip address
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,
237 mem_ctx,
238 ads,
239 creds,
240 machine_name,
241 iplist,
242 num_addrs,
243 remove_host);
245 SAFE_FREE(iplist_alloc);
246 return status;
249 #endif
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;
256 NTSTATUS status;
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"));
272 return;
275 if (!r->out.domain_is_ad) {
276 return;
280 * We enter this block with user creds.
281 * kinit with the machine password to do dns update.
284 ads_dns = ads_init(ctx,
285 lp_realm(),
286 lp_workgroup(),
287 r->in.dc_name,
288 ADS_SASL_PLAIN);
289 if (ads_dns == NULL) {
290 d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
291 goto done;
294 status = pdb_get_trust_credentials(ads_dns->server.workgroup,
295 ads_dns->server.realm,
296 ads_dns,
297 &creds);
298 if (!NT_STATUS_IS_OK(status)) {
299 d_fprintf(stderr, "pdb_get_trust_credentials() failed: %s\n",
300 nt_errstr(status));
301 goto done;
304 status = net_update_dns_ext(c,
305 ads_dns,
306 ads_dns,
307 creds,
308 NULL,
309 NULL,
311 false);
312 if (!NT_STATUS_IS_OK(status)) {
313 d_fprintf( stderr, _("DNS update failed: %s\n"),
314 nt_errstr(status));
317 done:
318 TALLOC_FREE(ads_dns);
319 #endif
321 return;
324 #endif /* HAVE_ADS */