diff options
author | Thomas Haller <thaller@redhat.com> | 2015-01-23 16:42:58 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-02-24 10:35:24 +0100 |
commit | 2b518538bec1a0a537cc49672549e5d978716e3b (patch) | |
tree | 652d3eced6fd615873040c5c37f1463ff87a84e7 | |
parent | 9080ad696d6b2339db266486b15af2b052265a2f (diff) | |
download | NetworkManager-2b518538bec1a0a537cc49672549e5d978716e3b.tar.gz |
core: rework matching of nm_match_spec()
This includes several changes how to match device specs:
- matching the interface name is no longer case-insenstive as
interface names themselves are case-sensitive.
- Now we skip patterns that start with "mac:" or "s390-subchannels:"
for comparing interface names. Previously a spec "mac:1" would have
matched an interface named "mac:1", now it doesn't.
To match such an interface, you would have to specify
"interface-name:mac:1".
- previously, a pattern "a" would have matched an interface
named "interface-name:a", now it doesn't. Since valid interface
name (in the kernel) can be at most 15 characters long, this is
however no problem.
- if the spec has the prefix "interface-name:", we support
simple globbing using GPatternSpec. Globbing without exact
spec type will still not match "vboxnet*" -- with the exception
of "*".
You can disable globbing by putting an '=' immediately
after the ':'.
(a) "interface-name:em1" | matches "em1"
(b) "interface-name:em*" | matches "em", "em1", "em2", etc.
(c) "interface-name:em\*" | matches "em\", "em\1", etc.
(d) "interface-name:=em*" | matches "em*"
(e) "em*" | matches "em*"
-rw-r--r-- | src/NetworkManagerUtils.c | 66 | ||||
-rw-r--r-- | src/tests/test-general.c | 8 |
2 files changed, 53 insertions, 21 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 5b4cac94e8..e5ff3c265b 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -877,6 +877,10 @@ nm_match_spec_string (const GSList *specs, const char *match) return FALSE; } +#define MAC_TAG "mac:" +#define INTERFACE_NAME_TAG "interface-name:" +#define SUBCHAN_TAG "s390-subchannels:" + gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) { @@ -887,32 +891,57 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) for (iter = specs; iter; iter = g_slist_next (iter)) { const char *spec_str = iter->data; - if ( !g_ascii_strncasecmp (spec_str, "mac:", 4) - && nm_utils_hwaddr_matches (spec_str + 4, -1, hwaddr, -1)) - return TRUE; + if (!spec_str || !*spec_str) + continue; + + if ( !g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, STRLEN (INTERFACE_NAME_TAG)) + || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))) + continue; + + if (!g_ascii_strncasecmp (spec_str, MAC_TAG, STRLEN (MAC_TAG))) + spec_str += STRLEN (MAC_TAG); if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1)) return TRUE; } - return FALSE; } gboolean nm_match_spec_interface_name (const GSList *specs, const char *interface_name) { - char *iface_match; - gboolean matched; + const GSList *iter; g_return_val_if_fail (interface_name != NULL, FALSE); - if (nm_match_spec_string (specs, interface_name)) - return TRUE; + for (iter = specs; iter; iter = g_slist_next (iter)) { + const char *spec_str = iter->data; + gboolean use_pattern = FALSE; + + if (!spec_str || !*spec_str) + continue; - iface_match = g_strdup_printf ("interface-name:%s", interface_name); - matched = nm_match_spec_string (specs, iface_match); - g_free (iface_match); - return matched; + if ( !g_ascii_strncasecmp (spec_str, MAC_TAG, STRLEN (MAC_TAG)) + || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))) + continue; + + if (!g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, STRLEN (INTERFACE_NAME_TAG))) { + spec_str += STRLEN (INTERFACE_NAME_TAG); + if (spec_str[0] == '=') + spec_str += 1; + else { + if (spec_str[0] == '~') + spec_str += 1; + use_pattern=TRUE; + } + } + + if (!strcmp (spec_str, interface_name)) + return TRUE; + if (use_pattern && g_pattern_match_simple (spec_str, interface_name)) + return TRUE; + } + return FALSE; } #define BUFSIZE 10 @@ -981,8 +1010,6 @@ parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c) return TRUE; } -#define SUBCHAN_TAG "s390-subchannels:" - gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels) { @@ -996,11 +1023,14 @@ nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels) return FALSE; for (iter = specs; iter; iter = g_slist_next (iter)) { - const char *spec = iter->data; + const char *spec_str = iter->data; + + if (!spec_str || !*spec_str) + continue; - if (!strncmp (spec, SUBCHAN_TAG, strlen (SUBCHAN_TAG))) { - spec += strlen (SUBCHAN_TAG); - if (parse_subchannels (spec, &spec_a, &spec_b, &spec_c)) { + if (!g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))) { + spec_str += STRLEN (SUBCHAN_TAG); + if (parse_subchannels (spec_str, &spec_a, &spec_b, &spec_c)) { if (a == spec_a && b == spec_b && c == spec_c) return TRUE; } diff --git a/src/tests/test-general.c b/src/tests/test-general.c index 275fab29a5..15320191ba 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -847,11 +847,13 @@ test_nm_match_spec_interface_name (void) test_match_spec_ifname ("interface-name:em1", S ("em1")); test_match_spec_ifname ("interface-name:em*", - S ("em*")); + S ("em", "em*", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3")); test_match_spec_ifname ("interface-name:em\\*", - S ("em\\*")); + S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2")); + test_match_spec_ifname ("interface-name:~em\\*", + S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2")); test_match_spec_ifname ("interface-name:=em*", - S ("=em*")); + S ("em*")); #undef S } |