summary refs log tree commit diff
path: root/src/devices/nm-device-vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/nm-device-vlan.c')
-rw-r--r--src/devices/nm-device-vlan.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index e523e6bb..b330397f 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -56,6 +56,7 @@ typedef struct {
 
 	NMDevice *parent;
 	guint parent_state_id;
+	guint parent_hwaddr_id;
 	int vlan_id;
 } NMDeviceVlanPrivate;
 
@@ -88,6 +89,36 @@ parent_state_changed (NMDevice *parent,
 }
 
 static void
+parent_hwaddr_changed (NMDevice *parent,
+                       GParamSpec *pspec,
+                       gpointer user_data)
+{
+	NMDeviceVlan *self = NM_DEVICE_VLAN (user_data);
+	NMConnection *connection;
+	NMSettingWired *s_wired;
+	const char *cloned_mac = NULL;
+
+	/* Never touch assumed devices */
+	if (nm_device_uses_assumed_connection (self))
+		return;
+
+	connection = nm_device_get_connection (self);
+	if (!connection)
+		return;
+
+	/* Update the VLAN MAC only if configuration does not specify one */
+	s_wired = nm_connection_get_setting_wired (connection);
+	if (s_wired)
+		cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
+
+	if (!cloned_mac) {
+		_LOGD (LOGD_VLAN, "parent hardware address changed");
+		nm_device_set_hw_addr (self, nm_device_get_hw_address (parent),
+		                       "set", LOGD_VLAN);
+	}
+}
+
+static void
 nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean construct)
 {
 	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
@@ -96,10 +127,8 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr
 	if (parent == priv->parent)
 		return;
 
-	if (priv->parent_state_id) {
-		g_signal_handler_disconnect (priv->parent, priv->parent_state_id);
-		priv->parent_state_id = 0;
-	}
+	nm_clear_g_signal_handler (priv->parent, &priv->parent_state_id);
+	nm_clear_g_signal_handler (priv->parent, &priv->parent_hwaddr_id);
 	g_clear_object (&priv->parent);
 
 	if (parent) {
@@ -109,6 +138,9 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr
 		                                          G_CALLBACK (parent_state_changed),
 		                                          device);
 
+		priv->parent_hwaddr_id = g_signal_connect (priv->parent, "notify::" NM_DEVICE_HW_ADDRESS,
+		                                           G_CALLBACK (parent_hwaddr_changed), device);
+
 		/* Set parent-dependent unmanaged flag */
 		if (construct) {
 			nm_device_set_initial_unmanaged_flag (device,
@@ -666,6 +698,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 	NMSettingVlan *s_vlan;
 	gs_free char *iface = NULL;
 	NMPlatformError plerr;
+	const NMPlatformLink *plink;
 
 	if (!NM_IS_DEVICE (parent)) {
 		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
@@ -696,9 +729,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 		             nm_platform_error_to_string (plerr));
 		return NULL;
 	}
+	plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
 
 	device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN,
-	                                    NM_DEVICE_IFACE, iface,
+	                                    NM_DEVICE_PLATFORM_DEVICE, plink,
 	                                    NM_DEVICE_VLAN_INT_PARENT_DEVICE, parent,
 	                                    NM_DEVICE_DRIVER, "8021q",
 	                                    NM_DEVICE_TYPE_DESC, "VLAN",