4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1 |
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
2 |
/* NetworkManager -- Network link manager
|
|
3 |
*
|
|
4 |
* This program is free software; you can redistribute it and/or modify
|
|
5 |
* it under the terms of the GNU General Public License as published by
|
|
6 |
* the Free Software Foundation; either version 2 of the License, or
|
|
7 |
* (at your option) any later version.
|
|
8 |
*
|
|
9 |
* This program is distributed in the hope that it will be useful,
|
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
* GNU General Public License for more details.
|
|
13 |
*
|
|
14 |
* You should have received a copy of the GNU General Public License along
|
|
15 |
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
16 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
17 |
*
|
|
18 |
* Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com>
|
|
6147
by Jiří Klimeš
policy,dns: fix a race in looking up hostname and updating DNS (rh #877084) |
19 |
* Copyright (C) 2004 - 2013 Red Hat, Inc.
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
20 |
* Copyright (C) 2005 - 2008 Novell, Inc.
|
21 |
* and others
|
|
22 |
*/
|
|
23 |
||
24 |
#include "config.h" |
|
25 |
||
6337
by Dan Winship
dns-manager: minor cleanups |
26 |
#include <errno.h> |
27 |
#include <resolv.h> |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
28 |
#include <stdlib.h> |
6337
by Dan Winship
dns-manager: minor cleanups |
29 |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
30 |
#include <glib.h> |
31 |
#include <glib/gi18n.h> |
|
32 |
||
33 |
#include "nm-dns-manager.h" |
|
34 |
#include "nm-ip4-config.h" |
|
35 |
#include "nm-ip6-config.h" |
|
36 |
#include "nm-logging.h" |
|
37 |
#include "NetworkManagerUtils.h" |
|
5553
by Jiří Klimeš
core: unblock signals for child processes we spawn out of NM (rh #739836) |
38 |
#include "nm-posix-signals.h" |
6328
by Dan Winship
core: don't pass config data to NMDHCPManager and NMDnsManager |
39 |
#include "nm-config.h" |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
40 |
|
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
41 |
#include "nm-dns-plugin.h" |
4249.7.2
by Dan Williams
dns: first cut of a dnsmasq local caching plugin |
42 |
#include "nm-dns-dnsmasq.h" |
43 |
||
6337
by Dan Winship
dns-manager: minor cleanups |
44 |
G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
45 |
|
46 |
#define NM_DNS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
|
|
47 |
NM_TYPE_DNS_MANAGER, \
|
|
48 |
NMDnsManagerPrivate))
|
|
49 |
||
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
50 |
#define HASH_LEN 20
|
51 |
||
4612
by Dan Williams
dns: write usable resolv.conf on shutdown if DNS plugins are used |
52 |
typedef struct { |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
53 |
NMIP4Config *ip4_vpn_config; |
54 |
NMIP4Config *ip4_device_config; |
|
55 |
NMIP6Config *ip6_vpn_config; |
|
56 |
NMIP6Config *ip6_device_config; |
|
57 |
GSList *configs; |
|
58 |
char *hostname; |
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
59 |
guint updates_queue; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
60 |
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
61 |
guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */ |
62 |
guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */ |
|
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
63 |
|
6339
by Dan Winship
dns-manager: add dns=none |
64 |
gboolean manage_dns; |
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
65 |
NMDnsPlugin *plugin; |
4249.7.1
by Dan Williams
core: add DNS plugin config options |
66 |
|
6127
by Dan Williams
core: track which interface an IP config came from |
67 |
gboolean dns_touched; |
4612
by Dan Williams
dns: write usable resolv.conf on shutdown if DNS plugins are used |
68 |
} NMDnsManagerPrivate; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
69 |
|
6147
by Jiří Klimeš
policy,dns: fix a race in looking up hostname and updating DNS (rh #877084) |
70 |
enum { |
71 |
CONFIG_CHANGED, |
|
72 |
||
73 |
LAST_SIGNAL
|
|
74 |
};
|
|
75 |
||
76 |
static guint signals[LAST_SIGNAL] = { 0 }; |
|
77 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
78 |
|
79 |
typedef struct { |
|
80 |
GPtrArray *nameservers; |
|
81 |
const char *domain; |
|
82 |
GPtrArray *searches; |
|
83 |
const char *nis_domain; |
|
84 |
GPtrArray *nis_servers; |
|
85 |
} NMResolvConfData; |
|
86 |
||
87 |
static void |
|
88 |
add_string_item (GPtrArray *array, const char *str) |
|
89 |
{
|
|
90 |
int i; |
|
91 |
||
92 |
g_return_if_fail (array != NULL); |
|
93 |
g_return_if_fail (str != NULL); |
|
94 |
||
95 |
/* Check for dupes before adding */
|
|
96 |
for (i = 0; i < array->len; i++) { |
|
97 |
const char *candidate = g_ptr_array_index (array, i); |
|
98 |
||
99 |
if (candidate && !strcmp (candidate, str)) |
|
100 |
return; |
|
101 |
}
|
|
102 |
||
103 |
/* No dupes, add the new item */
|
|
104 |
g_ptr_array_add (array, g_strdup (str)); |
|
105 |
}
|
|
106 |
||
107 |
static void |
|
108 |
merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src) |
|
109 |
{
|
|
110 |
guint32 num, i; |
|
111 |
||
112 |
num = nm_ip4_config_get_num_nameservers (src); |
|
113 |
for (i = 0; i < num; i++) { |
|
114 |
struct in_addr addr; |
|
115 |
char buf[INET_ADDRSTRLEN]; |
|
116 |
||
117 |
addr.s_addr = nm_ip4_config_get_nameserver (src, i); |
|
118 |
if (inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN) > 0) |
|
119 |
add_string_item (rc->nameservers, buf); |
|
120 |
}
|
|
121 |
||
122 |
num = nm_ip4_config_get_num_domains (src); |
|
123 |
for (i = 0; i < num; i++) { |
|
124 |
const char *domain; |
|
125 |
||
126 |
domain = nm_ip4_config_get_domain (src, i); |
|
127 |
if (!rc->domain) |
|
128 |
rc->domain = domain; |
|
129 |
add_string_item (rc->searches, domain); |
|
130 |
}
|
|
131 |
||
132 |
num = nm_ip4_config_get_num_searches (src); |
|
133 |
for (i = 0; i < num; i++) |
|
134 |
add_string_item (rc->searches, nm_ip4_config_get_search (src, i)); |
|
135 |
||
136 |
/* NIS stuff */
|
|
137 |
num = nm_ip4_config_get_num_nis_servers (src); |
|
138 |
for (i = 0; i < num; i++) { |
|
139 |
struct in_addr addr; |
|
140 |
char buf[INET_ADDRSTRLEN]; |
|
141 |
||
142 |
addr.s_addr = nm_ip4_config_get_nis_server (src, i); |
|
143 |
if (inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN) > 0) |
|
144 |
add_string_item (rc->nis_servers, buf); |
|
145 |
}
|
|
146 |
||
147 |
if (nm_ip4_config_get_nis_domain (src)) { |
|
148 |
/* FIXME: handle multiple domains */
|
|
149 |
if (!rc->nis_domain) |
|
150 |
rc->nis_domain = nm_ip4_config_get_nis_domain (src); |
|
151 |
}
|
|
152 |
}
|
|
153 |
||
154 |
static void |
|
6127
by Dan Williams
core: track which interface an IP config came from |
155 |
merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
156 |
{
|
157 |
guint32 num, i; |
|
6127
by Dan Williams
core: track which interface an IP config came from |
158 |
const char *iface; |
159 |
||
160 |
iface = g_object_get_data (G_OBJECT (src), IP_CONFIG_IFACE_TAG); |
|
161 |
g_assert (iface); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
162 |
|
163 |
num = nm_ip6_config_get_num_nameservers (src); |
|
164 |
for (i = 0; i < num; i++) { |
|
165 |
const struct in6_addr *addr; |
|
166 |
char buf[INET6_ADDRSTRLEN]; |
|
6127
by Dan Williams
core: track which interface an IP config came from |
167 |
char *tmp; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
168 |
|
169 |
addr = nm_ip6_config_get_nameserver (src, i); |
|
170 |
||
171 |
/* inet_ntop is probably supposed to do this for us, but it doesn't */
|
|
172 |
if (IN6_IS_ADDR_V4MAPPED (addr)) { |
|
173 |
if (inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, INET_ADDRSTRLEN) > 0) |
|
174 |
add_string_item (rc->nameservers, buf); |
|
175 |
} else { |
|
4807
by Jiří Klimeš
dns: append %interface to link-local IPv6 addresses in resolv.conf (rh #720001) |
176 |
if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0) { |
177 |
if (IN6_IS_ADDR_LINKLOCAL (addr) && strchr (buf, '%') == NULL) { |
|
178 |
tmp = g_strdup_printf ("%s%%%s", buf, iface); |
|
179 |
add_string_item (rc->nameservers, tmp); |
|
180 |
g_free (tmp); |
|
181 |
} else |
|
182 |
add_string_item (rc->nameservers, buf); |
|
183 |
}
|
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
184 |
}
|
185 |
}
|
|
186 |
||
187 |
num = nm_ip6_config_get_num_domains (src); |
|
188 |
for (i = 0; i < num; i++) { |
|
189 |
const char *domain; |
|
190 |
||
191 |
domain = nm_ip6_config_get_domain (src, i); |
|
192 |
if (!rc->domain) |
|
193 |
rc->domain = domain; |
|
194 |
add_string_item (rc->searches, domain); |
|
195 |
}
|
|
196 |
||
197 |
num = nm_ip6_config_get_num_searches (src); |
|
198 |
for (i = 0; i < num; i++) |
|
199 |
add_string_item (rc->searches, nm_ip6_config_get_search (src, i)); |
|
200 |
}
|
|
201 |
||
202 |
||
5869
by Pavel Šimerda
distro: add --with-netconfig option for SUSE |
203 |
#if defined(NETCONFIG_PATH)
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
204 |
/**********************************/
|
205 |
/* SUSE */
|
|
206 |
||
207 |
static void |
|
208 |
netconfig_child_setup (gpointer user_data G_GNUC_UNUSED) |
|
209 |
{
|
|
210 |
pid_t pid = getpid (); |
|
211 |
setpgid (pid, pid); |
|
5553
by Jiří Klimeš
core: unblock signals for child processes we spawn out of NM (rh #739836) |
212 |
|
213 |
/*
|
|
214 |
* We blocked signals in main(). We need to restore original signal
|
|
215 |
* mask for netconfig here so that it can receive signals.
|
|
216 |
*/
|
|
217 |
nm_unblock_posix_signals (NULL); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
218 |
}
|
219 |
||
220 |
static GPid |
|
221 |
run_netconfig (GError **error, gint *stdin_fd) |
|
222 |
{
|
|
223 |
char *argv[5]; |
|
224 |
char *tmp; |
|
225 |
GPid pid = -1; |
|
226 |
||
5869
by Pavel Šimerda
distro: add --with-netconfig option for SUSE |
227 |
argv[0] = NETCONFIG_PATH; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
228 |
argv[1] = "modify"; |
229 |
argv[2] = "--service"; |
|
230 |
argv[3] = "NetworkManager"; |
|
231 |
argv[4] = NULL; |
|
232 |
||
233 |
tmp = g_strjoinv (" ", argv); |
|
234 |
nm_log_dbg (LOGD_DNS, "spawning '%s'", tmp); |
|
235 |
g_free (tmp); |
|
236 |
||
237 |
if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, netconfig_child_setup, |
|
238 |
NULL, &pid, stdin_fd, NULL, NULL, error)) |
|
239 |
return -1; |
|
240 |
||
241 |
return pid; |
|
242 |
}
|
|
243 |
||
244 |
static void |
|
245 |
write_to_netconfig (gint fd, const char *key, const char *value) |
|
246 |
{
|
|
247 |
char *str; |
|
248 |
int x; |
|
249 |
||
250 |
str = g_strdup_printf ("%s='%s'\n", key, value); |
|
251 |
nm_log_dbg (LOGD_DNS, "writing to netconfig: %s", str); |
|
252 |
x = write (fd, str, strlen (str)); |
|
253 |
g_free (str); |
|
254 |
}
|
|
255 |
||
256 |
static gboolean |
|
257 |
dispatch_netconfig (const char *domain, |
|
258 |
char **searches, |
|
259 |
char **nameservers, |
|
260 |
const char *nis_domain, |
|
261 |
char **nis_servers, |
|
262 |
GError **error) |
|
263 |
{
|
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
264 |
char *str, *tmp; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
265 |
GPid pid; |
266 |
gint fd; |
|
267 |
int ret; |
|
268 |
||
269 |
pid = run_netconfig (error, &fd); |
|
270 |
if (pid < 0) |
|
271 |
return FALSE; |
|
272 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
273 |
/* NM is writing already-merged DNS information to netconfig, so it
|
274 |
* does not apply to a specific network interface.
|
|
275 |
*/
|
|
276 |
write_to_netconfig (fd, "INTERFACE", "NetworkManager"); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
277 |
|
278 |
if (searches) { |
|
279 |
str = g_strjoinv (" ", searches); |
|
280 |
||
281 |
if (domain) { |
|
282 |
tmp = g_strconcat (domain, " ", str, NULL); |
|
283 |
g_free (str); |
|
284 |
str = tmp; |
|
285 |
}
|
|
286 |
||
287 |
write_to_netconfig (fd, "DNSSEARCH", str); |
|
288 |
g_free (str); |
|
289 |
}
|
|
290 |
||
291 |
if (nameservers) { |
|
4249.7.10
by Dan Williams
dns: write only 127.0.0.1 to resolv.conf when caching |
292 |
str = g_strjoinv (" ", nameservers); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
293 |
write_to_netconfig (fd, "DNSSERVERS", str); |
294 |
g_free (str); |
|
295 |
}
|
|
296 |
||
297 |
if (nis_domain) |
|
298 |
write_to_netconfig (fd, "NISDOMAIN", nis_domain); |
|
299 |
||
300 |
if (nis_servers) { |
|
301 |
str = g_strjoinv (" ", nis_servers); |
|
302 |
write_to_netconfig (fd, "NISSERVERS", str); |
|
303 |
g_free (str); |
|
304 |
}
|
|
305 |
||
306 |
close (fd); |
|
307 |
||
308 |
/* Wait until the process exits */
|
|
309 |
||
310 |
again: |
|
311 |
||
312 |
ret = waitpid (pid, NULL, 0); |
|
313 |
if (ret < 0 && errno == EINTR) |
|
314 |
goto again; |
|
315 |
else if (ret < 0 && errno == ECHILD) { |
|
316 |
/* When the netconfig exist, the errno is ECHILD, it should return TRUE */
|
|
317 |
return TRUE; |
|
318 |
}
|
|
319 |
||
320 |
return ret > 0; |
|
321 |
}
|
|
322 |
#endif
|
|
323 |
||
324 |
||
325 |
static gboolean |
|
326 |
write_resolv_conf (FILE *f, const char *domain, |
|
327 |
char **searches, |
|
328 |
char **nameservers, |
|
329 |
GError **error) |
|
330 |
{
|
|
331 |
char *domain_str = NULL; |
|
332 |
char *searches_str = NULL; |
|
333 |
char *nameservers_str = NULL; |
|
334 |
int i; |
|
335 |
gboolean retval = FALSE; |
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
336 |
GString *str; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
337 |
|
338 |
if (fprintf (f, "%s","# Generated by NetworkManager\n") < 0) { |
|
339 |
g_set_error (error, |
|
340 |
NM_DNS_MANAGER_ERROR, |
|
341 |
NM_DNS_MANAGER_ERROR_SYSTEM, |
|
6337
by Dan Winship
dns-manager: minor cleanups |
342 |
"Could not write " _PATH_RESCONF ": %s\n", |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
343 |
g_strerror (errno)); |
344 |
return FALSE; |
|
345 |
}
|
|
346 |
||
347 |
if (domain) |
|
348 |
domain_str = g_strconcat ("domain ", domain, "\n", NULL); |
|
349 |
||
350 |
if (searches) { |
|
351 |
char *tmp_str; |
|
352 |
||
353 |
tmp_str = g_strjoinv (" ", searches); |
|
354 |
searches_str = g_strconcat ("search ", tmp_str, "\n", NULL); |
|
355 |
g_free (tmp_str); |
|
356 |
}
|
|
357 |
||
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
358 |
str = g_string_new (""); |
359 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
360 |
if (nameservers) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
361 |
int num = g_strv_length (nameservers); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
362 |
|
363 |
for (i = 0; i < num; i++) { |
|
4249.7.10
by Dan Williams
dns: write only 127.0.0.1 to resolv.conf when caching |
364 |
if (i == 3) { |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
365 |
g_string_append (str, "# "); |
366 |
g_string_append (str, _("NOTE: the libc resolver may not support more than 3 nameservers.")); |
|
367 |
g_string_append (str, "\n# "); |
|
368 |
g_string_append (str, _("The nameservers listed below may not be recognized.")); |
|
369 |
g_string_append_c (str, '\n'); |
|
370 |
}
|
|
371 |
||
372 |
g_string_append (str, "nameserver "); |
|
373 |
g_string_append (str, nameservers[i]); |
|
374 |
g_string_append_c (str, '\n'); |
|
375 |
}
|
|
376 |
}
|
|
377 |
||
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
378 |
nameservers_str = g_string_free (str, FALSE); |
379 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
380 |
if (fprintf (f, "%s%s%s", |
381 |
domain_str ? domain_str : "", |
|
382 |
searches_str ? searches_str : "", |
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
383 |
strlen (nameservers_str) ? nameservers_str : "") != -1) |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
384 |
retval = TRUE; |
385 |
||
386 |
g_free (domain_str); |
|
387 |
g_free (searches_str); |
|
388 |
g_free (nameservers_str); |
|
389 |
||
390 |
return retval; |
|
391 |
}
|
|
392 |
||
393 |
#ifdef RESOLVCONF_PATH
|
|
394 |
static gboolean |
|
395 |
dispatch_resolvconf (const char *domain, |
|
396 |
char **searches, |
|
397 |
char **nameservers, |
|
398 |
GError **error) |
|
399 |
{
|
|
400 |
char *cmd; |
|
401 |
FILE *f; |
|
402 |
gboolean retval = FALSE; |
|
403 |
||
404 |
if (! g_file_test (RESOLVCONF_PATH, G_FILE_TEST_IS_EXECUTABLE)) |
|
405 |
return FALSE; |
|
406 |
||
407 |
if (domain || searches || nameservers) { |
|
408 |
cmd = g_strconcat (RESOLVCONF_PATH, " -a ", "NetworkManager", NULL); |
|
6127
by Dan Williams
core: track which interface an IP config came from |
409 |
nm_log_info (LOGD_DNS, "Writing DNS information to %s", RESOLVCONF_PATH); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
410 |
if ((f = popen (cmd, "w")) == NULL) |
411 |
g_set_error (error, |
|
412 |
NM_DNS_MANAGER_ERROR, |
|
413 |
NM_DNS_MANAGER_ERROR_SYSTEM, |
|
414 |
"Could not write to %s: %s\n", |
|
415 |
RESOLVCONF_PATH, |
|
416 |
g_strerror (errno)); |
|
417 |
else { |
|
4249.7.10
by Dan Williams
dns: write only 127.0.0.1 to resolv.conf when caching |
418 |
retval = write_resolv_conf (f, domain, searches, nameservers, error); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
419 |
retval &= (pclose (f) == 0); |
420 |
}
|
|
421 |
} else { |
|
422 |
cmd = g_strconcat (RESOLVCONF_PATH, " -d ", "NetworkManager", NULL); |
|
6127
by Dan Williams
core: track which interface an IP config came from |
423 |
nm_log_info (LOGD_DNS, "Removing DNS information from %s", RESOLVCONF_PATH); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
424 |
if (nm_spawn_process (cmd) == 0) |
425 |
retval = TRUE; |
|
426 |
}
|
|
427 |
||
428 |
g_free (cmd); |
|
429 |
||
430 |
return retval; |
|
431 |
}
|
|
432 |
#endif
|
|
433 |
||
434 |
static gboolean |
|
435 |
update_resolv_conf (const char *domain, |
|
436 |
char **searches, |
|
437 |
char **nameservers, |
|
438 |
GError **error) |
|
439 |
{
|
|
440 |
char *tmp_resolv_conf; |
|
441 |
char *tmp_resolv_conf_realpath; |
|
442 |
char *resolv_conf_realpath; |
|
443 |
FILE *f; |
|
444 |
int do_rename = 1; |
|
445 |
int old_errno = 0; |
|
446 |
||
447 |
g_return_val_if_fail (error != NULL, FALSE); |
|
448 |
||
449 |
/* Find the real path of resolv.conf; it could be a symlink to something */
|
|
6337
by Dan Winship
dns-manager: minor cleanups |
450 |
resolv_conf_realpath = realpath (_PATH_RESCONF, NULL); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
451 |
if (!resolv_conf_realpath) |
6337
by Dan Winship
dns-manager: minor cleanups |
452 |
resolv_conf_realpath = strdup (_PATH_RESCONF); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
453 |
|
454 |
/* Build up the real path for the temp resolv.conf that we're about to
|
|
455 |
* write out.
|
|
456 |
*/
|
|
457 |
tmp_resolv_conf = g_strdup_printf ("%s.tmp", resolv_conf_realpath); |
|
458 |
tmp_resolv_conf_realpath = realpath (tmp_resolv_conf, NULL); |
|
459 |
if (!tmp_resolv_conf_realpath) |
|
460 |
tmp_resolv_conf_realpath = strdup (tmp_resolv_conf); |
|
461 |
g_free (tmp_resolv_conf); |
|
462 |
tmp_resolv_conf = NULL; |
|
463 |
||
464 |
if ((f = fopen (tmp_resolv_conf_realpath, "w")) == NULL) { |
|
465 |
do_rename = 0; |
|
466 |
old_errno = errno; |
|
6337
by Dan Winship
dns-manager: minor cleanups |
467 |
if ((f = fopen (_PATH_RESCONF, "w")) == NULL) { |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
468 |
g_set_error (error, |
469 |
NM_DNS_MANAGER_ERROR, |
|
470 |
NM_DNS_MANAGER_ERROR_SYSTEM, |
|
471 |
"Could not open %s: %s\nCould not open %s: %s\n", |
|
472 |
tmp_resolv_conf_realpath, |
|
473 |
g_strerror (old_errno), |
|
6337
by Dan Winship
dns-manager: minor cleanups |
474 |
_PATH_RESCONF, |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
475 |
g_strerror (errno)); |
476 |
goto out; |
|
477 |
}
|
|
478 |
/* Update tmp_resolv_conf_realpath so the error message on fclose()
|
|
479 |
* failure will be correct.
|
|
480 |
*/
|
|
6337
by Dan Winship
dns-manager: minor cleanups |
481 |
strcpy (tmp_resolv_conf_realpath, _PATH_RESCONF); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
482 |
}
|
483 |
||
4249.7.10
by Dan Williams
dns: write only 127.0.0.1 to resolv.conf when caching |
484 |
write_resolv_conf (f, domain, searches, nameservers, error); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
485 |
|
486 |
if (fclose (f) < 0) { |
|
487 |
if (*error == NULL) { |
|
488 |
/* only set an error here if write_resolv_conf() was successful,
|
|
489 |
* since its error is more important.
|
|
490 |
*/
|
|
491 |
g_set_error (error, |
|
492 |
NM_DNS_MANAGER_ERROR, |
|
493 |
NM_DNS_MANAGER_ERROR_SYSTEM, |
|
494 |
"Could not close %s: %s\n", |
|
495 |
tmp_resolv_conf_realpath, |
|
496 |
g_strerror (errno)); |
|
497 |
}
|
|
498 |
}
|
|
499 |
||
500 |
/* Don't rename the tempfile over top of the existing resolv.conf if there
|
|
501 |
* was an error writing it out.
|
|
502 |
*/
|
|
503 |
if (*error == NULL && do_rename) { |
|
504 |
if (rename (tmp_resolv_conf_realpath, resolv_conf_realpath) < 0) { |
|
505 |
g_set_error (error, |
|
506 |
NM_DNS_MANAGER_ERROR, |
|
507 |
NM_DNS_MANAGER_ERROR_SYSTEM, |
|
6337
by Dan Winship
dns-manager: minor cleanups |
508 |
"Could not replace " _PATH_RESCONF ": %s\n", |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
509 |
g_strerror (errno)); |
510 |
}
|
|
511 |
}
|
|
512 |
||
513 |
out: |
|
514 |
free (tmp_resolv_conf_realpath); |
|
515 |
free (resolv_conf_realpath); |
|
516 |
return *error ? FALSE : TRUE; |
|
517 |
}
|
|
518 |
||
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
519 |
static void |
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
520 |
compute_hash (NMDnsManager *self, guint8 buffer[HASH_LEN]) |
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
521 |
{
|
522 |
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); |
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
523 |
GChecksum *sum; |
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
524 |
GSList *iter; |
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
525 |
gsize len = HASH_LEN; |
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
526 |
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
527 |
sum = g_checksum_new (G_CHECKSUM_SHA1); |
528 |
g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); |
|
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
529 |
|
530 |
if (priv->ip4_vpn_config) |
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
531 |
nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE); |
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
532 |
if (priv->ip4_device_config) |
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
533 |
nm_ip4_config_hash (priv->ip4_device_config, sum, TRUE); |
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
534 |
|
535 |
if (priv->ip6_vpn_config) |
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
536 |
nm_ip6_config_hash (priv->ip6_vpn_config, sum, TRUE); |
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
537 |
if (priv->ip6_device_config) |
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
538 |
nm_ip6_config_hash (priv->ip6_device_config, sum, TRUE); |
539 |
||
540 |
/* add any other configs we know about */
|
|
541 |
for (iter = priv->configs; iter; iter = g_slist_next (iter)) { |
|
542 |
if ( (iter->data == priv->ip4_vpn_config) |
|
543 |
&& (iter->data == priv->ip4_device_config) |
|
544 |
&& (iter->data == priv->ip6_vpn_config) |
|
545 |
&& (iter->data == priv->ip6_device_config)) |
|
546 |
continue; |
|
547 |
||
548 |
if (NM_IS_IP4_CONFIG (iter->data)) |
|
549 |
nm_ip4_config_hash (NM_IP4_CONFIG (iter->data), sum, TRUE); |
|
550 |
else if (NM_IS_IP6_CONFIG (iter->data)) |
|
551 |
nm_ip6_config_hash (NM_IP6_CONFIG (iter->data), sum, TRUE); |
|
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
552 |
}
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
553 |
|
554 |
g_checksum_get_digest (sum, buffer, &len); |
|
555 |
g_checksum_free (sum); |
|
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
556 |
}
|
557 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
558 |
static gboolean |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
559 |
update_dns (NMDnsManager *self, |
560 |
gboolean no_caching, |
|
561 |
GError **error) |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
562 |
{
|
563 |
NMDnsManagerPrivate *priv; |
|
564 |
NMResolvConfData rc; |
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
565 |
GSList *iter, *vpn_configs = NULL, *dev_configs = NULL, *other_configs = NULL; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
566 |
const char *domain = NULL; |
567 |
const char *nis_domain = NULL; |
|
568 |
char **searches = NULL; |
|
569 |
char **nameservers = NULL; |
|
570 |
char **nis_servers = NULL; |
|
571 |
int num, i, len; |
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
572 |
gboolean success = FALSE, caching = FALSE; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
573 |
|
574 |
g_return_val_if_fail (error != NULL, FALSE); |
|
575 |
g_return_val_if_fail (*error == NULL, FALSE); |
|
576 |
||
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
577 |
priv = NM_DNS_MANAGER_GET_PRIVATE (self); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
578 |
|
6339
by Dan Winship
dns-manager: add dns=none |
579 |
if (!priv->manage_dns) |
580 |
return TRUE; |
|
581 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
582 |
priv->dns_touched = TRUE; |
583 |
||
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
584 |
nm_log_dbg (LOGD_DNS, "updating resolv.conf"); |
585 |
||
4249.7.5
by Dan Williams
dns: only write out new DNS config if it really changed |
586 |
/* Update hash with config we're applying */
|
587 |
compute_hash (self, priv->hash); |
|
588 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
589 |
rc.nameservers = g_ptr_array_new (); |
590 |
rc.domain = NULL; |
|
591 |
rc.searches = g_ptr_array_new (); |
|
4249.1.440
by Jiří Klimeš
dns: fix a crash due to uninitialized nis_domain (novell #655685) |
592 |
rc.nis_domain = NULL; |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
593 |
rc.nis_servers = g_ptr_array_new (); |
594 |
||
595 |
if (priv->ip4_vpn_config) |
|
596 |
merge_one_ip4_config (&rc, priv->ip4_vpn_config); |
|
597 |
if (priv->ip4_device_config) |
|
598 |
merge_one_ip4_config (&rc, priv->ip4_device_config); |
|
599 |
||
600 |
if (priv->ip6_vpn_config) |
|
6127
by Dan Williams
core: track which interface an IP config came from |
601 |
merge_one_ip6_config (&rc, priv->ip6_vpn_config); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
602 |
if (priv->ip6_device_config) |
6127
by Dan Williams
core: track which interface an IP config came from |
603 |
merge_one_ip6_config (&rc, priv->ip6_device_config); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
604 |
|
605 |
for (iter = priv->configs; iter; iter = g_slist_next (iter)) { |
|
606 |
if ( (iter->data == priv->ip4_vpn_config) |
|
607 |
|| (iter->data == priv->ip4_device_config) |
|
608 |
|| (iter->data == priv->ip6_vpn_config) |
|
609 |
|| (iter->data == priv->ip6_device_config)) |
|
610 |
continue; |
|
611 |
||
612 |
if (NM_IS_IP4_CONFIG (iter->data)) { |
|
613 |
NMIP4Config *config = NM_IP4_CONFIG (iter->data); |
|
614 |
||
615 |
merge_one_ip4_config (&rc, config); |
|
616 |
} else if (NM_IS_IP6_CONFIG (iter->data)) { |
|
617 |
NMIP6Config *config = NM_IP6_CONFIG (iter->data); |
|
618 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
619 |
merge_one_ip6_config (&rc, config); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
620 |
} else |
621 |
g_assert_not_reached (); |
|
622 |
}
|
|
623 |
||
624 |
/* Add the current domain name (from the hostname) to the searches list;
|
|
625 |
* see rh #600407. The bug report is that when the hostname is set to
|
|
626 |
* something like 'dcbw.foobar.com' (ie an FQDN) that pinging 'dcbw' doesn't
|
|
627 |
* work because the resolver doesn't have anything to append to 'dcbw' when
|
|
628 |
* looking it up.
|
|
629 |
*/
|
|
630 |
if (priv->hostname) { |
|
631 |
const char *hostsearch = strchr (priv->hostname, '.'); |
|
632 |
||
633 |
/* +1 to get rid of the dot */
|
|
634 |
if (hostsearch && strlen (hostsearch + 1)) |
|
635 |
add_string_item (rc.searches, hostsearch + 1); |
|
636 |
}
|
|
637 |
||
638 |
domain = rc.domain; |
|
639 |
||
640 |
/* Per 'man resolv.conf', the search list is limited to 6 domains
|
|
641 |
* totalling 256 characters.
|
|
642 |
*/
|
|
643 |
num = MIN (rc.searches->len, 6); |
|
644 |
for (i = 0, len = 0; i < num; i++) { |
|
645 |
len += strlen (rc.searches->pdata[i]) + 1; /* +1 for spaces */ |
|
646 |
if (len > 256) |
|
647 |
break; |
|
648 |
}
|
|
649 |
g_ptr_array_set_size (rc.searches, i); |
|
650 |
if (rc.searches->len) { |
|
651 |
g_ptr_array_add (rc.searches, NULL); |
|
652 |
searches = (char **) g_ptr_array_free (rc.searches, FALSE); |
|
653 |
} else |
|
654 |
g_ptr_array_free (rc.searches, TRUE); |
|
655 |
||
656 |
if (rc.nameservers->len) { |
|
657 |
g_ptr_array_add (rc.nameservers, NULL); |
|
658 |
nameservers = (char **) g_ptr_array_free (rc.nameservers, FALSE); |
|
659 |
} else |
|
660 |
g_ptr_array_free (rc.nameservers, TRUE); |
|
661 |
||
662 |
if (rc.nis_servers->len) { |
|
663 |
g_ptr_array_add (rc.nis_servers, NULL); |
|
664 |
nis_servers = (char **) g_ptr_array_free (rc.nis_servers, FALSE); |
|
665 |
} else |
|
666 |
g_ptr_array_free (rc.nis_servers, TRUE); |
|
667 |
||
668 |
nis_domain = rc.nis_domain; |
|
669 |
||
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
670 |
/* Build up config lists for plugins; we use the raw configs here, not the
|
671 |
* merged information that we write to resolv.conf so that the plugins can
|
|
672 |
* still use the domain information in each config to provide split DNS if
|
|
673 |
* they want to.
|
|
674 |
*/
|
|
675 |
if (priv->ip4_vpn_config) |
|
676 |
vpn_configs = g_slist_append (vpn_configs, priv->ip4_vpn_config); |
|
677 |
if (priv->ip6_vpn_config) |
|
678 |
vpn_configs = g_slist_append (vpn_configs, priv->ip6_vpn_config); |
|
679 |
if (priv->ip4_device_config) |
|
680 |
dev_configs = g_slist_append (dev_configs, priv->ip4_device_config); |
|
681 |
if (priv->ip6_device_config) |
|
682 |
dev_configs = g_slist_append (dev_configs, priv->ip6_device_config); |
|
683 |
||
684 |
for (iter = priv->configs; iter; iter = g_slist_next (iter)) { |
|
685 |
if ( (iter->data != priv->ip4_vpn_config) |
|
686 |
&& (iter->data != priv->ip4_device_config) |
|
687 |
&& (iter->data != priv->ip6_vpn_config) |
|
688 |
&& (iter->data != priv->ip6_device_config)) |
|
689 |
other_configs = g_slist_append (other_configs, iter->data); |
|
690 |
}
|
|
691 |
||
692 |
/* Let any plugins do their thing first */
|
|
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
693 |
if (priv->plugin) { |
694 |
NMDnsPlugin *plugin = priv->plugin; |
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
695 |
const char *plugin_name = nm_dns_plugin_get_name (plugin); |
696 |
||
697 |
if (nm_dns_plugin_is_caching (plugin)) { |
|
698 |
if (no_caching) { |
|
699 |
nm_log_dbg (LOGD_DNS, "DNS: plugin %s ignored (caching disabled)", |
|
700 |
plugin_name); |
|
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
701 |
goto skip; |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
702 |
}
|
703 |
caching = TRUE; |
|
704 |
}
|
|
705 |
||
706 |
nm_log_dbg (LOGD_DNS, "DNS: updating plugin %s", plugin_name); |
|
707 |
if (!nm_dns_plugin_update (plugin, |
|
708 |
vpn_configs, |
|
709 |
dev_configs, |
|
710 |
other_configs, |
|
6127
by Dan Williams
core: track which interface an IP config came from |
711 |
priv->hostname)) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
712 |
nm_log_warn (LOGD_DNS, "DNS: plugin %s update failed", plugin_name); |
713 |
||
714 |
/* If the plugin failed to update, we shouldn't write out a local
|
|
715 |
* caching DNS configuration to resolv.conf.
|
|
716 |
*/
|
|
717 |
caching = FALSE; |
|
718 |
}
|
|
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
719 |
|
720 |
skip: |
|
721 |
;
|
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
722 |
}
|
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
723 |
|
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
724 |
g_slist_free (vpn_configs); |
725 |
g_slist_free (dev_configs); |
|
726 |
g_slist_free (other_configs); |
|
727 |
||
4249.7.10
by Dan Williams
dns: write only 127.0.0.1 to resolv.conf when caching |
728 |
/* If caching was successful, we only send 127.0.0.1 to /etc/resolv.conf
|
729 |
* to ensure that the glibc resolver doesn't try to round-robin nameservers,
|
|
730 |
* but only uses the local caching nameserver.
|
|
731 |
*/
|
|
732 |
if (caching) { |
|
733 |
if (nameservers) |
|
734 |
g_strfreev (nameservers); |
|
735 |
nameservers = g_new0 (char*, 2); |
|
736 |
nameservers[0] = g_strdup ("127.0.0.1"); |
|
737 |
}
|
|
738 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
739 |
#ifdef RESOLVCONF_PATH
|
6127
by Dan Williams
core: track which interface an IP config came from |
740 |
success = dispatch_resolvconf (domain, searches, nameservers, error); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
741 |
#endif
|
742 |
||
5869
by Pavel Šimerda
distro: add --with-netconfig option for SUSE |
743 |
#ifdef NETCONFIG_PATH
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
744 |
if (success == FALSE) { |
745 |
success = dispatch_netconfig (domain, searches, nameservers, |
|
6127
by Dan Williams
core: track which interface an IP config came from |
746 |
nis_domain, nis_servers, error); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
747 |
}
|
748 |
#endif
|
|
749 |
||
750 |
if (success == FALSE) |
|
6127
by Dan Williams
core: track which interface an IP config came from |
751 |
success = update_resolv_conf (domain, searches, nameservers, error); |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
752 |
|
6147
by Jiří Klimeš
policy,dns: fix a race in looking up hostname and updating DNS (rh #877084) |
753 |
/* signal that resolv.conf was changed */
|
754 |
if (success) |
|
755 |
g_signal_emit (self, signals[CONFIG_CHANGED], 0); |
|
756 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
757 |
if (searches) |
758 |
g_strfreev (searches); |
|
759 |
if (nameservers) |
|
760 |
g_strfreev (nameservers); |
|
761 |
if (nis_servers) |
|
762 |
g_strfreev (nis_servers); |
|
763 |
||
764 |
return success; |
|
765 |
}
|
|
766 |
||
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
767 |
static void |
768 |
plugin_failed (NMDnsPlugin *plugin, gpointer user_data) |
|
769 |
{
|
|
770 |
NMDnsManager *self = NM_DNS_MANAGER (user_data); |
|
771 |
GError *error = NULL; |
|
772 |
||
773 |
/* Errors with non-caching plugins aren't fatal */
|
|
774 |
if (!nm_dns_plugin_is_caching (plugin)) |
|
775 |
return; |
|
776 |
||
777 |
/* Disable caching until the next DNS update */
|
|
6127
by Dan Williams
core: track which interface an IP config came from |
778 |
if (!update_dns (self, TRUE, &error)) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
779 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", |
780 |
error ? error->code : -1, |
|
781 |
error && error->message ? error->message : "(unknown)"); |
|
782 |
g_clear_error (&error); |
|
783 |
}
|
|
784 |
}
|
|
785 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
786 |
gboolean
|
787 |
nm_dns_manager_add_ip4_config (NMDnsManager *mgr, |
|
788 |
const char *iface, |
|
789 |
NMIP4Config *config, |
|
790 |
NMDnsIPConfigType cfg_type) |
|
791 |
{
|
|
792 |
NMDnsManagerPrivate *priv; |
|
793 |
GError *error = NULL; |
|
794 |
||
795 |
g_return_val_if_fail (mgr != NULL, FALSE); |
|
796 |
g_return_val_if_fail (iface != NULL, FALSE); |
|
797 |
g_return_val_if_fail (config != NULL, FALSE); |
|
798 |
||
799 |
priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); |
|
800 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
801 |
g_object_set_data_full (G_OBJECT (config), IP_CONFIG_IFACE_TAG, g_strdup (iface), g_free); |
802 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
803 |
switch (cfg_type) { |
804 |
case NM_DNS_IP_CONFIG_TYPE_VPN: |
|
805 |
priv->ip4_vpn_config = config; |
|
806 |
break; |
|
807 |
case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE: |
|
808 |
priv->ip4_device_config = config; |
|
809 |
break; |
|
810 |
default: |
|
811 |
break; |
|
812 |
}
|
|
813 |
||
814 |
/* Don't allow the same zone added twice */
|
|
815 |
if (!g_slist_find (priv->configs, config)) |
|
816 |
priv->configs = g_slist_append (priv->configs, g_object_ref (config)); |
|
817 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
818 |
if (!priv->updates_queue && !update_dns (mgr, FALSE, &error)) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
819 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", |
820 |
error ? error->code : -1, |
|
821 |
error && error->message ? error->message : "(unknown)"); |
|
822 |
g_clear_error (&error); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
823 |
}
|
824 |
||
825 |
return TRUE; |
|
826 |
}
|
|
827 |
||
828 |
gboolean
|
|
6127
by Dan Williams
core: track which interface an IP config came from |
829 |
nm_dns_manager_remove_ip4_config (NMDnsManager *mgr, NMIP4Config *config) |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
830 |
{
|
831 |
NMDnsManagerPrivate *priv; |
|
832 |
GError *error = NULL; |
|
833 |
||
834 |
g_return_val_if_fail (mgr != NULL, FALSE); |
|
835 |
g_return_val_if_fail (config != NULL, FALSE); |
|
836 |
||
837 |
priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); |
|
838 |
||
839 |
/* Can't remove it if it wasn't in the list to begin with */
|
|
840 |
if (!g_slist_find (priv->configs, config)) |
|
841 |
return FALSE; |
|
842 |
||
843 |
priv->configs = g_slist_remove (priv->configs, config); |
|
844 |
||
845 |
if (config == priv->ip4_vpn_config) |
|
846 |
priv->ip4_vpn_config = NULL; |
|
847 |
if (config == priv->ip4_device_config) |
|
848 |
priv->ip4_device_config = NULL; |
|
849 |
||
850 |
g_object_unref (config); |
|
851 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
852 |
if (!priv->updates_queue && !update_dns (mgr, FALSE, &error)) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
853 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", |
854 |
error ? error->code : -1, |
|
855 |
error && error->message ? error->message : "(unknown)"); |
|
856 |
g_clear_error (&error); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
857 |
}
|
858 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
859 |
g_object_set_data (G_OBJECT (config), IP_CONFIG_IFACE_TAG, NULL); |
860 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
861 |
return TRUE; |
862 |
}
|
|
863 |
||
864 |
gboolean
|
|
865 |
nm_dns_manager_add_ip6_config (NMDnsManager *mgr, |
|
866 |
const char *iface, |
|
867 |
NMIP6Config *config, |
|
868 |
NMDnsIPConfigType cfg_type) |
|
869 |
{
|
|
870 |
NMDnsManagerPrivate *priv; |
|
871 |
GError *error = NULL; |
|
872 |
||
873 |
g_return_val_if_fail (mgr != NULL, FALSE); |
|
874 |
g_return_val_if_fail (iface != NULL, FALSE); |
|
875 |
g_return_val_if_fail (config != NULL, FALSE); |
|
876 |
||
877 |
priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); |
|
878 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
879 |
g_object_set_data_full (G_OBJECT (config), IP_CONFIG_IFACE_TAG, g_strdup (iface), g_free); |
880 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
881 |
switch (cfg_type) { |
882 |
case NM_DNS_IP_CONFIG_TYPE_VPN: |
|
883 |
priv->ip6_vpn_config = config; |
|
884 |
break; |
|
885 |
case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE: |
|
886 |
priv->ip6_device_config = config; |
|
887 |
break; |
|
888 |
default: |
|
889 |
break; |
|
890 |
}
|
|
891 |
||
892 |
/* Don't allow the same zone added twice */
|
|
893 |
if (!g_slist_find (priv->configs, config)) |
|
894 |
priv->configs = g_slist_append (priv->configs, g_object_ref (config)); |
|
895 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
896 |
if (!priv->updates_queue && !update_dns (mgr, FALSE, &error)) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
897 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", |
898 |
error ? error->code : -1, |
|
899 |
error && error->message ? error->message : "(unknown)"); |
|
900 |
g_clear_error (&error); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
901 |
}
|
902 |
||
903 |
return TRUE; |
|
904 |
}
|
|
905 |
||
906 |
gboolean
|
|
6127
by Dan Williams
core: track which interface an IP config came from |
907 |
nm_dns_manager_remove_ip6_config (NMDnsManager *mgr, NMIP6Config *config) |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
908 |
{
|
909 |
NMDnsManagerPrivate *priv; |
|
910 |
GError *error = NULL; |
|
911 |
||
912 |
g_return_val_if_fail (mgr != NULL, FALSE); |
|
913 |
g_return_val_if_fail (config != NULL, FALSE); |
|
914 |
||
915 |
priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); |
|
916 |
||
917 |
/* Can't remove it if it wasn't in the list to begin with */
|
|
918 |
if (!g_slist_find (priv->configs, config)) |
|
919 |
return FALSE; |
|
920 |
||
921 |
priv->configs = g_slist_remove (priv->configs, config); |
|
922 |
||
923 |
if (config == priv->ip6_vpn_config) |
|
924 |
priv->ip6_vpn_config = NULL; |
|
925 |
if (config == priv->ip6_device_config) |
|
926 |
priv->ip6_device_config = NULL; |
|
927 |
||
928 |
g_object_unref (config); |
|
929 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
930 |
if (!priv->updates_queue && !update_dns (mgr, FALSE, &error)) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
931 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", |
932 |
error ? error->code : -1, |
|
933 |
error && error->message ? error->message : "(unknown)"); |
|
934 |
g_clear_error (&error); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
935 |
}
|
936 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
937 |
g_object_set_data (G_OBJECT (config), IP_CONFIG_IFACE_TAG, NULL); |
938 |
||
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
939 |
return TRUE; |
940 |
}
|
|
941 |
||
942 |
void
|
|
943 |
nm_dns_manager_set_hostname (NMDnsManager *mgr, |
|
944 |
const char *hostname) |
|
945 |
{
|
|
946 |
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); |
|
947 |
GError *error = NULL; |
|
948 |
const char *filtered = NULL; |
|
949 |
||
950 |
/* Certain hostnames we don't want to include in resolv.conf 'searches' */
|
|
951 |
if ( hostname |
|
952 |
&& strcmp (hostname, "localhost.localdomain") |
|
953 |
&& strcmp (hostname, "localhost6.localdomain6") |
|
954 |
&& !strstr (hostname, ".in-addr.arpa") |
|
955 |
&& strchr (hostname, '.')) { |
|
956 |
filtered = hostname; |
|
957 |
}
|
|
958 |
||
959 |
if ( (!priv->hostname && !filtered) |
|
960 |
|| (priv->hostname && filtered && !strcmp (priv->hostname, filtered))) |
|
961 |
return; |
|
962 |
||
963 |
g_free (priv->hostname); |
|
964 |
priv->hostname = g_strdup (filtered); |
|
965 |
||
6127
by Dan Williams
core: track which interface an IP config came from |
966 |
if (!priv->updates_queue && !update_dns (mgr, FALSE, &error)) { |
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
967 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", |
968 |
error ? error->code : -1, |
|
969 |
error && error->message ? error->message : "(unknown)"); |
|
970 |
g_clear_error (&error); |
|
971 |
}
|
|
972 |
}
|
|
973 |
||
974 |
void
|
|
975 |
nm_dns_manager_begin_updates (NMDnsManager *mgr, const char *func) |
|
976 |
{
|
|
977 |
NMDnsManagerPrivate *priv; |
|
978 |
||
979 |
g_return_if_fail (mgr != NULL); |
|
980 |
priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); |
|
981 |
||
982 |
/* Save current hash when starting a new batch */
|
|
983 |
if (priv->updates_queue == 0) |
|
984 |
memcpy (priv->prev_hash, priv->hash, sizeof (priv->hash)); |
|
985 |
||
986 |
priv->updates_queue++; |
|
987 |
||
988 |
nm_log_dbg (LOGD_DNS, "(%s): queueing DNS updates (%d)", func, priv->updates_queue); |
|
989 |
}
|
|
990 |
||
991 |
void
|
|
992 |
nm_dns_manager_end_updates (NMDnsManager *mgr, const char *func) |
|
993 |
{
|
|
994 |
NMDnsManagerPrivate *priv; |
|
995 |
GError *error = NULL; |
|
996 |
gboolean changed; |
|
997 |
guint8 new[HASH_LEN]; |
|
998 |
||
999 |
g_return_if_fail (mgr != NULL); |
|
1000 |
||
1001 |
priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); |
|
1002 |
g_return_if_fail (priv->updates_queue > 0); |
|
1003 |
||
1004 |
compute_hash (mgr, new); |
|
1005 |
changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE; |
|
1006 |
nm_log_dbg (LOGD_DNS, "(%s): DNS configuration %s", __func__, changed ? "changed" : "did not change"); |
|
1007 |
||
1008 |
priv->updates_queue--; |
|
1009 |
if ((priv->updates_queue > 0) || (changed == FALSE)) { |
|
1010 |
nm_log_dbg (LOGD_DNS, "(%s): no DNS changes to commit (%d)", func, priv->updates_queue); |
|
1011 |
return; |
|
1012 |
}
|
|
1013 |
||
1014 |
/* Commit all the outstanding changes */
|
|
1015 |
nm_log_dbg (LOGD_DNS, "(%s): committing DNS changes (%d)", func, priv->updates_queue); |
|
6127
by Dan Williams
core: track which interface an IP config came from |
1016 |
if (!update_dns (mgr, FALSE, &error)) { |
4249.7.3
by Dan Williams
dns: hook plugins into DNS updates and make dnsmasq plugin actually work |
1017 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", |
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
1018 |
error ? error->code : -1, |
1019 |
error && error->message ? error->message : "(unknown)"); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1020 |
g_clear_error (&error); |
1021 |
}
|
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
1022 |
|
1023 |
memset (priv->prev_hash, 0, sizeof (priv->prev_hash)); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1024 |
}
|
1025 |
||
4249.7.1
by Dan Williams
core: add DNS plugin config options |
1026 |
/******************************************************************/
|
1027 |
||
1028 |
NMDnsManager * |
|
6328
by Dan Winship
core: don't pass config data to NMDHCPManager and NMDnsManager |
1029 |
nm_dns_manager_get (void) |
4249.7.1
by Dan Williams
core: add DNS plugin config options |
1030 |
{
|
1031 |
static NMDnsManager * singleton = NULL; |
|
1032 |
||
1033 |
if (!singleton) { |
|
1034 |
singleton = NM_DNS_MANAGER (g_object_new (NM_TYPE_DNS_MANAGER, NULL)); |
|
1035 |
g_assert (singleton); |
|
1036 |
} else |
|
1037 |
g_object_ref (singleton); |
|
1038 |
||
1039 |
return singleton; |
|
1040 |
}
|
|
1041 |
||
1042 |
GQuark
|
|
1043 |
nm_dns_manager_error_quark (void) |
|
1044 |
{
|
|
1045 |
static GQuark quark = 0; |
|
1046 |
if (!quark) |
|
1047 |
quark = g_quark_from_static_string ("nm_dns_manager_error"); |
|
1048 |
||
1049 |
return quark; |
|
1050 |
}
|
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1051 |
|
1052 |
static void |
|
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
1053 |
nm_dns_manager_init (NMDnsManager *self) |
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1054 |
{
|
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
1055 |
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); |
1056 |
const char *mode; |
|
1057 |
||
5606
by Dan Williams
dns: fix change hashing and add batch update functions |
1058 |
/* Set the initial hash */
|
1059 |
compute_hash (self, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); |
|
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
1060 |
|
1061 |
mode = nm_config_get_dns_mode (nm_config_get ()); |
|
6339
by Dan Winship
dns-manager: add dns=none |
1062 |
if (!g_strcmp0 (mode, "none")) { |
1063 |
priv->manage_dns = FALSE; |
|
1064 |
nm_log_info (LOGD_DNS, "DNS: not managing " _PATH_RESCONF); |
|
1065 |
} else { |
|
1066 |
priv->manage_dns = TRUE; |
|
1067 |
if (!g_strcmp0 (mode, "dnsmasq")) |
|
1068 |
priv->plugin = nm_dns_dnsmasq_new (); |
|
1069 |
else if (mode && g_strcmp0 (mode, "default") != 0) |
|
1070 |
nm_log_warn (LOGD_DNS, "Unknown DNS mode '%s'", mode); |
|
1071 |
}
|
|
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
1072 |
|
1073 |
if (priv->plugin) { |
|
1074 |
nm_log_info (LOGD_DNS, "DNS: loaded plugin %s", nm_dns_plugin_get_name (priv->plugin)); |
|
1075 |
g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); |
|
1076 |
}
|
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1077 |
}
|
1078 |
||
1079 |
static void |
|
4612
by Dan Williams
dns: write usable resolv.conf on shutdown if DNS plugins are used |
1080 |
dispose (GObject *object) |
1081 |
{
|
|
1082 |
NMDnsManager *self = NM_DNS_MANAGER (object); |
|
1083 |
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); |
|
1084 |
GError *error = NULL; |
|
1085 |
||
6338
by Dan Winship
dns-manager, config: make the dns config key single-valued |
1086 |
g_clear_object (&priv->plugin); |
6337
by Dan Winship
dns-manager: minor cleanups |
1087 |
|
1088 |
/* If we're quitting, leave a valid resolv.conf in place, not one
|
|
1089 |
* pointing to 127.0.0.1 if any plugins were active. Thus update
|
|
1090 |
* DNS after disposing of all plugins. But if we haven't done any
|
|
1091 |
* DNS updates yet, there's no reason to touch resolv.conf on shutdown.
|
|
1092 |
*/
|
|
1093 |
if (priv->dns_touched && !update_dns (self, TRUE, &error)) { |
|
1094 |
nm_log_warn (LOGD_DNS, "could not commit DNS changes on shutdown: (%d) %s", |
|
1095 |
error ? error->code : -1, |
|
1096 |
error && error->message ? error->message : "(unknown)"); |
|
1097 |
g_clear_error (&error); |
|
1098 |
priv->dns_touched = FALSE; |
|
4612
by Dan Williams
dns: write usable resolv.conf on shutdown if DNS plugins are used |
1099 |
}
|
1100 |
||
6337
by Dan Winship
dns-manager: minor cleanups |
1101 |
g_slist_free_full (priv->configs, g_object_unref); |
1102 |
priv->configs = NULL; |
|
1103 |
||
4612
by Dan Williams
dns: write usable resolv.conf on shutdown if DNS plugins are used |
1104 |
G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); |
1105 |
}
|
|
1106 |
||
1107 |
static void |
|
1108 |
finalize (GObject *object) |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1109 |
{
|
1110 |
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (object); |
|
1111 |
||
1112 |
g_free (priv->hostname); |
|
1113 |
||
1114 |
G_OBJECT_CLASS (nm_dns_manager_parent_class)->finalize (object); |
|
1115 |
}
|
|
1116 |
||
1117 |
static void |
|
1118 |
nm_dns_manager_class_init (NMDnsManagerClass *klass) |
|
1119 |
{
|
|
1120 |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
|
1121 |
||
6147
by Jiří Klimeš
policy,dns: fix a race in looking up hostname and updating DNS (rh #877084) |
1122 |
g_type_class_add_private (object_class, sizeof (NMDnsManagerPrivate)); |
1123 |
||
1124 |
/* virtual methods */
|
|
4612
by Dan Williams
dns: write usable resolv.conf on shutdown if DNS plugins are used |
1125 |
object_class->dispose = dispose; |
1126 |
object_class->finalize = finalize; |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1127 |
|
6147
by Jiří Klimeš
policy,dns: fix a race in looking up hostname and updating DNS (rh #877084) |
1128 |
/* signals */
|
1129 |
signals[CONFIG_CHANGED] = |
|
1130 |
g_signal_new ("config-changed", |
|
1131 |
G_OBJECT_CLASS_TYPE (object_class), |
|
1132 |
G_SIGNAL_RUN_FIRST, |
|
1133 |
G_STRUCT_OFFSET (NMDnsManagerClass, config_changed), |
|
1134 |
NULL, NULL, |
|
1135 |
g_cclosure_marshal_VOID__VOID, |
|
1136 |
G_TYPE_NONE, 0); |
|
4249.1.343
by Dan Williams
core: rename NMNamedManager -> NMDnsManager |
1137 |
}
|
1138 |