From 358261ccd9d1cf4b97969136d657e7c49be52bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Mon, 27 Sep 2010 09:53:51 +0200 Subject: [PATCH] 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. --- src/nm-device-ethernet.c | 37 +++++++++++++++++++++++++++++++++---- src/nm-device-wifi.c | 35 ++++++++++++++++++++++++++++++++--- src/nm-device.c | 3 +++ src/nm-device.h | 1 + 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index 393b921c65..08bbc50112 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -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; diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 3973fe7bc5..b09d112547 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -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; diff --git a/src/nm-device.c b/src/nm-device.c index a7f7b868bb..6b12471adc 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -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); diff --git a/src/nm-device.h b/src/nm-device.h index ca067f441e..db2b1b7db0 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -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);