config: cleanup fields in NMGlobalDnsConfig

- consistently set options, searches, domains fields to %NULL,
  if there are no values.

- in nm_global_dns_config_update_checksum(), ensure that we uniquely
  hash values. E.g. a config with "searches[a], options=[b]" should
  hash differently from "searches=[ab], options=[]".

- in nm_global_dns_config_to_dbus(), reuse the sorted domain list.
  We already have it, and it guarantees a consistent ordering of
  fields.

- in global_dns_domain_from_dbus(), fix memleaks if D-Bus strdict
  contains duplicate entries.
This commit is contained in:
Thomas Haller
2018-03-26 08:18:51 +02:00
parent 0f1dc3bca3
commit cd48bc74b6
3 changed files with 135 additions and 87 deletions

View File

@@ -970,30 +970,36 @@ merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf)
const char *const *searches; const char *const *searches;
const char *const *options; const char *const *options;
const char *const *servers; const char *const *servers;
gint i; guint i;
if (!global_conf) if (!global_conf)
return FALSE; return FALSE;
searches = nm_global_dns_config_get_searches (global_conf); searches = nm_global_dns_config_get_searches (global_conf);
options = nm_global_dns_config_get_options (global_conf); if (searches) {
for (i = 0; searches[i]; i++) {
for (i = 0; searches && searches[i]; i++) {
if (domain_is_routing (searches[i])) if (domain_is_routing (searches[i]))
continue; continue;
if (!domain_is_valid (searches[i], FALSE)) if (!domain_is_valid (searches[i], FALSE))
continue; continue;
add_string_item (rc->searches, searches[i], TRUE); add_string_item (rc->searches, searches[i], TRUE);
} }
}
for (i = 0; options && options[i]; i++) options = nm_global_dns_config_get_options (global_conf);
if (options) {
for (i = 0; options[i]; i++)
add_string_item (rc->options, options[i], TRUE); add_string_item (rc->options, options[i], TRUE);
}
default_domain = nm_global_dns_config_lookup_domain (global_conf, "*"); default_domain = nm_global_dns_config_lookup_domain (global_conf, "*");
g_assert (default_domain); nm_assert (default_domain);
servers = nm_global_dns_domain_get_servers (default_domain); servers = nm_global_dns_domain_get_servers (default_domain);
for (i = 0; servers && servers[i]; i++) if (servers) {
for (i = 0; servers[i]; i++)
add_string_item (rc->nameservers, servers[i], TRUE); add_string_item (rc->nameservers, servers[i], TRUE);
}
return TRUE; return TRUE;
} }

View File

@@ -54,7 +54,7 @@ struct _NMGlobalDnsConfig {
char **searches; char **searches;
char **options; char **options;
GHashTable *domains; GHashTable *domains;
char **domain_list; const char **domain_list;
gboolean internal; gboolean internal;
}; };
@@ -725,9 +725,8 @@ guint
nm_global_dns_config_get_num_domains (const NMGlobalDnsConfig *dns_config) nm_global_dns_config_get_num_domains (const NMGlobalDnsConfig *dns_config)
{ {
g_return_val_if_fail (dns_config, 0); g_return_val_if_fail (dns_config, 0);
g_return_val_if_fail (dns_config->domains, 0);
return g_hash_table_size (dns_config->domains); return dns_config->domains ? g_hash_table_size (dns_config->domains) : 0;
} }
NMGlobalDnsDomain * NMGlobalDnsDomain *
@@ -737,22 +736,22 @@ nm_global_dns_config_get_domain (const NMGlobalDnsConfig *dns_config, guint i)
g_return_val_if_fail (dns_config, NULL); g_return_val_if_fail (dns_config, NULL);
g_return_val_if_fail (dns_config->domains, NULL); g_return_val_if_fail (dns_config->domains, NULL);
g_return_val_if_fail (dns_config->domain_list, NULL); g_return_val_if_fail (i < g_hash_table_size (dns_config->domains), NULL);
g_return_val_if_fail (i < g_strv_length (dns_config->domain_list), NULL);
nm_assert (NM_PTRARRAY_LEN (dns_config->domain_list) == g_hash_table_size (dns_config->domains));
domain = g_hash_table_lookup (dns_config->domains, dns_config->domain_list[i]); domain = g_hash_table_lookup (dns_config->domains, dns_config->domain_list[i]);
g_return_val_if_fail (domain, NULL);
nm_assert (domain);
return domain; return domain;
} }
NMGlobalDnsDomain *nm_global_dns_config_lookup_domain (const NMGlobalDnsConfig *dns_config, const char *name) NMGlobalDnsDomain *nm_global_dns_config_lookup_domain (const NMGlobalDnsConfig *dns_config, const char *name)
{ {
g_return_val_if_fail (dns_config, NULL); g_return_val_if_fail (dns_config, NULL);
g_return_val_if_fail (dns_config->domains, NULL);
g_return_val_if_fail (name, NULL); g_return_val_if_fail (name, NULL);
return g_hash_table_lookup (dns_config->domains, name); return dns_config->domains ? g_hash_table_lookup (dns_config->domains, name) : NULL;
} }
const char * const char *
@@ -775,6 +774,7 @@ const char *const *
nm_global_dns_domain_get_options (const NMGlobalDnsDomain *domain) nm_global_dns_domain_get_options (const NMGlobalDnsDomain *domain)
{ {
g_return_val_if_fail (domain, NULL); g_return_val_if_fail (domain, NULL);
return (const char *const *) domain->options; return (const char *const *) domain->options;
} }
@@ -788,42 +788,59 @@ gboolean
nm_global_dns_config_is_empty (const NMGlobalDnsConfig *dns_config) nm_global_dns_config_is_empty (const NMGlobalDnsConfig *dns_config)
{ {
g_return_val_if_fail (dns_config, TRUE); g_return_val_if_fail (dns_config, TRUE);
g_return_val_if_fail (dns_config->domains, TRUE);
return (!dns_config->searches || g_strv_length (dns_config->searches) == 0) return !dns_config->searches
&& (!dns_config->options || g_strv_length (dns_config->options) == 0) && !dns_config->options
&& g_hash_table_size (dns_config->domains) == 0; && !dns_config->domain_list;
} }
void void
nm_global_dns_config_update_checksum (const NMGlobalDnsConfig *dns_config, GChecksum *sum) nm_global_dns_config_update_checksum (const NMGlobalDnsConfig *dns_config, GChecksum *sum)
{ {
NMGlobalDnsDomain *domain; NMGlobalDnsDomain *domain;
GList *keys, *key;
guint i; guint i;
guint8 v8;
g_return_if_fail (dns_config); g_return_if_fail (dns_config);
g_return_if_fail (dns_config->domains);
g_return_if_fail (sum); g_return_if_fail (sum);
for (i = 0; dns_config->searches && dns_config->searches[i]; i++) v8 = NM_HASH_COMBINE_BOOLS (guint8,
g_checksum_update (sum, (guchar *) dns_config->searches[i], strlen (dns_config->searches[i])); !dns_config->searches,
for (i = 0; dns_config->options && dns_config->options[i]; i++) !dns_config->options,
g_checksum_update (sum, (guchar *) dns_config->options[i], strlen (dns_config->options[i])); !dns_config->domain_list);
g_checksum_update (sum, (guchar *) &v8, 1);
keys = g_list_sort (g_hash_table_get_keys (dns_config->domains), (GCompareFunc) strcmp); if (dns_config->searches) {
for (key = keys; key; key = g_list_next (key)) { for (i = 0; dns_config->searches[i]; i++)
g_checksum_update (sum, (guchar *) dns_config->searches[i], strlen (dns_config->searches[i]) + 1);
domain = g_hash_table_lookup (dns_config->domains, key->data); }
g_assert (domain != NULL); if (dns_config->options) {
g_checksum_update (sum, (guchar *) domain->name, strlen (domain->name)); for (i = 0; dns_config->options[i]; i++)
g_checksum_update (sum, (guchar *) dns_config->options[i], strlen (dns_config->options[i]) + 1);
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++) if (dns_config->domain_list) {
g_checksum_update (sum, (guchar *) domain->options[i], strlen (domain->options[i])); for (i = 0; dns_config->domain_list[i]; i++) {
domain = g_hash_table_lookup (dns_config->domains, dns_config->domain_list[i]);
nm_assert (domain);
v8 = NM_HASH_COMBINE_BOOLS (guint8,
!domain->servers,
!domain->options);
g_checksum_update (sum, (guchar *) &v8, 1);
g_checksum_update (sum, (guchar *) domain->name, strlen (domain->name) + 1);
if (domain->servers) {
for (i = 0; domain->servers && domain->servers[i]; i++)
g_checksum_update (sum, (guchar *) domain->servers[i], strlen (domain->servers[i]) + 1);
}
if (domain->options) {
for (i = 0; domain->options[i]; i++)
g_checksum_update (sum, (guchar *) domain->options[i], strlen (domain->options[i]) + 1);
}
}
} }
g_list_free (keys);
} }
static void static void
@@ -844,6 +861,7 @@ nm_global_dns_config_free (NMGlobalDnsConfig *dns_config)
g_strfreev (dns_config->searches); g_strfreev (dns_config->searches);
g_strfreev (dns_config->options); g_strfreev (dns_config->options);
g_free (dns_config->domain_list); g_free (dns_config->domain_list);
if (dns_config->domains)
g_hash_table_unref (dns_config->domains); g_hash_table_unref (dns_config->domains);
g_free (dns_config); g_free (dns_config);
} }
@@ -858,12 +876,16 @@ nm_config_data_get_global_dns_config (const NMConfigData *self)
} }
static void static void
global_dns_config_update_domain_list (NMGlobalDnsConfig *dns_config) global_dns_config_seal_domains (NMGlobalDnsConfig *dns_config)
{ {
guint length; nm_assert (dns_config);
nm_assert (dns_config->domains);
nm_assert (!dns_config->domain_list);
g_free (dns_config->domain_list); if (g_hash_table_size (dns_config->domains) == 0)
dns_config->domain_list = (char **) g_hash_table_get_keys_as_array (dns_config->domains, &length); nm_clear_pointer (&dns_config->domains, g_hash_table_unref);
else
dns_config->domain_list = nm_utils_strdict_get_keys (dns_config->domains, TRUE, NULL);
} }
static NMGlobalDnsConfig * static NMGlobalDnsConfig *
@@ -892,8 +914,13 @@ load_global_dns (GKeyFile *keyfile, gboolean internal)
g_free, (GDestroyNotify) global_dns_domain_free); g_free, (GDestroyNotify) global_dns_domain_free);
strv = g_key_file_get_string_list (keyfile, group, "searches", NULL, NULL); strv = g_key_file_get_string_list (keyfile, group, "searches", NULL, NULL);
if (strv) if (strv) {
dns_config->searches = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE); _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
if (!strv[0])
g_free (strv);
else
dns_config->searches = strv;
}
strv = g_key_file_get_string_list (keyfile, group, "options", NULL, NULL); strv = g_key_file_get_string_list (keyfile, group, "options", NULL, NULL);
if (strv) { if (strv) {
@@ -904,9 +931,13 @@ load_global_dns (GKeyFile *keyfile, gboolean internal)
else else
g_free (strv[i]); g_free (strv[i]);
} }
if (j == 0)
g_free (strv);
else {
strv[j] = NULL; strv[j] = NULL;
dns_config->options = strv; dns_config->options = strv;
} }
}
groups = g_key_file_get_groups (keyfile, NULL); groups = g_key_file_get_groups (keyfile, NULL);
for (g = 0; groups[g]; g++) { for (g = 0; groups[g]; g++) {
@@ -928,20 +959,23 @@ load_global_dns (GKeyFile *keyfile, gboolean internal)
else else
g_free (strv[i]); g_free (strv[i]);
} }
if (j) { if (j == 0)
g_free (strv);
else {
strv[j] = NULL; strv[j] = NULL;
servers = strv; servers = strv;
} }
else
g_free (strv);
} }
if (!servers) if (!servers)
continue; continue;
strv = g_key_file_get_string_list (keyfile, groups[g], "options", NULL, NULL); strv = g_key_file_get_string_list (keyfile, groups[g], "options", NULL, NULL);
if (strv) if (strv) {
options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE); options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
if (!options[0])
nm_clear_g_free (&options);
}
name = strdup (&groups[g][domain_prefix_len]); name = strdup (&groups[g][domain_prefix_len]);
domain = g_malloc0 (sizeof (NMGlobalDnsDomain)); domain = g_malloc0 (sizeof (NMGlobalDnsDomain));
@@ -963,7 +997,7 @@ load_global_dns (GKeyFile *keyfile, gboolean internal)
} }
dns_config->internal = internal; dns_config->internal = internal;
global_dns_config_update_domain_list (dns_config); global_dns_config_seal_domains (dns_config);
return dns_config; return dns_config;
} }
@@ -972,8 +1006,7 @@ void
nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns_config, GValue *value) nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns_config, GValue *value)
{ {
GVariantBuilder conf_builder, domains_builder, domain_builder; GVariantBuilder conf_builder, domains_builder, domain_builder;
NMGlobalDnsDomain *domain; guint i;
GHashTableIter iter;
g_variant_builder_init (&conf_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&conf_builder, G_VARIANT_TYPE ("a{sv}"));
if (!dns_config) if (!dns_config)
@@ -990,9 +1023,11 @@ nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns_config, GValue *value
} }
g_variant_builder_init (&domains_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&domains_builder, G_VARIANT_TYPE ("a{sv}"));
if (dns_config->domain_list) {
for (i = 0; dns_config->domain_list[i]; i++) {
NMGlobalDnsDomain *domain;
g_hash_table_iter_init (&iter, dns_config->domains); domain = g_hash_table_lookup (dns_config->domains, dns_config->domain_list[i]);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &domain)) {
g_variant_builder_init (&domain_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&domain_builder, G_VARIANT_TYPE ("a{sv}"));
@@ -1008,9 +1043,10 @@ nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns_config, GValue *value
g_variant_builder_add (&domains_builder, "{sv}", domain->name, g_variant_builder_add (&domains_builder, "{sv}", domain->name,
g_variant_builder_end (&domain_builder)); g_variant_builder_end (&domain_builder));
} }
}
g_variant_builder_add (&conf_builder, "{sv}", "domains", g_variant_builder_add (&conf_builder, "{sv}", "domains",
g_variant_builder_end (&domains_builder)); g_variant_builder_end (&domains_builder));
out: out:
g_value_take_variant (value, g_variant_builder_end (&conf_builder)); g_value_take_variant (value, g_variant_builder_end (&conf_builder));
} }
@@ -1044,15 +1080,20 @@ global_dns_domain_from_dbus (char *name, GVariant *variant)
else else
g_free (strv[i]); g_free (strv[i]);
} }
if (j) { if (j == 0)
strv[j] = NULL;
domain->servers = strv;
} else
g_free (strv); g_free (strv);
else {
strv[j] = NULL;
g_strfreev (domain->servers);
domain->servers = strv;
}
} else if ( !g_strcmp0 (key, "options") } else if ( !g_strcmp0 (key, "options")
&& g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) { && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
strv = g_variant_dup_strv (val, NULL); strv = g_variant_dup_strv (val, NULL);
g_strfreev (domain->options);
domain->options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE); domain->options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
if (!domain->options[0])
nm_clear_g_free (&domain->options);
} }
g_variant_unref (val); g_variant_unref (val);
@@ -1111,11 +1152,12 @@ nm_global_dns_config_from_dbus (const GValue *value, GError **error)
else else
g_free (strv[i]); g_free (strv[i]);
} }
if (j == 0)
if (strv) g_free (strv);
else {
strv[j] = NULL; strv[j] = NULL;
dns_config->options = strv; dns_config->options = strv;
}
} else if ( !g_strcmp0 (key, "domains") } else if ( !g_strcmp0 (key, "domains")
&& g_variant_is_of_type (val, G_VARIANT_TYPE ("a{sv}"))) { && g_variant_is_of_type (val, G_VARIANT_TYPE ("a{sv}"))) {
NMGlobalDnsDomain *domain; NMGlobalDnsDomain *domain;
@@ -1145,7 +1187,7 @@ nm_global_dns_config_from_dbus (const GValue *value, GError **error)
return NULL; return NULL;
} }
global_dns_config_update_domain_list (dns_config); global_dns_config_seal_domains (dns_config);
return dns_config; return dns_config;
} }