summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-06-15 09:03:53 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-10-01 09:05:08 +0200
commitae9e82354a9c1b2247b7d071ed62acd9e83ae27b (patch)
tree6311de68a5c76da2520de24523b8e7c05b625d61
parent55c204b9a357e917cb26b1a1742dff703223037e (diff)
downloadNetworkManager-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.c69
-rw-r--r--src/dns-manager/nm-dns-manager.c110
-rw-r--r--src/dns-manager/nm-dns-plugin.c2
-rw-r--r--src/dns-manager/nm-dns-plugin.h7
-rw-r--r--src/dns-manager/nm-dns-unbound.c1
-rw-r--r--src/nm-config-data.c31
-rw-r--r--src/nm-config-data.h1
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 */