diff options
author | Jiří Klimeš <jklimes@redhat.com> | 2015-10-29 18:57:52 +0100 |
---|---|---|
committer | Jiří Klimeš <jklimes@redhat.com> | 2015-11-03 08:31:04 +0100 |
commit | 212b3e671316c7c3e78ae0e7e00e99328137e857 (patch) | |
tree | d0a1f854e7669ec0c9497ed28a0f173ede98af68 | |
parent | 05dad07978a8e1ba956cfa4de2178ef7429af080 (diff) | |
download | NetworkManager-212b3e671316c7c3e78ae0e7e00e99328137e857.tar.gz |
core: fix assuming a connection without S390 properties (rh #1276343)
When a connection should be assumed and the generated connection did not
contain a wired setting, the connection did not match due to S390 properties.
Such a connection should be allowed to match to a connection with a wired
setting with default (empty) S390 properties.
This can happen when there is a VLAN profile configured that contains a wired
setting in it and NetworkManager is (re)started.
Example/reproducer:
$ nmcli con add type vlan con-name vlan-test autoconnect no dev em1 id 44
$ nmcli con mod vlan-test eth.mtu 1450 (modify the connection, so that it has a wired setting)
$ nmcli con up vlan-test (activate the connection)
$ sudo systemctl restart NetworkManager
$ nmcli device
check that 'vlan-test' connection is active on em1.44 device
(and not the auto-generated em1.44)
https://bugzilla.redhat.com/show_bug.cgi?id=1276343
-rw-r--r-- | src/NetworkManagerUtils.c | 52 | ||||
-rw-r--r-- | src/tests/test-general.c | 33 |
2 files changed, 85 insertions, 0 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index cd8d717e96..d683d7fa73 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -2211,6 +2211,9 @@ remove_from_hash (GHashTable *s_hash, const char *s_name, const char *p_name) { + if (!p_hash) + return; + g_hash_table_remove (p_hash, p_name); if (g_hash_table_size (p_hash) == 0) g_hash_table_remove (s_hash, s_name); @@ -2399,6 +2402,52 @@ check_connection_cloned_mac_address (NMConnection *orig, return FALSE; } +static gboolean +check_connection_s390_props (NMConnection *orig, + NMConnection *candidate, + GHashTable *settings) +{ + GHashTable *props1, *props2, *props3; + NMSettingWired *s_wired_orig, *s_wired_cand; + + props1 = check_property_in_hash (settings, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_SUBCHANNELS); + props2 = check_property_in_hash (settings, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_NETTYPE); + props3 = check_property_in_hash (settings, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_OPTIONS); + if (!props1 && !props2 && !props3) + return TRUE; + + /* If the generated connection did not contain wired setting, + * allow it to match to a connection with a wired setting, + * but default (empty) s390-* properties */ + s_wired_orig = nm_connection_get_setting_wired (orig); + s_wired_cand = nm_connection_get_setting_wired (candidate); + if (!s_wired_orig && s_wired_cand) { + const char * const *subchans = nm_setting_wired_get_s390_subchannels (s_wired_cand); + const char *nettype = nm_setting_wired_get_s390_nettype (s_wired_cand); + guint32 num_options = nm_setting_wired_get_num_s390_options (s_wired_cand); + + if ((!subchans || !*subchans) && !nettype && num_options == 0) { + remove_from_hash (settings, props1, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_SUBCHANNELS); + remove_from_hash (settings, props2, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_NETTYPE); + remove_from_hash (settings, props3, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_WIRED_S390_OPTIONS); + return TRUE; + } + } + return FALSE; +} + static NMConnection * check_possible_match (NMConnection *orig, NMConnection *candidate, @@ -2422,6 +2471,9 @@ check_possible_match (NMConnection *orig, if (!check_connection_cloned_mac_address (orig, candidate, settings)) return NULL; + if (!check_connection_s390_props (orig, candidate, settings)) + return NULL; + if (g_hash_table_size (settings) == 0) return candidate; else diff --git a/src/tests/test-general.c b/src/tests/test-general.c index 2eb524c3b4..da68c9a97c 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -439,6 +439,38 @@ test_connection_match_wired (void) } static void +test_connection_match_wired2 (void) +{ + NMConnection *orig, *copy, *matched; + GSList *connections = NULL; + NMSettingWired *s_wired; + const char *mac = "52:54:00:ab:db:23"; + + orig = _match_connection_new (); + s_wired = nm_connection_get_setting_wired (orig); + g_assert (s_wired); + g_object_set (G_OBJECT (s_wired), + NM_SETTING_WIRED_PORT, "tp", /* port is not compared */ + NM_SETTING_WIRED_MAC_ADDRESS, mac, /* we allow MAC address just in one connection */ + NULL); + + copy = nm_simple_connection_new_clone (orig); + connections = g_slist_append (connections, copy); + + /* Check that if the generated connection do not have wired setting + * and s390 properties in the existing connection's setting are default, + * the connections match. It can happen if assuming VLAN devices. */ + nm_connection_remove_setting (orig, NM_TYPE_SETTING_WIRED); + + matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL); + g_assert (matched == copy); + + g_slist_free (connections); + g_object_unref (orig); + g_object_unref (copy); +} + +static void test_connection_match_cloned_mac (void) { NMConnection *orig, *exact, *fuzzy, *matched; @@ -1100,6 +1132,7 @@ main (int argc, char **argv) g_test_add_func ("/general/connection-match/ip4-method", test_connection_match_ip4_method); g_test_add_func ("/general/connection-match/con-interface-name", test_connection_match_interface_name); g_test_add_func ("/general/connection-match/wired", test_connection_match_wired); + g_test_add_func ("/general/connection-match/wired2", test_connection_match_wired2); g_test_add_func ("/general/connection-match/cloned_mac", test_connection_match_cloned_mac); g_test_add_func ("/general/connection-match/no-match-ip4-addr", test_connection_no_match_ip4_addr); g_test_add_func ("/general/connection-match/no-match-vlan", test_connection_no_match_vlan); |