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.c96
1 files changed, 52 insertions, 44 deletions
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index b7f0c4e7..b0e746a8 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -331,39 +331,33 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
 /*****************************************************************************/
 
 static gboolean
-check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
 	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE ((NMDeviceVlan *) device);
 	NMSettingVlan *s_vlan;
-	const char *parent;
+	const char *parent = NULL;
 
-	if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection, error))
+	if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection))
 		return FALSE;
 
-	if (nm_device_is_real (device)) {
-		s_vlan = nm_connection_get_setting_vlan (connection);
+	s_vlan = nm_connection_get_setting_vlan (connection);
+	if (!s_vlan)
+		return FALSE;
 
-		if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) {
-			nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-			                            "vlan id setting mismatches");
+	/* Before the device is realized some properties will not be set */
+	if (nm_device_is_real (device)) {
+		if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
 			return FALSE;
-		}
 
 		/* Check parent interface; could be an interface name or a UUID */
 		parent = nm_setting_vlan_get_parent (s_vlan);
 		if (parent) {
-			if (!nm_device_match_parent (device, parent)) {
-				nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-				                            "vlan parent setting differs");
+			if (!nm_device_match_parent (device, parent))
 				return FALSE;
-			}
 		} else {
 			/* Parent could be a MAC address in an NMSettingWired */
-			if (!nm_device_match_parent_hwaddr (device, connection, TRUE)) {
-				nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-				                            "vlan parent mac setting differs");
+			if (!nm_device_match_hwaddr (device, connection, TRUE))
 				return FALSE;
-			}
 		}
 	}
 
@@ -374,13 +368,12 @@ static gboolean
 check_connection_available (NMDevice *device,
                             NMConnection *connection,
                             NMDeviceCheckConAvailableFlags flags,
-                            const char *specific_object,
-                            GError **error)
+                            const char *specific_object)
 {
 	if (!nm_device_is_real (device))
 		return TRUE;
 
-	return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_available (device, connection, flags, specific_object, error);
+	return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_available (device, connection, flags, specific_object);
 }
 
 static gboolean
@@ -412,7 +405,7 @@ complete_connection (NMDevice *device,
 	 * settings, then there's not enough information to complete the setting.
 	 */
 	if (   !nm_setting_vlan_get_parent (s_vlan)
-	    && !nm_device_match_parent_hwaddr (device, connection, TRUE)) {
+	    && !nm_device_match_hwaddr (device, connection, TRUE)) {
 		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION,
 		                     "The 'vlan' setting had no interface name, parent, or hardware address.");
 		return FALSE;
@@ -427,8 +420,10 @@ update_connection (NMDevice *device, NMConnection *connection)
 	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
 	NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection);
 	int ifindex = nm_device_get_ifindex (device);
+	const char *setting_parent, *new_parent;
 	const NMPlatformLink *plink;
 	const NMPObject *polnk;
+	NMDevice *parent_device;
 	guint vlan_id;
 	guint vlan_flags;
 
@@ -446,11 +441,26 @@ update_connection (NMDevice *device, NMConnection *connection)
 	if (vlan_id != nm_setting_vlan_get_id (s_vlan))
 		g_object_set (s_vlan, NM_SETTING_VLAN_ID, vlan_id, NULL);
 
-	g_object_set (s_vlan,
-	              NM_SETTING_VLAN_PARENT,
-	              nm_device_parent_find_for_connection (device,
-	                                                    nm_setting_vlan_get_parent (s_vlan)),
-	              NULL);
+	/* Update parent in the connection; default to parent's interface name */
+	parent_device = nm_device_parent_get_device (device);
+	if (   parent_device
+	    && polnk
+	    && plink->parent > 0
+	    && nm_device_get_ifindex (parent_device) == plink->parent) {
+		new_parent = nm_device_get_iface (parent_device);
+		setting_parent = nm_setting_vlan_get_parent (s_vlan);
+		if (setting_parent && nm_utils_is_uuid (setting_parent)) {
+			NMConnection *parent_connection;
+
+			/* Don't change a parent specified by UUID if it's still valid */
+			parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent);
+			if (parent_connection && nm_device_check_connection_compatible (parent_device, parent_connection))
+				new_parent = NULL;
+		}
+		if (new_parent)
+			g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL);
+	} else
+		g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, NULL, NULL);
 
 	if (polnk)
 		vlan_flags = polnk->lnk_vlan.flags;
@@ -589,29 +599,27 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass);
-	NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
+	NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+
+	NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_VLAN_SETTING_NAME, NM_LINK_TYPE_VLAN)
 
 	object_class->get_property = get_property;
 
 	dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_vlan);
 
-	device_class->connection_type_supported = NM_SETTING_VLAN_SETTING_NAME;
-	device_class->connection_type_check_compatible = NM_SETTING_VLAN_SETTING_NAME;
-	device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_VLAN);
-
-	device_class->create_and_realize = create_and_realize;
-	device_class->link_changed = link_changed;
-	device_class->unrealize_notify = unrealize_notify;
-	device_class->get_generic_capabilities = get_generic_capabilities;
-	device_class->act_stage1_prepare = act_stage1_prepare;
-	device_class->get_configured_mtu = get_configured_mtu;
-	device_class->is_available = is_available;
-	device_class->parent_changed_notify = parent_changed_notify;
-
-	device_class->check_connection_compatible = check_connection_compatible;
-	device_class->check_connection_available = check_connection_available;
-	device_class->complete_connection = complete_connection;
-	device_class->update_connection = update_connection;
+	parent_class->create_and_realize = create_and_realize;
+	parent_class->link_changed = link_changed;
+	parent_class->unrealize_notify = unrealize_notify;
+	parent_class->get_generic_capabilities = get_generic_capabilities;
+	parent_class->act_stage1_prepare = act_stage1_prepare;
+	parent_class->get_configured_mtu = get_configured_mtu;
+	parent_class->is_available = is_available;
+	parent_class->parent_changed_notify = parent_changed_notify;
+
+	parent_class->check_connection_compatible = check_connection_compatible;
+	parent_class->check_connection_available = check_connection_available;
+	parent_class->complete_connection = complete_connection;
+	parent_class->update_connection = update_connection;
 
 	obj_properties[PROP_VLAN_ID] =
 	     g_param_spec_uint (NM_DEVICE_VLAN_ID, "", "",