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*"

(cherry picked from commit 2b518538be)
This commit is contained in:
Thomas Haller 2015-01-23 16:42:58 +01:00 committed by Beniamino Galvani
parent c2e4e2f1fd
commit a01da5f95e
2 changed files with 53 additions and 21 deletions

View file

@ -843,6 +843,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)
{
@ -853,32 +857,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;
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 (!spec_str || !*spec_str)
continue;
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
@ -947,8 +976,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)
{
@ -962,11 +989,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 (!strncmp (spec, SUBCHAN_TAG, strlen (SUBCHAN_TAG))) {
spec += strlen (SUBCHAN_TAG);
if (parse_subchannels (spec, &spec_a, &spec_b, &spec_c)) {
if (!spec_str || !*spec_str)
continue;
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;
}

View file

@ -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
}