diff options
author | Dan Winship <danw@gnome.org> | 2013-09-12 10:28:21 -0400 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2013-11-06 10:21:27 -0500 |
commit | a1f16cd4d9fff66d7feeee0846e554c9c3a5f998 (patch) | |
tree | d55f935d64fdf4c2150859796185d8158aba57ca | |
parent | 154264d99c75ee8db920b3ba5ea609b57c2298d4 (diff) | |
download | NetworkManager-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.c | 67 | ||||
-rw-r--r-- | src/nm-manager.h | 2 | ||||
-rw-r--r-- | src/nm-policy.c | 2 |
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) { |