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
This commit is contained in:
Dan Williams 2010-06-24 15:14:53 -07:00
parent 3beea85a0b
commit 88eb6ced3f
4 changed files with 181 additions and 186 deletions

View file

@ -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), &ether);
hwaddr = nm_ether_ntop (&ether);
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), &ether);
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));

View file

@ -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 */

View file

@ -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), &ether);
hwaddr = nm_ether_ntop (&ether);
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));

View file

@ -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);