diff options
Diffstat (limited to 'src/nm-policy.c')
-rw-r--r-- | src/nm-policy.c | 104 |
1 files changed, 84 insertions, 20 deletions
diff --git a/src/nm-policy.c b/src/nm-policy.c index ffe9203e7b..11034cb858 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -666,6 +666,59 @@ check_activating_devices (NMPolicy *self) g_object_thaw_notify (object); } +static NMSettingsConnection * +_find_connection_to_assume (NMPolicy *self, + NMDevice *device) +{ + NMPolicyPrivate *priv; + NMSettingsConnection *connection; + gs_free const char *uuid = NULL; + const NMPlatformLink *pllink; + + uuid = nm_device_steal_connection_uuid_to_assume (device); + if (!uuid) + return NULL; + + priv = NM_POLICY_GET_PRIVATE (self); + + connection = nm_settings_get_connection_by_uuid (priv->settings, uuid); + if (!connection) + return NULL; + + if (nm_manager_get_connection_device (priv->manager, NM_CONNECTION (connection))) { + /* if the connection is already active on another device, it cannot be + * activated here. */ + return NULL; + } + + if (!nm_device_check_connection_available (device, + NM_CONNECTION (connection), + NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, + NULL)) { + /* the connection must be compatible and available on the device. */ + return NULL; + } + + /* only if the device exists. */ + pllink = nm_platform_link_get (NM_PLATFORM_GET, + nm_device_get_ip_ifindex (device)); + if (!pllink) + return NULL; + + if (nm_setting_connection_get_slave_type (nm_connection_get_setting_connection (NM_CONNECTION (connection)))) { + /* a slave. Is the link still enslaved? */ + if (pllink->master <= 0) + return NULL; + } else { + /* the device must be up and not a slave. */ + if ( pllink->master > 0 + || !NM_FLAGS_HAS (pllink->n_ifi_flags, IFF_UP)) + return NULL; + } + + return connection; +} + typedef struct { NMPolicy *policy; NMDevice *device; @@ -694,8 +747,7 @@ auto_activate_device (NMPolicy *self, NMPolicyPrivate *priv; NMSettingsConnection *best_connection; gs_free char *specific_object = NULL; - GPtrArray *connections; - GSList *connection_list; + gboolean assume = FALSE; guint i; nm_assert (NM_IS_POLICY (self)); @@ -710,30 +762,37 @@ auto_activate_device (NMPolicy *self, if (nm_device_get_act_request (device)) return; - connection_list = nm_manager_get_activatable_connections (priv->manager); - if (!connection_list) - return; + best_connection = _find_connection_to_assume (self, device); + if (best_connection) + assume = TRUE; + else { + GSList *connection_list; + gs_unref_ptrarray GPtrArray *connections = NULL; - connections = _nm_utils_copy_slist_to_array (connection_list, NULL, NULL); - g_slist_free (connection_list); + connection_list = nm_manager_get_activatable_connections (priv->manager); + if (!connection_list) + return; - /* sort is stable (which is important at this point) so that connections - * with same priority are still sorted by last-connected-timestamp. */ - g_ptr_array_sort (connections, (GCompareFunc) nm_utils_cmp_connection_by_autoconnect_priority); + connections = _nm_utils_copy_slist_to_array (connection_list, NULL, NULL); + g_slist_free (connection_list); - /* Find the first connection that should be auto-activated */ - best_connection = NULL; - for (i = 0; i < connections->len; i++) { - NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (connections->pdata[i]); + /* sort is stable (which is important at this point) so that connections + * with same priority are still sorted by last-connected-timestamp. */ + g_ptr_array_sort (connections, (GCompareFunc) nm_utils_cmp_connection_by_autoconnect_priority); - if (!nm_settings_connection_can_autoconnect (candidate)) - continue; - if (nm_device_can_auto_connect (device, (NMConnection *) candidate, &specific_object)) { - best_connection = candidate; - break; + /* Find the first connection that should be auto-activated */ + best_connection = NULL; + for (i = 0; i < connections->len; i++) { + NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (connections->pdata[i]); + + if (!nm_settings_connection_can_autoconnect (candidate)) + continue; + if (nm_device_can_auto_connect (device, (NMConnection *) candidate, &specific_object)) { + best_connection = candidate; + break; + } } } - g_ptr_array_free (connections, TRUE); if (best_connection) { GError *error = NULL; @@ -748,6 +807,9 @@ auto_activate_device (NMPolicy *self, specific_object, device, subject, + assume + ? NM_ACTIVATION_TYPE_ASSUME + : NM_ACTIVATION_TYPE_FULL, &error)) { _LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: (%d) %s", nm_settings_connection_get_id (best_connection), @@ -1153,6 +1215,7 @@ activate_secondary_connections (NMPolicy *self, nm_exported_object_get_path (NM_EXPORTED_OBJECT (req)), device, nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (req)), + NM_ACTIVATION_TYPE_FULL, &error); if (ac) secondary_ac_list = g_slist_append (secondary_ac_list, g_object_ref (ac)); @@ -1555,6 +1618,7 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *self) NULL, NULL, nm_active_connection_get_subject (ac), + NM_ACTIVATION_TYPE_FULL, &error)) { _LOGW (LOGD_DEVICE, "VPN '%s' reconnect failed: %s", nm_settings_connection_get_id (connection), |