summary refs log tree commit diff
path: root/src/devices/nm-device.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2016-05-11 17:08:25 +0200
committerMichael Biebl <biebl@debian.org>2016-05-11 17:08:25 +0200
commit73e152af6e3fb4f5848bfb8394484026ff119003 (patch)
treed5a8b37778d3a95c51511451b38b6a329b94cb41 /src/devices/nm-device.c
parent78c3b8801ecf4975e5da1af3b10ae20dd2d876de (diff)
Imported Upstream version 1.2.2 upstream/1.2.2
Diffstat (limited to 'src/devices/nm-device.c')
-rw-r--r--src/devices/nm-device.c139
1 files changed, 89 insertions, 50 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 08cf6dce..8472ff80 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1276,7 +1276,7 @@ void
 nm_device_update_dynamic_ip_setup (NMDevice *self)
 {
 	NMDevicePrivate *priv;
-	GError *error;
+	GError *error = NULL;
 	gconstpointer addr;
 	size_t addr_length;
 
@@ -1887,6 +1887,8 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
 	g_return_if_fail (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT));
 	g_return_if_fail (priv->ip_ifindex <= 0);
 	g_return_if_fail (priv->ip_iface == NULL);
+	g_return_if_fail (!priv->queued_ip4_config_id);
+	g_return_if_fail (!priv->queued_ip6_config_id);
 
 	_LOGD (LOGD_DEVICE, "start setup of %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), plink ? plink->ifindex : 0);
 
@@ -3382,6 +3384,15 @@ activation_source_schedule (NMDevice *self, ActivationHandleFunc func, int famil
 	act_data->id = new_id;
 }
 
+static gboolean
+activation_source_is_scheduled (NMDevice *self, ActivationHandleFunc func, int family)
+{
+	ActivationHandleData *act_data;
+
+	act_data = activation_source_get_by_family (self, family, NULL);
+	return act_data->func == func;
+}
+
 /*****************************************************************************/
 
 static gboolean
@@ -4456,6 +4467,8 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config)
 		                    NULL,
 		                    NULL,
 		                    NULL);
+
+		nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE);
 	}
 }
 
@@ -5187,6 +5200,8 @@ dhcp6_lease_change (NMDevice *self)
 		                    settings_connection,
 		                    nm_device_get_applied_connection (self),
 		                    self, NULL, NULL, NULL);
+
+		nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
 	}
 }
 
@@ -6827,30 +6842,6 @@ activate_stage5_ip4_config_commit (NMDevice *self)
 	check_ip_done (self);
 }
 
-static void
-queued_ip4_config_change_clear (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->queued_ip4_config_id) {
-		_LOGD (LOGD_DEVICE, "clearing queued IP4 config change");
-		g_source_remove (priv->queued_ip4_config_id);
-		priv->queued_ip4_config_id = 0;
-	}
-}
-
-static void
-queued_ip6_config_change_clear (NMDevice *self)
-{
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
-	if (priv->queued_ip6_config_id) {
-		_LOGD (LOGD_DEVICE, "clearing queued IP6 config change");
-		g_source_remove (priv->queued_ip6_config_id);
-		priv->queued_ip6_config_id = 0;
-	}
-}
-
 void
 nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *config)
 {
@@ -6863,7 +6854,6 @@ nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *conf
 	if (config)
 		priv->dev_ip4_config = g_object_ref (config);
 
-	queued_ip4_config_change_clear (self);
 	activation_source_schedule (self, activate_stage5_ip4_config_commit, AF_INET);
 }
 
@@ -7109,7 +7099,9 @@ _cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type)
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
 	priv->ip4_state =  IP_NONE;
-	queued_ip4_config_change_clear (self);
+
+	if (nm_clear_g_source (&priv->queued_ip4_config_id))
+		_LOGD (LOGD_DEVICE, "clearing queued IP4 config change");
 
 	dhcp4_cleanup (self, cleanup_type, FALSE);
 	arp_cleanup (self);
@@ -7123,7 +7115,9 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type)
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 
 	priv->ip6_state = IP_NONE;
-	queued_ip6_config_change_clear (self);
+
+	if (nm_clear_g_source (&priv->queued_ip6_config_id))
+		_LOGD (LOGD_DEVICE, "clearing queued IP6 config change");
 
 	dhcp6_cleanup (self, cleanup_type, FALSE);
 	linklocal6_cleanup (self);
@@ -7169,22 +7163,25 @@ _hash_check_invalid_keys_impl (GHashTable *hash, const char *setting_name, GErro
 
 		g_hash_table_iter_init (&iter, hash);
 		while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) {
-			for (i = 0; argv[i]; i++) {
-				if (!strcmp (argv[i], k)) {
-					first_invalid_key = k;
-					break;
-				}
-			}
-			if (first_invalid_key)
+			if (_nm_utils_strv_find_first ((char **) argv, -1, k) < 0) {
+				first_invalid_key = k;
 				break;
+			}
+		}
+		if (setting_name) {
+			g_set_error (error,
+			             NM_DEVICE_ERROR,
+			             NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
+			             "Can't reapply changes to '%s.%s' setting",
+			             setting_name,
+			             first_invalid_key);
+		} else {
+			g_set_error (error,
+			             NM_DEVICE_ERROR,
+			             NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
+			             "Can't reapply any changes to '%s' setting",
+			             first_invalid_key);
 		}
-		g_set_error (error,
-		             NM_DEVICE_ERROR,
-		             NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
-		             "Can't reapply changes to '%s%s%s' setting",
-		             setting_name ? : "",
-		             setting_name ? "." : "",
-		             first_invalid_key ? : "<UNKNOWN>");
 		g_return_val_if_fail (first_invalid_key, FALSE);
 		return FALSE;
 	}
@@ -7305,9 +7302,16 @@ reapply_connection (NMDevice *self,
 	                               NM_SETTING_CONNECTION_SETTING_NAME))
 		return FALSE;
 
+	/* whitelist allowed properties from "connection" setting which are allowed to differ.
+	 *
+	 * This includes UUID, there is no principal problem with reapplying a connection
+	 * and changing it's UUID. In fact, disallowing it makes it cumbersome for the user
+	 * to reapply any connection but the original settings-connection. */
 	if (!_hash_check_invalid_keys (diffs ? g_hash_table_lookup (diffs, NM_SETTING_CONNECTION_SETTING_NAME) : NULL,
 	                               NM_SETTING_CONNECTION_SETTING_NAME,
 	                               error,
+	                               NM_SETTING_CONNECTION_ID,
+	                               NM_SETTING_CONNECTION_UUID,
 	                               NM_SETTING_CONNECTION_ZONE,
 	                               NM_SETTING_CONNECTION_METERED))
 		return FALSE;
@@ -7336,6 +7340,7 @@ reapply_connection (NMDevice *self,
 		con_old = applied_clone  = nm_simple_connection_new_clone (applied);
 		con_new = applied;
 		nm_connection_replace_settings_from_connection (applied, connection);
+		nm_connection_clear_secrets (applied);
 	} else
 		con_old = con_new = applied;
 
@@ -8779,6 +8784,19 @@ update_ip4_config (NMDevice *self, gboolean initial)
 	gboolean capture_resolv_conf;
 	NMDnsManagerResolvConfMode resolv_conf_mode;
 
+	/* If a commit is scheduled, this function would potentially interfere with
+	 * it changing IP configurations before they are applied. Postpone the
+	 * update in such case.
+	 */
+	if (   !initial
+	    && activation_source_is_scheduled (self,
+	                                       activate_stage5_ip4_config_commit,
+	                                       AF_INET)) {
+		priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
+		_LOGT (LOGD_DEVICE, "IP4 update was postponed");
+		return;
+	}
+
 	ifindex = nm_device_get_ip_ifindex (self);
 	if (!ifindex)
 		return;
@@ -8857,6 +8875,19 @@ update_ip6_config (NMDevice *self, gboolean initial)
 	gboolean capture_resolv_conf;
 	NMDnsManagerResolvConfMode resolv_conf_mode;
 
+	/* If a commit is scheduled, this function would potentially interfere with
+	 * it changing IP configurations before they are applied. Postpone the
+	 * update in such case.
+	 */
+	if (   !initial
+	    && activation_source_is_scheduled (self,
+	                                       activate_stage5_ip6_config_commit,
+	                                       AF_INET6)) {
+		priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
+		_LOGT (LOGD_DEVICE, "IP6 update was postponed");
+		return;
+	}
+
 	ifindex = nm_device_get_ip_ifindex (self);
 	if (!ifindex)
 		return;
@@ -8922,8 +8953,12 @@ nm_device_capture_initial_config (NMDevice *self)
 static gboolean
 queued_ip4_config_change (gpointer user_data)
 {
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+	NMDevice *self = user_data;
+	NMDevicePrivate *priv;
+
+	g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE);
+
+	priv = NM_DEVICE_GET_PRIVATE (self);
 
 	/* Wait for any queued state changes */
 	if (priv->queued_state.id)
@@ -8942,11 +8977,15 @@ queued_ip4_config_change (gpointer user_data)
 static gboolean
 queued_ip6_config_change (gpointer user_data)
 {
-	NMDevice *self = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+	NMDevice *self = user_data;
+	NMDevicePrivate *priv;
 	GSList *iter;
 	gboolean need_ipv6ll = FALSE;
 
+	g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE);
+
+	priv = NM_DEVICE_GET_PRIVATE (self);
+
 	/* Wait for any queued state changes */
 	if (priv->queued_state.id)
 		return TRUE;
@@ -11201,6 +11240,10 @@ dispose (GObject *object)
 
 	_LOGD (LOGD_DEVICE, "disposing");
 
+	platform = nm_platform_get ();
+	g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
+	g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
+
 	g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy);
 	priv->arping.dad_list = NULL;
 
@@ -11241,10 +11284,6 @@ dispose (GObject *object)
 
 	_clear_queued_act_request (priv);
 
-	platform = nm_platform_get ();
-	g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
-	g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
-
 	nm_clear_g_source (&priv->device_link_changed_id);
 	nm_clear_g_source (&priv->device_ip_link_changed_id);