summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-08-07 19:43:35 +0200
committerThomas Haller <thaller@redhat.com>2020-08-24 16:10:42 +0200
commit606f97ad548591e10579822df3e691e0761d30eb (patch)
tree76142b79b22cc48797d5ee63e42289860ca6994a
parent059d02ed3f90b94580c73c34fdd8ba50705e7c7d (diff)
downloadNetworkManager-th/dns-rc-manager-auto.tar.gz
dns: add new "rc-manager=auto" modeth/dns-rc-manager-auto
Add a new `main.rc-manager=auto` setting, that favours to use systemd-resolved (and not touch "/etc/resolv.conf" but configure it via D-Bus), or falls back to `resolvconf`/`netconfig` binaries if they are installed and enabled at compile time. As final fallback use "symlink", like before. Note that on Fedora there is no "openresolv" package ([1]). Instead, "systemd" package provides "/usr/sbin/resolvconf" as a wrapper for systemd-resolved's "resolvectl". On such a system the fallback to resolvconf is always wrong, because NetworkManager should either talk to systemd-resolved directly or not but never call "/usr/sbin/resolvconf". So, the special handling for resolvconf and netconfig is only done if NetworkManager was build with these applications explicitly enabled. Note that SUSE builds NetworkManager with --with-netconfig=yes --with-config-dns-rc-manager-default=netconfig and the new option won't be used there either. But of course, netconfig already does all the right things on SUSE. [1] https://bugzilla.redhat.com/show_bug.cgi?id=668153 Suggested-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--NEWS8
-rw-r--r--configure.ac13
-rw-r--r--contrib/fedora/rpm/NetworkManager.spec8
-rwxr-xr-xcontrib/fedora/rpm/build_clean.sh2
-rw-r--r--man/NetworkManager.conf.xml73
-rw-r--r--meson_options.txt2
-rw-r--r--src/dns/nm-dns-manager.c43
-rw-r--r--src/dns/nm-dns-manager.h16
8 files changed, 120 insertions, 45 deletions
diff --git a/NEWS b/NEWS
index ca30fd033d..314cecb6f5 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,14 @@ The API is subject to change and not guaranteed to be compatible
with the later release.
USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
+* Introduce new "rc-manager=auto" setting and make it the default,
+ unless a different default is chosen at compile time.
+ This mode tries to detect "systemd-resolved", "resolvconf", and "netconfig"
+ and chooses the mode that seems most suitable depending on build
+ setting and runtime detection.
+ "resolvconf" and "netconfig" are only considered iff NetworkManager
+ was build with the respective options enabled.
+
=============================================
NetworkManager-1.26
Overview of changes since NetworkManager-1.24
diff --git a/configure.ac b/configure.ac
index d6842670a2..8f8b9338f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -891,14 +891,15 @@ AC_SUBST(NM_CONFIG_DEFAULT_MAIN_DHCP, $config_dhcp_default)
AC_ARG_WITH(resolvconf, AS_HELP_STRING([--with-resolvconf=yes|no|path], [Enable resolvconf support]))
AC_ARG_WITH(netconfig, AS_HELP_STRING([--with-netconfig=yes|no], [Enable SUSE netconfig support]))
-AC_ARG_WITH(config-dns-rc-manager-default, AS_HELP_STRING([--with-config-dns-rc-manager-default=symlink|file|netconfig|resolvconf], [Configure default value for main.rc-manager setting]), [config_dns_rc_manager_default=$withval])
+AC_ARG_WITH(config-dns-rc-manager-default, AS_HELP_STRING([--with-config-dns-rc-manager-default=auto|symlink|file|netconfig|resolvconf], [Configure default value for main.rc-manager setting]), [config_dns_rc_manager_default=$withval])
if test "$config_dns_rc_manager_default" != "" -a \
+ "$config_dns_rc_manager_default" != auto -a \
"$config_dns_rc_manager_default" != file -a \
"$config_dns_rc_manager_default" != symlink -a \
"$config_dns_rc_manager_default" != netconfig -a \
"$config_dns_rc_manager_default" != resolvconf; then
AC_MSG_WARN([Unknown --with-config-dns-rc-manager-default=$config_dns_rc_manager_default setting.])
- config_dns_rc_manager_default=
+ config_dns_rc_manager_default=auto
fi
# Use netconfig by default on SUSE
AS_IF([test -z "$with_netconfig" -a -f /etc/SuSE-release], with_netconfig=yes)
@@ -912,9 +913,6 @@ if test "$with_resolvconf" = "yes"; then
AC_MSG_ERROR(cannot find resolvconf in path. Set the path explicitly via --with-resolvconf=PATH.)
fi
fi
-if test "$with_resolvconf" != "no"; then
- AS_IF([test -z "$config_dns_rc_manager_default"], config_dns_rc_manager_default=resolvconf)
-fi
if test "$with_netconfig" = "yes"; then
AC_PATH_PROGS(with_netconfig, netconfig, yes, /sbin:/usr/sbin:/usr/local/sbin)
@@ -922,11 +920,6 @@ if test "$with_netconfig" = "yes"; then
AC_MSG_ERROR(cannot find netconfig in path. Set the path explicitly via --with-netconfig=PATH.)
fi
fi
-if test "$with_netconfig" != "no"; then
- AS_IF([test -z "$config_dns_rc_manager_default"], config_dns_rc_manager_default=netconfig)
-fi
-
-AS_IF([test -z "$config_dns_rc_manager_default"], config_dns_rc_manager_default=symlink)
if test "$with_resolvconf" != "no"; then
AC_DEFINE_UNQUOTED(RESOLVCONF_PATH, "$with_resolvconf", [Path to resolvconf])
diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec
index 20001c6fd7..343e291998 100644
--- a/contrib/fedora/rpm/NetworkManager.spec
+++ b/contrib/fedora/rpm/NetworkManager.spec
@@ -115,7 +115,11 @@
%if 0%{?fedora} || 0%{?rhel} > 7
%global logging_backend_default journal
+%if 0%{?fedora} || 0%{?rhel} > 8
+%global dns_rc_manager_default auto
+%else
%global dns_rc_manager_default symlink
+%endif
%else
%global logging_backend_default syslog
%global dns_rc_manager_default file
@@ -641,6 +645,8 @@ This tool is still experimental.
%endif
-Ddist_version=%{version}-%{release} \
-Dconfig_plugins_default=%{config_plugins_default} \
+ -Dresolvconf=no \
+ -Dnetconfig=no \
-Dconfig_dns_rc_manager_default=%{dns_rc_manager_default} \
-Dconfig_logging_backend_default=%{logging_backend_default} \
-Djson_validation=true
@@ -779,6 +785,8 @@ intltoolize --automake --copy --force
%endif
--with-dist-version=%{version}-%{release} \
--with-config-plugins-default=%{config_plugins_default} \
+ --with-resolvconf=no \
+ --with-netconfig=no \
--with-config-dns-rc-manager-default=%{dns_rc_manager_default} \
--with-config-logging-backend-default=%{logging_backend_default} \
--enable-json-validation
diff --git a/contrib/fedora/rpm/build_clean.sh b/contrib/fedora/rpm/build_clean.sh
index 776e4c4df6..e7afdb4f24 100755
--- a/contrib/fedora/rpm/build_clean.sh
+++ b/contrib/fedora/rpm/build_clean.sh
@@ -158,7 +158,7 @@ if [[ $NO_DIST != 1 ]]; then
--enable-polkit=yes \
--with-nm-cloud-setup=yes \
--with-config-dhcp-default=internal \
- --with-config-dns-rc-manager-default=symlink \
+ --with-config-dns-rc-manager-default=auto \
|| die "Error autogen.sh"
if [[ $QUICK == 1 ]]; then
make dist -j 7 || die "Error make dist"
diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml
index aac80a0878..ce61c8216d 100644
--- a/man/NetworkManager.conf.xml
+++ b/man/NetworkManager.conf.xml
@@ -309,7 +309,8 @@ no-auto-default=*
</para>
<para><literal>default</literal>: NetworkManager will update
<filename>/etc/resolv.conf</filename> to reflect the nameservers
- provided by currently active connections.</para>
+ provided by currently active connections. The <literal>rc-manager</literal>
+ setting (below) controls how this is done.</para>
<para><literal>dnsmasq</literal>: NetworkManager will run
dnsmasq as a local caching nameserver, using "Conditional Forwarding"
if you are connected to a VPN, and then update
@@ -349,37 +350,57 @@ no-auto-default=*
<varlistentry>
<term><varname>rc-manager</varname></term>
- <listitem><para>Set the <filename>resolv.conf</filename>
- management mode. The default value depends on NetworkManager build
- options, and this version of NetworkManager was build with a default of
- "<literal>&NM_CONFIG_DEFAULT_MAIN_RC_MANAGER;</literal>".
- Regardless of this setting, NetworkManager will
- always write resolv.conf to its runtime state directory
- <filename>&nmrundir;/resolv.conf</filename>.</para>
+ <listitem>
+ <para>Set the <filename>resolv.conf</filename>
+ management mode. This option is about how NetworkManager writes to
+ <filename>/etc/resolv.conf</filename>, if at all.
+ The default value depends on NetworkManager build
+ options, and this version of NetworkManager was build with a default of
+ "<literal>&NM_CONFIG_DEFAULT_MAIN_RC_MANAGER;</literal>".
+ Regardless of this setting, NetworkManager will
+ always write its version of resolv.conf to its runtime state directory
+ as <filename>&nmrundir;/resolv.conf</filename>.
+ </para>
+ <para>If you configure <literal>dns=none</literal> or make <filename>/etc/resolv.conf</filename>
+ immutable with <literal>chattr +i</literal>, NetworkManager will ignore this setting and
+ always choose <literal>unmanaged</literal> (below).
+ </para>
+ <para><literal>auto</literal>: if systemd-resolved plugin is configured via
+ the <literal>dns</literal> setting or if it gets detected as main DNS plugin,
+ NetworkManager will update systemd-resolved without touching <filename>/etc/resolv.conf</filename>.
+ Alternatively, if <literal>resolvconf</literal> or <literal>netconfig</literal> are enabled
+ at compile time and the respective binary is found, NetworkManager will automatically use it.
+ Note that if you install or uninstall these binaries, you need to reload the
+ <literal>rc-manager</literal> setting with SIGHUP or
+ <literal>systemctl reload NetworkManager</literal>. As last fallback
+ it uses the <literal>symlink</literal> option (see next).
+ </para>
<para><literal>symlink</literal>: If <filename>/etc/resolv.conf</filename> is
- a regular file, NetworkManager will replace the file on update. If
- <filename>/etc/resolv.conf</filename> is instead a symlink, NetworkManager
- will leave it alone. Unless the symlink points to the internal file
- <filename>&nmrundir;/resolv.conf</filename>,
- in which case the symlink will be updated to emit an inotify notification.
- This allows the user to conveniently instruct NetworkManager not
- to manage <filename>/etc/resolv.conf</filename> by replacing it with
- a symlink.</para>
+ a regular file or does not exist, NetworkManager will write the file directly.
+ If <filename>/etc/resolv.conf</filename> is instead a symlink, NetworkManager
+ will leave it alone. Unless the symlink points to the internal file
+ <filename>&nmrundir;/resolv.conf</filename>,
+ in which case the symlink will be updated to emit an inotify notification.
+ This allows the user to conveniently instruct NetworkManager not
+ to manage <filename>/etc/resolv.conf</filename> by replacing it with
+ a symlink.
+ </para>
<para><literal>file</literal>: NetworkManager will write
- <filename>/etc/resolv.conf</filename> as file. If it finds
- a symlink to an existing target, it will follow the symlink and
- update the target instead. In no case will an existing symlink
- be replaced by a file. Note that older versions of NetworkManager
- behaved differently and would replace dangling symlinks with a
- plain file.</para>
+ <filename>/etc/resolv.conf</filename> as regular file. If it finds
+ a symlink to an existing target, it will follow the symlink and
+ update the target instead. In no case will an existing symlink
+ be replaced by a file. Note that older versions of NetworkManager
+ behaved differently and would replace dangling symlinks with a
+ plain file.
+ </para>
<para><literal>resolvconf</literal>: NetworkManager will run
- resolvconf to update the DNS configuration.</para>
+ resolvconf to update the DNS configuration.</para>
<para><literal>netconfig</literal>: NetworkManager will run
- netconfig to update the DNS configuration.</para>
+ netconfig to update the DNS configuration.</para>
<para><literal>unmanaged</literal>: don't touch
- <filename>/etc/resolv.conf</filename>.</para>
+ <filename>/etc/resolv.conf</filename>.</para>
<para><literal>none</literal>: deprecated alias for
- <literal>symlink</literal>.</para>
+ <literal>symlink</literal>.</para>
</listitem>
</varlistentry>
diff --git a/meson_options.txt b/meson_options.txt
index d6306711ec..5bfa3b151e 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -49,7 +49,7 @@ option('ifupdown', type: 'boolean', value: false, description: 'enable ifupdown
# handlers for resolv.conf
option('resolvconf', type: 'string', value: '', description: 'Enable resolvconf support')
option('netconfig', type: 'string', value: '', description: 'Enable SUSE netconfig support')
-option('config_dns_rc_manager_default', type: 'combo', choices: ['symlink', 'file', 'netconfig', 'resolvconf'], value: 'symlink', description: 'Configure default value for main.rc-manager setting')
+option('config_dns_rc_manager_default', type: 'combo', choices: ['auto', 'symlink', 'file', 'netconfig', 'resolvconf'], value: 'auto', description: 'Configure default value for main.rc-manager setting')
# dhcp clients
option('dhclient', type: 'string', value: '', description: 'Enable dhclient support')
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c
index 9108911cbb..12463d0cc2 100644
--- a/src/dns/nm-dns-manager.c
+++ b/src/dns/nm-dns-manager.c
@@ -42,10 +42,16 @@
#ifndef RESOLVCONF_PATH
#define RESOLVCONF_PATH "/sbin/resolvconf"
+#define HAS_RESOLVCONF 0
+#else
+#define HAS_RESOLVCONF 1
#endif
#ifndef NETCONFIG_PATH
#define NETCONFIG_PATH "/sbin/netconfig"
+#define HAS_NETCONFIG 0
+#else
+#define HAS_NETCONFIG 1
#endif
/*****************************************************************************/
@@ -182,6 +188,7 @@ domain_is_routing (const char *domain)
static
NM_UTILS_LOOKUP_STR_DEFINE (_rc_manager_to_string, NMDnsManagerResolvConfManager,
NM_UTILS_LOOKUP_DEFAULT_WARN (NULL),
+ NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO, "auto"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "unknown"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, "unmanaged"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE, "immutable"),
@@ -1900,6 +1907,7 @@ _check_resconf_immutable (NMDnsManagerResolvConfManager rc_manager)
case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE:
case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF:
case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG:
+ case NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO:
break;
}
}
@@ -1999,6 +2007,7 @@ init_resolv_conf_mode (NMDnsManager *self, gboolean force_reload_plugin)
gboolean param_changed = FALSE;
gboolean plugin_changed = FALSE;
gboolean systemd_resolved_changed = FALSE;
+ gboolean rc_manager_was_auto = FALSE;
mode = nm_config_data_get_dns_mode (nm_config_get_data (priv->config));
systemd_resolved = nm_config_data_get_systemd_resolved (nm_config_get_data (priv->config));
@@ -2014,7 +2023,9 @@ init_resolv_conf_mode (NMDnsManager *self, gboolean force_reload_plugin)
again:
if (!man) {
/* nop */
- } else if (NM_IN_STRSET (man, "symlink", "none"))
+ } else if (nm_streq (man, "auto"))
+ rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO;
+ else if (NM_IN_STRSET (man, "symlink", "none"))
rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK;
else if (nm_streq (man, "file"))
rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE;
@@ -2031,7 +2042,7 @@ again:
man, ""NM_CONFIG_DEFAULT_MAIN_RC_MANAGER);
}
man = ""NM_CONFIG_DEFAULT_MAIN_RC_MANAGER;
- rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK;
+ rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO;
goto again;
}
}
@@ -2070,6 +2081,31 @@ again:
plugin_changed = TRUE;
}
+ if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO) {
+ rc_manager_was_auto = TRUE;
+ if (nm_streq (mode, "systemd-resolved"))
+ rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED;
+ else if ( HAS_RESOLVCONF
+ && g_file_test (RESOLVCONF_PATH, G_FILE_TEST_IS_EXECUTABLE)) {
+ /* We detect /sbin/resolvconf only at this stage. That means, if you install
+ * or uninstall openresolv afterwards, you need to reload the DNS settings
+ * (with SIGHUP or `systemctl reload NetworkManager.service`).
+ *
+ * We only accept resolvconf is NetworkManager was build with --with-resolvconf.
+ * For example, on Fedora the systemd package provides a compat resolvconf
+ * implementation for systemd-resolved. But using that never makes sense, because
+ * there we either use full systemd-resolved mode or not. In no case does it
+ * make sense to call that resolvconf implementation. */
+ rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF;
+ } else if ( HAS_NETCONFIG
+ && g_file_test (NETCONFIG_PATH, G_FILE_TEST_IS_EXECUTABLE)) {
+ /* Like for resolvconf, we detect only once. We only autoenable this
+ * option, if NetworkManager was build with netconfig explicitly enabled. */
+ rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG;
+ } else
+ rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK;
+ }
+
/* The systemd-resolved plugin is special. We typically always want to keep
* systemd-resolved up to date even if the configured plugin is different. */
if (systemd_resolved) {
@@ -2096,10 +2132,11 @@ again:
}
if (param_changed || plugin_changed || systemd_resolved_changed) {
- _LOGI ("init: dns=%s%s rc-manager=%s%s%s%s",
+ _LOGI ("init: dns=%s%s rc-manager=%s%s%s%s%s",
mode,
(systemd_resolved ? ",systemd-resolved" : ""),
_rc_manager_to_string (rc_manager),
+ rc_manager_was_auto ? " (auto)" : "",
NM_PRINT_FMT_QUOTED (priv->plugin, ", plugin=",
nm_dns_plugin_get_name (priv->plugin), "", ""));
}
diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h
index 2a0c9deee3..e3c8ffb742 100644
--- a/src/dns/nm-dns-manager.h
+++ b/src/dns/nm-dns-manager.h
@@ -88,12 +88,19 @@ void nm_dns_manager_set_hostname (NMDnsManager *self,
* @NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED: do not touch /etc/resolv.conf
* (but still write the internal copy -- unless it is symlinked by
* /etc/resolv.conf)
+ * @NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO: if /etc/resolv.conf is marked
+ * as an immutable file, use "unmanaged" and don't touch /etc/resolv.conf.
+ * Otherwise, if "systemd-resolved" is enabled (or detected), configure systemd-resolved via D-Bus
+ * and don't touch /etc/resolv.conf.
+ * Otherwise, if "resolvconf" application is found, use it.
+ * As last resort, fallback to "symlink" which writes to /etc/resolv.conf
+ * if (and only if) the file is missing or not a symlink.
* @NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE: similar to "unmanaged",
* but indicates that resolv.conf cannot be modified.
- * @NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: NM writes resolv.conf
- * by symlinking it to the run state directory.
- * @NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: Like SYMLINK, but instead of
- * symlinking /etc/resolv.conf, write it as a file.
+ * @NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: NM writes /etc/resolv.conf
+ * if the file is missing or not a smylink.
+ * @NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: Write to /etc/resolv.conf directly.
+ * If it is a file, write it as file, otherwise follow symlinks.
* @NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: NM is managing resolv.conf
through resolvconf
* @NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: NM is managing resolv.conf
@@ -103,6 +110,7 @@ void nm_dns_manager_set_hostname (NMDnsManager *self,
*/
typedef enum {
NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN,
+ NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO,
NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED,
NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE,
NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK,