From 7b922c1b71f4063e0c8babd5b937d4283300d2f0 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Oct 20 2019 09:14:45 +0000 Subject: import NetworkManager-1.18.0-6.el7 --- diff --git a/.NetworkManager.metadata b/.NetworkManager.metadata new file mode 100644 index 0000000..462411f --- /dev/null +++ b/.NetworkManager.metadata @@ -0,0 +1 @@ +c1c90837161e149f454e886c4cdba414e87fc120 SOURCES/NetworkManager-1.18.0.tar.xz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03b22ff --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/NetworkManager-1.18.0.tar.xz diff --git a/SOURCES/00-server.conf b/SOURCES/00-server.conf new file mode 100644 index 0000000..ba3d29f --- /dev/null +++ b/SOURCES/00-server.conf @@ -0,0 +1,14 @@ +# This configuration file changes NetworkManager's behavior to +# what's expected on "traditional UNIX server" type deployments. +# +# See "man NetworkManager.conf" for more information about these +# and other keys. + +[main] +# Do not do automatic (DHCP/SLAAC) configuration on ethernet devices +# with no other matching connections. +no-auto-default=* + +# Ignore the carrier (cable plugged in) state when attempting to +# activate static-IP connections. +ignore-carrier=* diff --git a/SOURCES/0001-cloned-mac-address-permanent-rh1413312.patch b/SOURCES/0001-cloned-mac-address-permanent-rh1413312.patch new file mode 100644 index 0000000..fb8e464 --- /dev/null +++ b/SOURCES/0001-cloned-mac-address-permanent-rh1413312.patch @@ -0,0 +1,128 @@ +From 488696bfaabe783972f756f53ff2cce7b0aa8d4b Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Fri, 24 Feb 2017 20:25:56 +0100 +Subject: [PATCH] Revert "device: change default value for cloned-mac-address + to "preserve" (bgo#770611)" + +https://bugzilla.redhat.com/show_bug.cgi?id=1413312 + +This reverts commit fae5ecec5a4d9987a1915441602cb78275a9f490. +--- + clients/common/settings-docs.h.in | 4 ++-- + libnm-core/nm-setting-wired.c | 7 +++---- + libnm-core/nm-setting-wireless.c | 7 +++---- + man/NetworkManager.conf.xml | 4 ++-- + src/devices/nm-device.c | 3 ++- + 5 files changed, 12 insertions(+), 13 deletions(-) + +diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in +index 59ca4cc..5fbafb7 100644 +--- a/clients/common/settings-docs.h.in ++++ b/clients/common/settings-docs.h.in +@@ -7,7 +7,7 @@ + #define DESCRIBE_DOC_NM_SETTING_WIRELESS_BAND N_("802.11 frequency band of the network. One of \"a\" for 5GHz 802.11a or \"bg\" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the specific band, i.e. if \"a\" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible. This setting depends on specific driver capability and may not work with all drivers.") + #define DESCRIBE_DOC_NM_SETTING_WIRELESS_BSSID N_("If specified, directs the device to only associate with the given access point. This capability is highly driver dependent and not supported by all devices. Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future.") + #define DESCRIBE_DOC_NM_SETTING_WIRELESS_CHANNEL N_("Wireless channel to use for the Wi-Fi connection. The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. Because channel numbers overlap between bands, this property also requires the \"band\" property to be set.") +-#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address of the device. \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".") ++#define DESCRIBE_DOC_NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead of its permanent MAC address. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address of the device. \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"permanent\". On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".") + #define DESCRIBE_DOC_NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK N_("With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered.") + #define DESCRIBE_DOC_NM_SETTING_WIRELESS_HIDDEN N_("If TRUE, indicates that the network is a non-broadcasting network that hides its SSID. This works both in infrastructure and AP mode. In infrastructure mode, various workarounds are used for a more reliable discovery of hidden networks, such as probe-scanning the SSID. However, these workarounds expose inherent insecurities with hidden SSID networks, and thus hidden SSID networks should be used with caution. In AP mode, the created network does not broadcast its SSID. Note that marking the network as hidden may be a privacy issue for you (in infrastructure mode) or client stations (in AP mode), as the explicit probe-scans are distinctly recognizable on the air.") + #define DESCRIBE_DOC_NM_SETTING_WIRELESS_MAC_ADDRESS N_("If specified, this connection will only apply to the Wi-Fi device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).") +@@ -86,7 +86,7 @@ + #define DESCRIBE_DOC_NM_SETTING_802_1X_SUBJECT_MATCH N_("Substring to be matched against the subject of the certificate presented by the authentication server. When unset, no verification of the authentication server certificate's subject is performed. This property provides little security, if any, and its use is deprecated in favor of NMSetting8021x:domain-suffix-match.") + #define DESCRIBE_DOC_NM_SETTING_802_1X_SYSTEM_CA_CERTS N_("When TRUE, overrides the \"ca-path\" and \"phase2-ca-path\" properties using the system CA directory specified at configure time with the --system-ca-path switch. The certificates in this directory are added to the verification chain in addition to any certificates specified by the \"ca-cert\" and \"phase2-ca-cert\" properties. If the path provided with --system-ca-path is rather a file name (bundle of trusted CA certificates), it overrides \"ca-cert\" and \"phase2-ca-cert\" properties instead (sets ca_cert/ca_cert2 options for wpa_supplicant).") + #define DESCRIBE_DOC_NM_SETTING_WIRED_AUTO_NEGOTIATE N_("When TRUE, enforce auto-negotiation of speed and duplex mode. If \"speed\" and \"duplex\" properties are both specified, only that single mode will be advertised and accepted during the link auto-negotiation process: this works only for BASE-T 802.3 specifications and is useful for enforcing gigabits modes, as in these cases link negotiation is mandatory. When FALSE, \"speed\" and \"duplex\" properties should be both set or link configuration will be skipped.") +-#define DESCRIBE_DOC_NM_SETTING_WIRED_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address if the device has one (otherwise this is treated as \"preserve\"). \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"preserve\" (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".") ++#define DESCRIBE_DOC_NM_SETTING_WIRED_CLONED_MAC_ADDRESS N_("If specified, request that the device use this MAC address instead of its permanent MAC address. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\" and \"stable\" are supported. \"preserve\" means not to touch the MAC address on activation. \"permanent\" means to use the permanent hardware address if the device has one (otherwise this is treated as \"preserve\"). \"random\" creates a random MAC address on each connect. \"stable\" creates a hashed MAC address based on connection.stable-id and a machine dependent key. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to \"permanent\". On D-Bus, this field is expressed as \"assigned-mac-address\" or the deprecated \"cloned-mac-address\".") + #define DESCRIBE_DOC_NM_SETTING_WIRED_DUPLEX N_("When a value is set, either \"half\" or \"full\", configures the device to use the specified duplex mode. If \"auto-negotiate\" is \"yes\" the specified duplex mode will be the only one advertised during link negotiation: this works only for BASE-T 802.3 specifications and is useful for enforcing gigabits modes, as in these cases link negotiation is mandatory. If the value is unset (the default), the link configuration will be either skipped (if \"auto-negotiate\" is \"no\", the default) or will be auto-negotiated (if \"auto-negotiate\" is \"yes\") and the local device will advertise all the supported duplex modes. Must be set together with the \"speed\" property if specified. Before specifying a duplex mode be sure your device supports it.") + #define DESCRIBE_DOC_NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK N_("With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all bits of the MAC address are scrambled and a locally-administered, unicast MAC address is created. This property allows to specify that certain bits are fixed. Note that the least significant bit of the first MAC address will always be unset to create a unicast MAC address. If the property is NULL, it is eligible to be overwritten by a default connection setting. If the value is still NULL or an empty string, the default is to create a locally-administered, unicast MAC address. If the value contains one MAC address, this address is used as mask. The set bits of the mask are to be filled with the current MAC address of the device, while the unset bits are subject to randomization. Setting \"FE:FF:FF:00:00:00\" means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the \"random\" or \"stable\" algorithm. If the value contains one additional MAC address after the mask, this address is used instead of the current MAC address to fill the bits that shall not be randomized. For example, a value of \"FE:FF:FF:00:00:00 68:F7:28:00:00:00\" will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of \"02:00:00:00:00:00 00:00:00:00:00:00\" will create a fully scrambled globally-administered, burned-in MAC address. If the value contains more than one additional MAC addresses, one of them is chosen randomly. For example, \"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00\" will create a fully scrambled MAC address, randomly locally or globally administered.") + #define DESCRIBE_DOC_NM_SETTING_WIRED_MAC_ADDRESS N_("If specified, this connection will only apply to the Ethernet device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).") +diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c +index 7f08430..b916a7c 100644 +--- a/libnm-core/nm-setting-wired.c ++++ b/libnm-core/nm-setting-wired.c +@@ -1150,8 +1150,8 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass) + /** + * NMSettingWired:cloned-mac-address: + * +- * If specified, request that the device use this MAC address instead. +- * This is known as MAC cloning or spoofing. ++ * If specified, request that the device use this MAC address instead of its ++ * permanent MAC address. This is known as MAC cloning or spoofing. + * + * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", + * "random" and "stable" are supported. +@@ -1163,8 +1163,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass) + * machine dependent key. + * + * If unspecified, the value can be overwritten via global defaults, see manual +- * of NetworkManager.conf. If still unspecified, it defaults to "preserve" +- * (older versions of NetworkManager may use a different default value). ++ * of NetworkManager.conf. If still unspecified, it defaults to "permanent". + * + * On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated + * "cloned-mac-address". +diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c +index b4cb105..ac3f168 100644 +--- a/libnm-core/nm-setting-wireless.c ++++ b/libnm-core/nm-setting-wireless.c +@@ -1405,8 +1405,8 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) + /** + * NMSettingWireless:cloned-mac-address: + * +- * If specified, request that the device use this MAC address instead. +- * This is known as MAC cloning or spoofing. ++ * If specified, request that the device use this MAC address instead of its ++ * permanent MAC address. This is known as MAC cloning or spoofing. + * + * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", + * "random" and "stable" are supported. +@@ -1417,8 +1417,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass) + * machine dependent key. + * + * If unspecified, the value can be overwritten via global defaults, see manual +- * of NetworkManager.conf. If still unspecified, it defaults to "preserve" +- * (older versions of NetworkManager may use a different default value). ++ * of NetworkManager.conf. If still unspecified, it defaults to "permanent". + * + * On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated + * "cloned-mac-address". +diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml +index 2893424..a8c4d0b 100644 +--- a/man/NetworkManager.conf.xml ++++ b/man/NetworkManager.conf.xml +@@ -705,7 +705,7 @@ ipv6.ip6-privacy=0 + + + ethernet.cloned-mac-address +- If left unspecified, it defaults to "preserve". ++ If left unspecified, it defaults to "permanent". + + + ethernet.generate-mac-address-mask +@@ -794,7 +794,7 @@ ipv6.ip6-privacy=0 + + + wifi.cloned-mac-address +- If left unspecified, it defaults to "preserve". ++ If left unspecified, it defaults to "permanent". + + + wifi.generate-mac-address-mask +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 06ad2ce82..c0867a04b 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -15453,7 +15453,8 @@ _get_cloned_mac_address_setting (NMDevice *self, NMConnection *connection, gbool + : NM_CON_DEFAULT ("ethernet.cloned-mac-address"), + self); + +- addr = NM_CLONED_MAC_PRESERVE; ++ /* RHEL patches the default to permanent (rh#1413312) */ ++ addr = NM_CLONED_MAC_PERMANENT; + + if (!a) { + if (is_wifi) { +-- +2.21.0 + diff --git a/SOURCES/0002-nm-wait-online-not-require-nm-service-rh1520865.patch b/SOURCES/0002-nm-wait-online-not-require-nm-service-rh1520865.patch new file mode 100644 index 0000000..69296ab --- /dev/null +++ b/SOURCES/0002-nm-wait-online-not-require-nm-service-rh1520865.patch @@ -0,0 +1,39 @@ +From 5ad9e8b26c48b456251175eb211fd52f6b8d207c Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Fri, 8 Dec 2017 14:20:35 +0100 +Subject: [PATCH 1/1] Revert "systemd: let "NetworkManager-wait-online.service" + require "NetworkManager.service"" + +Upstream changes "NetworkManager-wait-online.service" to require NM. + +See + - https://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=28b97f02f64ecf94e22c8929dfd0ba64151bd9d3 + - https://bugzilla.redhat.com/show_bug.cgi?id=1452866#c50 + - https://github.com/systemd/systemd/commit/9db307820e6f545665fc87f255af737228b7183c + +This is a change in behavior, that we want to avoid for RHEL. +See also Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=1513613 + +This reverts commit 28b97f02f64ecf94e22c8929dfd0ba64151bd9d3. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1520865 +--- + data/NetworkManager-wait-online.service.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/NetworkManager-wait-online.service.in b/data/NetworkManager-wait-online.service.in +index 896324685..1753d2039 100644 +--- a/data/NetworkManager-wait-online.service.in ++++ b/data/NetworkManager-wait-online.service.in +@@ -1,7 +1,7 @@ + [Unit] + Description=Network Manager Wait Online + Documentation=man:nm-online(1) +-Requires=NetworkManager.service ++Requisite=NetworkManager.service + After=NetworkManager.service + Before=network-online.target + +-- +2.14.3 + diff --git a/SOURCES/0003-dhclient-no-leading-zero-client-id-rh1556983.patch b/SOURCES/0003-dhclient-no-leading-zero-client-id-rh1556983.patch new file mode 100644 index 0000000..b3516dc --- /dev/null +++ b/SOURCES/0003-dhclient-no-leading-zero-client-id-rh1556983.patch @@ -0,0 +1,342 @@ +From bbee3b6833ab1792e75470db5f3b7022e9a965f5 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Wed, 20 Jun 2018 11:49:22 +0200 +Subject: [PATCH 1/2] Revert "dhclient: write client-id with backslash and + quotes as hex" + +This reverts commit 0e4b33ee7552b036332f1bdbfed78f8ee75f000e. +--- + src/dhcp/nm-dhcp-dhclient-utils.c | 2 +- + src/dhcp/tests/test-dhcp-dhclient.c | 33 +---------------------------- + 2 files changed, 2 insertions(+), 33 deletions(-) + +diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c +index cbd706f..7324597 100644 +--- a/src/dhcp/nm-dhcp-dhclient-utils.c ++++ b/src/dhcp/nm-dhcp-dhclient-utils.c +@@ -124,7 +124,7 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean + * as long as all the characters are printable. + */ + for (i = 1; (p[0] == 0) && i < l; i++) { +- if (!g_ascii_isprint (p[i]) || p[i] == '\\' || p[i] == '"') ++ if (!g_ascii_isprint (p[i])) + break; + } + +diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c +index 55d712b..7df0720 100644 +--- a/src/dhcp/tests/test-dhcp-dhclient.c ++++ b/src/dhcp/tests/test-dhcp-dhclient.c +@@ -178,36 +178,6 @@ test_quote_client_id (void) + + /*****************************************************************************/ + +-static const char *quote_client_id_expected_2 = \ +- "# Created by NetworkManager\n" +- "\n" +- "send dhcp-client-identifier 00:61:5c:62:63; # added by NetworkManager\n" +- "\n" +- "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" +- "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" +- "option wpad code 252 = string;\n" +- "\n" +- "also request rfc3442-classless-static-routes;\n" +- "also request ms-classless-static-routes;\n" +- "also request static-routes;\n" +- "also request wpad;\n" +- "also request ntp-servers;\n" +- "also request root-path;\n" +- "\n"; +- +-static void +-test_quote_client_id_2 (void) +-{ +- test_config (NULL, quote_client_id_expected_2, +- AF_INET, NULL, 0, FALSE, +- "a\\bc", +- NULL, +- "eth0", +- NULL); +-} +- +-/*****************************************************************************/ +- + static const char *hex_zero_client_id_expected = \ + "# Created by NetworkManager\n" + "\n" +@@ -1130,8 +1100,7 @@ main (int argc, char **argv) + + g_test_add_func ("/dhcp/dhclient/orig_missing", test_orig_missing); + g_test_add_func ("/dhcp/dhclient/override_client_id", test_override_client_id); +- g_test_add_func ("/dhcp/dhclient/quote_client_id/1", test_quote_client_id); +- g_test_add_func ("/dhcp/dhclient/quote_client_id/2", test_quote_client_id_2); ++ g_test_add_func ("/dhcp/dhclient/quote_client_id", test_quote_client_id); + g_test_add_func ("/dhcp/dhclient/hex_zero_client_id", test_hex_zero_client_id); + g_test_add_func ("/dhcp/dhclient/ascii_client_id", test_ascii_client_id); + g_test_add_func ("/dhcp/dhclient/hex_single_client_id", test_hex_single_client_id); +-- +2.21.0 + +From 2049c9c861f262aa6c949f45cd401ec515c2f2d0 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Wed, 20 Jun 2018 11:50:51 +0200 +Subject: [PATCH 2/2] Revert "dhcp: dhclient: set type 0 for printable client + IDs" + +Keep the RHEL 7.5 behavior. + +This reverts commit 8ffa22d10d3001405965826b46463663fd2dacc2. +--- + src/dhcp/nm-dhcp-dhclient-utils.c | 46 +++------------ + src/dhcp/tests/test-dhcp-dhclient.c | 87 +++-------------------------- + 2 files changed, 17 insertions(+), 116 deletions(-) + +diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c +index 7324597..4eb4c5d 100644 +--- a/src/dhcp/nm-dhcp-dhclient-utils.c ++++ b/src/dhcp/nm-dhcp-dhclient-utils.c +@@ -137,9 +137,8 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean + g_string_append_printf (str, "%02x", (guint8) p[i]); + } + } else { +- /* Printable; just add to the line with type 0 */ ++ /* Printable; just add to the line minus the 'type' */ + g_string_append_c (str, '"'); +- g_string_append (str, "\\x00"); + g_string_append_len (str, p + 1, l - 1); + g_string_append_c (str, '"'); + } +@@ -177,60 +176,31 @@ read_client_id (const char *str) + { + gs_free char *s = NULL; + char *p; +- int i = 0, j = 0; + + nm_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG))); +- str += NM_STRLEN (CLIENTID_TAG); + +- if (!g_ascii_isspace (*str)) +- return NULL; ++ str += NM_STRLEN (CLIENTID_TAG); + while (g_ascii_isspace (*str)) + str++; + + if (*str == '"') { +- /* Parse string literal with escape sequences */ + s = g_strdup (str + 1); + p = strrchr (s, '"'); + if (p) + *p = '\0'; + else + return NULL; ++ } else ++ s = g_strdup (str); + +- if (!s[0]) +- return NULL; +- +- while (s[i]) { +- if ( s[i] == '\\' +- && s[i + 1] == 'x' +- && g_ascii_isxdigit (s[i + 2]) +- && g_ascii_isxdigit (s[i + 3])) { +- s[j++] = (g_ascii_xdigit_value (s[i + 2]) << 4) +- + g_ascii_xdigit_value (s[i + 3]); +- i += 4; +- continue; +- } +- if ( s[i] == '\\' +- && s[i + 1] >= '0' && s[i + 1] <= '7' +- && s[1 + 2] >= '0' && s[i + 2] <= '7' +- && s[1 + 3] >= '0' && s[i + 3] <= '7') { +- s[j++] = ((s[i + 1] - '0') << 6) +- + ((s[i + 2] - '0') << 3) +- + ( s[i + 3] - '0'); +- i += 4; +- continue; +- } +- s[j++] = s[i++]; +- } +- return g_bytes_new_take (g_steal_pointer (&s), j); +- } +- +- /* Otherwise, try to read a hexadecimal sequence */ +- s = g_strdup (str); + g_strchomp (s); + if (s[strlen (s) - 1] == ';') + s[strlen (s) - 1] = '\0'; + +- return nm_utils_hexstr2bin (s); ++ if (!s[0]) ++ return NULL; ++ ++ return nm_dhcp_utils_client_id_string_to_bytes (s); + } + + static gboolean +diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c +index 7df0720..acdd276 100644 +--- a/src/dhcp/tests/test-dhcp-dhclient.c ++++ b/src/dhcp/tests/test-dhcp-dhclient.c +@@ -151,7 +151,7 @@ test_override_client_id (void) + static const char *quote_client_id_expected = \ + "# Created by NetworkManager\n" + "\n" +- "send dhcp-client-identifier \"\\x00abcd\"; # added by NetworkManager\n" ++ "send dhcp-client-identifier \"1234\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" +@@ -170,37 +170,7 @@ test_quote_client_id (void) + { + test_config (NULL, quote_client_id_expected, + AF_INET, NULL, 0, FALSE, +- "abcd", +- NULL, +- "eth0", +- NULL); +-} +- +-/*****************************************************************************/ +- +-static const char *hex_zero_client_id_expected = \ +- "# Created by NetworkManager\n" +- "\n" +- "send dhcp-client-identifier 00:11:22:33; # added by NetworkManager\n" +- "\n" +- "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" +- "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" +- "option wpad code 252 = string;\n" +- "\n" +- "also request rfc3442-classless-static-routes;\n" +- "also request ms-classless-static-routes;\n" +- "also request static-routes;\n" +- "also request wpad;\n" +- "also request ntp-servers;\n" +- "also request root-path;\n" +- "\n"; +- +-static void +-test_hex_zero_client_id (void) +-{ +- test_config (NULL, hex_zero_client_id_expected, +- AF_INET, NULL, 0, FALSE, +- "00:11:22:33", ++ "1234", + NULL, + "eth0", + NULL); +@@ -211,7 +181,7 @@ test_hex_zero_client_id (void) + static const char *ascii_client_id_expected = \ + "# Created by NetworkManager\n" + "\n" +- "send dhcp-client-identifier \"\\x00qb:cd:ef:12:34:56\"; # added by NetworkManager\n" ++ "send dhcp-client-identifier \"qb:cd:ef:12:34:56\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" +@@ -269,13 +239,13 @@ test_hex_single_client_id (void) + /*****************************************************************************/ + + static const char *existing_hex_client_id_orig = \ +- "send dhcp-client-identifier 10:30:04:20:7A:08;\n"; ++ "send dhcp-client-identifier 00:30:04:20:7A:08;\n"; + + static const char *existing_hex_client_id_expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" +- "send dhcp-client-identifier 10:30:04:20:7A:08;\n" ++ "send dhcp-client-identifier 00:30:04:20:7A:08;\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" +@@ -293,7 +263,7 @@ static void + test_existing_hex_client_id (void) + { + gs_unref_bytes GBytes *new_client_id = NULL; +- const guint8 bytes[] = { 0x10, 0x30, 0x04, 0x20, 0x7A, 0x08 }; ++ const guint8 bytes[] = { 0x00, 0x30, 0x04,0x20, 0x7A, 0x08 }; + + new_client_id = g_bytes_new (bytes, sizeof (bytes)); + test_config (existing_hex_client_id_orig, existing_hex_client_id_expected, +@@ -306,53 +276,16 @@ test_existing_hex_client_id (void) + + /*****************************************************************************/ + +-static const char *existing_escaped_client_id_orig = \ +- "send dhcp-client-identifier \"\\044test\\xfe\";\n"; +- +-static const char *existing_escaped_client_id_expected = \ +- "# Created by NetworkManager\n" +- "# Merged from /path/to/dhclient.conf\n" +- "\n" +- "send dhcp-client-identifier \"\\044test\\xfe\";\n" +- "\n" +- "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" +- "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" +- "option wpad code 252 = string;\n" +- "\n" +- "also request rfc3442-classless-static-routes;\n" +- "also request ms-classless-static-routes;\n" +- "also request static-routes;\n" +- "also request wpad;\n" +- "also request ntp-servers;\n" +- "also request root-path;\n" +- "\n"; +- +-static void +-test_existing_escaped_client_id (void) +-{ +- gs_unref_bytes GBytes *new_client_id = NULL; +- +- new_client_id = g_bytes_new ("$test\xfe", 6); +- test_config (existing_escaped_client_id_orig, existing_escaped_client_id_expected, +- AF_INET, NULL, 0, FALSE, +- NULL, +- new_client_id, +- "eth0", +- NULL); +-} +- +-/*****************************************************************************/ +- + #define EACID "qb:cd:ef:12:34:56" + + static const char *existing_ascii_client_id_orig = \ +- "send dhcp-client-identifier \"\\x00" EACID "\";\n"; ++ "send dhcp-client-identifier \"" EACID "\";\n"; + + static const char *existing_ascii_client_id_expected = \ + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" +- "send dhcp-client-identifier \"\\x00" EACID "\";\n" ++ "send dhcp-client-identifier \"" EACID "\";\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" +@@ -944,7 +877,7 @@ static void + test_structured (void) + { + gs_unref_bytes GBytes *new_client_id = NULL; +- const guint8 bytes[] = "sad-and-useless"; ++ const guint8 bytes[] = "\x00sad-and-useless"; + + static const char *const orig = \ + "interface \"eth0\" { \n" +@@ -1101,11 +1034,9 @@ main (int argc, char **argv) + g_test_add_func ("/dhcp/dhclient/orig_missing", test_orig_missing); + g_test_add_func ("/dhcp/dhclient/override_client_id", test_override_client_id); + g_test_add_func ("/dhcp/dhclient/quote_client_id", test_quote_client_id); +- g_test_add_func ("/dhcp/dhclient/hex_zero_client_id", test_hex_zero_client_id); + g_test_add_func ("/dhcp/dhclient/ascii_client_id", test_ascii_client_id); + g_test_add_func ("/dhcp/dhclient/hex_single_client_id", test_hex_single_client_id); + g_test_add_func ("/dhcp/dhclient/existing-hex-client-id", test_existing_hex_client_id); +- g_test_add_func ("/dhcp/dhclient/existing-client-id", test_existing_escaped_client_id); + g_test_add_func ("/dhcp/dhclient/existing-ascii-client-id", test_existing_ascii_client_id); + g_test_add_func ("/dhcp/dhclient/fqdn", test_fqdn); + g_test_add_func ("/dhcp/dhclient/fqdn_options_override", test_fqdn_options_override); +-- +2.21.0 + diff --git a/SOURCES/0004-ibft-cap-sys-admin-rh1371201.patch b/SOURCES/0004-ibft-cap-sys-admin-rh1371201.patch new file mode 100644 index 0000000..e7f3bfb --- /dev/null +++ b/SOURCES/0004-ibft-cap-sys-admin-rh1371201.patch @@ -0,0 +1,33 @@ +From 53a95f9ebd941c9fd2464f69ee420c4c82842eda Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Fri, 2 Sep 2016 15:58:42 +0200 +Subject: [PATCH] service: give CAP_SYS_ADMIN for ibft/iscsiadm (rh#1371201) + +systemd on rhel-7.3 has a bug with merging CapabilityBoundingSet. +https://github.com/systemd/systemd/issues/1221 +Thus it is all in one line. +--- + data/NetworkManager.service.in | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/data/NetworkManager.service.in b/data/NetworkManager.service.in +index ff90456ff..680b5889a 100644 +--- a/data/NetworkManager.service.in ++++ b/data/NetworkManager.service.in +@@ -14,10 +14,10 @@ ExecStart=@sbindir@/NetworkManager --no-daemon + Restart=on-failure + # NM doesn't want systemd to kill its children for it + KillMode=process +-CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT ++#CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT + +-# ibft settings plugin calls iscsiadm which needs CAP_SYS_ADMIN +-#CapabilityBoundingSet=CAP_SYS_ADMIN ++# ibft settings plugin calls iscsiadm which needs CAP_SYS_ADMIN (rh#1371201) ++CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT CAP_SYS_ADMIN + + ProtectSystem=true + ProtectHome=read-only +-- +2.17.1 + diff --git a/SOURCES/0005-dhcp-internal-default-client-id-rh1695723.patch b/SOURCES/0005-dhcp-internal-default-client-id-rh1695723.patch new file mode 100644 index 0000000..aa198b2 --- /dev/null +++ b/SOURCES/0005-dhcp-internal-default-client-id-rh1695723.patch @@ -0,0 +1,47 @@ +From 5ca3888861d4f05935c9f330804c1f30ab8c57e5 Mon Sep 17 00:00:00 2001 +From: Francesco Giudici +Date: Tue, 9 Apr 2019 11:41:27 +0200 +Subject: [PATCH] dhcp/internal: make default dhcp-client-id based on systemd + DUID-EN + +For RHEL-7 we want to stick to the legacy behavior of the internal +dhcp client: the default dhcp-client-id is based on systemd DUID-EN. + +https://bugzilla.redhat.com/show_bug.cgi?id=1695723 + +This reverts commit cfd696cc3cf43f5f510046b757949546bcee4cdc. +--- + src/dhcp/nm-dhcp-manager.c | 2 +- + src/dhcp/nm-dhcp-systemd.c | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c +index 7063c82cf..4a40d2e52 100644 +--- a/src/dhcp/nm-dhcp-manager.c ++++ b/src/dhcp/nm-dhcp-manager.c +@@ -237,7 +237,7 @@ client_start (NMDhcpManager *self, + * + * - for IPv4, the calling code may determine a client-id (from NM's connection profile). + * If present, it is taken. If not present, the DHCP plugin uses a plugin specific default. +- * - for "internal" plugin, the default is just "mac". ++ * - for "internal" plugin, the default is just "duid". + * - for "dhclient", we try to get the configuration from dhclient's /etc/dhcp or fallback + * to whatever dhclient uses by default. + * We do it this way, because for dhclient the user may configure a default +diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c +index 70ed87150..84973aa2a 100644 +--- a/src/dhcp/nm-dhcp-systemd.c ++++ b/src/dhcp/nm-dhcp-systemd.c +@@ -750,7 +750,8 @@ ip4_start (NMDhcpClient *client, + + client_id = nm_dhcp_client_get_client_id (client); + if (!client_id) { +- client_id_new = nm_utils_dhcp_client_id_mac (arp_type, hwaddr_arr, hwaddr_len); ++ client_id_new = nm_utils_dhcp_client_id_systemd_node_specific (TRUE, ++ nm_dhcp_client_get_iface (client)); + client_id = client_id_new; + } + +-- +2.20.1 + diff --git a/SOURCES/0006-no-keyfile-file-name-extension-rh1697858.patch b/SOURCES/0006-no-keyfile-file-name-extension-rh1697858.patch new file mode 100644 index 0000000..5f45622 --- /dev/null +++ b/SOURCES/0006-no-keyfile-file-name-extension-rh1697858.patch @@ -0,0 +1,40 @@ +From a67de1d4f7025f86701c1e2cc319238cbbc88f98 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Tue, 9 Apr 2019 18:00:21 +0200 +Subject: [PATCH 1/1] Revert "keyfile: also add ".nmconnection" extension when + writing keyfiles in /etc" + +This reverts commit d37ad15f12bafd91cf724cda50aea7093e04bf7a. +--- + src/settings/plugins/keyfile/nms-keyfile-writer.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c +index 8c75d8c79..fe05df28e 100644 +--- a/src/settings/plugins/keyfile/nms-keyfile-writer.c ++++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c +@@ -357,16 +357,19 @@ nms_keyfile_writer_connection (NMConnection *connection, + GError **error) + { + const char *keyfile_dir; ++ gboolean with_extension = FALSE; + + if (save_to_disk) + keyfile_dir = nms_keyfile_utils_get_path (); +- else ++ else { + keyfile_dir = NM_KEYFILE_PATH_NAME_RUN; ++ with_extension = TRUE; ++ } + + return _internal_write_connection (connection, + keyfile_dir, + nms_keyfile_utils_get_path (), +- TRUE, ++ with_extension, + 0, + 0, + existing_path, +-- +2.20.1 + diff --git a/SOURCES/10-slaves-order.conf b/SOURCES/10-slaves-order.conf new file mode 100644 index 0000000..09726ce --- /dev/null +++ b/SOURCES/10-slaves-order.conf @@ -0,0 +1,13 @@ +# This configuration file changes NetworkManager's behavior to order +# slaves by ifindex when they are autoactivated. +# +# See "man NetworkManager.conf" for more information about these +# and other keys. +# +# Do not edit this file; it will be overwritten on upgrades. If you +# want to override the values here, or set additional values, you can +# do so by adding another file (eg, "99-local.conf") in +# /etc/NetworkManager/conf.d/ and setting keys there. + +[main] +slaves-order=index diff --git a/SOURCES/1000-cli-hide-certificate-blobs-rh1702199.patch b/SOURCES/1000-cli-hide-certificate-blobs-rh1702199.patch new file mode 100644 index 0000000..02d3c75 --- /dev/null +++ b/SOURCES/1000-cli-hide-certificate-blobs-rh1702199.patch @@ -0,0 +1,398 @@ +From ff8fb5975a6cf8d904256fa414b359c9f1c4682d Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 14:17:47 +0200 +Subject: [PATCH 1/6] cli: fix setting private key password + +Fixes: fe390556abfe ('cli: add property type for 802-1x certificate properties (pt3)') +(cherry picked from commit ee96387578ca5428b9836dda382f9e6d64d5a7a8) +(cherry picked from commit d8badb280ce2acfcd0ae6fb3d8d133cae6326b7c) +--- + clients/common/nm-meta-setting-desc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c +index 698ded869..b21ce37cf 100644 +--- a/clients/common/nm-meta-setting-desc.c ++++ b/clients/common/nm-meta-setting-desc.c +@@ -2276,6 +2276,7 @@ _set_fcn_cert_8021x (ARGS_SET_FCN) + password = path + strcspn (path, " \t"); + if (password[0] != '\0') { + password[0] = '\0'; ++ password++; + while (nm_utils_is_separator (password[0])) + password++; + } else { +-- +2.20.1 + +From 2fe6e3a039fa1c1b1975020f409a1b505c27ec3d Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 14:55:32 +0200 +Subject: [PATCH 2/6] cli: parse escape sequences when reading an 802.1x + private key + +In this way it become possible to specify a filename that includes one +of the delimiters. + +(cherry picked from commit eac15501b2364a20505a90661e037a339a63b0ea) +(cherry picked from commit 0f03773b75548151a98cae8d696fcfc698a23bb7) +--- + clients/common/nm-meta-setting-desc.c | 28 +++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c +index b21ce37cf..768e371e9 100644 +--- a/clients/common/nm-meta-setting-desc.c ++++ b/clients/common/nm-meta-setting-desc.c +@@ -2268,17 +2268,25 @@ _set_fcn_cert_8021x (ARGS_SET_FCN) + vtable = &nm_setting_8021x_scheme_vtable[property_info->property_typ_data->subtype.cert_8021x.scheme_type]; + + if (vtable->is_secret) { +- gs_free char *path = NULL; + nm_auto_free_secret char *password_free = NULL; +- char *password; +- +- path = g_strdup (value); +- password = path + strcspn (path, " \t"); +- if (password[0] != '\0') { +- password[0] = '\0'; +- password++; +- while (nm_utils_is_separator (password[0])) +- password++; ++ gs_free const char **strv = NULL; ++ const char *password; ++ const char *path; ++ gsize len; ++ ++ strv = nm_utils_escaped_tokens_split (value, NM_ASCII_SPACES); ++ len = NM_PTRARRAY_LEN (strv); ++ if (len > 2) { ++ g_set_error_literal (error, ++ NM_UTILS_ERROR, ++ NM_UTILS_ERROR_INVALID_ARGUMENT, ++ _("too many arguments. Please only specify a private key file and optionally a password")); ++ return FALSE; ++ } ++ ++ path = len > 0 ? strv[0] : NULL; ++ if (len == 2) { ++ password = strv[1]; + } else { + password_free = g_strdup (vtable->passwd_func (NM_SETTING_802_1X (setting))); + password = password_free; +-- +2.20.1 + +From 312f84cefd672ee141c999e374d49711176ff877 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 21:14:31 +0200 +Subject: [PATCH 3/6] cli: remove bluetooth completion code + +The 'bt-type' property alias accepts values provided by +gen_func_bt_type(); instead the 'bluetooth.type' property can only be +set to [dun, panu, nap] and therefore it doesn't need special +handling. + +(cherry picked from commit 78b9448b69d1e511aab9f24f4da8a6731c2dc7ee) +(cherry picked from commit a9728a61125ef44ac5008ebb0d6d028d26d683af) +--- + clients/cli/connections.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/clients/cli/connections.c b/clients/cli/connections.c +index 6ee3b49f9..b8f9b5f27 100644 +--- a/clients/cli/connections.c ++++ b/clients/cli/connections.c +@@ -4561,14 +4561,8 @@ complete_property (const char *setting_name, const char *property, const char *p + const NMMetaPropertyInfo *property_info; + + property_info = nm_meta_property_info_find_by_name (setting_name, property); +- if (property_info) { +- if (complete_option ((const NMMetaAbstractInfo *) property_info, prefix, connection)) +- return; +- } +- +- if ( strcmp (setting_name, NM_SETTING_BLUETOOTH_SETTING_NAME) == 0 +- && strcmp (property, NM_SETTING_BLUETOOTH_TYPE) == 0) +- run_rl_generator (gen_func_bt_type, prefix); ++ if (property_info) ++ complete_option ((const NMMetaAbstractInfo *) property_info, prefix, connection); + } + + /*****************************************************************************/ +-- +2.20.1 + +From 00cffb99f83e058835ed1f5a0ce78e4b2dc92e5c Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 21:35:19 +0200 +Subject: [PATCH 4/6] cli: allow completing filenames + +Allow the completion function to indicate that the word should be +completed as a filename by the shell. + +(cherry picked from commit eb724293c25038c7e0f0d6789af2cea11da176eb) +(cherry picked from commit 09f9831fc628c2bfa406987bc1e1b77c036a3b20) +--- + clients/cli/connections.c | 23 ++++++++++++++++------- + clients/common/nm-meta-setting-access.c | 2 ++ + clients/common/nm-meta-setting-access.h | 1 + + clients/common/nm-meta-setting-desc.c | 4 +++- + clients/common/nm-meta-setting-desc.h | 2 ++ + 5 files changed, 24 insertions(+), 8 deletions(-) + +diff --git a/clients/cli/connections.c b/clients/cli/connections.c +index b8f9b5f27..034fc19f5 100644 +--- a/clients/cli/connections.c ++++ b/clients/cli/connections.c +@@ -3785,6 +3785,7 @@ _meta_abstract_complete (const NMMetaAbstractInfo *abstract_info, const char *te + nmc_meta_environment_arg, + &ctx, + text, ++ NULL, + &values_to_free); + if (values) + return values_to_free ?: g_strdupv ((char **) values); +@@ -4525,11 +4526,12 @@ run_rl_generator (rl_compentry_func_t *generator_func, const char *prefix) + } + + static gboolean +-complete_option (const NMMetaAbstractInfo *abstract_info, const char *prefix, NMConnection *context_connection) ++complete_option (NmCli *nmc, const NMMetaAbstractInfo *abstract_info, const char *prefix, NMConnection *context_connection) + { + const OptionInfo *candidate; + const char *const*values; + gs_strfreev char **values_to_free = NULL; ++ gboolean complete_filename = FALSE; + const NMMetaOperationContext ctx = { + .connection = context_connection, + }; +@@ -4539,7 +4541,12 @@ complete_option (const NMMetaAbstractInfo *abstract_info, const char *prefix, NM + nmc_meta_environment_arg, + &ctx, + prefix, ++ &complete_filename, + &values_to_free); ++ if (complete_filename) { ++ nmc->return_value = NMC_RESULT_COMPLETE_FILE; ++ return TRUE; ++ } + if (values) { + for (; values[0]; values++) + g_print ("%s\n", values[0]); +@@ -4556,13 +4563,13 @@ complete_option (const NMMetaAbstractInfo *abstract_info, const char *prefix, NM + } + + static void +-complete_property (const char *setting_name, const char *property, const char *prefix, NMConnection *connection) ++complete_property (NmCli *nmc, const char *setting_name, const char *property, const char *prefix, NMConnection *connection) + { + const NMMetaPropertyInfo *property_info; + + property_info = nm_meta_property_info_find_by_name (setting_name, property); + if (property_info) +- complete_option ((const NMMetaAbstractInfo *) property_info, prefix, connection); ++ complete_option (nmc, (const NMMetaAbstractInfo *) property_info, prefix, connection); + } + + /*****************************************************************************/ +@@ -4652,8 +4659,10 @@ nmc_read_connection_properties (NmCli *nmc, + if (!get_value (&value, argc, argv, option, error)) + return FALSE; + +- if (!*argc && nmc->complete) +- complete_property (setting, strv[1], value ?: "", connection); ++ if (!*argc && nmc->complete) { ++ complete_property (nmc, setting, strv[1], value ?: "", connection); ++ return TRUE; ++ } + + if (!set_property (nmc->client, connection, setting_name, strv[1], value, modifier, error)) + return FALSE; +@@ -4734,7 +4743,7 @@ nmc_read_connection_properties (NmCli *nmc, + return FALSE; + + if (!*argc && nmc->complete) +- complete_option (chosen, value ?: "", connection); ++ complete_option (nmc, chosen, value ?: "", connection); + + if (!set_option (nmc, connection, chosen, value, error)) + return FALSE; +@@ -8861,7 +8870,7 @@ do_connection_import (NmCli *nmc, int argc, char **argv) + if ( argc == 1 + && nmc->complete) { + nmc_complete_strings (*argv, "wireguard"); +- complete_option ((const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type, ++ complete_option (nmc, (const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type, + *argv, + NULL); + } +diff --git a/clients/common/nm-meta-setting-access.c b/clients/common/nm-meta-setting-access.c +index 8399f29db..ce5cd331c 100644 +--- a/clients/common/nm-meta-setting-access.c ++++ b/clients/common/nm-meta-setting-access.c +@@ -273,6 +273,7 @@ nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abstract_info, + gpointer environment_user_data, + const NMMetaOperationContext *operation_context, + const char *text, ++ gboolean *out_complete_filename, + char ***out_to_free) + { + const char *const*values; +@@ -292,6 +293,7 @@ nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abstract_info, + environment_user_data, + operation_context, + text, ++ out_complete_filename, + out_to_free); + + nm_assert (!*out_to_free || values == (const char *const*) *out_to_free); +diff --git a/clients/common/nm-meta-setting-access.h b/clients/common/nm-meta-setting-access.h +index ec1c2ba00..38f22c7a4 100644 +--- a/clients/common/nm-meta-setting-access.h ++++ b/clients/common/nm-meta-setting-access.h +@@ -69,6 +69,7 @@ const char *const*nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abst + gpointer environment_user_data, + const NMMetaOperationContext *operation_context, + const char *text, ++ gboolean *out_complete_filename, + char ***out_to_free); + + /*****************************************************************************/ +diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c +index 768e371e9..7e4eb3d31 100644 +--- a/clients/common/nm-meta-setting-desc.c ++++ b/clients/common/nm-meta-setting-desc.c +@@ -788,7 +788,7 @@ _env_warn_fcn (const NMMetaEnvironment *environment, + const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, GError **error + + #define ARGS_COMPLETE_FCN \ +- const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, const NMMetaOperationContext *operation_context, const char *text, char ***out_to_free ++ const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, const NMMetaOperationContext *operation_context, const char *text, gboolean *out_complete_filename, char ***out_to_free + + #define ARGS_VALUES_FCN \ + const NMMetaPropertyInfo *property_info, char ***out_to_free +@@ -8159,6 +8159,7 @@ _meta_type_property_info_complete_fcn (const NMMetaAbstractInfo *abstract_info, + gpointer environment_user_data, + const NMMetaOperationContext *operation_context, + const char *text, ++ gboolean *out_complete_filename, + char ***out_to_free) + { + const NMMetaPropertyInfo *info = (const NMMetaPropertyInfo *) abstract_info; +@@ -8171,6 +8172,7 @@ _meta_type_property_info_complete_fcn (const NMMetaAbstractInfo *abstract_info, + environment_user_data, + operation_context, + text, ++ out_complete_filename, + out_to_free); + } + +diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h +index b69a07b50..2fee080b9 100644 +--- a/clients/common/nm-meta-setting-desc.h ++++ b/clients/common/nm-meta-setting-desc.h +@@ -221,6 +221,7 @@ struct _NMMetaPropertyType { + gpointer environment_user_data, + const NMMetaOperationContext *operation_context, + const char *text, ++ gboolean *out_complete_filename, + char ***out_to_free); + + /* Whether set_fcn() supports the '-' modifier. That is, whether the property +@@ -444,6 +445,7 @@ struct _NMMetaType { + gpointer environment_user_data, + const NMMetaOperationContext *operation_context, + const char *text, ++ gboolean *out_complete_filename, + char ***out_to_free); + }; + +-- +2.20.1 + +From 4fe5505236fdf1d268d8d8a8cc9a339c4e2eb47e Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 22:01:15 +0200 +Subject: [PATCH 5/6] cli: complete 802.1x certificate file names + +(cherry picked from commit ec4a12ecdbebbca5b8108e1611e95fa93b43d637) +(cherry picked from commit 3d3fac55e38c5da544f8acc36aaf9334a92cbf11) +--- + clients/common/nm-meta-setting-desc.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c +index 7e4eb3d31..7c8f89563 100644 +--- a/clients/common/nm-meta-setting-desc.c ++++ b/clients/common/nm-meta-setting-desc.c +@@ -2307,6 +2307,26 @@ _set_fcn_cert_8021x (ARGS_SET_FCN) + } + } + ++static const char *const* ++_complete_fcn_cert_8021x (ARGS_COMPLETE_FCN) ++{ ++ const NMSetting8021xSchemeVtable *vtable; ++ ++ vtable = &nm_setting_8021x_scheme_vtable[property_info->property_typ_data->subtype.cert_8021x.scheme_type]; ++ ++ if (vtable->is_secret) { ++ gs_free const char **strv = NULL; ++ ++ strv = nm_utils_escaped_tokens_split (text, NM_ASCII_SPACES); ++ /* don't try to complete the password */ ++ if (NM_PTRARRAY_LEN (strv) > 1) ++ return NULL; ++ } ++ ++ NM_SET_OUT (out_complete_filename, TRUE); ++ return NULL; ++} ++ + static gconstpointer + _get_fcn_gobject_bytes (ARGS_GET_FCN) + { +@@ -4466,6 +4486,7 @@ static const NMMetaPropertyType _pt_dcb = { + static const NMMetaPropertyType _pt_cert_8021x = { + .get_fcn = _get_fcn_cert_8021x, + .set_fcn = _set_fcn_cert_8021x, ++ .complete_fcn = _complete_fcn_cert_8021x, + }; + + static const NMMetaPropertyType _pt_ethtool = { +-- +2.20.1 + +From 1d02cd13072aa90471cdf0f0f2dde048a126c007 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Wed, 24 Apr 2019 15:21:34 +0200 +Subject: [PATCH 6/6] cli: hide certificate blobs unless --show-secrets is + passed + +This restores the behavior before commit 99711579ed43. + +Fixes: 99711579ed43 ('cli: add property type for 802-1x certificate properties (pt2)'). +(cherry picked from commit c91aad49695fc0d5ff1dd07a4459dc7fbe9bdbc0) +(cherry picked from commit 8c75120df055ac6c7b778a885473af202897abf9) +--- + clients/common/nm-meta-setting-desc.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c +index 7c8f89563..9b5debcfe 100644 +--- a/clients/common/nm-meta-setting-desc.c ++++ b/clients/common/nm-meta-setting-desc.c +@@ -2229,8 +2229,7 @@ _get_fcn_cert_8021x (ARGS_GET_FCN) + + switch (vtable->scheme_func (s_8021X)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: +- if ( vtable->is_secret +- && !NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS)) ++ if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS)) + return _get_text_hidden (get_type); + str = bytes_to_string (vtable->blob_func (s_8021X)); + break; +-- +2.20.1 + diff --git a/SOURCES/1001-device-fix-reapply-of-MTU-rh1702657.patch b/SOURCES/1001-device-fix-reapply-of-MTU-rh1702657.patch new file mode 100644 index 0000000..cd52c15 --- /dev/null +++ b/SOURCES/1001-device-fix-reapply-of-MTU-rh1702657.patch @@ -0,0 +1,42 @@ +From 89af6353940018621493764927a3f10335084628 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Fri, 26 Apr 2019 10:49:21 +0200 +Subject: [PATCH] device: fix reapply of MTU + +When we set the MTU on the link we remember its previous source +(ip-config, parent-device or connection profile) and don't change it +again afterwards to avoid interfering with user's manual changes. The +only exceptions when we change it again are (1) if the parent device +MTU changes and (2) if the new MTU has higher priority than the one +previously set. + +To allow a live reapply of the MTU property we also need to clear the +saved source, or the checks described above will prevent setting the +new value. + +Fixes: 2f8917237fdf ('device: rework mtu priority handling') + +https://bugzilla.redhat.com/show_bug.cgi?id=1702657 +(cherry picked from commit 4ed72fa658c03790700ba9084e9328fe38afdee9) +(cherry picked from commit e738479bdd714f754aa311bada3315147efab376) +--- + src/devices/nm-device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index b909f0ddf..8ae64b968 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -11312,6 +11312,9 @@ check_and_reapply_connection (NMDevice *self, + s_ip6_old = nm_connection_get_setting_ip6_config (con_old); + s_ip6_new = nm_connection_get_setting_ip6_config (con_new); + ++ /* Allow reapply of MTU */ ++ priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; ++ + nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); + nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); + +-- +2.20.1 + diff --git a/SOURCES/1002-settings-fix-failed-assertion-rh1707261.patch b/SOURCES/1002-settings-fix-failed-assertion-rh1707261.patch new file mode 100644 index 0000000..6ab52cc --- /dev/null +++ b/SOURCES/1002-settings-fix-failed-assertion-rh1707261.patch @@ -0,0 +1,34 @@ +From f85322d23536c1004db8ddc722d4f2f6abc56aba Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 11:10:33 +0200 +Subject: [PATCH] settings: fix failed assertion + +Fix the following assertion failure: + + g_object_ref: assertion 'G_IS_OBJECT (object)' failed. + +nm_settings_add_connection() can return a NULL connection. + +Fixes: f034f17ff69c ('settings: keep the added connection alive for a bit longer') +(cherry picked from commit 48ce3628c528553d4105ed443934d733998e81b4) +(cherry picked from commit d80818e6cad94def1402be8326274bde998aa276) +--- + src/settings/nm-settings.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c +index 8e18a33e0..e594860bc 100644 +--- a/src/settings/nm-settings.c ++++ b/src/settings/nm-settings.c +@@ -1174,7 +1174,7 @@ pk_add_cb (NMAuthChain *chain, + * because it's found to be incompatible with the device on AddAndActivate). + * But we need to keep it alive for a bit longer, precisely to check wehther + * it's still known to the setting manager. */ +- g_object_ref (added); ++ nm_g_object_ref (added); + } + + callback = nm_auth_chain_get_data (chain, "callback"); +-- +2.20.1 + diff --git a/SOURCES/1003-sw-devices-managed-after-wake-rh1701585.patch b/SOURCES/1003-sw-devices-managed-after-wake-rh1701585.patch new file mode 100644 index 0000000..9f8abb0 --- /dev/null +++ b/SOURCES/1003-sw-devices-managed-after-wake-rh1701585.patch @@ -0,0 +1,81 @@ +From 98b1cf070bfa857a8a39b6499b39494bc4f4e54b Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 16:39:17 +0200 +Subject: [PATCH 1/2] manager: clear unmanaged-sleeping flag on software + devices on resume + +When networking is disabled at NM startup we unmanage all devices +(including software ones) due to SLEEPING. After networking gets +enabled again we must clear the unmanaged-sleeping flag on software +devices. + +(cherry picked from commit 656753b70888badc29ffca592f82fd8355894596) +(cherry picked from commit bb555ff6b5959767ab663d610cdabb8baa280447) +--- + src/nm-manager.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/nm-manager.c b/src/nm-manager.c +index 40e068ac5..ed2fa3df4 100644 +--- a/src/nm-manager.c ++++ b/src/nm-manager.c +@@ -5923,10 +5923,10 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + guint i; + +- if (nm_device_is_software (device)) { +- /* We do not manage/unmanage software devices but +- * their dhcp leases could have gone stale so we need +- * to renew them */ ++ if ( nm_device_is_software (device) ++ && !nm_device_get_unmanaged_flags (device, NM_UNMANAGED_SLEEPING)) { ++ /* DHCP leases of software devices could have gone stale ++ * so we need to renew them. */ + nm_device_update_dynamic_ip_setup (device); + continue; + } +-- +2.20.1 + +From 9b08f52f043cb5f3794f1432df157a16c222b21c Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 23 Apr 2019 15:30:53 +0200 +Subject: [PATCH 2/2] manager: unmanage software devices when networking gets + disabled + +If a user disables networking, we consider that as an indication that +also software devices must be disconnected. OTOH, we don't want to +destroy them for external events as a system suspend. + +(cherry picked from commit 32ee51eee002f5e6717b856fd0a095114a02cc96) +(cherry picked from commit da8462df1a273cd6b31f885b866726a64ca14550) +--- + src/nm-manager.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/nm-manager.c b/src/nm-manager.c +index ed2fa3df4..c0cd15c0c 100644 +--- a/src/nm-manager.c ++++ b/src/nm-manager.c +@@ -5866,9 +5866,15 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) + * suspend/resume? + */ + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { +- /* FIXME: shouldn't we be unmanaging software devices if !suspending? */ +- if (nm_device_is_software (device)) +- continue; ++ if (nm_device_is_software (device)) { ++ /* If a user disables networking we consider that as an ++ * indication that also software devices must be disconnected. ++ * But we don't want to destroy them for external events as ++ * a system suspend. ++ */ ++ if (suspending) ++ continue; ++ } + /* Wake-on-LAN devices will be taken down post-suspend rather than pre- */ + if ( suspending + && device_is_wake_on_lan (priv->platform, device)) { +-- +2.20.1 + diff --git a/SOURCES/1004-device-restore-ipv6-config-on-link-up-rh1548237.patch b/SOURCES/1004-device-restore-ipv6-config-on-link-up-rh1548237.patch new file mode 100644 index 0000000..01d5972 --- /dev/null +++ b/SOURCES/1004-device-restore-ipv6-config-on-link-up-rh1548237.patch @@ -0,0 +1,123 @@ +From bb782ab4b2058e0ae14aae1a4c71bd0dc908fbdc Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 7 May 2019 16:26:09 +0200 +Subject: [PATCH 1/3] all: fix typos (milli seconds -> milliseconds) + +(cherry picked from commit 4735d6764a5dc9c3bc6bc09d3220751e789b39c4) +(cherry picked from commit f6b9366eb4435d7ee45f862dabdefb5f87c4739d) +--- + shared/nm-glib-aux/nm-time-utils.c | 2 +- + src/devices/nm-device.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/shared/nm-glib-aux/nm-time-utils.c b/shared/nm-glib-aux/nm-time-utils.c +index ae526c342..98a414595 100644 +--- a/shared/nm-glib-aux/nm-time-utils.c ++++ b/shared/nm-glib-aux/nm-time-utils.c +@@ -231,7 +231,7 @@ nm_utils_get_monotonic_timestamp_s (void) + * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME. + * @timestamp_ns_per_tick: How many nano seconds make one unit of @timestamp? E.g. if + * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; @timestamp in nano +- * seconds, pass 1; @timestamp in milli seconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc. ++ * seconds, pass 1; @timestamp in milliseconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc. + * + * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime(). + * The unit is the same as the passed in @timestamp basd on @timestamp_ns_per_tick. +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 8ae64b968..7bf1eb4ce 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -3588,7 +3588,7 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier) + now_ms = nm_utils_get_monotonic_timestamp_ms (); + until_ms = NM_MAX (now_ms + _get_carrier_wait_ms (self), priv->carrier_wait_until_ms); + priv->carrier_defer_id = g_timeout_add (until_ms - now_ms, carrier_disconnected_action_cb, self); +- _LOGD (LOGD_DEVICE, "carrier: link disconnected (deferring action for %ld milli seconds) (id=%u)", ++ _LOGD (LOGD_DEVICE, "carrier: link disconnected (deferring action for %ld milliseconds) (id=%u)", + (long) (until_ms - now_ms), priv->carrier_defer_id); + } + } +-- +2.20.1 + +From ef2113cf7c06d5157ddd2cdc26c1f781b60c477c Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 7 May 2019 16:25:04 +0200 +Subject: [PATCH 2/3] device: unconditionally reapply IP configuration on link + up + +Consider the situation in which ipv4.method=auto and there is an +address configured. Also, the DHCP timeout is long and there is no +DHCP server. If the link is brought down temporarily, the prefix route +for the static address is lost and not restored by NM because we +reapply the IP configuration only when the IP state is DONE. + +The same can happen also for IPv6, but in that case also static IPv6 +addresses are lost. + +We should always reapply the IP configuration when the link goes up. + +(cherry picked from commit d0b16b9283dc16e9db642280be9d6b10a04092a8) +(cherry picked from commit 4482ca64ba5bbf1c173ea5b4a3854da0173542a8) +--- + src/devices/nm-device.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 7bf1eb4ce..510d9792e 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -3890,16 +3890,12 @@ device_link_changed (NMDevice *self) + if (priv->up && (!was_up || seen_down)) { + /* the link was down and just came up. That happens for example, while changing MTU. + * We must restore IP configuration. */ +- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) { +- if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) +- _LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again"); +- } ++ if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) ++ _LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again"); + + priv->linklocal6_dad_counter = 0; +- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) { +- if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) +- _LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again"); +- } ++ if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) ++ _LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again"); + } + + if (update_unmanaged_specs) +-- +2.20.1 + +From b3f9c33557951ed90767ff50e9e72e533a211b45 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 7 May 2019 16:32:12 +0200 +Subject: [PATCH 3/3] device: fix intersecting IPv6 configurations + +If the link is down we shouldn't drop the link-local address from +configuration as it wasn't removed by user but by kernel. + +(cherry picked from commit 18d2edfaa13d97597ddf5551e6dd5ea854f1fdbf) +(cherry picked from commit 6f6914450072b79a91731e042e498ca26892696c) +--- + src/devices/nm-device.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 510d9792e..06a95110b 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -12882,7 +12882,8 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config + for (iter = priv->vpn_configs_6; iter; iter = iter->next) + nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, is_up, is_up, 0); + +- if ( priv->ipv6ll_has ++ if ( is_up ++ && priv->ipv6ll_has + && !nm_ip6_config_lookup_address (priv->ext_ip_config_6, &priv->ipv6ll_addr)) + priv->ipv6ll_has = FALSE; + } +-- +2.20.1 + diff --git a/SOURCES/1005-load-connection-dbus-fixes-rh1708660.patch b/SOURCES/1005-load-connection-dbus-fixes-rh1708660.patch new file mode 100644 index 0000000..5f3b2af --- /dev/null +++ b/SOURCES/1005-load-connection-dbus-fixes-rh1708660.patch @@ -0,0 +1,127 @@ +From 48193ae383de29c52bf37d869f2e0a8534fbe825 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Fri, 10 May 2019 14:35:52 +0200 +Subject: [PATCH 1/2] settings: avoid assertion for LoadConnections D-Bus + method with relative paths + + $ busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager/Settings org.freedesktop.NetworkManager.Settings LoadConnections as 1 relative/filename + +triggers a g_critical() assertion in nm_utils_file_is_in_path(): + + ... + #3 0x00007ffff7a19e7d in g_return_if_fail_warning + (log_domain=log_domain@entry=0x55555586c333 "NetworkManager", pretty_function=pretty_function@entry=0x55555586c0a0 <__FUNCTION__.38585> "nm_utils_file_is_in_path", expression=expression@entry=0x55555586c010 "abs_filename && abs_filename[0] == '/'") at ../glib/gmessages.c:2767 + #4 0x00005555555f1128 in nm_utils_file_is_in_path (abs_filename=abs_filename@entry=0x555555b56670 "dfd", abs_path=) at src/NetworkManagerUtils.c:1077 + #5 0x00005555555a4779 in load_connection (config=, filename=0x555555b56670 "dfd") at src/settings/plugins/keyfile/nms-keyfile-plugin.c:522 + #6 0x00005555557ce291 in nm_settings_plugin_load_connection (self=0x5555559fd400 [NMSKeyfilePlugin], filename=0x555555b56670 "dfd") at src/settings/nm-settings-plugin.c:70 + #7 0x000055555559ccdf in impl_settings_load_connections + (obj=, interface_info=, method_info=, connection=, sender=, invocation=0x7fffe0015ed0 [GDBusMethodInvocation], parameters=) at src/settings/nm-settings.c:1439 + #8 0x00005555555a9bf9 in dbus_vtable_method_call + (connection=0x5555559b91b0 [GDBusConnection], sender=sender@entry=0x555555b5c360 ":1.32283", object_path=object_path@entry=0x7fffe0019070 "/org/freedesktop/NetworkManager/Settings", interface_name=, interface_name@entry=0x7fffe002aa70 "org.freedesktop.NetworkManager.Settings", method_name=, + method_name@entry=0x7fffe00276b0 "LoadConnections", parameters=parameters@entry=0x555555c4a690, invocation=0x7fffe0015ed0 [GDBusMethodInvocation], user_data=0x5555559a1a00) + at src/nm-dbus-manager.c:947 + #9 0x00007ffff7c506c4 in call_in_idle_cb (user_data=user_data@entry=0x7fffe0015ed0) at ../gio/gdbusconnection.c:4874 + #10 0x00007ffff7a0e8eb in g_idle_dispatch (source=source@entry=0x7fffe00208a0, callback=0x7ffff7c50590 , user_data=0x7fffe0015ed0) at ../glib/gmain.c:5627 + #11 0x00007ffff7a11fd0 in g_main_dispatch (context=0x555555994d00) at ../glib/gmain.c:3189 + #12 0x00007ffff7a11fd0 in g_main_context_dispatch (context=context@entry=0x555555994d00) at ../glib/gmain.c:3854 + #13 0x00007ffff7a12368 in g_main_context_iterate (context=0x555555994d00, block=block@entry=1, dispatch=dispatch@entry=1, self=) at ../glib/gmain.c:3927 + #14 0x00007ffff7a126b3 in g_main_loop_run (loop=0x555555995e60) at ../glib/gmain.c:4123 + #15 0x000055555558a741 in main (argc=, argv=) at src/main.c:444 + +Filter out relative filenames early. + +(cherry picked from commit a1b102eae4bc412297b72c327530abc1ca38d659) +(cherry picked from commit c21171e06987353868e91d6e1cd395ade05e9390) +--- + src/settings/nm-settings.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c +index e594860bc..1f8314847 100644 +--- a/src/settings/nm-settings.c ++++ b/src/settings/nm-settings.c +@@ -1409,8 +1409,6 @@ impl_settings_load_connections (NMDBusObject *obj, + NMSettings *self = NM_SETTINGS (obj); + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + gs_unref_ptrarray GPtrArray *failures = NULL; +- GSList *iter; +- guint i; + gs_free const char **filenames = NULL; + + g_variant_get (parameters, "(^a&s)", &filenames); +@@ -1427,21 +1425,28 @@ impl_settings_load_connections (NMDBusObject *obj, + return; + + if (filenames) { ++ gsize i; ++ + for (i = 0; filenames[i]; i++) { +- for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { +- NMSettingsPlugin *plugin = NM_SETTINGS_PLUGIN (iter->data); ++ GSList *iter; + +- if (nm_settings_plugin_load_connection (plugin, filenames[i])) +- break; +- } ++ if (filenames[i][0] != '/') ++ _LOGW ("load: connection filename '%s' is not an absolute path", filenames[i]); ++ else { ++ for (iter = priv->plugins; iter; iter = iter->next) { ++ NMSettingsPlugin *plugin = NM_SETTINGS_PLUGIN (iter->data); + +- if (!iter) { +- if (!g_path_is_absolute (filenames[i])) +- _LOGW ("connection filename '%s' is not an absolute path", filenames[i]); +- if (!failures) +- failures = g_ptr_array_new (); +- g_ptr_array_add (failures, (char *) filenames[i]); ++ if (nm_settings_plugin_load_connection (plugin, filenames[i])) ++ goto next_filename; ++ } + } ++ ++ if (!failures) ++ failures = g_ptr_array_new (); ++ g_ptr_array_add (failures, (char *) filenames[i]); ++ ++next_filename: ++ ; + } + } + +-- +2.21.0 + + +From b9123eb59de18ddf30b2cb5eab0f5a0c0eeef345 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Fri, 10 May 2019 14:53:51 +0200 +Subject: [PATCH 2/2] settings/d-bus: fix boolean return value of + "LoadConnections" + +The boolean value is intended to indicate success. It would indicated +failure due to a bug. + +Fixes: 297d4985abcc ('core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API'): +(cherry picked from commit 22e830f0469a654159e71b5bbddb2774bb5342c2) +(cherry picked from commit e73a505866a784b41393ae6082a26ff7389633d3) +--- + src/settings/nm-settings.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c +index 1f8314847..90dd892cb 100644 +--- a/src/settings/nm-settings.c ++++ b/src/settings/nm-settings.c +@@ -1455,7 +1455,7 @@ next_filename: + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(b^as)", +- (gboolean) (!!failures), ++ (gboolean) (!failures), + failures + ? (const char **) failures->pdata + : NM_PTRARRAY_EMPTY (const char *))); +-- +2.21.0 + diff --git a/SOURCES/1006-fix-file-permissions-secret-key-rh1709849.patch b/SOURCES/1006-fix-file-permissions-secret-key-rh1709849.patch new file mode 100644 index 0000000..ad50f90 --- /dev/null +++ b/SOURCES/1006-fix-file-permissions-secret-key-rh1709849.patch @@ -0,0 +1,43 @@ +From a6562097a4d0f35c22c4f0f949012dee918bf510 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Tue, 14 May 2019 13:55:41 +0200 +Subject: [PATCH 1/1] core: fix file permissions for + "/var/lib/NetworkManager/secret_key" + +Ooherwise, the file has wrong permissions: + + # ls -la /var/lib/NetworkManager/secret_key + ----r-xr-x. 1 root root 50 May 14 13:52 /var/lib/NetworkManager/secret_key + +Luckily, /var/lib/NetworkManager should be already + + # ls -lad /var/lib/NetworkManager + drwx------. 2 root root 8192 May 14 13:57 /var/lib/NetworkManager + +which mitigates this a bit. + +Fixes: dbcb1d6d97c6 ('core: let nm_utils_secret_key_read() handle failures internally') + +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/175 +(cherry picked from commit dc3a2f9bc4c35030bcaf9e81953daf7894ab62b6) +(cherry picked from commit 2d46247c6ac6f89a0b8bac86d684431c07dc6c8e) +--- + src/nm-core-utils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c +index b0cc914e7..fd1628027 100644 +--- a/src/nm-core-utils.c ++++ b/src/nm-core-utils.c +@@ -2697,7 +2697,7 @@ _host_id_read (guint8 **out_host_id, + } else if (!nm_utils_file_set_contents (SECRET_KEY_FILE, + (const char *) new_content, + len, +- 0077, ++ 0600, + &error)) { + nm_log_warn (LOGD_CORE, "secret-key: failure to persist secret key in \"%s\" (%s) (use non-persistent key)", + SECRET_KEY_FILE, error->message); +-- +2.21.0 + diff --git a/SOURCES/1007-tc-update-rh1546802.patch b/SOURCES/1007-tc-update-rh1546802.patch new file mode 100644 index 0000000..59c29e3 --- /dev/null +++ b/SOURCES/1007-tc-update-rh1546802.patch @@ -0,0 +1,2449 @@ +From 67047a444d45dd6e74d381cfe06a418c13693539 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Tue, 9 Apr 2019 13:42:52 +0200 +Subject: [PATCH 01/20] tc/qdisc: add support for fq_codel attributes + +(cherry picked from commit 1efe982e39be7e8b7852a19957c7b49cab46e67c) +--- + libnm-core/nm-utils.c | 13 ++++++ + src/devices/nm-device.c | 23 ++++++++++ + src/platform/nm-linux-platform.c | 72 ++++++++++++++++++++++++++++++++ + src/platform/nm-platform.c | 55 ++++++++++++++++++++---- + src/platform/nm-platform.h | 14 +++++++ + 5 files changed, 170 insertions(+), 7 deletions(-) + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index 04d5b1b558..b82c580345 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2309,12 +2309,25 @@ static const NMVariantAttributeSpec * const tc_object_attribute_spec[] = { + NULL, + }; + ++static const NMVariantAttributeSpec * const tc_qdisc_fq_codel_spec[] = { ++ TC_ATTR_SPEC_PTR ("limit", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("flows", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("target", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("interval", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("quantum", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("ce_threshold", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("memory", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("ecn", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), ++ NULL, ++}; ++ + typedef struct { + const char *kind; + const NMVariantAttributeSpec * const *attrs; + } NMQdiscAttributeSpec; + + static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = { ++ &(const NMQdiscAttributeSpec) { "fq_codel", tc_qdisc_fq_codel_spec }, + NULL, + }; + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 60709c50d5..195686707b 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6522,6 +6522,29 @@ tc_commit (NMDevice *self) + qdisc->parent = nm_tc_qdisc_get_parent (s_qdisc); + qdisc->info = 0; + ++#define GET_ATTR(name, dst, variant_type, type, dflt) G_STMT_START { \ ++ GVariant *_variant = nm_tc_qdisc_get_attribute (s_qdisc, ""name""); \ ++ \ ++ if ( _variant \ ++ && g_variant_is_of_type (_variant, G_VARIANT_TYPE_ ## variant_type)) \ ++ (dst) = g_variant_get_ ## type (_variant); \ ++ else \ ++ (dst) = (dflt); \ ++} G_STMT_END ++ ++ if (strcmp (qdisc->kind, "fq_codel") == 0) { ++ GET_ATTR("limit", qdisc->fq_codel.limit, UINT32, uint32, 0); ++ GET_ATTR("flows", qdisc->fq_codel.flows, UINT32, uint32, 0); ++ GET_ATTR("target", qdisc->fq_codel.target, UINT32, uint32, 0); ++ GET_ATTR("interval", qdisc->fq_codel.interval, UINT32, uint32, 0); ++ GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0); ++ GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, -1); ++ GET_ATTR("memory", qdisc->fq_codel.memory, UINT32, uint32, -1); ++ GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE); ++ } ++ ++#undef GET_ADDR ++ + g_ptr_array_add (qdiscs, q); + } + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index d4b0115252..a346d6618c 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -84,6 +84,13 @@ enum { + + /*****************************************************************************/ + ++/* Compat with older kernels. */ ++ ++#define TCA_FQ_CODEL_CE_THRESHOLD 7 ++#define TCA_FQ_CODEL_MEMORY_LIMIT 9 ++ ++/*****************************************************************************/ ++ + #define VLAN_FLAG_MVRP 0x8 + + /*****************************************************************************/ +@@ -3481,6 +3488,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) + { + static const struct nla_policy policy[] = { + [TCA_KIND] = { .type = NLA_STRING }, ++ [TCA_OPTIONS] = { .type = NLA_NESTED }, + }; + struct nlattr *tb[G_N_ELEMENTS (policy)]; + const struct tcmsg *tcm; +@@ -3506,6 +3514,45 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) + obj->qdisc.parent = tcm->tcm_parent; + obj->qdisc.info = tcm->tcm_info; + ++ if (tb[TCA_OPTIONS]) { ++ struct nlattr *options_attr; ++ int remaining; ++ ++ nla_for_each_nested (options_attr, tb[TCA_OPTIONS], remaining) { ++ if (nla_len (options_attr) < sizeof (uint32_t)) ++ continue; ++ ++ if (nm_streq0 (obj->qdisc.kind, "fq_codel")) { ++ switch (nla_type (options_attr)) { ++ case TCA_FQ_CODEL_LIMIT: ++ obj->qdisc.fq_codel.limit = nla_get_u32 (options_attr); ++ break; ++ case TCA_FQ_CODEL_FLOWS: ++ obj->qdisc.fq_codel.flows = nla_get_u32 (options_attr); ++ break; ++ case TCA_FQ_CODEL_TARGET: ++ obj->qdisc.fq_codel.target = nla_get_u32 (options_attr); ++ break; ++ case TCA_FQ_CODEL_INTERVAL: ++ obj->qdisc.fq_codel.interval = nla_get_u32 (options_attr); ++ break; ++ case TCA_FQ_CODEL_QUANTUM: ++ obj->qdisc.fq_codel.quantum = nla_get_u32 (options_attr); ++ break; ++ case TCA_FQ_CODEL_CE_THRESHOLD: ++ obj->qdisc.fq_codel.ce_threshold = nla_get_u32 (options_attr); ++ break; ++ case TCA_FQ_CODEL_MEMORY_LIMIT: ++ obj->qdisc.fq_codel.memory = nla_get_u32 (options_attr); ++ break; ++ case TCA_FQ_CODEL_ECN: ++ obj->qdisc.fq_codel.ecn = nla_get_u32 (options_attr); ++ break; ++ } ++ } ++ } ++ } ++ + return obj; + } + +@@ -4161,6 +4208,7 @@ _nl_msg_new_qdisc (int nlmsg_type, + const NMPlatformQdisc *qdisc) + { + nm_auto_nlmsg struct nl_msg *msg = NULL; ++ struct nlattr *tc_options; + const struct tcmsg tcm = { + .tcm_family = qdisc->addr_family, + .tcm_ifindex = qdisc->ifindex, +@@ -4176,6 +4224,30 @@ _nl_msg_new_qdisc (int nlmsg_type, + + NLA_PUT_STRING (msg, TCA_KIND, qdisc->kind); + ++ if (!(tc_options = nla_nest_start (msg, TCA_OPTIONS))) ++ goto nla_put_failure; ++ ++ if (strcmp (qdisc->kind, "fq_codel") == 0) { ++ if (qdisc->fq_codel.limit) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_LIMIT, qdisc->fq_codel.limit); ++ if (qdisc->fq_codel.flows) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_FLOWS, qdisc->fq_codel.flows); ++ if (qdisc->fq_codel.target) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_TARGET, qdisc->fq_codel.target); ++ if (qdisc->fq_codel.interval) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval); ++ if (qdisc->fq_codel.quantum) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); ++ if (qdisc->fq_codel.ce_threshold != -1) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); ++ if (qdisc->fq_codel.memory != -1) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory); ++ if (qdisc->fq_codel.ecn) ++ NLA_PUT_S32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); ++ } ++ ++ nla_nest_end (msg, tc_options); ++ + return g_steal_pointer (&msg); + + nla_put_failure: +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index 1fc0ccb750..3d78902860 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -6430,13 +6430,32 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) + if (!nm_utils_to_string_buffer_init_null (qdisc, &buf, &len)) + return buf; + +- g_snprintf (buf, len, "%s%s family %d handle %x parent %x info %x", +- qdisc->kind, +- _to_string_dev (NULL, qdisc->ifindex, str_dev, sizeof (str_dev)), +- qdisc->addr_family, +- qdisc->handle, +- qdisc->parent, +- qdisc->info); ++ nm_utils_strbuf_append (&buf, &len, "%s%s family %u handle %x parent %x info %x", ++ qdisc->kind, ++ _to_string_dev (NULL, qdisc->ifindex, str_dev, sizeof (str_dev)), ++ qdisc->addr_family, ++ qdisc->handle, ++ qdisc->parent, ++ qdisc->info); ++ ++ if (nm_streq0 (qdisc->kind, "fq_codel")) { ++ if (qdisc->fq_codel.limit) ++ nm_utils_strbuf_append (&buf, &len, " limit %u", qdisc->fq_codel.limit); ++ if (qdisc->fq_codel.flows) ++ nm_utils_strbuf_append (&buf, &len, " flows %u", qdisc->fq_codel.flows); ++ if (qdisc->fq_codel.target) ++ nm_utils_strbuf_append (&buf, &len, " target %u", qdisc->fq_codel.target); ++ if (qdisc->fq_codel.interval) ++ nm_utils_strbuf_append (&buf, &len, " interval %u", qdisc->fq_codel.interval); ++ if (qdisc->fq_codel.quantum) ++ nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum); ++ if (qdisc->fq_codel.ce_threshold != -1) ++ nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold); ++ if (qdisc->fq_codel.memory != -1) ++ nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory); ++ if (qdisc->fq_codel.ecn) ++ nm_utils_strbuf_append (&buf, &len, " ecn"); ++ } + + return buf; + } +@@ -6451,6 +6470,17 @@ nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h) + obj->handle, + obj->parent, + obj->info); ++ if (nm_streq0 (obj->kind, "fq_codel")) { ++ nm_hash_update_vals (h, ++ obj->fq_codel.limit, ++ obj->fq_codel.flows, ++ obj->fq_codel.target, ++ obj->fq_codel.interval, ++ obj->fq_codel.quantum, ++ obj->fq_codel.ce_threshold, ++ obj->fq_codel.memory, ++ obj->fq_codel.ecn == TRUE); ++ } + } + + int +@@ -6464,6 +6494,17 @@ nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b) + NM_CMP_FIELD (a, b, handle); + NM_CMP_FIELD (a, b, info); + ++ if (nm_streq0 (a->kind, "fq_codel")) { ++ NM_CMP_FIELD (a, b, fq_codel.limit); ++ NM_CMP_FIELD (a, b, fq_codel.flows); ++ NM_CMP_FIELD (a, b, fq_codel.target); ++ NM_CMP_FIELD (a, b, fq_codel.interval); ++ NM_CMP_FIELD (a, b, fq_codel.quantum); ++ NM_CMP_FIELD (a, b, fq_codel.ce_threshold); ++ NM_CMP_FIELD (a, b, fq_codel.memory); ++ NM_CMP_FIELD (a, b, fq_codel.ecn == TRUE); ++ } ++ + return 0; + } + +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index 97be88324e..8742b90555 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -596,6 +596,17 @@ typedef struct { + bool uid_range_has:1; /* has(FRA_UID_RANGE) */ + } NMPlatformRoutingRule; + ++typedef struct { ++ guint32 limit; ++ guint32 flows; ++ guint32 target; ++ guint32 interval; ++ guint32 quantum; ++ guint32 ce_threshold; ++ guint32 memory; ++ bool ecn:1; ++} NMPlatformQdiscFqCodel; ++ + typedef struct { + __NMPlatformObjWithIfindex_COMMON; + const char *kind; +@@ -603,6 +614,9 @@ typedef struct { + guint32 handle; + guint32 parent; + guint32 info; ++ union { ++ NMPlatformQdiscFqCodel fq_codel; ++ }; + } NMPlatformQdisc; + + typedef struct { +-- +2.21.0 + +From 4be7cf71e06da4801d8bb066b977c733e7e7097c Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Tue, 9 Apr 2019 16:23:39 +0200 +Subject: [PATCH 02/20] tc/tfilter: add mirred action + +(cherry picked from commit 900292147d8fd584479a7af0881984c2d77a60bf) +--- + libnm-core/nm-utils.c | 11 +++++++++++ + src/devices/nm-device.c | 29 +++++++++++++++++++++++----- + src/platform/nm-linux-platform.c | 33 ++++++++++++++++++++++++++++++++ + src/platform/nm-platform.c | 29 +++++++++++++++++++++++++--- + src/platform/nm-platform.h | 10 ++++++++++ + 5 files changed, 104 insertions(+), 8 deletions(-) + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index b82c580345..3af3e04ed9 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2542,6 +2542,15 @@ static const NMVariantAttributeSpec * const tc_action_simple_attribute_spec[] = + NULL, + }; + ++static const NMVariantAttributeSpec * const tc_action_mirred_attribute_spec[] = { ++ TC_ATTR_SPEC_PTR ("egress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("ingress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("mirror", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("redirect", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), ++ TC_ATTR_SPEC_PTR ("dev", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ), ++ NULL, ++}; ++ + static const NMVariantAttributeSpec * const tc_action_attribute_spec[] = { + TC_ATTR_SPEC_PTR ("kind", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ), + TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ), +@@ -2636,6 +2645,8 @@ nm_utils_tc_action_from_str (const char *str, GError **error) + kind = g_variant_get_string (variant, NULL); + if (strcmp (kind, "simple") == 0) + attrs = tc_action_simple_attribute_spec; ++ else if (strcmp (kind, "mirred") == 0) ++ attrs = tc_action_mirred_attribute_spec; + else + attrs = NULL; + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 195686707b..ea6ad7e2ad 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6566,16 +6566,35 @@ tc_commit (NMDevice *self) + + action = nm_tc_tfilter_get_action (s_tfilter); + if (action) { ++ GVariant *var; ++ + tfilter->action.kind = nm_tc_action_get_kind (action); + if (strcmp (tfilter->action.kind, "simple") == 0) { +- GVariant *sdata; +- +- sdata = nm_tc_action_get_attribute (action, "sdata"); +- if (sdata && g_variant_is_of_type (sdata, G_VARIANT_TYPE_BYTESTRING)) { ++ var = nm_tc_action_get_attribute (action, "sdata"); ++ if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_BYTESTRING)) { + g_strlcpy (tfilter->action.simple.sdata, +- g_variant_get_bytestring (sdata), ++ g_variant_get_bytestring (var), + sizeof (tfilter->action.simple.sdata)); + } ++ } else if (strcmp (tfilter->action.kind, "mirred") == 0) { ++ if (nm_tc_action_get_attribute (action, "egress")) ++ tfilter->action.mirred.egress = TRUE; ++ ++ if (nm_tc_action_get_attribute (action, "ingress")) ++ tfilter->action.mirred.ingress = TRUE; ++ ++ if (nm_tc_action_get_attribute (action, "mirror")) ++ tfilter->action.mirred.mirror = TRUE; ++ ++ if (nm_tc_action_get_attribute (action, "redirect")) ++ tfilter->action.mirred.redirect = TRUE; ++ ++ var = nm_tc_action_get_attribute (action, "dev"); ++ if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_STRING)) { ++ int ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (self), ++ g_variant_get_string (var, NULL)); ++ tfilter->action.mirred.ifindex = ifindex; ++ } + } + } + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index a346d6618c..6064d89eb6 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -4275,6 +4276,36 @@ nla_put_failure: + return FALSE; + } + ++static gboolean ++_add_action_mirred (struct nl_msg *msg, ++ const NMPlatformActionMirred *mirred) ++{ ++ struct nlattr *act_options; ++ struct tc_mirred sel = { 0, }; ++ ++ if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS))) ++ goto nla_put_failure; ++ ++ if (mirred->egress && mirred->redirect) ++ sel.eaction = TCA_EGRESS_REDIR; ++ else if (mirred->egress && mirred->mirror) ++ sel.eaction = TCA_EGRESS_MIRROR; ++ else if (mirred->ingress && mirred->redirect) ++ sel.eaction = TCA_INGRESS_REDIR; ++ else if (mirred->ingress && mirred->mirror) ++ sel.eaction = TCA_INGRESS_MIRROR; ++ sel.ifindex = mirred->ifindex; ++ ++ NLA_PUT (msg, TCA_MIRRED_PARMS, sizeof (sel), &sel); ++ ++ nla_nest_end (msg, act_options); ++ ++ return TRUE; ++ ++nla_put_failure: ++ return FALSE; ++} ++ + static gboolean + _add_action (struct nl_msg *msg, + const NMPlatformAction *action) +@@ -4290,6 +4321,8 @@ _add_action (struct nl_msg *msg, + + if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) + _add_action_simple (msg, &action->simple); ++ else if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_MIRRED)) ++ _add_action_mirred (msg, &action->mirred); + + nla_nest_end (msg, prio); + +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index 3d78902860..6f23ddb589 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + + #include "nm-utils.h" +@@ -6533,11 +6534,18 @@ nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsiz + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL + | NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII, + &t)); ++ } else if (nm_streq (tfilter->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { ++ nm_utils_strbuf_append (&p, &l, "%s%s%s%s dev %d", ++ tfilter->action.mirred.ingress ? " ingress" : "", ++ tfilter->action.mirred.egress ? " egress" : "", ++ tfilter->action.mirred.mirror ? " mirror" : "", ++ tfilter->action.mirred.redirect ? " redirect" : "", ++ tfilter->action.mirred.ifindex); + } + } else + act_buf[0] = '\0'; + +- g_snprintf (buf, len, "%s%s family %d handle %x parent %x info %x%s", ++ g_snprintf (buf, len, "%s%s family %u handle %x parent %x info %x%s", + tfilter->kind, + _to_string_dev (NULL, tfilter->ifindex, str_dev, sizeof (str_dev)), + tfilter->addr_family, +@@ -6561,8 +6569,16 @@ nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h) + obj->info); + if (obj->action.kind) { + nm_hash_update_str (h, obj->action.kind); +- if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) ++ if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { + nm_hash_update_strarr (h, obj->action.simple.sdata); ++ } else if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { ++ nm_hash_update_vals (h, ++ obj->action.mirred.ingress, ++ obj->action.mirred.egress, ++ obj->action.mirred.mirror, ++ obj->action.mirred.redirect, ++ obj->action.mirred.ifindex); ++ } + } + } + +@@ -6579,8 +6595,15 @@ nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b) + + NM_CMP_FIELD_STR_INTERNED (a, b, action.kind); + if (a->action.kind) { +- if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) ++ if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { + NM_CMP_FIELD_STR (a, b, action.simple.sdata); ++ } else if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { ++ NM_CMP_FIELD (a, b, action.mirred.ingress); ++ NM_CMP_FIELD (a, b, action.mirred.egress); ++ NM_CMP_FIELD (a, b, action.mirred.mirror); ++ NM_CMP_FIELD (a, b, action.mirred.redirect); ++ NM_CMP_FIELD (a, b, action.mirred.ifindex); ++ } + } + + return 0; +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index 8742b90555..16747f093b 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -623,14 +623,24 @@ typedef struct { + char sdata[32]; + } NMPlatformActionSimple; + ++typedef struct { ++ gboolean egress; ++ gboolean ingress; ++ gboolean mirror; ++ gboolean redirect; ++ int ifindex; ++} NMPlatformActionMirred; ++ + typedef struct { + const char *kind; + union { + NMPlatformActionSimple simple; ++ NMPlatformActionMirred mirred; + }; + } NMPlatformAction; + + #define NM_PLATFORM_ACTION_KIND_SIMPLE "simple" ++#define NM_PLATFORM_ACTION_KIND_MIRRED "mirred" + + typedef struct { + __NMPlatformObjWithIfindex_COMMON; +-- +2.21.0 + +From 84bd35e4fadf0aa8244b2c683c60fdfc4b87cf6f Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 11:36:02 +0200 +Subject: [PATCH 03/20] shared: use nm_str_skip_leading_spaces() in + _nm_utils_ascii_str_to_int64() + +(cherry picked from commit 9d2623cceb8550fbe6becf5dde2e0cef152e1086) +--- + shared/nm-glib-aux/nm-shared-utils.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c +index cf08a77fde..fb945ef9fb 100644 +--- a/shared/nm-glib-aux/nm-shared-utils.c ++++ b/shared/nm-glib-aux/nm-shared-utils.c +@@ -734,10 +734,7 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma + gint64 v; + const char *s = NULL; + +- if (str) { +- while (g_ascii_isspace (str[0])) +- str++; +- } ++ str = nm_str_skip_leading_spaces (str); + if (!str || !str[0]) { + errno = EINVAL; + return fallback; +@@ -748,9 +745,9 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma + + if (errno != 0) + return fallback; ++ + if (s[0] != '\0') { +- while (g_ascii_isspace (s[0])) +- s++; ++ s = nm_str_skip_leading_spaces (s); + if (s[0] != '\0') { + errno = EINVAL; + return fallback; +-- +2.21.0 + +From 13e3bd4161d11c81cd4188a733c6d370d41452c3 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 10:49:16 +0200 +Subject: [PATCH 04/20] libnm/tests: add test for _nm_utils_parse_tc_handle() + +(cherry picked from commit fac95d0062d9bbe256b8e479ba7cb452cbac340e) +--- + libnm-core/tests/test-setting.c | 56 +++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c +index 03100a039b..7587b65ba7 100644 +--- a/libnm-core/tests/test-setting.c ++++ b/libnm-core/tests/test-setting.c +@@ -2979,6 +2979,60 @@ test_routing_rule (gconstpointer test_data) + + /*****************************************************************************/ + ++static void ++test_parse_tc_handle (void) ++{ ++#define _parse_tc_handle(str, exp) \ ++ G_STMT_START { \ ++ gs_free_error GError *_error = NULL; \ ++ GError **_perror = nmtst_get_rand_bool () ? &_error : NULL; \ ++ guint32 _v; \ ++ const guint32 _v_exp = (exp); \ ++ \ ++ _v = _nm_utils_parse_tc_handle (""str"", _perror); \ ++ \ ++ if (_v != _v_exp) \ ++ g_error ("%s:%d: \"%s\" gave %08x but %08x expected.", __FILE__, __LINE__, ""str"", _v, _v_exp); \ ++ \ ++ if (_v == TC_H_UNSPEC) \ ++ g_assert (!_perror || *_perror); \ ++ else \ ++ g_assert (!_perror || !*_perror); \ ++ \ ++ } G_STMT_END ++ ++#define _parse_tc_handle_inval(str) _parse_tc_handle (str, TC_H_UNSPEC) ++#define _parse_tc_handle_valid(str, maj, min) _parse_tc_handle (str, TC_H_MAKE (((guint32) (maj)) << 16, ((guint16) (min)))) ++ ++ _parse_tc_handle_inval (""); ++ _parse_tc_handle_inval (" "); ++ _parse_tc_handle_inval (" \n"); ++ _parse_tc_handle_valid ("1", 1, 0); ++ _parse_tc_handle_inval(" 1 "); ++ _parse_tc_handle_valid ("1:", 1, 0); ++ _parse_tc_handle_inval ("1: "); ++ _parse_tc_handle_valid ("1:0", 1, 0); ++ _parse_tc_handle_inval ("1 :0"); ++ _parse_tc_handle_inval ("1 \t\n\f\r:0"); ++ _parse_tc_handle_inval ("1 \t\n\f\r\v:0"); ++ _parse_tc_handle_inval (" 1 : 0 "); ++ _parse_tc_handle_valid (" \t\v\n1: 0", 1, 0); ++ _parse_tc_handle_valid ("1:2", 1, 2); ++ _parse_tc_handle_valid ("01:02", 1, 2); ++ _parse_tc_handle_valid ("0x01:0x02", 1, 2); ++ _parse_tc_handle_valid (" 01: 02", 1, 2); ++ _parse_tc_handle_valid ("019: 020", 0x19, 0x20); ++ _parse_tc_handle_valid ("FFFF: 020", 0xFFFF, 0x20); ++ _parse_tc_handle_valid ("FfFF: ffff", 0xFFFF, 0xFFFF); ++ _parse_tc_handle_valid ("FFFF", 0xFFFF, 0); ++ _parse_tc_handle_valid ("0xFFFF", 0xFFFF, 0); ++ _parse_tc_handle_inval ("10000"); ++ _parse_tc_handle_valid ("\t\n\f\r FFFF", 0xFFFF, 0); ++ _parse_tc_handle_valid ("\t\n\f\r \vFFFF", 0xFFFF, 0); ++} ++ ++/*****************************************************************************/ ++ + NMTST_DEFINE (); + + int +@@ -3064,5 +3118,7 @@ main (int argc, char **argv) + + g_test_add_data_func ("/libnm/settings/routing-rule/1", GINT_TO_POINTER (0), test_routing_rule); + ++ g_test_add_func ("/libnm/parse-tc-handle", test_parse_tc_handle); ++ + return g_test_run (); + } +-- +2.21.0 + +From b954ddc2752285b28885398441879edb922c68fc Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 10:27:32 +0200 +Subject: [PATCH 05/20] libnm: cleanup _nm_utils_parse_tc_handle() + +- g_ascii_strtoll() accepts leading spaces, but it leaves + the end pointer at the first space after the digit. That means, + we accepted "1: 0" but not "1 :0". We should either consistently + accept spaces around the digits/colon or reject it. + +- g_ascii_strtoll() accepts "\v" as a space (just like `man 3 isspace` + comments that "\v" is a space in C and POSIX locale. + For some reasons (unknown to me) g_ascii_isspace() does not treat + "\v" as space. And neither does NM_ASCII_SPACES and + nm_str_skip_leading_spaces(). + We should be consistent about what we consider spaces and what not. + It's already odd to accept '\n' as spaces here, but well, lets do + it for the sake of consistency (so that it matches with our + understanding of ASCII spaces, albeit not POSIX's). + +- don't use bogus error domains in "g_set_error (error, 1, 0, ..." + That is a bug and we have NM_UTILS_ERROR exactly for error instances + with unspecified domain and code. + +- as before, accept a trailing ":" with omitted minor number. + +- reject all unexpected characters. strtoll() accepts '+' / '-' + and a "0x" prefix of the numbers (and leading POSIX spaces). Be + strict here and only accepts NM_ASCII_SPACES, ':', and hexdigits. + In particular, don't accept the "0x" prefix. + +This parsing would be significantly simpler to implement, if we could +just strdup() the string, split the string at the colon delimiter and +use _nm_utils_ascii_str_to_int64() which gets leading/trailing spaces +right. But let's save the "overhead" of an additional alloc. + +(cherry picked from commit cc9f07167607124bcb0df735034858aadfdb8541) +--- + libnm-core/nm-utils.c | 43 ++++++++++++++++++++++++--------- + libnm-core/tests/test-setting.c | 18 +++++++------- + 2 files changed, 41 insertions(+), 20 deletions(-) + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index 3af3e04ed9..7a7c6de114 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2280,21 +2280,42 @@ _nm_utils_string_append_tc_parent (GString *string, const char *prefix, guint32 + guint32 + _nm_utils_parse_tc_handle (const char *str, GError **error) + { +- gint64 maj, min; +- char *sep; ++ gint64 maj; ++ gint64 min = 0; ++ const char *sep; + +- maj = g_ascii_strtoll (str, &sep, 0x10); +- if (*sep == ':') +- min = g_ascii_strtoll (&sep[1], &sep, 0x10); +- else +- min = 0; ++ nm_assert (str); + +- if (*sep != '\0' || maj <= 0 || maj > 0xffff || min < 0 || min > 0xffff) { +- g_set_error (error, 1, 0, _("'%s' is not a valid handle."), str); +- return TC_H_UNSPEC; ++ maj = g_ascii_strtoll (str, (char **) &sep, 0x10); ++ if (sep == str) ++ goto fail; ++ ++ sep = nm_str_skip_leading_spaces (sep); ++ ++ if (sep[0] == ':') { ++ const char *str2 = &sep[1]; ++ ++ min = g_ascii_strtoll (str2, (char **) &sep, 0x10); ++ sep = nm_str_skip_leading_spaces (sep); ++ if (sep[0] != '\0') ++ goto fail; ++ } else if (sep[0] != '\0') ++ goto fail; ++ ++ if ( maj <= 0 ++ || maj > 0xffff ++ || min < 0 ++ || min > 0xffff ++ || !NM_STRCHAR_ALL (str, ch, ( g_ascii_isxdigit (ch) ++ || ch == ':' ++ || g_ascii_isspace (ch)))) { ++ goto fail; + } + +- return TC_H_MAKE (maj << 16, min); ++ return TC_H_MAKE (((guint32) maj) << 16, (guint32) min); ++fail: ++ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, _("'%s' is not a valid handle."), str); ++ return TC_H_UNSPEC; + } + + #define TC_ATTR_SPEC_PTR(name, type, no_value, consumes_rest, str_type) \ +diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c +index 7587b65ba7..5c9c614fb5 100644 +--- a/libnm-core/tests/test-setting.c ++++ b/libnm-core/tests/test-setting.c +@@ -3008,27 +3008,27 @@ test_parse_tc_handle (void) + _parse_tc_handle_inval (" "); + _parse_tc_handle_inval (" \n"); + _parse_tc_handle_valid ("1", 1, 0); +- _parse_tc_handle_inval(" 1 "); ++ _parse_tc_handle_valid(" 1 ", 1, 0); + _parse_tc_handle_valid ("1:", 1, 0); +- _parse_tc_handle_inval ("1: "); ++ _parse_tc_handle_valid ("1: ", 1, 0); + _parse_tc_handle_valid ("1:0", 1, 0); +- _parse_tc_handle_inval ("1 :0"); +- _parse_tc_handle_inval ("1 \t\n\f\r:0"); ++ _parse_tc_handle_valid ("1 :0", 1, 0); ++ _parse_tc_handle_valid ("1 \t\n\f\r:0", 1, 0); + _parse_tc_handle_inval ("1 \t\n\f\r\v:0"); +- _parse_tc_handle_inval (" 1 : 0 "); +- _parse_tc_handle_valid (" \t\v\n1: 0", 1, 0); ++ _parse_tc_handle_valid (" 1 : 0 ", 1, 0); ++ _parse_tc_handle_inval (" \t\v\n1: 0"); + _parse_tc_handle_valid ("1:2", 1, 2); + _parse_tc_handle_valid ("01:02", 1, 2); +- _parse_tc_handle_valid ("0x01:0x02", 1, 2); ++ _parse_tc_handle_inval ("0x01:0x02"); + _parse_tc_handle_valid (" 01: 02", 1, 2); + _parse_tc_handle_valid ("019: 020", 0x19, 0x20); + _parse_tc_handle_valid ("FFFF: 020", 0xFFFF, 0x20); + _parse_tc_handle_valid ("FfFF: ffff", 0xFFFF, 0xFFFF); + _parse_tc_handle_valid ("FFFF", 0xFFFF, 0); +- _parse_tc_handle_valid ("0xFFFF", 0xFFFF, 0); ++ _parse_tc_handle_inval ("0xFFFF"); + _parse_tc_handle_inval ("10000"); + _parse_tc_handle_valid ("\t\n\f\r FFFF", 0xFFFF, 0); +- _parse_tc_handle_valid ("\t\n\f\r \vFFFF", 0xFFFF, 0); ++ _parse_tc_handle_inval ("\t\n\f\r \vFFFF"); + } + + /*****************************************************************************/ +-- +2.21.0 + +From fde9250cdc664b557a80a517f57929a36597094a Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 11:53:13 +0200 +Subject: [PATCH 06/20] libnm: mark NMVariantAttributeSpec pointers as const + +This actually allows the compiler/linker to mark the memory as read-only and any +modification will cause a segmentation fault. + +I would also think that it allows the compiler to put the structure directly +beside the outer constant array (in which this pointer is embedded). That is good +locality-wise. + +(cherry picked from commit 4e3955e6ddf02d5ea32012bd563aa02fece5c0ef) +--- + libnm-core/nm-setting-ip-config.c | 2 +- + libnm-core/nm-setting-sriov.c | 2 +- + libnm-core/nm-utils.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c +index f362945f41..26fbc8849f 100644 +--- a/libnm-core/nm-setting-ip-config.c ++++ b/libnm-core/nm-setting-ip-config.c +@@ -1213,7 +1213,7 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value) + } + + #define ATTR_SPEC_PTR(name, type, v4, v6, str_type) \ +- &(NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type } ++ &((const NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type }) + + static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = { + ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), +diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c +index b662ca2cf6..9a47d141d2 100644 +--- a/libnm-core/nm-setting-sriov.c ++++ b/libnm-core/nm-setting-sriov.c +@@ -366,7 +366,7 @@ nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name) + } + + #define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \ +- &(NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type } ++ &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type }) + + const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = { + SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, 'm'), +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index 7a7c6de114..7df63b83bb 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2319,7 +2319,7 @@ fail: + } + + #define TC_ATTR_SPEC_PTR(name, type, no_value, consumes_rest, str_type) \ +- &(NMVariantAttributeSpec) { name, type, FALSE, FALSE, no_value, consumes_rest, str_type } ++ &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, no_value, consumes_rest, str_type }) + + static const NMVariantAttributeSpec * const tc_object_attribute_spec[] = { + TC_ATTR_SPEC_PTR ("root", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), +-- +2.21.0 + +From 38cf36022ef0bb678daf4d2e70da82c96185b310 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 11:56:29 +0200 +Subject: [PATCH 07/20] libnm: use macro and designated initializers for + NMVariantAttributeSpec + +I think initializing structs should (almost) be always done with designated +initializers, because otherwise it's easy to get the order wrong. The +problem is that otherwise the order of fields gets additional meaning +not only for the memory layout, but also for the code that initialize +the structs. + +Add a macro NM_VARIANT_ATTRIBUTE_SPEC_DEFINE() that replaces the other +(duplicate) macros. This macro also gets it right to mark the struct as +const. + +(cherry picked from commit 86dc50d4760b77f30f3d29c5fa46ea32b06d73f8) +--- + libnm-core/nm-setting-ip-config.c | 35 ++++++++-------- + libnm-core/nm-setting-sriov.c | 17 ++++---- + libnm-core/nm-utils-private.h | 7 ++++ + libnm-core/nm-utils.c | 67 +++++++++++++++---------------- + 4 files changed, 62 insertions(+), 64 deletions(-) + +diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c +index 26fbc8849f..375c309dd6 100644 +--- a/libnm-core/nm-setting-ip-config.c ++++ b/libnm-core/nm-setting-ip-config.c +@@ -1212,25 +1212,22 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value) + g_hash_table_remove (route->attributes, name); + } + +-#define ATTR_SPEC_PTR(name, type, v4, v6, str_type) \ +- &((const NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type }) +- +-static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = { +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), +- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), ++static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'a', ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, .v6 = TRUE, .str_type = 'p', ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ), + NULL, + }; + +diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c +index 9a47d141d2..0625331e3f 100644 +--- a/libnm-core/nm-setting-sriov.c ++++ b/libnm-core/nm-setting-sriov.c +@@ -365,17 +365,14 @@ nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name) + return g_hash_table_lookup (vf->attributes, name); + } + +-#define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \ +- &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type }) +- +-const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = { +- SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, 'm'), +- SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, 0), +- SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, 0), +- SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, 0), +- SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, 0), ++const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, .str_type = 'm', ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, ), + /* D-Bus only, synthetic attributes */ +- SRIOV_ATTR_SPEC_PTR ("vlans", G_VARIANT_TYPE_STRING, 'd'), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("vlans", G_VARIANT_TYPE_STRING, .str_type = 'd', ), + NULL, + }; + +diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h +index a1a1369a39..1b9b888773 100644 +--- a/libnm-core/nm-utils-private.h ++++ b/libnm-core/nm-utils-private.h +@@ -38,6 +38,13 @@ struct _NMVariantAttributeSpec { + char str_type; + }; + ++#define NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(_name, _type, ...) \ ++ (&((const NMVariantAttributeSpec) { \ ++ .name = _name, \ ++ .type = _type, \ ++ __VA_ARGS__ \ ++ })) ++ + gboolean _nm_utils_string_slist_validate (GSList *list, + const char **valid_values); + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index 7df63b83bb..7cf482d3de 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2318,33 +2318,30 @@ fail: + return TC_H_UNSPEC; + } + +-#define TC_ATTR_SPEC_PTR(name, type, no_value, consumes_rest, str_type) \ +- &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, no_value, consumes_rest, str_type }) +- +-static const NMVariantAttributeSpec * const tc_object_attribute_spec[] = { +- TC_ATTR_SPEC_PTR ("root", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("parent", G_VARIANT_TYPE_STRING, FALSE, FALSE, 'a' ), +- TC_ATTR_SPEC_PTR ("handle", G_VARIANT_TYPE_STRING, FALSE, FALSE, 'a' ), +- TC_ATTR_SPEC_PTR ("kind", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ), +- TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ), ++static const NMVariantAttributeSpec *const tc_object_attribute_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("root", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("parent", G_VARIANT_TYPE_STRING, .str_type = 'a', ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("handle", G_VARIANT_TYPE_STRING, .str_type = 'a', ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ), + NULL, + }; + +-static const NMVariantAttributeSpec * const tc_qdisc_fq_codel_spec[] = { +- TC_ATTR_SPEC_PTR ("limit", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("flows", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("target", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("interval", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("quantum", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("ce_threshold", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("memory", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("ecn", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), ++static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("limit", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("flows", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("target", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("interval", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("quantum", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ce_threshold", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("memory", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NULL, + }; + + typedef struct { + const char *kind; +- const NMVariantAttributeSpec * const *attrs; ++ const NMVariantAttributeSpec *const *attrs; + } NMQdiscAttributeSpec; + + static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = { +@@ -2558,23 +2555,23 @@ nm_utils_tc_qdisc_from_str (const char *str, GError **error) + + /*****************************************************************************/ + +-static const NMVariantAttributeSpec * const tc_action_simple_attribute_spec[] = { +- TC_ATTR_SPEC_PTR ("sdata", G_VARIANT_TYPE_BYTESTRING, FALSE, FALSE, 0 ), ++static const NMVariantAttributeSpec *const tc_action_simple_attribute_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("sdata", G_VARIANT_TYPE_BYTESTRING, ), + NULL, + }; + +-static const NMVariantAttributeSpec * const tc_action_mirred_attribute_spec[] = { +- TC_ATTR_SPEC_PTR ("egress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("ingress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("mirror", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("redirect", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("dev", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ), ++static const NMVariantAttributeSpec *const tc_action_mirred_attribute_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("egress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ingress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("mirror", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("redirect", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("dev", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ), + NULL, + }; + +-static const NMVariantAttributeSpec * const tc_action_attribute_spec[] = { +- TC_ATTR_SPEC_PTR ("kind", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ), +- TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ), ++static const NMVariantAttributeSpec *const tc_action_attribute_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ), + NULL, + }; + +@@ -2643,7 +2640,7 @@ nm_utils_tc_action_from_str (const char *str, GError **error) + gs_unref_hashtable GHashTable *ht = NULL; + gs_unref_hashtable GHashTable *options = NULL; + GVariant *variant; +- const NMVariantAttributeSpec * const *attrs; ++ const NMVariantAttributeSpec *const *attrs; + + nm_assert (str); + nm_assert (!error || !*error); +@@ -2771,9 +2768,9 @@ nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error) + return g_string_free (string, FALSE); + } + +-static const NMVariantAttributeSpec * const tc_tfilter_attribute_spec[] = { +- TC_ATTR_SPEC_PTR ("action", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), +- TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ), ++static const NMVariantAttributeSpec *const tc_tfilter_attribute_spec[] = { ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("action", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ), + NULL, + }; + +@@ -6460,7 +6457,7 @@ nm_utils_parse_variant_attributes (const char *string, + gs_unref_hashtable GHashTable *ht = NULL; + const char *ptr = string, *start = NULL, *sep; + GVariant *variant; +- const NMVariantAttributeSpec * const *s; ++ const NMVariantAttributeSpec *const *s; + + g_return_val_if_fail (string, NULL); + g_return_val_if_fail (attr_separator, NULL); +-- +2.21.0 + +From 73fdcd38f16eb759de395de8680c994a742fbe1c Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 08:52:54 +0200 +Subject: [PATCH 08/20] device: fix type of loop variable in tc_commit() + +nqdiscs and ntfilters are unsigned integers. The loop variable must agree in +range and signedness. + +(cherry picked from commit 438855e915c328867b7802b14ebef47d7f946ca8) +--- + src/devices/nm-device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index ea6ad7e2ad..e07798094f 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6496,7 +6496,7 @@ tc_commit (NMDevice *self) + NMSettingTCConfig *s_tc = NULL; + int ip_ifindex; + guint nqdiscs, ntfilters; +- int i; ++ guint i; + + connection = nm_device_get_applied_connection (self); + if (connection) +-- +2.21.0 + +From 366d3af00960803c973a307a6bd7ffeedd9c1520 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 08:10:47 +0200 +Subject: [PATCH 09/20] platform: use NM_CMP_FIELD_UNSAFE() for comparing + bitfield in nm_platform_qdisc_cmp() + +"NM_CMP_FIELD (a, b, fq_codel.ecn == TRUE)" is quite a hack as it relies on +the implementation of the macro in a particular way. The problem is, that +NM_CMP_FIELD() uses typeof() which cannot be used with bitfields. So, the +nicer solution is to use NM_CMP_FIELD_UNSAFE() which exists exactly for bitfields +(it's "unsafe", because it evaluates arguments more than once as it avoids +the temporary variable with typeof()). + +Same with nm_hash_update_vals() which uses typeof() to avoid evaluating +arguments more than once. But that again does not work with bitfields. +The "proper" way is to use NM_HASH_COMBINE_BOOLS(). + +(cherry picked from commit 47d8bee1130c619a41fe64753d88d88012f9fb98) +--- + src/platform/nm-platform.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index 6f23ddb589..f8cf0b8999 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -6480,7 +6480,8 @@ nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h) + obj->fq_codel.quantum, + obj->fq_codel.ce_threshold, + obj->fq_codel.memory, +- obj->fq_codel.ecn == TRUE); ++ NM_HASH_COMBINE_BOOLS (guint8, ++ obj->fq_codel.ecn)); + } + } + +@@ -6503,7 +6504,7 @@ nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b) + NM_CMP_FIELD (a, b, fq_codel.quantum); + NM_CMP_FIELD (a, b, fq_codel.ce_threshold); + NM_CMP_FIELD (a, b, fq_codel.memory); +- NM_CMP_FIELD (a, b, fq_codel.ecn == TRUE); ++ NM_CMP_FIELD_UNSAFE (a, b, fq_codel.ecn); + } + + return 0; +-- +2.21.0 + +From ef2b660bb8cb2c30faf55c51a411e8a757707076 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 08:20:42 +0200 +Subject: [PATCH 10/20] platform: use u32 netlink type for TCA_FQ_CODEL_ECN + +In practice, there is no difference when representing 0 or 1 as signed/unsigned 32 +bit integer. But still use the correct type that also kernel uses. + +Also, the implicit conversation from uint32 to bool was correct already. +Still, explicitly convert the uint32 value to boolean in _new_from_nl_qdisc(). +It's no change in behavior. + +(cherry picked from commit a1099a1fab661a430fa8e8015369b536c806433e) +--- + src/platform/nm-linux-platform.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index 6064d89eb6..1428778e03 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -3547,7 +3547,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) + obj->qdisc.fq_codel.memory = nla_get_u32 (options_attr); + break; + case TCA_FQ_CODEL_ECN: +- obj->qdisc.fq_codel.ecn = nla_get_u32 (options_attr); ++ obj->qdisc.fq_codel.ecn = !!nla_get_u32 (options_attr); + break; + } + } +@@ -4244,7 +4244,7 @@ _nl_msg_new_qdisc (int nlmsg_type, + if (qdisc->fq_codel.memory != -1) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory); + if (qdisc->fq_codel.ecn) +- NLA_PUT_S32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); + } + + nla_nest_end (msg, tc_options); +-- +2.21.0 + +From dd3ca10284f9f7f95b1f313a3aa678f2aef01b3f Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 08:23:00 +0200 +Subject: [PATCH 11/20] platform: fix nm_platform_qdisc_to_string() + +When using nm_utils_strbuf_*() API, the buffer gets always moved to the current +end. We must thus remember and return the original start of the buffer. + +(cherry picked from commit b658e3da0825cf6e62e0850d3508dde1dd5c1914) +--- + src/platform/nm-platform.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index f8cf0b8999..4d3b61405d 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -6427,10 +6427,13 @@ const char * + nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) + { + char str_dev[TO_STRING_DEV_BUF_SIZE]; ++ const char *buf0; + + if (!nm_utils_to_string_buffer_init_null (qdisc, &buf, &len)) + return buf; + ++ buf0 = buf; ++ + nm_utils_strbuf_append (&buf, &len, "%s%s family %u handle %x parent %x info %x", + qdisc->kind, + _to_string_dev (NULL, qdisc->ifindex, str_dev, sizeof (str_dev)), +@@ -6458,7 +6461,7 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) + nm_utils_strbuf_append (&buf, &len, " ecn"); + } + +- return buf; ++ return buf0; + } + + void +-- +2.21.0 + +From 509a1bc5f2e52f6d639b75a0467b584c08a90463 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 08:43:31 +0200 +Subject: [PATCH 12/20] platform: fix handling of fq_codel's memory limit + default value + +The memory-limit is an unsigned integer. It is ugly (if not wrong) to compare unsigned +values with "-1". When comparing with the default value we must also use an u32 type. +Instead add a define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET. + +Note that like iproute2 we treat NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET +to indicate to not set TCA_FQ_CODEL_MEMORY_LIMIT in RTM_NEWQDISC. This +special value is entirely internal to NetworkManager (or iproute2) and +kernel will then choose a default memory limit (of 32MB). So setting +NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET means to leave it to kernel to +choose a value (which then chooses 32MB). + +See kernel's net/sched/sch_fq_codel.c: + + static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + { + ... + q->memory_limit = 32 << 20; /* 32 MBytes */ + + static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + ... + if (tb[TCA_FQ_CODEL_MEMORY_LIMIT]) + q->memory_limit = min(1U << 31, nla_get_u32(tb[TCA_FQ_CODEL_MEMORY_LIMIT])); + +Note that not having zero as default value is problematic. In fields like +"NMPlatformIP4Route.table_coerced" and "NMPlatformRoutingRule.suppress_prefixlen_inverse" +we avoid this problem by storing a coerced value in the structure so that zero is still +the default. We don't do that here for memory-limit, so the caller must always explicitly +set the value. + +(cherry picked from commit 46a904389bf13a2cfd40888ab2a843827fda7469) +--- + libnm-core/nm-utils.c | 5 +++++ + src/devices/nm-device.c | 2 +- + src/platform/nm-linux-platform.c | 5 ++++- + src/platform/nm-platform.c | 2 +- + src/platform/nm-platform.h | 9 ++++++++- + 5 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index 7cf482d3de..2e66e6ae2d 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2334,7 +2334,12 @@ static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("interval", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("quantum", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ce_threshold", G_VARIANT_TYPE_UINT32, ), ++ ++ /* kernel clamps the value at 2^31. Possibly such values should be rejected from configuration ++ * as they cannot be configured. Leaving the attribute unspecified causes kernel to choose ++ * a default (currently 32MB). */ + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("memory", G_VARIANT_TYPE_UINT32, ), ++ + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NULL, + }; +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index e07798094f..ce50d5b73d 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6539,7 +6539,7 @@ tc_commit (NMDevice *self) + GET_ATTR("interval", qdisc->fq_codel.interval, UINT32, uint32, 0); + GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0); + GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, -1); +- GET_ATTR("memory", qdisc->fq_codel.memory, UINT32, uint32, -1); ++ GET_ATTR("memory", qdisc->fq_codel.memory, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET); + GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE); + } + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index 1428778e03..cec5fb9431 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -3515,6 +3515,9 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) + obj->qdisc.parent = tcm->tcm_parent; + obj->qdisc.info = tcm->tcm_info; + ++ if (nm_streq0 (obj->qdisc.kind, "fq_codel")) ++ obj->qdisc.fq_codel.memory = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET; ++ + if (tb[TCA_OPTIONS]) { + struct nlattr *options_attr; + int remaining; +@@ -4241,7 +4244,7 @@ _nl_msg_new_qdisc (int nlmsg_type, + NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); + if (qdisc->fq_codel.ce_threshold != -1) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); +- if (qdisc->fq_codel.memory != -1) ++ if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory); + if (qdisc->fq_codel.ecn) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index 4d3b61405d..fc49db19a1 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -6455,7 +6455,7 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) + nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum); + if (qdisc->fq_codel.ce_threshold != -1) + nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold); +- if (qdisc->fq_codel.memory != -1) ++ if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) + nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory); + if (qdisc->fq_codel.ecn) + nm_utils_strbuf_append (&buf, &len, " ecn"); +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index 16747f093b..9f9fcf5c31 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -596,6 +596,8 @@ typedef struct { + bool uid_range_has:1; /* has(FRA_UID_RANGE) */ + } NMPlatformRoutingRule; + ++#define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET (~((guint32) 0)) ++ + typedef struct { + guint32 limit; + guint32 flows; +@@ -603,7 +605,12 @@ typedef struct { + guint32 interval; + guint32 quantum; + guint32 ce_threshold; +- guint32 memory; ++ guint32 memory; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel ++ * and kernel defaults to 32MB. ++ * Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET ++ * to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request). ++ * This will cause kernel to choose the default (32MB). ++ * Beware: zero is not the default you must always explicitly set this value. */ + bool ecn:1; + } NMPlatformQdiscFqCodel; + +-- +2.21.0 + +From 859f8479d453c9270987245b9d6e537af0e42077 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 09:19:59 +0200 +Subject: [PATCH 13/20] platform: fix handling of default value for + TCA_FQ_CODEL_CE_THRESHOLD + +iproute2 uses the special value ~0u to indicate not to set +TCA_FQ_CODEL_CE_THRESHOLD in RTM_NEWQDISC. When not explicitly +setting the value, kernel treats the threshold as disabled. + +However note that 0xFFFFFFFFu is not an invalid threshold (as far as +kernel is concerned). Thus, we should not use that as value to indicate +that the value is unset. Note that iproute2 uses the special value ~0u +only internally thereby making it impossible to set the threshold to +0xFFFFFFFFu). But kernel does not have this limitation. + +Maybe the cleanest way would be to add another field to NMPlatformQDisc: + + guint32 ce_threshold; + bool ce_threshold_set:1; + +that indicates whether the threshold is enable or not. +But note that kernel does: + + static void codel_params_init(struct codel_params *params) + { + ... + params->ce_threshold = CODEL_DISABLED_THRESHOLD; + + static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + { + ... + if (tb[TCA_FQ_CODEL_CE_THRESHOLD]) { + u64 val = nla_get_u32(tb[TCA_FQ_CODEL_CE_THRESHOLD]); + + q->cparams.ce_threshold = (val * NSEC_PER_USEC) >> CODEL_SHIFT; + } + + static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb) + { + ... + if (q->cparams.ce_threshold != CODEL_DISABLED_THRESHOLD && + nla_put_u32(skb, TCA_FQ_CODEL_CE_THRESHOLD, + codel_time_to_us(q->cparams.ce_threshold))) + goto nla_put_failure; + +This means, kernel internally uses the special value 0x83126E97u to indicate +that the threshold is disabled (WTF). That is because + + (((guint64) 0x83126E97u) * NSEC_PER_USEC) >> CODEL_SHIFT == CODEL_DISABLED_THRESHOLD + +So in kernel API this value is reserved (and has a special meaning +to indicate that the threshold is disabled). So, instead of adding a +ce_threshold_set flag, use the same value that kernel anyway uses. + +(cherry picked from commit 973db2d41b957c4ee9d4ee9863f4b35c6890ac30) +--- + libnm-core/nm-utils.c | 3 +++ + src/devices/nm-device.c | 2 +- + src/platform/nm-linux-platform.c | 6 ++++-- + src/platform/nm-platform.c | 2 +- + src/platform/nm-platform.h | 12 +++++++++++- + 5 files changed, 20 insertions(+), 5 deletions(-) + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index 2e66e6ae2d..9e2eb63594 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2333,6 +2333,9 @@ static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = { + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("target", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("interval", G_VARIANT_TYPE_UINT32, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("quantum", G_VARIANT_TYPE_UINT32, ), ++ ++ /* 0x83126E97u is not a valid value (it means "disabled"). We should reject that ++ * value. Or alternatively, reject all values >= MAX_INT(32). */ + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ce_threshold", G_VARIANT_TYPE_UINT32, ), + + /* kernel clamps the value at 2^31. Possibly such values should be rejected from configuration +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index ce50d5b73d..22ccabb26e 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6538,7 +6538,7 @@ tc_commit (NMDevice *self) + GET_ATTR("target", qdisc->fq_codel.target, UINT32, uint32, 0); + GET_ATTR("interval", qdisc->fq_codel.interval, UINT32, uint32, 0); + GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0); +- GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, -1); ++ GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED); + GET_ATTR("memory", qdisc->fq_codel.memory, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET); + GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE); + } +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index cec5fb9431..2e11052e1a 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -3515,8 +3515,10 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) + obj->qdisc.parent = tcm->tcm_parent; + obj->qdisc.info = tcm->tcm_info; + +- if (nm_streq0 (obj->qdisc.kind, "fq_codel")) ++ if (nm_streq0 (obj->qdisc.kind, "fq_codel")) { + obj->qdisc.fq_codel.memory = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET; ++ obj->qdisc.fq_codel.ce_threshold = NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED; ++ } + + if (tb[TCA_OPTIONS]) { + struct nlattr *options_attr; +@@ -4242,7 +4244,7 @@ _nl_msg_new_qdisc (int nlmsg_type, + NLA_PUT_U32 (msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval); + if (qdisc->fq_codel.quantum) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); +- if (qdisc->fq_codel.ce_threshold != -1) ++ if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); + if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory); +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index fc49db19a1..cbf9eed5c1 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -6453,7 +6453,7 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) + nm_utils_strbuf_append (&buf, &len, " interval %u", qdisc->fq_codel.interval); + if (qdisc->fq_codel.quantum) + nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum); +- if (qdisc->fq_codel.ce_threshold != -1) ++ if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) + nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold); + if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) + nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory); +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index 9f9fcf5c31..d7c388b1b8 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -598,13 +598,23 @@ typedef struct { + + #define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET (~((guint32) 0)) + ++#define NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED ((guint32) 0x83126E97u) ++ ++G_STATIC_ASSERT (((((guint64) NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) * 1000u) >> 10) == (guint64) INT_MAX); ++ + typedef struct { + guint32 limit; + guint32 flows; + guint32 target; + guint32 interval; + guint32 quantum; +- guint32 ce_threshold; ++ guint32 ce_threshold; /* TCA_FQ_CODEL_CE_THRESHOLD: kernel internally stores this value as ++ * ((val64 * NSEC_PER_USEC) >> CODEL_SHIFT). The default value (in ++ * the domain with this coersion) is CODEL_DISABLED_THRESHOLD (INT_MAX). ++ * That means, "disabled" is expressed on RTM_NEWQDISC netlink API by absence of the ++ * netlink attribute but also as the special value 0x83126E97u ++ * (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED). ++ * Beware: zero is not the default you must always explicitly set this value. */ + guint32 memory; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel + * and kernel defaults to 32MB. + * Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET +-- +2.21.0 + +From c17fa82b314d6b3c027240ee3506706e26ef9e5d Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 12:56:46 +0200 +Subject: [PATCH 14/20] libnm: rename "memory" parameter of fq_codel QDisc to + "memory_limit" + +Kernel calls the netlink attribute TCA_FQ_CODEL_MEMORY_LIMIT. Likewise, +iproute2 calls this "memory_limit". + +Rename because TC parameters are inherrently tied to the kernel +implementation and we should use the familiar name. + +(cherry picked from commit 666d58802b6f9072825d97498ab74e5d37652e93) +--- + libnm-core/nm-utils.c | 2 +- + src/devices/nm-device.c | 2 +- + src/platform/nm-linux-platform.c | 8 ++++---- + src/platform/nm-platform.c | 8 ++++---- + src/platform/nm-platform.h | 2 +- + 5 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c +index 9e2eb63594..394ca7c3a7 100644 +--- a/libnm-core/nm-utils.c ++++ b/libnm-core/nm-utils.c +@@ -2341,7 +2341,7 @@ static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = { + /* kernel clamps the value at 2^31. Possibly such values should be rejected from configuration + * as they cannot be configured. Leaving the attribute unspecified causes kernel to choose + * a default (currently 32MB). */ +- NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("memory", G_VARIANT_TYPE_UINT32, ), ++ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("memory_limit", G_VARIANT_TYPE_UINT32, ), + + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ), + NULL, +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 22ccabb26e..e2a5fd4bf2 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6539,7 +6539,7 @@ tc_commit (NMDevice *self) + GET_ATTR("interval", qdisc->fq_codel.interval, UINT32, uint32, 0); + GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0); + GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED); +- GET_ATTR("memory", qdisc->fq_codel.memory, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET); ++ GET_ATTR("memory_limit", qdisc->fq_codel.memory_limit, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET); + GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE); + } + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index 2e11052e1a..9721ff9403 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -3516,7 +3516,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) + obj->qdisc.info = tcm->tcm_info; + + if (nm_streq0 (obj->qdisc.kind, "fq_codel")) { +- obj->qdisc.fq_codel.memory = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET; ++ obj->qdisc.fq_codel.memory_limit = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET; + obj->qdisc.fq_codel.ce_threshold = NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED; + } + +@@ -3549,7 +3549,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) + obj->qdisc.fq_codel.ce_threshold = nla_get_u32 (options_attr); + break; + case TCA_FQ_CODEL_MEMORY_LIMIT: +- obj->qdisc.fq_codel.memory = nla_get_u32 (options_attr); ++ obj->qdisc.fq_codel.memory_limit = nla_get_u32 (options_attr); + break; + case TCA_FQ_CODEL_ECN: + obj->qdisc.fq_codel.ecn = !!nla_get_u32 (options_attr); +@@ -4246,8 +4246,8 @@ _nl_msg_new_qdisc (int nlmsg_type, + NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); + if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); +- if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) +- NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory); ++ if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) ++ NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory_limit); + if (qdisc->fq_codel.ecn) + NLA_PUT_U32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); + } +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index cbf9eed5c1..ea73f21019 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -6455,8 +6455,8 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) + nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum); + if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) + nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold); +- if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) +- nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory); ++ if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) ++ nm_utils_strbuf_append (&buf, &len, " memory_limit %u", qdisc->fq_codel.memory_limit); + if (qdisc->fq_codel.ecn) + nm_utils_strbuf_append (&buf, &len, " ecn"); + } +@@ -6482,7 +6482,7 @@ nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h) + obj->fq_codel.interval, + obj->fq_codel.quantum, + obj->fq_codel.ce_threshold, +- obj->fq_codel.memory, ++ obj->fq_codel.memory_limit, + NM_HASH_COMBINE_BOOLS (guint8, + obj->fq_codel.ecn)); + } +@@ -6506,7 +6506,7 @@ nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b) + NM_CMP_FIELD (a, b, fq_codel.interval); + NM_CMP_FIELD (a, b, fq_codel.quantum); + NM_CMP_FIELD (a, b, fq_codel.ce_threshold); +- NM_CMP_FIELD (a, b, fq_codel.memory); ++ NM_CMP_FIELD (a, b, fq_codel.memory_limit); + NM_CMP_FIELD_UNSAFE (a, b, fq_codel.ecn); + } + +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index d7c388b1b8..5a0efceca7 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -615,7 +615,7 @@ typedef struct { + * netlink attribute but also as the special value 0x83126E97u + * (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED). + * Beware: zero is not the default you must always explicitly set this value. */ +- guint32 memory; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel ++ guint32 memory_limit; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel + * and kernel defaults to 32MB. + * Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET + * to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request). +-- +2.21.0 + +From 79e3b2a838b1ae7e6174de8ff000509e918d5c90 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 12:58:37 +0200 +Subject: [PATCH 15/20] platform: use bool bitfields in NMPlatformActionMirred + structure + +Arguably, the structure is used inside a union with another (larger) +struct, hence no memory is saved. + +In fact, it may well be slower performance wise to access a boolean bitfield +than a gboolean (int). + +Still, boolean fields in structures should be bool:1 bitfields for +consistency. + +(cherry picked from commit 36d6aa3bcd97f2144e8f435249ed8f3cb709ae43) +--- + src/platform/nm-platform.c | 19 ++++++++++--------- + src/platform/nm-platform.h | 8 ++++---- + 2 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index ea73f21019..ee71319dd6 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -6577,11 +6577,12 @@ nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h) + nm_hash_update_strarr (h, obj->action.simple.sdata); + } else if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { + nm_hash_update_vals (h, +- obj->action.mirred.ingress, +- obj->action.mirred.egress, +- obj->action.mirred.mirror, +- obj->action.mirred.redirect, +- obj->action.mirred.ifindex); ++ obj->action.mirred.ifindex, ++ NM_HASH_COMBINE_BOOLS (guint8, ++ obj->action.mirred.ingress, ++ obj->action.mirred.egress, ++ obj->action.mirred.mirror, ++ obj->action.mirred.redirect)); + } + } + } +@@ -6602,11 +6603,11 @@ nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b) + if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { + NM_CMP_FIELD_STR (a, b, action.simple.sdata); + } else if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { +- NM_CMP_FIELD (a, b, action.mirred.ingress); +- NM_CMP_FIELD (a, b, action.mirred.egress); +- NM_CMP_FIELD (a, b, action.mirred.mirror); +- NM_CMP_FIELD (a, b, action.mirred.redirect); + NM_CMP_FIELD (a, b, action.mirred.ifindex); ++ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.ingress); ++ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.egress); ++ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.mirror); ++ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.redirect); + } + } + +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index 5a0efceca7..9b6848d977 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -641,11 +641,11 @@ typedef struct { + } NMPlatformActionSimple; + + typedef struct { +- gboolean egress; +- gboolean ingress; +- gboolean mirror; +- gboolean redirect; + int ifindex; ++ bool egress:1; ++ bool ingress:1; ++ bool mirror:1; ++ bool redirect:1; + } NMPlatformActionMirred; + + typedef struct { +-- +2.21.0 + +From 8b1b398c0545f31121c52d323276e013705ddf80 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 13:07:43 +0200 +Subject: [PATCH 16/20] platform: assert for out-of-memory in netlink code + +These lines can be reached if the allocated buffer is too +small to hold the netlink message. That is actually a bug +that we need to fix. Assert. + +(cherry picked from commit 3784a2a2ec6f8c6307f45bae12c17630b7d70b0a) +--- + src/platform/nm-linux-platform.c | 10 +++++----- + src/platform/wifi/nm-wifi-utils-nl80211.c | 12 ++++++------ + src/platform/wpan/nm-wpan-utils.c | 8 ++++---- + 3 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index 9721ff9403..6dd5b4ab3e 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -3681,7 +3681,7 @@ _nl_msg_new_link_set_afspec (struct nl_msg *msg, + + return TRUE; + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + static gboolean +@@ -3832,7 +3832,7 @@ _nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg, + + return TRUE; + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + static struct nl_msg * +@@ -4278,7 +4278,7 @@ _add_action_simple (struct nl_msg *msg, + return TRUE; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + static gboolean +@@ -4308,7 +4308,7 @@ _add_action_mirred (struct nl_msg *msg, + return TRUE; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + static gboolean +@@ -4334,7 +4334,7 @@ _add_action (struct nl_msg *msg, + return TRUE; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + static struct nl_msg * +diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c +index 4f7ede9757..6a8525ed4b 100644 +--- a/src/platform/wifi/nm-wifi-utils-nl80211.c ++++ b/src/platform/wifi/nm-wifi-utils-nl80211.c +@@ -103,7 +103,7 @@ _nl80211_alloc_msg (int id, int ifindex, int phy, guint32 cmd, guint32 flags) + return g_steal_pointer (&msg); + + nla_put_failure: +- return NULL; ++ g_return_val_if_reached (NULL); + } + + static struct nl_msg * +@@ -250,7 +250,7 @@ wifi_nl80211_set_mode (NMWifiUtils *data, const NM80211Mode mode) + return err >= 0; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + static gboolean +@@ -267,7 +267,7 @@ wifi_nl80211_set_powersave (NMWifiUtils *data, guint32 powersave) + return err >= 0; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + static int +@@ -365,7 +365,7 @@ wifi_nl80211_set_wake_on_wlan (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wo + return err >= 0; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + /* @divisor: pass what value @xbm should be divided by to get dBm */ +@@ -642,7 +642,7 @@ nl80211_get_ap_info (NMWifiUtilsNl80211 *self, + return; + + nla_put_failure: +- return; ++ g_return_if_reached (); + } + + static guint32 +@@ -695,7 +695,7 @@ wifi_nl80211_indicate_addressing_running (NMWifiUtils *data, gboolean running) + return err >= 0; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + struct nl80211_device_info { +diff --git a/src/platform/wpan/nm-wpan-utils.c b/src/platform/wpan/nm-wpan-utils.c +index b7a51e9bf2..0afc2a4d0c 100644 +--- a/src/platform/wpan/nm-wpan-utils.c ++++ b/src/platform/wpan/nm-wpan-utils.c +@@ -92,7 +92,7 @@ _nl802154_alloc_msg (int id, int ifindex, guint32 cmd, guint32 flags) + return g_steal_pointer (&msg); + + nla_put_failure: +- return NULL; ++ g_return_val_if_reached (NULL); + } + + static struct nl_msg * +@@ -217,7 +217,7 @@ nm_wpan_utils_set_pan_id (NMWpanUtils *self, guint16 pan_id) + return err >= 0; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + guint16 +@@ -244,7 +244,7 @@ nm_wpan_utils_set_short_addr (NMWpanUtils *self, guint16 short_addr) + return err >= 0; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + gboolean +@@ -262,7 +262,7 @@ nm_wpan_utils_set_channel (NMWpanUtils *self, guint8 page, guint8 channel) + return err >= 0; + + nla_put_failure: +- return FALSE; ++ g_return_val_if_reached (FALSE); + } + + /*****************************************************************************/ +-- +2.21.0 + +From 27341d042487afabcd48fbc08054069f89b9c424 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 13:15:57 +0200 +Subject: [PATCH 17/20] platform: merge _add_action(), _add_action_simple() and + _add_action_mirred() into _nl_msg_new_tfilter() + +There is only one caller, hence it's simpler to see it all in one place. +I prefer this, because then I can read the code top to bottom and +see what's happening, without following helper functions. + +Also, this way we can "reuse" the nla_put_failure label and assertion. Previously, +if the assertion was hit we would not rewind the buffer but continue +constructing the message (which is already borked). Not that it matters +too much, because this was on an "failed-assertion" code path. + +(cherry picked from commit 04bd404dffc8bc1ec5c3fed91e75fad1a1b1a4d3) +--- + src/platform/nm-linux-platform.c | 125 ++++++++++++------------------- + 1 file changed, 46 insertions(+), 79 deletions(-) + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index 6dd5b4ab3e..4a62a76485 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -4260,83 +4260,6 @@ nla_put_failure: + g_return_val_if_reached (NULL); + } + +-static gboolean +-_add_action_simple (struct nl_msg *msg, +- const NMPlatformActionSimple *simple) +-{ +- struct nlattr *act_options; +- struct tc_defact sel = { 0, }; +- +- if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS))) +- goto nla_put_failure; +- +- NLA_PUT (msg, TCA_DEF_PARMS, sizeof (sel), &sel); +- NLA_PUT (msg, TCA_DEF_DATA, sizeof (simple->sdata), simple->sdata); +- +- nla_nest_end (msg, act_options); +- +- return TRUE; +- +-nla_put_failure: +- g_return_val_if_reached (FALSE); +-} +- +-static gboolean +-_add_action_mirred (struct nl_msg *msg, +- const NMPlatformActionMirred *mirred) +-{ +- struct nlattr *act_options; +- struct tc_mirred sel = { 0, }; +- +- if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS))) +- goto nla_put_failure; +- +- if (mirred->egress && mirred->redirect) +- sel.eaction = TCA_EGRESS_REDIR; +- else if (mirred->egress && mirred->mirror) +- sel.eaction = TCA_EGRESS_MIRROR; +- else if (mirred->ingress && mirred->redirect) +- sel.eaction = TCA_INGRESS_REDIR; +- else if (mirred->ingress && mirred->mirror) +- sel.eaction = TCA_INGRESS_MIRROR; +- sel.ifindex = mirred->ifindex; +- +- NLA_PUT (msg, TCA_MIRRED_PARMS, sizeof (sel), &sel); +- +- nla_nest_end (msg, act_options); +- +- return TRUE; +- +-nla_put_failure: +- g_return_val_if_reached (FALSE); +-} +- +-static gboolean +-_add_action (struct nl_msg *msg, +- const NMPlatformAction *action) +-{ +- struct nlattr *prio; +- +- nm_assert (action || action->kind); +- +- if (!(prio = nla_nest_start (msg, 1 /* priority */))) +- goto nla_put_failure; +- +- NLA_PUT_STRING (msg, TCA_ACT_KIND, action->kind); +- +- if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) +- _add_action_simple (msg, &action->simple); +- else if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_MIRRED)) +- _add_action_mirred (msg, &action->mirred); +- +- nla_nest_end (msg, prio); +- +- return TRUE; +- +-nla_put_failure: +- g_return_val_if_reached (FALSE); +-} +- + static struct nl_msg * + _nl_msg_new_tfilter (int nlmsg_type, + int nlmsg_flags, +@@ -4366,8 +4289,52 @@ _nl_msg_new_tfilter (int nlmsg_type, + if (!(act_tab = nla_nest_start (msg, TCA_OPTIONS))) // 3 TCA_ACT_KIND TCA_ACT_KIND + goto nla_put_failure; + +- if (tfilter->action.kind) +- _add_action (msg, &tfilter->action); ++ if (tfilter->action.kind) { ++ const NMPlatformAction *action = &tfilter->action; ++ struct nlattr *prio; ++ struct nlattr *act_options; ++ ++ if (!(prio = nla_nest_start (msg, 1 /* priority */))) ++ goto nla_put_failure; ++ ++ NLA_PUT_STRING (msg, TCA_ACT_KIND, action->kind); ++ ++ if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { ++ const NMPlatformActionSimple *simple = &action->simple; ++ struct tc_defact sel = { 0, }; ++ ++ if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS))) ++ goto nla_put_failure; ++ ++ NLA_PUT (msg, TCA_DEF_PARMS, sizeof (sel), &sel); ++ NLA_PUT (msg, TCA_DEF_DATA, sizeof (simple->sdata), simple->sdata); ++ ++ nla_nest_end (msg, act_options); ++ ++ } else if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { ++ const NMPlatformActionMirred *mirred = &action->mirred; ++ struct tc_mirred sel = { 0, }; ++ ++ if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS))) ++ goto nla_put_failure; ++ ++ if (mirred->egress && mirred->redirect) ++ sel.eaction = TCA_EGRESS_REDIR; ++ else if (mirred->egress && mirred->mirror) ++ sel.eaction = TCA_EGRESS_MIRROR; ++ else if (mirred->ingress && mirred->redirect) ++ sel.eaction = TCA_INGRESS_REDIR; ++ else if (mirred->ingress && mirred->mirror) ++ sel.eaction = TCA_INGRESS_MIRROR; ++ sel.ifindex = mirred->ifindex; ++ ++ NLA_PUT (msg, TCA_MIRRED_PARMS, sizeof (sel), &sel); ++ ++ nla_nest_end (msg, act_options); ++ } ++ ++ nla_nest_end (msg, prio); ++ } + + nla_nest_end (msg, tc_options); + +-- +2.21.0 + +From a0161aa9772af8d7a35812dfdf86864bb941f751 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 13:27:28 +0200 +Subject: [PATCH 18/20] device/trivial: add space between macro name and + arguments and vertically align lines + +Also calling macros we commonly put a space between the macro name and +the parenthesis. + +Also align the parameters. Otherwise it's hard to read for me. + +(cherry picked from commit 9399297a82cbb5e8fc218fdefde7005353cb44d6) +--- + src/devices/nm-device.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index e2a5fd4bf2..1241a098d1 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6533,14 +6533,14 @@ tc_commit (NMDevice *self) + } G_STMT_END + + if (strcmp (qdisc->kind, "fq_codel") == 0) { +- GET_ATTR("limit", qdisc->fq_codel.limit, UINT32, uint32, 0); +- GET_ATTR("flows", qdisc->fq_codel.flows, UINT32, uint32, 0); +- GET_ATTR("target", qdisc->fq_codel.target, UINT32, uint32, 0); +- GET_ATTR("interval", qdisc->fq_codel.interval, UINT32, uint32, 0); +- GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0); +- GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED); +- GET_ATTR("memory_limit", qdisc->fq_codel.memory_limit, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET); +- GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE); ++ GET_ATTR ("limit", qdisc->fq_codel.limit, UINT32, uint32, 0); ++ GET_ATTR ("flows", qdisc->fq_codel.flows, UINT32, uint32, 0); ++ GET_ATTR ("target", qdisc->fq_codel.target, UINT32, uint32, 0); ++ GET_ATTR ("interval", qdisc->fq_codel.interval, UINT32, uint32, 0); ++ GET_ATTR ("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0); ++ GET_ATTR ("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED); ++ GET_ATTR ("memory_limit", qdisc->fq_codel.memory_limit, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET); ++ GET_ATTR ("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE); + } + + #undef GET_ADDR +-- +2.21.0 + +From ea7de52d774f3aa3a099f6fce1cb9313b6456cef Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 16:34:27 +0200 +Subject: [PATCH 19/20] device: don't rely on nm_platform_link_get_ifindex() + returning 0 + +While nm_platform_link_get_ifindex() is documented to return 0 if the device +is not found, don't rely on it. Instead, check that a valid(!) ifindex was +returned, and only then set the ifindex. Otherwise leave it at zero. There +is of course no difference in practice, but we generally treat invalid ifindexes +as <= 0, so it's not immediately clear what nm_platform_link_get_ifindex() +returns to signal no device. + +(cherry picked from commit 9eefe27a1c7879e6f94bbb7dec5c9efe722888fa) +--- + src/devices/nm-device.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 1241a098d1..5195eb667f 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6504,7 +6504,7 @@ tc_commit (NMDevice *self) + + ip_ifindex = nm_device_get_ip_ifindex (self); + if (!ip_ifindex) +- return s_tc == NULL; ++ return s_tc == NULL; + + if (s_tc) { + nqdiscs = nm_setting_tc_config_get_num_qdiscs (s_tc); +@@ -6591,9 +6591,12 @@ tc_commit (NMDevice *self) + + var = nm_tc_action_get_attribute (action, "dev"); + if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_STRING)) { +- int ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (self), +- g_variant_get_string (var, NULL)); +- tfilter->action.mirred.ifindex = ifindex; ++ int ifindex; ++ ++ ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (self), ++ g_variant_get_string (var, NULL)); ++ if (ifindex > 0) ++ tfilter->action.mirred.ifindex = ifindex; + } + } + } +-- +2.21.0 + +From 6d9030acb60c2f9a89224847f0a5e68f8b55b0f0 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +Date: Wed, 1 May 2019 16:35:29 +0200 +Subject: [PATCH 20/20] device/trivial: add comment about lifetime of "kind" in + tc_commit() + +In general, all fields of public NMPlatform* structs must be +plain/simple. Meaning: copying the struct must be possible without +caring about cloning/duplicating memory. +In other words, if there are fields which lifetime is limited, +then these fields cannot be inside the public part NMPlatform*. + +That is why + + - "NMPlatformLink.kind", "NMPlatformQdisc.kind", "NMPlatformTfilter.kind" + are set by platform code to an interned string (g_intern_string()) + that has a static lifetime. + + - the "ingress_qos_map" field is inside the ref-counted struct NMPObjectLnkVlan + and not NMPlatformLnkVlan. This field requires managing the lifetime + of the array and NMPlatformLnkVlan cannot provide that. + +See also for example NMPClass.cmd_obj_copy() which can deep-copy an object. +But this is only suitable for fields in NMPObject*. The purpose of this +rule is that you always can safely copy a NMPlatform* struct without +worrying about the ownership and lifetime of the fields (the field's +lifetime is unlimited). + +This rule and managing of resource lifetime is the main reason for the +NMPlatform*/NMPObject* split. NMPlatform* structs simply have no mechanism +for copying/releasing fields, that is why the NMPObject* counterpart exists +(which is ref-counted and has a copy and destructor function). + +This is violated in tc_commit() for the "kind" strings. The lifetime +of these strings is tied to the setting instance. + +We cannot intern the strings (because these are arbitrary strings +and interned strings are leaked indefinitely). We also cannot g_strdup() +the strings, because NMPlatform* is not supposed to own strings. + +So, just add comments that warn about this ugliness. + +The more correct solution would be to move the "kind" fields inside +NMPObjectQdisc and NMPObjectTfilter, but that is a lot of extra effort. + +(cherry picked from commit f2ae994b2359aa690183a268c5b4cc8fb1a6012e) +--- + src/devices/nm-device.c | 14 +++++++++++++ + src/platform/nm-linux-platform.c | 6 ++++++ + src/platform/nm-platform.c | 34 ++++++++++++++++++++++++++++++++ + src/platform/nm-platform.h | 12 +++++++++++ + 4 files changed, 66 insertions(+) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 5195eb667f..09ba9c5d57 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -6516,7 +6516,12 @@ tc_commit (NMDevice *self) + NMPlatformQdisc *qdisc = NMP_OBJECT_CAST_QDISC (q); + + qdisc->ifindex = ip_ifindex; ++ ++ /* Note: kind string is still owned by NMTCTfilter. ++ * This qdisc instance must not be kept alive beyond this function. ++ * nm_platform_qdisc_sync() promises to do that. */ + qdisc->kind = nm_tc_qdisc_get_kind (s_qdisc); ++ + qdisc->addr_family = AF_UNSPEC; + qdisc->handle = nm_tc_qdisc_get_handle (s_qdisc); + qdisc->parent = nm_tc_qdisc_get_parent (s_qdisc); +@@ -6558,7 +6563,12 @@ tc_commit (NMDevice *self) + NMPlatformTfilter *tfilter = NMP_OBJECT_CAST_TFILTER (q); + + tfilter->ifindex = ip_ifindex; ++ ++ /* Note: kind string is still owned by NMTCTfilter. ++ * This tfilter instance must not be kept alive beyond this function. ++ * nm_platform_tfilter_sync() promises to do that. */ + tfilter->kind = nm_tc_tfilter_get_kind (s_tfilter); ++ + tfilter->addr_family = AF_UNSPEC; + tfilter->handle = nm_tc_tfilter_get_handle (s_tfilter); + tfilter->parent = nm_tc_tfilter_get_parent (s_tfilter); +@@ -6568,7 +6578,11 @@ tc_commit (NMDevice *self) + if (action) { + GVariant *var; + ++ /* Note: kind string is still owned by NMTCAction. ++ * This tfilter instance must not be kept alive beyond this function. ++ * nm_platform_tfilter_sync() promises to do that. */ + tfilter->action.kind = nm_tc_action_get_kind (action); ++ + if (strcmp (tfilter->action.kind, "simple") == 0) { + var = nm_tc_action_get_attribute (action, "sdata"); + if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_BYTESTRING)) { +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index 4a62a76485..7d66a88fa7 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -8244,6 +8244,9 @@ qdisc_add (NMPlatform *platform, + char s_buf[256]; + nm_auto_nlmsg struct nl_msg *msg = NULL; + ++ /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind ++ * is undefined. */ ++ + msg = _nl_msg_new_qdisc (RTM_NEWQDISC, flags, qdisc); + + event_handler_read_netlink (platform, FALSE); +@@ -8285,6 +8288,9 @@ tfilter_add (NMPlatform *platform, + char s_buf[256]; + nm_auto_nlmsg struct nl_msg *msg = NULL; + ++ /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind ++ * and tfilter.action.kind is undefined. */ ++ + msg = _nl_msg_new_tfilter (RTM_NEWTFILTER, flags, tfilter); + + event_handler_read_netlink (platform, FALSE); +diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c +index ee71319dd6..7add7dcdbe 100644 +--- a/src/platform/nm-platform.c ++++ b/src/platform/nm-platform.c +@@ -5077,10 +5077,27 @@ nm_platform_qdisc_add (NMPlatform *self, + int ifindex = qdisc->ifindex; + _CHECK_SELF (self, klass, -NME_BUG); + ++ /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind ++ * is undefined. */ ++ + _LOG3D ("adding or updating a qdisc: %s", nm_platform_qdisc_to_string (qdisc, NULL, 0)); + return klass->qdisc_add (self, flags, qdisc); + } + ++/** ++ * nm_platform_qdisc_sync: ++ * @self: the #NMPlatform instance ++ * @ifindex: the ifindex where to configure the qdiscs. ++ * @known_qdiscs: the list of qdiscs (#NMPObject). ++ * ++ * The function promises not to take any reference to the qdisc ++ * instances from @known_qdiscs, nor to keep them around after ++ * the function returns. This is important, because it allows the ++ * caller to pass NMPlatformQdisc instances which "kind" string ++ * have a limited lifetime. ++ * ++ * Returns: %TRUE on success. ++ */ + gboolean + nm_platform_qdisc_sync (NMPlatform *self, + int ifindex, +@@ -5143,10 +5160,27 @@ nm_platform_tfilter_add (NMPlatform *self, + int ifindex = tfilter->ifindex; + _CHECK_SELF (self, klass, -NME_BUG); + ++ /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind ++ * and tfilter.action.kind is undefined. */ ++ + _LOG3D ("adding or updating a tfilter: %s", nm_platform_tfilter_to_string (tfilter, NULL, 0)); + return klass->tfilter_add (self, flags, tfilter); + } + ++/** ++ * nm_platform_qdisc_sync: ++ * @self: the #NMPlatform instance ++ * @ifindex: the ifindex where to configure the qdiscs. ++ * @known_tfilters: the list of tfilters (#NMPObject). ++ * ++ * The function promises not to take any reference to the tfilter ++ * instances from @known_tfilters, nor to keep them around after ++ * the function returns. This is important, because it allows the ++ * caller to pass NMPlatformTfilter instances which "kind" string ++ * have a limited lifetime. ++ * ++ * Returns: %TRUE on success. ++ */ + gboolean + nm_platform_tfilter_sync (NMPlatform *self, + int ifindex, +diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h +index 9b6848d977..a2d8e57ff6 100644 +--- a/src/platform/nm-platform.h ++++ b/src/platform/nm-platform.h +@@ -626,7 +626,11 @@ typedef struct { + + typedef struct { + __NMPlatformObjWithIfindex_COMMON; ++ ++ /* beware, kind is embedded in an NMPObject, hence you must ++ * take care of the lifetime of the string. */ + const char *kind; ++ + int addr_family; + guint32 handle; + guint32 parent; +@@ -649,7 +653,11 @@ typedef struct { + } NMPlatformActionMirred; + + typedef struct { ++ ++ /* beware, kind is embedded in an NMPObject, hence you must ++ * take care of the lifetime of the string. */ + const char *kind; ++ + union { + NMPlatformActionSimple simple; + NMPlatformActionMirred mirred; +@@ -661,7 +669,11 @@ typedef struct { + + typedef struct { + __NMPlatformObjWithIfindex_COMMON; ++ ++ /* beware, kind is embedded in an NMPObject, hence you must ++ * take care of the lifetime of the string. */ + const char *kind; ++ + int addr_family; + guint32 handle; + guint32 parent; +-- +2.21.0 + diff --git a/SOURCES/1008-don-t-kill-teamd-for-external-devices-rh1711952.patch b/SOURCES/1008-don-t-kill-teamd-for-external-devices-rh1711952.patch new file mode 100644 index 0000000..18134c7 --- /dev/null +++ b/SOURCES/1008-don-t-kill-teamd-for-external-devices-rh1711952.patch @@ -0,0 +1,33 @@ +From 2711e9be108063d9e269412c9026c10c63f1cda3 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Sun, 19 May 2019 11:35:02 +0200 +Subject: [PATCH] team: don't kill teamd for external devices + +The teamd instance must not be killed if the device was externally +activated. + +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/158 +https://bugzilla.redhat.com/show_bug.cgi?id=1693142 +(cherry picked from commit 008a4b4215dcce40345b2c372ffc8cfd0d388fa5) +(cherry picked from commit bd113fe72eac3f609a6d05ab33ef52d6773c1985) +--- + src/devices/team/nm-device-team.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c +index 287f4d1b1..4ae276dbf 100644 +--- a/src/devices/team/nm-device-team.c ++++ b/src/devices/team/nm-device-team.c +@@ -694,6 +694,9 @@ deactivate (NMDevice *device) + NMDeviceTeam *self = NM_DEVICE_TEAM (device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + ++ if (nm_device_sys_iface_state_is_external (device)) ++ return; ++ + if (priv->teamd_pid || priv->tdc) + _LOGI (LOGD_TEAM, "deactivation: stopping teamd..."); + +-- +2.20.1 + diff --git a/SOURCES/1009-ifcfg-rh-use-PKCS12-private-as-client-cert-rh1714610.patch b/SOURCES/1009-ifcfg-rh-use-PKCS12-private-as-client-cert-rh1714610.patch new file mode 100644 index 0000000..770eaa9 --- /dev/null +++ b/SOURCES/1009-ifcfg-rh-use-PKCS12-private-as-client-cert-rh1714610.patch @@ -0,0 +1,305 @@ +From 51c47c0a9d77f04d04c6cde7f1254623328898f9 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 14 May 2019 13:59:00 +0200 +Subject: [PATCH 1/3] ifcfg-rh: write client certificate even if it is pkcs12 + +The writer should only persist properties without too much additional +logic, which should be instead embedded in the setting itself. + +(cherry picked from commit a995244e9bf526b2d10143858655c3ea3731bf91) +(cherry picked from commit 5a5cd8d05dfbde11b0983e09a5a37f6929bb2178) +--- + .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 4 ---- + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 24 ++++++------------- + 2 files changed, 7 insertions(+), 21 deletions(-) + +diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +index e5423b181..9b7511064 100644 +--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c ++++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +@@ -3117,10 +3117,6 @@ eap_tls_reader (const char *eap_method, + &client_cert, + error)) + return FALSE; +- /* FIXME: writer does not actually write IEEE_8021X_CLIENT_CERT_PASSWORD and other +- * certificate related passwords. It should, because otherwise persisting such profiles +- * to ifcfg looses information. As this currently only matters for PKCS11 URIs, it seems +- * a seldom used feature so that it is not fixed yet. */ + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, +diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +index 80b1bffe1..90f06e183 100644 +--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c ++++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +@@ -358,23 +358,13 @@ write_8021x_certs (NMSetting8021x *s_8021x, + if (!write_object (s_8021x, ifcfg, secrets, blobs, otype, error)) + return FALSE; + +- /* Client certificate */ +- if (otype->vtable->format_func (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { +- /* Don't need a client certificate with PKCS#12 since the file is both +- * the client certificate and the private key in one file. +- */ +- svSetValueStr (ifcfg, +- phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", +- NULL); +- } else { +- /* Save the client certificate */ +- if (!write_object (s_8021x, ifcfg, secrets, blobs, +- phase2 +- ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] +- : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT], +- error)) +- return FALSE; +- } ++ /* Save the client certificate */ ++ if (!write_object (s_8021x, ifcfg, secrets, blobs, ++ phase2 ++ ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] ++ : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT], ++ error)) ++ return FALSE; + + return TRUE; + } +-- +2.20.1 + +From c62a97f608c4c28cbefe1b5b57bec5f6da24b342 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 14 May 2019 14:32:19 +0200 +Subject: [PATCH 2/3] ifcfg-rh: don't check for 802.1x private key or client + cert in reader + +Let the setting check it in verify(). + +(cherry picked from commit d9b3b2b8cec9fdb984a6103240688dc46f33866e) +(cherry picked from commit c28db67a781388e1f742b3406e26a35c8c2522a8) +--- + .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 16 +++------------- + 1 file changed, 3 insertions(+), 13 deletions(-) + +diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +index 9b7511064..da3b89e1a 100644 +--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c ++++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +@@ -3077,6 +3077,7 @@ eap_tls_reader (const char *eap_method, + svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free), + NULL); + ++ /* CA certificate */ + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT", +@@ -3090,6 +3091,7 @@ eap_tls_reader (const char *eap_method, + phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD" : "IEEE_8021X_CA_CERT_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD : NM_SETTING_802_1X_CA_CERT_PASSWORD); + ++ /* Private key */ + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", +@@ -3102,14 +3104,8 @@ eap_tls_reader (const char *eap_method, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" : "IEEE_8021X_PRIVATE_KEY_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); +- if (!privkey) { +- g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, +- "Missing %s for EAP method '%s'.", +- phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", +- eap_method); +- return FALSE; +- } + ++ /* Client certificate */ + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", +@@ -3122,12 +3118,6 @@ eap_tls_reader (const char *eap_method, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); +- if (!client_cert) { +- g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, +- "Missing certificate for EAP method '%s'.", +- eap_method); +- return FALSE; +- } + + return TRUE; + } +-- +2.20.1 + +From b3935bb0f25bede6e9c29735314f42f4bd773e09 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 14 May 2019 15:27:45 +0200 +Subject: [PATCH 3/3] ifcfg-rh: use PKCS #12 private key also as client cert in + reader + +Before commit e3ac45c02610 the reader set the private key in the +setting using the libnm function, which also set the key as client +certificate if it was in PKCS #12 format. + +After the commit, existing connections with a PKCS #12 private key but +without a client certificate became invalid. Restore the old behavior. + +Fixes: e3ac45c02610 ('ifcfg-rh: don't use 802-1x certifcate setter functions') +(cherry picked from commit 9a410fc312c50ac405c57ff4e9eb692e798e248d) +(cherry picked from commit 51896e1e6b24e0b5d6aefce3c4945d27a5b9f5b7) +--- + Makefile.am | 2 ++ + .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 28 ++++++++++++++++-- + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 21 +++++++++---- + ...fg-test-wired-8021x-tls-p12-no-client-cert | 13 ++++++++ + .../tests/network-scripts/test_client.p12 | Bin 0 -> 2848 bytes + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 23 ++++++++++++++ + 6 files changed, 79 insertions(+), 8 deletions(-) + create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert + create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 + +diff --git a/Makefile.am b/Makefile.am +index d78bfdeda..8c470df31 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3014,6 +3014,7 @@ EXTRA_DIST += \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always \ ++ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static \ +@@ -3083,6 +3084,7 @@ EXTRA_DIST += \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem \ ++ src/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 \ + $(NULL) + + # make target dependencies can't have colons in their names, which ends up +diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +index da3b89e1a..317e22f7a 100644 +--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c ++++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +@@ -3071,6 +3071,10 @@ eap_tls_reader (const char *eap_method, + gs_unref_bytes GBytes *privkey = NULL; + gs_unref_bytes GBytes *client_cert = NULL; + gs_free char *identity_free = NULL; ++ gs_free char *value_to_free = NULL; ++ const char *client_cert_var; ++ const char *client_cert_prop; ++ NMSetting8021xCKFormat format; + + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, +@@ -3106,10 +3110,12 @@ eap_tls_reader (const char *eap_method, + phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); + + /* Client certificate */ ++ client_cert_var = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT"; ++ client_cert_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT : NM_SETTING_802_1X_CLIENT_CERT; + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, +- phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", +- phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT : NM_SETTING_802_1X_CLIENT_CERT, ++ client_cert_var, ++ client_cert_prop, + &client_cert, + error)) + return FALSE; +@@ -3119,6 +3125,24 @@ eap_tls_reader (const char *eap_method, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); + ++ /* In the past when the private key and client certificate ++ * were the same PKCS #12 file we used to write only the ++ * private key variable. Still support that even if it means ++ * that we have to look into the file content, which makes ++ * the connection not self-contained. ++ */ ++ if ( !client_cert ++ && privkey ++ && !svGetValue (ifcfg, client_cert_var, &value_to_free)) { ++ if (phase2) ++ format = nm_setting_802_1x_get_phase2_private_key_format (s_8021x); ++ else ++ format = nm_setting_802_1x_get_private_key_format (s_8021x); ++ ++ if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) ++ g_object_set (s_8021x, client_cert_prop, privkey, NULL); ++ } ++ + return TRUE; + } + +diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +index 90f06e183..6e2bc8493 100644 +--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c ++++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +@@ -209,6 +209,7 @@ write_object (NMSetting8021x *s_8021x, + GHashTable *secrets, + GHashTable *blobs, + const Setting8021xSchemeVtable *objtype, ++ gboolean force_write, + GError **error) + { + NMSetting8021xCKScheme scheme; +@@ -287,7 +288,7 @@ write_object (NMSetting8021x *s_8021x, + */ + standard_file = utils_cert_path (svFileGetName (ifcfg), objtype->vtable->file_suffix, extension); + g_hash_table_replace (blobs, standard_file, NULL); +- svUnsetValue (ifcfg, objtype->ifcfg_rh_key); ++ svSetValue (ifcfg, objtype->ifcfg_rh_key, force_write ? "" : NULL); + return TRUE; + } + +@@ -338,31 +339,39 @@ write_8021x_certs (NMSetting8021x *s_8021x, + shvarFile *ifcfg, + GError **error) + { +- const Setting8021xSchemeVtable *otype = NULL; ++ const Setting8021xSchemeVtable *pk_otype = NULL; ++ gs_free char *value_to_free = NULL; + + /* CA certificate */ + if (!write_object (s_8021x, ifcfg, secrets, blobs, + phase2 + ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] + : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT], ++ FALSE, + error)) + return FALSE; + + /* Private key */ + if (phase2) +- otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY]; ++ pk_otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY]; + else +- otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY]; ++ pk_otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY]; + + /* Save the private key */ +- if (!write_object (s_8021x, ifcfg, secrets, blobs, otype, error)) ++ if (!write_object (s_8021x, ifcfg, secrets, blobs, pk_otype, FALSE, error)) + return FALSE; + +- /* Save the client certificate */ ++ /* Save the client certificate. ++ * If there is a private key, always write a property for the ++ * client certificate even if it is empty, so that the reader ++ * doesn't have to read the private key file to determine if it ++ * is a PKCS #12 one which serves also as client certificate. ++ */ + if (!write_object (s_8021x, ifcfg, secrets, blobs, + phase2 + ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] + : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT], ++ !!svGetValue (ifcfg, pk_otype->ifcfg_rh_key, &value_to_free), + error)) + return FALSE; + +-- +2.20.1 + diff --git a/SOURCES/1010-translations-rh1689962.patch b/SOURCES/1010-translations-rh1689962.patch new file mode 100644 index 0000000..f37e570 --- /dev/null +++ b/SOURCES/1010-translations-rh1689962.patch @@ -0,0 +1,39527 @@ +From 9de7c0542c6ee44cb0c54c0fcdb5155d00ef3a31 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Tue, 21 May 2019 10:00:16 +0200 +Subject: [PATCH 1/2] po: update-po + +--- + po/ar.po | 4526 +++++++++++++++++++++++-------------------- + po/as.po | 4643 +++++++++++++++++++++++++-------------------- + po/be@latin.po | 4487 +++++++++++++++++++++++-------------------- + po/bg.po | 4544 ++++++++++++++++++++++++-------------------- + po/bn_IN.po | 4642 ++++++++++++++++++++++++-------------------- + po/bs.po | 4516 +++++++++++++++++++++++-------------------- + po/ca.po | 4658 +++++++++++++++++++++++++-------------------- + po/cs.po | 4811 ++++++++++++++++++++++++---------------------- + po/da.po | 4398 ++++++++++++++++++++++-------------------- + po/de.po | 4703 +++++++++++++++++++++++++-------------------- + po/dz.po | 4536 +++++++++++++++++++++++-------------------- + po/el.po | 4652 +++++++++++++++++++++++++-------------------- + po/en_CA.po | 4618 +++++++++++++++++++++++--------------------- + po/en_GB.po | 4545 ++++++++++++++++++++++++-------------------- + po/eo.po | 3110 +++++++++++++++--------------- + po/es.po | 4749 ++++++++++++++++++++++++++-------------------- + po/et.po | 4505 +++++++++++++++++++++++-------------------- + po/eu.po | 4541 ++++++++++++++++++++++++-------------------- + po/fi.po | 4579 +++++++++++++++++++++++--------------------- + po/fr.po | 4700 +++++++++++++++++++++++++-------------------- + po/gd.po | 4631 ++++++++++++++++++++++++-------------------- + po/gl.po | 4536 +++++++++++++++++++++++-------------------- + po/gu.po | 4603 ++++++++++++++++++++++++-------------------- + po/he.po | 4485 +++++++++++++++++++++++-------------------- + po/hi.po | 4718 ++++++++++++++++++++++++--------------------- + po/hr.po | 4557 ++++++++++++++++++++++++-------------------- + po/hu.po | 4599 ++++++++++++++++++++++++-------------------- + po/id.po | 4959 ++++++++++++++++++++++++++---------------------- + po/it.po | 3470 ++++++++++++++++++--------------- + po/ja.po | 4680 +++++++++++++++++++++++++-------------------- + po/ka.po | 4546 ++++++++++++++++++++++++-------------------- + po/kn.po | 4646 +++++++++++++++++++++++++-------------------- + po/ko.po | 4681 +++++++++++++++++++++++++-------------------- + po/ku.po | 4576 +++++++++++++++++++++++--------------------- + po/lt.po | 4619 ++++++++++++++++++++++++-------------------- + po/lv.po | 4555 +++++++++++++++++++++++--------------------- + po/mk.po | 4485 +++++++++++++++++++++++-------------------- + po/ml.po | 4604 ++++++++++++++++++++++++-------------------- + po/mr.po | 4640 ++++++++++++++++++++++++-------------------- + po/nb.po | 4487 +++++++++++++++++++++++-------------------- + po/ne.po | 4525 +++++++++++++++++++++++-------------------- + po/nl.po | 4489 +++++++++++++++++++++++-------------------- + po/oc.po | 4562 ++++++++++++++++++++++++-------------------- + po/or.po | 4602 ++++++++++++++++++++++++-------------------- + po/pa.po | 4740 ++++++++++++++++++++++++--------------------- + po/pl.po | 3877 ++++++++++++++++++++++++++++++------- + po/pt.po | 4536 +++++++++++++++++++++++-------------------- + po/pt_BR.po | 1433 +++++++------- + po/ru.po | 4696 +++++++++++++++++++++++++-------------------- + po/rw.po | 4595 +++++++++++++++++++++++--------------------- + po/sk.po | 4526 +++++++++++++++++++++++-------------------- + po/sl.po | 4550 ++++++++++++++++++++++++-------------------- + po/sq.po | 4496 +++++++++++++++++++++++-------------------- + po/sr.po | 4604 +++++++++++++++++++++++--------------------- + po/sr@latin.po | 4604 +++++++++++++++++++++++--------------------- + po/sv.po | 4950 +++++++++++++++++++++++++---------------------- + po/ta.po | 4647 +++++++++++++++++++++++++-------------------- + po/te.po | 4639 ++++++++++++++++++++++++-------------------- + po/th.po | 4546 ++++++++++++++++++++++++-------------------- + po/tr.po | 4647 +++++++++++++++++++++++++-------------------- + po/uk.po | 4845 +++++++++++++++++++++++++--------------------- + po/vi.po | 4505 +++++++++++++++++++++++-------------------- + po/wa.po | 4543 ++++++++++++++++++++++++-------------------- + po/zh_CN.po | 4671 +++++++++++++++++++++++++-------------------- + po/zh_HK.po | 4546 ++++++++++++++++++++++++-------------------- + po/zh_TW.po | 4687 +++++++++++++++++++++++++-------------------- + 66 files changed, 162449 insertions(+), 135152 deletions(-) + +diff --git a/po/fr.po b/po/fr.po +index 4193042a1b..4c13083f08 100644 +--- a/po/fr.po ++++ b/po/fr.po +@@ -19,7 +19,7 @@ msgid "" + msgstr "" + "Project-Id-Version: PACKAGE VERSION\n" + "Report-Msgid-Bugs-To: \n" +-"POT-Creation-Date: 2019-01-08 18:22+0100\n" ++"POT-Creation-Date: 2019-05-21 09:59+0200\n" + "PO-Revision-Date: 2017-11-07 06:49+0000\n" + "Last-Translator: Copied by Zanata \n" + "Language-Team: French \n" +@@ -30,7 +30,7 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=n>1;\n" + "X-Generator: Zanata 4.6.2\n" + +-#: ../clients/cli/agent.c:40 ++#: ../clients/cli/agent.c:39 + #, c-format + msgid "" + "Usage: nmcli agent { COMMAND | help }\n" +@@ -43,7 +43,7 @@ msgstr "" + "COMMAND := { secret | polkit | all }\n" + "\n" + +-#: ../clients/cli/agent.c:48 ++#: ../clients/cli/agent.c:47 + #, c-format + msgid "" + "Usage: nmcli agent secret { help }\n" +@@ -65,7 +65,7 @@ msgstr "" + "à l'utilisateur.\n" + "\n" + +-#: ../clients/cli/agent.c:58 ++#: ../clients/cli/agent.c:57 + #, c-format + msgid "" + "Usage: nmcli agent polkit { help }\n" +@@ -83,7 +83,7 @@ msgstr "" + "l'utilisateur et donnera la réponse à polkit.\n" + "\n" + +-#: ../clients/cli/agent.c:68 ++#: ../clients/cli/agent.c:67 + #, c-format + msgid "" + "Usage: nmcli agent all { help }\n" +@@ -97,49 +97,49 @@ msgstr "" + "polkit.\n" + "\n" + +-#: ../clients/cli/agent.c:157 ++#: ../clients/cli/agent.c:159 + #, c-format + msgid "nmcli successfully registered as a NetworkManager's secret agent.\n" + msgstr "" + "nmcli est enregistré avec succès comme agent de secret NetworkManager.\n" + +-#: ../clients/cli/agent.c:159 ++#: ../clients/cli/agent.c:161 + #, c-format + msgid "Error: secret agent initialization failed" + msgstr "Erreur : l'initialisation de l'agent de secret a échoué" + +-#: ../clients/cli/agent.c:178 ++#: ../clients/cli/agent.c:180 + #, c-format + msgid "Error: polkit agent initialization failed: %s" + msgstr "Erreur : l'initialisation de l'agent polkit a échoué : %s" + +-#: ../clients/cli/agent.c:186 ++#: ../clients/cli/agent.c:188 + #, c-format + msgid "nmcli successfully registered as a polkit agent.\n" + msgstr "nmcli est enregistré comme agent polkit.\n" + +-#: ../clients/cli/common.c:361 ../clients/cli/common.c:362 +-#: ../clients/cli/common.c:393 ../clients/cli/common.c:394 +-#: ../clients/cli/connections.c:1454 ++#: ../clients/cli/common.c:360 ../clients/cli/common.c:361 ++#: ../clients/cli/common.c:392 ../clients/cli/common.c:393 ++#: ../clients/cli/connections.c:1460 + msgid "GROUP" + msgstr "GROUPE" + +-#: ../clients/cli/common.c:621 ++#: ../clients/cli/common.c:620 + #, c-format + msgid "Error: openconnect failed: %s\n" + msgstr "Erreur : échec de openconnect : %s\n" + +-#: ../clients/cli/common.c:628 ++#: ../clients/cli/common.c:627 + #, c-format + msgid "Error: openconnect failed with status %d\n" + msgstr "Erreur : échec de openconnect avec l'état %d\n" + +-#: ../clients/cli/common.c:630 ++#: ../clients/cli/common.c:629 + #, c-format + msgid "Error: openconnect failed with signal %d\n" + msgstr "Erreur : échec de openconnect avec le signal %d\n" + +-#: ../clients/cli/common.c:711 ++#: ../clients/cli/common.c:717 + #, c-format + msgid "" + "Warning: password for '%s' not given in 'passwd-file' and nmcli cannot ask " +@@ -149,134 +149,134 @@ msgstr "" + "paramètre« passwd-file » et nmcli ne peut le demander à l'utilisateur sans " + "l'option « --ask ».\n" + +-#: ../clients/cli/common.c:1211 ++#: ../clients/cli/common.c:1217 + #, c-format + msgid "Error: Could not create NMClient object: %s." + msgstr "Erreur : impossible de créer l'objet NMClient : %s." + +-#: ../clients/cli/common.c:1231 ++#: ../clients/cli/common.c:1237 + msgid "Error: NetworkManager is not running." + msgstr "Erreur : NetworkManager n'est pas lancé." + +-#: ../clients/cli/common.c:1327 ++#: ../clients/cli/common.c:1333 + #, c-format + msgid "Error: argument '%s' not understood. Try passing --help instead." + msgstr "Erreur : paramètre « %s » non reconnu. Essayez plutôt --help." + +-#: ../clients/cli/common.c:1337 ++#: ../clients/cli/common.c:1343 + msgid "Error: missing argument. Try passing --help." + msgstr "Erreur : paramètre manquant. Essayez --help." + +-#: ../clients/cli/common.c:1390 ++#: ../clients/cli/common.c:1412 + msgid "access denied" + msgstr "accès refusé" + +-#: ../clients/cli/common.c:1398 ../clients/cli/connections.c:81 +-#: ../clients/cli/connections.c:90 ../clients/cli/devices.c:444 +-#: ../clients/cli/devices.c:536 ../clients/cli/devices.c:543 +-#: ../clients/cli/general.c:41 ../clients/cli/general.c:129 +-#: ../clients/cli/general.c:134 ../clients/common/nm-client-utils.c:260 +-#: ../clients/common/nm-client-utils.c:273 ++#: ../clients/cli/common.c:1420 ../clients/cli/connections.c:79 ++#: ../clients/cli/connections.c:88 ../clients/cli/devices.c:438 ++#: ../clients/cli/devices.c:530 ../clients/cli/devices.c:537 ++#: ../clients/cli/general.c:40 ../clients/cli/general.c:130 ++#: ../clients/cli/general.c:135 ../clients/common/nm-client-utils.c:264 + #: ../clients/common/nm-client-utils.c:277 +-#: ../clients/common/nm-client-utils.c:282 +-#: ../clients/common/nm-meta-setting-desc.c:1567 +-#: ../clients/common/nm-meta-setting-desc.c:1617 +-#: ../clients/common/nm-meta-setting-desc.c:2757 +-#: ../clients/common/nm-meta-setting-desc.c:2812 ++#: ../clients/common/nm-client-utils.c:281 ++#: ../clients/common/nm-client-utils.c:286 ++#: ../clients/common/nm-meta-setting-desc.c:1766 ++#: ../clients/common/nm-meta-setting-desc.c:1797 ++#: ../clients/common/nm-meta-setting-desc.c:2708 ++#: ../clients/common/nm-meta-setting-desc.c:2766 + msgid "unknown" + msgstr "inconnu" + +-#: ../clients/cli/common.c:1399 ++#: ../clients/cli/common.c:1421 + msgid "none" + msgstr "aucun" + +-#: ../clients/cli/common.c:1400 ++#: ../clients/cli/common.c:1422 + msgid "portal" + msgstr "portail" + +-#: ../clients/cli/common.c:1401 ++#: ../clients/cli/common.c:1423 + msgid "limited" + msgstr "limité" + +-#: ../clients/cli/common.c:1402 ++#: ../clients/cli/common.c:1424 + msgid "full" + msgstr "plein" + + #. define some prompts for connection editor +-#: ../clients/cli/connections.c:65 ++#: ../clients/cli/connections.c:63 + msgid "Setting name? " + msgstr "Nom du paramètre ?" + +-#: ../clients/cli/connections.c:66 ++#: ../clients/cli/connections.c:64 + msgid "Property name? " + msgstr "Nom de la propriété ?" + +-#: ../clients/cli/connections.c:67 ++#: ../clients/cli/connections.c:65 + msgid "Enter connection type: " + msgstr "Saisissez le type de connexion : " + + #. define some other prompts +-#: ../clients/cli/connections.c:71 ++#: ../clients/cli/connections.c:69 + msgid "Connection (name, UUID, or path): " + msgstr "Connexion (nom, UUID, ou chemin) :" + +-#: ../clients/cli/connections.c:72 ++#: ../clients/cli/connections.c:70 + msgid "VPN connection (name, UUID, or path): " + msgstr "Connexion VPN (nom, UUID, ou chemin) :" + +-#: ../clients/cli/connections.c:73 ++#: ../clients/cli/connections.c:71 + msgid "Connection(s) (name, UUID, or path): " + msgstr "Connexion(s) (nom, UUID, ou chemin) :" + +-#: ../clients/cli/connections.c:74 ++#: ../clients/cli/connections.c:72 + msgid "Connection(s) (name, UUID, path or apath): " + msgstr "Connexion(s) (nom, UUID, path ou apath) : " + +-#: ../clients/cli/connections.c:82 ++#: ../clients/cli/connections.c:80 + msgid "activating" + msgstr "activation" + +-#: ../clients/cli/connections.c:83 ++#: ../clients/cli/connections.c:81 + msgid "activated" + msgstr "activé" + +-#: ../clients/cli/connections.c:84 ../clients/common/nm-client-utils.c:271 ++#: ../clients/cli/connections.c:82 ../clients/common/nm-client-utils.c:275 + msgid "deactivating" + msgstr "désactivation" + +-#: ../clients/cli/connections.c:85 ++#: ../clients/cli/connections.c:83 + msgid "deactivated" + msgstr "désactivé" + +-#: ../clients/cli/connections.c:91 ++#: ../clients/cli/connections.c:89 + msgid "VPN connecting (prepare)" + msgstr "Connexion VPN (préparation)" + +-#: ../clients/cli/connections.c:92 ++#: ../clients/cli/connections.c:90 + msgid "VPN connecting (need authentication)" + msgstr "Connexion VPN (authentification requise)" + +-#: ../clients/cli/connections.c:93 ++#: ../clients/cli/connections.c:91 + msgid "VPN connecting" + msgstr "Connexion VPN" + +-#: ../clients/cli/connections.c:94 ++#: ../clients/cli/connections.c:92 + msgid "VPN connecting (getting IP configuration)" + msgstr "Connexion VPN (obtention de la configuration IP)" + +-#: ../clients/cli/connections.c:95 ++#: ../clients/cli/connections.c:93 + msgid "VPN connected" + msgstr "VPN connecté" + +-#: ../clients/cli/connections.c:96 ++#: ../clients/cli/connections.c:94 + msgid "VPN connection failed" + msgstr "Échec de la connexion VPN" + +-#: ../clients/cli/connections.c:97 ++#: ../clients/cli/connections.c:95 + msgid "VPN disconnected" + msgstr "VPN déconnecté" + +-#: ../clients/cli/connections.c:518 ++#: ../clients/cli/connections.c:516 + msgid "never" + msgstr "jamais" + +@@ -1021,342 +1021,337 @@ msgstr "" + msgid "Error updating secrets for %s: %s\n" + msgstr "Erreur lors de la mise à jour des secrets pour l'objet %s : %s\n" + +-#: ../clients/cli/connections.c:1307 ++#: ../clients/cli/connections.c:1313 + msgid "Connection profile details" + msgstr "Informations de profil de connexion" + +-#: ../clients/cli/connections.c:1320 ../clients/cli/connections.c:1405 ++#: ../clients/cli/connections.c:1326 ../clients/cli/connections.c:1411 + #, c-format + msgid "Error: 'connection show': %s" + msgstr "Erreur : « connection show » : %s" + +-#: ../clients/cli/connections.c:1395 ++#: ../clients/cli/connections.c:1401 + msgid "Activate connection details" + msgstr "Informations d'activation de connexion" + +-#: ../clients/cli/connections.c:1503 ../clients/cli/devices.c:1453 +-#: ../clients/cli/devices.c:1467 ../clients/cli/devices.c:1482 +-#: ../clients/cli/devices.c:1540 ../clients/cli/devices.c:1642 ++#: ../clients/cli/connections.c:1509 ../clients/cli/devices.c:1447 ++#: ../clients/cli/devices.c:1461 ../clients/cli/devices.c:1476 ++#: ../clients/cli/devices.c:1534 ../clients/cli/devices.c:1636 + msgid "NAME" + msgstr "NOM" + +-#: ../clients/cli/connections.c:1591 ++#: ../clients/cli/connections.c:1602 + #, c-format + msgid "invalid field '%s'; allowed fields: %s and %s, or %s,%s" + msgstr "champ invalide « %s » ; champs autorisés : %s et %s, ou %s,%s" + +-#: ../clients/cli/connections.c:1606 ../clients/cli/connections.c:1614 ++#: ../clients/cli/connections.c:1612 ../clients/cli/connections.c:1620 + #, c-format + msgid "'%s' has to be alone" + msgstr "« %s » doit être seul" + +-#: ../clients/cli/connections.c:1876 ++#: ../clients/cli/connections.c:1880 + #, c-format + msgid "incorrect string '%s' of '--order' option" + msgstr "chaîne incorrecte « %s » de l'option « --order »" + +-#: ../clients/cli/connections.c:1901 ++#: ../clients/cli/connections.c:1905 + #, c-format + msgid "incorrect item '%s' in '--order' option" + msgstr "élément incorrect « %s » de l'option « --order »" + +-#: ../clients/cli/connections.c:1939 ++#: ../clients/cli/connections.c:1943 + msgid "No connection specified" + msgstr "Aucune connexion spécifiée." + +-#: ../clients/cli/connections.c:1950 ++#: ../clients/cli/connections.c:1954 + #, c-format + msgid "%s argument is missing" + msgstr "le paramètre %s est manquant" + +-#: ../clients/cli/connections.c:1968 ++#: ../clients/cli/connections.c:1972 + #, c-format + msgid "unknown connection '%s'" + msgstr "connexion inconnue : « %s »" + +-#: ../clients/cli/connections.c:1997 ++#: ../clients/cli/connections.c:2001 + msgid "'--order' argument is missing" + msgstr "l'argument de « --order » est manquant" + +-#: ../clients/cli/connections.c:2057 ++#: ../clients/cli/connections.c:2061 + msgid "NetworkManager active profiles" + msgstr "Profils actifs NetworkManager" + + # auto translated by TM merge from project: NetworkManager, version: 0.9.8.2, DocId: NetworkManager +-#: ../clients/cli/connections.c:2058 ++#: ../clients/cli/connections.c:2062 + msgid "NetworkManager connection profiles" + msgstr "Profils de connexion NetworkManager" + +-#: ../clients/cli/connections.c:2110 ../clients/cli/connections.c:2856 +-#: ../clients/cli/connections.c:2868 ../clients/cli/connections.c:2880 +-#: ../clients/cli/connections.c:3109 ../clients/cli/connections.c:8899 +-#: ../clients/cli/connections.c:8915 ../clients/cli/devices.c:2976 +-#: ../clients/cli/devices.c:2988 ../clients/cli/devices.c:3001 +-#: ../clients/cli/devices.c:3195 ../clients/cli/devices.c:3206 +-#: ../clients/cli/devices.c:3224 ../clients/cli/devices.c:3233 +-#: ../clients/cli/devices.c:3254 ../clients/cli/devices.c:3265 +-#: ../clients/cli/devices.c:3283 ../clients/cli/devices.c:3725 +-#: ../clients/cli/devices.c:3735 ../clients/cli/devices.c:3743 +-#: ../clients/cli/devices.c:3755 ../clients/cli/devices.c:3770 +-#: ../clients/cli/devices.c:3778 ../clients/cli/devices.c:3952 +-#: ../clients/cli/devices.c:3963 ../clients/cli/devices.c:4134 ++#: ../clients/cli/connections.c:2114 ../clients/cli/connections.c:2859 ++#: ../clients/cli/connections.c:2871 ../clients/cli/connections.c:2883 ++#: ../clients/cli/connections.c:3112 ../clients/cli/connections.c:8866 ++#: ../clients/cli/connections.c:8887 ../clients/cli/devices.c:2970 ++#: ../clients/cli/devices.c:2982 ../clients/cli/devices.c:2995 ++#: ../clients/cli/devices.c:3189 ../clients/cli/devices.c:3200 ++#: ../clients/cli/devices.c:3218 ../clients/cli/devices.c:3227 ++#: ../clients/cli/devices.c:3248 ../clients/cli/devices.c:3259 ++#: ../clients/cli/devices.c:3277 ../clients/cli/devices.c:3721 ++#: ../clients/cli/devices.c:3731 ../clients/cli/devices.c:3739 ++#: ../clients/cli/devices.c:3751 ../clients/cli/devices.c:3766 ++#: ../clients/cli/devices.c:3774 ../clients/cli/devices.c:3949 ++#: ../clients/cli/devices.c:3960 ../clients/cli/devices.c:4131 + #, c-format + msgid "Error: %s argument is missing." + msgstr "Erreur : le paramètre %s est manquant." + +-#: ../clients/cli/connections.c:2138 ++#: ../clients/cli/connections.c:2142 + #, c-format + msgid "Error: %s - no such connection profile." + msgstr "Erreur : %s - profil de connexion introuvable." + +-#: ../clients/cli/connections.c:2229 ../clients/cli/connections.c:2843 +-#: ../clients/cli/connections.c:2907 ../clients/cli/connections.c:8419 +-#: ../clients/cli/connections.c:8525 ../clients/cli/connections.c:9015 +-#: ../clients/cli/devices.c:1727 ../clients/cli/devices.c:1995 +-#: ../clients/cli/devices.c:2168 ../clients/cli/devices.c:2276 +-#: ../clients/cli/devices.c:2468 ../clients/cli/devices.c:3915 +-#: ../clients/cli/devices.c:4140 ../clients/cli/general.c:895 ++#: ../clients/cli/connections.c:2233 ../clients/cli/connections.c:2846 ++#: ../clients/cli/connections.c:2910 ../clients/cli/connections.c:8383 ++#: ../clients/cli/connections.c:8489 ../clients/cli/connections.c:8992 ++#: ../clients/cli/devices.c:1721 ../clients/cli/devices.c:1989 ++#: ../clients/cli/devices.c:2162 ../clients/cli/devices.c:2270 ++#: ../clients/cli/devices.c:2462 ../clients/cli/devices.c:3912 ++#: ../clients/cli/devices.c:4137 ../clients/cli/general.c:896 + #, c-format + msgid "Error: %s." + msgstr "Erreur : %s." + +-#: ../clients/cli/connections.c:2322 ++#: ../clients/cli/connections.c:2326 + #, c-format + msgid "no active connection on device '%s'" + msgstr "aucune connexion active sur le périphérique « %s »" + +-#: ../clients/cli/connections.c:2330 ++#: ../clients/cli/connections.c:2334 + msgid "no active connection or device" + msgstr "aucune connexion ou périphérique actif" + +-#: ../clients/cli/connections.c:2350 ++#: ../clients/cli/connections.c:2354 + #, fuzzy, c-format + msgid "device '%s' not compatible with connection '%s': " + msgstr "périphérique « %s » incompatible avec la connexion « %s » :" + +-#: ../clients/cli/connections.c:2383 ++#: ../clients/cli/connections.c:2387 + #, c-format + msgid "device '%s' not compatible with connection '%s'" + msgstr "périphérique « %s » incompatible avec la connexion « %s »" + +-#: ../clients/cli/connections.c:2386 ++#: ../clients/cli/connections.c:2390 + #, c-format + msgid "no device found for connection '%s'" + msgstr "aucun périphérique trouvé pour la connexion « %s »" + +-#: ../clients/cli/connections.c:2437 ++#: ../clients/cli/connections.c:2441 + #, c-format + msgid "Hint: use '%s' to get more details." + msgstr "" + +-#: ../clients/cli/connections.c:2455 ++#: ../clients/cli/connections.c:2459 + #, c-format + msgid "Connection successfully activated (%s) (D-Bus active path: %s)\n" + msgstr "Connexion activée (%s) (Chemin D-Bus actif : %s)\n" + +-#: ../clients/cli/connections.c:2459 ../clients/cli/connections.c:2609 +-#: ../clients/cli/connections.c:6716 ++#: ../clients/cli/connections.c:2463 ../clients/cli/connections.c:2613 ++#: ../clients/cli/connections.c:6701 + #, c-format + msgid "Connection successfully activated (D-Bus active path: %s)\n" + msgstr "Connexion activée (chemin D-Bus actif : %s)\n" + +-#: ../clients/cli/connections.c:2466 ../clients/cli/connections.c:2588 ++#: ../clients/cli/connections.c:2470 ../clients/cli/connections.c:2592 + #, c-format + msgid "Error: Connection activation failed: %s" + msgstr "Erreur : l'activation de la connexion a échoué : %s" + +-#: ../clients/cli/connections.c:2503 ++#: ../clients/cli/connections.c:2507 + #, c-format + msgid "Error: Timeout expired (%d seconds)" + msgstr "Erreur : le délai d'attente a expiré (%d secondes)" + +-#: ../clients/cli/connections.c:2671 ++#: ../clients/cli/connections.c:2675 + #, c-format + msgid "failed to read passwd-file '%s': %s" + msgstr "Erreur : échec de lecture du fichier de mot de passe « %s » : %s" + +-#: ../clients/cli/connections.c:2684 ++#: ../clients/cli/connections.c:2688 + #, c-format + msgid "missing colon in 'password' entry '%s'" + msgstr "Virgule manquant dans la saisie du mot de passe « %s »" + +-#: ../clients/cli/connections.c:2692 ++#: ../clients/cli/connections.c:2696 + #, c-format + msgid "missing dot in 'password' entry '%s'" + msgstr "Point manquant dans la saisie du mot de passe « %s »" + +-#: ../clients/cli/connections.c:2705 ++#: ../clients/cli/connections.c:2709 + #, c-format + msgid "invalid setting name in 'password' entry '%s'" + msgstr "Nom du paramètre non valide dans la saisie du mot de passe « %s »" + +-#: ../clients/cli/connections.c:2759 ++#: ../clients/cli/connections.c:2763 + #, c-format + msgid "unknown device '%s'." + msgstr "périphérique inconnu « %s »." + +-#: ../clients/cli/connections.c:2764 ++#: ../clients/cli/connections.c:2768 + msgid "neither a valid connection nor device given" + msgstr "pas de connexion ni de périphérique valide n'a été donné" + +-#: ../clients/cli/connections.c:2890 ../clients/cli/devices.c:1686 +-#: ../clients/cli/devices.c:3033 ../clients/cli/devices.c:3296 +-#: ../clients/cli/devices.c:3969 ++#: ../clients/cli/connections.c:2893 ../clients/cli/devices.c:1680 ++#: ../clients/cli/devices.c:3027 ../clients/cli/devices.c:3290 ++#: ../clients/cli/devices.c:3966 + #, c-format + msgid "Unknown parameter: %s\n" + msgstr "Paramètre inconnu : %s\n" + +-#: ../clients/cli/connections.c:2915 ++#: ../clients/cli/connections.c:2918 + msgid "preparing" + msgstr "préparation" + +-#: ../clients/cli/connections.c:3024 ++#: ../clients/cli/connections.c:3027 + #, c-format + msgid "Connection '%s' (%s) successfully deleted.\n" + msgstr "Connexion « %s » (%s) supprimée.\n" + +-#: ../clients/cli/connections.c:3040 ++#: ../clients/cli/connections.c:3043 + #, c-format + msgid "Connection '%s' successfully deactivated (D-Bus active path: %s)\n" + msgstr "Connexion « %s » désactivée (chemin D-Bus actif : %s)\n" + +-#: ../clients/cli/connections.c:3091 ../clients/cli/connections.c:8633 +-#: ../clients/cli/connections.c:8664 ../clients/cli/connections.c:8822 ++#: ../clients/cli/connections.c:3094 ../clients/cli/connections.c:8597 ++#: ../clients/cli/connections.c:8628 ../clients/cli/connections.c:8786 + #, c-format + msgid "Error: No connection specified." + msgstr "Erreur : aucune connexion spécifiée." + +-#: ../clients/cli/connections.c:3121 ++#: ../clients/cli/connections.c:3124 + #, c-format + msgid "Error: '%s' is not an active connection.\n" + msgstr "Erreur : « %s » n'est pas une connexion active.\n" + +-#: ../clients/cli/connections.c:3122 ++#: ../clients/cli/connections.c:3125 + #, c-format + msgid "Error: not all active connections found." + msgstr "Erreur : les connexions n'ont pas toutes été trouvées." + +-#: ../clients/cli/connections.c:3130 ++#: ../clients/cli/connections.c:3133 + #, c-format + msgid "Error: no active connection provided." + msgstr "Erreur : aucune connexion fournie." + +-#: ../clients/cli/connections.c:3161 ++#: ../clients/cli/connections.c:3164 + #, c-format + msgid "Connection '%s' deactivation failed: %s\n" + msgstr "La désactivation de la connexion « %s » a échoué : %s\n" + +-#: ../clients/cli/connections.c:3412 ../clients/cli/connections.c:3469 +-#: ../clients/common/nm-client-utils.c:221 ++#: ../clients/cli/connections.c:3415 ../clients/cli/connections.c:3472 ++#: ../clients/common/nm-client-utils.c:225 + #, c-format + msgid "'%s' not among [%s]" + msgstr "« %s » ne fait pas partie de [%s]" + + #. We should not really come here +-#: ../clients/cli/connections.c:3432 ../clients/cli/connections.c:3492 +-#: ../clients/common/nm-client-utils.c:289 ++#: ../clients/cli/connections.c:3435 ../clients/cli/connections.c:3495 ++#: ../clients/common/nm-client-utils.c:293 + #, c-format + msgid "Unknown error" + msgstr "Erreur inconnue" + +-#: ../clients/cli/connections.c:3626 ++#: ../clients/cli/connections.c:3629 + #, c-format + msgid "Warning: master='%s' doesn't refer to any existing profile.\n" + msgstr "" + "Avertissement : master=« %s » ne correspond à un aucun profil existant.\n" + +-#: ../clients/cli/connections.c:3979 ++#: ../clients/cli/connections.c:3984 + #, c-format + msgid "Error: invalid property '%s': %s." + msgstr "Erreur : propriété « %s » non valide : %s." + +-#: ../clients/cli/connections.c:3996 +-#, c-format +-msgid "Error: failed to modify %s.%s: %s." ++#: ../clients/cli/connections.c:3998 ++#, fuzzy, c-format ++msgid "Error: failed to %s %s.%s: %s." + msgstr "Erreur : échec de la modification de %s.%s : %s." + +-#: ../clients/cli/connections.c:4016 +-#, c-format +-msgid "Error: failed to remove a value from %s.%s: %s." +-msgstr "Erreur : échec lors de la suppression d'une valeur de %s.%s : %s." +- +-#: ../clients/cli/connections.c:4050 ++#: ../clients/cli/connections.c:4033 + #, c-format + msgid "Error: '%s' is mandatory." + msgstr "Erreur : « %s » est obligatoire." + +-#: ../clients/cli/connections.c:4077 ++#: ../clients/cli/connections.c:4060 + #, c-format + msgid "Error: invalid slave type; %s." + msgstr "Erreur : type esclave invalide ; %s." + +-#: ../clients/cli/connections.c:4085 ++#: ../clients/cli/connections.c:4068 + #, c-format + msgid "Error: invalid connection type; %s." + msgstr "Erreur : type de connexion non valide ; %s." + +-#: ../clients/cli/connections.c:4162 ++#: ../clients/cli/connections.c:4145 + #, c-format + msgid "Error: bad connection type: %s" + msgstr "Erreur : type de connexion invalide : %s." + +-#: ../clients/cli/connections.c:4208 ++#: ../clients/cli/connections.c:4191 + #, c-format + msgid "Error: '%s': %s" + msgstr "Erreur : « %s » : %s" + +-#: ../clients/cli/connections.c:4229 ++#: ../clients/cli/connections.c:4212 + msgid "Error: master is required" + msgstr "Erreur : « master » requis." + +-#: ../clients/cli/connections.c:4288 ++#: ../clients/cli/connections.c:4271 + #, c-format + msgid "Error: error adding bond option '%s=%s'." + msgstr "Erreur : erreur à l'ajout de l'option d'agrégation de lien « %s=%s »." + +-#: ../clients/cli/connections.c:4319 ++#: ../clients/cli/connections.c:4302 + #, c-format + msgid "Error: '%s' is not a valid monitoring mode; use '%s' or '%s'.\n" + msgstr "" + "Erreur : « %s » n'est pas un mode de contrôle valide ; utilisez « %s » ou " + "« %s ».\n" + +-#: ../clients/cli/connections.c:4350 ++#: ../clients/cli/connections.c:4333 + #, c-format + msgid "Error: 'bt-type': '%s' not valid; use [%s, %s, %s (%s), %s]." + msgstr "" + "Erreur:'bt-type' : ' ' '%s non valide ; utiliser [%s, %s, %s (%s), ]%s." + +-#: ../clients/cli/connections.c:4599 ++#: ../clients/cli/connections.c:4582 + #, c-format + msgid "Error: value for '%s' is missing." + msgstr "Erreur : la valeur de l'argument « %s » est requise." + +-#: ../clients/cli/connections.c:4645 ++#: ../clients/cli/connections.c:4628 + msgid "Error: . argument is missing." + msgstr "Erreur : l'argument . est manquant." + +-#: ../clients/cli/connections.c:4668 ++#: ../clients/cli/connections.c:4651 + #, c-format + msgid "Error: invalid or not allowed setting '%s': %s." + msgstr "Erreur : non valide, ou le paramètre « %s » n'est pas autorisé : %s." + +-#: ../clients/cli/connections.c:4714 ../clients/cli/connections.c:4730 ++#: ../clients/cli/connections.c:4699 ../clients/cli/connections.c:4715 + #, c-format + msgid "Error: '%s' is ambiguous (%s.%s or %s.%s)." + msgstr "Erreur : « %s » est ambigu (%s.%s ou %s.%s)." + +-#: ../clients/cli/connections.c:4748 ++#: ../clients/cli/connections.c:4733 + #, c-format + msgid "Error: invalid . '%s'." + msgstr "Erreur : . non valide '%s’." + +-#: ../clients/cli/connections.c:4792 ../clients/cli/connections.c:8465 ++#: ../clients/cli/connections.c:4777 ../clients/cli/connections.c:8429 + #, c-format + msgid "Error: Failed to add '%s' connection: %s" + msgstr "Erreur: impossible d'ajouter la connexion « %s » : %s" + +-#: ../clients/cli/connections.c:4810 ++#: ../clients/cli/connections.c:4795 + #, c-format + msgid "" + "Warning: There is another connection with the name '%1$s'. Reference the " +@@ -1371,32 +1366,32 @@ msgstr[1] "" + "Attention : il y a %3$u autres connexions avec le nom '%1$s’. Référez-vous à " + "la connexion par son uuid '%2$s'\n" + +-#: ../clients/cli/connections.c:4819 ++#: ../clients/cli/connections.c:4804 + #, c-format + msgid "Connection '%s' (%s) successfully added.\n" + msgstr "Connexion « %s » (%s) ajoutée avec succès.\n" + +-#: ../clients/cli/connections.c:4872 ../clients/cli/connections.c:6839 +-#: ../clients/cli/connections.c:6840 ../clients/cli/devices.c:535 +-#: ../clients/cli/devices.c:542 ../clients/cli/devices.c:1207 +-#: ../clients/cli/general.c:136 ../clients/cli/utils.h:296 +-#: ../clients/common/nm-client-utils.c:279 +-#: ../clients/common/nm-meta-setting-desc.c:771 +-#: ../clients/common/nm-meta-setting-desc.c:2752 ++#: ../clients/cli/connections.c:4857 ../clients/cli/connections.c:6824 ++#: ../clients/cli/connections.c:6825 ../clients/cli/devices.c:529 ++#: ../clients/cli/devices.c:536 ../clients/cli/devices.c:1201 ++#: ../clients/cli/general.c:137 ../clients/cli/utils.h:296 ++#: ../clients/common/nm-client-utils.c:283 ++#: ../clients/common/nm-meta-setting-desc.c:939 ++#: ../clients/common/nm-meta-setting-desc.c:2703 + msgid "no" + msgstr "non" + +-#: ../clients/cli/connections.c:4873 ../clients/cli/connections.c:6839 +-#: ../clients/cli/connections.c:6840 ../clients/cli/devices.c:534 +-#: ../clients/cli/devices.c:541 ../clients/cli/devices.c:1207 +-#: ../clients/cli/general.c:135 ../clients/cli/utils.h:296 +-#: ../clients/common/nm-client-utils.c:278 +-#: ../clients/common/nm-meta-setting-desc.c:771 +-#: ../clients/common/nm-meta-setting-desc.c:2749 ++#: ../clients/cli/connections.c:4858 ../clients/cli/connections.c:6824 ++#: ../clients/cli/connections.c:6825 ../clients/cli/devices.c:528 ++#: ../clients/cli/devices.c:535 ../clients/cli/devices.c:1201 ++#: ../clients/cli/general.c:136 ../clients/cli/utils.h:296 ++#: ../clients/common/nm-client-utils.c:282 ++#: ../clients/common/nm-meta-setting-desc.c:939 ++#: ../clients/common/nm-meta-setting-desc.c:2700 + msgid "yes" + msgstr "oui" + +-#: ../clients/cli/connections.c:4959 ++#: ../clients/cli/connections.c:4944 + #, c-format + msgid "" + "You can specify this option more than once. Press when you're done.\n" +@@ -1405,36 +1400,36 @@ msgstr "" + "vous avez terminé.\n" + + #. Ask for optional arguments. +-#: ../clients/cli/connections.c:5061 ++#: ../clients/cli/connections.c:5046 + #, c-format + msgid "There is %d optional setting for %s.\n" + msgid_plural "There are %d optional settings for %s.\n" + msgstr[0] "Il existe %d paramètre optionnel pour %s.\n" + msgstr[1] "Il existe %d paramètres optionnels pour %s.\n" + +-#: ../clients/cli/connections.c:5067 ++#: ../clients/cli/connections.c:5052 + #, c-format + msgid "Do you want to provide it? %s" + msgid_plural "Do you want to provide them? %s" + msgstr[0] "Souhaitez-vous le fournir ? %s" + msgstr[1] "Souhaitez-vous les fournir ? %s" + +-#: ../clients/cli/connections.c:5200 ../clients/cli/utils.c:295 ++#: ../clients/cli/connections.c:5185 ../clients/cli/utils.c:293 + #, c-format + msgid "Error: value for '%s' argument is required." + msgstr "Erreur : la valeur de l'argument « %s » est requise." + +-#: ../clients/cli/connections.c:5207 ++#: ../clients/cli/connections.c:5192 + #, c-format + msgid "Error: 'save': %s." + msgstr "Erreur: « save » : %s." + +-#: ../clients/cli/connections.c:5293 ../clients/cli/connections.c:5304 ++#: ../clients/cli/connections.c:5278 ../clients/cli/connections.c:5289 + #, c-format + msgid "Error: '%s' argument is required." + msgstr "Erreur : l'argument « %s » est requis." + +-#: ../clients/cli/connections.c:6269 ++#: ../clients/cli/connections.c:6254 + #, c-format + msgid "['%s' setting values]\n" + msgstr "[« %s » setting values]\n" +@@ -1442,7 +1437,7 @@ msgstr "[« %s » setting values]\n" + #. TRANSLATORS: do not translate command names and keywords before :: + #. * However, you should translate terms enclosed in <>. + #. +-#: ../clients/cli/connections.c:6378 ++#: ../clients/cli/connections.c:6363 + #, c-format + msgid "" + "---[ Main menu ]---\n" +@@ -1477,7 +1472,7 @@ msgstr "" + "nmcli :: configuration de nmcli\n" + "quit :: quitter nmcli\n" + +-#: ../clients/cli/connections.c:6405 ++#: ../clients/cli/connections.c:6390 + #, c-format + msgid "" + "goto [.] | :: enter setting/property for editing\n" +@@ -1498,7 +1493,7 @@ msgstr "" + " nmcli connection> goto secondaries\n" + " nmcli> goto ipv4.addresses\n" + +-#: ../clients/cli/connections.c:6412 ++#: ../clients/cli/connections.c:6397 + #, c-format + msgid "" + "remove [.] :: remove setting or reset property value\n" +@@ -1520,7 +1515,7 @@ msgstr "" + "Exemples : nmcli> remove wifi-sec\n" + " nmcli> remove eth.mtu\n" + +-#: ../clients/cli/connections.c:6419 ++#: ../clients/cli/connections.c:6404 + #, c-format + msgid "" + "set [. ] :: set property value\n" +@@ -1535,7 +1530,7 @@ msgstr "" + "\n" + "Exemple : nmcli> set con.id My connection\n" + +-#: ../clients/cli/connections.c:6424 ++#: ../clients/cli/connections.c:6409 + #, c-format + msgid "" + "describe [.] :: describe property\n" +@@ -1548,7 +1543,7 @@ msgstr "" + "Affiche la description de la propriété. Vous pouvez consulter la page du " + "manuel nm-settings(5) pour afficher tous les paramètres et propriétés NM.\n" + +-#: ../clients/cli/connections.c:6429 ++#: ../clients/cli/connections.c:6414 + #, c-format + msgid "" + "print [all] :: print setting or connection values\n" +@@ -1563,7 +1558,7 @@ msgstr "" + "\n" + "Exemple : nmcli ipv4> print all\n" + +-#: ../clients/cli/connections.c:6434 ++#: ../clients/cli/connections.c:6419 + #, c-format + msgid "" + "verify [all | fix] :: verify setting or connection validity\n" +@@ -1589,7 +1584,7 @@ msgstr "" + " nmcli> verify fix\n" + " nmcli bond> verifyerify\n" + +-#: ../clients/cli/connections.c:6443 ++#: ../clients/cli/connections.c:6428 + #, c-format + msgid "" + "save [persistent|temporary] :: save the connection\n" +@@ -1619,7 +1614,7 @@ msgstr "" + "connexion\n" + "persitante, le profil de connexion devra être supprimé.\n" + +-#: ../clients/cli/connections.c:6454 ++#: ../clients/cli/connections.c:6439 + #, c-format + msgid "" + "activate [] [/|] :: activate the connection\n" +@@ -1640,7 +1635,7 @@ msgstr "" + "/| - AP (Wi-Fi) ou NSP (WiMAX) (ajouter avec ou lorsque " + "n'est pas spécifié)\n" + +-#: ../clients/cli/connections.c:6461 ../clients/cli/connections.c:6619 ++#: ../clients/cli/connections.c:6446 ../clients/cli/connections.c:6604 + #, c-format + msgid "" + "back :: go to upper menu level\n" +@@ -1649,7 +1644,7 @@ msgstr "" + "back :: aller au niveau supérieur du menu\n" + "\n" + +-#: ../clients/cli/connections.c:6464 ++#: ../clients/cli/connections.c:6449 + #, c-format + msgid "" + "help/? [] :: help for the nmcli commands\n" +@@ -1658,7 +1653,7 @@ msgstr "" + "help/? [] :: aide pour les commandes nmcli\n" + "\n" + +-#: ../clients/cli/connections.c:6467 ++#: ../clients/cli/connections.c:6452 + #, c-format + msgid "" + "nmcli [ ] :: nmcli configuration\n" +@@ -1684,7 +1679,7 @@ msgstr "" + " nmcli> nmcli save-confirmation no\n" + " nmcli> nmcli prompt-color 3\n" + +-#: ../clients/cli/connections.c:6489 ../clients/cli/connections.c:6625 ++#: ../clients/cli/connections.c:6474 ../clients/cli/connections.c:6610 + #, c-format + msgid "" + "quit :: exit nmcli\n" +@@ -1698,8 +1693,8 @@ msgstr "" + "modification n'est pas enregistrée, il est demandé à l'utilisateur de " + "confirmer l'action.\n" + +-#: ../clients/cli/connections.c:6494 ../clients/cli/connections.c:6630 +-#: ../clients/cli/connections.c:7065 ../clients/cli/connections.c:8048 ++#: ../clients/cli/connections.c:6479 ../clients/cli/connections.c:6615 ++#: ../clients/cli/connections.c:7024 ../clients/cli/connections.c:8009 + #, c-format + msgid "Unknown command: '%s'\n" + msgstr "Commande inconnue : « %s »\n" +@@ -1707,7 +1702,7 @@ msgstr "Commande inconnue : « %s »\n" + #. TRANSLATORS: do not translate command names and keywords before :: + #. * However, you should translate terms enclosed in <>. + #. +-#: ../clients/cli/connections.c:6559 ++#: ../clients/cli/connections.c:6544 + #, c-format + msgid "" + "---[ Property menu ]---\n" +@@ -1736,7 +1731,7 @@ msgstr "" + "commande\n" + "quit :: quitter nmcli\n" + +-#: ../clients/cli/connections.c:6584 ++#: ../clients/cli/connections.c:6569 + #, c-format + msgid "" + "set [] :: set new value\n" +@@ -1747,7 +1742,7 @@ msgstr "" + "\n" + "Cette commande définit la (valeur) fournie à cette propriété\n" + +-#: ../clients/cli/connections.c:6588 ++#: ../clients/cli/connections.c:6573 + #, c-format + msgid "" + "add [] :: append new value to the property\n" +@@ -1762,7 +1757,7 @@ msgstr "" + "propriété est d'un type de conteneur. Pour les propriétés à valeur unique, " + "ceci remplace la valeur (comme « set »).\n" + +-#: ../clients/cli/connections.c:6594 ++#: ../clients/cli/connections.c:6579 + #, c-format + msgid "" + "change :: change current value\n" +@@ -1773,7 +1768,7 @@ msgstr "" + "\n" + "Affiche la valeur actuelle et permet sa modification.\n" + +-#: ../clients/cli/connections.c:6598 ++#: ../clients/cli/connections.c:6583 + #, c-format + msgid "" + "remove [||