From d4eb4cb45f41b1751cacf71da558bf8f0988f383 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 3 Jul 2018 14:35:32 +0200 Subject: [PATCH] dns: allow loading nm-dns-systemd-resolve alongside other DNS plugins Even when the system resolver is configured to something else that systemd-resolved, it still is a good idea to keep systemd-resolved up to date. If not anything else, it does a good job at doing per-interface resolving for connectivity checks. If for whatever reasons don't want NetworkManager to push the DNS data it discovers to systemd-resolved, the functionality can be disabled with: [main] systemd-resolved=false --- man/NetworkManager.conf.xml | 14 ++++++++++++ src/dns/nm-dns-manager.c | 45 +++++++++++++++++++++++++++++++------ src/nm-config-data.c | 10 +++++++++ src/nm-config-data.h | 1 + 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml index 6735af5fd4..1e1d0aab15 100644 --- a/man/NetworkManager.conf.xml +++ b/man/NetworkManager.conf.xml @@ -387,6 +387,20 @@ no-auto-default=* + + systemd-resolved + Send the connection DNS configuration to + systemd-resolved. Defaults to "true". + + Note that this setting is complementary to the + dns setting. You can keep this enable while using + dns set to another DNS plugin alongside + systemd-resolved, or dns set to + systemd-resolved to configure the system resolver to use + systemd-resolved. + + + debug Comma separated list of options to aid diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index a8dc0413d4..461a1385a5 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -122,6 +122,7 @@ typedef struct { NMDnsManagerResolvConfManager rc_manager; char *mode; + NMDnsPlugin *sd_resolve_plugin; NMDnsPlugin *plugin; NMConfig *config; @@ -1398,6 +1399,16 @@ update_dns (NMDnsManager *self, &searches, &options, &nameservers, &nis_servers, &nis_domain); + if (priv->plugin || priv->sd_resolve_plugin) + rebuild_domain_lists (self); + + if (priv->sd_resolve_plugin) { + nm_dns_plugin_update (priv->sd_resolve_plugin, + global_config, + _ip_config_lst_head (self), + priv->hostname); + } + /* Let any plugins do their thing first */ if (priv->plugin) { NMDnsPlugin *plugin = priv->plugin; @@ -1413,7 +1424,6 @@ update_dns (NMDnsManager *self, } _LOGD ("update-dns: updating plugin %s", plugin_name); - rebuild_domain_lists (self); if (!nm_dns_plugin_update (plugin, global_config, _ip_config_lst_head (self), @@ -1425,15 +1435,17 @@ update_dns (NMDnsManager *self, */ caching = FALSE; } - /* Clear the generated search list as it points to - * strings owned by IP configurations and we can't - * guarantee they stay alive. */ - clear_domain_lists (self); skip: ; } + /* Clear the generated search list as it points to + * strings owned by IP configurations and we can't + * guarantee they stay alive. */ + clear_domain_lists (self); + clear_domain_lists (self); + update_resolv_conf_no_stub (self, searches, nameservers, options); /* If caching was successful, we only send 127.0.0.1 to /etc/resolv.conf @@ -1932,9 +1944,11 @@ init_resolv_conf_mode (NMDnsManager *self, gboolean force_reload_plugin) NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); NMDnsManagerResolvConfManager rc_manager; const char *mode; + gboolean systemd_resolved = FALSE; gboolean param_changed = FALSE, plugin_changed = 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)); if (nm_streq0 (mode, "none")) rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED; @@ -1980,6 +1994,7 @@ again: plugin_changed = TRUE; } mode = "systemd-resolved"; + systemd_resolved = FALSE; } else if (nm_streq0 (mode, "dnsmasq")) { if (force_reload_plugin || !NM_IS_DNS_DNSMASQ (priv->plugin)) { _clear_plugin (self); @@ -2002,6 +2017,20 @@ again: plugin_changed = TRUE; } + /* 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) { + if (!priv->sd_resolve_plugin) { + priv->sd_resolve_plugin = nm_dns_systemd_resolved_new (); + plugin_changed = TRUE; + } + } else { + if (priv->sd_resolve_plugin) { + g_clear_object (&priv->sd_resolve_plugin); + plugin_changed = TRUE; + } + } + if (plugin_changed && priv->plugin) { g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); g_signal_connect (priv->plugin, NM_DNS_PLUGIN_CHILD_QUIT, G_CALLBACK (plugin_child_quit), self); @@ -2023,8 +2052,9 @@ again: } if (param_changed || plugin_changed) { - _LOGI ("init: dns=%s, rc-manager=%s%s%s%s", - mode, _rc_manager_to_string (rc_manager), + _LOGI ("init: dns=%s%s rc-manager=%s%s%s%s", + mode, (systemd_resolved ? ",systemd-resolved" : ""), + _rc_manager_to_string (rc_manager), NM_PRINT_FMT_QUOTED (priv->plugin, ", plugin=", nm_dns_plugin_get_name (priv->plugin), "", "")); } @@ -2285,6 +2315,7 @@ dispose (GObject *object) if (priv->config) g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self); + g_clear_object (&priv->sd_resolve_plugin); _clear_plugin (self); priv->best_ip_config_4 = NULL; diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 8d84e74abc..c37e36b421 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -108,6 +108,7 @@ typedef struct { char *dns_mode; char *rc_manager; + gboolean systemd_resolved; NMGlobalDnsConfig *global_dns; } NMConfigDataPrivate; @@ -322,6 +323,14 @@ nm_config_data_get_rc_manager (const NMConfigData *self) return NM_CONFIG_DATA_GET_PRIVATE (self)->rc_manager; } +gboolean +nm_config_data_get_systemd_resolved (const NMConfigData *self) +{ + g_return_val_if_fail (self, FALSE); + + return NM_CONFIG_DATA_GET_PRIVATE (self)->systemd_resolved; +} + gboolean nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device) { @@ -1654,6 +1663,7 @@ constructed (GObject *object) priv->dns_mode = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "dns", NULL)); priv->rc_manager = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "rc-manager", NULL)); + priv->systemd_resolved = nm_config_keyfile_get_boolean (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "systemd-resolved", TRUE); priv->ignore_carrier = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "ignore-carrier", NULL); priv->assume_ipv6ll_only = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "assume-ipv6ll-only", NULL); diff --git a/src/nm-config-data.h b/src/nm-config-data.h index b52ddcc4f8..9d1e20a6a2 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -170,6 +170,7 @@ gboolean nm_config_data_get_no_auto_default_for_device (const NMConfigD const char *nm_config_data_get_dns_mode (const NMConfigData *self); const char *nm_config_data_get_rc_manager (const NMConfigData *self); +gboolean nm_config_data_get_systemd_resolved (const NMConfigData *self); gboolean nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device); gboolean nm_config_data_get_assume_ipv6ll_only (const NMConfigData *self, NMDevice *device);