mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-01 13:55:36 +00:00
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:
parent
4c6edb22b7
commit
b869d9cc0d
|
@ -138,6 +138,7 @@ EXTRA_DIST += \
|
|||
examples/lua/lgi/deactivate-all.lua \
|
||||
\
|
||||
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/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>".
|
||||
Globbing is not supported.</para></listitem>
|
||||
</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>
|
||||
<term>except:SPEC</term>
|
||||
<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,
|
||||
nm_device_get_iface (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),
|
||||
klass->get_s390_subchannels ? klass->get_s390_subchannels (self) : NULL);
|
||||
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 INTERFACE_NAME_TAG "interface-name:"
|
||||
#define DEVICE_TYPE_TAG "type:"
|
||||
#define DRIVER_TAG "driver:"
|
||||
#define SUBCHAN_TAG "s390-subchannels:"
|
||||
#define EXCEPT_TAG "except:"
|
||||
#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 {
|
||||
const char *interface_name;
|
||||
const char *device_type;
|
||||
const char *driver;
|
||||
const char *driver_version;
|
||||
struct {
|
||||
const char *value;
|
||||
gboolean is_parsed;
|
||||
|
@ -1374,6 +1377,38 @@ match_device_eval (const char *spec_str,
|
|||
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))
|
||||
return match_data_s390_subchannels_eval (spec_str, match_data);
|
||||
|
||||
|
@ -1392,6 +1427,8 @@ NMMatchSpecMatchType
|
|||
nm_match_spec_device (const GSList *specs,
|
||||
const char *interface_name,
|
||||
const char *device_type,
|
||||
const char *driver,
|
||||
const char *driver_version,
|
||||
const char *hwaddr,
|
||||
const char *s390_subchannels)
|
||||
{
|
||||
|
@ -1402,6 +1439,8 @@ nm_match_spec_device (const GSList *specs,
|
|||
MatchDeviceData match_data = {
|
||||
.interface_name = interface_name,
|
||||
.device_type = nm_str_not_empty (device_type),
|
||||
.driver = nm_str_not_empty (driver),
|
||||
.driver_version = nm_str_not_empty (driver_version),
|
||||
.hwaddr = {
|
||||
.value = hwaddr,
|
||||
},
|
||||
|
|
|
@ -142,6 +142,8 @@ typedef enum {
|
|||
|
||||
NMMatchSpecMatchType nm_match_spec_device (const GSList *specs,
|
||||
const char *interface_name,
|
||||
const char *driver,
|
||||
const char *driver_version,
|
||||
const char *device_type,
|
||||
const char *hwaddr,
|
||||
const char *s390_subchannels);
|
||||
|
|
|
@ -986,13 +986,25 @@ test_connection_sort_autoconnect_priority (void)
|
|||
/*****************************************************************************/
|
||||
|
||||
#define MATCH_S390 "S390:"
|
||||
#define MATCH_DRIVER "DRIVER:"
|
||||
|
||||
static NMMatchSpecMatchType
|
||||
_test_match_spec_device (const GSList *specs, const char *match_str)
|
||||
{
|
||||
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, match_str, NULL, NULL, NULL);
|
||||
return nm_match_spec_device (specs, NULL, NULL, NULL, NULL, NULL, &match_str[NM_STRLEN (MATCH_S390)]);
|
||||
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
|
||||
|
@ -1142,6 +1154,23 @@ test_match_spec_device (void)
|
|||
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"));
|
||||
|
||||
_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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue