diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c index 4691722384..99d596fa56 100644 --- a/libnm-core/nm-setting-tc-config.c +++ b/libnm-core/nm-setting-tc-config.c @@ -515,7 +515,7 @@ G_DEFINE_BOXED_TYPE (NMTCTfilter, nm_tc_tfilter, nm_tc_tfilter_dup, nm_tc_tfilte struct NMTCTfilter { guint refcount; - const char *kind; + char *kind; guint32 handle; guint32 parent; NMTCAction *action; @@ -540,10 +540,26 @@ nm_tc_tfilter_new (const char *kind, { NMTCTfilter *tfilter; + if (!kind || !*kind || strchr (kind, ' ') || strchr (kind, '\t')) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid kind"), kind); + return NULL; + } + + if (!parent) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("parent handle missing")); + return NULL; + } + tfilter = g_slice_new0 (NMTCTfilter); tfilter->refcount = 1; - tfilter->kind = g_intern_string (kind); + tfilter->kind = g_strdup (kind); tfilter->parent = parent; return tfilter; @@ -583,6 +599,7 @@ nm_tc_tfilter_unref (NMTCTfilter *tfilter) tfilter->refcount--; if (tfilter->refcount == 0) { + g_free (tfilter->kind); if (tfilter->action) nm_tc_action_unref (tfilter->action); g_slice_free (NMTCTfilter, tfilter); diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index c4ee4431b5..b935760f92 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -1371,6 +1371,61 @@ test_tc_config_action (void) nm_tc_action_unref (action2); } +static void +test_tc_config_tfilter (void) +{ + NMTCAction *action1; + NMTCTfilter *tfilter1, *tfilter2; + char *str; + GError *error = NULL; + + tfilter1 = nm_tc_tfilter_new ("matchall", + TC_H_MAKE (0x1234 << 16, 0x0000), + &error); + nmtst_assert_success (tfilter1, error); + + tfilter2 = nm_tc_tfilter_new ("matchall", + TC_H_MAKE (0x1234 << 16, 0x0000), + &error); + nmtst_assert_success (tfilter2, error); + + g_assert (nm_tc_tfilter_equal (tfilter1, tfilter2)); + + action1 = nm_tc_action_new ("simple", &error); + nmtst_assert_success (action1, error); + nm_tc_action_set_attribute (action1, "sdata", g_variant_new_bytestring ("Hello")); + nm_tc_tfilter_set_action (tfilter1, action1); + nm_tc_action_unref (action1); + + g_assert (!nm_tc_tfilter_equal (tfilter1, tfilter2)); + + str = nm_utils_tc_tfilter_to_str (tfilter1, &error); + nmtst_assert_success (str, error); + g_assert_cmpstr (str, ==, "parent 1234: matchall action simple sdata Hello"); + g_free (str); + + nm_tc_tfilter_unref (tfilter2); + tfilter2 = nm_tc_tfilter_dup (tfilter1); + + g_assert (nm_tc_tfilter_equal (tfilter1, tfilter2)); + + nm_tc_tfilter_unref (tfilter1); + tfilter1 = nm_utils_tc_tfilter_from_str ("narodil sa kristus pan", &error); + nmtst_assert_no_success (tfilter1, error); + g_clear_error (&error); + + str = nm_utils_tc_tfilter_to_str (tfilter2, &error); + nmtst_assert_success (str, error); + tfilter1 = nm_utils_tc_tfilter_from_str (str, &error); + nmtst_assert_success (tfilter1, error); + g_free (str); + + g_assert (nm_tc_tfilter_equal (tfilter1, tfilter2)); + + nm_tc_tfilter_unref (tfilter1); + nm_tc_tfilter_unref (tfilter2); +} + static void test_tc_config_setting (void) { @@ -1411,6 +1466,8 @@ test_tc_config_dbus (void) NMConnection *connection1, *connection2; NMSetting *s_tc; NMTCQdisc *qdisc1, *qdisc2; + NMTCTfilter *tfilter1, *tfilter2; + NMTCAction *action; GVariant *dbus, *tc_dbus, *var1, *var2; GError *error = NULL; gboolean success; @@ -1432,6 +1489,28 @@ test_tc_config_dbus (void) nm_tc_qdisc_set_handle (qdisc2, TC_H_MAKE (TC_H_INGRESS, 0)); nm_setting_tc_config_add_qdisc (NM_SETTING_TC_CONFIG (s_tc), qdisc2); + tfilter1 = nm_tc_tfilter_new ("matchall", + TC_H_MAKE (0x1234 << 16, 0x0000), + &error); + nmtst_assert_success (tfilter1, error); + action = nm_tc_action_new ("drop", &error); + nmtst_assert_success (action, error); + nm_tc_tfilter_set_action (tfilter1, action); + nm_tc_action_unref (action); + nm_setting_tc_config_add_tfilter (NM_SETTING_TC_CONFIG (s_tc), tfilter1); + nm_tc_tfilter_unref (tfilter1); + + tfilter2 = nm_tc_tfilter_new ("matchall", + TC_H_MAKE (TC_H_INGRESS, 0), + &error); + nmtst_assert_success (tfilter2, error); + action = nm_tc_action_new ("simple", &error); + nmtst_assert_success (action, error); + nm_tc_action_set_attribute (action, "sdata", g_variant_new_bytestring ("Hello")); + nm_tc_tfilter_set_action (tfilter2, action); + nm_tc_action_unref (action); + nm_setting_tc_config_add_tfilter (NM_SETTING_TC_CONFIG (s_tc), tfilter2); + nm_tc_tfilter_unref (tfilter2); nm_connection_add_setting (connection1, s_tc); @@ -1451,7 +1530,21 @@ test_tc_config_dbus (void) g_variant_unref (var1); g_variant_unref (var2); + var1 = g_variant_lookup_value (tc_dbus, "tfilters", G_VARIANT_TYPE ("aa{sv}")); + var2 = g_variant_new_parsed ("[{'kind': <'matchall'>," + " 'handle': ," + " 'parent': ," + " 'action': <{'kind': <'drop'>}>}," + " {'kind': <'matchall'>," + " 'handle': ," + " 'parent': ," + " 'action': <{'kind': <'simple'>," + " 'sdata': }>}]"); + g_variant_unref (var1); + g_variant_unref (var2); + g_variant_unref (tc_dbus); + connection2 = nm_simple_connection_new (); success = nm_connection_replace_settings (connection2, dbus, &error); nmtst_assert_success (success, error); @@ -1501,6 +1594,7 @@ 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/dbus", test_tc_config_dbus);