core: read initial MAC address on startup; reset to this MAC when disconnecting

Previously, NM reset permanent MAC to an interface while disconnecting. That
basically ignored MAC addresses set before NM started managing the interface.
Now, the initial MAC address is remembered and set back to the interface when
disconnecting.
This commit is contained in:
Jiří Klimeš 2010-09-27 09:53:51 +02:00
parent b80f31e191
commit 358261ccd9
4 changed files with 69 additions and 7 deletions

View file

@ -107,8 +107,9 @@ typedef struct Supplicant {
typedef struct {
gboolean disposed;
guint8 hw_addr[ETH_ALEN]; /* Currently set MAC address */
guint8 perm_hw_addr[ETH_ALEN]; /* Currently set MAC address */
guint8 hw_addr[ETH_ALEN]; /* Currently set MAC address */
guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */
guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */
gboolean carrier;
NMNetlinkMonitor * monitor;
@ -739,6 +740,33 @@ real_update_permanent_hw_address (NMDevice *dev)
close (fd);
}
static void
real_update_initial_hw_address (NMDevice *dev)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
char *mac_str = NULL;
guint8 *addr = priv->initial_hw_addr;
guint8 zero[ETH_ALEN] = {0,0,0,0,0,0};
/* This sets initial MAC address from current MAC address. It should only
* be called from NMDevice constructor() to really get the initial address.
*/
if (!memcmp (&priv->hw_addr, &zero, ETH_ALEN))
real_update_hw_address (dev);
if (memcmp (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN))
memcpy (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN);
mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s",
nm_device_get_iface (dev), mac_str);
g_free (mac_str);
}
static guint32
real_get_generic_capabilities (NMDevice *dev)
{
@ -1735,8 +1763,8 @@ real_deactivate_quickly (NMDevice *device)
supplicant_interface_release (self);
/* Reset MAC address back to permanent address */
_set_hw_addr (self, priv->perm_hw_addr, "reset");
/* Reset MAC address back to initial address */
_set_hw_addr (self, priv->initial_hw_addr, "reset");
}
static gboolean
@ -2110,6 +2138,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
parent_class->can_interrupt_activation = real_can_interrupt_activation;
parent_class->update_hw_address = real_update_hw_address;
parent_class->update_permanent_hw_address = real_update_permanent_hw_address;
parent_class->update_initial_hw_address = real_update_initial_hw_address;
parent_class->get_best_auto_connection = real_get_best_auto_connection;
parent_class->is_available = real_is_available;
parent_class->connection_secrets_updated = real_connection_secrets_updated;

View file

@ -146,8 +146,9 @@ typedef struct Supplicant {
struct _NMDeviceWifiPrivate {
gboolean disposed;
guint8 hw_addr[ETH_ALEN]; /* Currently set MAC address */
guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */
guint8 hw_addr[ETH_ALEN]; /* Currently set MAC address */
guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */
guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */
/* Legacy rfkill for ipw2x00; will be fixed with 2.6.33 kernel */
char * ipw_rfkill_path;
@ -1250,7 +1251,8 @@ real_deactivate_quickly (NMDevice *dev)
g_object_unref (orig_ap);
}
_set_hw_addr (self, priv->perm_hw_addr, "reset");
/* Reset MAC address back to initial address */
_set_hw_addr (self, priv->initial_hw_addr, "reset");
}
static void
@ -3106,6 +3108,32 @@ real_update_permanent_hw_address (NMDevice *dev)
close (fd);
}
static void
real_update_initial_hw_address (NMDevice *dev)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
char *mac_str = NULL;
guint8 *addr = priv->initial_hw_addr;
guint8 zero[ETH_ALEN] = {0,0,0,0,0,0};
/* This sets initial MAC address from current MAC address. It should only
* be called from NMDevice constructor() to really get the initial address.
*/
if (!memcmp (&priv->hw_addr, &zero, ETH_ALEN))
real_update_hw_address (dev);
if (memcmp (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN))
memcpy (&priv->initial_hw_addr, &priv->hw_addr, ETH_ALEN);
mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s",
nm_device_get_iface (dev), mac_str);
g_free (mac_str);
}
static NMActStageReturn
real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
@ -3935,6 +3963,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
parent_class->take_down = real_take_down;
parent_class->update_hw_address = real_update_hw_address;
parent_class->update_permanent_hw_address = real_update_permanent_hw_address;
parent_class->update_initial_hw_address = real_update_initial_hw_address;
parent_class->get_best_auto_connection = real_get_best_auto_connection;
parent_class->is_available = real_is_available;
parent_class->connection_secrets_updated = real_connection_secrets_updated;

View file

@ -288,6 +288,9 @@ constructor (GType type,
if (NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address)
NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address (dev);
if (NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address)
NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address (dev);
priv->dhcp_manager = nm_dhcp_manager_get ();
update_accept_ra_save (dev);

View file

@ -73,6 +73,7 @@ typedef struct {
void (* update_hw_address) (NMDevice *self);
void (* update_permanent_hw_address) (NMDevice *self);
void (* update_initial_hw_address) (NMDevice *self);
guint32 (* get_type_capabilities) (NMDevice *self);
guint32 (* get_generic_capabilities) (NMDevice *self);