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.c338
1 files changed, 166 insertions, 172 deletions
diff --git a/src/nm-policy.c b/src/nm-policy.c
index fcada545..aed2f897 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -36,9 +36,6 @@
 #include "nm-device-wifi.h"
 #include "nm-device-ethernet.h"
 #include "nm-device-modem.h"
-#if WITH_WIMAX
-#include "nm-device-wimax.h"
-#endif
 #include "nm-dbus-manager.h"
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-connection.h"
@@ -51,16 +48,13 @@ struct NMPolicy {
 	NMManager *manager;
 	guint update_state_id;
 	GSList *pending_activation_checks;
-	GSList *manager_ids;
-	GSList *settings_ids;
-	GSList *dev_ids;
+	GSList *signal_ids;
+	GSList *dev_signal_ids;
 
 	NMVPNManager *vpn_manager;
 	gulong vpn_activated_id;
 	gulong vpn_deactivated_id;
 
-	NMSettings *settings;
-
 	NMDevice *default_device4;
 	NMDevice *default_device6;
 
@@ -70,8 +64,20 @@ struct NMPolicy {
 	char *cur_hostname;  /* hostname we want to assign */
 };
 
-#define RETRIES_TAG "autoconnect-retries"
-#define RETRIES_DEFAULT	4
+#define INVALID_TAG "invalid"
+
+static const char *
+get_connection_id (NMConnection *connection)
+{
+	NMSettingConnection *s_con;
+
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	g_return_val_if_fail (s_con != NULL, NULL);
+
+	return nm_setting_connection_get_id (s_con);
+}
 
 static NMDevice *
 get_best_ip4_device (NMManager *manager, NMActRequest **out_req)
@@ -281,7 +287,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6)
 
 	/* Hostname precedence order:
 	 *
-	 * 1) a configured hostname (from settings)
+	 * 1) a configured hostname (from system-settings)
 	 * 2) automatic hostname from the default device's config (DHCP, VPN, etc)
 	 * 3) the original hostname when NM started
 	 * 4) reverse-DNS of the best device's IPv4 address
@@ -470,6 +476,7 @@ update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update)
 
 			dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
 		}
+		g_object_unref (candidate);
 	}
 	g_slist_free (vpns);
 
@@ -594,6 +601,7 @@ update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update)
 
 			dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
 		}
+		g_object_unref (candidate);
 	}
 	g_slist_free (vpns);
 #endif
@@ -666,20 +674,6 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update)
 	update_system_hostname (policy, policy->default_device4, policy->default_device6);
 }
 
-static void
-set_connection_auto_retries (NMConnection *connection, guint retries)
-{
-	/* add +1 so that the tag still exists if the # retries is 0 */
-	g_object_set_data (G_OBJECT (connection), RETRIES_TAG, GUINT_TO_POINTER (retries + 1));
-}
-
-static guint32
-get_connection_auto_retries (NMConnection *connection)
-{
-	/* subtract 1 to handle the +1 from set_connection_auto_retries() */
-	return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), RETRIES_TAG)) - 1;
-}
-
 typedef struct {
 	NMPolicy *policy;
 	NMDevice *device;
@@ -705,21 +699,23 @@ auto_activate_device (gpointer user_data)
 	if (nm_device_get_act_request (data->device))
 		goto out;
 
-	iter = connections = nm_settings_get_connections (policy->settings);
+	/* System connections first, then user connections */
+	connections = nm_manager_get_connections (policy->manager, NM_CONNECTION_SCOPE_SYSTEM);
+	if (nm_manager_auto_user_connections_allowed (policy->manager))
+		connections = g_slist_concat (connections, nm_manager_get_connections (policy->manager, NM_CONNECTION_SCOPE_USER));
 
-	/* Remove connections that shouldn't be auto-activated */
+	/* Remove connections that are in the invalid list. */
+	iter = connections;
 	while (iter) {
-		NMConnection *candidate = NM_CONNECTION (iter->data);
-
-		/* Grab next item before we possibly delete the current item */
-		iter = g_slist_next (iter);
+		NMConnection *iter_connection = NM_CONNECTION (iter->data);
+		GSList *next = g_slist_next (iter);
 
-		/* Ignore connections that were tried too many times or are not visible
-		 * to any logged-in users.
-		 */
-		if (   get_connection_auto_retries (candidate) == 0
-		    || nm_settings_connection_is_visible (NM_SETTINGS_CONNECTION (candidate)) == FALSE)
-			connections = g_slist_remove (connections, candidate);
+		if (g_object_get_data (G_OBJECT (iter_connection), INVALID_TAG)) {
+			connections = g_slist_remove_link (connections, iter);
+			g_object_unref (iter_connection);
+			g_slist_free (iter);
+		}
+		iter = next;
 	}
 
 	best_connection = nm_device_get_best_auto_connection (data->device, connections, &specific_object);
@@ -730,14 +726,20 @@ auto_activate_device (gpointer user_data)
 		                                     best_connection,
 		                                     specific_object,
 		                                     nm_device_get_path (data->device),
-		                                     NULL,
+		                                     FALSE,
 		                                     &error)) {
+			NMSettingConnection *s_con;
+
+			s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (best_connection, NM_TYPE_SETTING_CONNECTION));
+			g_assert (s_con);
+
 			nm_log_info (LOGD_DEVICE, "Connection '%s' auto-activation failed: (%d) %s",
-			             nm_connection_get_id (best_connection), error->code, error->message);
+			             nm_setting_connection_get_id (s_con), error->code, error->message);
 			g_error_free (error);
 		}
 	}
 
+	g_slist_foreach (connections, (GFunc) g_object_unref, NULL);
 	g_slist_free (connections);
 
  out:
@@ -783,18 +785,18 @@ hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
 static void
 sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
 {
-	NMPolicy *policy = user_data;
 	gboolean sleeping = FALSE, enabled = FALSE;
 	GSList *connections, *iter;
 
 	g_object_get (G_OBJECT (manager), NM_MANAGER_SLEEPING, &sleeping, NULL);
 	g_object_get (G_OBJECT (manager), NM_MANAGER_NETWORKING_ENABLED, &enabled, NULL);
 
-	/* Reset retries on all connections so they'll checked on wakeup */
+	/* Clear the invalid flag on all connections so they'll get retried on wakeup */
 	if (sleeping || !enabled) {
-		connections = nm_settings_get_connections (policy->settings);
+		connections = nm_manager_get_connections (manager, NM_CONNECTION_SCOPE_SYSTEM);
+		connections = g_slist_concat (connections, nm_manager_get_connections (manager, NM_CONNECTION_SCOPE_USER));
 		for (iter = connections; iter; iter = g_slist_next (iter))
-			set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT);
+			g_object_set_data (G_OBJECT (iter->data), INVALID_TAG, NULL);
 		g_slist_free (connections);
 	}
 }
@@ -859,32 +861,16 @@ device_state_changed (NMDevice *device,
 		 * it doesn't get automatically chosen over and over and over again.
 		 */
 		if (connection && IS_ACTIVATING_STATE (old_state)) {
-			guint32 tries = get_connection_auto_retries (connection);
-
-			if (reason == NM_DEVICE_STATE_REASON_NO_SECRETS) {
-				/* If the connection couldn't get the secrets it needed (ex because
-				 * the user canceled, or no secrets exist), there's no point in
-				 * automatically retrying because it's just going to fail anyway.
-				 */
-				set_connection_auto_retries (connection, 0);
-			} else if (tries > 0) {
-				/* Otherwise if it's a random failure, just decrease the number
-				 * of automatic retries so that the connection gets tried again
-				 * if it still has a retry count.
-				 */
-				set_connection_auto_retries (connection, tries - 1);
-			}
-
-			if (get_connection_auto_retries (connection) == 0)
-				nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", nm_connection_get_id (connection));
+			g_object_set_data (G_OBJECT (connection), INVALID_TAG, GUINT_TO_POINTER (TRUE));
+			nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", get_connection_id (connection));
 			nm_connection_clear_secrets (connection);
 		}
 		schedule_activate_check (policy, device, 3);
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
 		if (connection) {
-			/* Reset auto retries back to default since connection was successful */
-			set_connection_auto_retries (connection, RETRIES_DEFAULT);
+			/* Clear the invalid tag on the connection */
+			g_object_set_data (G_OBJECT (connection), INVALID_TAG, NULL);
 
 			/* And clear secrets so they will always be requested from the
 			 * settings service when the next connection is made.
@@ -919,48 +905,56 @@ wireless_networks_changed (NMDeviceWifi *device, NMAccessPoint *ap, gpointer use
 	schedule_activate_check ((NMPolicy *) user_data, NM_DEVICE (device), 0);
 }
 
-#if WITH_WIMAX
-static void
-nsps_changed (NMDeviceWimax *device, NMWimaxNsp *nsp, gpointer user_data)
-{
-	schedule_activate_check ((NMPolicy *) user_data, NM_DEVICE (device), 0);
-}
-#endif
-
 typedef struct {
 	gulong id;
 	NMDevice *device;
-} DeviceSignalId;
+} DeviceSignalID;
 
-static void
-_connect_device_signal (NMPolicy *policy, NMDevice *device, const char *name, gpointer callback)
+static GSList *
+add_device_signal_id (GSList *list, gulong id, NMDevice *device)
 {
-	DeviceSignalId *data;
+	DeviceSignalID *data;
 
-	data = g_slice_new0 (DeviceSignalId);
-	g_assert (data);
-	data->id = g_signal_connect (device, name, callback, policy);
+	data = g_malloc0 (sizeof (DeviceSignalID));
+	if (!data)
+		return list;
+
+	data->id = id;
 	data->device = device;
-	policy->dev_ids = g_slist_prepend (policy->dev_ids, data);
+	return g_slist_append (list, data);
 }
 
 static void
 device_added (NMManager *manager, NMDevice *device, gpointer user_data)
 {
 	NMPolicy *policy = (NMPolicy *) user_data;
+	gulong id;
+
+	id = g_signal_connect (device, "state-changed",
+	                       G_CALLBACK (device_state_changed),
+	                       policy);
+	policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
 
-	_connect_device_signal (policy, device, "state-changed", device_state_changed);
-	_connect_device_signal (policy, device, "notify::" NM_DEVICE_INTERFACE_IP4_CONFIG, device_ip_config_changed);
-	_connect_device_signal (policy, device, "notify::" NM_DEVICE_INTERFACE_IP6_CONFIG, device_ip_config_changed);
+	id = g_signal_connect (device, "notify::" NM_DEVICE_INTERFACE_IP4_CONFIG,
+	                       G_CALLBACK (device_ip_config_changed),
+	                       policy);
+	policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
+
+	id = g_signal_connect (device, "notify::" NM_DEVICE_INTERFACE_IP6_CONFIG,
+	                       G_CALLBACK (device_ip_config_changed),
+	                       policy);
+	policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
 
 	if (NM_IS_DEVICE_WIFI (device)) {
-		_connect_device_signal (policy, device, "access-point-added", wireless_networks_changed);
-		_connect_device_signal (policy, device, "access-point-removed", wireless_networks_changed);
-#if WITH_WIMAX
-	} else if (NM_IS_DEVICE_WIMAX (device)) {
-		_connect_device_signal (policy, device, "nsp-added", nsps_changed);
-		_connect_device_signal (policy, device, "nsp-removed", nsps_changed);
-#endif
+		id = g_signal_connect (device, "access-point-added",
+		                       G_CALLBACK (wireless_networks_changed),
+		                       policy);
+		policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
+
+		id = g_signal_connect (device, "access-point-removed",
+		                       G_CALLBACK (wireless_networks_changed),
+		                       policy);
+		policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
 	}
 }
 
@@ -986,15 +980,15 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data)
 	}
 
 	/* Clear any signal handlers for this device */
-	iter = policy->dev_ids;
+	iter = policy->dev_signal_ids;
 	while (iter) {
-		DeviceSignalId *data = iter->data;
+		DeviceSignalID *data = (DeviceSignalID *) iter->data;
 		GSList *next = g_slist_next (iter);
 
 		if (data->device == device) {
 			g_signal_handler_disconnect (data->device, data->id);
-			g_slice_free (DeviceSignalId, data);
-			policy->dev_ids = g_slist_delete_link (policy->dev_ids, iter);
+			g_free (data);
+			policy->dev_signal_ids = g_slist_delete_link (policy->dev_signal_ids, iter);
 		}
 		iter = next;
 	}
@@ -1013,38 +1007,48 @@ schedule_activate_all (NMPolicy *policy)
 }
 
 static void
-connection_added (NMSettings *settings,
-                  NMConnection *connection,
-                  gpointer user_data)
+connections_added (NMManager *manager,
+                   NMConnectionScope scope,
+                   gpointer user_data)
 {
-	set_connection_auto_retries (connection, RETRIES_DEFAULT);
 	schedule_activate_all ((NMPolicy *) user_data);
 }
 
 static void
-connections_loaded (NMSettings *settings,
-					gpointer user_data)
+connection_added (NMManager *manager,
+                  NMConnection *connection,
+                  NMConnectionScope scope,
+                  gpointer user_data)
 {
 	schedule_activate_all ((NMPolicy *) user_data);
 }
 
 static void
-connection_updated (NMSettings *settings,
+connection_updated (NMManager *manager,
                     NMConnection *connection,
+                    NMConnectionScope scope,
                     gpointer user_data)
 {
-	/* Reset auto retries back to default since connection was updated */
-	set_connection_auto_retries (connection, RETRIES_DEFAULT);
+	/* Clear the invalid tag on the connection if it got updated. */
+	g_object_set_data (G_OBJECT (connection), INVALID_TAG, NULL);
 
 	schedule_activate_all ((NMPolicy *) user_data);
 }
 
 static void
-_deactivate_if_active (NMManager *manager, NMConnection *connection)
+connection_removed (NMManager *manager,
+                    NMConnection *connection,
+                    NMConnectionScope scope,
+                    gpointer user_data)
 {
+	NMSettingConnection *s_con;
 	GPtrArray *list;
 	int i;
 
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	if (!s_con)
+		return;
+
 	list = nm_manager_get_active_connections_by_connection (manager, connection);
 	if (!list)
 		return;
@@ -1055,7 +1059,7 @@ _deactivate_if_active (NMManager *manager, NMConnection *connection)
 
 		if (!nm_manager_deactivate_connection (manager, path, NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, &error)) {
 			nm_log_warn (LOGD_DEVICE, "Connection '%s' disappeared, but error deactivating it: (%d) %s",
-			             nm_connection_get_id (connection), error->code, error->message);
+			             nm_setting_connection_get_id (s_con), error->code, error->message);
 			g_error_free (error);
 		}
 		g_free (path);
@@ -1064,50 +1068,13 @@ _deactivate_if_active (NMManager *manager, NMConnection *connection)
 }
 
 static void
-connection_removed (NMSettings *settings,
-                    NMConnection *connection,
-                    gpointer user_data)
-{
-	NMPolicy *policy = user_data;
-
-	_deactivate_if_active (policy->manager, connection);
-}
-
-static void
-connection_visibility_changed (NMSettings *settings,
-                               NMSettingsConnection *connection,
-                               gpointer user_data)
-{
-	NMPolicy *policy = user_data;
-
-	if (nm_settings_connection_is_visible (connection))
-		schedule_activate_all (policy);
-	else
-		_deactivate_if_active (policy->manager, NM_CONNECTION (connection));
-}
-
-static void
-_connect_manager_signal (NMPolicy *policy, const char *name, gpointer callback)
-{
-	guint id;
-
-	id = g_signal_connect (policy->manager, name, callback, policy);
-	policy->manager_ids = g_slist_prepend (policy->manager_ids, GUINT_TO_POINTER (id));
-}
-
-static void
-_connect_settings_signal (NMPolicy *policy, const char *name, gpointer callback)
+manager_user_permissions_changed (NMManager *manager, NMPolicy *policy)
 {
-	guint id;
-
-	id = g_signal_connect (policy->settings, name, callback, policy);
-	policy->settings_ids = g_slist_prepend (policy->settings_ids, GUINT_TO_POINTER (id));
+	schedule_activate_all (policy);
 }
 
 NMPolicy *
-nm_policy_new (NMManager *manager,
-               NMVPNManager *vpn_manager,
-               NMSettings *settings)
+nm_policy_new (NMManager *manager, NMVPNManager *vpn_manager)
 {
 	NMPolicy *policy;
 	static gboolean initialized = FALSE;
@@ -1119,7 +1086,6 @@ nm_policy_new (NMManager *manager,
 
 	policy = g_malloc0 (sizeof (NMPolicy));
 	policy->manager = g_object_ref (manager);
-	policy->settings = g_object_ref (settings);
 	policy->update_state_id = 0;
 
 	/* Grab hostname on startup and use that if nothing provides one */
@@ -1138,21 +1104,54 @@ nm_policy_new (NMManager *manager,
 	                       G_CALLBACK (vpn_connection_deactivated), policy);
 	policy->vpn_deactivated_id = id;
 
-	_connect_manager_signal (policy, "state-changed", global_state_changed);
-	_connect_manager_signal (policy, "notify::" NM_MANAGER_HOSTNAME, hostname_changed);
-	_connect_manager_signal (policy, "notify::" NM_MANAGER_SLEEPING, sleeping_changed);
-	_connect_manager_signal (policy, "notify::" NM_MANAGER_NETWORKING_ENABLED, sleeping_changed);
-	_connect_manager_signal (policy, "device-added", device_added);
-	_connect_manager_signal (policy, "device-removed", device_removed);
-
-	_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTIONS_LOADED, connections_loaded);
-	_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, connection_added);
-	_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, connection_updated);
-	_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed);
-	_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED,
-	                          connection_visibility_changed);
-
-	initialized = TRUE;
+	id = g_signal_connect (manager, "state-changed",
+	                       G_CALLBACK (global_state_changed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "notify::" NM_MANAGER_HOSTNAME,
+	                       G_CALLBACK (hostname_changed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "notify::" NM_MANAGER_SLEEPING,
+	                       G_CALLBACK (sleeping_changed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "notify::" NM_MANAGER_NETWORKING_ENABLED,
+	                       G_CALLBACK (sleeping_changed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "device-added",
+	                       G_CALLBACK (device_added), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "device-removed",
+	                       G_CALLBACK (device_removed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	/* Large batch of connections added, manager doesn't want us to
+	 * process each one individually.
+	 */
+	id = g_signal_connect (manager, "connections-added",
+	                       G_CALLBACK (connections_added), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	/* Single connection added */
+	id = g_signal_connect (manager, "connection-added",
+	                       G_CALLBACK (connection_added), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "connection-updated",
+	                       G_CALLBACK (connection_updated), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "connection-removed",
+	                       G_CALLBACK (connection_removed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
+	id = g_signal_connect (manager, "user-permissions-changed",
+	                       G_CALLBACK (manager_user_permissions_changed), policy);
+	policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
+
 	return policy;
 }
 
@@ -1184,26 +1183,21 @@ nm_policy_destroy (NMPolicy *policy)
 	g_signal_handler_disconnect (policy->vpn_manager, policy->vpn_deactivated_id);
 	g_object_unref (policy->vpn_manager);
 
-	for (iter = policy->manager_ids; iter; iter = g_slist_next (iter))
-		g_signal_handler_disconnect (policy->manager, GPOINTER_TO_UINT (iter->data));
-	g_slist_free (policy->manager_ids);
+	for (iter = policy->signal_ids; iter; iter = g_slist_next (iter))
+		g_signal_handler_disconnect (policy->manager, (gulong) iter->data);
+	g_slist_free (policy->signal_ids);
 
-	for (iter = policy->settings_ids; iter; iter = g_slist_next (iter))
-		g_signal_handler_disconnect (policy->settings, GPOINTER_TO_UINT (iter->data));
-	g_slist_free (policy->settings_ids);
-
-	for (iter = policy->dev_ids; iter; iter = g_slist_next (iter)) {
-		DeviceSignalId *data = iter->data;
+	for (iter = policy->dev_signal_ids; iter; iter = g_slist_next (iter)) {
+		DeviceSignalID *data = (DeviceSignalID *) iter->data;
 
 		g_signal_handler_disconnect (data->device, data->id);
-		g_slice_free (DeviceSignalId, data);
+		g_free (data);
 	}
-	g_slist_free (policy->dev_ids);
+	g_slist_free (policy->dev_signal_ids);
 
 	g_free (policy->orig_hostname);
 	g_free (policy->cur_hostname);
 
-	g_object_unref (policy->settings);
 	g_object_unref (policy->manager);
 	g_free (policy);
 }