core: merge branch 'th/spec-match-bgo743411'

https://bugzilla.gnome.org/show_bug.cgi?id=743411
This commit is contained in:
Thomas Haller
2015-02-24 10:58:47 +01:00
10 changed files with 431 additions and 135 deletions

View File

@@ -148,7 +148,7 @@ Copyright 2010 - 2014 Red Hat, Inc.
</varlistentry>
<varlistentry>
<term><varname>no-auto-default</varname></term>
<listitem><para>Comma-separated list of devices for which
<listitem><para>Specify devices for which
NetworkManager shouldn't create default wired connection
(Auto eth0). By default, NetworkManager creates a temporary
wired connection for any Ethernet device that is managed and
@@ -162,11 +162,15 @@ Copyright 2010 - 2014 Red Hat, Inc.
<filename>/var/run/NetworkManager/no-auto-default.state</filename>
to prevent creating the default connection for that device
again.</para>
<para>See <xref linkend="device-spec"/> for the syntax how to
specify a device.
</para>
<para>
Example:
<programlisting>
no-auto-default=00:22:68:5c:5d:c4,00:1e:65:ff:aa:ee
no-auto-default=eth0,eth1
no-auto-default=*
no-auto-default=00:22:68:5c:5d:c4,00:1e:65:ff:aa:ee
no-auto-default=eth0,eth1
no-auto-default=*
</programlisting>
</para>
</listitem>
@@ -176,8 +180,8 @@ Copyright 2010 - 2014 Red Hat, Inc.
<term><varname>ignore-carrier</varname></term>
<listitem>
<para>
Comma-separated list of devices for which NetworkManager
will (partially) ignore the carrier state. Normally, for
Specify devices for which NetworkManager will (partially)
ignore the carrier state. Normally, for
device types that support carrier-detect, such as Ethernet
and InfiniBand, NetworkManager will only allow a
connection to be activated on the device if carrier is
@@ -193,15 +197,14 @@ Copyright 2010 - 2014 Red Hat, Inc.
connection (whether static or dynamic) to remain active on
the device when carrier is lost.
</para>
<para>
May have the special value <literal>*</literal> to apply
to all devices.
</para>
<para>
Note that the "carrier" property of NMDevices and device D-Bus
interfaces will still reflect the actual device state; it's just
that NetworkManager will not make use of that information.
</para>
<para>See <xref linkend="device-spec"/> for the syntax how to
specify a device.
</para>
</listitem>
</varlistentry>
@@ -279,17 +282,11 @@ Copyright 2010 - 2014 Red Hat, Inc.
<varlistentry>
<term><varname>unmanaged-devices</varname></term>
<listitem><para>Set devices that should be ignored by
NetworkManager when using the <literal>keyfile</literal>
plugin. Devices are specified in the following
format:</para>
<para><literal>mac:&lt;hwaddr&gt;</literal> or
<literal>interface-name:&lt;ifname&gt;</literal>. Here
<literal>hwaddr</literal> is the MAC address of the device
to be ignored, in hex-digits-and-colons notation.
<literal>ifname</literal> is the interface name of the
ignored device.</para>
<para>Multiple entries are separated with semicolons. No
spaces are allowed in the value.</para>
NetworkManager.
</para>
<para>See <xref linkend="device-spec"/> for the syntax how to
specify a device.
</para>
<para>
Example:
<programlisting>
@@ -545,6 +542,77 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth
</variablelist>
</refsect1>
<refsect1>
<title>Appendix</title>
<refsect2 id="device-spec">
<title>Device List Format</title>
<para>
The configuration options <literal>main.no-auto-default</literal>, <literal>main.ignore-carrier</literal>,
and <literal>keyfile.unmanaged-devices</literal> select devices based on a list of matchings.
Devices can be specified using the following format:
</para>
<para>
<variablelist>
<varlistentry>
<term>*</term>
<listitem><para>Matches every device.</para></listitem>
</varlistentry>
<varlistentry>
<term>IFNAME</term>
<listitem><para>Case sensitive match of interface name of the device. Globbing is not supported.</para></listitem>
</varlistentry>
<varlistentry>
<term>HWADDR</term>
<listitem><para>Match the MAC address of the device. Globbing is not supported</para></listitem>
</varlistentry>
<varlistentry>
<term>interface-name:IFNAME</term>
<term>interface-name:~IFNAME</term>
<listitem><para>Case sensitive match of interface name of the device. Simple globbing is supported with
<literal>*</literal> and <literal>?</literal>. Ranges and escaping is not supported.</para></listitem>
</varlistentry>
<varlistentry>
<term>interface-name:=IFNAME</term>
<listitem><para>Case sensitive match of interface name of the device. Globbing is disabled and <literal>IFNAME</literal>
is taken literally.</para></listitem>
</varlistentry>
<varlistentry>
<term>mac:HWADDR</term>
<listitem><para>Match the MAC address of the device. Globbing is not supported</para></listitem>
</varlistentry>
<varlistentry>
<term>s390-subchannels:HWADDR</term>
<listitem><para>Match the device based on the subchannel address. Globbing is not supported</para></listitem>
</varlistentry>
<varlistentry>
<term>except:SPEC</term>
<listitem><para>Negative match of a device. <literal>SPEC</literal> must be explicitly qualified with
a prefix such as <literal>interface-name:</literal>. A negative match has higher priority then the positive
matches above.</para></listitem>
</varlistentry>
<varlistentry>
<term>SPEC[,;]SPEC</term>
<listitem><para>Multiple specs can be concatenated with comman or semicolon. The order does not matter as
matches are either positive (inclusive) or negative, with negative matches having higher priority.</para>
<para>Backslash is supported to escape the separators ';' and ',', and to express special
characters such as newline ('\n'), tabulator ('\t'), whitespace ('\s') and backslash ('\\'). The globbing of
interface names cannot be escaped. Whitespace is taken literally so usually the specs will be concatenated
without spaces.</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
Example:
<programlisting>
interface-name:em4
mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth2
interface-name:vboxnet*,except:interface-name:vboxnet2
*,except:mac:00:22:68:1c:59:b1
</programlisting>
</para>
</refsect2>
</refsect1>
<refsect1>
<title>See Also</title>
<para>

View File

@@ -864,55 +864,99 @@ nm_utils_find_helper(const char *progname, const char *try_first, GError **error
/******************************************************************************************/
gboolean
nm_match_spec_string (const GSList *specs, const char *match)
#define MAC_TAG "mac:"
#define INTERFACE_NAME_TAG "interface-name:"
#define SUBCHAN_TAG "s390-subchannels:"
#define EXCEPT_TAG "except:"
static const char *
_match_except (const char *spec_str, gboolean *out_except)
{
const GSList *iter;
for (iter = specs; iter; iter = g_slist_next (iter)) {
if (!g_ascii_strcasecmp ((const char *) iter->data, match))
return TRUE;
}
return FALSE;
if (!g_ascii_strncasecmp (spec_str, EXCEPT_TAG, STRLEN (EXCEPT_TAG))) {
spec_str += STRLEN (EXCEPT_TAG);
*out_except = TRUE;
} else
*out_except = FALSE;
return spec_str;
}
gboolean
NMMatchSpecMatchType
nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
g_return_val_if_fail (hwaddr != NULL, FALSE);
g_return_val_if_fail (hwaddr != NULL, NM_MATCH_SPEC_NO_MATCH);
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec_str = iter->data;
gboolean except;
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 (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1))
return TRUE;
spec_str = _match_except (spec_str, &except);
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);
else if (except)
continue;
if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1)) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
return FALSE;
return match;
}
gboolean
NMMatchSpecMatchType
nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
{
char *iface_match;
gboolean matched;
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
g_return_val_if_fail (interface_name != NULL, FALSE);
g_return_val_if_fail (interface_name != NULL, NM_MATCH_SPEC_NO_MATCH);
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;
gboolean except;
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;
spec_str = _match_except (spec_str, &except);
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;
}
} else if (except)
continue;
if ( !strcmp (spec_str, interface_name)
|| (use_pattern && g_pattern_match_simple (spec_str, interface_name))) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
return match;
}
#define BUFSIZE 10
@@ -981,33 +1025,108 @@ parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
return TRUE;
}
#define SUBCHAN_TAG "s390-subchannels:"
gboolean
NMMatchSpecMatchType
nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
{
const GSList *iter;
guint32 a = 0, b = 0, c = 0;
guint32 spec_a = 0, spec_b = 0, spec_c = 0;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
g_return_val_if_fail (subchannels != NULL, FALSE);
g_return_val_if_fail (subchannels != NULL, NM_MATCH_SPEC_NO_MATCH);
if (!parse_subchannels (subchannels, &a, &b, &c))
return FALSE;
return NM_MATCH_SPEC_NO_MATCH;
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec = iter->data;
const char *spec_str = iter->data;
gboolean except;
if (!strncmp (spec, SUBCHAN_TAG, strlen (SUBCHAN_TAG))) {
spec += strlen (SUBCHAN_TAG);
if (parse_subchannels (spec, &spec_a, &spec_b, &spec_c)) {
if (a == spec_a && b == spec_b && c == spec_c)
return TRUE;
if (!spec_str || !*spec_str)
continue;
spec_str = _match_except (spec_str, &except);
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) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
}
}
return match;
}
return FALSE;
GSList *
nm_match_spec_split (const char *value)
{
char *string_value, *p, *q0, *q;
GSList *pieces = NULL;
if (!value || !*value)
return NULL;
/* Copied from glibs g_key_file_parse_value_as_string() function
* and adjusted. */
string_value = g_new (gchar, strlen (value) + 1);
p = (gchar *) value;
q0 = q = string_value;
while (*p) {
if (*p == '\\') {
p++;
switch (*p) {
case 's':
*q = ' ';
break;
case 'n':
*q = '\n';
break;
case 't':
*q = '\t';
break;
case 'r':
*q = '\r';
break;
case '\\':
*q = '\\';
break;
case '\0':
break;
default:
if (NM_IN_SET (*p, ',', ';'))
*q = *p;
else {
*q++ = '\\';
*q = *p;
}
break;
}
} else {
*q = *p;
if (NM_IN_SET (*p, ',', ';')) {
if (q0 < q)
pieces = g_slist_prepend (pieces, g_strndup (q0, q - q0));
q0 = q + 1;
}
}
if (*p == '\0')
break;
q++;
p++;
}
*q = '\0';
if (q0 < q)
pieces = g_slist_prepend (pieces, g_strndup (q0, q - q0));
g_free (string_value);
return g_slist_reverse (pieces);
}
const char *

View File

@@ -96,10 +96,16 @@ const char *nm_utils_find_helper (const char *progname,
const char *try_first,
GError **error);
gboolean nm_match_spec_string (const GSList *specs, const char *string);
gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
gboolean nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
typedef enum {
NM_MATCH_SPEC_NO_MATCH = 0,
NM_MATCH_SPEC_MATCH = 1,
NM_MATCH_SPEC_NEG_MATCH = 2,
} NMMatchSpecMatchType;
NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
GSList *nm_match_spec_split (const char *value);
const char *nm_utils_get_shared_wifi_permission (NMConnection *connection);

View File

@@ -1495,15 +1495,19 @@ new_default_connection (NMDevice *self)
return connection;
}
static gboolean
static NMMatchSpecMatchType
spec_match_list (NMDevice *device, const GSList *specs)
{
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
if (priv->subchannels && nm_match_spec_s390_subchannels (specs, priv->subchannels))
return TRUE;
return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs);
if (priv->subchannels)
matched = nm_match_spec_s390_subchannels (specs, priv->subchannels);
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
m = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs);
matched = MAX (matched, m);
}
return matched;
}
static void

View File

@@ -8080,24 +8080,30 @@ nm_device_spec_match_list (NMDevice *self, const GSList *specs)
if (!specs)
return FALSE;
return NM_DEVICE_GET_CLASS (self)->spec_match_list (self, specs);
return NM_DEVICE_GET_CLASS (self)->spec_match_list (self, specs) == NM_MATCH_SPEC_MATCH;
}
static gboolean
static NMMatchSpecMatchType
spec_match_list (NMDevice *self, const GSList *specs)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean matched = FALSE;
if (nm_match_spec_string (specs, "*"))
return TRUE;
if (priv->hw_addr_len)
matched = nm_match_spec_hwaddr (specs, priv->hw_addr);
if (!matched)
matched = nm_match_spec_interface_name (specs, nm_device_get_iface (self));
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
const GSList *iter;
for (iter = specs; iter; iter = g_slist_next (iter)) {
if (!strcmp ((const char *) iter->data, "*")) {
matched = NM_MATCH_SPEC_MATCH;
break;
}
}
if (priv->hw_addr_len) {
m = nm_match_spec_hwaddr (specs, priv->hw_addr);
matched = MAX (matched, m);
}
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
m = nm_match_spec_interface_name (specs, nm_device_get_iface (self));
matched = MAX (matched, m);
}
return matched;
}

View File

@@ -187,7 +187,7 @@ typedef struct {
/* Sync deactivating (in the DISCONNECTED phase) */
void (* deactivate) (NMDevice *self);
gboolean (* spec_match_list) (NMDevice *self, const GSList *specs);
NMMatchSpecMatchType (* spec_match_list) (NMDevice *self, const GSList *specs);
/* Update the connection with currently configured L2 settings */
void (* update_connection) (NMDevice *device, NMConnection *connection);

View File

@@ -32,6 +32,7 @@
#include "NetworkManagerUtils.h"
#include "gsystem-local-alloc.h"
#include "nm-enum-types.h"
#include "nm-core-internal.h"
#include <gio/gio.h>
#include <glib/gi18n.h>
@@ -76,7 +77,7 @@ typedef struct {
char *debug;
char **ignore_carrier;
GSList *ignore_carrier;
gboolean configure_and_quit;
} NMConfigPrivate;
@@ -237,21 +238,10 @@ nm_config_get_configure_and_quit (NMConfig *config)
gboolean
nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
GSList *specs = NULL;
int i;
gboolean match;
g_return_val_if_fail (NM_IS_CONFIG (config), FALSE);
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
if (!priv->ignore_carrier)
return FALSE;
for (i = 0; priv->ignore_carrier[i]; i++)
specs = g_slist_prepend (specs, priv->ignore_carrier[i]);
match = nm_device_spec_match_list (device, specs);
g_slist_free (specs);
return match;
return nm_device_spec_match_list (device, NM_CONFIG_GET_PRIVATE (config)->ignore_carrier);
}
/************************************************************************/
@@ -689,6 +679,15 @@ read_entire_config (const NMConfigCmdLineOptions *cli,
return keyfile;
}
GSList *
nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, const char *key)
{
gs_free char *value = NULL;
value = g_key_file_get_string ((GKeyFile *) keyfile, group, key, NULL);
return nm_match_spec_split (value);
}
/************************************************************************/
void
@@ -813,7 +812,8 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
char *config_main_file = NULL;
char *config_description = NULL;
char **no_auto_default;
char **no_auto_default_orig;
GSList *no_auto_default_orig_list;
GPtrArray *no_auto_default_orig;
if (priv->config_dir) {
/* Object is already initialized. */
@@ -859,17 +859,22 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
priv->debug = g_key_file_get_value (keyfile, "main", "debug", NULL);
priv->ignore_carrier = g_key_file_get_string_list (keyfile, "main", "ignore-carrier", NULL, NULL);
priv->ignore_carrier = nm_config_get_device_match_spec (keyfile, "main", "ignore-carrier");
priv->configure_and_quit = _get_bool_value (keyfile, "main", "configure-and-quit", FALSE);
no_auto_default_orig = g_key_file_get_string_list (keyfile, "main", "no-auto-default", NULL, NULL);
no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) no_auto_default_orig);
no_auto_default_orig_list = nm_config_get_device_match_spec (keyfile, "main", "no-auto-default");
no_auto_default_orig = _nm_utils_copy_slist_to_array (no_auto_default_orig_list, NULL, NULL);
g_ptr_array_add (no_auto_default_orig, NULL);
no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) no_auto_default_orig->pdata);
g_ptr_array_unref (no_auto_default_orig);
g_slist_free_full (no_auto_default_orig_list, g_free);
priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile);
g_strfreev (no_auto_default);
g_strfreev (no_auto_default_orig);
priv->config_data = g_object_ref (priv->config_data_orig);
@@ -910,7 +915,7 @@ finalize (GObject *gobject)
g_free (priv->log_level);
g_free (priv->log_domains);
g_free (priv->debug);
g_strfreev (priv->ignore_carrier);
g_slist_free_full (priv->ignore_carrier, g_free);
_nm_config_cmd_line_options_clear (&priv->cli);

View File

@@ -90,6 +90,7 @@ NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error);
void nm_config_reload (NMConfig *config);
GKeyFile *nm_config_create_keyfile (void);
GSList *nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, const char *key);
G_END_DECLS

View File

@@ -585,45 +585,19 @@ get_unmanaged_specs (NMSystemConfigInterface *config)
GKeyFile *key_file;
GSList *specs = NULL;
GError *error = NULL;
char *str;
if (!priv->conf_file)
return NULL;
key_file = g_key_file_new ();
if (!parse_key_file_allow_none (priv, key_file, &error))
goto out;
key_file = nm_config_create_keyfile ();
if (parse_key_file_allow_none (priv, key_file, &error))
specs = nm_config_get_device_match_spec (key_file, "keyfile", "unmanaged-devices");
str = g_key_file_get_value (key_file, "keyfile", "unmanaged-devices", NULL);
if (str) {
char **udis;
int i;
udis = g_strsplit_set (str, ";,", -1);
g_free (str);
for (i = 0; udis[i] != NULL; i++) {
/* Verify unmanaged specification and add it to the list */
if (!strncmp (udis[i], "mac:", 4) && nm_utils_hwaddr_valid (udis[i] + 4, -1)) {
specs = g_slist_append (specs, udis[i]);
} else if (!strncmp (udis[i], "interface-name:", 15) && nm_utils_iface_valid_name (udis[i] + 15)) {
specs = g_slist_append (specs, udis[i]);
} else {
nm_log_warn (LOGD_SETTINGS, "keyfile: error in file '%s': invalid unmanaged-devices entry: '%s'", priv->conf_file, udis[i]);
g_free (udis[i]);
}
}
g_free (udis); /* Yes, g_free, not g_strfreev because we need the strings in the list */
}
out:
if (error) {
nm_log_warn (LOGD_SETTINGS, "keyfile: error getting unmanaged specs: %s", error->message);
g_error_free (error);
}
if (key_file)
g_key_file_free (key_file);
g_key_file_free (key_file);
return specs;
}

View File

@@ -774,6 +774,118 @@ test_nm_utils_uuid_generate_from_strings (void)
/*******************************************/
static const char *_test_match_spec_all[] = {
"e",
"em",
"em*",
"em\\",
"em\\*",
"em\\1",
"em\\11",
"em\\2",
"em1",
"em11",
"em2",
"=em*",
NULL
};
static gboolean
_test_match_spec_contains (const char **matches, const char *match)
{
guint i;
for (i = 0; matches && matches[i]; i++) {
if (strcmp (match, matches[i]) == 0)
return TRUE;
}
return FALSE;
}
static void
test_match_spec_ifname (const char *spec_str, const char **matches, const char **neg_matches)
{
const char *m;
GSList *specs, *specs_reverse = NULL;
guint i;
g_assert (spec_str);
specs = nm_match_spec_split (spec_str);
specs_reverse = g_slist_reverse (g_slist_copy (specs));
for (i = 0; matches && matches[i]; i++) {
g_assert (nm_match_spec_interface_name (specs, matches[i]) == NM_MATCH_SPEC_MATCH);
g_assert (nm_match_spec_interface_name (specs_reverse, matches[i]) == NM_MATCH_SPEC_MATCH);
}
for (i = 0; neg_matches && neg_matches[i]; i++) {
g_assert (nm_match_spec_interface_name (specs, neg_matches[i]) == NM_MATCH_SPEC_NEG_MATCH);
g_assert (nm_match_spec_interface_name (specs_reverse, neg_matches[i]) == NM_MATCH_SPEC_NEG_MATCH);
}
for (i = 0; (m = _test_match_spec_all[i]); i++) {
if (_test_match_spec_contains (matches, m))
continue;
if (_test_match_spec_contains (neg_matches, m))
continue;
g_assert (nm_match_spec_interface_name (specs, m) == NM_MATCH_SPEC_NO_MATCH);
g_assert (nm_match_spec_interface_name (specs_reverse, m) == NM_MATCH_SPEC_NO_MATCH);
}
g_slist_free (specs_reverse);
g_slist_free_full (specs, g_free);
}
static void
test_nm_match_spec_interface_name (void)
{
#define S(...) ((const char *[]) { __VA_ARGS__, NULL } )
test_match_spec_ifname ("em1",
S ("em1"),
NULL);
test_match_spec_ifname ("em1,em2",
S ("em1", "em2"),
NULL);
test_match_spec_ifname ("em1,em2,interface-name:em2",
S ("em1", "em2"),
NULL);
test_match_spec_ifname ("interface-name:em1",
S ("em1"),
NULL);
test_match_spec_ifname ("interface-name:em*",
S ("em", "em*", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3"),
NULL);
test_match_spec_ifname ("interface-name:em\\*",
S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2"),
NULL);
test_match_spec_ifname ("interface-name:~em\\*",
S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2"),
NULL);
test_match_spec_ifname ("interface-name:=em*",
S ("em*"),
NULL);
test_match_spec_ifname ("interface-name:em*,except:interface-name:em1*",
S ("em", "em*", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em2", "em3"),
S ("em1", "em11"));
test_match_spec_ifname ("interface-name:em*,except:interface-name:=em*",
S ("em", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3"),
S ("em*"));
test_match_spec_ifname ("aa,bb,cc\\,dd,e,,",
S ("aa", "bb", "cc,dd", "e"),
NULL);
test_match_spec_ifname ("aa;bb;cc\\;dd;e,;",
S ("aa", "bb", "cc;dd", "e"),
NULL);
test_match_spec_ifname ("interface-name:em\\;1,em\\,2,\\,,\\\\,,em\\\\x",
S ("em;1", "em,2", ",", "\\", "em\\x"),
NULL);
test_match_spec_ifname (" , interface-name:a, ,",
S (" ", " ", " interface-name:a"),
NULL);
#undef S
}
/*******************************************/
NMTST_DEFINE ();
int
@@ -797,6 +909,7 @@ main (int argc, char **argv)
g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
g_test_add_func ("/general/nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings);
g_test_add_func ("/general/nm_match_spec_interface_name", test_nm_match_spec_interface_name);
return g_test_run ();
}