From 88eb6ced3f04f2f9bd7cc47c1e0ebbe2b4b5dab7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 24 Jun 2010 15:14:53 -0700 Subject: [PATCH] core: consolidate and clean up MAC cloning code - Just use a byte array to old MAC addresses so we don't need to use .ether_addr_octet everywhere - Consolidate setting the current MAC address into one location - Make sure that if the GPERMADDR call fails we use the current MAC (this wasn't done for wired devices) - Make log messages consistent --- src/nm-device-ethernet.c | 188 ++++++++++++++++++++------------------- src/nm-device-ethernet.h | 3 - src/nm-device-wifi.c | 174 +++++++++++++++++------------------- src/nm-device-wifi.h | 2 - 4 files changed, 181 insertions(+), 186 deletions(-) diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index 2045ee7d70..30100c8197 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -104,8 +104,8 @@ typedef struct Supplicant { typedef struct { gboolean disposed; - struct ether_addr hw_addr; /* Currently set MAC address */ - struct ether_addr perm_hw_addr; /* Permanent MAC address */ + guint8 hw_addr[ETH_ALEN]; /* Currently set MAC address */ + guint8 perm_hw_addr[ETH_ALEN]; /* Currently set MAC address */ gboolean carrier; NMNetlinkMonitor * monitor; @@ -451,25 +451,13 @@ nm_device_ethernet_new (const char *udi, void nm_device_ethernet_get_address (NMDeviceEthernet *self, struct ether_addr *addr) { + NMDeviceEthernetPrivate *priv; + g_return_if_fail (self != NULL); g_return_if_fail (addr != NULL); - memcpy (addr, &(NM_DEVICE_ETHERNET_GET_PRIVATE (self)->hw_addr), sizeof (struct ether_addr)); -} - -/* - * nm_device_ethernet_get_permanent_address - * - * Get a device's permanent hardware address - * - */ -void -nm_device_ethernet_get_permanent_address (NMDeviceEthernet *self, struct ether_addr *addr) -{ - g_return_if_fail (self != NULL); - g_return_if_fail (addr != NULL); - - memcpy (addr, &(NM_DEVICE_ETHERNET_GET_PRIVATE (self)->perm_hw_addr), sizeof (struct ether_addr)); + priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + memcpy (addr, &priv->hw_addr, sizeof (priv->hw_addr)); } /* Returns speed in Mb/s */ @@ -512,11 +500,66 @@ out: return speed; } +static void +_update_hw_addr (NMDeviceEthernet *self, const guint8 *addr) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + g_return_if_fail (addr != NULL); + + if (memcmp (&priv->hw_addr, addr, ETH_ALEN)) { + memcpy (&priv->hw_addr, addr, ETH_ALEN); + g_object_notify (G_OBJECT (self), NM_DEVICE_ETHERNET_HW_ADDRESS); + } +} + +static gboolean +_set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail) +{ + NMDevice *dev = NM_DEVICE (self); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + const char *iface; + char *mac_str = NULL; + gboolean success = FALSE; + + g_return_val_if_fail (addr != NULL, FALSE); + + iface = nm_device_get_iface (dev); + + mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + /* Do nothing if current MAC is same */ + if (!memcmp (&priv->hw_addr, addr, ETH_ALEN)) { + nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): no MAC address change needed", + iface, detail, mac_str); + g_free (mac_str); + return TRUE; + } + + /* Can't change MAC address while device is up */ + real_hw_take_down (dev); + + success = nm_system_device_set_mac (iface, (struct ether_addr *) addr); + if (success) { + /* MAC address succesfully changed; update the current MAC to match */ + _update_hw_addr (self, addr); + nm_log_info (LOGD_DEVICE | LOGD_ETHER, "(%s): %s MAC address to %s", + iface, detail, mac_str); + } else { + nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "(%s): failed to %s MAC address to %s", + iface, detail, mac_str); + } + real_hw_bring_up (dev, NULL); + g_free (mac_str); + + return success; +} + static void real_update_hw_address (NMDevice *dev) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); struct ifreq req; int fd; @@ -528,19 +571,15 @@ real_update_hw_address (NMDevice *dev) memset (&req, 0, sizeof (struct ifreq)); strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); + + errno = 0; if (ioctl (fd, SIOCGIFHWADDR, &req) < 0) { nm_log_err (LOGD_HW | LOGD_ETHER, - "(%s) error getting hardware address: %d", + "(%s) failed to read hardware address (error %d)", nm_device_get_iface (dev), errno); - goto out; - } + } else + _update_hw_addr (self, (const guint8 *) &req.ifr_hwaddr.sa_data); - if (memcmp (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr))) { - memcpy (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr)); - g_object_notify (G_OBJECT (dev), NM_DEVICE_ETHERNET_HW_ADDRESS); - } - -out: close (fd); } @@ -551,7 +590,7 @@ real_update_permanent_hw_address (NMDevice *dev) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); struct ifreq req; struct ethtool_perm_addr *epaddr = NULL; - int fd; + int fd, ret; fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd < 0) { @@ -562,24 +601,26 @@ real_update_permanent_hw_address (NMDevice *dev) /* Get permanent MAC address */ memset (&req, 0, sizeof (struct ifreq)); strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); - epaddr = (struct ethtool_perm_addr *) g_malloc0 (sizeof(struct ethtool_perm_addr) + ETH_ALEN); + + epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN); epaddr->cmd = ETHTOOL_GPERMADDR; epaddr->size = ETH_ALEN; - req.ifr_data = epaddr; + req.ifr_data = (void *) epaddr; + errno = 0; - if (ioctl (fd, SIOCETHTOOL, &req) < 0) { - nm_log_err (LOGD_HW | LOGD_ETHER, "SIOCETHTOOL failed: %d; unable to get permanent MAC address for %s", - errno, nm_device_get_iface (dev)); - goto out; + ret = ioctl (fd, SIOCETHTOOL, &req); + if (ret < 0) { + nm_log_err (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)", + nm_device_get_iface (dev), errno); + /* Fall back to current address */ + memcpy (epaddr->data, &priv->hw_addr, ETH_ALEN); } - if (memcmp (&priv->perm_hw_addr, epaddr->data, sizeof (struct ether_addr))) { - memcpy (&priv->perm_hw_addr, epaddr->data, sizeof (struct ether_addr)); + if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) { + memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN); g_object_notify (G_OBJECT (dev), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS); } -out: - g_free (epaddr); close (fd); } @@ -666,7 +707,7 @@ real_get_best_auto_connection (NMDevice *dev, const GByteArray *mac; mac = nm_setting_wired_get_mac_address (s_wired); - if (mac && memcmp (mac->data, priv->hw_addr.ether_addr_octet, ETH_ALEN)) + if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) continue; } @@ -1278,7 +1319,6 @@ static NMActStageReturn real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMActRequest *req; NMSettingWired *s_wired; const GByteArray *cloned_mac; @@ -1292,23 +1332,10 @@ real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) s_wired = NM_SETTING_WIRED (device_get_setting (dev, NM_TYPE_SETTING_WIRED)); g_assert (s_wired); + /* Set device MAC address if the connection wants to change it */ cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac) { - char *mac_str = NULL; - - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", cloned_mac->data[0], cloned_mac->data[1], cloned_mac->data[2], - cloned_mac->data[3], cloned_mac->data[4], cloned_mac->data[5]); - real_hw_take_down (dev); - if (nm_system_device_set_mac (nm_device_get_iface (dev), (struct ether_addr *) cloned_mac->data)) { - /* MAC address succesfully spoofed on interface, set it to hw_addr too */ - memcpy (priv->hw_addr.ether_addr_octet, cloned_mac->data, ETH_ALEN); - nm_log_info (LOGD_DEVICE | LOGD_ETHER, "cloned MAC %s set to %s", mac_str, nm_device_get_iface (dev)); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "failed to set cloned MAC %s to %s", mac_str, nm_device_get_iface (dev)); - } - real_hw_bring_up (dev, NULL); - g_free (mac_str); - } + if (cloned_mac && (cloned_mac->len == ETH_ALEN)) + _set_hw_addr (self, (const guint8 *) cloned_mac->data, "set"); return ret; } @@ -1541,8 +1568,8 @@ real_act_stage4_get_ip4_config (NMDevice *device, static void real_deactivate_quickly (NMDevice *device) { - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - char *mac_str = NULL; + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); if (priv->pending_ip4_config) { g_object_unref (priv->pending_ip4_config); @@ -1554,23 +1581,10 @@ real_deactivate_quickly (NMDevice *device) priv->ppp_manager = NULL; } - supplicant_interface_release (NM_DEVICE_ETHERNET (device)); + supplicant_interface_release (self); - /* Set permanent MAC address back to the interface */ - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - priv->perm_hw_addr.ether_addr_octet[0], priv->perm_hw_addr.ether_addr_octet[1], priv->perm_hw_addr.ether_addr_octet[2], - priv->perm_hw_addr.ether_addr_octet[3], priv->perm_hw_addr.ether_addr_octet[4], priv->perm_hw_addr.ether_addr_octet[5]); - real_hw_take_down (device); - if (nm_system_device_set_mac (nm_device_get_iface (device), &priv->perm_hw_addr)) { - /* MAC address succesfully spoofed on interface, set it to hw_addr too */ - memcpy (priv->hw_addr.ether_addr_octet, &priv->perm_hw_addr, ETH_ALEN); - nm_log_info (LOGD_DEVICE | LOGD_ETHER, "permanent MAC address %s set back to %s", mac_str, nm_device_get_iface (device)); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "failed to set permanent MAC address %s back to %s", mac_str, nm_device_get_iface (device)); - } - real_hw_bring_up (device, NULL); - - g_free (mac_str); + /* Reset MAC address back to permanent address */ + _set_hw_addr (self, priv->perm_hw_addr, "reset"); } static gboolean @@ -1613,7 +1627,7 @@ real_check_connection_compatible (NMDevice *device, const GByteArray *mac; mac = nm_setting_wired_get_mac_address (s_wired); - if (mac && memcmp (mac->data, &(priv->perm_hw_addr.ether_addr_octet), ETH_ALEN)) { + if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) { g_set_error (error, NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, "The connection's MAC address did not match this device."); @@ -1629,12 +1643,11 @@ real_check_connection_compatible (NMDevice *device, static gboolean spec_match_list (NMDevice *device, const GSList *specs) { - struct ether_addr ether; + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); char *hwaddr; gboolean matched; - nm_device_ethernet_get_permanent_address (NM_DEVICE_ETHERNET (device), ðer); - hwaddr = nm_ether_ntop (ðer); + hwaddr = nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr); matched = nm_match_spec_hwaddr (specs, hwaddr); g_free (hwaddr); @@ -1644,8 +1657,8 @@ spec_match_list (NMDevice *device, const GSList *specs) static gboolean wired_match_config (NMDevice *self, NMConnection *connection) { + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMSettingWired *s_wired; - struct ether_addr ether; const GByteArray *s_ether; s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED); @@ -1654,12 +1667,8 @@ wired_match_config (NMDevice *self, NMConnection *connection) /* MAC address check */ s_ether = nm_setting_wired_get_mac_address (s_wired); - if (s_ether) { - nm_device_ethernet_get_permanent_address (NM_DEVICE_ETHERNET (self), ðer); - - if (memcmp (s_ether->data, ether.ether_addr_octet, ETH_ALEN)) - return FALSE; - } + if (s_ether && memcmp (s_ether->data, priv->perm_hw_addr, ETH_ALEN)) + return FALSE; return TRUE; } @@ -1875,16 +1884,13 @@ get_property (GObject *object, guint prop_id, { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - struct ether_addr hw_addr; switch (prop_id) { case PROP_HW_ADDRESS: - nm_device_ethernet_get_address (self, &hw_addr); - g_value_take_string (value, nm_ether_ntop (&hw_addr)); + g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->hw_addr)); break; case PROP_PERM_HW_ADDRESS: - nm_device_ethernet_get_permanent_address (self, &hw_addr); - g_value_take_string (value, nm_ether_ntop (&hw_addr)); + g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr)); break; case PROP_SPEED: g_value_set_uint (value, nm_device_ethernet_get_speed (self)); diff --git a/src/nm-device-ethernet.h b/src/nm-device-ethernet.h index 243fbedb29..b9e2afd402 100644 --- a/src/nm-device-ethernet.h +++ b/src/nm-device-ethernet.h @@ -63,9 +63,6 @@ NMDevice *nm_device_ethernet_new (const char *udi, void nm_device_ethernet_get_address (NMDeviceEthernet *dev, struct ether_addr *addr); -void nm_device_ethernet_get_permanent_address (NMDeviceEthernet *dev, - struct ether_addr *addr); - G_END_DECLS #endif /* NM_DEVICE_ETHERNET_H */ diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 9aac25fa3c..bbc365e7ba 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -146,9 +146,8 @@ typedef struct Supplicant { struct _NMDeviceWifiPrivate { gboolean disposed; - struct ether_addr hw_addr; /* Currently set MAC address */ - struct ether_addr perm_hw_addr; /* Permanent MAC address */ - gboolean perm_hw_addr_is_set; + guint8 hw_addr[ETH_ALEN]; /* Currently set MAC address */ + guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */ /* Legacy rfkill for ipw2x00; will be fixed with 2.6.33 kernel */ char * ipw_rfkill_path; @@ -1090,6 +1089,62 @@ real_bring_up (NMDevice *dev) return TRUE; } +static void +_update_hw_addr (NMDeviceWifi *self, const guint8 *addr) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + g_return_if_fail (addr != NULL); + + if (memcmp (&priv->hw_addr, addr, ETH_ALEN)) { + memcpy (&priv->hw_addr, addr, ETH_ALEN); + g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_HW_ADDRESS); + } +} + +static gboolean +_set_hw_addr (NMDeviceWifi *self, const guint8 *addr, const char *detail) +{ + NMDevice *dev = NM_DEVICE (self); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + const char *iface; + char *mac_str = NULL; + gboolean success = FALSE; + + g_return_val_if_fail (addr != NULL, FALSE); + + iface = nm_device_get_iface (dev); + + mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + /* Do nothing if current MAC is same */ + if (!memcmp (&priv->hw_addr, addr, ETH_ALEN)) { + nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): no MAC address change needed", + iface, detail, mac_str); + g_free (mac_str); + return TRUE; + } + + /* Can't change MAC address while device is up */ + real_hw_take_down (dev); + + success = nm_system_device_set_mac (iface, (struct ether_addr *) addr); + if (success) { + /* MAC address succesfully changed; update the current MAC to match */ + _update_hw_addr (self, addr); + nm_log_info (LOGD_DEVICE | LOGD_ETHER, "(%s): %s MAC address to %s", + iface, detail, mac_str); + } else { + nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "(%s): failed to %s MAC address to %s", + iface, detail, mac_str); + } + real_hw_bring_up (dev, NULL); + g_free (mac_str); + + return success; +} + static void access_point_removed (NMDeviceWifi *device, NMAccessPoint *ap) { @@ -1135,7 +1190,6 @@ real_deactivate_quickly (NMDevice *dev) NMDeviceWifi *self = NM_DEVICE_WIFI (dev); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMAccessPoint *orig_ap = nm_device_wifi_get_activation_ap (self); - char *mac_str = NULL; cleanup_association_attempt (self, TRUE); @@ -1156,21 +1210,7 @@ real_deactivate_quickly (NMDevice *dev) g_object_unref (orig_ap); } - /* Set permanent MAC address back to the interface */ - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - priv->perm_hw_addr.ether_addr_octet[0], priv->perm_hw_addr.ether_addr_octet[1], priv->perm_hw_addr.ether_addr_octet[2], - priv->perm_hw_addr.ether_addr_octet[3], priv->perm_hw_addr.ether_addr_octet[4], priv->perm_hw_addr.ether_addr_octet[5]); - real_hw_take_down (dev); - if (nm_system_device_set_mac (nm_device_get_iface (dev), &priv->perm_hw_addr)) { - /* MAC address succesfully spoofed on interface, set it to hw_addr too */ - memcpy (priv->hw_addr.ether_addr_octet, &priv->perm_hw_addr, ETH_ALEN); - nm_log_info (LOGD_DEVICE | LOGD_ETHER, "permanent MAC address %s set back to %s", mac_str, nm_device_get_iface (dev)); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "failed to set permanent MAC address %s back to %s", mac_str, nm_device_get_iface (dev)); - } - real_hw_bring_up (dev, NULL); - - g_free (mac_str); + _set_hw_addr (self, priv->perm_hw_addr, "reset"); } static void @@ -1213,7 +1253,7 @@ real_check_connection_compatible (NMDevice *device, } mac = nm_setting_wireless_get_mac_address (s_wireless); - if (mac && memcmp (mac->data, &(priv->perm_hw_addr.ether_addr_octet), ETH_ALEN)) { + if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) { g_set_error (error, NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, "The connection's MAC address did not match this device."); @@ -1288,7 +1328,7 @@ real_get_best_auto_connection (NMDevice *dev, continue; mac = nm_setting_wireless_get_mac_address (s_wireless); - if (mac && memcmp (mac->data, priv->hw_addr.ether_addr_octet, ETH_ALEN)) + if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) continue; /* Use the connection if it's a shared connection */ @@ -1328,26 +1368,7 @@ nm_device_wifi_get_address (NMDeviceWifi *self, g_return_if_fail (addr != NULL); priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - memcpy (addr, &(priv->hw_addr), sizeof (struct ether_addr)); -} - -/* - * nm_device_wifi_get_permanent_address - * - * Get a device's permanent hardware address - * - */ -void -nm_device_wifi_get_permanent_address (NMDeviceWifi *self, - struct ether_addr *addr) -{ - NMDeviceWifiPrivate *priv; - - g_return_if_fail (self != NULL); - g_return_if_fail (addr != NULL); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - memcpy (addr, &(priv->perm_hw_addr), sizeof (struct ether_addr)); + memcpy (addr, &priv->hw_addr, sizeof (struct ether_addr)); } static void @@ -2964,7 +2985,6 @@ static void real_update_hw_address (NMDevice *dev) { NMDeviceWifi *self = NM_DEVICE_WIFI (dev); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); struct ifreq req; int fd; @@ -2976,18 +2996,13 @@ real_update_hw_address (NMDevice *dev) memset (&req, 0, sizeof (struct ifreq)); strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); + errno = 0; if (ioctl (fd, SIOCGIFHWADDR, &req) < 0) { - nm_log_err (LOGD_HW | LOGD_WIFI, "(%s) error getting hardware address: %d", + nm_log_err (LOGD_HW | LOGD_WIFI, "(%s): unable to read hardware address (error %d)", nm_device_get_iface (dev), errno); - goto out; - } + } else + _update_hw_addr (self, (const guint8 *) &req.ifr_hwaddr.sa_data); - if (memcmp (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr))) { - memcpy (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr)); - g_object_notify (G_OBJECT (dev), NM_DEVICE_WIFI_HW_ADDRESS); - } - -out: close (fd); } @@ -2998,7 +3013,7 @@ real_update_permanent_hw_address (NMDevice *dev) NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); struct ifreq req; struct ethtool_perm_addr *epaddr = NULL; - int fd; + int fd, ret; fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd < 0) { @@ -3009,29 +3024,26 @@ real_update_permanent_hw_address (NMDevice *dev) /* Get permanent MAC address */ memset (&req, 0, sizeof (struct ifreq)); strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); - epaddr = (struct ethtool_perm_addr *) g_malloc0 (sizeof(struct ethtool_perm_addr) + ETH_ALEN); + + epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN); epaddr->cmd = ETHTOOL_GPERMADDR; epaddr->size = ETH_ALEN; req.ifr_data = (void *) epaddr; + errno = 0; - if (ioctl (fd, SIOCETHTOOL, &req) < 0) { - nm_log_err (LOGD_HW | LOGD_ETHER, "SIOCETHTOOL failed: %d; unable to get permanent MAC address for %s", - errno, nm_device_get_iface (dev)); - - nm_log_warn (LOGD_HW | LOGD_ETHER, "Using current address as permanent address for %s", - nm_device_get_iface (dev)); - memcpy (&priv->perm_hw_addr, &priv->hw_addr, sizeof (struct ether_addr)); - g_object_notify (G_OBJECT (dev), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS); - - goto out; + ret = ioctl (fd, SIOCETHTOOL, &req); + if (ret < 0) { + nm_log_err (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)", + nm_device_get_iface (dev), errno); + /* Fall back to current address */ + memcpy (epaddr->data, &priv->hw_addr, ETH_ALEN); } - if (memcmp (&priv->perm_hw_addr, epaddr->data, sizeof (struct ether_addr))) { - memcpy (&priv->perm_hw_addr, epaddr->data, sizeof (struct ether_addr)); + if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) { + memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN); g_object_notify (G_OBJECT (dev), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS); } -out: g_free (epaddr); close (fd); } @@ -3060,22 +3072,8 @@ real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) g_assert (s_wireless); cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless); - if (cloned_mac) { - char *mac_str = NULL; - - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", cloned_mac->data[0], cloned_mac->data[1], cloned_mac->data[2], - cloned_mac->data[3], cloned_mac->data[4], cloned_mac->data[5]); - real_hw_take_down (dev); - if (nm_system_device_set_mac (nm_device_get_iface (dev), (struct ether_addr *) cloned_mac->data)) { - /* MAC address succesfully spoofed on interface, set it to hw_addr too */ - memcpy (priv->hw_addr.ether_addr_octet, cloned_mac->data, ETH_ALEN); - nm_log_info (LOGD_DEVICE | LOGD_ETHER, "cloned MAC %s set to %s", mac_str, nm_device_get_iface (dev)); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "failed to set cloned MAC %s to %s", mac_str, nm_device_get_iface (dev)); - } - real_hw_bring_up (dev, NULL); - g_free (mac_str); - } + if (cloned_mac && (cloned_mac->len == ETH_ALEN)) + _set_hw_addr (self, (const guint8 *) cloned_mac->data, "set"); /* If the user is trying to connect to an AP that NM doesn't yet know about * (hidden network or something), create an fake AP from the security @@ -3537,12 +3535,11 @@ real_get_type_capabilities (NMDevice *dev) static gboolean spec_match_list (NMDevice *device, const GSList *specs) { - struct ether_addr ether; + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); char *hwaddr; gboolean matched; - nm_device_wifi_get_permanent_address (NM_DEVICE_WIFI (device), ðer); - hwaddr = nm_ether_ntop (ðer); + hwaddr = nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr); matched = nm_match_spec_hwaddr (specs, hwaddr); g_free (hwaddr); @@ -3800,16 +3797,13 @@ get_property (GObject *object, guint prop_id, { NMDeviceWifi *device = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); - struct ether_addr hw_addr; switch (prop_id) { case PROP_HW_ADDRESS: - nm_device_wifi_get_address (device, &hw_addr); - g_value_take_string (value, nm_ether_ntop (&hw_addr)); + g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->hw_addr)); break; case PROP_PERM_HW_ADDRESS: - nm_device_wifi_get_permanent_address (device, &hw_addr); - g_value_take_string (value, nm_ether_ntop (&hw_addr)); + g_value_take_string (value, nm_ether_ntop ((struct ether_addr *) &priv->perm_hw_addr)); break; case PROP_MODE: g_value_set_uint (value, nm_device_wifi_get_mode (device)); diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h index d8b8522858..31ac5ad5b5 100644 --- a/src/nm-device-wifi.h +++ b/src/nm-device-wifi.h @@ -88,8 +88,6 @@ NMDevice *nm_device_wifi_new (const char *udi, void nm_device_wifi_get_address (NMDeviceWifi *dev, struct ether_addr *addr); -void nm_device_wifi_get_permanent_address (NMDeviceWifi *dev, struct ether_addr *addr); - void nm_device_wifi_get_bssid (NMDeviceWifi *dev, struct ether_addr *bssid); const GByteArray * nm_device_wifi_get_ssid (NMDeviceWifi *self);