diff options
author | Thomas Haller <thaller@redhat.com> | 2017-03-17 16:18:48 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-03-17 17:40:00 +0100 |
commit | b869d9cc0dda4fe5300f5ec5b5a090199ecd4e3e (patch) | |
tree | 654c693a00aaf40f3293c8b9f452c8622f777138 | |
parent | 4c6edb22b70249c302209dc4af29c5caa88a764d (diff) |
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
-rw-r--r-- | Makefile.examples | 1 | ||||
-rw-r--r-- | examples/nm-conf.d/31-mac-addr-change.conf | 11 | ||||
-rw-r--r-- | man/NetworkManager.conf.xml | 7 | ||||
-rw-r--r-- | src/devices/nm-device.c | 2 | ||||
-rw-r--r-- | src/nm-core-utils.c | 39 | ||||
-rw-r--r-- | src/nm-core-utils.h | 2 | ||||
-rw-r--r-- | src/tests/test-general.c | 33 |
7 files changed, 93 insertions, 2 deletions
diff --git a/Makefile.examples b/Makefile.examples index 61c2b1df6e..f464b061d6 100644 --- a/Makefile.examples +++ b/Makefile.examples @@ -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 \ diff --git a/examples/nm-conf.d/31-mac-addr-change.conf b/examples/nm-conf.d/31-mac-addr-change.conf new file mode 100644 index 0000000000..1ae2e0dc12 --- /dev/null +++ b/examples/nm-conf.d/31-mac-addr-change.conf @@ -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 diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml index 7ca496bfb0..13282f488b 100644 --- a/man/NetworkManager.conf.xml +++ b/man/NetworkManager.conf.xml @@ -1173,6 +1173,13 @@ enable=nm-version-min:1.3,nm-version-min:1.2.6,nm-version-min:1.0.16 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 a prefix such as <literal>interface-name:</literal>. A negative match has higher priority then the positive diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 0632463605..de9bf78bc7 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -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; diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index adef77e296..25ca18853e 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -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, }, diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 779ba90ab9..f9fa88a29b 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -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); diff --git a/src/tests/test-general.c b/src/tests/test-general.c index cecce83f2c..498615822e 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -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 } |