diff options
Diffstat (limited to 'src/dns/nm-dns-manager.c')
| -rw-r--r-- | src/dns/nm-dns-manager.c | 88 |
1 files changed, 66 insertions, 22 deletions
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 952468e3..d5392b7d 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -497,7 +497,7 @@ dispatch_netconfig (NMDnsManager *self, g_free (str); } - close (fd); + nm_close (fd); /* Wait until the process exits */ if (!nm_utils_kill_child_sync (pid, 0, LOGD_DNS, "netconfig", &status, 1000, 0)) { @@ -1167,9 +1167,16 @@ update_dns (NMDnsManager *self, * but only uses the local caching nameserver. */ if (caching) { + const char *lladdr = "127.0.0.1"; + + if (NM_IS_DNS_SYSTEMD_RESOLVED (priv->plugin)) { + /* systemd-resolved uses a different link-local address */ + lladdr = "127.0.0.53"; + } + g_strfreev (nameservers); - nameservers = g_new0 (char*, 2); - nameservers[0] = g_strdup ("127.0.0.1"); + nameservers = g_new0 (char *, 2); + nameservers[0] = g_strdup (lladdr); } if (update) { @@ -1427,6 +1434,7 @@ nm_dns_manager_set_initial_hostname (NMDnsManager *self, { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + g_free (priv->hostname); priv->hostname = g_strdup (hostname); } @@ -1625,7 +1633,7 @@ _check_resconf_immutable (NMDnsManagerResolvConfManager rc_manager) if (fd != -1) { if (ioctl (fd, FS_IOC_GETFLAGS, &flags) != -1) immutable = NM_FLAGS_HAS (flags, FS_IMMUTABLE_FL); - close (fd); + nm_close (fd); } return immutable ? NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE : rc_manager; } @@ -1634,32 +1642,68 @@ _check_resconf_immutable (NMDnsManagerResolvConfManager rc_manager) static gboolean _resolvconf_resolved_managed (void) { - static const char *const resolved_paths[] = { + static const char *const RESOLVED_PATHS[] = { "/run/systemd/resolve/resolv.conf", "/lib/systemd/resolv.conf", "/usr/lib/systemd/resolv.conf", }; - GFile *f; - GFileInfo *info; - gboolean ret = FALSE; + struct stat st, st_test; + guint i; - f = g_file_new_for_path (_PATH_RESCONF); - info = g_file_query_info (f, - G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK","\ - G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); + if (lstat (_PATH_RESCONF, &st) != 0) + return FALSE; - if (info && g_file_info_get_is_symlink (info)) { - ret = nm_utils_strv_find_first ((gchar **) resolved_paths, - G_N_ELEMENTS (resolved_paths), - g_file_info_get_symlink_target (info)) >= 0; - } + if (S_ISLNK (st.st_mode)) { + gs_free char *full_path = NULL; + nm_auto_free char *real_path = NULL; + + /* see if resolv.conf is a symlink with a target that is + * exactly like one of the candidates. + * + * This check will work for symlinks, even if the target + * does not exist and realpath() cannot resolve anything. + * + * We want to handle that, because systemd-resolved might not + * have started yet. */ + full_path = g_file_read_link (_PATH_RESCONF, NULL); + if (nm_utils_strv_find_first ((char **) RESOLVED_PATHS, + G_N_ELEMENTS (RESOLVED_PATHS), + full_path) >= 0) + return TRUE; + + /* see if resolv.conf is a symlink that resolves exactly one + * of the candidate paths. + * + * This check will work for symlinks that can be resolved + * to a realpath, but the actual file might not exist. + * + * We want to handle that, because systemd-resolved might not + * have started yet. */ + real_path = realpath (_PATH_RESCONF, NULL); + if (nm_utils_strv_find_first ((char **) RESOLVED_PATHS, + G_N_ELEMENTS (RESOLVED_PATHS), + real_path) >= 0) + return TRUE; - g_clear_object(&info); - g_clear_object(&f); + /* fall-through and resolve the symlink, to check the file + * it points to (below). + * + * This check is the most reliable, but it only works if + * systemd-resolved already started and created the file. */ + if (stat (_PATH_RESCONF, &st) != 0) + return FALSE; + } + + /* see if resolv.conf resolves to one of the candidate + * paths (or whether it is hard-linked). */ + for (i = 0; i < G_N_ELEMENTS (RESOLVED_PATHS); i++) { + if ( stat (RESOLVED_PATHS[i], &st_test) == 0 + && st.st_dev == st_test.st_dev + && st.st_ino == st_test.st_ino) + return TRUE; + } - return ret; + return FALSE; } static void |