summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2013-09-12 10:28:21 -0400
committerDan Winship <danw@gnome.org>2013-11-06 10:21:27 -0500
commita1f16cd4d9fff66d7feeee0846e554c9c3a5f998 (patch)
treed55f935d64fdf4c2150859796185d8158aba57ca
parent154264d99c75ee8db920b3ba5ea609b57c2298d4 (diff)
downloadNetworkManager-a1f16cd4d9fff66d7feeee0846e554c9c3a5f998.tar.gz
core: don't allow activating the same connection twice (rh #997998)
Change the rules for connection activation so that a given NMConnection can only be used by a single NMActiveConnection at any given time.
-rw-r--r--src/nm-manager.c67
-rw-r--r--src/nm-manager.h2
-rw-r--r--src/nm-policy.c2
3 files changed, 66 insertions, 5 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 9aa40e68a4..54e04df1e6 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -400,6 +400,46 @@ nm_manager_get_active_connections (NMManager *manager)
}
static NMActiveConnection *
+find_ac_for_connection (NMManager *manager, NMConnection *connection)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
+ GSList *iter;
+ NMActiveConnection *ac;
+ NMConnection *ac_connection;
+ const char *uuid;
+
+ uuid = nm_connection_get_uuid (connection);
+ for (iter = priv->active_connections; iter; iter = iter->next) {
+ ac = iter->data;
+ ac_connection = nm_active_connection_get_connection (ac);
+
+ if (!strcmp (nm_connection_get_uuid (ac_connection), uuid))
+ return ac;
+ }
+
+ return NULL;
+}
+
+GSList *
+nm_manager_get_activatable_connections (NMManager *manager)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
+ GSList *all_connections = nm_settings_get_connections (priv->settings);
+ GSList *connections = NULL, *iter;
+ NMConnection *connection;
+
+ for (iter = all_connections; iter; iter = iter->next) {
+ connection = iter->data;
+
+ if (!find_ac_for_connection (manager, connection))
+ connections = g_slist_prepend (connections, connection);
+ }
+
+ g_slist_free (all_connections);
+ return connections;
+}
+
+static NMActiveConnection *
active_connection_get_by_path (NMManager *manager, const char *path)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
@@ -1735,8 +1775,7 @@ local_slist_free (void *loc)
static NMConnection *
get_connection (NMManager *manager, NMDevice *device)
{
- NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
- free_slist GSList *connections = nm_settings_get_connections (priv->settings);
+ free_slist GSList *connections = nm_manager_get_activatable_connections (manager);
NMConnection *connection = NULL;
GSList *iter;
@@ -2471,7 +2510,7 @@ find_master (NMManager *self,
* virtual interfaces and see if one of their virtual interface
* names matches the master.
*/
- connections = nm_settings_get_connections (priv->settings);
+ connections = nm_manager_get_activatable_connections (self);
for (iter = connections; iter && !master_connection; iter = g_slist_next (iter)) {
NMConnection *candidate = iter->data;
char *vname;
@@ -2569,7 +2608,7 @@ ensure_master_active_connection (NMManager *self,
g_assert (master_connection == NULL);
/* Find a compatible connection and activate this device using it */
- connections = nm_settings_get_connections (priv->settings);
+ connections = nm_manager_get_activatable_connections (self);
for (iter = connections; iter; iter = g_slist_next (iter)) {
NMConnection *candidate = NM_CONNECTION (iter->data);
@@ -2906,9 +2945,29 @@ _new_active_connection (NMManager *self,
NMAuthSubject *subject,
GError **error)
{
+ NMActiveConnection *existing_ac;
+
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
+ /* Can't create new AC for already-active connection */
+ existing_ac = find_ac_for_connection (self, connection);
+ if (existing_ac) {
+ NMDevice *existing_device = nm_active_connection_get_device (existing_ac);
+
+ if (NM_IS_VPN_CONNECTION (existing_ac) || existing_device == device) {
+ g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE,
+ "Connection '%s' is already active",
+ nm_connection_get_id (connection));
+ } else {
+ g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE,
+ "Connection '%s' is already active on %s",
+ nm_connection_get_id (connection),
+ nm_device_get_iface (existing_device));
+ }
+ return NULL;
+ }
+
/* Normalize the specific object */
if (specific_object && g_strcmp0 (specific_object, "/") == 0)
specific_object = NULL;
diff --git a/src/nm-manager.h b/src/nm-manager.h
index 5f848688d9..4d84db5d26 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -48,6 +48,7 @@ typedef enum {
NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE, /*< nick=UnsupportedConnectionType >*/
NM_MANAGER_ERROR_DEPENDENCY_FAILED, /*< nick=DependencyFailed >*/
NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED, /*< nick=AutoconnectNotAllowed >*/
+ NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, /*< nick=ConnectionAlreadyActive >*/
} NMManagerError;
#define NM_MANAGER_VERSION "version"
@@ -103,6 +104,7 @@ NMManager *nm_manager_get (void);
void nm_manager_start (NMManager *manager);
const GSList *nm_manager_get_active_connections (NMManager *manager);
+GSList *nm_manager_get_activatable_connections (NMManager *manager);
/* Device handling */
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 98818047c0..2bdcfa95b4 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -1001,7 +1001,7 @@ auto_activate_device (gpointer user_data)
if (nm_device_get_act_request (data->device))
goto out;
- iter = connections = nm_settings_get_connections (priv->settings);
+ iter = connections = nm_manager_get_activatable_connections (priv->manager);
/* Remove connections that shouldn't be auto-activated */
while (iter) {