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().
This commit is contained in:
@@ -210,6 +210,13 @@ _get_option_sort (gconstpointer p_a, gconstpointer p_b, gpointer _unused)
|
|||||||
return 0;
|
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:
|
* nm_setting_bond_get_option:
|
||||||
* @setting: the #NMSettingBond
|
* @setting: the #NMSettingBond
|
||||||
@@ -248,8 +255,7 @@ nm_setting_bond_get_option (NMSettingBond *setting,
|
|||||||
if (idx >= len)
|
if (idx >= len)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!G_UNLIKELY (priv->options_idx_cache))
|
_ensure_options_idx_cache (priv);
|
||||||
priv->options_idx_cache = nm_utils_named_values_from_str_dict_with_sort (priv->options, NULL, _get_option_sort, NULL);
|
|
||||||
|
|
||||||
NM_SET_OUT (out_name, priv->options_idx_cache[idx].name);
|
NM_SET_OUT (out_name, priv->options_idx_cache[idx].name);
|
||||||
NM_SET_OUT (out_value, priv->options_idx_cache[idx].value_str);
|
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)
|
verify (NMSetting *setting, NMConnection *connection, GError **error)
|
||||||
{
|
{
|
||||||
NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
|
NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
|
||||||
GHashTableIter iter;
|
int mode;
|
||||||
const char *key, *value;
|
int miimon = 0;
|
||||||
int mode, miimon = 0, arp_interval = 0;
|
int arp_interval = 0;
|
||||||
int num_grat_arp = -1, num_unsol_na = -1;
|
int num_grat_arp = -1;
|
||||||
const char *mode_orig, *mode_new;
|
int num_unsol_na = -1;
|
||||||
|
const char *mode_orig;
|
||||||
|
const char *mode_new;
|
||||||
const char *arp_ip_target = NULL;
|
const char *arp_ip_target = NULL;
|
||||||
const char *lacp_rate;
|
const char *lacp_rate;
|
||||||
const char *primary;
|
const char *primary;
|
||||||
NMBondMode bond_mode;
|
NMBondMode bond_mode;
|
||||||
|
guint i;
|
||||||
|
const NMUtilsNamedValue *n;
|
||||||
|
const char *value;
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, priv->options);
|
_ensure_options_idx_cache (priv);
|
||||||
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
|
|
||||||
if (!value[0] || !nm_setting_bond_validate_option (key, value)) {
|
if (priv->options_idx_cache) {
|
||||||
g_set_error (error,
|
for (i = 0; priv->options_idx_cache[i].name; i++) {
|
||||||
NM_CONNECTION_ERROR,
|
n = &priv->options_idx_cache[i];
|
||||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
|
||||||
_("invalid option '%s' or its value '%s'"),
|
if ( !n->value_str
|
||||||
key, value);
|
|| !nm_setting_bond_validate_option (n->name, n->value_str)) {
|
||||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
|
g_set_error (error,
|
||||||
return FALSE;
|
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 */
|
/* normalize unsupported options for the current mode */
|
||||||
bond_mode = _nm_setting_bond_mode_from_string (mode_new);
|
bond_mode = _nm_setting_bond_mode_from_string (mode_new);
|
||||||
g_hash_table_iter_init (&iter, priv->options);
|
for (i = 0; priv->options_idx_cache[i].name; i++) {
|
||||||
while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) {
|
n = &priv->options_idx_cache[i];
|
||||||
if (nm_streq (key, "mode"))
|
if (!_nm_setting_bond_option_supported (n->name, bond_mode)) {
|
||||||
continue;
|
|
||||||
if (!_nm_setting_bond_option_supported (key, bond_mode)) {
|
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
NM_CONNECTION_ERROR,
|
NM_CONNECTION_ERROR,
|
||||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
_("'%s' option is not valid with mode '%s'"),
|
_("'%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);
|
g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
|
||||||
return NM_SETTING_VERIFY_NORMALIZABLE;
|
return NM_SETTING_VERIFY_NORMALIZABLE;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user