mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-26 21:40:08 +01:00
dns: better detect systemd-resolved when checking for resolv.conf symlink
We autodetect systemd-resolved based on whether /etc/resolv.conf points to one of the well known files of systemd-resolved. Extend the check by also - follow symlinks and compare the absolute link target - open the file and compare the inodes for hard-linking Note that when NetworkManager starts, systemd-resolved might not have started yet. So, while comparing the inode is the best check, we also compare symlinks (g_file_read_link() and realpath()). Based-on-patch-by: Sam Morris <sam@robots.org.uk> https://github.com/NetworkManager/NetworkManager/pull/16 https://bugzilla.gnome.org/show_bug.cgi?id=779269
This commit is contained in:
parent
e70dfb4df7
commit
fae84b16f8
1 changed files with 53 additions and 17 deletions
|
|
@ -1642,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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
g_clear_object(&info);
|
||||
g_clear_object(&f);
|
||||
/* 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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue