summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-11-17 12:52:14 +0100
committerThomas Haller <thaller@redhat.com>2023-11-17 12:52:14 +0100
commit087ae7df3c746b1768990f54ab3c33a3872a6c4d (patch)
tree686f98717e61c6c89c930081637515dd795adf0e
parent83a1ce39b05a18227d8a1674bffba482c807ce45 (diff)
parentea8dbd7a6d0f29a35f573f12630fbad46f520dc0 (diff)
wifi: merge branch 'th/fedora-wifi-mac-addr-rand'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1789
-rw-r--r--NEWS4
-rw-r--r--contrib/fedora/rpm/22-wifi-mac-addr.conf31
-rw-r--r--contrib/fedora/rpm/NetworkManager.spec20
-rwxr-xr-xcontrib/fedora/rpm/build.sh2
-rw-r--r--src/core/NetworkManagerUtils.c4
-rw-r--r--src/core/devices/nm-device.c34
-rw-r--r--src/core/nm-core-utils.c31
-rw-r--r--src/core/nm-core-utils.h4
-rw-r--r--src/core/tests/test-core.c42
-rw-r--r--src/libnm-core-aux-intern/nm-common-macros.h29
-rw-r--r--src/libnm-core-impl/nm-keyfile.c11
-rw-r--r--src/libnm-core-impl/nm-setting-connection.c16
-rw-r--r--src/libnm-core-impl/nm-setting-wired.c2
-rw-r--r--src/libnm-core-impl/nm-setting-wireless.c6
-rw-r--r--src/libnmc-setting/nm-meta-setting-desc.c10
-rw-r--r--src/libnmc-setting/nm-meta-setting-desc.h3
-rw-r--r--src/libnmc-setting/settings-docs.h.in4
-rw-r--r--src/nmcli/gen-metadata-nm-settings-nmcli.c23
-rw-r--r--src/nmcli/gen-metadata-nm-settings-nmcli.xml.in6
-rw-r--r--src/nmtui/nmt-mac-entry.c8
-rw-r--r--src/nmtui/nmt-mac-entry.h3
-rw-r--r--src/nmtui/nmt-page-bond.c2
-rw-r--r--src/nmtui/nmt-page-ethernet.c2
-rw-r--r--src/nmtui/nmt-page-vlan.c2
-rw-r--r--src/nmtui/nmt-page-wifi.c2
25 files changed, 240 insertions, 61 deletions
diff --git a/NEWS b/NEWS
index cd46906b50..5759157b42 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,10 @@ NetworkManager-1.46
Overview of changes since NetworkManager-1.44
=============================================
+* Support dynamic value "${NETWORK_SSID}" for connection.stable-id to generate
+ the stable ID based on the Wi-Fi's SSID.
+* Support new value "wifi.cloned-mac-address=stable-ssid" for randomizing the
+ MAC address based on the Wi-Fi network.
* Change internal ABI of NMSetting types and NMSimpleConnection. The layout of
these structs was already hidden from public headers since 1.34 and this change
should not be noticeable.
diff --git a/contrib/fedora/rpm/22-wifi-mac-addr.conf b/contrib/fedora/rpm/22-wifi-mac-addr.conf
new file mode 100644
index 0000000000..2e329c8895
--- /dev/null
+++ b/contrib/fedora/rpm/22-wifi-mac-addr.conf
@@ -0,0 +1,31 @@
+# This sets defaults for Wi-Fi profiles to set a generated, stable MAC address.
+#
+# Do not modify this file. You can hide/overwrite this file by placing a file
+# to "/etc/NetworkManager/conf.d/22-wifi-mac-addr.conf". You can also add
+# configuration snippets with higher priority that override this setting (see
+# `man 5 NetworkManager.conf`). Most importantly, this snippet only sets
+# default values for the profile. You can explicitly set the value for each
+# profile, so that this default value is not used.
+#
+# For example, on a particular profile/network set
+#
+# $ nmcli connection modify "$PROFILE" wifi.cloned-mac-address permanent
+#
+# to use the hardware MAC address. This prevents the default from this file
+# to take effect.
+#
+# Or
+#
+# $ nmcli connection modify "$PROFILE" wifi.cloned-mac-address stable connection.stable-id '${NETWORK_SSID}/${BOOT}'
+#
+# to get a generated MAC address that changes on each boot. Note how setting
+# "connection.stable-id" also affects other aspects of the profile.
+#
+# See `man 5 nm-settings` for "wifi.cloned-mac-address" and "connection.stable-id".
+
+[connection.22-wifi-mac-addr]
+match-device=type:wifi
+wifi.cloned-mac-address=stable-ssid
+
+[.config]
+enable=nm-version-min:1.45
diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec
index db07a30ac7..65e64f3b73 100644
--- a/contrib/fedora/rpm/NetworkManager.spec
+++ b/contrib/fedora/rpm/NetworkManager.spec
@@ -209,9 +209,10 @@ Source1: NetworkManager.conf
Source2: 00-server.conf
Source4: 20-connectivity-fedora.conf
Source5: 20-connectivity-redhat.conf
-Source6: 70-nm-connectivity.conf
-Source7: readme-ifcfg-rh.txt
-Source8: readme-ifcfg-rh-migrated.txt
+Source6: 22-wifi-mac-addr.conf
+Source7: 70-nm-connectivity.conf
+Source8: readme-ifcfg-rh.txt
+Source9: readme-ifcfg-rh-migrated.txt
#Patch1: 0001-some.patch
@@ -918,14 +919,18 @@ cp %{SOURCE4} %{buildroot}%{nmlibdir}/conf.d/
%if %{with connectivity_redhat}
cp %{SOURCE5} %{buildroot}%{nmlibdir}/conf.d/
mkdir -p %{buildroot}%{_sysctldir}
-cp %{SOURCE6} %{buildroot}%{_sysctldir}
+cp %{SOURCE7} %{buildroot}%{_sysctldir}
+%endif
+
+%if 0%{?fedora} >= 40
+cp %{SOURCE6} %{buildroot}%{nmlibdir}/conf.d/
%endif
%if 0%{?ifcfg_warning}
-cp %{SOURCE7} %{buildroot}%{_sysconfdir}/sysconfig/network-scripts
+cp %{SOURCE8} %{buildroot}%{_sysconfdir}/sysconfig/network-scripts
%endif
%if 0%{?ifcfg_migrate}
-cp %{SOURCE8} %{buildroot}%{_sysconfdir}/sysconfig/network-scripts/readme-ifcfg-rh.txt
+cp %{SOURCE9} %{buildroot}%{_sysconfdir}/sysconfig/network-scripts/readme-ifcfg-rh.txt
%endif
cp examples/dispatcher/10-ifcfg-rh-routes.sh %{buildroot}%{nmlibdir}/dispatcher.d/
@@ -1072,6 +1077,9 @@ fi
%dir %{_sysconfdir}/%{name}/dnsmasq-shared.d
%dir %{_sysconfdir}/%{name}/system-connections
%config(noreplace) %{_sysconfdir}/%{name}/NetworkManager.conf
+%if 0%{?fedora} >= 40
+%{nmlibdir}/conf.d/22-wifi-mac-addr.conf.conf
+%endif
%ghost %{_sysconfdir}/%{name}/VPN
%{_bindir}/nm-online
%{_libexecdir}/nm-dhcp-helper
diff --git a/contrib/fedora/rpm/build.sh b/contrib/fedora/rpm/build.sh
index 838119ed48..8160b915e6 100755
--- a/contrib/fedora/rpm/build.sh
+++ b/contrib/fedora/rpm/build.sh
@@ -145,6 +145,7 @@ SOURCE_NETWORKMANAGER_CONF="$(abs_path "$SOURCE_NETWORKMANAGER_CONF" "$SCRIPTDIR
SOURCE_CONFIG_SERVER="$(abs_path "$SOURCE_CONFIG_SERVER" "$SCRIPTDIR/00-server.conf")" || die "invalid \$SOURCE_CONFIG_SERVER argument"
SOURCE_CONFIG_CONNECTIVITY_FEDORA="$(abs_path "$SOURCE_CONFIG_CONNECTIVITY_FEDORA" "$SCRIPTDIR/20-connectivity-fedora.conf")" || die "invalid \$SOURCE_CONFIG_CONNECTIVITY_FEDORA argument"
SOURCE_CONFIG_CONNECTIVITY_REDHAT="$(abs_path "$SOURCE_CONFIG_CONNECTIVITY_REDHAT" "$SCRIPTDIR/20-connectivity-redhat.conf")" || die "invalid \$SOURCE_CONFIG_CONNECTIVITY_REDHAT argument"
+SOURCE_CONFIG_WIFI_MAC_ADDR="$(abs_path "$SOURCE_CONFIG_WIFI_MAC_ADDR" "$SCRIPTDIR/22-wifi-mac-addr.conf")" || die "invalid \$SOURCE_CONFIG_WIFI_MAC_ADDR argument"
SOURCE_SYSCTL_RP_FILTER_REDHAT="$(abs_path "$SOURCE_SYSCTL_RP_FILTER_REDHAT" "$SCRIPTDIR/70-nm-connectivity.conf")" || die "invalid \$SOURCE_SYSCTL_RP_FILTER_REDHAT argument"
SOURCE_README_IFCFG_FILES="$(abs_path "$SOURCE_README_IFCFG_FILES" "$SCRIPTDIR/readme-ifcfg-rh.txt")" || die "invalid \$SOURCE_README_IFCFG_FILES argument"
SOURCE_README_IFCFG_MIGRATED="$(abs_path "$SOURCE_README_IFCFG_MIGRATED" "$SCRIPTDIR/readme-ifcfg-rh-migrated.txt")" || die "invalid \$SOURCE_README_IFCFG_MIGRATED argument"
@@ -203,6 +204,7 @@ cp "$SOURCE_NETWORKMANAGER_CONF" "$TEMP/SOURCES/NetworkManager.conf" || die "Cou
cp "$SOURCE_CONFIG_SERVER" "$TEMP/SOURCES/00-server.conf" || die "Could not copy source $SOURCE_CONFIG_SERVER to $TEMP/SOURCES"
cp "$SOURCE_CONFIG_CONNECTIVITY_FEDORA" "$TEMP/SOURCES/20-connectivity-fedora.conf" || die "Could not copy source $SOURCE_CONFIG_CONNECTIVITY_FEDORA to $TEMP/SOURCES"
cp "$SOURCE_CONFIG_CONNECTIVITY_REDHAT" "$TEMP/SOURCES/20-connectivity-redhat.conf" || die "Could not copy source $SOURCE_CONFIG_CONNECTIVITY_REDHAT to $TEMP/SOURCES"
+cp "$SOURCE_CONFIG_WIFI_MAC_ADDR" "$TEMP/SOURCES/22-wifi-mac-addr.conf" || die "Could not copy source $SOURCE_CONFIG_WIFI_MAC_ADDR to $TEMP/SOURCES"
cp "$SOURCE_SYSCTL_RP_FILTER_REDHAT" "$TEMP/SOURCES/70-nm-connectivity.conf" || die "Could not copy source $SOURCE_SYSCTL_RP_FILTER_REDHAT to $TEMP/SOURCES"
cp "$SOURCE_README_IFCFG_FILES" "$TEMP/SOURCES/readme-ifcfg-rh.txt" || die "Could not copy source $SOURCE_README_IFCFG_FILES to $TEMP/SOURCES"
cp "$SOURCE_README_IFCFG_MIGRATED" "$TEMP/SOURCES/readme-ifcfg-rh-migrated.txt" || die "Could not copy source $SOURCE_README_IFCFG_MIGRATED to $TEMP/SOURCES"
diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c
index 7b6a20ab42..84379cdf95 100644
--- a/src/core/NetworkManagerUtils.c
+++ b/src/core/NetworkManagerUtils.c
@@ -670,9 +670,9 @@ check_connection_cloned_mac_address(NMConnection *orig,
cand_mac = nm_setting_wired_get_cloned_mac_address(s_wired_cand);
/* special cloned mac address entries are accepted. */
- if (NM_CLONED_MAC_IS_SPECIAL(orig_mac))
+ if (NM_CLONED_MAC_IS_SPECIAL(orig_mac, FALSE))
orig_mac = NULL;
- if (NM_CLONED_MAC_IS_SPECIAL(cand_mac))
+ if (NM_CLONED_MAC_IS_SPECIAL(cand_mac, FALSE))
cand_mac = NULL;
if (!orig_mac || !cand_mac) {
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 7a2b9e1060..b7e855bcde 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -1033,12 +1033,14 @@ _prop_get_connection_stable_id(NMDevice *self,
gs_free char *generated = NULL;
NMUtilsStableType stable_type;
NMSettingConnection *s_con;
+ NMSettingWireless *s_wifi;
gboolean hwaddr_is_fake;
const char *hwaddr;
const char *stable_id;
const char *uuid;
- s_con = nm_connection_get_setting_connection(connection);
+ s_con = nm_connection_get_setting_connection(connection);
+ s_wifi = nm_connection_get_setting_wireless(connection);
stable_id = nm_setting_connection_get_stable_id(s_con);
@@ -1061,6 +1063,7 @@ _prop_get_connection_stable_id(NMDevice *self,
!hwaddr_is_fake ? hwaddr : NULL,
nm_utils_boot_id_str(),
uuid,
+ s_wifi ? nm_setting_wireless_get_ssid(s_wifi) : NULL,
&generated);
/* current_stable_id_type is a bitfield! */
@@ -2349,7 +2352,7 @@ _prop_get_x_cloned_mac_address(NMDevice *self, NMConnection *connection, gboolea
if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
addr = NM_CLONED_MAC_RANDOM;
}
- } else if (NM_CLONED_MAC_IS_SPECIAL(a) || nm_utils_hwaddr_valid(a, ETH_ALEN))
+ } else if (NM_CLONED_MAC_IS_SPECIAL(a, is_wifi) || nm_utils_hwaddr_valid(a, ETH_ALEN))
addr = a;
}
@@ -17430,9 +17433,12 @@ _hw_addr_get_cloned(NMDevice *self,
addr_out = g_steal_pointer(&hw_addr_generated);
type_out = HW_ADDR_TYPE_GENERATED;
- } else if (NM_IN_STRSET(addr, NM_CLONED_MAC_STABLE)) {
+ } else if (nm_streq(addr, NM_CLONED_MAC_STABLE)
+ || (is_wifi && nm_streq(addr, NM_CLONED_MAC_STABLE_SSID))) {
+ gs_free char *stable_id_free = NULL;
NMUtilsStableType stable_type;
const char *stable_id;
+ GBytes *ssid = NULL;
if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) {
/* hm, we already use a generate MAC address. Most certainly, that is from the same
@@ -17440,7 +17446,27 @@ _hw_addr_get_cloned(NMDevice *self,
goto out_no_action;
}
- stable_id = _prop_get_connection_stable_id(self, connection, &stable_type);
+ if (!nm_streq(addr, NM_CLONED_MAC_STABLE)) {
+ NMSettingWireless *s_wifi;
+
+ s_wifi = nm_connection_get_setting_wireless(connection);
+ if (s_wifi)
+ ssid = nm_setting_wireless_get_ssid(s_wifi);
+ }
+
+ if (G_UNLIKELY(ssid)) {
+ stable_type = nm_utils_stable_id_parse_network_ssid(ssid,
+ nm_connection_get_uuid(connection),
+ &stable_id_free);
+ stable_id = stable_id_free;
+ } else {
+ /* If @addr is NM_CLONED_MAC_STABLE_SSID, and this is not a Wi-Fi
+ * profile, the behavior is the same as NM_CLONED_MAC_STABLE. Note
+ * that this really shouldn't happen, because we have a Wi-Fi
+ * profile at hand, and an SSID should be set. */
+ stable_id = _prop_get_connection_stable_id(self, connection, &stable_type);
+ }
+
hw_addr_generated = nm_utils_hw_addr_gen_stable_eth(
stable_type,
stable_id,
diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c
index 9d3bb9582e..66549605ec 100644
--- a/src/core/nm-core-utils.c
+++ b/src/core/nm-core-utils.c
@@ -3397,6 +3397,7 @@ nm_utils_stable_id_parse(const char *stable_id,
const char *hwaddr,
const char *bootid,
const char *uuid,
+ GBytes *ssid,
char **out_generated)
{
nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT_A(NM_UTILS_GET_NEXT_REALLOC_SIZE_232, FALSE);
@@ -3482,7 +3483,29 @@ nm_utils_stable_id_parse(const char *stable_id,
_stable_id_append(&str, deviceid);
else if (CHECK_PREFIX("${MAC}"))
_stable_id_append(&str, hwaddr);
- else if (g_str_has_prefix(&stable_id[i], "${RANDOM}")) {
+ else if (CHECK_PREFIX("${NETWORK_SSID}")) {
+ gs_free char *value_free = NULL;
+ gs_free char *s = NULL;
+ const char *value;
+ const char *type_id;
+
+ if (ssid) {
+ type_id = "s:";
+ value = nm_utils_buf_utf8safe_escape_bytes(ssid,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL,
+ &value_free);
+ } else {
+ /* If we have no SSID, we fallback to the connection's UUID.
+ *
+ * Give a separate prefix (@type_id), so that an SSID and a UUID
+ * fallback never result in the same output. */
+ type_id = "c:";
+ value = uuid ?: "";
+ }
+
+ s = g_strjoin("", type_id, value, NULL);
+ _stable_id_append(&str, s);
+ } else if (g_str_has_prefix(&stable_id[i], "${RANDOM}")) {
/* RANDOM makes not so much sense for cloned-mac-address
* as the result is similar to specifying "cloned-mac-address=random".
* It makes however sense for RFC 7217 Stable Privacy IPv6 addresses
@@ -3523,6 +3546,12 @@ nm_utils_stable_id_parse(const char *stable_id,
return NM_UTILS_STABLE_TYPE_GENERATED;
}
+NMUtilsStableType
+nm_utils_stable_id_parse_network_ssid(GBytes *ssid, const char *uuid, char **out_stable_id)
+{
+ return nm_utils_stable_id_parse("${NETWORK_SSID}", NULL, NULL, NULL, uuid, ssid, out_stable_id);
+}
+
/*****************************************************************************/
static gboolean
diff --git a/src/core/nm-core-utils.h b/src/core/nm-core-utils.h
index d73cfd6467..22ee8686af 100644
--- a/src/core/nm-core-utils.h
+++ b/src/core/nm-core-utils.h
@@ -313,8 +313,12 @@ NMUtilsStableType nm_utils_stable_id_parse(const char *stable_id,
const char *hwaddr,
const char *bootid,
const char *uuid,
+ GBytes *ssid,
char **out_generated);
+NMUtilsStableType
+nm_utils_stable_id_parse_network_ssid(GBytes *ssid, const char *uuid, char **out_stable_id);
+
char *nm_utils_stable_id_random(void);
char *nm_utils_stable_id_generated_complete(const char *msg);
diff --git a/src/core/tests/test-core.c b/src/core/tests/test-core.c
index 8296d74579..faf51f4706 100644
--- a/src/core/tests/test-core.c
+++ b/src/core/tests/test-core.c
@@ -2104,8 +2104,19 @@ do_test_stable_id_parse(const char *stable_id,
NMUtilsStableType expected_stable_type,
const char *expected_generated)
{
- gs_free char *generated = NULL;
- NMUtilsStableType stable_type;
+ gs_free char *generated = NULL;
+ NMUtilsStableType stable_type;
+ char ssid_bin[] = "SSID(\202)";
+ gs_unref_bytes GBytes *ssid = g_bytes_new_static(ssid_bin, sizeof(ssid_bin) - 1);
+
+ while (TRUE) {
+ if (NM_STR_HAS_PREFIX(stable_id, "NO_SSID:")) {
+ stable_id += NM_STRLEN("NO_SSID:");
+ nm_clear_pointer(&ssid, g_bytes_unref);
+ continue;
+ }
+ break;
+ }
if (expected_stable_type == NM_UTILS_STABLE_TYPE_GENERATED)
g_assert(expected_generated);
@@ -2117,8 +2128,13 @@ do_test_stable_id_parse(const char *stable_id,
else
g_assert(stable_id);
- stable_type =
- nm_utils_stable_id_parse(stable_id, "_DEVICE", "_MAC", "_BOOT", "_CONNECTION", &generated);
+ stable_type = nm_utils_stable_id_parse(stable_id,
+ "_DEVICE",
+ "_MAC",
+ "_BOOT",
+ "_CONNECTION",
+ ssid,
+ &generated);
g_assert_cmpint(expected_stable_type, ==, stable_type);
@@ -2160,6 +2176,12 @@ test_stable_id_parse(void)
_parse_generated("${${CONNECTION}", "${${CONNECTION}=11{_CONNECTION}");
_parse_generated("${CONNECTION}x", "${CONNECTION}=11{_CONNECTION}x");
_parse_generated("x${CONNECTION}", "x${CONNECTION}=11{_CONNECTION}");
+ _parse_generated("x${CONNECTION}${NETWORK_SSID}",
+ "x${CONNECTION}=11{_CONNECTION}${NETWORK_SSID}=12{s:SSID(\\202)}");
+ _parse_generated("NO_SSID:x${CONNECTION}${NETWORK_SSID}",
+ "x${CONNECTION}=11{_CONNECTION}${NETWORK_SSID}=13{c:_CONNECTION}");
+ _parse_generated("${NETWORK_SSID}", "${NETWORK_SSID}=12{s:SSID(\\202)}");
+ _parse_generated("NO_SSID:${NETWORK_SSID}", "${NETWORK_SSID}=13{c:_CONNECTION}");
_parse_generated("${BOOT}x", "${BOOT}=5{_BOOT}x");
_parse_generated("x${BOOT}", "x${BOOT}=5{_BOOT}");
_parse_generated("x${BOOT}${CONNECTION}", "x${BOOT}=5{_BOOT}${CONNECTION}=11{_CONNECTION}");
@@ -2169,6 +2191,18 @@ test_stable_id_parse(void)
_parse_random("${RANDOM}");
_parse_random(" ${RANDOM}");
_parse_random("${BOOT}${RANDOM}");
+
+ {
+ gs_free char *str = NULL;
+ char ssid_bin[] = "foo\n";
+ gs_unref_bytes GBytes *ssid = g_bytes_new_static(ssid_bin, sizeof(ssid_bin) - 1);
+ NMUtilsStableType stable_type;
+
+ stable_type = nm_utils_stable_id_parse_network_ssid(ssid, "uuid", &str);
+
+ g_assert_cmpstr(str, ==, "${NETWORK_SSID}=9{s:foo\\012}");
+ g_assert_cmpint(stable_type, ==, NM_UTILS_STABLE_TYPE_GENERATED);
+ }
}
/*****************************************************************************/
diff --git a/src/libnm-core-aux-intern/nm-common-macros.h b/src/libnm-core-aux-intern/nm-common-macros.h
index c452b7d3cb..3e6eabaead 100644
--- a/src/libnm-core-aux-intern/nm-common-macros.h
+++ b/src/libnm-core-aux-intern/nm-common-macros.h
@@ -34,19 +34,28 @@
"org.freedesktop.NetworkManager.enable-disable-connectivity-check"
#define NM_AUTH_PERMISSION_WIFI_SCAN "org.freedesktop.NetworkManager.wifi.scan"
-#define NM_CLONED_MAC_PRESERVE "preserve"
-#define NM_CLONED_MAC_PERMANENT "permanent"
-#define NM_CLONED_MAC_RANDOM "random"
-#define NM_CLONED_MAC_STABLE "stable"
+#define NM_CLONED_MAC_PRESERVE "preserve"
+#define NM_CLONED_MAC_PERMANENT "permanent"
+#define NM_CLONED_MAC_RANDOM "random"
+#define NM_CLONED_MAC_STABLE "stable"
+#define NM_CLONED_MAC_STABLE_SSID "stable-ssid"
static inline gboolean
-NM_CLONED_MAC_IS_SPECIAL(const char *str)
+NM_CLONED_MAC_IS_SPECIAL(const char *str, gboolean is_wifi)
{
- return NM_IN_STRSET(str,
- NM_CLONED_MAC_PRESERVE,
- NM_CLONED_MAC_PERMANENT,
- NM_CLONED_MAC_RANDOM,
- NM_CLONED_MAC_STABLE);
+ if (NM_IN_STRSET(str,
+ NM_CLONED_MAC_PRESERVE,
+ NM_CLONED_MAC_PERMANENT,
+ NM_CLONED_MAC_RANDOM,
+ NM_CLONED_MAC_STABLE))
+ return TRUE;
+
+ if (is_wifi) {
+ if (NM_IN_STRSET(str, NM_CLONED_MAC_STABLE_SSID))
+ return TRUE;
+ }
+
+ return FALSE;
}
#define NM_IAID_MAC "mac"
diff --git a/src/libnm-core-impl/nm-keyfile.c b/src/libnm-core-impl/nm-keyfile.c
index 82581d9fea..078ea5d766 100644
--- a/src/libnm-core-impl/nm-keyfile.c
+++ b/src/libnm-core-impl/nm-keyfile.c
@@ -1219,9 +1219,14 @@ mac_address_parser(KeyfileReaderInfo *info,
tmp_string = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL);
- if (cloned_mac_addr && NM_CLONED_MAC_IS_SPECIAL(tmp_string)) {
- mac_str = tmp_string;
- goto out;
+ if (cloned_mac_addr) {
+ gboolean is_wifi;
+
+ is_wifi = NM_IS_SETTING_WIRELESS(setting);
+ if (NM_CLONED_MAC_IS_SPECIAL(tmp_string, is_wifi)) {
+ mac_str = tmp_string;
+ goto out;
+ }
}
if (tmp_string && nm_utils_hwaddr_aton(tmp_string, addr_bin, addr_len))
diff --git a/src/libnm-core-impl/nm-setting-connection.c b/src/libnm-core-impl/nm-setting-connection.c
index a228ecf0c5..28f3b24c69 100644
--- a/src/libnm-core-impl/nm-setting-connection.c
+++ b/src/libnm-core-impl/nm-setting-connection.c
@@ -1928,13 +1928,15 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
*
* The '$' character is treated special to perform dynamic substitutions at
* activation time. Currently, supported are "${CONNECTION}", "${DEVICE}",
- * "${MAC}", "${BOOT}", "${RANDOM}". These effectively create unique IDs
- * per-connection, per-device, per-boot, or every time. The "${CONNECTION}"
- * uses the profile's connection.uuid, the "${DEVICE}" uses the interface
- * name of the device and "${MAC}" the permanent MAC address of the device.
- * Any unrecognized patterns following '$' are treated verbatim, however
- * are reserved for future use. You are thus advised to avoid '$' or escape
- * it as "$$". For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to
+ * "${MAC}", "${NETWORK_SSID}", "${BOOT}", "${RANDOM}". These effectively
+ * create unique IDs per-connection, per-device, per-SSID, per-boot, or
+ * every time. The "${CONNECTION}" uses the profile's connection.uuid, the
+ * "${DEVICE}" uses the interface name of the device and "${MAC}" the
+ * permanent MAC address of the device. "${NETWORK_SSID}" uses the SSID for
+ * Wi-Fi networks and falls back to "${CONNECTION}" on other networks. Any
+ * unrecognized patterns following '$' are treated verbatim, however are
+ * reserved for future use. You are thus advised to avoid '$' or escape it
+ * as "$$". For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to
* create a unique id for this connection that changes with every reboot
* and differs depending on the interface where the profile activates.
*
diff --git a/src/libnm-core-impl/nm-setting-wired.c b/src/libnm-core-impl/nm-setting-wired.c
index 5476d983b4..82c3840ffa 100644
--- a/src/libnm-core-impl/nm-setting-wired.c
+++ b/src/libnm-core-impl/nm-setting-wired.c
@@ -891,7 +891,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
}
}
- if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address)
+ if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address, FALSE)
&& !nm_utils_hwaddr_valid(priv->cloned_mac_address, ETH_ALEN)) {
g_set_error(error,
NM_CONNECTION_ERROR,
diff --git a/src/libnm-core-impl/nm-setting-wireless.c b/src/libnm-core-impl/nm-setting-wireless.c
index 14b7e874a8..06450f5227 100644
--- a/src/libnm-core-impl/nm-setting-wireless.c
+++ b/src/libnm-core-impl/nm-setting-wireless.c
@@ -963,7 +963,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
return FALSE;
}
- if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address)
+ if (priv->cloned_mac_address && !NM_CLONED_MAC_IS_SPECIAL(priv->cloned_mac_address, TRUE)
&& !nm_utils_hwaddr_valid(priv->cloned_mac_address, ETH_ALEN)) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
@@ -1542,12 +1542,14 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass)
* This is known as MAC cloning or spoofing.
*
* Beside explicitly specifying a MAC address, the special values "preserve", "permanent",
- * "random" and "stable" are supported.
+ * "random", "stable" and "stable-ssid" 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.
+ * "stable-ssid" creates a hashed MAC address based on the SSID, the same as setting the
+ * stable-id to "${NETWORK_SSID}".
*
* If unspecified, the value can be overwritten via global defaults, see manual
* of NetworkManager.conf. If still unspecified, it defaults to "preserve"
diff --git a/src/libnmc-setting/nm-meta-setting-desc.c b/src/libnmc-setting/nm-meta-setting-desc.c
index 2e9593f81e..650c54fa9f 100644
--- a/src/libnmc-setting/nm-meta-setting-desc.c
+++ b/src/libnmc-setting/nm-meta-setting-desc.c
@@ -1557,7 +1557,11 @@ _set_fcn_gobject_mac(ARGS_SET_FCN)
} else {
valid =
nm_utils_hwaddr_valid(value, ETH_ALEN)
- || (mode == NM_META_PROPERTY_TYPE_MAC_MODE_CLONED && NM_CLONED_MAC_IS_SPECIAL(value));
+ || (NM_IN_SET(mode,
+ NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_ETHERNET,
+ NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_WIFI)
+ && NM_CLONED_MAC_IS_SPECIAL(value,
+ mode == NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_WIFI));
}
if (!valid) {
@@ -7937,7 +7941,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRED[] = {
.prompt = N_("Cloned MAC [none]"),
.property_type = &_pt_gobject_mac,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mac,
- .mode = NM_META_PROPERTY_TYPE_MAC_MODE_CLONED,
+ .mode = NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_ETHERNET,
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK,
@@ -8118,7 +8122,7 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS[] = {
.prompt = N_("Cloned MAC [none]"),
.property_type = &_pt_gobject_mac,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mac,
- .mode = NM_META_PROPERTY_TYPE_MAC_MODE_CLONED,
+ .mode = NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_WIFI,
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK,
diff --git a/src/libnmc-setting/nm-meta-setting-desc.h b/src/libnmc-setting/nm-meta-setting-desc.h
index 94a689457c..f8e36b0e0a 100644
--- a/src/libnmc-setting/nm-meta-setting-desc.h
+++ b/src/libnmc-setting/nm-meta-setting-desc.h
@@ -178,7 +178,8 @@ typedef enum {
typedef enum {
NM_META_PROPERTY_TYPE_MAC_MODE_DEFAULT,
- NM_META_PROPERTY_TYPE_MAC_MODE_CLONED,
+ NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_ETHERNET,
+ NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_WIFI,
NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND,
NM_META_PROPERTY_TYPE_MAC_MODE_WPAN,
} NMMetaPropertyTypeMacMode;
diff --git a/src/libnmc-setting/settings-docs.h.in b/src/libnmc-setting/settings-docs.h.in
index beb2e56fcf..b9c06e55eb 100644
--- a/src/libnmc-setting/settings-docs.h.in
+++ b/src/libnmc-setting/settings-docs.h.in
@@ -21,7 +21,7 @@
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_READ_ONLY N_("This property is deprecated and has no meaning.")
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SECONDARIES N_("List of connection UUIDs that should be activated when the base connection itself is activated. Currently, only VPN connections are supported.")
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_SLAVE_TYPE N_("Setting name of the device type of this slave's master connection (eg, \"bond\"), or NULL if this connection is not a slave.")
-#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used to derive the DHCP client identifier with ipv4.dhcp-client-id=stable, the DHCPv6 DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid] and the DHCP IAID with ipv4.iaid=stable and ipv6.iaid=stable. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret_key. See NetworkManager(8) manual about the secret-key and the host identity. The '$' character is treated special to perform dynamic substitutions at activation time. Currently, supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-boot, or every time. The \"${CONNECTION}\" uses the profile's connection.uuid, the \"${DEVICE}\" uses the interface name of the device and \"${MAC}\" the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is \"default${CONNECTION}\" go generate an ID unique per connection profile.")
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_STABLE_ID N_("This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used to derive the DHCP client identifier with ipv4.dhcp-client-id=stable, the DHCPv6 DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid] and the DHCP IAID with ipv4.iaid=stable and ipv6.iaid=stable. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret_key. See NetworkManager(8) manual about the secret-key and the host identity. The '$' character is treated special to perform dynamic substitutions at activation time. Currently, supported are \"${CONNECTION}\", \"${DEVICE}\", \"${MAC}\", \"${NETWORK_SSID}\", \"${BOOT}\", \"${RANDOM}\". These effectively create unique IDs per-connection, per-device, per-SSID, per-boot, or every time. The \"${CONNECTION}\" uses the profile's connection.uuid, the \"${DEVICE}\" uses the interface name of the device and \"${MAC}\" the permanent MAC address of the device. \"${NETWORK_SSID}\" uses the SSID for Wi-Fi networks and falls back to \"${CONNECTION}\" on other networks. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as \"$$\". For example, set it to \"${CONNECTION}-${BOOT}-${DEVICE}\" to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is \"default${CONNECTION}\" go generate an ID unique per connection profile.")
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).")
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).")
#define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("The connection.uuid is the real identifier of a profile. It cannot change and it must be unique. It is therefore often best to refer to a profile by UUID, for example with `nmcli connection up uuid $UUID`. The UUID cannot be changed, except in offline mode. In that case, the special values \"new\", \"generate\" and \"\" are allowed to generate a new random UUID.")
@@ -400,7 +400,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. Locking a client profile to a certain BSSID will prevent roaming and also disable background scanning. That can be useful, if there is only one access point for the SSID.")
#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. This is known as MAC cloning or spoofing. Beside explicitly specifying a MAC address, the special values \"preserve\", \"permanent\", \"random\", \"stable\" and \"stable-ssid\" 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. \"stable-ssid\" creates a hashed MAC address based on the SSID, the same as setting the stable-id to \"${NETWORK_SSID}\". 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_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).")
diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.c b/src/nmcli/gen-metadata-nm-settings-nmcli.c
index 874bc6ddb6..babf1f064b 100644
--- a/src/nmcli/gen-metadata-nm-settings-nmcli.c
+++ b/src/nmcli/gen-metadata-nm-settings-nmcli.c
@@ -5,6 +5,7 @@
#include "libnmc-setting/nm-meta-setting-desc.h"
#include "libnmc-setting/nm-meta-setting-base.h"
#include "libnm-glib-aux/nm-enum-utils.h"
+#include "libnm-core-aux-intern/nm-common-macros.h"
#include "nm-core-enum-types.h"
#include <stdarg.h>
#include <stdlib.h>
@@ -87,7 +88,8 @@ get_mac_format(const NMMetaPropertyInfo *prop_info)
if (prop_typ_data) {
switch (prop_typ_data->subtype.mac.mode) {
case NM_META_PROPERTY_TYPE_MAC_MODE_DEFAULT:
- case NM_META_PROPERTY_TYPE_MAC_MODE_CLONED:
+ case NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_ETHERNET:
+ case NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_WIFI:
break;
case NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND:
return g_strdup("Infiniband MAC address");
@@ -471,9 +473,22 @@ get_property_special_values(const NMMetaPropertyInfo *prop_info)
append_int_special_values(prop_info, special_values);
break;
case NM_META_PROPERTY_TYPE_FORMAT_MAC:
- if (prop_typ_data
- && prop_typ_data->subtype.mac.mode == NM_META_PROPERTY_TYPE_MAC_MODE_CLONED)
- append_vals(special_values, "preserve", "permanent", "random", "stable");
+ if (prop_typ_data) {
+ switch (prop_typ_data->subtype.mac.mode) {
+ case NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_ETHERNET:
+ case NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_WIFI:
+ append_vals(special_values,
+ NM_CLONED_MAC_PRESERVE,
+ NM_CLONED_MAC_PERMANENT,
+ NM_CLONED_MAC_RANDOM,
+ NM_CLONED_MAC_STABLE);
+ if (prop_typ_data->subtype.mac.mode == NM_META_PROPERTY_TYPE_MAC_MODE_CLONED_WIFI)
+ append_vals(special_values, NM_CLONED_MAC_STABLE_SSID);
+ break;
+ default:
+ break;
+ }
+ }
break;
case NM_META_PROPERTY_TYPE_FORMAT_MTU:
g_ptr_array_add(special_values, g_strdup("auto"));
diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
index ed06e92968..bea062b0f2 100644
--- a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
+++ b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
@@ -49,9 +49,9 @@
format="MAC address" />
<property name="cloned-mac-address"
alias="cloned-mac"
- nmcli-description="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 &quot;preserve&quot;, &quot;permanent&quot;, &quot;random&quot; and &quot;stable&quot; are supported. &quot;preserve&quot; means not to touch the MAC address on activation. &quot;permanent&quot; means to use the permanent hardware address of the device. &quot;random&quot; creates a random MAC address on each connect. &quot;stable&quot; 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 &quot;preserve&quot; (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as &quot;assigned-mac-address&quot; or the deprecated &quot;cloned-mac-address&quot;."
+ nmcli-description="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 &quot;preserve&quot;, &quot;permanent&quot;, &quot;random&quot;, &quot;stable&quot; and &quot;stable-ssid&quot; are supported. &quot;preserve&quot; means not to touch the MAC address on activation. &quot;permanent&quot; means to use the permanent hardware address of the device. &quot;random&quot; creates a random MAC address on each connect. &quot;stable&quot; creates a hashed MAC address based on connection.stable-id and a machine dependent key. &quot;stable-ssid&quot; creates a hashed MAC address based on the SSID, the same as setting the stable-id to &quot;${NETWORK_SSID}&quot;. If unspecified, the value can be overwritten via global defaults, see manual of NetworkManager.conf. If still unspecified, it defaults to &quot;preserve&quot; (older versions of NetworkManager may use a different default value). On D-Bus, this field is expressed as &quot;assigned-mac-address&quot; or the deprecated &quot;cloned-mac-address&quot;."
format="MAC address"
- special-values="preserve, permanent, random, stable" />
+ special-values="preserve, permanent, random, stable, stable-ssid" />
<property name="generate-mac-address-mask"
nmcli-description="With &quot;cloned-mac-address&quot; setting &quot;random&quot; or &quot;stable&quot;, 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 &quot;FE:FF:FF:00:00:00&quot; means to preserve the OUI of the current MAC address and only randomize the lower 3 bytes using the &quot;random&quot; or &quot;stable&quot; 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 &quot;FE:FF:FF:00:00:00 68:F7:28:00:00:00&quot; will set the OUI of the MAC address to 68:F7:28, while the lower bits are randomized. A value of &quot;02:00:00:00:00:00 00:00:00:00:00:00&quot; 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, &quot;02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00&quot; will create a fully scrambled MAC address, randomly locally or globally administered."
format="string" />
@@ -610,7 +610,7 @@
nmcli-description="The connection.uuid is the real identifier of a profile. It cannot change and it must be unique. It is therefore often best to refer to a profile by UUID, for example with `nmcli connection up uuid $UUID`. The UUID cannot be changed, except in offline mode. In that case, the special values &quot;new&quot;, &quot;generate&quot; and &quot;&quot; are allowed to generate a new random UUID."
format="string" />
<property name="stable-id"
- nmcli-description="This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used to derive the DHCP client identifier with ipv4.dhcp-client-id=stable, the DHCPv6 DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid] and the DHCP IAID with ipv4.iaid=stable and ipv6.iaid=stable. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device&apos;s name is included, so that different interfaces yield different addresses. The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret_key. See NetworkManager(8) manual about the secret-key and the host identity. The &apos;$&apos; character is treated special to perform dynamic substitutions at activation time. Currently, supported are &quot;${CONNECTION}&quot;, &quot;${DEVICE}&quot;, &quot;${MAC}&quot;, &quot;${BOOT}&quot;, &quot;${RANDOM}&quot;. These effectively create unique IDs per-connection, per-device, per-boot, or every time. The &quot;${CONNECTION}&quot; uses the profile&apos;s connection.uuid, the &quot;${DEVICE}&quot; uses the interface name of the device and &quot;${MAC}&quot; the permanent MAC address of the device. Any unrecognized patterns following &apos;$&apos; are treated verbatim, however are reserved for future use. You are thus advised to avoid &apos;$&apos; or escape it as &quot;$$&quot;. For example, set it to &quot;${CONNECTION}-${BOOT}-${DEVICE}&quot; to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is &quot;default${CONNECTION}&quot; go generate an ID unique per connection profile."
+ nmcli-description="This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used to derive the DHCP client identifier with ipv4.dhcp-client-id=stable, the DHCPv6 DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid] and the DHCP IAID with ipv4.iaid=stable and ipv6.iaid=stable. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device&apos;s name is included, so that different interfaces yield different addresses. The per-host key is the identity of your machine and stored in /var/lib/NetworkManager/secret_key. See NetworkManager(8) manual about the secret-key and the host identity. The &apos;$&apos; character is treated special to perform dynamic substitutions at activation time. Currently, supported are &quot;${CONNECTION}&quot;, &quot;${DEVICE}&quot;, &quot;${MAC}&quot;, &quot;${NETWORK_SSID}&quot;, &quot;${BOOT}&quot;, &quot;${RANDOM}&quot;. These effectively create unique IDs per-connection, per-device, per-SSID, per-boot, or every time. The &quot;${CONNECTION}&quot; uses the profile&apos;s connection.uuid, the &quot;${DEVICE}&quot; uses the interface name of the device and &quot;${MAC}&quot; the permanent MAC address of the device. &quot;${NETWORK_SSID}&quot; uses the SSID for Wi-Fi networks and falls back to &quot;${CONNECTION}&quot; on other networks. Any unrecognized patterns following &apos;$&apos; are treated verbatim, however are reserved for future use. You are thus advised to avoid &apos;$&apos; or escape it as &quot;$$&quot;. For example, set it to &quot;${CONNECTION}-${BOOT}-${DEVICE}&quot; to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is &quot;default${CONNECTION}&quot; go generate an ID unique per connection profile."
format="string" />
<property name="type"
alias="type"
diff --git a/src/nmtui/nmt-mac-entry.c b/src/nmtui/nmt-mac-entry.c
index 11ceecf9e9..6cecf0e9d8 100644
--- a/src/nmtui/nmt-mac-entry.c
+++ b/src/nmtui/nmt-mac-entry.c
@@ -90,8 +90,10 @@ mac_validator(NmtNewtEntry *entry, const char *text, gpointer user_data)
if (!*text)
return TRUE;
- if (priv->entry_type == NMT_MAC_ENTRY_TYPE_CLONED) {
- if (NM_CLONED_MAC_IS_SPECIAL(text))
+ if (NM_IN_SET(priv->entry_type,
+ NMT_MAC_ENTRY_TYPE_CLONED_ETHERNET,
+ NMT_MAC_ENTRY_TYPE_CLONED_WIFI)) {
+ if (NM_CLONED_MAC_IS_SPECIAL(text, priv->entry_type == NMT_MAC_ENTRY_TYPE_CLONED_WIFI))
return TRUE;
}
@@ -237,7 +239,7 @@ nmt_mac_entry_class_init(NmtMacEntryClass *entry_class)
"",
"",
NMT_MAC_ENTRY_TYPE_MAC,
- NMT_MAC_ENTRY_TYPE_CLONED,
+ NMT_MAC_ENTRY_TYPE_CLONED_WIFI,
NMT_MAC_ENTRY_TYPE_MAC,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
}
diff --git a/src/nmtui/nmt-mac-entry.h b/src/nmtui/nmt-mac-entry.h
index 6b5b289685..c5acd35a98 100644
--- a/src/nmtui/nmt-mac-entry.h
+++ b/src/nmtui/nmt-mac-entry.h
@@ -11,7 +11,8 @@
typedef enum {
NMT_MAC_ENTRY_TYPE_MAC,
- NMT_MAC_ENTRY_TYPE_CLONED,
+ NMT_MAC_ENTRY_TYPE_CLONED_ETHERNET,
+ NMT_MAC_ENTRY_TYPE_CLONED_WIFI,
} NmtMacEntryType;
#define NMT_TYPE_MAC_ENTRY (nmt_mac_entry_get_type())
diff --git a/src/nmtui/nmt-page-bond.c b/src/nmtui/nmt-page-bond.c
index 5a64590cdd..c748315035 100644
--- a/src/nmtui/nmt-page-bond.c
+++ b/src/nmtui/nmt-page-bond.c
@@ -395,7 +395,7 @@ nmt_page_bond_constructed(GObject *object)
nmt_editor_grid_append(grid, _("ARP targets"), widget, NULL);
priv->arp_ip_target = NMT_ADDRESS_LIST(widget);
- widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
+ widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED_ETHERNET);
g_object_bind_property(s_wired,
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
widget,
diff --git a/src/nmtui/nmt-page-ethernet.c b/src/nmtui/nmt-page-ethernet.c
index 77abbb405e..652a2603e7 100644
--- a/src/nmtui/nmt-page-ethernet.c
+++ b/src/nmtui/nmt-page-ethernet.c
@@ -107,7 +107,7 @@ nmt_page_ethernet_constructed(GObject *object)
section = nmt_editor_section_new(_("ETHERNET"), NULL, FALSE);
grid = nmt_editor_section_get_body(section);
- widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
+ widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED_ETHERNET);
g_object_bind_property(s_wired,
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
widget,
diff --git a/src/nmtui/nmt-page-vlan.c b/src/nmtui/nmt-page-vlan.c
index 1956d3d64a..238dbafb5b 100644
--- a/src/nmtui/nmt-page-vlan.c
+++ b/src/nmtui/nmt-page-vlan.c
@@ -83,7 +83,7 @@ nmt_page_vlan_constructed(GObject *object)
nmt_editor_grid_append(grid, NULL, nmt_newt_separator_new(), NULL);
- widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
+ widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED_ETHERNET);
g_object_bind_property(s_wired,
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
widget,
diff --git a/src/nmtui/nmt-page-wifi.c b/src/nmtui/nmt-page-wifi.c
index 55feaee256..9767597b95 100644
--- a/src/nmtui/nmt-page-wifi.c
+++ b/src/nmtui/nmt-page-wifi.c
@@ -378,7 +378,7 @@ nmt_page_wifi_constructed(GObject *object)
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
nmt_editor_grid_append(grid, _("BSSID"), widget, NULL);
- widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
+ widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED_WIFI);
g_object_bind_property(s_wireless,
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
widget,