mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-09-06 09:04:55 +00:00
libnm-core: reject tc configurations with duplicate elements
A configuration with duplicate tc qdiscs and tfilters is not valid; reject it in verify(). Note that nm_setting_tc_config_add_qdisc() and nm_setting_tc_config_add_tfilter() can't add duplicate entries and so the only way to achieve an invalid configuration is setting the properties directly. https://github.com/NetworkManager/NetworkManager/pull/95
This commit is contained in:
parent
5e8773ee63
commit
2576e3a8e8
|
@ -154,6 +154,19 @@ nm_tc_qdisc_equal (NMTCQdisc *qdisc, NMTCQdisc *other)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
_nm_tc_qdisc_hash (NMTCQdisc *qdisc)
|
||||
{
|
||||
NMHashState h;
|
||||
|
||||
nm_hash_init (&h, 43869703);
|
||||
nm_hash_update_vals (&h,
|
||||
qdisc->handle,
|
||||
qdisc->parent);
|
||||
nm_hash_update_str0 (&h, qdisc->kind);
|
||||
return nm_hash_complete (&h);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_tc_qdisc_dup:
|
||||
* @qdisc: the #NMTCQdisc
|
||||
|
@ -626,6 +639,38 @@ nm_tc_tfilter_equal (NMTCTfilter *tfilter, NMTCTfilter *other)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
_nm_tc_tfilter_hash (NMTCTfilter *tfilter)
|
||||
{
|
||||
gs_free const char **names = NULL;
|
||||
guint i, attr_hash;
|
||||
GVariant *variant;
|
||||
NMHashState h;
|
||||
guint length;
|
||||
|
||||
nm_hash_init (&h, 63624437);
|
||||
nm_hash_update_vals (&h,
|
||||
tfilter->handle,
|
||||
tfilter->parent);
|
||||
nm_hash_update_str0 (&h, tfilter->kind);
|
||||
if (tfilter->action) {
|
||||
nm_hash_update_str0 (&h, tfilter->action->kind);
|
||||
names = nm_utils_strdict_get_keys (tfilter->action->attributes, TRUE, &length);
|
||||
for (i = 0; i < length; i++) {
|
||||
nm_hash_update_str (&h, names[i]);
|
||||
variant = g_hash_table_lookup (tfilter->action->attributes, names[i]);
|
||||
if (g_variant_type_is_basic (g_variant_get_type (variant))) {
|
||||
/* g_variant_hash() works only for basic types, thus
|
||||
* we ignore any non-basic attribute. Actions differing
|
||||
* only for non-basic attributes will collide. */
|
||||
attr_hash = g_variant_hash (variant);
|
||||
nm_hash_update_val (&h, attr_hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nm_hash_complete (&h);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_tc_tfilter_dup:
|
||||
* @tfilter: the #NMTCTfilter
|
||||
|
@ -1137,6 +1182,55 @@ finalize (GObject *object)
|
|||
G_OBJECT_CLASS (nm_setting_tc_config_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
verify (NMSetting *setting, NMConnection *connection, GError **error)
|
||||
{
|
||||
NMSettingTCConfig *self = NM_SETTING_TC_CONFIG (setting);
|
||||
guint i;
|
||||
|
||||
if (self->qdiscs->len != 0) {
|
||||
gs_unref_hashtable GHashTable *ht = NULL;
|
||||
|
||||
ht = g_hash_table_new ((GHashFunc) _nm_tc_qdisc_hash,
|
||||
(GEqualFunc) nm_tc_qdisc_equal);
|
||||
for (i = 0; i < self->qdiscs->len; i++) {
|
||||
if (!g_hash_table_add (ht, self->qdiscs->pdata[i])) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("there are duplicate TC qdiscs"));
|
||||
g_prefix_error (error,
|
||||
"%s.%s: ",
|
||||
NM_SETTING_TC_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_TC_CONFIG_QDISCS);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self->tfilters->len != 0) {
|
||||
gs_unref_hashtable GHashTable *ht = NULL;
|
||||
|
||||
ht = g_hash_table_new ((GHashFunc) _nm_tc_tfilter_hash,
|
||||
(GEqualFunc) nm_tc_tfilter_equal);
|
||||
for (i = 0; i < self->tfilters->len; i++) {
|
||||
if (!g_hash_table_add (ht, self->tfilters->pdata[i])) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("there are duplicate TC filters"));
|
||||
g_prefix_error (error,
|
||||
"%s.%s: ",
|
||||
NM_SETTING_TC_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_TC_CONFIG_TFILTERS);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
compare_property (NMSetting *setting,
|
||||
NMSetting *other,
|
||||
|
@ -1502,6 +1596,7 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class)
|
|||
object_class->get_property = get_property;
|
||||
object_class->finalize = finalize;
|
||||
parent_class->compare_property = compare_property;
|
||||
parent_class->verify = verify;
|
||||
|
||||
/* Properties */
|
||||
|
||||
|
|
|
@ -1440,7 +1440,7 @@ test_tc_config_tfilter (void)
|
|||
}
|
||||
|
||||
static void
|
||||
test_tc_config_setting (void)
|
||||
test_tc_config_setting_valid (void)
|
||||
{
|
||||
gs_unref_object NMSettingTCConfig *s_tc = NULL;
|
||||
NMTCQdisc *qdisc1, *qdisc2;
|
||||
|
@ -1473,6 +1473,70 @@ test_tc_config_setting (void)
|
|||
nm_tc_qdisc_unref (qdisc2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_tc_config_setting_duplicates (void)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *qdiscs = NULL;
|
||||
gs_unref_ptrarray GPtrArray *tfilters = NULL;
|
||||
NMSettingConnection *s_con;
|
||||
NMConnection *con;
|
||||
NMSetting *s_tc;
|
||||
NMTCQdisc *qdisc;
|
||||
NMTCTfilter *tfilter;
|
||||
GError *error = NULL;
|
||||
|
||||
con = nmtst_create_minimal_connection ("dummy",
|
||||
NULL,
|
||||
NM_SETTING_DUMMY_SETTING_NAME,
|
||||
&s_con);
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_INTERFACE_NAME, "dummy1",
|
||||
NULL);
|
||||
|
||||
s_tc = nm_setting_tc_config_new ();
|
||||
nm_connection_add_setting (con, s_tc);
|
||||
qdiscs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_tc_qdisc_unref);
|
||||
tfilters = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_tc_tfilter_unref);
|
||||
|
||||
/* 1. add duplicate qdiscs */
|
||||
qdisc = nm_utils_tc_qdisc_from_str ("handle 1234 parent fff1:1 pfifo_fast", &error);
|
||||
nmtst_assert_success (qdisc, error);
|
||||
g_ptr_array_add (qdiscs, qdisc);
|
||||
|
||||
qdisc = nm_utils_tc_qdisc_from_str ("handle 1234 parent fff1:1 pfifo_fast", &error);
|
||||
nmtst_assert_success (qdisc, error);
|
||||
g_ptr_array_add (qdiscs, qdisc);
|
||||
|
||||
g_object_set (s_tc, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL);
|
||||
nmtst_assert_connection_unnormalizable (con,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
||||
|
||||
/* 2. make qdiscs unique */
|
||||
g_ptr_array_remove_index (qdiscs, 0);
|
||||
g_object_set (s_tc, NM_SETTING_TC_CONFIG_QDISCS, qdiscs, NULL);
|
||||
nmtst_assert_connection_verifies_and_normalizable (con);
|
||||
|
||||
/* 3. add duplicate filters */
|
||||
tfilter = nm_utils_tc_tfilter_from_str ("parent 1234: matchall action simple sdata Hello", &error);
|
||||
nmtst_assert_success (tfilter, error);
|
||||
g_ptr_array_add (tfilters, tfilter);
|
||||
|
||||
tfilter = nm_utils_tc_tfilter_from_str ("parent 1234: matchall action simple sdata Hello", &error);
|
||||
nmtst_assert_success (tfilter, error);
|
||||
g_ptr_array_add (tfilters, tfilter);
|
||||
|
||||
g_object_set (s_tc, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL);
|
||||
nmtst_assert_connection_unnormalizable (con,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
||||
|
||||
/* 4. make filters unique */
|
||||
g_ptr_array_remove_index (tfilters, 0);
|
||||
g_object_set (s_tc, NM_SETTING_TC_CONFIG_TFILTERS, tfilters, NULL);
|
||||
nmtst_assert_connection_verifies_and_normalizable (con);
|
||||
}
|
||||
|
||||
static void
|
||||
test_tc_config_dbus (void)
|
||||
{
|
||||
|
@ -1608,7 +1672,8 @@ main (int argc, char **argv)
|
|||
g_test_add_func ("/libnm/settings/tc_config/qdisc", test_tc_config_qdisc);
|
||||
g_test_add_func ("/libnm/settings/tc_config/action", test_tc_config_action);
|
||||
g_test_add_func ("/libnm/settings/tc_config/tfilter", test_tc_config_tfilter);
|
||||
g_test_add_func ("/libnm/settings/tc_config/setting", test_tc_config_setting);
|
||||
g_test_add_func ("/libnm/settings/tc_config/setting/valid", test_tc_config_setting_valid);
|
||||
g_test_add_func ("/libnm/settings/tc_config/setting/duplicates", test_tc_config_setting_duplicates);
|
||||
g_test_add_func ("/libnm/settings/tc_config/dbus", test_tc_config_dbus);
|
||||
|
||||
#if WITH_JSON_VALIDATION
|
||||
|
|
Loading…
Reference in a new issue