mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-03 06:45:26 +00:00
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.
This commit is contained in:
parent
55c204b9a3
commit
ae9e82354a
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
@ -741,6 +744,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,
|
||||
|
@ -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 (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);
|
||||
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;
|
||||
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...");
|
||||
|
||||
/* Set the initial hash */
|
||||
compute_hash (self, NM_DNS_MANAGER_GET_PRIVATE (self)->hash);
|
||||
|
||||
priv->config = g_object_ref (nm_config_get ());
|
||||
/* Set the initial hash */
|
||||
compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)),
|
||||
NM_DNS_MANAGER_GET_PRIVATE (self)->hash);
|
||||
|
||||
g_signal_connect (G_OBJECT (priv->config),
|
||||
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
|
||||
G_CALLBACK (config_changed_cb),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue