core: merge branch 'th/spec-match-bgo743411'
https://bugzilla.gnome.org/show_bug.cgi?id=743411
This commit is contained in:
@@ -148,7 +148,7 @@ Copyright 2010 - 2014 Red Hat, Inc.
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>no-auto-default</varname></term>
|
<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
|
NetworkManager shouldn't create default wired connection
|
||||||
(Auto eth0). By default, NetworkManager creates a temporary
|
(Auto eth0). By default, NetworkManager creates a temporary
|
||||||
wired connection for any Ethernet device that is managed and
|
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>
|
<filename>/var/run/NetworkManager/no-auto-default.state</filename>
|
||||||
to prevent creating the default connection for that device
|
to prevent creating the default connection for that device
|
||||||
again.</para>
|
again.</para>
|
||||||
|
<para>See <xref linkend="device-spec"/> for the syntax how to
|
||||||
|
specify a device.
|
||||||
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
Example:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
no-auto-default=00:22:68:5c:5d:c4,00:1e:65:ff:aa:ee
|
no-auto-default=00:22:68:5c:5d:c4,00:1e:65:ff:aa:ee
|
||||||
no-auto-default=eth0,eth1
|
no-auto-default=eth0,eth1
|
||||||
no-auto-default=*
|
no-auto-default=*
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@@ -176,8 +180,8 @@ Copyright 2010 - 2014 Red Hat, Inc.
|
|||||||
<term><varname>ignore-carrier</varname></term>
|
<term><varname>ignore-carrier</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Comma-separated list of devices for which NetworkManager
|
Specify devices for which NetworkManager will (partially)
|
||||||
will (partially) ignore the carrier state. Normally, for
|
ignore the carrier state. Normally, for
|
||||||
device types that support carrier-detect, such as Ethernet
|
device types that support carrier-detect, such as Ethernet
|
||||||
and InfiniBand, NetworkManager will only allow a
|
and InfiniBand, NetworkManager will only allow a
|
||||||
connection to be activated on the device if carrier is
|
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
|
connection (whether static or dynamic) to remain active on
|
||||||
the device when carrier is lost.
|
the device when carrier is lost.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
May have the special value <literal>*</literal> to apply
|
|
||||||
to all devices.
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
Note that the "carrier" property of NMDevices and device D-Bus
|
Note that the "carrier" property of NMDevices and device D-Bus
|
||||||
interfaces will still reflect the actual device state; it's just
|
interfaces will still reflect the actual device state; it's just
|
||||||
that NetworkManager will not make use of that information.
|
that NetworkManager will not make use of that information.
|
||||||
</para>
|
</para>
|
||||||
|
<para>See <xref linkend="device-spec"/> for the syntax how to
|
||||||
|
specify a device.
|
||||||
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@@ -279,17 +282,11 @@ Copyright 2010 - 2014 Red Hat, Inc.
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>unmanaged-devices</varname></term>
|
<term><varname>unmanaged-devices</varname></term>
|
||||||
<listitem><para>Set devices that should be ignored by
|
<listitem><para>Set devices that should be ignored by
|
||||||
NetworkManager when using the <literal>keyfile</literal>
|
NetworkManager.
|
||||||
plugin. Devices are specified in the following
|
</para>
|
||||||
format:</para>
|
<para>See <xref linkend="device-spec"/> for the syntax how to
|
||||||
<para><literal>mac:<hwaddr></literal> or
|
specify a device.
|
||||||
<literal>interface-name:<ifname></literal>. Here
|
</para>
|
||||||
<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>
|
|
||||||
<para>
|
<para>
|
||||||
Example:
|
Example:
|
||||||
<programlisting>
|
<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>
|
</variablelist>
|
||||||
</refsect1>
|
</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>
|
<refsect1>
|
||||||
<title>See Also</title>
|
<title>See Also</title>
|
||||||
<para>
|
<para>
|
||||||
|
@@ -864,55 +864,99 @@ nm_utils_find_helper(const char *progname, const char *try_first, GError **error
|
|||||||
|
|
||||||
/******************************************************************************************/
|
/******************************************************************************************/
|
||||||
|
|
||||||
gboolean
|
#define MAC_TAG "mac:"
|
||||||
nm_match_spec_string (const GSList *specs, const char *match)
|
#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;
|
if (!g_ascii_strncasecmp (spec_str, EXCEPT_TAG, STRLEN (EXCEPT_TAG))) {
|
||||||
|
spec_str += STRLEN (EXCEPT_TAG);
|
||||||
for (iter = specs; iter; iter = g_slist_next (iter)) {
|
*out_except = TRUE;
|
||||||
if (!g_ascii_strcasecmp ((const char *) iter->data, match))
|
} else
|
||||||
return TRUE;
|
*out_except = FALSE;
|
||||||
}
|
return spec_str;
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
NMMatchSpecMatchType
|
||||||
nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
|
nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
|
||||||
{
|
{
|
||||||
const GSList *iter;
|
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)) {
|
for (iter = specs; iter; iter = g_slist_next (iter)) {
|
||||||
const char *spec_str = iter->data;
|
const char *spec_str = iter->data;
|
||||||
|
gboolean except;
|
||||||
|
|
||||||
if ( !g_ascii_strncasecmp (spec_str, "mac:", 4)
|
if (!spec_str || !*spec_str)
|
||||||
&& nm_utils_hwaddr_matches (spec_str + 4, -1, hwaddr, -1))
|
continue;
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1))
|
spec_str = _match_except (spec_str, &except);
|
||||||
return TRUE;
|
|
||||||
|
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 match;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
NMMatchSpecMatchType
|
||||||
nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
|
nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
|
||||||
{
|
{
|
||||||
char *iface_match;
|
const GSList *iter;
|
||||||
gboolean matched;
|
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))
|
for (iter = specs; iter; iter = g_slist_next (iter)) {
|
||||||
return TRUE;
|
const char *spec_str = iter->data;
|
||||||
|
gboolean use_pattern = FALSE;
|
||||||
|
gboolean except;
|
||||||
|
|
||||||
iface_match = g_strdup_printf ("interface-name:%s", interface_name);
|
if (!spec_str || !*spec_str)
|
||||||
matched = nm_match_spec_string (specs, iface_match);
|
continue;
|
||||||
g_free (iface_match);
|
|
||||||
return matched;
|
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
|
#define BUFSIZE 10
|
||||||
@@ -981,33 +1025,108 @@ parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SUBCHAN_TAG "s390-subchannels:"
|
NMMatchSpecMatchType
|
||||||
|
|
||||||
gboolean
|
|
||||||
nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
|
nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
|
||||||
{
|
{
|
||||||
const GSList *iter;
|
const GSList *iter;
|
||||||
guint32 a = 0, b = 0, c = 0;
|
guint32 a = 0, b = 0, c = 0;
|
||||||
guint32 spec_a = 0, spec_b = 0, spec_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))
|
if (!parse_subchannels (subchannels, &a, &b, &c))
|
||||||
return FALSE;
|
return NM_MATCH_SPEC_NO_MATCH;
|
||||||
|
|
||||||
for (iter = specs; iter; iter = g_slist_next (iter)) {
|
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))) {
|
if (!spec_str || !*spec_str)
|
||||||
spec += strlen (SUBCHAN_TAG);
|
continue;
|
||||||
if (parse_subchannels (spec, &spec_a, &spec_b, &spec_c)) {
|
|
||||||
if (a == spec_a && b == spec_b && c == spec_c)
|
spec_str = _match_except (spec_str, &except);
|
||||||
return TRUE;
|
|
||||||
|
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 *
|
const char *
|
||||||
|
@@ -96,10 +96,16 @@ const char *nm_utils_find_helper (const char *progname,
|
|||||||
const char *try_first,
|
const char *try_first,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean nm_match_spec_string (const GSList *specs, const char *string);
|
typedef enum {
|
||||||
gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
|
NM_MATCH_SPEC_NO_MATCH = 0,
|
||||||
gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
|
NM_MATCH_SPEC_MATCH = 1,
|
||||||
gboolean nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
|
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);
|
const char *nm_utils_get_shared_wifi_permission (NMConnection *connection);
|
||||||
|
|
||||||
|
@@ -1495,15 +1495,19 @@ new_default_connection (NMDevice *self)
|
|||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static NMMatchSpecMatchType
|
||||||
spec_match_list (NMDevice *device, const GSList *specs)
|
spec_match_list (NMDevice *device, const GSList *specs)
|
||||||
{
|
{
|
||||||
|
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
|
||||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
|
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
|
||||||
|
|
||||||
if (priv->subchannels && nm_match_spec_s390_subchannels (specs, priv->subchannels))
|
if (priv->subchannels)
|
||||||
return TRUE;
|
matched = nm_match_spec_s390_subchannels (specs, priv->subchannels);
|
||||||
|
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
|
||||||
return NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs);
|
m = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs);
|
||||||
|
matched = MAX (matched, m);
|
||||||
|
}
|
||||||
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -8080,24 +8080,30 @@ nm_device_spec_match_list (NMDevice *self, const GSList *specs)
|
|||||||
if (!specs)
|
if (!specs)
|
||||||
return FALSE;
|
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)
|
spec_match_list (NMDevice *self, const GSList *specs)
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
gboolean matched = FALSE;
|
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
|
||||||
|
const GSList *iter;
|
||||||
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));
|
|
||||||
|
|
||||||
|
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;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -187,7 +187,7 @@ typedef struct {
|
|||||||
/* Sync deactivating (in the DISCONNECTED phase) */
|
/* Sync deactivating (in the DISCONNECTED phase) */
|
||||||
void (* deactivate) (NMDevice *self);
|
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 */
|
/* Update the connection with currently configured L2 settings */
|
||||||
void (* update_connection) (NMDevice *device, NMConnection *connection);
|
void (* update_connection) (NMDevice *device, NMConnection *connection);
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
#include "gsystem-local-alloc.h"
|
#include "gsystem-local-alloc.h"
|
||||||
#include "nm-enum-types.h"
|
#include "nm-enum-types.h"
|
||||||
|
#include "nm-core-internal.h"
|
||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
@@ -76,7 +77,7 @@ typedef struct {
|
|||||||
|
|
||||||
char *debug;
|
char *debug;
|
||||||
|
|
||||||
char **ignore_carrier;
|
GSList *ignore_carrier;
|
||||||
|
|
||||||
gboolean configure_and_quit;
|
gboolean configure_and_quit;
|
||||||
} NMConfigPrivate;
|
} NMConfigPrivate;
|
||||||
@@ -237,21 +238,10 @@ nm_config_get_configure_and_quit (NMConfig *config)
|
|||||||
gboolean
|
gboolean
|
||||||
nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device)
|
nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device)
|
||||||
{
|
{
|
||||||
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
|
g_return_val_if_fail (NM_IS_CONFIG (config), FALSE);
|
||||||
GSList *specs = NULL;
|
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
|
||||||
int i;
|
|
||||||
gboolean match;
|
|
||||||
|
|
||||||
if (!priv->ignore_carrier)
|
return nm_device_spec_match_list (device, NM_CONFIG_GET_PRIVATE (config)->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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@@ -689,6 +679,15 @@ read_entire_config (const NMConfigCmdLineOptions *cli,
|
|||||||
return keyfile;
|
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
|
void
|
||||||
@@ -813,7 +812,8 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
|
|||||||
char *config_main_file = NULL;
|
char *config_main_file = NULL;
|
||||||
char *config_description = NULL;
|
char *config_description = NULL;
|
||||||
char **no_auto_default;
|
char **no_auto_default;
|
||||||
char **no_auto_default_orig;
|
GSList *no_auto_default_orig_list;
|
||||||
|
GPtrArray *no_auto_default_orig;
|
||||||
|
|
||||||
if (priv->config_dir) {
|
if (priv->config_dir) {
|
||||||
/* Object is already initialized. */
|
/* 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->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);
|
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_orig_list = nm_config_get_device_match_spec (keyfile, "main", "no-auto-default");
|
||||||
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 = _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);
|
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);
|
||||||
g_strfreev (no_auto_default_orig);
|
|
||||||
|
|
||||||
priv->config_data = g_object_ref (priv->config_data_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_level);
|
||||||
g_free (priv->log_domains);
|
g_free (priv->log_domains);
|
||||||
g_free (priv->debug);
|
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);
|
_nm_config_cmd_line_options_clear (&priv->cli);
|
||||||
|
|
||||||
|
@@ -90,6 +90,7 @@ NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error);
|
|||||||
void nm_config_reload (NMConfig *config);
|
void nm_config_reload (NMConfig *config);
|
||||||
|
|
||||||
GKeyFile *nm_config_create_keyfile (void);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -585,45 +585,19 @@ get_unmanaged_specs (NMSystemConfigInterface *config)
|
|||||||
GKeyFile *key_file;
|
GKeyFile *key_file;
|
||||||
GSList *specs = NULL;
|
GSList *specs = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
char *str;
|
|
||||||
|
|
||||||
if (!priv->conf_file)
|
if (!priv->conf_file)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
key_file = g_key_file_new ();
|
key_file = nm_config_create_keyfile ();
|
||||||
if (!parse_key_file_allow_none (priv, key_file, &error))
|
if (parse_key_file_allow_none (priv, key_file, &error))
|
||||||
goto out;
|
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) {
|
if (error) {
|
||||||
nm_log_warn (LOGD_SETTINGS, "keyfile: error getting unmanaged specs: %s", error->message);
|
nm_log_warn (LOGD_SETTINGS, "keyfile: error getting unmanaged specs: %s", error->message);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
if (key_file)
|
g_key_file_free (key_file);
|
||||||
g_key_file_free (key_file);
|
|
||||||
|
|
||||||
return specs;
|
return specs;
|
||||||
}
|
}
|
||||||
|
@@ -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 ();
|
NMTST_DEFINE ();
|
||||||
|
|
||||||
int
|
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/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_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 ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user