When a master connection is activated, check all its slaves and decide whether they should be activated as well. This is done according to the autoconnect-slaves property. https://bugzilla.gnome.org/show_bug.cgi?id=735052 https://bugzilla.redhat.com/show_bug.cgi?id=1158529
This commit is contained in:
124
src/nm-manager.c
124
src/nm-manager.c
@@ -2392,6 +2392,127 @@ ensure_master_active_connection (NMManager *self,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_slaves:
|
||||||
|
* @manager: #NMManager object
|
||||||
|
* @connection: the master #NMConnection to find slave connections for
|
||||||
|
* @device: the master #NMDevice for the @connection
|
||||||
|
*
|
||||||
|
* Given an #NMConnection, attempts to find its slaves. If @connection is not
|
||||||
|
* master, or has not any slaves, this will return %NULL.
|
||||||
|
*
|
||||||
|
* Returns: list of slave connections for given master @connection, or %NULL
|
||||||
|
**/
|
||||||
|
static GSList *
|
||||||
|
find_slaves (NMManager *manager,
|
||||||
|
NMConnection *connection,
|
||||||
|
NMDevice *device)
|
||||||
|
{
|
||||||
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
||||||
|
GSList *all_connections, *iter;
|
||||||
|
GSList *slaves = NULL;
|
||||||
|
NMSettingConnection *s_con;
|
||||||
|
const char *master;
|
||||||
|
|
||||||
|
s_con = nm_connection_get_setting_connection (connection);
|
||||||
|
g_assert (s_con);
|
||||||
|
master = nm_setting_connection_get_master (s_con);
|
||||||
|
|
||||||
|
if (master != NULL)
|
||||||
|
return NULL; /* connection is not master */
|
||||||
|
|
||||||
|
/* Search through all connections, not only inactive ones, because
|
||||||
|
* even if a slave was already active, it might be deactivated during
|
||||||
|
* master reactivation.
|
||||||
|
*/
|
||||||
|
all_connections = nm_settings_get_connections (priv->settings);
|
||||||
|
for (iter = all_connections; iter; iter = iter->next) {
|
||||||
|
NMConnection *master_connection = NULL;
|
||||||
|
NMDevice *master_device = NULL;
|
||||||
|
NMConnection *candidate = iter->data;
|
||||||
|
|
||||||
|
find_master (manager, candidate, NULL, &master_connection, &master_device, NULL, NULL);
|
||||||
|
if ( (master_connection && master_connection == connection)
|
||||||
|
|| (master_device && master_device == device)) {
|
||||||
|
slaves = g_slist_prepend (slaves, candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_slist_free (all_connections);
|
||||||
|
|
||||||
|
return g_slist_reverse (slaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
should_connect_slaves (NMConnection *connection, NMDevice *device)
|
||||||
|
{
|
||||||
|
NMSettingConnection *s_con;
|
||||||
|
NMSettingConnectionAutoconnectSlaves autoconnect_slaves;
|
||||||
|
gs_free char *value = NULL;
|
||||||
|
|
||||||
|
s_con = nm_connection_get_setting_connection (connection);
|
||||||
|
g_assert (s_con);
|
||||||
|
|
||||||
|
/* Check autoconnect-slaves property */
|
||||||
|
autoconnect_slaves = nm_setting_connection_get_autoconnect_slaves (s_con);
|
||||||
|
if (autoconnect_slaves != NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Check configuration default for autoconnect-slaves property */
|
||||||
|
value = nm_config_data_get_connection_default (nm_config_get_data (nm_config_get ()),
|
||||||
|
"connection.autoconnect-slaves", device);
|
||||||
|
if (value)
|
||||||
|
autoconnect_slaves = _nm_utils_ascii_str_to_int64 (value, 10, 0, 1, -1);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO)
|
||||||
|
return FALSE;
|
||||||
|
if (autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
autoconnect_slaves (NMManager *manager,
|
||||||
|
NMConnection *master_connection,
|
||||||
|
NMDevice *master_device,
|
||||||
|
NMAuthSubject *subject)
|
||||||
|
{
|
||||||
|
GError *local_err = NULL;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
if (should_connect_slaves (master_connection, master_device)) {
|
||||||
|
GSList *slaves, *iter;
|
||||||
|
|
||||||
|
iter = slaves = find_slaves (manager, master_connection, master_device);
|
||||||
|
ret = slaves != NULL;
|
||||||
|
|
||||||
|
while (iter) {
|
||||||
|
NMConnection *slave_connection = iter->data;
|
||||||
|
|
||||||
|
iter = iter->next;
|
||||||
|
nm_log_dbg (LOGD_CORE, "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)",
|
||||||
|
nm_connection_get_id (slave_connection),
|
||||||
|
nm_connection_get_uuid (slave_connection),
|
||||||
|
nm_connection_get_id (master_connection),
|
||||||
|
nm_connection_get_uuid (master_connection));
|
||||||
|
|
||||||
|
/* Schedule slave activation */
|
||||||
|
nm_manager_activate_connection (manager,
|
||||||
|
slave_connection,
|
||||||
|
NULL,
|
||||||
|
nm_manager_get_best_device_for_connection (manager, slave_connection),
|
||||||
|
subject,
|
||||||
|
&local_err);
|
||||||
|
if (local_err) {
|
||||||
|
nm_log_warn (LOGD_CORE, "Slave connection activation failed: %s", local_err->message);
|
||||||
|
g_error_free (local_err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_slist_free (slaves);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **error)
|
_internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **error)
|
||||||
{
|
{
|
||||||
@@ -2564,6 +2685,9 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
|||||||
nm_active_connection_get_path (master_ac));
|
nm_active_connection_get_path (master_ac));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check slaves for master connection and possibly activate them */
|
||||||
|
autoconnect_slaves (self, connection, device, nm_active_connection_get_subject (active));
|
||||||
|
|
||||||
/* Disconnect the connection if connected or queued on another device */
|
/* Disconnect the connection if connected or queued on another device */
|
||||||
existing = nm_manager_get_connection_device (self, connection);
|
existing = nm_manager_get_connection_device (self, connection);
|
||||||
if (existing)
|
if (existing)
|
||||||
|
Reference in New Issue
Block a user