about summary refs log tree commit diff
path: root/src/nm-policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-policy.c')
-rw-r--r--src/nm-policy.c95
1 files changed, 75 insertions, 20 deletions
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 7f8c665c..77fc929c 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -30,6 +30,7 @@
 
 #include "NetworkManagerUtils.h"
 #include "nm-act-request.h"
+#include "nm-keep-alive.h"
 #include "devices/nm-device.h"
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-connection.h"
@@ -178,9 +179,10 @@ static void
 clear_ip6_prefix_delegation (gpointer data)
 {
 	IP6PrefixDelegation *delegation = data;
+	char sbuf[NM_UTILS_INET_ADDRSTRLEN];
 
 	_LOGD (LOGD_IP6, "ipv6-pd: undelegating prefix %s/%d",
-	       nm_utils_inet6_ntop (&delegation->prefix.address, NULL),
+	       nm_utils_inet6_ntop (&delegation->prefix.address, sbuf),
 	       delegation->prefix.plen);
 
 	g_hash_table_foreach (delegation->subnets, _clear_ip6_subnet, NULL);
@@ -214,13 +216,14 @@ ip6_subnet_from_delegation (IP6PrefixDelegation *delegation, NMDevice *device)
 {
 	NMPlatformIP6Address *subnet;
 	int ifindex = nm_device_get_ifindex (device);
+	char sbuf[NM_UTILS_INET_ADDRSTRLEN];
 
 	subnet = g_hash_table_lookup (delegation->subnets, GINT_TO_POINTER (ifindex));
 	if (!subnet) {
 		/* Check for out-of-prefixes condition. */
 		if (delegation->next_subnet >= (1 << (64 - delegation->prefix.plen))) {
 			_LOGD (LOGD_IP6, "ipv6-pd: no more prefixes in %s/%d",
-			       nm_utils_inet6_ntop (&delegation->prefix.address, NULL),
+			       nm_utils_inet6_ntop (&delegation->prefix.address, sbuf),
 			       delegation->prefix.plen);
 			return FALSE;
 		}
@@ -248,7 +251,7 @@ ip6_subnet_from_delegation (IP6PrefixDelegation *delegation, NMDevice *device)
 	subnet->preferred = delegation->prefix.preferred;
 
 	_LOGD (LOGD_IP6, "ipv6-pd: %s allocated from a /%d prefix on %s",
-	       nm_utils_inet6_ntop (&subnet->address, NULL),
+	       nm_utils_inet6_ntop (&subnet->address, sbuf),
 	       delegation->prefix.plen,
 	       nm_device_get_iface (device));
 
@@ -319,9 +322,10 @@ device_ip6_prefix_delegated (NMDevice *device,
 	guint i;
 	const CList *tmp_list;
 	NMActiveConnection *ac;
+	char sbuf[NM_UTILS_INET_ADDRSTRLEN];
 
 	_LOGI (LOGD_IP6, "ipv6-pd: received a prefix %s/%d from %s",
-	       nm_utils_inet6_ntop (&prefix->address, NULL),
+	       nm_utils_inet6_ntop (&prefix->address, sbuf),
 	       prefix->plen,
 	       nm_device_get_iface (device));
 
@@ -1283,6 +1287,7 @@ auto_activate_device (NMPolicy *self,
 	                                     subject,
 	                                     NM_ACTIVATION_TYPE_MANAGED,
 	                                     NM_ACTIVATION_REASON_AUTOCONNECT,
+	                                     NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY,
 	                                     &error);
 	if (!ac) {
 		_LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: %s",
@@ -1673,9 +1678,14 @@ activate_secondary_connections (NMPolicy *self,
 	GError *error = NULL;
 	guint32 i;
 	gboolean success = TRUE;
+	NMActivationStateFlags initial_state_flags;
 
 	s_con = nm_connection_get_setting_connection (connection);
-	nm_assert (s_con);
+	nm_assert (NM_IS_SETTING_CONNECTION (s_con));
+
+	/* we propagate the activation's state flags. */
+	initial_state_flags =   nm_device_get_activation_state_flags (device)
+	                      & NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY;
 
 	for (i = 0; i < nm_setting_connection_get_num_secondaries (s_con); i++) {
 		NMSettingsConnection *sett_conn;
@@ -1699,7 +1709,6 @@ activate_secondary_connections (NMPolicy *self,
 		}
 
 		req = nm_device_get_act_request (device);
-		g_assert (req);
 
 		_LOGD (LOGD_DEVICE, "activating secondary connection '%s (%s)' for base connection '%s (%s)'",
 		       nm_settings_connection_get_id (sett_conn), sec_uuid,
@@ -1712,6 +1721,7 @@ activate_secondary_connections (NMPolicy *self,
 		                                     nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (req)),
 		                                     NM_ACTIVATION_TYPE_MANAGED,
 		                                     nm_active_connection_get_activation_reason (NM_ACTIVE_CONNECTION (req)),
+		                                     initial_state_flags,
 		                                     &error);
 		if (ac)
 			secondary_ac_list = g_slist_append (secondary_ac_list, g_object_ref (ac));
@@ -1751,17 +1761,14 @@ device_state_changed (NMDevice *device,
 	NMSettingConnection *s_con = NULL;
 
 	switch (nm_device_state_reason_check (reason)) {
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED:
-	case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING:
-	case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED:
 	case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
 	case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED:
-	case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG:
 	case NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT:
-	case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED:
 	case NM_DEVICE_STATE_REASON_GSM_APN_FAILED:
-		/* Block autoconnect of the just-failed connection for situations
-		 * where a retry attempt would just fail again.
+		/* Block autoconnection at settings level if there is any settings-specific
+		 * error reported by the modem (e.g. wrong SIM-PIN or wrong APN). Do not block
+		 * autoconnection at settings level for errors in the device domain (e.g.
+		 * a missing SIM or wrong modem initialization).
 		 */
 		if (sett_conn) {
 			nm_settings_connection_autoconnect_blocked_reason_set (sett_conn,
@@ -1875,8 +1882,8 @@ device_state_changed (NMDevice *device,
 			if (blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE) {
 				_LOGD (LOGD_DEVICE, "blocking autoconnect of connection '%s': %s",
 				       nm_settings_connection_get_id (sett_conn),
-				       NM_UTILS_LOOKUP_STR (nm_device_state_reason_to_str,
-				                            nm_device_state_reason_check (reason)));
+				       NM_UTILS_LOOKUP_STR_A (nm_device_state_reason_to_str,
+				                              nm_device_state_reason_check (reason)));
 				nm_settings_connection_autoconnect_blocked_reason_set (sett_conn, blocked_reason, TRUE);
 			}
 		}
@@ -1969,7 +1976,7 @@ device_ip_config_changed (NMDevice *device,
 	/* We catch already all the IP events registering on the device state changes but
 	 * the ones where the IP changes but the device state keep stable (i.e., activated):
 	 * ignore IP config changes but when the device is in activated state.
-	 * Prevents unecessary changes to DNS information.
+	 * Prevents unnecessary changes to DNS information.
 	 */
 	if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
 		if (old_config != new_config) {
@@ -2161,6 +2168,8 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *self)
 	                                     nm_active_connection_get_subject (ac),
 	                                     NM_ACTIVATION_TYPE_MANAGED,
 	                                     nm_active_connection_get_activation_reason (ac),
+	                                     (  nm_active_connection_get_state_flags (ac)
+	                                      & NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY),
 	                                     &error)) {
 		_LOGW (LOGD_DEVICE, "VPN '%s' reconnect failed: %s",
 		       nm_settings_connection_get_id (connection),
@@ -2183,12 +2192,47 @@ active_connection_state_changed (NMActiveConnection *active,
 }
 
 static void
+active_connection_keep_alive_changed (NMKeepAlive *keep_alive,
+                                      GParamSpec *pspec,
+                                      NMPolicy *self)
+{
+	NMPolicyPrivate *priv;
+	NMActiveConnection *ac;
+	GError *error = NULL;
+
+	nm_assert (NM_IS_POLICY (self));
+	nm_assert (NM_IS_KEEP_ALIVE (keep_alive));
+	nm_assert (NM_IS_ACTIVE_CONNECTION (nm_keep_alive_get_owner (keep_alive)));
+
+	if (nm_keep_alive_is_alive (keep_alive))
+		return;
+
+	ac = nm_keep_alive_get_owner (keep_alive);
+
+	if (nm_active_connection_get_state (ac) > NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
+		return;
+
+	priv = NM_POLICY_GET_PRIVATE (self);
+
+	if (!nm_manager_deactivate_connection (priv->manager,
+	                                       ac,
+	                                       NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,
+	                                       &error)) {
+		_LOGW (LOGD_DEVICE, "connection '%s' is no longer kept alive, but error deactivating it: %s",
+		       nm_active_connection_get_settings_connection_id (ac),
+		       error->message);
+		g_clear_error (&error);
+	}
+}
+
+static void
 active_connection_added (NMManager *manager,
                          NMActiveConnection *active,
                          gpointer user_data)
 {
 	NMPolicyPrivate *priv = user_data;
 	NMPolicy *self = _PRIV_TO_SELF (priv);
+	NMKeepAlive *keep_alive;
 
 	if (NM_IS_VPN_CONNECTION (active)) {
 		g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
@@ -2199,9 +2243,18 @@ active_connection_added (NMManager *manager,
 		                  self);
 	}
 
+	keep_alive = nm_active_connection_get_keep_alive (active);
+
+	nm_keep_alive_arm (keep_alive);
+
 	g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE,
 	                  G_CALLBACK (active_connection_state_changed),
 	                  self);
+	g_signal_connect (keep_alive,
+	                  "notify::" NM_KEEP_ALIVE_ALIVE,
+	                  G_CALLBACK (active_connection_keep_alive_changed),
+	                  self);
+	active_connection_keep_alive_changed (keep_alive, NULL, self);
 }
 
 static void
@@ -2221,6 +2274,9 @@ active_connection_removed (NMManager *manager,
 	g_signal_handlers_disconnect_by_func (active,
 	                                      active_connection_state_changed,
 	                                      self);
+	g_signal_handlers_disconnect_by_func (nm_active_connection_get_keep_alive (active),
+	                                      active_connection_keep_alive_changed,
+	                                      self);
 }
 
 /*****************************************************************************/
@@ -2358,12 +2414,12 @@ _deactivate_if_active (NMPolicy *self, NMSettingsConnection *connection)
 {
 	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
 	NMActiveConnection *ac;
-	const CList *tmp_list;
+	const CList *tmp_list, *tmp_safe;
 	GError *error = NULL;
 
 	nm_assert (NM_IS_SETTINGS_CONNECTION (connection));
 
-	nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
+	nm_manager_for_each_active_connection_safe (priv->manager, ac, tmp_list, tmp_safe) {
 
 		if (   nm_active_connection_get_settings_connection (ac) == connection
 		    && (nm_active_connection_get_state (ac) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
@@ -2404,8 +2460,7 @@ connection_flags_changed (NMSettings *settings,
 	                  NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE)) {
 		if (!nm_settings_connection_autoconnect_is_blocked (connection))
 			schedule_activate_all (self);
-	} else
-		_deactivate_if_active (self, connection);
+	}
 }
 
 static void