core: merge branch 'bg/global-dns-conf-bgo750458'
Add support for a global DNS configuration read from user configuration file or set through D-Bus. https://bugzilla.gnome.org/show_bug.cgi?id=750458
This commit is contained in:
@@ -303,4 +303,43 @@ _g_key_file_save_to_file (GKeyFile *key_file,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
|
||||||
|
static inline gpointer *
|
||||||
|
_nm_g_hash_table_get_keys_as_array (GHashTable *hash_table,
|
||||||
|
guint *length)
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, *ret;
|
||||||
|
guint i = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail (hash_table, NULL);
|
||||||
|
|
||||||
|
ret = g_new0 (gpointer, g_hash_table_size (hash_table) + 1);
|
||||||
|
g_hash_table_iter_init (&iter, hash_table);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||||
|
ret[i++] = key;
|
||||||
|
|
||||||
|
ret[i] = NULL;
|
||||||
|
|
||||||
|
if (length)
|
||||||
|
*length = i;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if !GLIB_CHECK_VERSION(2, 40, 0)
|
||||||
|
#define g_hash_table_get_keys_as_array(hash_table, length) \
|
||||||
|
G_GNUC_EXTENSION ({ \
|
||||||
|
_nm_g_hash_table_get_keys_as_array (hash_table, length); \
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
#define g_hash_table_get_keys_as_array(hash_table, length) \
|
||||||
|
G_GNUC_EXTENSION ({ \
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
|
||||||
|
(g_hash_table_get_keys_as_array) ((hash_table), (length)); \
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __NM_GLIB_H__ */
|
#endif /* __NM_GLIB_H__ */
|
||||||
|
@@ -368,6 +368,20 @@
|
|||||||
</tp:docstring>
|
</tp:docstring>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property name="GlobalDnsConfiguration" type="a{sv}" access="readwrite">
|
||||||
|
<tp:docstring>
|
||||||
|
Dictionary of global DNS settings where the key is one of
|
||||||
|
"searches", "options" and "domains". The values for the
|
||||||
|
"searches" and "options" keys are string arrays describing the
|
||||||
|
list of search domains and resolver options, respectively.
|
||||||
|
The value of the "domains" key is a second-level dictionary,
|
||||||
|
where each key is a domain name, and each key's value is a
|
||||||
|
third-level dictionary with the keys "servers" and
|
||||||
|
"options". "servers" is a string array of DNS servers,
|
||||||
|
"options" is a string array of domain-specific options.
|
||||||
|
</tp:docstring>
|
||||||
|
</property>
|
||||||
|
|
||||||
<signal name="PropertiesChanged">
|
<signal name="PropertiesChanged">
|
||||||
<tp:docstring>
|
<tp:docstring>
|
||||||
NetworkManager's properties changed.
|
NetworkManager's properties changed.
|
||||||
|
@@ -4534,6 +4534,41 @@ test_g_ptr_array_insert (void)
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_g_hash_table_get_keys_as_array (void)
|
||||||
|
{
|
||||||
|
GHashTable *table = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
guint length;
|
||||||
|
char **keys;
|
||||||
|
|
||||||
|
g_hash_table_insert (table, "one", "1");
|
||||||
|
g_hash_table_insert (table, "two", "2");
|
||||||
|
g_hash_table_insert (table, "three", "3");
|
||||||
|
|
||||||
|
keys = (char **) _nm_g_hash_table_get_keys_as_array (table, &length);
|
||||||
|
g_assert (keys);
|
||||||
|
g_assert_cmpuint (length, ==, 3);
|
||||||
|
|
||||||
|
g_assert ( !strcmp (keys[0], "one")
|
||||||
|
|| !strcmp (keys[1], "one")
|
||||||
|
|| !strcmp (keys[2], "one"));
|
||||||
|
|
||||||
|
g_assert ( !strcmp (keys[0], "two")
|
||||||
|
|| !strcmp (keys[1], "two")
|
||||||
|
|| !strcmp (keys[2], "two"));
|
||||||
|
|
||||||
|
g_assert ( !strcmp (keys[0], "three")
|
||||||
|
|| !strcmp (keys[1], "three")
|
||||||
|
|| !strcmp (keys[2], "three"));
|
||||||
|
|
||||||
|
g_assert (!keys[3]);
|
||||||
|
|
||||||
|
g_free (keys);
|
||||||
|
g_hash_table_unref (table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_test_find_binary_search_cmp (gconstpointer a, gconstpointer b, gpointer dummy)
|
_test_find_binary_search_cmp (gconstpointer a, gconstpointer b, gpointer dummy)
|
||||||
{
|
{
|
||||||
@@ -4903,6 +4938,7 @@ int main (int argc, char **argv)
|
|||||||
g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
||||||
g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
|
g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
|
||||||
g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
|
g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
|
||||||
|
g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array);
|
||||||
g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
|
g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
|
||||||
g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
|
g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
|
||||||
|
|
||||||
|
@@ -636,6 +636,72 @@ ipv6.ip6-privacy=1
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title><literal>global-dns</literal> section</title>
|
||||||
|
<para>This section specifies global DNS settings that override
|
||||||
|
connection-specific configuration.</para>
|
||||||
|
<para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>enable</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Whether the global DNS configuration should be used.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>searches</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A list of search domains to be used during hostname lookup.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>options</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A list of of options to be passed to the hostname resolver.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title><literal>global-dns-domain</literal> sections</title>
|
||||||
|
<para>Sections with a name starting with the "global-dns-domain-"
|
||||||
|
prefix allow to define global DNS configuration for specific
|
||||||
|
domains. The part of section name after "global-dns-domain-"
|
||||||
|
specifies the domain name a section applies to. More specific
|
||||||
|
domains have the precedence over less specific ones and the
|
||||||
|
default domain is represented by the wildcard "*". A default
|
||||||
|
domain section is mandatory.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>servers</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A list of addresses of DNS servers to be used for the given domain.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>options</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A list of domain-specific DNS options. Not used at the moment.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Plugins</title>
|
<title>Plugins</title>
|
||||||
|
|
||||||
|
@@ -112,5 +112,15 @@
|
|||||||
</defaults>
|
</defaults>
|
||||||
</action>
|
</action>
|
||||||
|
|
||||||
|
<action id="org.freedesktop.NetworkManager.settings.modify.global-dns">
|
||||||
|
<_description>Modify persistent global DNS configuration</_description>
|
||||||
|
<_message>System policy prevents modification of the persistent global DNS configuration</_message>
|
||||||
|
<defaults>
|
||||||
|
<allow_any>auth_admin_keep</allow_any>
|
||||||
|
<allow_inactive>auth_admin_keep</allow_inactive>
|
||||||
|
<allow_active>auth_admin_keep</allow_active>
|
||||||
|
</defaults>
|
||||||
|
</action>
|
||||||
|
|
||||||
</policyconfig>
|
</policyconfig>
|
||||||
|
|
||||||
|
@@ -135,6 +135,30 @@ ip6_addr_to_string (const struct in6_addr *addr, const char *iface)
|
|||||||
return buf;
|
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
|
static gboolean
|
||||||
add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split)
|
add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split)
|
||||||
{
|
{
|
||||||
@@ -201,6 +225,7 @@ update (NMDnsPlugin *plugin,
|
|||||||
const GSList *vpn_configs,
|
const GSList *vpn_configs,
|
||||||
const GSList *dev_configs,
|
const GSList *dev_configs,
|
||||||
const GSList *other_configs,
|
const GSList *other_configs,
|
||||||
|
const NMGlobalDnsConfig *global_config,
|
||||||
const char *hostname)
|
const char *hostname)
|
||||||
{
|
{
|
||||||
NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
|
NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
|
||||||
@@ -229,6 +254,9 @@ update (NMDnsPlugin *plugin,
|
|||||||
/* Build up the new dnsmasq config file */
|
/* Build up the new dnsmasq config file */
|
||||||
conf = g_string_sized_new (150);
|
conf = g_string_sized_new (150);
|
||||||
|
|
||||||
|
if (global_config)
|
||||||
|
add_global_config (conf, global_config);
|
||||||
|
else {
|
||||||
/* Use split DNS for VPN configs */
|
/* Use split DNS for VPN configs */
|
||||||
for (iter = (GSList *) vpn_configs; iter; iter = g_slist_next (iter)) {
|
for (iter = (GSList *) vpn_configs; iter; iter = g_slist_next (iter)) {
|
||||||
if (NM_IS_IP4_CONFIG (iter->data))
|
if (NM_IS_IP4_CONFIG (iter->data))
|
||||||
@@ -252,6 +280,7 @@ update (NMDnsPlugin *plugin,
|
|||||||
else if (NM_IS_IP6_CONFIG (iter->data))
|
else if (NM_IS_IP6_CONFIG (iter->data))
|
||||||
add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE);
|
add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Write out the config file */
|
/* Write out the config file */
|
||||||
if (!g_file_set_contents (CONFFILE, conf->str, -1, &error)) {
|
if (!g_file_set_contents (CONFFILE, conf->str, -1, &error)) {
|
||||||
|
@@ -667,7 +667,7 @@ update_resolv_conf (NMDnsManager *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
|
||||||
GChecksum *sum;
|
GChecksum *sum;
|
||||||
@@ -677,6 +677,9 @@ compute_hash (NMDnsManager *self, guint8 buffer[HASH_LEN])
|
|||||||
sum = g_checksum_new (G_CHECKSUM_SHA1);
|
sum = g_checksum_new (G_CHECKSUM_SHA1);
|
||||||
g_assert (len == g_checksum_type_get_length (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)
|
if (priv->ip4_vpn_config)
|
||||||
nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE);
|
nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE);
|
||||||
if (priv->ip4_device_config)
|
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
|
static gboolean
|
||||||
update_dns (NMDnsManager *self,
|
update_dns (NMDnsManager *self,
|
||||||
gboolean no_caching,
|
gboolean no_caching,
|
||||||
@@ -758,6 +793,8 @@ update_dns (NMDnsManager *self,
|
|||||||
gboolean caching = FALSE, update = TRUE;
|
gboolean caching = FALSE, update = TRUE;
|
||||||
gboolean resolv_conf_updated = FALSE;
|
gboolean resolv_conf_updated = FALSE;
|
||||||
SpawnResult result = SR_ERROR;
|
SpawnResult result = SR_ERROR;
|
||||||
|
NMConfigData *data;
|
||||||
|
NMGlobalDnsConfig *global_config;
|
||||||
|
|
||||||
g_return_val_if_fail (!error || !*error, FALSE);
|
g_return_val_if_fail (!error || !*error, FALSE);
|
||||||
|
|
||||||
@@ -771,8 +808,11 @@ update_dns (NMDnsManager *self,
|
|||||||
_LOGD ("update-dns: updating resolv.conf");
|
_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 */
|
/* 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.nameservers = g_ptr_array_new ();
|
||||||
rc.searches = g_ptr_array_new ();
|
rc.searches = g_ptr_array_new ();
|
||||||
@@ -780,6 +820,9 @@ update_dns (NMDnsManager *self,
|
|||||||
rc.nis_domain = NULL;
|
rc.nis_domain = NULL;
|
||||||
rc.nis_servers = g_ptr_array_new ();
|
rc.nis_servers = g_ptr_array_new ();
|
||||||
|
|
||||||
|
if (global_config)
|
||||||
|
merge_global_dns_config (&rc, global_config);
|
||||||
|
else {
|
||||||
if (priv->ip4_vpn_config)
|
if (priv->ip4_vpn_config)
|
||||||
merge_one_ip4_config (&rc, priv->ip4_vpn_config);
|
merge_one_ip4_config (&rc, priv->ip4_vpn_config);
|
||||||
if (priv->ip4_device_config)
|
if (priv->ip4_device_config)
|
||||||
@@ -808,6 +851,7 @@ update_dns (NMDnsManager *self,
|
|||||||
} else
|
} else
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it
|
/* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it
|
||||||
* ("example.com") to the searches list, to ensure that we can still resolve its
|
* ("example.com") to the searches list, to ensure that we can still resolve its
|
||||||
@@ -879,6 +923,7 @@ update_dns (NMDnsManager *self,
|
|||||||
caching = TRUE;
|
caching = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!global_config)
|
||||||
build_plugin_config_lists (self, &vpn_configs, &dev_configs, &other_configs);
|
build_plugin_config_lists (self, &vpn_configs, &dev_configs, &other_configs);
|
||||||
|
|
||||||
_LOGD ("update-dns: updating plugin %s", plugin_name);
|
_LOGD ("update-dns: updating plugin %s", plugin_name);
|
||||||
@@ -886,6 +931,7 @@ update_dns (NMDnsManager *self,
|
|||||||
vpn_configs,
|
vpn_configs,
|
||||||
dev_configs,
|
dev_configs,
|
||||||
other_configs,
|
other_configs,
|
||||||
|
global_config,
|
||||||
priv->hostname)) {
|
priv->hostname)) {
|
||||||
_LOGW ("update-dns: plugin %s update failed", plugin_name);
|
_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);
|
priv = NM_DNS_MANAGER_GET_PRIVATE (self);
|
||||||
g_return_if_fail (priv->updates_queue > 0);
|
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;
|
changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE;
|
||||||
_LOGD ("(%s): DNS configuration %s", func, changed ? "changed" : "did not change");
|
_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 |
|
if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_SIGHUP |
|
||||||
NM_CONFIG_CHANGE_SIGUSR1 |
|
NM_CONFIG_CHANGE_SIGUSR1 |
|
||||||
NM_CONFIG_CHANGE_DNS_MODE |
|
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)) {
|
if (!update_dns (self, TRUE, &error)) {
|
||||||
_LOGW ("could not commit DNS changes: %s", error->message);
|
_LOGW ("could not commit DNS changes: %s", error->message);
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
@@ -1361,10 +1408,11 @@ nm_dns_manager_init (NMDnsManager *self)
|
|||||||
|
|
||||||
_LOGt ("creating...");
|
_LOGt ("creating...");
|
||||||
|
|
||||||
/* Set the initial hash */
|
|
||||||
compute_hash (self, NM_DNS_MANAGER_GET_PRIVATE (self)->hash);
|
|
||||||
|
|
||||||
priv->config = g_object_ref (nm_config_get ());
|
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),
|
g_signal_connect (G_OBJECT (priv->config),
|
||||||
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
|
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
|
||||||
G_CALLBACK (config_changed_cb),
|
G_CALLBACK (config_changed_cb),
|
||||||
|
@@ -56,6 +56,7 @@ nm_dns_plugin_update (NMDnsPlugin *self,
|
|||||||
const GSList *vpn_configs,
|
const GSList *vpn_configs,
|
||||||
const GSList *dev_configs,
|
const GSList *dev_configs,
|
||||||
const GSList *other_configs,
|
const GSList *other_configs,
|
||||||
|
const NMGlobalDnsConfig *global_config,
|
||||||
const char *hostname)
|
const char *hostname)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE);
|
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,
|
vpn_configs,
|
||||||
dev_configs,
|
dev_configs,
|
||||||
other_configs,
|
other_configs,
|
||||||
|
global_config,
|
||||||
hostname);
|
hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "nm-default.h"
|
#include "nm-default.h"
|
||||||
|
|
||||||
|
#include "nm-config-data.h"
|
||||||
|
|
||||||
#define NM_TYPE_DNS_PLUGIN (nm_dns_plugin_get_type ())
|
#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(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))
|
#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
|
* NMIP4Config or NMIP6Config objects from VPN connections, while
|
||||||
* 'dev_configs' is a list of NMPI4Config or NMIP6Config objects from
|
* 'dev_configs' is a list of NMPI4Config or NMIP6Config objects from
|
||||||
* active devices. 'other_configs' represent other IP configuration that
|
* 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.
|
* order.
|
||||||
*/
|
*/
|
||||||
gboolean (*update) (NMDnsPlugin *self,
|
gboolean (*update) (NMDnsPlugin *self,
|
||||||
const GSList *vpn_configs,
|
const GSList *vpn_configs,
|
||||||
const GSList *dev_configs,
|
const GSList *dev_configs,
|
||||||
const GSList *other_configs,
|
const GSList *other_configs,
|
||||||
|
const NMGlobalDnsConfig *global_config,
|
||||||
const char *hostname);
|
const char *hostname);
|
||||||
|
|
||||||
/* Subclasses should override and return TRUE if they start a local
|
/* 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 *vpn_configs,
|
||||||
const GSList *dev_configs,
|
const GSList *dev_configs,
|
||||||
const GSList *other_configs,
|
const GSList *other_configs,
|
||||||
|
const NMGlobalDnsConfig *global_config,
|
||||||
const char *hostname);
|
const char *hostname);
|
||||||
|
|
||||||
/* For subclasses/plugins */
|
/* For subclasses/plugins */
|
||||||
|
@@ -31,6 +31,7 @@ update (NMDnsPlugin *plugin,
|
|||||||
const GSList *vpn_configs,
|
const GSList *vpn_configs,
|
||||||
const GSList *dev_configs,
|
const GSList *dev_configs,
|
||||||
const GSList *other_configs,
|
const GSList *other_configs,
|
||||||
|
const NMGlobalDnsConfig *global_config,
|
||||||
const char *hostname)
|
const char *hostname)
|
||||||
{
|
{
|
||||||
/* TODO: We currently call a script installed with the dnssec-trigger
|
/* TODO: We currently call a script installed with the dnssec-trigger
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM "org.freedesktop.NetworkManager.settings.modify.system"
|
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM "org.freedesktop.NetworkManager.settings.modify.system"
|
||||||
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
|
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
|
||||||
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname"
|
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname"
|
||||||
|
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns"
|
||||||
|
|
||||||
|
|
||||||
typedef struct NMAuthChain NMAuthChain;
|
typedef struct NMAuthChain NMAuthChain;
|
||||||
|
@@ -72,10 +72,25 @@ typedef struct {
|
|||||||
char *dns_mode;
|
char *dns_mode;
|
||||||
char *rc_manager;
|
char *rc_manager;
|
||||||
|
|
||||||
|
NMGlobalDnsConfig *global_dns;
|
||||||
|
|
||||||
/* mutable field */
|
/* mutable field */
|
||||||
char *value_cached;
|
char *value_cached;
|
||||||
} NMConfigDataPrivate;
|
} NMConfigDataPrivate;
|
||||||
|
|
||||||
|
struct _NMGlobalDnsDomain {
|
||||||
|
char *name;
|
||||||
|
char **servers;
|
||||||
|
char **options;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _NMGlobalDnsConfig {
|
||||||
|
char **searches;
|
||||||
|
char **options;
|
||||||
|
GHashTable *domains;
|
||||||
|
char **domain_list;
|
||||||
|
gboolean internal;
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@@ -91,6 +106,7 @@ enum {
|
|||||||
LAST_PROP
|
LAST_PROP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT)
|
||||||
|
|
||||||
#define NM_CONFIG_DATA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG_DATA, NMConfigDataPrivate))
|
#define NM_CONFIG_DATA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG_DATA, NMConfigDataPrivate))
|
||||||
@@ -534,6 +550,492 @@ nm_config_data_log (const NMConfigData *self, const char *prefix)
|
|||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
const char *const *
|
||||||
|
nm_global_dns_config_get_searches (const NMGlobalDnsConfig *dns)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (dns, NULL);
|
||||||
|
|
||||||
|
return (const char *const *) dns->searches;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *const *
|
||||||
|
nm_global_dns_config_get_options (const NMGlobalDnsConfig *dns)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (dns, NULL);
|
||||||
|
|
||||||
|
return (const char *const *) dns->options;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
nm_global_dns_config_get_num_domains (const NMGlobalDnsConfig *dns)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (dns, 0);
|
||||||
|
g_return_val_if_fail (dns->domains, 0);
|
||||||
|
|
||||||
|
return g_hash_table_size (dns->domains);
|
||||||
|
}
|
||||||
|
|
||||||
|
NMGlobalDnsDomain *
|
||||||
|
nm_global_dns_config_get_domain (const NMGlobalDnsConfig *dns, guint i)
|
||||||
|
{
|
||||||
|
NMGlobalDnsDomain *domain;
|
||||||
|
|
||||||
|
g_return_val_if_fail (dns, NULL);
|
||||||
|
g_return_val_if_fail (dns->domains, NULL);
|
||||||
|
g_return_val_if_fail (dns->domain_list, NULL);
|
||||||
|
g_return_val_if_fail (i < g_strv_length (dns->domain_list), NULL);
|
||||||
|
|
||||||
|
domain = g_hash_table_lookup (dns->domains, dns->domain_list[i]);
|
||||||
|
g_return_val_if_fail (domain, NULL);
|
||||||
|
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
NMGlobalDnsDomain *nm_global_dns_config_lookup_domain (const NMGlobalDnsConfig *dns, const char *name)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (dns, NULL);
|
||||||
|
g_return_val_if_fail (dns->domains, NULL);
|
||||||
|
g_return_val_if_fail (name, NULL);
|
||||||
|
|
||||||
|
return g_hash_table_lookup (dns->domains, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nm_global_dns_domain_get_name (const NMGlobalDnsDomain *domain)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (domain, NULL);
|
||||||
|
|
||||||
|
return (const char *) domain->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *const *
|
||||||
|
nm_global_dns_domain_get_servers (const NMGlobalDnsDomain *domain)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (domain, NULL);
|
||||||
|
|
||||||
|
return (const char *const *) domain->servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *const *
|
||||||
|
nm_global_dns_domain_get_options (const NMGlobalDnsDomain *domain)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (domain, NULL);
|
||||||
|
return (const char *const *) domain->options;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_global_dns_config_is_internal (const NMGlobalDnsConfig *dns)
|
||||||
|
{
|
||||||
|
return dns->internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_global_dns_config_is_empty (const NMGlobalDnsConfig *dns)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (dns, TRUE);
|
||||||
|
g_return_val_if_fail (dns->domains, TRUE);
|
||||||
|
|
||||||
|
return (!dns->searches || g_strv_length (dns->searches) == 0)
|
||||||
|
&& (!dns->options || g_strv_length (dns->options) == 0)
|
||||||
|
&& 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)
|
||||||
|
{
|
||||||
|
if (domain) {
|
||||||
|
g_free (domain->name);
|
||||||
|
g_strfreev (domain->servers);
|
||||||
|
g_strfreev (domain->options);
|
||||||
|
g_free (domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_global_dns_config_free (NMGlobalDnsConfig *conf)
|
||||||
|
{
|
||||||
|
if (conf) {
|
||||||
|
g_strfreev (conf->searches);
|
||||||
|
g_strfreev (conf->options);
|
||||||
|
g_free (conf->domain_list);
|
||||||
|
g_hash_table_unref (conf->domains);
|
||||||
|
g_free (conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NMGlobalDnsConfig *
|
||||||
|
nm_config_data_get_global_dns_config (const NMConfigData *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (NM_IS_CONFIG_DATA (self), NULL);
|
||||||
|
|
||||||
|
return NM_CONFIG_DATA_GET_PRIVATE (self)->global_dns;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
global_dns_config_update_domain_list (NMGlobalDnsConfig *dns)
|
||||||
|
{
|
||||||
|
guint length;
|
||||||
|
|
||||||
|
g_free (dns->domain_list);
|
||||||
|
dns->domain_list = (char **) g_hash_table_get_keys_as_array (dns->domains, &length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NMGlobalDnsConfig *
|
||||||
|
load_global_dns (GKeyFile *keyfile, gboolean internal)
|
||||||
|
{
|
||||||
|
NMGlobalDnsConfig *conf;
|
||||||
|
char *group, *domain_prefix;
|
||||||
|
gs_strfreev char **groups = NULL;
|
||||||
|
int g, i, j, domain_prefix_len;
|
||||||
|
gboolean default_found = FALSE;
|
||||||
|
char **strv;
|
||||||
|
|
||||||
|
group = internal
|
||||||
|
? NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS
|
||||||
|
: NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS;
|
||||||
|
domain_prefix = internal
|
||||||
|
? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN
|
||||||
|
: NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN;
|
||||||
|
domain_prefix_len = strlen (domain_prefix);
|
||||||
|
|
||||||
|
if (!keyfile || !nm_config_keyfile_get_boolean (keyfile, group, NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE, FALSE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
conf = g_malloc0 (sizeof (NMGlobalDnsConfig));
|
||||||
|
conf->domains = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, (GDestroyNotify) global_dns_domain_free);
|
||||||
|
|
||||||
|
strv = g_key_file_get_string_list (keyfile, group, "searches", NULL, NULL);
|
||||||
|
if (strv)
|
||||||
|
conf->searches = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
strv = g_key_file_get_string_list (keyfile, group, "options", NULL, NULL);
|
||||||
|
if (strv) {
|
||||||
|
_nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
for (i = 0, j = 0; strv[i]; i++) {
|
||||||
|
if (_nm_utils_dns_option_validate (strv[i], NULL, NULL, TRUE, NULL))
|
||||||
|
strv[j++] = strv[i];
|
||||||
|
else
|
||||||
|
g_free (strv[i]);
|
||||||
|
}
|
||||||
|
strv[j] = NULL;
|
||||||
|
conf->options = strv;
|
||||||
|
}
|
||||||
|
|
||||||
|
groups = g_key_file_get_groups (keyfile, NULL);
|
||||||
|
for (g = 0; groups[g]; g++) {
|
||||||
|
char *name;
|
||||||
|
char **servers = NULL, **options = NULL;
|
||||||
|
NMGlobalDnsDomain *domain;
|
||||||
|
|
||||||
|
if ( !g_str_has_prefix (groups[g], domain_prefix)
|
||||||
|
|| !groups[g][domain_prefix_len])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
strv = g_key_file_get_string_list (keyfile, groups[g], "servers", NULL, NULL);
|
||||||
|
if (strv) {
|
||||||
|
_nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
for (i = 0, j = 0; strv[i]; i++) {
|
||||||
|
if ( nm_utils_ipaddr_valid (AF_INET, strv[i])
|
||||||
|
|| nm_utils_ipaddr_valid (AF_INET6, strv[i]))
|
||||||
|
strv[j++] = strv[i];
|
||||||
|
else
|
||||||
|
g_free (strv[i]);
|
||||||
|
}
|
||||||
|
if (j) {
|
||||||
|
strv[j] = NULL;
|
||||||
|
servers = strv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_free (strv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!servers)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
strv = g_key_file_get_string_list (keyfile, groups[g], "options", NULL, NULL);
|
||||||
|
if (strv)
|
||||||
|
options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
name = strdup (&groups[g][domain_prefix_len]);
|
||||||
|
domain = g_malloc0 (sizeof (NMGlobalDnsDomain));
|
||||||
|
domain->name = name;
|
||||||
|
domain->servers = servers;
|
||||||
|
domain->options = options;
|
||||||
|
|
||||||
|
g_hash_table_insert (conf->domains, strdup (name), domain);
|
||||||
|
|
||||||
|
if (!strcmp (name, "*"))
|
||||||
|
default_found = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!default_found) {
|
||||||
|
nm_log_dbg (LOGD_CORE, "%s global DNS configuration is missing default domain, ignore it",
|
||||||
|
internal ? "internal" : "user");
|
||||||
|
nm_global_dns_config_free (conf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->internal = internal;
|
||||||
|
global_dns_config_update_domain_list (conf);
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns, GValue *value)
|
||||||
|
{
|
||||||
|
GVariantBuilder conf_builder, domains_builder, domain_builder;
|
||||||
|
NMGlobalDnsDomain *domain;
|
||||||
|
GHashTableIter iter;
|
||||||
|
|
||||||
|
g_variant_builder_init (&conf_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||||
|
if (!dns)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (dns->searches) {
|
||||||
|
g_variant_builder_add (&conf_builder, "{sv}", "searches",
|
||||||
|
g_variant_new_strv ((const char *const *) dns->searches, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns->options) {
|
||||||
|
g_variant_builder_add (&conf_builder, "{sv}", "options",
|
||||||
|
g_variant_new_strv ((const char *const *) dns->options, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_init (&domains_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, dns->domains);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &domain)) {
|
||||||
|
|
||||||
|
g_variant_builder_init (&domain_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||||
|
|
||||||
|
if (domain->servers) {
|
||||||
|
g_variant_builder_add (&domain_builder, "{sv}", "servers",
|
||||||
|
g_variant_new_strv ((const char *const *) domain->servers, -1));
|
||||||
|
}
|
||||||
|
if (domain->options) {
|
||||||
|
g_variant_builder_add (&domain_builder, "{sv}", "options",
|
||||||
|
g_variant_new_strv ((const char *const *) domain->options, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_add (&domains_builder, "{sv}", domain->name,
|
||||||
|
g_variant_builder_end (&domain_builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_add (&conf_builder, "{sv}", "domains",
|
||||||
|
g_variant_builder_end (&domains_builder));
|
||||||
|
out:
|
||||||
|
g_value_take_variant (value, g_variant_builder_end (&conf_builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
static NMGlobalDnsDomain *
|
||||||
|
global_dns_domain_from_dbus (char *name, GVariant *variant)
|
||||||
|
{
|
||||||
|
NMGlobalDnsDomain *domain;
|
||||||
|
GVariantIter iter;
|
||||||
|
char **strv, *key;
|
||||||
|
GVariant *val;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}")))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
domain = g_malloc0 (sizeof (NMGlobalDnsDomain));
|
||||||
|
domain->name = g_strdup (name);
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, variant);
|
||||||
|
while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) {
|
||||||
|
|
||||||
|
if ( !g_strcmp0 (key, "servers")
|
||||||
|
&& g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
|
||||||
|
strv = g_variant_dup_strv (val, NULL);
|
||||||
|
_nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
for (i = 0, j = 0; strv && strv[i]; i++) {
|
||||||
|
if ( nm_utils_ipaddr_valid (AF_INET, strv[i])
|
||||||
|
|| nm_utils_ipaddr_valid (AF_INET6, strv[i]))
|
||||||
|
strv[j++] = strv[i];
|
||||||
|
else
|
||||||
|
g_free (strv[i]);
|
||||||
|
}
|
||||||
|
if (j) {
|
||||||
|
strv[j] = NULL;
|
||||||
|
domain->servers = strv;
|
||||||
|
} else
|
||||||
|
g_free (strv);
|
||||||
|
} else if ( !g_strcmp0 (key, "options")
|
||||||
|
&& g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
|
||||||
|
strv = g_variant_dup_strv (val, NULL);
|
||||||
|
domain->options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_unref (val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At least one server is required */
|
||||||
|
if (!domain->servers) {
|
||||||
|
global_dns_domain_free (domain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
NMGlobalDnsConfig *
|
||||||
|
nm_global_dns_config_from_dbus (const GValue *value, GError **error)
|
||||||
|
{
|
||||||
|
NMGlobalDnsConfig *dns_config;
|
||||||
|
GVariant *variant, *val;
|
||||||
|
GVariantIter iter;
|
||||||
|
char **strv, *key;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!G_VALUE_HOLDS_VARIANT (value)) {
|
||||||
|
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
|
||||||
|
"invalid value type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
variant = g_value_get_variant (value);
|
||||||
|
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}"))) {
|
||||||
|
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
|
||||||
|
"invalid variant type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_config = g_malloc0 (sizeof (NMGlobalDnsConfig));
|
||||||
|
dns_config->domains = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, (GDestroyNotify) global_dns_domain_free);
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, variant);
|
||||||
|
while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) {
|
||||||
|
|
||||||
|
if ( !g_strcmp0 (key, "searches")
|
||||||
|
&& g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
|
||||||
|
strv = g_variant_dup_strv (val, NULL);
|
||||||
|
dns_config->searches = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
} else if ( !g_strcmp0 (key, "options")
|
||||||
|
&& g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
|
||||||
|
strv = g_variant_dup_strv (val, NULL);
|
||||||
|
_nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
for (i = 0, j = 0; strv && strv[i]; i++) {
|
||||||
|
if (_nm_utils_dns_option_validate (strv[i], NULL, NULL, TRUE, NULL))
|
||||||
|
strv[j++] = strv[i];
|
||||||
|
else
|
||||||
|
g_free (strv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strv)
|
||||||
|
strv[j] = NULL;
|
||||||
|
|
||||||
|
dns_config->options = strv;
|
||||||
|
} else if ( !g_strcmp0 (key, "domains")
|
||||||
|
&& g_variant_is_of_type (val, G_VARIANT_TYPE ("a{sv}"))) {
|
||||||
|
NMGlobalDnsDomain *domain;
|
||||||
|
GVariantIter domain_iter;
|
||||||
|
GVariant *v;
|
||||||
|
char *k;
|
||||||
|
|
||||||
|
g_variant_iter_init (&domain_iter, val);
|
||||||
|
while (g_variant_iter_next (&domain_iter, "{&sv}", &k, &v)) {
|
||||||
|
if (k) {
|
||||||
|
domain = global_dns_domain_from_dbus (k, v);
|
||||||
|
if (domain)
|
||||||
|
g_hash_table_insert (dns_config->domains, strdup (k), domain);
|
||||||
|
}
|
||||||
|
g_variant_unref (v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_variant_unref (val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* An empty value is valid and clears the internal configuration */
|
||||||
|
if ( !nm_global_dns_config_is_empty (dns_config)
|
||||||
|
&& !nm_global_dns_config_lookup_domain (dns_config, "*")) {
|
||||||
|
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
|
||||||
|
"Global DNS configuration is missing the default domain");
|
||||||
|
nm_global_dns_config_free (dns_config);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_dns_config_update_domain_list (dns_config);
|
||||||
|
return dns_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
global_dns_equal (NMGlobalDnsConfig *old, NMGlobalDnsConfig *new)
|
||||||
|
{
|
||||||
|
NMGlobalDnsDomain *domain_old, *domain_new;
|
||||||
|
gpointer key, value_old, value_new;
|
||||||
|
GHashTableIter iter;
|
||||||
|
|
||||||
|
if (old == new)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (!old || !new)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if ( !_nm_utils_strv_equal (old->options, new->options)
|
||||||
|
|| !_nm_utils_strv_equal (old->searches, new->searches))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if ((!old->domains || !new->domains) && old->domains != new->domains)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (g_hash_table_size (old->domains) != g_hash_table_size (new->domains))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, old->domains);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value_old)) {
|
||||||
|
value_new = g_hash_table_lookup (new->domains, key);
|
||||||
|
if (!value_new)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
domain_old = value_old;
|
||||||
|
domain_new = value_new;
|
||||||
|
|
||||||
|
if ( !_nm_utils_strv_equal (domain_old->options, domain_new->options)
|
||||||
|
|| !_nm_utils_strv_equal (domain_old->servers, domain_new->servers))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
nm_config_data_get_connection_default (const NMConfigData *self,
|
nm_config_data_get_connection_default (const NMConfigData *self,
|
||||||
const char *property,
|
const char *property,
|
||||||
@@ -683,6 +1185,9 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data)
|
|||||||
if (g_strcmp0 (nm_config_data_get_rc_manager (old_data), nm_config_data_get_rc_manager (new_data)))
|
if (g_strcmp0 (nm_config_data_get_rc_manager (old_data), nm_config_data_get_rc_manager (new_data)))
|
||||||
changes |= NM_CONFIG_CHANGE_RC_MANAGER;
|
changes |= NM_CONFIG_CHANGE_RC_MANAGER;
|
||||||
|
|
||||||
|
if (!global_dns_equal (priv_old->global_dns, priv_new->global_dns))
|
||||||
|
changes |= NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG;
|
||||||
|
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -804,6 +1309,8 @@ finalize (GObject *gobject)
|
|||||||
g_slist_free_full (priv->ignore_carrier, g_free);
|
g_slist_free_full (priv->ignore_carrier, g_free);
|
||||||
g_slist_free_full (priv->assume_ipv6ll_only, g_free);
|
g_slist_free_full (priv->assume_ipv6ll_only, g_free);
|
||||||
|
|
||||||
|
nm_global_dns_config_free (priv->global_dns);
|
||||||
|
|
||||||
if (priv->connection_infos) {
|
if (priv->connection_infos) {
|
||||||
for (i = 0; priv->connection_infos[i].group_name; i++) {
|
for (i = 0; priv->connection_infos[i].group_name; i++) {
|
||||||
g_free (priv->connection_infos[i].group_name);
|
g_free (priv->connection_infos[i].group_name);
|
||||||
@@ -858,6 +1365,10 @@ constructed (GObject *object)
|
|||||||
|
|
||||||
priv->no_auto_default.specs_config = nm_config_get_device_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "no-auto-default", NULL);
|
priv->no_auto_default.specs_config = nm_config_get_device_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "no-auto-default", NULL);
|
||||||
|
|
||||||
|
priv->global_dns = load_global_dns (priv->keyfile_user, FALSE);
|
||||||
|
if (!priv->global_dns)
|
||||||
|
priv->global_dns = load_global_dns (priv->keyfile_intern, TRUE);
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object);
|
G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,6 +76,7 @@ typedef enum { /*< flags >*/
|
|||||||
NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 8),
|
NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 8),
|
||||||
NM_CONFIG_CHANGE_DNS_MODE = (1L << 9),
|
NM_CONFIG_CHANGE_DNS_MODE = (1L << 9),
|
||||||
NM_CONFIG_CHANGE_RC_MANAGER = (1L << 10),
|
NM_CONFIG_CHANGE_RC_MANAGER = (1L << 10),
|
||||||
|
NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG = (1L << 11),
|
||||||
|
|
||||||
_NM_CONFIG_CHANGE_LAST,
|
_NM_CONFIG_CHANGE_LAST,
|
||||||
NM_CONFIG_CHANGE_ALL = ((_NM_CONFIG_CHANGE_LAST - 1) << 1) - 1,
|
NM_CONFIG_CHANGE_ALL = ((_NM_CONFIG_CHANGE_LAST - 1) << 1) - 1,
|
||||||
@@ -89,6 +90,9 @@ typedef struct {
|
|||||||
GObjectClass parent;
|
GObjectClass parent;
|
||||||
} NMConfigDataClass;
|
} NMConfigDataClass;
|
||||||
|
|
||||||
|
typedef struct _NMGlobalDnsConfig NMGlobalDnsConfig;
|
||||||
|
typedef struct _NMGlobalDnsDomain NMGlobalDnsDomain;
|
||||||
|
|
||||||
GType nm_config_data_get_type (void);
|
GType nm_config_data_get_type (void);
|
||||||
|
|
||||||
NMConfigData *nm_config_data_new (const char *config_main_file,
|
NMConfigData *nm_config_data_new (const char *config_main_file,
|
||||||
@@ -124,6 +128,7 @@ const char *nm_config_data_get_rc_manager (const NMConfigData *self);
|
|||||||
|
|
||||||
gboolean nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device);
|
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);
|
gboolean nm_config_data_get_assume_ipv6ll_only (const NMConfigData *self, NMDevice *device);
|
||||||
|
NMGlobalDnsConfig *nm_config_data_get_global_dns_config (const NMConfigData *self);
|
||||||
|
|
||||||
char *nm_config_data_get_connection_default (const NMConfigData *self,
|
char *nm_config_data_get_connection_default (const NMConfigData *self,
|
||||||
const char *property,
|
const char *property,
|
||||||
@@ -135,6 +140,22 @@ gboolean nm_config_data_is_intern_atomic_group (const NMConfigData *self, const
|
|||||||
|
|
||||||
GKeyFile *nm_config_data_clone_keyfile_intern (const NMConfigData *self);
|
GKeyFile *nm_config_data_clone_keyfile_intern (const NMConfigData *self);
|
||||||
|
|
||||||
|
const char *const *nm_global_dns_config_get_searches (const NMGlobalDnsConfig *dns);
|
||||||
|
const char *const *nm_global_dns_config_get_options (const NMGlobalDnsConfig *dns);
|
||||||
|
guint nm_global_dns_config_get_num_domains (const NMGlobalDnsConfig *dns);
|
||||||
|
NMGlobalDnsDomain *nm_global_dns_config_get_domain (const NMGlobalDnsConfig *dns, guint i);
|
||||||
|
NMGlobalDnsDomain *nm_global_dns_config_lookup_domain (const NMGlobalDnsConfig *dns, const char *name);
|
||||||
|
const char *nm_global_dns_domain_get_name (const NMGlobalDnsDomain *domain);
|
||||||
|
const char *const *nm_global_dns_domain_get_servers (const NMGlobalDnsDomain *domain);
|
||||||
|
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);
|
||||||
|
|
||||||
|
NMGlobalDnsConfig *nm_global_dns_config_from_dbus (const GValue *value, GError **error);
|
||||||
|
void nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns_config, GValue *value);
|
||||||
|
|
||||||
/* private accessors */
|
/* private accessors */
|
||||||
GKeyFile *_nm_config_data_get_keyfile (const NMConfigData *self);
|
GKeyFile *_nm_config_data_get_keyfile (const NMConfigData *self);
|
||||||
GKeyFile *_nm_config_data_get_keyfile_user (const NMConfigData *self);
|
GKeyFile *_nm_config_data_get_keyfile_user (const NMConfigData *self);
|
||||||
|
@@ -1184,6 +1184,24 @@ intern_config_read (const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
/*
|
||||||
|
* If user configuration specifies global DNS options, the DNS
|
||||||
|
* options in internal configuration must be deleted. Otherwise a
|
||||||
|
* deletion of options from user configuration may cause the
|
||||||
|
* internal options to appear again.
|
||||||
|
*/
|
||||||
|
if (nm_config_keyfile_get_boolean (keyfile_conf, NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS, NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE, FALSE)) {
|
||||||
|
if (g_key_file_remove_group (keyfile_intern, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NULL))
|
||||||
|
needs_rewrite = TRUE;
|
||||||
|
for (g = 0; groups && groups[g]; g++) {
|
||||||
|
if ( g_str_has_prefix (groups[g], NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)
|
||||||
|
&& groups[g][STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)]) {
|
||||||
|
g_key_file_remove_group (keyfile_intern, groups[g], NULL);
|
||||||
|
needs_rewrite = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_key_file_unref (keyfile);
|
g_key_file_unref (keyfile);
|
||||||
|
|
||||||
if (out_needs_rewrite)
|
if (out_needs_rewrite)
|
||||||
@@ -1413,6 +1431,73 @@ nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, con
|
|||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError **error)
|
||||||
|
{
|
||||||
|
NMConfigPrivate *priv;
|
||||||
|
GKeyFile *keyfile;
|
||||||
|
char **groups;
|
||||||
|
const NMGlobalDnsConfig *old_global_dns;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
|
||||||
|
|
||||||
|
priv = NM_CONFIG_GET_PRIVATE (self);
|
||||||
|
g_return_val_if_fail (priv->config_data, FALSE);
|
||||||
|
|
||||||
|
old_global_dns = nm_config_data_get_global_dns_config (priv->config_data);
|
||||||
|
if (old_global_dns && !nm_global_dns_config_is_internal (old_global_dns)) {
|
||||||
|
g_set_error_literal (error, 1, 0,
|
||||||
|
"Global DNS configuration already set via configuration file");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyfile = nm_config_data_clone_keyfile_intern (priv->config_data);
|
||||||
|
|
||||||
|
/* Remove existing groups */
|
||||||
|
g_key_file_remove_group (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NULL);
|
||||||
|
groups = g_key_file_get_groups (keyfile, NULL);
|
||||||
|
for (i = 0; groups[i]; i++) {
|
||||||
|
if (g_str_has_prefix (groups[i], NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN))
|
||||||
|
g_key_file_remove_group (keyfile, groups[i], NULL);
|
||||||
|
}
|
||||||
|
g_strfreev (groups);
|
||||||
|
|
||||||
|
/* An empty configuration removes everything from internal configuration file */
|
||||||
|
if (nm_global_dns_config_is_empty (global_dns))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Set new values */
|
||||||
|
g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE, "yes");
|
||||||
|
|
||||||
|
nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS,
|
||||||
|
"searches", nm_global_dns_config_get_searches (global_dns),
|
||||||
|
-1);
|
||||||
|
|
||||||
|
nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS,
|
||||||
|
"options", nm_global_dns_config_get_options (global_dns),
|
||||||
|
-1);
|
||||||
|
|
||||||
|
for (i = 0; i < nm_global_dns_config_get_num_domains (global_dns); i++) {
|
||||||
|
NMGlobalDnsDomain *domain = nm_global_dns_config_get_domain (global_dns, i);
|
||||||
|
gs_free char *group_name;
|
||||||
|
|
||||||
|
group_name = g_strdup_printf (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN "%s",
|
||||||
|
nm_global_dns_domain_get_name (domain));
|
||||||
|
|
||||||
|
nm_config_keyfile_set_string_list (keyfile, group_name, "servers",
|
||||||
|
nm_global_dns_domain_get_servers (domain), -1);
|
||||||
|
nm_config_keyfile_set_string_list (keyfile, group_name, "options",
|
||||||
|
nm_global_dns_domain_get_options (domain), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
nm_config_set_values (self, keyfile, TRUE, FALSE);
|
||||||
|
g_key_file_unref (keyfile);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_config_set_values:
|
* nm_config_set_values:
|
||||||
* @self: the NMConfig instance
|
* @self: the NMConfig instance
|
||||||
@@ -1593,6 +1678,8 @@ _change_flags_one_to_string (NMConfigChangeFlags flag)
|
|||||||
return "dns-mode";
|
return "dns-mode";
|
||||||
case NM_CONFIG_CHANGE_RC_MANAGER:
|
case NM_CONFIG_CHANGE_RC_MANAGER:
|
||||||
return "rc-manager";
|
return "rc-manager";
|
||||||
|
case NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG:
|
||||||
|
return "global-dns-config";
|
||||||
default:
|
default:
|
||||||
g_return_val_if_reached ("unknown");
|
g_return_val_if_reached ("unknown");
|
||||||
}
|
}
|
||||||
|
@@ -49,17 +49,20 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN ".intern."
|
#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN ".intern."
|
||||||
#define NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION "connection"
|
#define NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION "connection"
|
||||||
|
#define NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN "global-dns-domain-"
|
||||||
#define NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST ".test-append-stringlist"
|
#define NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST ".test-append-stringlist"
|
||||||
|
|
||||||
#define NM_CONFIG_KEYFILE_GROUP_MAIN "main"
|
#define NM_CONFIG_KEYFILE_GROUP_MAIN "main"
|
||||||
#define NM_CONFIG_KEYFILE_GROUP_LOGGING "logging"
|
#define NM_CONFIG_KEYFILE_GROUP_LOGGING "logging"
|
||||||
#define NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY "connectivity"
|
#define NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY "connectivity"
|
||||||
|
#define NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS "global-dns"
|
||||||
|
|
||||||
#define NM_CONFIG_KEYFILE_GROUP_KEYFILE "keyfile"
|
#define NM_CONFIG_KEYFILE_GROUP_KEYFILE "keyfile"
|
||||||
#define NM_CONFIG_KEYFILE_GROUP_IFUPDOWN "ifupdown"
|
#define NM_CONFIG_KEYFILE_GROUP_IFUPDOWN "ifupdown"
|
||||||
#define NM_CONFIG_KEYFILE_GROUP_IFNET "ifnet"
|
#define NM_CONFIG_KEYFILE_GROUP_IFNET "ifnet"
|
||||||
|
|
||||||
#define NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND "backend"
|
#define NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND "backend"
|
||||||
|
#define NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE "enable"
|
||||||
#define NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS ".was"
|
#define NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS ".was"
|
||||||
#define NM_CONFIG_KEYFILE_KEY_IFNET_AUTO_REFRESH "auto_refresh"
|
#define NM_CONFIG_KEYFILE_KEY_IFNET_AUTO_REFRESH "auto_refresh"
|
||||||
#define NM_CONFIG_KEYFILE_KEY_IFNET_MANAGED "managed"
|
#define NM_CONFIG_KEYFILE_KEY_IFNET_MANAGED "managed"
|
||||||
@@ -69,6 +72,11 @@ G_BEGIN_DECLS
|
|||||||
#define NM_CONFIG_KEYFILE_KEYPREFIX_WAS ".was."
|
#define NM_CONFIG_KEYFILE_KEYPREFIX_WAS ".was."
|
||||||
#define NM_CONFIG_KEYFILE_KEYPREFIX_SET ".set."
|
#define NM_CONFIG_KEYFILE_KEYPREFIX_SET ".set."
|
||||||
|
|
||||||
|
#define NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS \
|
||||||
|
NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS
|
||||||
|
#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN \
|
||||||
|
NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN
|
||||||
|
|
||||||
typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions;
|
typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions;
|
||||||
|
|
||||||
struct _NMConfig {
|
struct _NMConfig {
|
||||||
@@ -139,6 +147,8 @@ GSList *nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *gr
|
|||||||
|
|
||||||
void _nm_config_sort_groups (char **groups, gsize ngroups);
|
void _nm_config_sort_groups (char **groups, gsize ngroups);
|
||||||
|
|
||||||
|
gboolean nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_CONFIG_H__ */
|
#endif /* __NETWORKMANAGER_CONFIG_H__ */
|
||||||
|
@@ -181,6 +181,7 @@ enum {
|
|||||||
PROP_ACTIVATING_CONNECTION,
|
PROP_ACTIVATING_CONNECTION,
|
||||||
PROP_DEVICES,
|
PROP_DEVICES,
|
||||||
PROP_METERED,
|
PROP_METERED,
|
||||||
|
PROP_GLOBAL_DNS_CONFIGURATION,
|
||||||
|
|
||||||
/* Not exported */
|
/* Not exported */
|
||||||
PROP_HOSTNAME,
|
PROP_HOSTNAME,
|
||||||
@@ -424,6 +425,9 @@ _config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeF
|
|||||||
NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data),
|
NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data),
|
||||||
NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data),
|
NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG))
|
||||||
|
g_object_notify (G_OBJECT (self), NM_MANAGER_GLOBAL_DNS_CONFIGURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@@ -4430,7 +4434,6 @@ typedef struct {
|
|||||||
char *audit_prop_value;
|
char *audit_prop_value;
|
||||||
GType interface_type;
|
GType interface_type;
|
||||||
const char *glib_propname;
|
const char *glib_propname;
|
||||||
gboolean set_enable;
|
|
||||||
} PropertyFilterData;
|
} PropertyFilterData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -4453,9 +4456,12 @@ prop_set_auth_done_cb (NMAuthChain *chain,
|
|||||||
PropertyFilterData *pfd = user_data;
|
PropertyFilterData *pfd = user_data;
|
||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pfd->self);
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pfd->self);
|
||||||
NMAuthCallResult result;
|
NMAuthCallResult result;
|
||||||
GDBusMessage *reply;
|
GDBusMessage *reply = NULL;
|
||||||
const char *error_message;
|
const char *error_message;
|
||||||
NMExportedObject *object;
|
NMExportedObject *object;
|
||||||
|
const NMGlobalDnsConfig *global_dns;
|
||||||
|
gs_unref_variant GVariant *value = NULL;
|
||||||
|
GVariant *args;
|
||||||
|
|
||||||
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
|
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
|
||||||
result = nm_auth_chain_get_result (chain, pfd->permission);
|
result = nm_auth_chain_get_result (chain, pfd->permission);
|
||||||
@@ -4485,9 +4491,29 @@ prop_set_auth_done_cb (NMAuthChain *chain,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args = g_dbus_message_get_body (pfd->message);
|
||||||
|
g_variant_get (args, "(&s&sv)", NULL, NULL, &value);
|
||||||
|
g_assert (pfd->glib_propname);
|
||||||
|
|
||||||
|
if (!strcmp (pfd->glib_propname, NM_MANAGER_GLOBAL_DNS_CONFIGURATION)) {
|
||||||
|
g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a{sv}")));
|
||||||
|
global_dns = nm_config_data_get_global_dns_config (nm_config_get_data (priv->config));
|
||||||
|
|
||||||
|
if (global_dns && !nm_global_dns_config_is_internal (global_dns)) {
|
||||||
|
reply = g_dbus_message_new_method_error (pfd->message,
|
||||||
|
NM_PERM_DENIED_ERROR,
|
||||||
|
(error_message = "Global DNS configuration already set via configuration file"));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* ... but set the property on the @object itself. It would be correct to set the property
|
/* ... but set the property on the @object itself. It would be correct to set the property
|
||||||
* on the skeleton interface, but as it is now, the result is the same. */
|
* on the skeleton interface, but as it is now, the result is the same. */
|
||||||
g_object_set (object, pfd->glib_propname, pfd->set_enable, NULL);
|
g_object_set (object, pfd->glib_propname, value, NULL);
|
||||||
|
} else {
|
||||||
|
g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN));
|
||||||
|
/* the same here */
|
||||||
|
g_object_set (object, pfd->glib_propname, g_variant_get_boolean (value), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
reply = g_dbus_message_new_method_reply (pfd->message);
|
reply = g_dbus_message_new_method_reply (pfd->message);
|
||||||
g_dbus_message_set_body (reply, g_variant_new_tuple (NULL, 0));
|
g_dbus_message_set_body (reply, g_variant_new_tuple (NULL, 0));
|
||||||
error_message = NULL;
|
error_message = NULL;
|
||||||
@@ -4552,14 +4578,15 @@ prop_filter (GDBusConnection *connection,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
gs_unref_object NMManager *self = NULL;
|
gs_unref_object NMManager *self = NULL;
|
||||||
GVariant *args, *value = NULL;
|
GVariant *args;
|
||||||
const char *propiface = NULL;
|
const char *propiface = NULL;
|
||||||
const char *propname = NULL;
|
const char *propname = NULL;
|
||||||
const char *glib_propname = NULL, *permission = NULL;
|
const char *glib_propname = NULL, *permission = NULL;
|
||||||
const char *audit_op = NULL;
|
const char *audit_op = NULL;
|
||||||
gboolean set_enable;
|
|
||||||
GType interface_type = G_TYPE_INVALID;
|
GType interface_type = G_TYPE_INVALID;
|
||||||
PropertyFilterData *pfd;
|
PropertyFilterData *pfd;
|
||||||
|
const GVariantType *expected_type = G_VARIANT_TYPE_BOOLEAN;
|
||||||
|
gs_unref_variant GVariant *value = NULL;
|
||||||
|
|
||||||
self = g_weak_ref_get (user_data);
|
self = g_weak_ref_get (user_data);
|
||||||
if (!self)
|
if (!self)
|
||||||
@@ -4576,17 +4603,10 @@ prop_filter (GDBusConnection *connection,
|
|||||||
|| g_strcmp0 (g_dbus_message_get_member (message), "Set") != 0)
|
|| g_strcmp0 (g_dbus_message_get_member (message), "Set") != 0)
|
||||||
return message;
|
return message;
|
||||||
|
|
||||||
/* Only filter calls with correct arguments (all filtered properties are boolean) */
|
|
||||||
args = g_dbus_message_get_body (message);
|
args = g_dbus_message_get_body (message);
|
||||||
if (!g_variant_is_of_type (args, G_VARIANT_TYPE ("(ssv)")))
|
if (!g_variant_is_of_type (args, G_VARIANT_TYPE ("(ssv)")))
|
||||||
return message;
|
return message;
|
||||||
g_variant_get (args, "(&s&sv)", &propiface, &propname, &value);
|
g_variant_get (args, "(&s&sv)", &propiface, &propname, &value);
|
||||||
if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) {
|
|
||||||
g_variant_unref (value);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
set_enable = g_variant_get_boolean (value);
|
|
||||||
g_variant_unref (value);
|
|
||||||
|
|
||||||
/* Only filter calls to filtered properties, on existing objects */
|
/* Only filter calls to filtered properties, on existing objects */
|
||||||
if (!strcmp (propiface, NM_DBUS_INTERFACE)) {
|
if (!strcmp (propiface, NM_DBUS_INTERFACE)) {
|
||||||
@@ -4602,6 +4622,11 @@ prop_filter (GDBusConnection *connection,
|
|||||||
glib_propname = NM_MANAGER_WIMAX_ENABLED;
|
glib_propname = NM_MANAGER_WIMAX_ENABLED;
|
||||||
permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
|
permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
|
||||||
audit_op = NM_AUDIT_OP_RADIO_CONTROL;
|
audit_op = NM_AUDIT_OP_RADIO_CONTROL;
|
||||||
|
} else if (!strcmp (propname, "GlobalDnsConfiguration")) {
|
||||||
|
glib_propname = NM_MANAGER_GLOBAL_DNS_CONFIGURATION;
|
||||||
|
permission = NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
|
||||||
|
audit_op = NM_AUDIT_OP_NET_CONTROL;
|
||||||
|
expected_type = G_VARIANT_TYPE ("a{sv}");
|
||||||
} else
|
} else
|
||||||
return message;
|
return message;
|
||||||
interface_type = NMDBUS_TYPE_MANAGER_SKELETON;
|
interface_type = NMDBUS_TYPE_MANAGER_SKELETON;
|
||||||
@@ -4620,6 +4645,9 @@ prop_filter (GDBusConnection *connection,
|
|||||||
} else
|
} else
|
||||||
return message;
|
return message;
|
||||||
|
|
||||||
|
if (!g_variant_is_of_type (value, expected_type))
|
||||||
|
return message;
|
||||||
|
|
||||||
/* This filter function is called from a gdbus worker thread which we can't
|
/* This filter function is called from a gdbus worker thread which we can't
|
||||||
* make other D-Bus calls from. In particular, we cannot call
|
* make other D-Bus calls from. In particular, we cannot call
|
||||||
* org.freedesktop.DBus.GetConnectionUnixUser to find the remote UID.
|
* org.freedesktop.DBus.GetConnectionUnixUser to find the remote UID.
|
||||||
@@ -4632,9 +4660,13 @@ prop_filter (GDBusConnection *connection,
|
|||||||
pfd->permission = permission;
|
pfd->permission = permission;
|
||||||
pfd->interface_type = interface_type;
|
pfd->interface_type = interface_type;
|
||||||
pfd->glib_propname = glib_propname;
|
pfd->glib_propname = glib_propname;
|
||||||
pfd->set_enable = set_enable;
|
|
||||||
pfd->audit_op = audit_op;
|
pfd->audit_op = audit_op;
|
||||||
pfd->audit_prop_value = g_strdup_printf ("%s:%d", pfd->glib_propname, pfd->set_enable);
|
if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) {
|
||||||
|
pfd->audit_prop_value = g_strdup_printf ("%s:%d", pfd->glib_propname,
|
||||||
|
g_variant_get_boolean (value));
|
||||||
|
} else
|
||||||
|
pfd->audit_prop_value = g_strdup (pfd->glib_propname);
|
||||||
|
|
||||||
g_idle_add (do_set_property_check, pfd);
|
g_idle_add (do_set_property_check, pfd);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -5028,6 +5060,8 @@ get_property (GObject *object, guint prop_id,
|
|||||||
{
|
{
|
||||||
NMManager *self = NM_MANAGER (object);
|
NMManager *self = NM_MANAGER (object);
|
||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||||
|
NMConfigData *config_data;
|
||||||
|
const NMGlobalDnsConfig *dns_config;
|
||||||
const char *type;
|
const char *type;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
@@ -5097,6 +5131,11 @@ get_property (GObject *object, guint prop_id,
|
|||||||
case PROP_METERED:
|
case PROP_METERED:
|
||||||
g_value_set_uint (value, priv->metered);
|
g_value_set_uint (value, priv->metered);
|
||||||
break;
|
break;
|
||||||
|
case PROP_GLOBAL_DNS_CONFIGURATION:
|
||||||
|
config_data = nm_config_get_data (priv->config);
|
||||||
|
dns_config = nm_config_data_get_global_dns_config (config_data);
|
||||||
|
nm_global_dns_config_to_dbus (dns_config, value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -5109,6 +5148,8 @@ set_property (GObject *object, guint prop_id,
|
|||||||
{
|
{
|
||||||
NMManager *self = NM_MANAGER (object);
|
NMManager *self = NM_MANAGER (object);
|
||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||||
|
NMGlobalDnsConfig *dns_config;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_NETWORKING_ENABLED:
|
case PROP_NETWORKING_ENABLED:
|
||||||
@@ -5128,6 +5169,18 @@ set_property (GObject *object, guint prop_id,
|
|||||||
case PROP_WIMAX_ENABLED:
|
case PROP_WIMAX_ENABLED:
|
||||||
/* WIMAX is depreacted. This does nothing. */
|
/* WIMAX is depreacted. This does nothing. */
|
||||||
break;
|
break;
|
||||||
|
case PROP_GLOBAL_DNS_CONFIGURATION:
|
||||||
|
dns_config = nm_global_dns_config_from_dbus (value, &error);
|
||||||
|
if (!error)
|
||||||
|
nm_config_set_global_dns (priv->config, dns_config, &error);
|
||||||
|
|
||||||
|
nm_global_dns_config_free (dns_config);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
nm_log_dbg (LOGD_CORE, "set global DNS failed with error: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -5395,6 +5448,21 @@ nm_manager_class_init (NMManagerClass *manager_class)
|
|||||||
G_PARAM_READABLE |
|
G_PARAM_READABLE |
|
||||||
G_PARAM_STATIC_STRINGS));
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NMManager:global-dns-configuration:
|
||||||
|
*
|
||||||
|
* The global DNS configuration.
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
**/
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class, PROP_GLOBAL_DNS_CONFIGURATION,
|
||||||
|
g_param_spec_variant (NM_MANAGER_GLOBAL_DNS_CONFIGURATION, "", "",
|
||||||
|
G_VARIANT_TYPE ("a{sv}"),
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
/* signals */
|
/* signals */
|
||||||
signals[DEVICE_ADDED] =
|
signals[DEVICE_ADDED] =
|
||||||
g_signal_new ("device-added",
|
g_signal_new ("device-added",
|
||||||
|
@@ -49,6 +49,7 @@
|
|||||||
#define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection"
|
#define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection"
|
||||||
#define NM_MANAGER_DEVICES "devices"
|
#define NM_MANAGER_DEVICES "devices"
|
||||||
#define NM_MANAGER_METERED "metered"
|
#define NM_MANAGER_METERED "metered"
|
||||||
|
#define NM_MANAGER_GLOBAL_DNS_CONFIGURATION "global-dns-configuration"
|
||||||
|
|
||||||
/* Not exported */
|
/* Not exported */
|
||||||
#define NM_MANAGER_HOSTNAME "hostname"
|
#define NM_MANAGER_HOSTNAME "hostname"
|
||||||
|
@@ -30,6 +30,8 @@ TESTS = test-config
|
|||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
NetworkManager.conf \
|
NetworkManager.conf \
|
||||||
bad.conf \
|
bad.conf \
|
||||||
|
global-dns-disabled.conf \
|
||||||
|
global-dns-invalid.conf \
|
||||||
conf.d/00-overrides.conf \
|
conf.d/00-overrides.conf \
|
||||||
conf.d/10-more.conf \
|
conf.d/10-more.conf \
|
||||||
conf.d/90-last.conf
|
conf.d/90-last.conf
|
||||||
|
@@ -81,3 +81,19 @@ ord.key07=A-0.3.07
|
|||||||
ord.key08=A-0.3.08
|
ord.key08=A-0.3.08
|
||||||
ord.key09=A-0.3.09
|
ord.key09=A-0.3.09
|
||||||
ord.ovw01=A-0.3.ovw01
|
ord.ovw01=A-0.3.ovw01
|
||||||
|
|
||||||
|
[global-dns]
|
||||||
|
enable=yes
|
||||||
|
searches=foo.com,bar.org
|
||||||
|
options=debug,edns0
|
||||||
|
|
||||||
|
[global-dns-domain-*]
|
||||||
|
servers=1.1.1.1,bad,1::128
|
||||||
|
options=opt1,opt2
|
||||||
|
|
||||||
|
[global-dns-domain-example.com]
|
||||||
|
servers=2.2.2.2
|
||||||
|
|
||||||
|
# Invalid section: 'servers' key is missing
|
||||||
|
[global-dns-domain-test.com]
|
||||||
|
options=opt3
|
||||||
|
8
src/tests/config/global-dns-disabled.conf
Normal file
8
src/tests/config/global-dns-disabled.conf
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[global-dns]
|
||||||
|
enable=no
|
||||||
|
searches=foo.com
|
||||||
|
options=timeout:5
|
||||||
|
|
||||||
|
[global-dns-domain-*]
|
||||||
|
servers=1.2.3.4
|
||||||
|
options=myoption
|
10
src/tests/config/global-dns-invalid.conf
Normal file
10
src/tests/config/global-dns-invalid.conf
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Invalid configuration, since there isn't a default domain section
|
||||||
|
|
||||||
|
[global-dns]
|
||||||
|
enable=yes
|
||||||
|
searches=foo.com
|
||||||
|
options=timeout:5
|
||||||
|
|
||||||
|
[global-dns-domain-test.com]
|
||||||
|
servers=1.2.3.4
|
||||||
|
options=myoption
|
@@ -243,6 +243,83 @@ test_config_override (void)
|
|||||||
g_object_unref (config);
|
g_object_unref (config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_config_global_dns (void)
|
||||||
|
{
|
||||||
|
NMConfig *config;
|
||||||
|
const NMGlobalDnsConfig *dns;
|
||||||
|
NMGlobalDnsDomain *domain;
|
||||||
|
const char *const *strv;
|
||||||
|
|
||||||
|
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", NULL,
|
||||||
|
"/no/such/dir", "", NULL);
|
||||||
|
|
||||||
|
dns = nm_config_data_get_global_dns_config (nm_config_get_data_orig (config));
|
||||||
|
g_assert (dns);
|
||||||
|
|
||||||
|
strv = nm_global_dns_config_get_searches (dns);
|
||||||
|
g_assert (strv);
|
||||||
|
g_assert_cmpuint (g_strv_length ((char **) strv), ==, 2);
|
||||||
|
g_assert_cmpstr (strv[0], ==, "foo.com");
|
||||||
|
g_assert_cmpstr (strv[1], ==, "bar.org");
|
||||||
|
|
||||||
|
strv = nm_global_dns_config_get_options (dns);
|
||||||
|
g_assert (strv);
|
||||||
|
g_assert_cmpuint (g_strv_length ((char **) strv), ==, 2);
|
||||||
|
g_assert_cmpstr (strv[0], ==, "debug");
|
||||||
|
g_assert_cmpstr (strv[1], ==, "edns0");
|
||||||
|
|
||||||
|
g_assert_cmpuint (nm_global_dns_config_get_num_domains (dns), ==, 2);
|
||||||
|
|
||||||
|
/* Default domain */
|
||||||
|
domain = nm_global_dns_config_lookup_domain (dns, "*");
|
||||||
|
g_assert (domain);
|
||||||
|
|
||||||
|
strv = nm_global_dns_domain_get_servers (domain);
|
||||||
|
g_assert (strv);
|
||||||
|
g_assert_cmpuint (g_strv_length ((char **) strv), ==, 2);
|
||||||
|
g_assert_cmpstr (strv[0], ==, "1.1.1.1");
|
||||||
|
g_assert_cmpstr (strv[1], ==, "1::128");
|
||||||
|
|
||||||
|
strv = nm_global_dns_domain_get_options (domain);
|
||||||
|
g_assert (strv);
|
||||||
|
g_assert_cmpuint (g_strv_length ((char **) strv), ==, 2);
|
||||||
|
g_assert_cmpstr (strv[0], ==, "opt1");
|
||||||
|
g_assert_cmpstr (strv[1], ==, "opt2");
|
||||||
|
|
||||||
|
/* 'example.com' domain */
|
||||||
|
domain = nm_global_dns_config_lookup_domain (dns, "example.com");
|
||||||
|
g_assert (domain);
|
||||||
|
|
||||||
|
strv = nm_global_dns_domain_get_servers (domain);
|
||||||
|
g_assert (strv);
|
||||||
|
g_assert_cmpuint (g_strv_length ((char **) strv), ==, 1);
|
||||||
|
g_assert_cmpstr (strv[0], ==, "2.2.2.2");
|
||||||
|
|
||||||
|
strv = nm_global_dns_domain_get_options (domain);
|
||||||
|
g_assert (!strv || g_strv_length ((char **) strv) == 0);
|
||||||
|
|
||||||
|
/* Non-existent domain 'test.com' */
|
||||||
|
domain = nm_global_dns_config_lookup_domain (dns, "test.com");
|
||||||
|
g_assert (!domain);
|
||||||
|
|
||||||
|
g_object_unref (config);
|
||||||
|
|
||||||
|
/* Check that a file without "enable=yes" gives a NULL configuration */
|
||||||
|
config = setup_config (NULL, SRCDIR "/global-dns-disabled.conf", "", NULL,
|
||||||
|
"/no/such/dir", "", NULL);
|
||||||
|
dns = nm_config_data_get_global_dns_config (nm_config_get_data_orig (config));
|
||||||
|
g_assert (!dns);
|
||||||
|
g_object_unref (config);
|
||||||
|
|
||||||
|
/* Check that a file without a default domain section gives a NULL configuration */
|
||||||
|
config = setup_config (NULL, SRCDIR "/global-dns-invalid.conf", "", NULL,
|
||||||
|
"/no/such/dir", "", NULL);
|
||||||
|
dns = nm_config_data_get_global_dns_config (nm_config_get_data_orig (config));
|
||||||
|
g_assert (!dns);
|
||||||
|
g_object_unref (config);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_config_no_auto_default (void)
|
test_config_no_auto_default (void)
|
||||||
{
|
{
|
||||||
@@ -852,6 +929,7 @@ main (int argc, char **argv)
|
|||||||
g_test_add_func ("/config/confdir-parse-error", test_config_confdir_parse_error);
|
g_test_add_func ("/config/confdir-parse-error", test_config_confdir_parse_error);
|
||||||
|
|
||||||
g_test_add_func ("/config/set-values", test_config_set_values);
|
g_test_add_func ("/config/set-values", test_config_set_values);
|
||||||
|
g_test_add_func ("/config/global-dns", test_config_global_dns);
|
||||||
|
|
||||||
g_test_add_func ("/config/signal", test_config_signal);
|
g_test_add_func ("/config/signal", test_config_signal);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user