diff options
author | Thomas Haller <thaller@redhat.com> | 2020-08-07 19:43:35 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-08-24 16:10:42 +0200 |
commit | 606f97ad548591e10579822df3e691e0761d30eb (patch) | |
tree | 76142b79b22cc48797d5ee63e42289860ca6994a | |
parent | 059d02ed3f90b94580c73c34fdd8ba50705e7c7d (diff) | |
download | NetworkManager-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-- | NEWS | 8 | ||||
-rw-r--r-- | configure.ac | 13 | ||||
-rw-r--r-- | contrib/fedora/rpm/NetworkManager.spec | 8 | ||||
-rwxr-xr-x | contrib/fedora/rpm/build_clean.sh | 2 | ||||
-rw-r--r-- | man/NetworkManager.conf.xml | 73 | ||||
-rw-r--r-- | meson_options.txt | 2 | ||||
-rw-r--r-- | src/dns/nm-dns-manager.c | 43 | ||||
-rw-r--r-- | src/dns/nm-dns-manager.h | 16 |
8 files changed, 120 insertions, 45 deletions
@@ -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, |