mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 20:00:23 +01:00
device: only set permanent hardware address once
While a device is realized, we only want to read the permanent MAC address once. If that fails, we fallback to the current MAC address. Thus, we want the permanent address be stable until the device unrealizes. While we want to fallback to the current MAC address, in some cases the caller wants to know whether this was a "real" permanent MAC address as read via ethtool. For example, when matching an ethernet device against ethernet.mac-address property, the fake (current) address should not be used in such case.
This commit is contained in:
parent
9fb5558f96
commit
2a94587232
4 changed files with 68 additions and 41 deletions
|
|
@ -408,7 +408,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
|||
if (!match_subchans (self, s_wired, &try_mac))
|
||||
return FALSE;
|
||||
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device);
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
|
||||
mac = nm_setting_wired_get_mac_address (s_wired);
|
||||
if (perm_hw_addr) {
|
||||
if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
|
||||
|
|
@ -1405,7 +1405,7 @@ complete_connection (NMDevice *device,
|
|||
nm_connection_add_setting (connection, NM_SETTING (s_wired));
|
||||
}
|
||||
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device);
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
|
||||
if (perm_hw_addr) {
|
||||
setting_mac = nm_setting_wired_get_mac_address (s_wired);
|
||||
if (setting_mac) {
|
||||
|
|
@ -1502,7 +1502,7 @@ update_connection (NMDevice *device, NMConnection *connection)
|
|||
{
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
|
||||
NMSettingWired *s_wired = nm_connection_get_setting_wired (connection);
|
||||
const char *perm_hw_addr = nm_device_get_permanent_hw_address (device);
|
||||
const char *perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
|
||||
const char *mac = nm_device_get_hw_address (device);
|
||||
const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS;
|
||||
GHashTableIter iter;
|
||||
|
|
@ -1636,7 +1636,7 @@ get_property (GObject *object, guint prop_id,
|
|||
|
||||
switch (prop_id) {
|
||||
case PROP_PERM_HW_ADDRESS:
|
||||
g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (object)));
|
||||
g_value_set_string (value, nm_device_get_permanent_hw_address ((NMDevice *) object, FALSE));
|
||||
break;
|
||||
case PROP_SPEED:
|
||||
g_value_set_uint (value, priv->speed);
|
||||
|
|
|
|||
|
|
@ -237,8 +237,9 @@ typedef struct _NMDevicePrivate {
|
|||
char * driver_version;
|
||||
char * firmware_version;
|
||||
RfKillType rfkill_type;
|
||||
bool firmware_missing;
|
||||
bool nm_plugin_missing;
|
||||
bool firmware_missing:1;
|
||||
bool nm_plugin_missing:1;
|
||||
bool hw_addr_perm_fake:1; /* whether the permanent HW address could not be read and is a fake */
|
||||
GHashTable * available_connections;
|
||||
char * hw_addr;
|
||||
guint hw_addr_len;
|
||||
|
|
@ -11371,17 +11372,14 @@ void
|
|||
nm_device_update_hw_address (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
int ifindex;
|
||||
const guint8 *hwaddr;
|
||||
gsize hwaddrlen = 0;
|
||||
|
||||
ifindex = nm_device_get_ifindex (self);
|
||||
if (ifindex <= 0)
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
if (priv->ifindex <= 0)
|
||||
return;
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddrlen);
|
||||
hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &hwaddrlen);
|
||||
|
||||
if ( priv->type == NM_DEVICE_TYPE_ETHERNET
|
||||
&& hwaddr
|
||||
|
|
@ -11433,29 +11431,49 @@ void
|
|||
nm_device_update_permanent_hw_address (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
|
||||
size_t len = 0;
|
||||
gboolean success_read;
|
||||
|
||||
if (priv->hw_addr_len) {
|
||||
if (priv->ifindex > 0) {
|
||||
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
|
||||
size_t len = 0;
|
||||
gboolean success_read;
|
||||
|
||||
success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len);
|
||||
|
||||
if (success_read && len == priv->hw_addr_len) {
|
||||
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
|
||||
_LOGD (LOGD_DEVICE | LOGD_HW, "read permanent MAC address %s",
|
||||
priv->hw_addr_perm);
|
||||
} else {
|
||||
/* Fall back to current address */
|
||||
_LOGD (LOGD_HW | LOGD_ETHER, "%s",
|
||||
success_read
|
||||
? "unable to read permanent MAC address"
|
||||
: "read HW addr length of permanent MAC address differs");
|
||||
priv->hw_addr_perm = g_strdup (priv->hw_addr);
|
||||
}
|
||||
}
|
||||
if (priv->hw_addr_perm) {
|
||||
/* the permanent hardware address is only read once and not
|
||||
* re-read later.
|
||||
*
|
||||
* Except during unrealize/realize cycles, where we clear the permanent
|
||||
* hardware address during unrealization. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->ifindex <= 0)
|
||||
return;
|
||||
|
||||
if (!priv->hw_addr_len) {
|
||||
nm_device_update_hw_address (self);
|
||||
if (!priv->hw_addr_len)
|
||||
return;
|
||||
}
|
||||
|
||||
success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len);
|
||||
if (!success_read || len != priv->hw_addr_len) {
|
||||
/* Fall back to current address. We use the fake address and keep it
|
||||
* until the device unrealizes.
|
||||
*
|
||||
* In some cases it might be necessary to know whether this is a "real" or
|
||||
* a temporary address (fake). */
|
||||
_LOGD (LOGD_HW | LOGD_ETHER, "hw-addr: %s (use current: %s)",
|
||||
success_read
|
||||
? "unable to read permanent MAC address"
|
||||
: "read HW addr length of permanent MAC address differs",
|
||||
priv->hw_addr);
|
||||
priv->hw_addr_perm_fake = TRUE;
|
||||
priv->hw_addr_perm = g_strdup (priv->hw_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->hw_addr_perm_fake = FALSE;
|
||||
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len);
|
||||
_LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'",
|
||||
priv->hw_addr_perm);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -11529,7 +11547,7 @@ nm_device_hw_addr_set (NMDevice *self, const char *addr)
|
|||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (!addr) {
|
||||
addr = priv->hw_addr_perm;
|
||||
addr = nm_device_get_permanent_hw_address (self, TRUE);
|
||||
if (!addr)
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -11546,18 +11564,26 @@ nm_device_hw_addr_reset (NMDevice *self)
|
|||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
addr = priv->hw_addr_initial;
|
||||
addr = nm_device_get_initial_hw_address (self);
|
||||
if (!addr)
|
||||
return FALSE;
|
||||
return _hw_addr_set (self, addr, "reset");
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_device_get_permanent_hw_address (NMDevice *self)
|
||||
nm_device_get_permanent_hw_address (NMDevice *self, gboolean fallback_fake)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
||||
|
||||
return NM_DEVICE_GET_PRIVATE (self)->hw_addr_perm;
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
if (!priv->hw_addr_perm)
|
||||
return NULL;
|
||||
if ( priv->hw_addr_perm_fake
|
||||
&& !fallback_fake)
|
||||
return NULL;
|
||||
return priv->hw_addr_perm;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
|
|||
|
|
@ -353,7 +353,8 @@ guint32 nm_device_get_ip4_route_metric (NMDevice *dev);
|
|||
guint32 nm_device_get_ip6_route_metric (NMDevice *dev);
|
||||
|
||||
const char * nm_device_get_hw_address (NMDevice *dev);
|
||||
const char * nm_device_get_permanent_hw_address (NMDevice *dev);
|
||||
const char * nm_device_get_permanent_hw_address (NMDevice *dev,
|
||||
gboolean fallback_fake);
|
||||
const char * nm_device_get_initial_hw_address (NMDevice *dev);
|
||||
|
||||
NMDhcp4Config * nm_device_get_dhcp4_config (NMDevice *dev);
|
||||
|
|
|
|||
|
|
@ -570,7 +570,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
|||
if (!s_wireless)
|
||||
return FALSE;
|
||||
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device);
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
|
||||
mac = nm_setting_wireless_get_mac_address (s_wireless);
|
||||
if (perm_hw_addr) {
|
||||
if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
|
||||
|
|
@ -862,7 +862,7 @@ complete_connection (NMDevice *device,
|
|||
if (hidden)
|
||||
g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL);
|
||||
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device);
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
|
||||
if (perm_hw_addr) {
|
||||
setting_mac = nm_setting_wireless_get_mac_address (s_wifi);
|
||||
if (setting_mac) {
|
||||
|
|
@ -2981,7 +2981,7 @@ get_property (GObject *object, guint prop_id,
|
|||
|
||||
switch (prop_id) {
|
||||
case PROP_PERM_HW_ADDRESS:
|
||||
g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (device)));
|
||||
g_value_set_string (value, nm_device_get_permanent_hw_address ((NMDevice *) device, FALSE));
|
||||
break;
|
||||
case PROP_MODE:
|
||||
g_value_set_uint (value, priv->mode);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue