summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-01-23 16:42:58 +0100
committerThomas Haller <thaller@redhat.com>2015-02-24 10:35:24 +0100
commit2b518538bec1a0a537cc49672549e5d978716e3b (patch)
tree652d3eced6fd615873040c5c37f1463ff87a84e7
parent9080ad696d6b2339db266486b15af2b052265a2f (diff)
downloadNetworkManager-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.c66
-rw-r--r--src/tests/test-general.c8
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
}