core: set MAC address for IP tunnels when creating device

There is however a serious issue currently: when NetworkManager creates
virtual devices, it starts from an unrealized NMDevice, creates the
netdev device, realizes the device, and transitions through states
UNMANAGED and DISCONNECTED. Thereby, the state of NMDevice gets cleared
again. That means, if the profile has "connection.stable-id=${RANDOM}"
and "ethernet.cloned-mac-address=stable", then we will first set a
random MAC address when creating the device. Then, the NMDevice
transitions through UNMANAGED state, forgets the MAC address it
generated and creates a new MAC address in stage 1. This should be
fixed by better handling unrealized devices. It also affects all
software devices that set the MAC address upon creation of the
interfaces (as they all should).
This commit is contained in:
Thomas Haller 2019-12-31 01:22:36 +01:00
parent 81d83b9e00
commit a90397b963
2 changed files with 41 additions and 7 deletions

View file

@ -736,10 +736,11 @@ create_and_realize (NMDevice *device,
if ( !hwaddr
&& nm_device_hw_addr_get_cloned (device, connection, FALSE,
&hwaddr_cloned, NULL, NULL)) {
/* The cloned MAC address might by dynamic, for example with stable-id="${RANDOM}".
* It's a bit odd that we first create the device with one dynamic address,
* and later on may reset it to another. That is, because we don't cache
* the dynamic address in @device, like we do during nm_device_hw_addr_set_cloned(). */
/* FIXME: we set the MAC address when creating the interface, while the
* NMDevice is still unrealized. As we afterwards realize the device, it
* forgets the parameters for the cloned MAC address, and in stage 1
* it might create a different MAC address. That should be fixed by
* better handling device realization. */
hwaddr = hwaddr_cloned;
}

View file

@ -657,11 +657,44 @@ create_and_realize (NMDevice *device,
gint64 val;
NMIPTunnelMode mode;
int r;
gs_free char *hwaddr = NULL;
guint8 mac_address[ETH_ALEN];
gboolean mac_address_valid = FALSE;
s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection);
g_assert (s_ip_tunnel);
nm_assert (NM_IS_SETTING_IP_TUNNEL (s_ip_tunnel));
mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel);
if ( nm_device_hw_addr_get_cloned (device,
connection,
FALSE,
&hwaddr,
NULL,
NULL)
&& hwaddr) {
/* FIXME: we set the MAC address when creating the interface, while the
* NMDevice is still unrealized. As we afterwards realize the device, it
* forgets the parameters for the cloned MAC address, and in stage 1
* it might create a different MAC address. That should be fixed by
* better handling device realization. */
if (!nm_utils_hwaddr_aton (hwaddr, mac_address, ETH_ALEN)) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"Invalid hardware address '%s'",
hwaddr);
g_return_val_if_reached (FALSE);
}
if (NM_IN_SET (mode, NM_IP_TUNNEL_MODE_GRE)) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"Invalid hardware address '%s' for tunnel type",
hwaddr);
return FALSE;
}
mac_address_valid = TRUE;
}
switch (mode) {
case NM_IP_TUNNEL_MODE_GRETAP:
lnk_gre.is_tap = TRUE;
@ -704,8 +737,8 @@ create_and_realize (NMDevice *device,
r = nm_platform_link_gre_add (nm_device_get_platform (device),
iface,
NULL,
0,
mac_address_valid ? mac_address : NULL,
mac_address_valid ? ETH_ALEN : 0,
&lnk_gre,
out_plink);
if (r < 0) {