device: add spec "driver:" to match devices
Changing the MAC address of devices is known to fail with certain drivers. Add a device-spec to allow disabling it for for such devices. Related: https://bugzilla.gnome.org/show_bug.cgi?id=777523
This commit is contained in:
@@ -138,6 +138,7 @@ EXTRA_DIST += \
|
|||||||
examples/lua/lgi/deactivate-all.lua \
|
examples/lua/lgi/deactivate-all.lua \
|
||||||
\
|
\
|
||||||
examples/nm-conf.d/30-anon.conf \
|
examples/nm-conf.d/30-anon.conf \
|
||||||
|
examples/nm-conf.d/31-mac-addr-change.conf \
|
||||||
\
|
\
|
||||||
examples/python/dbus/nm-state.py \
|
examples/python/dbus/nm-state.py \
|
||||||
examples/python/dbus/add-connection.py \
|
examples/python/dbus/add-connection.py \
|
||||||
|
11
examples/nm-conf.d/31-mac-addr-change.conf
Normal file
11
examples/nm-conf.d/31-mac-addr-change.conf
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Certain drivers are known not to support changing the MAC address.
|
||||||
|
# Disable touching the MAC address on such devices.
|
||||||
|
#
|
||||||
|
# See man NetworkManager.conf
|
||||||
|
#
|
||||||
|
# https://bugzilla.gnome.org/show_bug.cgi?id=777523
|
||||||
|
[device-mac-addr-change-wifi]
|
||||||
|
match-device=driver:rtl8723bs,driver:rtl8189es,driver:r8188eu,driver:eagle_sdio
|
||||||
|
wifi.scan-rand-mac-address=no
|
||||||
|
wifi.cloned-mac-address=preserve
|
||||||
|
ethernet.cloned-mac-address=preserve
|
@@ -1172,6 +1172,13 @@ enable=nm-version-min:1.3,nm-version-min:1.2.6,nm-version-min:1.0.16
|
|||||||
<listitem><para>Match the device type. Valid type names are as reported by "<literal>nmcli -f GENERAL.TYPE device show</literal>".
|
<listitem><para>Match the device type. Valid type names are as reported by "<literal>nmcli -f GENERAL.TYPE device show</literal>".
|
||||||
Globbing is not supported.</para></listitem>
|
Globbing is not supported.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>driver:DRIVER</term>
|
||||||
|
<listitem><para>Match the device driver as reported by "<literal>nmcli -f GENERAL.DRIVER,GENERAL.DRIVER-VERSION device show</literal>".
|
||||||
|
"<literal>DRIVER</literal>" must match the driver name exactly and does not support globbing.
|
||||||
|
Optionally, a driver version may be specified separated by '/'. Globbing is supported for the version.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>except:SPEC</term>
|
<term>except:SPEC</term>
|
||||||
<listitem><para>Negative match of a device. <literal>SPEC</literal> must be explicitly qualified with
|
<listitem><para>Negative match of a device. <literal>SPEC</literal> must be explicitly qualified with
|
||||||
|
@@ -13193,6 +13193,8 @@ nm_device_spec_match_list (NMDevice *self, const GSList *specs)
|
|||||||
m = nm_match_spec_device (specs,
|
m = nm_match_spec_device (specs,
|
||||||
nm_device_get_iface (self),
|
nm_device_get_iface (self),
|
||||||
nm_device_get_type_description (self),
|
nm_device_get_type_description (self),
|
||||||
|
nm_device_get_driver (self),
|
||||||
|
nm_device_get_driver_version (self),
|
||||||
nm_device_get_permanent_hw_address (self),
|
nm_device_get_permanent_hw_address (self),
|
||||||
klass->get_s390_subchannels ? klass->get_s390_subchannels (self) : NULL);
|
klass->get_s390_subchannels ? klass->get_s390_subchannels (self) : NULL);
|
||||||
return m == NM_MATCH_SPEC_MATCH;
|
return m == NM_MATCH_SPEC_MATCH;
|
||||||
|
@@ -1182,6 +1182,7 @@ nm_utils_read_link_absolute (const char *link_file, GError **error)
|
|||||||
#define MAC_TAG "mac:"
|
#define MAC_TAG "mac:"
|
||||||
#define INTERFACE_NAME_TAG "interface-name:"
|
#define INTERFACE_NAME_TAG "interface-name:"
|
||||||
#define DEVICE_TYPE_TAG "type:"
|
#define DEVICE_TYPE_TAG "type:"
|
||||||
|
#define DRIVER_TAG "driver:"
|
||||||
#define SUBCHAN_TAG "s390-subchannels:"
|
#define SUBCHAN_TAG "s390-subchannels:"
|
||||||
#define EXCEPT_TAG "except:"
|
#define EXCEPT_TAG "except:"
|
||||||
#define MATCH_TAG_CONFIG_NM_VERSION "nm-version:"
|
#define MATCH_TAG_CONFIG_NM_VERSION "nm-version:"
|
||||||
@@ -1192,6 +1193,8 @@ nm_utils_read_link_absolute (const char *link_file, GError **error)
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const char *interface_name;
|
const char *interface_name;
|
||||||
const char *device_type;
|
const char *device_type;
|
||||||
|
const char *driver;
|
||||||
|
const char *driver_version;
|
||||||
struct {
|
struct {
|
||||||
const char *value;
|
const char *value;
|
||||||
gboolean is_parsed;
|
gboolean is_parsed;
|
||||||
@@ -1374,6 +1377,38 @@ match_device_eval (const char *spec_str,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_MATCH_CHECK (spec_str, DRIVER_TAG)) {
|
||||||
|
const char *t;
|
||||||
|
|
||||||
|
if (!match_data->driver)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* support:
|
||||||
|
* 1) "${DRIVER}"
|
||||||
|
* In this case, DRIVER may not contain a '/' character.
|
||||||
|
* It matches any driver version.
|
||||||
|
* 2) "${DRIVER}/${DRIVER_VERSION}"
|
||||||
|
* In this case, DRIVER may contains '/' but DRIVER_VERSION
|
||||||
|
* may not. A '/' in DRIVER_VERSION may be replaced by '?'.
|
||||||
|
*
|
||||||
|
* It follows, that "${DRIVER}/""*" is like 1), but allows
|
||||||
|
* '/' inside DRIVER.
|
||||||
|
*
|
||||||
|
* The fields match to what `nmcli -f GENERAL.DRIVER,GENERAL.DRIVER-VERSION device show`
|
||||||
|
* gives. However, DRIVER matches literally, while DRIVER_VERSION is a glob
|
||||||
|
* supporting ? and *.
|
||||||
|
*/
|
||||||
|
|
||||||
|
t = strrchr (spec_str, '/');
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
return nm_streq (spec_str, match_data->driver);
|
||||||
|
|
||||||
|
return (strncmp (spec_str, match_data->driver, t - spec_str) == 0)
|
||||||
|
&& g_pattern_match_simple (&t[1],
|
||||||
|
match_data->driver_version ?: "");
|
||||||
|
}
|
||||||
|
|
||||||
if (_MATCH_CHECK (spec_str, SUBCHAN_TAG))
|
if (_MATCH_CHECK (spec_str, SUBCHAN_TAG))
|
||||||
return match_data_s390_subchannels_eval (spec_str, match_data);
|
return match_data_s390_subchannels_eval (spec_str, match_data);
|
||||||
|
|
||||||
@@ -1392,6 +1427,8 @@ NMMatchSpecMatchType
|
|||||||
nm_match_spec_device (const GSList *specs,
|
nm_match_spec_device (const GSList *specs,
|
||||||
const char *interface_name,
|
const char *interface_name,
|
||||||
const char *device_type,
|
const char *device_type,
|
||||||
|
const char *driver,
|
||||||
|
const char *driver_version,
|
||||||
const char *hwaddr,
|
const char *hwaddr,
|
||||||
const char *s390_subchannels)
|
const char *s390_subchannels)
|
||||||
{
|
{
|
||||||
@@ -1402,6 +1439,8 @@ nm_match_spec_device (const GSList *specs,
|
|||||||
MatchDeviceData match_data = {
|
MatchDeviceData match_data = {
|
||||||
.interface_name = interface_name,
|
.interface_name = interface_name,
|
||||||
.device_type = nm_str_not_empty (device_type),
|
.device_type = nm_str_not_empty (device_type),
|
||||||
|
.driver = nm_str_not_empty (driver),
|
||||||
|
.driver_version = nm_str_not_empty (driver_version),
|
||||||
.hwaddr = {
|
.hwaddr = {
|
||||||
.value = hwaddr,
|
.value = hwaddr,
|
||||||
},
|
},
|
||||||
|
@@ -142,6 +142,8 @@ typedef enum {
|
|||||||
|
|
||||||
NMMatchSpecMatchType nm_match_spec_device (const GSList *specs,
|
NMMatchSpecMatchType nm_match_spec_device (const GSList *specs,
|
||||||
const char *interface_name,
|
const char *interface_name,
|
||||||
|
const char *driver,
|
||||||
|
const char *driver_version,
|
||||||
const char *device_type,
|
const char *device_type,
|
||||||
const char *hwaddr,
|
const char *hwaddr,
|
||||||
const char *s390_subchannels);
|
const char *s390_subchannels);
|
||||||
|
@@ -986,13 +986,25 @@ test_connection_sort_autoconnect_priority (void)
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#define MATCH_S390 "S390:"
|
#define MATCH_S390 "S390:"
|
||||||
|
#define MATCH_DRIVER "DRIVER:"
|
||||||
|
|
||||||
static NMMatchSpecMatchType
|
static NMMatchSpecMatchType
|
||||||
_test_match_spec_device (const GSList *specs, const char *match_str)
|
_test_match_spec_device (const GSList *specs, const char *match_str)
|
||||||
{
|
{
|
||||||
if (match_str && g_str_has_prefix (match_str, MATCH_S390))
|
if (match_str && g_str_has_prefix (match_str, MATCH_S390))
|
||||||
return nm_match_spec_device (specs, NULL, NULL, NULL, &match_str[NM_STRLEN (MATCH_S390)]);
|
return nm_match_spec_device (specs, NULL, NULL, NULL, NULL, NULL, &match_str[NM_STRLEN (MATCH_S390)]);
|
||||||
return nm_match_spec_device (specs, match_str, NULL, NULL, NULL);
|
if (match_str && g_str_has_prefix (match_str, MATCH_DRIVER)) {
|
||||||
|
gs_free char *s = g_strdup (&match_str[NM_STRLEN (MATCH_DRIVER)]);
|
||||||
|
char *t;
|
||||||
|
|
||||||
|
t = strchr (s, '|');
|
||||||
|
if (t) {
|
||||||
|
t[0] = '\0';
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
return nm_match_spec_device (specs, NULL, NULL, s, t, NULL, NULL);
|
||||||
|
}
|
||||||
|
return nm_match_spec_device (specs, match_str, NULL, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1142,6 +1154,23 @@ test_match_spec_device (void)
|
|||||||
NULL,
|
NULL,
|
||||||
S (NULL),
|
S (NULL),
|
||||||
S (MATCH_S390"0.0.1000", MATCH_S390"0.0.1000,deadbeef", MATCH_S390"0.0.1000,0.0.1001", MATCH_S390"0.0.1000,0.0.1002"));
|
S (MATCH_S390"0.0.1000", MATCH_S390"0.0.1000,deadbeef", MATCH_S390"0.0.1000,0.0.1001", MATCH_S390"0.0.1000,0.0.1002"));
|
||||||
|
|
||||||
|
_do_test_match_spec_device ("driver:DRV",
|
||||||
|
S (MATCH_DRIVER"DRV", MATCH_DRIVER"DRV|1.6"),
|
||||||
|
S (MATCH_DRIVER"DR", MATCH_DRIVER"DR*"),
|
||||||
|
NULL);
|
||||||
|
_do_test_match_spec_device ("driver:DRV//",
|
||||||
|
S (MATCH_DRIVER"DRV/"),
|
||||||
|
S (MATCH_DRIVER"DRV/|1.6", MATCH_DRIVER"DR", MATCH_DRIVER"DR*"),
|
||||||
|
NULL);
|
||||||
|
_do_test_match_spec_device ("driver:DRV//*",
|
||||||
|
S (MATCH_DRIVER"DRV/", MATCH_DRIVER"DRV/|1.6"),
|
||||||
|
S (MATCH_DRIVER"DR", MATCH_DRIVER"DR*"),
|
||||||
|
NULL);
|
||||||
|
_do_test_match_spec_device ("driver:DRV//1.5*",
|
||||||
|
S (MATCH_DRIVER"DRV/|1.5", MATCH_DRIVER"DRV/|1.5.2"),
|
||||||
|
S (MATCH_DRIVER"DRV/", MATCH_DRIVER"DRV/|1.6", MATCH_DRIVER"DR", MATCH_DRIVER"DR*"),
|
||||||
|
NULL);
|
||||||
#undef S
|
#undef S
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user