core: implement :mtu and :cloned-mac-address for VLAN

This commit is contained in:
Dan Winship
2013-09-08 13:39:03 -04:00
parent 68bb65fbab
commit ebdf1796f1
5 changed files with 113 additions and 94 deletions

View File

@@ -301,54 +301,6 @@ nm_device_ethernet_new (NMPlatformLink *platform_device)
NULL); NULL);
} }
static gboolean
_set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail)
{
NMDevice *dev = NM_DEVICE (self);
const char *iface;
char *mac_str = NULL;
gboolean success = FALSE;
const guint8 *cur_addr = nm_device_get_hw_address (dev, NULL);
g_return_val_if_fail (addr != NULL, FALSE);
iface = nm_device_get_iface (dev);
/* Do nothing if current MAC is same */
if (cur_addr && !memcmp (cur_addr, addr, ETH_ALEN)) {
nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): no MAC address change needed", iface);
return TRUE;
}
mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
/* Can't change MAC address while device is up */
nm_device_take_down (dev, FALSE);
success = nm_platform_link_set_address (nm_device_get_ip_ifindex (dev), addr, ETH_ALEN);
if (success) {
/* MAC address succesfully changed; update the current MAC to match */
nm_device_update_hw_address (dev);
cur_addr = nm_device_get_hw_address (dev, NULL);
if (memcmp (cur_addr, addr, ETH_ALEN) == 0) {
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): new MAC address %s "
"not successfully set",
iface, mac_str);
}
} else {
nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "(%s): failed to %s MAC address to %s",
iface, detail, mac_str);
}
nm_device_bring_up (dev, FALSE, NULL);
g_free (mac_str);
return success;
}
static void static void
update_permanent_hw_address (NMDevice *dev) update_permanent_hw_address (NMDevice *dev)
{ {
@@ -953,7 +905,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
/* Set device MAC address if the connection wants to change it */ /* Set device MAC address if the connection wants to change it */
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
if (cloned_mac && (cloned_mac->len == ETH_ALEN)) if (cloned_mac && (cloned_mac->len == ETH_ALEN))
_set_hw_addr (self, (const guint8 *) cloned_mac->data, "set"); nm_device_set_hw_addr (dev, cloned_mac->data, "set", LOGD_ETHER);
} }
} }
@@ -1178,7 +1130,7 @@ deactivate (NMDevice *device)
supplicant_interface_release (self); supplicant_interface_release (self);
/* Reset MAC address back to initial address */ /* Reset MAC address back to initial address */
_set_hw_addr (self, priv->initial_hw_addr, "reset"); nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_ETHER);
} }
static gboolean static gboolean

View File

@@ -53,6 +53,8 @@ gboolean nm_device_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmwar
void nm_device_take_down (NMDevice *self, gboolean block); void nm_device_take_down (NMDevice *self, gboolean block);
gboolean nm_device_update_hw_address (NMDevice *self); gboolean nm_device_update_hw_address (NMDevice *self);
gboolean nm_device_set_hw_addr (NMDevice *device, const guint8 *addr,
const char *detail, guint64 hw_log_domain);
gboolean nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6); gboolean nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6);

View File

@@ -46,6 +46,8 @@ G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE)
#define NM_VLAN_ERROR (nm_vlan_error_quark ()) #define NM_VLAN_ERROR (nm_vlan_error_quark ())
typedef struct { typedef struct {
guint8 initial_hw_addr[ETH_ALEN];
gboolean disposed; gboolean disposed;
gboolean invalid; gboolean invalid;
@@ -76,6 +78,21 @@ nm_vlan_error_quark (void)
/******************************************************************/ /******************************************************************/
static void
update_initial_hw_address (NMDevice *dev)
{
NMDeviceVlan *self = NM_DEVICE_VLAN (dev);
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
char *mac_str;
memcpy (priv->initial_hw_addr, nm_device_get_hw_address (dev, NULL), ETH_ALEN);
mac_str = nm_utils_hwaddr_ntoa (priv->initial_hw_addr, ARPHRD_ETHER);
nm_log_dbg (LOGD_DEVICE | LOGD_VLAN, "(%s): read initial MAC address %s",
nm_device_get_iface (dev), mac_str);
g_free (mac_str);
}
static guint32 static guint32
get_generic_capabilities (NMDevice *dev) get_generic_capabilities (NMDevice *dev)
{ {
@@ -294,6 +311,8 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
NMActRequest *req; NMActRequest *req;
NMConnection *connection; NMConnection *connection;
NMSettingVlan *s_vlan; NMSettingVlan *s_vlan;
NMSettingWired *s_wired;
const GByteArray *cloned_mac;
NMActStageReturn ret; NMActStageReturn ret;
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
@@ -308,6 +327,14 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
connection = nm_act_request_get_connection (req); connection = nm_act_request_get_connection (req);
g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
s_wired = nm_connection_get_setting_wired (connection);
if (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 && (cloned_mac->len == ETH_ALEN))
nm_device_set_hw_addr (dev, (const guint8 *) cloned_mac->data, "set", LOGD_VLAN);
}
s_vlan = nm_connection_get_setting_vlan (connection); s_vlan = nm_connection_get_setting_vlan (connection);
if (s_vlan) { if (s_vlan) {
int ifindex = nm_device_get_ifindex (dev); int ifindex = nm_device_get_ifindex (dev);
@@ -329,6 +356,34 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
return ret; return ret;
} }
static void
ip4_config_pre_commit (NMDevice *device, NMIP4Config *config)
{
NMConnection *connection;
NMSettingWired *s_wired;
guint32 mtu;
connection = nm_device_get_connection (device);
g_assert (connection);
s_wired = nm_connection_get_setting_wired (connection);
if (s_wired) {
mtu = nm_setting_wired_get_mtu (s_wired);
if (mtu)
nm_ip4_config_set_mtu (config, mtu);
}
}
static void
deactivate (NMDevice *device)
{
NMDeviceVlan *self = NM_DEVICE_VLAN (device);
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
/* Reset MAC address back to initial address */
nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_VLAN);
}
/******************************************************************/ /******************************************************************/
static void static void
@@ -550,9 +605,12 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
object_class->set_property = set_property; object_class->set_property = set_property;
object_class->dispose = dispose; object_class->dispose = dispose;
parent_class->update_initial_hw_address = update_initial_hw_address;
parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->bring_up = bring_up; parent_class->bring_up = bring_up;
parent_class->act_stage1_prepare = act_stage1_prepare; parent_class->act_stage1_prepare = act_stage1_prepare;
parent_class->ip4_config_pre_commit = ip4_config_pre_commit;
parent_class->deactivate = deactivate;
parent_class->check_connection_compatible = check_connection_compatible; parent_class->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection; parent_class->complete_connection = complete_connection;

View File

@@ -784,48 +784,6 @@ bring_up (NMDevice *device, gboolean *no_firmware)
return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->bring_up (device, no_firmware); return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->bring_up (device, no_firmware);
} }
static gboolean
_set_hw_addr (NMDeviceWifi *self, const guint8 *addr, const char *detail)
{
NMDevice *dev = NM_DEVICE (self);
const char *iface;
char *mac_str = NULL;
gboolean success = FALSE;
const guint8 *cur_addr = nm_device_get_hw_address (dev, NULL);
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 (cur_addr && !memcmp (cur_addr, addr, ETH_ALEN)) {
nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): no MAC address change needed", iface);
g_free (mac_str);
return TRUE;
}
/* Can't change MAC address while device is up */
nm_device_take_down (dev, FALSE);
success = nm_platform_link_set_address (nm_device_get_ip_ifindex (dev), addr, ETH_ALEN);
if (success) {
/* MAC address succesfully changed; update the current MAC to match */
nm_device_update_hw_address (dev);
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);
}
bring_up (dev, NULL);
g_free (mac_str);
return success;
}
static void static void
remove_access_point (NMDeviceWifi *device, remove_access_point (NMDeviceWifi *device,
NMAccessPoint *ap, NMAccessPoint *ap,
@@ -896,7 +854,7 @@ deactivate (NMDevice *dev)
remove_access_point (self, orig_ap, TRUE); remove_access_point (self, orig_ap, TRUE);
/* Reset MAC address back to initial address */ /* Reset MAC address back to initial address */
_set_hw_addr (self, priv->initial_hw_addr, "reset"); nm_device_set_hw_addr (dev, priv->initial_hw_addr, "reset", LOGD_WIFI);
/* Ensure we're in infrastructure mode after deactivation; some devices /* Ensure we're in infrastructure mode after deactivation; some devices
* (usually older ones) don't scan well in adhoc mode. * (usually older ones) don't scan well in adhoc mode.
@@ -2881,7 +2839,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
/* Set spoof MAC to the interface */ /* Set spoof MAC to the interface */
cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless); cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
if (cloned_mac && (cloned_mac->len == ETH_ALEN)) if (cloned_mac && (cloned_mac->len == ETH_ALEN))
_set_hw_addr (self, (const guint8 *) cloned_mac->data, "set"); nm_device_set_hw_addr (dev, (const guint8 *) cloned_mac->data, "set", LOGD_WIFI);
/* AP mode never uses a specific object or existing scanned AP */ /* AP mode never uses a specific object or existing scanned AP */
if (priv->mode != NM_802_11_MODE_AP) { if (priv->mode != NM_802_11_MODE_AP) {

View File

@@ -6704,6 +6704,55 @@ nm_device_update_hw_address (NMDevice *dev)
return changed; return changed;
} }
gboolean
nm_device_set_hw_addr (NMDevice *device, const guint8 *addr,
const char *detail, guint64 hw_log_domain)
{
const char *iface;
char *mac_str = NULL;
gboolean success = FALSE;
guint len;
const guint8 *cur_addr = nm_device_get_hw_address (device, &len);
g_return_val_if_fail (addr != NULL, FALSE);
iface = nm_device_get_iface (device);
/* Do nothing if current MAC is same */
if (cur_addr && !memcmp (cur_addr, addr, len)) {
nm_log_dbg (LOGD_DEVICE | hw_log_domain, "(%s): no MAC address change needed", iface);
return TRUE;
}
mac_str = nm_utils_hwaddr_ntoa_len (addr, len);
/* Can't change MAC address while device is up */
nm_device_take_down (device, FALSE);
success = nm_platform_link_set_address (nm_device_get_ip_ifindex (device), addr, len);
if (success) {
/* MAC address succesfully changed; update the current MAC to match */
nm_device_update_hw_address (device);
cur_addr = nm_device_get_hw_address (device, NULL);
if (memcmp (cur_addr, addr, len) == 0) {
nm_log_info (LOGD_DEVICE | hw_log_domain, "(%s): %s MAC address to %s",
iface, detail, mac_str);
} else {
nm_log_warn (LOGD_DEVICE | hw_log_domain, "(%s): new MAC address %s "
"not successfully set",
iface, mac_str);
success = FALSE;
}
} else {
nm_log_warn (LOGD_DEVICE | hw_log_domain, "(%s): failed to %s MAC address to %s",
iface, detail, mac_str);
}
nm_device_bring_up (device, NULL);
g_free (mac_str);
return success;
}
void void
nm_device_add_pending_action (NMDevice *device, const char *action) nm_device_add_pending_action (NMDevice *device, const char *action)
{ {