diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2015-06-15 09:03:53 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2015-10-01 09:05:08 +0200 |
commit | ae9e82354a9c1b2247b7d071ed62acd9e83ae27b (patch) | |
tree | 6311de68a5c76da2520de24523b8e7c05b625d61 | |
parent | 55c204b9a357e917cb26b1a1742dff703223037e (diff) | |
download | NetworkManager-ae9e82354a9c1b2247b7d071ed62acd9e83ae27b.tar.gz |
dns: add support for global configuration in DNS manager
Modify the DNS manager to use the static global DNS configuration when
available. In addition, change DNS plugins interface to accept a new
argument for global configuration and add support for this new
parameter to the dnsmasq plugin.
-rw-r--r-- | src/dns-manager/nm-dns-dnsmasq.c | 69 | ||||
-rw-r--r-- | src/dns-manager/nm-dns-manager.c | 110 | ||||
-rw-r--r-- | src/dns-manager/nm-dns-plugin.c | 2 | ||||
-rw-r--r-- | src/dns-manager/nm-dns-plugin.h | 7 | ||||
-rw-r--r-- | src/dns-manager/nm-dns-unbound.c | 1 | ||||
-rw-r--r-- | src/nm-config-data.c | 31 | ||||
-rw-r--r-- | src/nm-config-data.h | 1 |
7 files changed, 169 insertions, 52 deletions
diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 59a341aa9a..63e37bf314 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -135,6 +135,30 @@ ip6_addr_to_string (const struct in6_addr *addr, const char *iface) return buf; } +static void +add_global_config (GString *str, const NMGlobalDnsConfig *config) +{ + guint i, j; + + g_return_if_fail (config); + + for (i = 0; i < nm_global_dns_config_get_num_domains (config); i++) { + NMGlobalDnsDomain *domain = nm_global_dns_config_get_domain (config, i); + const char *const *servers = nm_global_dns_domain_get_servers (domain); + + for (j = 0; servers && servers[j]; j++) { + if (!strcmp (servers[j], "*")) + g_string_append_printf (str, "server=%s\n", servers[j]); + else { + g_string_append_printf (str, "server=/%s/%s\n", + nm_global_dns_domain_get_name (domain), + servers[j]); + } + } + + } +} + static gboolean add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) { @@ -201,6 +225,7 @@ update (NMDnsPlugin *plugin, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, + const NMGlobalDnsConfig *global_config, const char *hostname) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); @@ -229,28 +254,32 @@ update (NMDnsPlugin *plugin, /* Build up the new dnsmasq config file */ conf = g_string_sized_new (150); - /* Use split DNS for VPN configs */ - for (iter = (GSList *) vpn_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (conf, NM_IP4_CONFIG (iter->data), TRUE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE); - } + if (global_config) + add_global_config (conf, global_config); + else { + /* Use split DNS for VPN configs */ + for (iter = (GSList *) vpn_configs; iter; iter = g_slist_next (iter)) { + if (NM_IS_IP4_CONFIG (iter->data)) + add_ip4_config (conf, NM_IP4_CONFIG (iter->data), TRUE); + else if (NM_IS_IP6_CONFIG (iter->data)) + add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE); + } - /* Now add interface configs without split DNS */ - for (iter = (GSList *) dev_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); - } + /* Now add interface configs without split DNS */ + for (iter = (GSList *) dev_configs; iter; iter = g_slist_next (iter)) { + if (NM_IS_IP4_CONFIG (iter->data)) + add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); + else if (NM_IS_IP6_CONFIG (iter->data)) + add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); + } - /* And any other random configs */ - for (iter = (GSList *) other_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); + /* And any other random configs */ + for (iter = (GSList *) other_configs; iter; iter = g_slist_next (iter)) { + if (NM_IS_IP4_CONFIG (iter->data)) + add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); + else if (NM_IS_IP6_CONFIG (iter->data)) + add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); + } } /* Write out the config file */ diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 58260a045c..fbf5da1201 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -667,7 +667,7 @@ update_resolv_conf (NMDnsManager *self, } static void -compute_hash (NMDnsManager *self, guint8 buffer[HASH_LEN]) +compute_hash (NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[HASH_LEN]) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); GChecksum *sum; @@ -677,6 +677,9 @@ compute_hash (NMDnsManager *self, guint8 buffer[HASH_LEN]) sum = g_checksum_new (G_CHECKSUM_SHA1); g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); + if (global) + nm_global_dns_config_update_checksum (global, sum); + if (priv->ip4_vpn_config) nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE); if (priv->ip4_device_config) @@ -742,6 +745,38 @@ build_plugin_config_lists (NMDnsManager *self, } static gboolean +merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) +{ + NMGlobalDnsDomain *default_domain; + const char *const *searches; + const char *const *options; + const char *const *servers; + gint i; + + if (!global_conf) + return FALSE; + + searches = nm_global_dns_config_get_searches (global_conf); + options = nm_global_dns_config_get_options (global_conf); + + for (i = 0; searches && searches[i]; i++) { + if (DOMAIN_IS_VALID (searches[i])) + add_string_item (rc->searches, searches[i]); + } + + for (i = 0; options && options[i]; i++) + add_string_item (rc->options, options[i]); + + default_domain = nm_global_dns_config_lookup_domain (global_conf, "*"); + g_assert (default_domain); + servers = nm_global_dns_domain_get_servers (default_domain); + for (i = 0; servers && servers[i]; i++) + add_string_item (rc->nameservers, servers[i]); + + return TRUE; +} + +static gboolean update_dns (NMDnsManager *self, gboolean no_caching, GError **error) @@ -758,6 +793,8 @@ update_dns (NMDnsManager *self, gboolean caching = FALSE, update = TRUE; gboolean resolv_conf_updated = FALSE; SpawnResult result = SR_ERROR; + NMConfigData *data; + NMGlobalDnsConfig *global_config; g_return_val_if_fail (!error || !*error, FALSE); @@ -771,8 +808,11 @@ update_dns (NMDnsManager *self, _LOGD ("update-dns: updating resolv.conf"); } + data = nm_config_get_data (priv->config); + global_config = nm_config_data_get_global_dns_config (data); + /* Update hash with config we're applying */ - compute_hash (self, priv->hash); + compute_hash (self, global_config, priv->hash); rc.nameservers = g_ptr_array_new (); rc.searches = g_ptr_array_new (); @@ -780,33 +820,37 @@ update_dns (NMDnsManager *self, rc.nis_domain = NULL; rc.nis_servers = g_ptr_array_new (); - if (priv->ip4_vpn_config) - merge_one_ip4_config (&rc, priv->ip4_vpn_config); - if (priv->ip4_device_config) - merge_one_ip4_config (&rc, priv->ip4_device_config); - - if (priv->ip6_vpn_config) - merge_one_ip6_config (&rc, priv->ip6_vpn_config); - if (priv->ip6_device_config) - merge_one_ip6_config (&rc, priv->ip6_device_config); - - for (iter = priv->configs; iter; iter = g_slist_next (iter)) { - if ( (iter->data == priv->ip4_vpn_config) - || (iter->data == priv->ip4_device_config) - || (iter->data == priv->ip6_vpn_config) - || (iter->data == priv->ip6_device_config)) - continue; + if (global_config) + merge_global_dns_config (&rc, global_config); + else { + if (priv->ip4_vpn_config) + merge_one_ip4_config (&rc, priv->ip4_vpn_config); + if (priv->ip4_device_config) + merge_one_ip4_config (&rc, priv->ip4_device_config); + + if (priv->ip6_vpn_config) + merge_one_ip6_config (&rc, priv->ip6_vpn_config); + if (priv->ip6_device_config) + merge_one_ip6_config (&rc, priv->ip6_device_config); + + for (iter = priv->configs; iter; iter = g_slist_next (iter)) { + if ( (iter->data == priv->ip4_vpn_config) + || (iter->data == priv->ip4_device_config) + || (iter->data == priv->ip6_vpn_config) + || (iter->data == priv->ip6_device_config)) + continue; - if (NM_IS_IP4_CONFIG (iter->data)) { - NMIP4Config *config = NM_IP4_CONFIG (iter->data); + if (NM_IS_IP4_CONFIG (iter->data)) { + NMIP4Config *config = NM_IP4_CONFIG (iter->data); - merge_one_ip4_config (&rc, config); - } else if (NM_IS_IP6_CONFIG (iter->data)) { - NMIP6Config *config = NM_IP6_CONFIG (iter->data); + merge_one_ip4_config (&rc, config); + } else if (NM_IS_IP6_CONFIG (iter->data)) { + NMIP6Config *config = NM_IP6_CONFIG (iter->data); - merge_one_ip6_config (&rc, config); - } else - g_assert_not_reached (); + merge_one_ip6_config (&rc, config); + } else + g_assert_not_reached (); + } } /* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it @@ -879,13 +923,15 @@ update_dns (NMDnsManager *self, caching = TRUE; } - build_plugin_config_lists (self, &vpn_configs, &dev_configs, &other_configs); + if (!global_config) + build_plugin_config_lists (self, &vpn_configs, &dev_configs, &other_configs); _LOGD ("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update (plugin, vpn_configs, dev_configs, other_configs, + global_config, priv->hostname)) { _LOGW ("update-dns: plugin %s update failed", plugin_name); @@ -1212,7 +1258,7 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) priv = NM_DNS_MANAGER_GET_PRIVATE (self); g_return_if_fail (priv->updates_queue > 0); - compute_hash (self, new); + compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), new); changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE; _LOGD ("(%s): DNS configuration %s", func, changed ? "changed" : "did not change"); @@ -1346,7 +1392,8 @@ config_changed_cb (NMConfig *config, if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_SIGHUP | NM_CONFIG_CHANGE_SIGUSR1 | NM_CONFIG_CHANGE_DNS_MODE | - NM_CONFIG_CHANGE_RC_MANAGER)) { + NM_CONFIG_CHANGE_RC_MANAGER | + NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) { if (!update_dns (self, TRUE, &error)) { _LOGW ("could not commit DNS changes: %s", error->message); g_clear_error (&error); @@ -1361,10 +1408,11 @@ nm_dns_manager_init (NMDnsManager *self) _LOGt ("creating..."); + priv->config = g_object_ref (nm_config_get ()); /* Set the initial hash */ - compute_hash (self, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); + compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), + NM_DNS_MANAGER_GET_PRIVATE (self)->hash); - priv->config = g_object_ref (nm_config_get ()); g_signal_connect (G_OBJECT (priv->config), NM_CONFIG_SIGNAL_CONFIG_CHANGED, G_CALLBACK (config_changed_cb), diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c index a53a7fca0a..5b3cc69fa4 100644 --- a/src/dns-manager/nm-dns-plugin.c +++ b/src/dns-manager/nm-dns-plugin.c @@ -56,6 +56,7 @@ nm_dns_plugin_update (NMDnsPlugin *self, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, + const NMGlobalDnsConfig *global_config, const char *hostname) { g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE); @@ -64,6 +65,7 @@ nm_dns_plugin_update (NMDnsPlugin *self, vpn_configs, dev_configs, other_configs, + global_config, hostname); } diff --git a/src/dns-manager/nm-dns-plugin.h b/src/dns-manager/nm-dns-plugin.h index 0a46759850..7ecaa424dc 100644 --- a/src/dns-manager/nm-dns-plugin.h +++ b/src/dns-manager/nm-dns-plugin.h @@ -21,6 +21,8 @@ #include "nm-default.h" +#include "nm-config-data.h" + #define NM_TYPE_DNS_PLUGIN (nm_dns_plugin_get_type ()) #define NM_DNS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DNS_PLUGIN, NMDnsPlugin)) #define NM_DNS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DNS_PLUGIN, NMDnsPluginClass)) @@ -46,13 +48,15 @@ typedef struct { * NMIP4Config or NMIP6Config objects from VPN connections, while * 'dev_configs' is a list of NMPI4Config or NMIP6Config objects from * active devices. 'other_configs' represent other IP configuration that - * may be in-use. Configs of the same IP version are sorted in priority + * may be in-use. 'global_config' is the optional global DNS + * configuration. Configs of the same IP version are sorted in priority * order. */ gboolean (*update) (NMDnsPlugin *self, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, + const NMGlobalDnsConfig *global_config, const char *hostname); /* Subclasses should override and return TRUE if they start a local @@ -91,6 +95,7 @@ gboolean nm_dns_plugin_update (NMDnsPlugin *self, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, + const NMGlobalDnsConfig *global_config, const char *hostname); /* For subclasses/plugins */ diff --git a/src/dns-manager/nm-dns-unbound.c b/src/dns-manager/nm-dns-unbound.c index 5723bf8229..08a7cd3ae0 100644 --- a/src/dns-manager/nm-dns-unbound.c +++ b/src/dns-manager/nm-dns-unbound.c @@ -31,6 +31,7 @@ update (NMDnsPlugin *plugin, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, + const NMGlobalDnsConfig *global_config, const char *hostname) { /* TODO: We currently call a script installed with the dnssec-trigger diff --git a/src/nm-config-data.c b/src/nm-config-data.c index b9fe9c2e4a..cfca59aa4b 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -640,6 +640,37 @@ nm_global_dns_config_is_empty (const NMGlobalDnsConfig *dns) && g_hash_table_size (dns->domains) == 0; } +void +nm_global_dns_config_update_checksum (const NMGlobalDnsConfig *dns, GChecksum *sum) +{ + NMGlobalDnsDomain *domain; + GList *keys, *key; + guint i; + + g_return_if_fail (dns); + g_return_if_fail (dns->domains); + g_return_if_fail (sum); + + for (i = 0; dns->searches && dns->searches[i]; i++) + g_checksum_update (sum, (guchar *) dns->searches[i], strlen (dns->searches[i])); + for (i = 0; dns->options && dns->options[i]; i++) + g_checksum_update (sum, (guchar *) dns->options[i], strlen (dns->options[i])); + + keys = g_list_sort (g_hash_table_get_keys (dns->domains), (GCompareFunc) strcmp); + for (key = keys; key; key = g_list_next (key)) { + + domain = g_hash_table_lookup (dns->domains, key->data); + g_assert_nonnull (domain); + g_checksum_update (sum, (guchar *) domain->name, strlen (domain->name)); + + for (i = 0; domain->servers && domain->servers[i]; i++) + g_checksum_update (sum, (guchar *) domain->servers[i], strlen (domain->servers[i])); + for (i = 0; domain->options && domain->options[i]; i++) + g_checksum_update (sum, (guchar *) domain->options[i], strlen (domain->options[i])); + } + g_list_free (keys); +} + static void global_dns_domain_free (NMGlobalDnsDomain *domain) { diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 0d7a6adfa6..41a7cd5e84 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -150,6 +150,7 @@ const char *const *nm_global_dns_domain_get_servers (const NMGlobalDnsDomain *do const char *const *nm_global_dns_domain_get_options (const NMGlobalDnsDomain *domain); gboolean nm_global_dns_config_is_internal (const NMGlobalDnsConfig *dns); gboolean nm_global_dns_config_is_empty (const NMGlobalDnsConfig *dns); +void nm_global_dns_config_update_checksum (const NMGlobalDnsConfig *dns, GChecksum *sum); void nm_global_dns_config_free (NMGlobalDnsConfig *conf); /* private accessors */ |