summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-02-19 16:47:36 +0100
committerThomas Haller <thaller@redhat.com>2020-02-19 17:15:26 +0100
commit8775c25c331893b8b2f2540f9a6824363680cb11 (patch)
tree7a00cf9f2b1ae91a09f10f73d7f0ad645483af5d
parentae1008b239aef5cfb7a33816c15fe9feffc80a38 (diff)
downloadNetworkManager-8775c25c331893b8b2f2540f9a6824363680cb11.tar.gz
libnm: verify bond option in defined order
verify() should validate options in a deterministic order, so that the same profile (with same libnm version) gives the same failure reason every time. Hence, visit the options in sorted order, like we do for nm_setting_bond_get_option().
-rw-r--r--libnm-core/nm-setting-bond.c61
1 files changed, 38 insertions, 23 deletions
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
index 4a9f968d23..df8a8a4985 100644
--- a/libnm-core/nm-setting-bond.c
+++ b/libnm-core/nm-setting-bond.c
@@ -210,6 +210,13 @@ _get_option_sort (gconstpointer p_a, gconstpointer p_b, gpointer _unused)
return 0;
}
+static void
+_ensure_options_idx_cache (NMSettingBondPrivate *priv)
+{
+ if (!G_UNLIKELY (priv->options_idx_cache))
+ priv->options_idx_cache = nm_utils_named_values_from_str_dict_with_sort (priv->options, NULL, _get_option_sort, NULL);
+}
+
/**
* nm_setting_bond_get_option:
* @setting: the #NMSettingBond
@@ -248,8 +255,7 @@ nm_setting_bond_get_option (NMSettingBond *setting,
if (idx >= len)
return FALSE;
- if (!G_UNLIKELY (priv->options_idx_cache))
- priv->options_idx_cache = nm_utils_named_values_from_str_dict_with_sort (priv->options, NULL, _get_option_sort, NULL);
+ _ensure_options_idx_cache (priv);
NM_SET_OUT (out_name, priv->options_idx_cache[idx].name);
NM_SET_OUT (out_value, priv->options_idx_cache[idx].value_str);
@@ -596,26 +602,37 @@ static gboolean
verify (NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
- GHashTableIter iter;
- const char *key, *value;
- int mode, miimon = 0, arp_interval = 0;
- int num_grat_arp = -1, num_unsol_na = -1;
- const char *mode_orig, *mode_new;
+ int mode;
+ int miimon = 0;
+ int arp_interval = 0;
+ int num_grat_arp = -1;
+ int num_unsol_na = -1;
+ const char *mode_orig;
+ const char *mode_new;
const char *arp_ip_target = NULL;
const char *lacp_rate;
const char *primary;
NMBondMode bond_mode;
+ guint i;
+ const NMUtilsNamedValue *n;
+ const char *value;
- g_hash_table_iter_init (&iter, priv->options);
- while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
- if (!value[0] || !nm_setting_bond_validate_option (key, value)) {
- g_set_error (error,
- NM_CONNECTION_ERROR,
- NM_CONNECTION_ERROR_INVALID_PROPERTY,
- _("invalid option '%s' or its value '%s'"),
- key, value);
- g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
- return FALSE;
+ _ensure_options_idx_cache (priv);
+
+ if (priv->options_idx_cache) {
+ for (i = 0; priv->options_idx_cache[i].name; i++) {
+ n = &priv->options_idx_cache[i];
+
+ if ( !n->value_str
+ || !nm_setting_bond_validate_option (n->name, n->value_str)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("invalid option '%s' or its value '%s'"),
+ n->name, n->value_str);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
}
}
@@ -841,16 +858,14 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
/* normalize unsupported options for the current mode */
bond_mode = _nm_setting_bond_mode_from_string (mode_new);
- g_hash_table_iter_init (&iter, priv->options);
- while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) {
- if (nm_streq (key, "mode"))
- continue;
- if (!_nm_setting_bond_option_supported (key, bond_mode)) {
+ for (i = 0; priv->options_idx_cache[i].name; i++) {
+ n = &priv->options_idx_cache[i];
+ if (!_nm_setting_bond_option_supported (n->name, bond_mode)) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("'%s' option is not valid with mode '%s'"),
- key, mode_new);
+ n->name, mode_new);
g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
return NM_SETTING_VERIFY_NORMALIZABLE;
}