From 39d95b83c13dd769a7b9526e8c25def1c2458eb2 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 28 Mar 2018 17:18:04 +0200 Subject: [PATCH 1/3] core: specify an activation reason for active connections Specify a reason when creating active connections. The reason will be used in the next commit to tell whether slaves must be reconnected or not if a master has autoconnect-slaves=yes. (cherry picked from commit 43a0f47ea20b4a55dac9d914c76fff67d9b3d750) (cherry picked from commit ca12c0fafb316d68763febad3c5357f42f96afc9) --- src/nm-act-request.c | 5 ++++- src/nm-act-request.h | 1 + src/nm-active-connection.c | 25 +++++++++++++++++++++++++ src/nm-active-connection.h | 13 ++++++++----- src/nm-checkpoint.c | 4 ++++ src/nm-manager.c | 23 ++++++++++++++++++++++- src/nm-manager.h | 1 + src/nm-policy.c | 3 +++ src/nm-types.h | 7 +++++++ src/vpn/nm-vpn-connection.c | 2 ++ src/vpn/nm-vpn-connection.h | 1 + 11 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/nm-act-request.c b/src/nm-act-request.c index 87070794f..dd73947db 100644 --- a/src/nm-act-request.c +++ b/src/nm-act-request.c @@ -541,7 +541,8 @@ nm_act_request_init (NMActRequest *req) * @specific_object: the object path of the specific object (ie, WiFi access point, * etc) that will be used to activate @connection and @device * @subject: the #NMAuthSubject representing the requestor of the activation - * @activation_type: the #NMActivationType. + * @activation_type: the #NMActivationType + * @activation_reason: the reason for activation * @device: the device/interface to configure according to @connection * * Creates a new device-based activation request. If an applied connection is @@ -555,6 +556,7 @@ nm_act_request_new (NMSettingsConnection *settings_connection, const char *specific_object, NMAuthSubject *subject, NMActivationType activation_type, + NMActivationReason activation_reason, NMDevice *device) { g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), NULL); @@ -568,6 +570,7 @@ nm_act_request_new (NMSettingsConnection *settings_connection, NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object, NM_ACTIVE_CONNECTION_INT_SUBJECT, subject, NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, (int) activation_type, + NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, (int) activation_reason, NULL); } diff --git a/src/nm-act-request.h b/src/nm-act-request.h index 5d1c9dfd3..a8f09271a 100644 --- a/src/nm-act-request.h +++ b/src/nm-act-request.h @@ -41,6 +41,7 @@ NMActRequest *nm_act_request_new (NMSettingsConnection *settings_connec const char *specific_object, NMAuthSubject *subject, NMActivationType activation_type, + NMActivationReason activation_reason, NMDevice *device); NMSettingsConnection *nm_act_request_get_settings_connection (NMActRequest *req); diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 2286a74b4..0065094a4 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -54,6 +54,7 @@ typedef struct _NMActiveConnectionPrivate { bool master_ready:1; NMActivationType activation_type:3; + NMActivationReason activation_reason:3; NMAuthSubject *subject; NMActiveConnection *master; @@ -92,6 +93,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection, PROP_INT_MASTER, PROP_INT_MASTER_READY, PROP_INT_ACTIVATION_TYPE, + PROP_INT_ACTIVATION_REASON, ); enum { @@ -852,6 +854,14 @@ _set_activation_type_managed (NMActiveConnection *self) nm_device_sys_iface_state_set (priv->device, NM_DEVICE_SYS_IFACE_STATE_MANAGED); } +NMActivationReason +nm_active_connection_get_activation_reason (NMActiveConnection *self) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NM_ACTIVATION_REASON_UNSET); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->activation_reason; +} + /*****************************************************************************/ static void @@ -1250,6 +1260,12 @@ set_property (GObject *object, guint prop_id, g_return_if_reached (); _set_activation_type (self, (NMActivationType) i); break; + case PROP_INT_ACTIVATION_REASON: + /* construct-only */ + i = g_value_get_int (value); + priv->activation_reason = i; + nm_assert (priv->activation_reason == ((NMActivationReason) i)); + break; case PROP_SPECIFIC_OBJECT: tmp = g_value_get_string (value); /* NM uses "/" to mean NULL */ @@ -1518,6 +1534,15 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_INT_ACTIVATION_REASON] = + g_param_spec_int (NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, "", "", + NM_ACTIVATION_REASON_UNSET, + NM_ACTIVATION_REASON_USER_REQUEST, + NM_ACTIVATION_REASON_UNSET, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[DEVICE_CHANGED] = diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index 5ede2b04f..120ef573c 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -54,11 +54,12 @@ /* Internal non-exported properties */ #define NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION "int-settings-connection" #define NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION "int-applied-connection" -#define NM_ACTIVE_CONNECTION_INT_DEVICE "int-device" -#define NM_ACTIVE_CONNECTION_INT_SUBJECT "int-subject" -#define NM_ACTIVE_CONNECTION_INT_MASTER "int-master" -#define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready" -#define NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE "int-activation-type" +#define NM_ACTIVE_CONNECTION_INT_DEVICE "int-device" +#define NM_ACTIVE_CONNECTION_INT_SUBJECT "int-subject" +#define NM_ACTIVE_CONNECTION_INT_MASTER "int-master" +#define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready" +#define NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE "int-activation-type" +#define NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON "int-activation-reason" /* Signals */ #define NM_ACTIVE_CONNECTION_STATE_CHANGED "state-changed" @@ -181,6 +182,8 @@ void nm_active_connection_set_parent (NMActiveConnection *self, NMActivationType nm_active_connection_get_activation_type (NMActiveConnection *self); +NMActivationReason nm_active_connection_get_activation_reason (NMActiveConnection *self); + void nm_active_connection_clear_secrets (NMActiveConnection *self); #endif /* __NETWORKMANAGER_ACTIVE_CONNECTION_H__ */ diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index d606dee32..bc57d449a 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -47,6 +47,7 @@ typedef struct { NMDeviceState state; bool realized:1; NMUnmanFlagOp unmanaged_explicit; + NMActivationReason activation_reason; } DeviceCheckpoint; NM_GOBJECT_PROPERTIES_DEFINE_BASE ( @@ -301,6 +302,7 @@ activate: device, subject, NM_ACTIVATION_TYPE_MANAGED, + dev_checkpoint->activation_reason, &local_error)) { _LOGW ("rollback: reactivation of connection %s/%s failed: %s", nm_connection_get_id ((NMConnection *) connection), @@ -410,6 +412,8 @@ device_checkpoint_create (NMDevice *device, g_return_val_if_fail (act_request, NULL); dev_checkpoint->ac_version_id = nm_active_connection_version_id_get (NM_ACTIVE_CONNECTION (act_request)); + dev_checkpoint->activation_reason = + nm_active_connection_get_activation_reason (NM_ACTIVE_CONNECTION (act_request)); } return dev_checkpoint; diff --git a/src/nm-manager.c b/src/nm-manager.c index a3862c788..fce1605d9 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -278,6 +278,7 @@ static NMActiveConnection *_new_active_connection (NMManager *self, NMDevice *device, NMAuthSubject *subject, NMActivationType activation_type, + NMActivationReason activation_reason, GError **error); static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data); @@ -2320,6 +2321,7 @@ recheck_assume_connection (NMManager *self, active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, device, subject, generated ? NM_ACTIVATION_TYPE_EXTERNAL : NM_ACTIVATION_TYPE_ASSUME, + NM_ACTIVATION_REASON_AUTOCONNECT, &error); if (!active) { @@ -3157,6 +3159,7 @@ find_master (NMManager *self, * @device: the #NMDevice, if any, which will activate @connection * @master_connection: the master connection, or %NULL * @master_device: the master device, or %NULL + * @activation_reason: the reason for activation * @error: the error, if an error occurred * * Determines whether a given #NMConnection depends on another connection to @@ -3184,6 +3187,7 @@ ensure_master_active_connection (NMManager *self, NMDevice *device, NMSettingsConnection *master_connection, NMDevice *master_device, + NMActivationReason activation_reason, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); @@ -3247,6 +3251,7 @@ ensure_master_active_connection (NMManager *self, master_device, subject, NM_ACTIVATION_TYPE_MANAGED, + activation_reason, error); return master_ac; } @@ -3293,6 +3298,7 @@ ensure_master_active_connection (NMManager *self, candidate, subject, NM_ACTIVATION_TYPE_MANAGED, + activation_reason, error); return master_ac; } @@ -3515,6 +3521,7 @@ autoconnect_slaves (NMManager *self, slave->device, subject, NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES, &local_err); if (local_err) { _LOGW (LOGD_CORE, "Slave connection activation failed: %s", local_err->message); @@ -3685,7 +3692,10 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * } parent_ac = nm_manager_activate_connection (self, parent_con, NULL, NULL, parent, - subject, NM_ACTIVATION_TYPE_MANAGED, error); + subject, + NM_ACTIVATION_TYPE_MANAGED, + nm_active_connection_get_activation_reason (active), + error); if (!parent_ac) { g_prefix_error (error, "%s failed to activate parent: ", nm_device_get_iface (device)); return FALSE; @@ -3746,6 +3756,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * device, master_connection, master_device, + nm_active_connection_get_activation_reason (active), error); if (!master_ac) { if (master_device) { @@ -3838,6 +3849,7 @@ _new_vpn_active_connection (NMManager *self, NMSettingsConnection *settings_connection, const char *specific_object, NMAuthSubject *subject, + NMActivationReason activation_reason, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); @@ -3873,6 +3885,7 @@ _new_vpn_active_connection (NMManager *self, return (NMActiveConnection *) nm_vpn_connection_new (settings_connection, device, nm_exported_object_get_path (NM_EXPORTED_OBJECT (parent)), + activation_reason, subject); } @@ -3884,6 +3897,7 @@ _new_active_connection (NMManager *self, NMDevice *device, NMAuthSubject *subject, NMActivationType activation_type, + NMActivationReason activation_reason, GError **error) { NMSettingsConnection *settings_connection = NULL; @@ -3918,6 +3932,7 @@ _new_active_connection (NMManager *self, settings_connection, specific_object, subject, + activation_reason, error); } @@ -3929,6 +3944,7 @@ _new_active_connection (NMManager *self, specific_object, subject, activation_type, + activation_reason, device); } @@ -4009,6 +4025,7 @@ _internal_activation_auth_done (NMActiveConnection *active, * @subject: the subject which requested activation * @activation_type: whether to assume the connection. That is, take over gracefully, * non-destructible. + * @activation_reason: the reason for activation * @error: return location for an error * * Begins a new internally-initiated activation of @connection on @device. @@ -4029,6 +4046,7 @@ nm_manager_activate_connection (NMManager *self, NMDevice *device, NMAuthSubject *subject, NMActivationType activation_type, + NMActivationReason activation_reason, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); @@ -4076,6 +4094,7 @@ nm_manager_activate_connection (NMManager *self, device, subject, activation_type, + activation_reason, error); if (active) { priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active); @@ -4319,6 +4338,7 @@ impl_manager_activate_connection (NMManager *self, device, subject, NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_USER_REQUEST, &error); if (!active) goto error; @@ -4544,6 +4564,7 @@ impl_manager_add_and_activate_connection (NMManager *self, device, subject, NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_USER_REQUEST, &error); if (!active) goto error; diff --git a/src/nm-manager.h b/src/nm-manager.h index b4587e088..da8385320 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -136,6 +136,7 @@ NMActiveConnection *nm_manager_activate_connection (NMManager *manager, NMDevice *device, NMAuthSubject *subject, NMActivationType activation_type, + NMActivationReason activation_reason, GError **error); gboolean nm_manager_deactivate_connection (NMManager *manager, diff --git a/src/nm-policy.c b/src/nm-policy.c index 4d0ef91a1..861ae9ea2 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1255,6 +1255,7 @@ auto_activate_device (NMPolicy *self, device, subject, NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_AUTOCONNECT, &error); if (!ac) { _LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: %s", @@ -1677,6 +1678,7 @@ activate_secondary_connections (NMPolicy *self, device, nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (req)), NM_ACTIVATION_TYPE_MANAGED, + nm_active_connection_get_activation_reason (NM_ACTIVE_CONNECTION (req)), &error); if (ac) secondary_ac_list = g_slist_append (secondary_ac_list, g_object_ref (ac)); @@ -2142,6 +2144,7 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *self) NULL, nm_active_connection_get_subject (ac), NM_ACTIVATION_TYPE_MANAGED, + nm_active_connection_get_activation_reason (ac), &error)) { _LOGW (LOGD_DEVICE, "VPN '%s' reconnect failed: %s", nm_settings_connection_get_id (connection), diff --git a/src/nm-types.h b/src/nm-types.h index 02163f87e..794b0a1c3 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -75,6 +75,13 @@ typedef enum { NM_ACTIVATION_TYPE_EXTERNAL = 2, } NMActivationType; +typedef enum { + NM_ACTIVATION_REASON_UNSET = 0, + NM_ACTIVATION_REASON_AUTOCONNECT = 1, + NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES = 2, + NM_ACTIVATION_REASON_USER_REQUEST = 3, +} NMActivationReason; + typedef enum { /* In priority order; higher number == higher priority */ diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c index 6c600c46a..12ee0059b 100644 --- a/src/vpn/nm-vpn-connection.c +++ b/src/vpn/nm-vpn-connection.c @@ -858,6 +858,7 @@ NMVpnConnection * nm_vpn_connection_new (NMSettingsConnection *settings_connection, NMDevice *parent_device, const char *specific_object, + NMActivationReason activation_reason, NMAuthSubject *subject) { g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), NULL); @@ -868,6 +869,7 @@ nm_vpn_connection_new (NMSettingsConnection *settings_connection, NM_ACTIVE_CONNECTION_INT_DEVICE, parent_device, NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object, NM_ACTIVE_CONNECTION_INT_SUBJECT, subject, + NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, activation_reason, NM_ACTIVE_CONNECTION_VPN, TRUE, NULL); } diff --git a/src/vpn/nm-vpn-connection.h b/src/vpn/nm-vpn-connection.h index 038d0efde..b287c3346 100644 --- a/src/vpn/nm-vpn-connection.h +++ b/src/vpn/nm-vpn-connection.h @@ -53,6 +53,7 @@ GType nm_vpn_connection_get_type (void); NMVpnConnection * nm_vpn_connection_new (NMSettingsConnection *settings_connection, NMDevice *parent_device, const char *specific_object, + NMActivationReason activation_reason, NMAuthSubject *subject); void nm_vpn_connection_activate (NMVpnConnection *self, -- 2.14.3 From c0f7ebbb95b6b9d8e926364c57893049277356fa Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 28 Mar 2018 17:26:57 +0200 Subject: [PATCH 2/3] manager: allow autoconnect-slaves to reconnect the same connection When a master connection is activated and has autoconnect-slaves=yes, we want to reactivate an existing slave connection even if it is already active. https://bugzilla.redhat.com/show_bug.cgi?id=1548265 (cherry picked from commit 4985ca5ada9b9c24118b57c3288c5aa37c38ab81) (cherry picked from commit 370f84081c6cd309dde4c18fdce87264aca3c12f) --- src/nm-manager.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index fce1605d9..2a6a0d90f 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -3982,13 +3982,15 @@ _internal_activation_auth_done (NMActiveConnection *active, priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active); - /* Don't continue with the activation if an equivalent active connection - * already exists. We also check this earlier, but there we may fail to + /* Don't continue with an internal activation if an equivalent active + * connection already exists. Note that slave autoconnections always force a + * reconnection. We also check this earlier, but there we may fail to * detect a duplicate if the existing active connection is undergoing * authorization in impl_manager_activate_connection(). */ if ( success - && nm_auth_subject_is_internal (nm_active_connection_get_subject (active))) { + && nm_auth_subject_is_internal (nm_active_connection_get_subject (active)) + && nm_active_connection_get_activation_reason (active) != NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES) { c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { if ( nm_active_connection_get_device (ac) == nm_active_connection_get_device (active) && nm_active_connection_get_settings_connection (ac) == nm_active_connection_get_settings_connection (active) -- 2.14.3 From 16d41aeb3278860b4e13390a582a95806b07defb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 12 Apr 2018 15:47:40 +0200 Subject: [PATCH 3/3] manager: don't coalesce duplicate internal activations with different reasons When combining internal activations, do that only if their reason also matches. Fixes: 4985ca5ada9b9c24118b57c3288c5aa37c38ab81 (cherry picked from commit 786adf969c297fc2e830b43cc9e9b1a154d43216) (cherry picked from commit 8e64c4fa764be317304ff8b38b6b5c2cae75cc78) --- src/nm-manager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 2a6a0d90f..c73fae432 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4085,7 +4085,8 @@ nm_manager_activate_connection (NMManager *self, && g_strcmp0 (nm_active_connection_get_specific_object (active), specific_object) == 0 && nm_active_connection_get_device (active) == device && nm_auth_subject_is_internal (nm_active_connection_get_subject (active)) - && nm_auth_subject_is_internal (subject)) + && nm_auth_subject_is_internal (subject) + && nm_active_connection_get_activation_reason (active) == activation_reason) return active; } -- 2.14.3