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.
This commit is contained in:
Dan Winship 2013-09-12 10:28:21 -04:00
parent 154264d99c
commit a1f16cd4d9
3 changed files with 66 additions and 5 deletions

View file

@ -399,6 +399,46 @@ nm_manager_get_active_connections (NMManager *manager)
return NM_MANAGER_GET_PRIVATE (manager)->active_connections;
}
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)
{
@ -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;

View file

@ -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 */

View file

@ -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) {