diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 4fc32c38f2..d458fffa22 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -108,6 +108,8 @@ typedef struct _NMDeviceEthernetPrivate { char * s390_nettype; GHashTable * s390_options; + NMActRequestGetSecretsCallId wired_secrets_id; + /* PPPoE */ NMPPPManager *ppp_manager; NMIP4Config *pending_ip4_config; @@ -133,6 +135,10 @@ G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) /*****************************************************************************/ +static void wired_secrets_cancel (NMDeviceEthernet *self); + +/*****************************************************************************/ + static char * get_link_basename (const char *parent_path, const char *name, GError **error) { @@ -285,6 +291,9 @@ device_state_changed (NMDevice *device, NMDeviceState old_state, NMDeviceStateReason reason) { + if (new_state > NM_DEVICE_STATE_ACTIVATED) + wired_secrets_cancel (NM_DEVICE_ETHERNET (device)); + if ( new_state == NM_DEVICE_STATE_ACTIVATED || new_state == NM_DEVICE_STATE_FAILED || new_state == NM_DEVICE_STATE_DISCONNECTED) @@ -459,22 +468,66 @@ wired_secrets_cb (NMActRequest *req, GError *error, gpointer user_data) { - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - NMDevice *dev = NM_DEVICE (self); + NMDeviceEthernet *self = user_data; + NMDevice *device = user_data; + NMDeviceEthernetPrivate *priv; - if (req != nm_device_get_act_request (dev)) + g_return_if_fail (NM_IS_DEVICE_ETHERNET (self)); + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + + priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + g_return_if_fail (priv->wired_secrets_id == call_id); + + priv->wired_secrets_id = NULL; + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; - g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); + g_return_if_fail (req == nm_device_get_act_request (device)); + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); g_return_if_fail (nm_act_request_get_settings_connection (req) == connection); if (error) { _LOGW (LOGD_ETHER, "%s", error->message); - nm_device_state_changed (dev, + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); } else - nm_device_activate_schedule_stage1_device_prepare (dev); + nm_device_activate_schedule_stage1_device_prepare (device); +} + +static void +wired_secrets_cancel (NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + if (priv->wired_secrets_id) + nm_act_request_cancel_secrets (NULL, priv->wired_secrets_id); + nm_assert (!priv->wired_secrets_id); +} + +static void +wired_secrets_get_secrets (NMDeviceEthernet *self, + const char *setting_name, + NMSecretAgentGetSecretsFlags flags) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMActRequest *req; + + wired_secrets_cancel (self); + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + + priv->wired_secrets_id = nm_act_request_get_secrets (req, + TRUE, + setting_name, + flags, + NULL, + wired_secrets_cb, + self); + g_return_if_fail (priv->wired_secrets_id); } static gboolean @@ -517,12 +570,7 @@ link_timeout_cb (gpointer user_data) supplicant_interface_release (self); nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - nm_act_request_get_secrets (req, - setting_name, - NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW, - NULL, - wired_secrets_cb, - self); + wired_secrets_get_secrets (self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW); return FALSE; @@ -698,12 +746,9 @@ handle_auth_or_fail (NMDeviceEthernet *self, setting_name = nm_connection_need_secrets (applied_connection, NULL); if (setting_name) { - NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; - - if (new_secrets) - flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - nm_act_request_get_secrets (req, setting_name, flags, NULL, wired_secrets_cb, self); - + wired_secrets_get_secrets (self, setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); g_object_set_data (G_OBJECT (applied_connection), WIRED_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); } else _LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); @@ -1656,6 +1701,8 @@ dispose (GObject *object) NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + wired_secrets_cancel (self); + supplicant_interface_release (self); nm_clear_g_source (&priv->pppoe_wait_id); @@ -1706,7 +1753,7 @@ get_property (GObject *object, guint prop_id, static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) + const GValue *value, GParamSpec *pspec) { switch (prop_id) { default: diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 0ec9fe8e66..4c56aa7c65 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -108,6 +108,8 @@ typedef struct { NM80211Mode mode; + NMActRequestGetSecretsCallId wifi_secrets_id; + guint periodic_source_id; guint link_timeout_id; guint32 failed_iface_count; @@ -1738,12 +1740,23 @@ wifi_secrets_cb (NMActRequest *req, GError *error, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); - NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDevice *device = user_data; + NMDeviceWifi *self = user_data; + NMDeviceWifiPrivate *priv; - if (req != nm_device_get_act_request (device)) + g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + g_return_if_fail (priv->wifi_secrets_id == call_id); + + priv->wifi_secrets_id = NULL; + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; + g_return_if_fail (req == nm_device_get_act_request (device)); g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); g_return_if_fail (nm_act_request_get_settings_connection (req) == connection); @@ -1756,6 +1769,39 @@ wifi_secrets_cb (NMActRequest *req, nm_device_activate_schedule_stage1_device_prepare (device); } +static void +wifi_secrets_cancel (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->wifi_secrets_id) + nm_act_request_cancel_secrets (NULL, priv->wifi_secrets_id); + nm_assert (!priv->wifi_secrets_id); +} + +static void +wifi_secrets_get_secrets (NMDeviceWifi *self, + const char *setting_name, + NMSecretAgentGetSecretsFlags flags) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMActRequest *req; + + wifi_secrets_cancel (self); + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + + priv->wifi_secrets_id = nm_act_request_get_secrets (req, + TRUE, + setting_name, + flags, + NULL, + wifi_secrets_cb, + self); + g_return_if_fail (priv->wifi_secrets_id); +} + /* * link_timeout_cb * @@ -1900,13 +1946,10 @@ handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, cleanup_association_attempt (self, TRUE); nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - nm_act_request_get_secrets (req, - setting_name, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW, - NULL, - wifi_secrets_cb, - self); + wifi_secrets_get_secrets (self, + setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW); handled = TRUE; } @@ -2171,7 +2214,7 @@ handle_auth_or_fail (NMDeviceWifi *self, if (!req) { req = nm_device_get_act_request (NM_DEVICE (self)); - g_assert (req); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); } applied_connection = nm_act_request_get_applied_connection (req); @@ -2185,12 +2228,9 @@ handle_auth_or_fail (NMDeviceWifi *self, nm_act_request_clear_secrets (req); setting_name = nm_connection_need_secrets (applied_connection, NULL); if (setting_name) { - NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; - - if (new_secrets) - flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - nm_act_request_get_secrets (req, setting_name, flags, NULL, wifi_secrets_cb, self); - + wifi_secrets_get_secrets (self, setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); ret = NM_ACT_STAGE_RETURN_POSTPONE; } else @@ -2878,6 +2918,9 @@ device_state_changed (NMDevice *device, NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); gboolean clear_aps = FALSE; + if (new_state > NM_DEVICE_STATE_ACTIVATED) + wifi_secrets_cancel (self); + if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { /* Clean up the supplicant interface because in these states the * device cannot be used. @@ -3028,6 +3071,8 @@ dispose (GObject *object) nm_clear_g_source (&priv->periodic_source_id); + wifi_secrets_cancel (self); + cleanup_association_attempt (self, TRUE); supplicant_interface_release (self); cleanup_supplicant_failures (self); @@ -3150,7 +3195,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) klass->scanning_allowed = scanning_allowed; - /* Properties */ obj_properties[PROP_MODE] = g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "", NM_802_11_MODE_UNKNOWN, @@ -3192,7 +3236,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - /* Signals */ signals[ACCESS_POINT_ADDED] = g_signal_new (NM_DEVICE_WIFI_ACCESS_POINT_ADDED, G_OBJECT_CLASS_TYPE (object_class), diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 635f20ea74..4a8e9094ad 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -820,6 +820,7 @@ nm_modem_get_secrets (NMModem *self, if (request_new) flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; priv->secrets_id = nm_act_request_get_secrets (priv->act_request, + FALSE, setting_name, flags, hint, @@ -870,6 +871,7 @@ nm_modem_act_stage1_prepare (NMModem *self, flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; priv->secrets_id = nm_act_request_get_secrets (req, + FALSE, setting_name, flags, hints ? g_ptr_array_index (hints, 0) : NULL, diff --git a/src/nm-act-request.c b/src/nm-act-request.c index b746e45baf..3a04667b3c 100644 --- a/src/nm-act-request.c +++ b/src/nm-act-request.c @@ -94,17 +94,19 @@ struct _NMActRequestGetSecretsCallId { NMActRequestSecretsFunc callback; gpointer callback_data; NMSettingsConnectionCallId call_id; + bool has_ref; }; typedef struct _NMActRequestGetSecretsCallId GetSecretsInfo; static GetSecretsInfo * -_get_secrets_info_new (NMActRequest *self, NMActRequestSecretsFunc callback, gpointer callback_data) +_get_secrets_info_new (NMActRequest *self, gboolean ref_self, NMActRequestSecretsFunc callback, gpointer callback_data) { GetSecretsInfo *info; info = g_slice_new0 (GetSecretsInfo); - info->self = self; + info->has_ref = ref_self; + info->self = ref_self ? g_object_ref (self) : self; info->callback = callback; info->callback_data = callback_data; @@ -114,6 +116,8 @@ _get_secrets_info_new (NMActRequest *self, NMActRequestSecretsFunc callback, gpo static void _get_secrets_info_free (GetSecretsInfo *info) { + if (info->has_ref) + g_object_unref (info->self); g_slice_free (GetSecretsInfo, info); } @@ -149,6 +153,8 @@ get_secrets_cb (NMSettingsConnection *connection, /** * nm_act_request_get_secrets: * @self: + * @ref_self: if %TRUE, the pending call take a reference on @self. + * It also allows you to omit the @self argument in nm_act_request_cancel_secrets(). * @setting_name: * @flags: * @hint: @@ -167,6 +173,7 @@ get_secrets_cb (NMSettingsConnection *connection, */ NMActRequestGetSecretsCallId nm_act_request_get_secrets (NMActRequest *self, + gboolean ref_self, const char *setting_name, NMSecretAgentGetSecretsFlags flags, const char *hint, @@ -180,14 +187,14 @@ nm_act_request_get_secrets (NMActRequest *self, NMConnection *applied_connection; const char *hints[2] = { hint, NULL }; - g_return_val_if_fail (NM_IS_ACT_REQUEST (self), 0); + g_return_val_if_fail (NM_IS_ACT_REQUEST (self), NULL); priv = NM_ACT_REQUEST_GET_PRIVATE (self); settings_connection = nm_act_request_get_settings_connection (self); applied_connection = nm_act_request_get_applied_connection (self); - info = _get_secrets_info_new (self, callback, callback_data); + info = _get_secrets_info_new (self, ref_self, callback, callback_data); priv->secrets_calls = g_slist_append (priv->secrets_calls, info); @@ -229,14 +236,32 @@ _do_cancel_secrets (NMActRequest *self, GetSecretsInfo *info, gboolean is_dispos _get_secrets_info_free (info); } +/** + * nm_act_request_cancel_secrets: + * @self: The #NMActRequest. Note that this argument can be %NULL if, and only if + * the call_id was created with @take_ref. + * @call_id: + * + * You are only allowed to cancel the call once, and only before the callback + * is already invoked. Note that cancelling causes the callback to be invoked + * synchronously. + */ void nm_act_request_cancel_secrets (NMActRequest *self, NMActRequestGetSecretsCallId call_id) { NMActRequestPrivate *priv; - g_return_if_fail (NM_IS_ACT_REQUEST (self)); g_return_if_fail (call_id); + if (self) { + g_return_if_fail (NM_IS_ACT_REQUEST (self)); + g_return_if_fail (self == call_id->self); + } else { + g_return_if_fail (call_id->has_ref); + g_return_if_fail (NM_IS_ACT_REQUEST (call_id->self)); + self = call_id->self; + } + priv = NM_ACT_REQUEST_GET_PRIVATE (self); if (!g_slist_find (priv->secrets_calls, call_id)) diff --git a/src/nm-act-request.h b/src/nm-act-request.h index 2443633f00..47247f8910 100644 --- a/src/nm-act-request.h +++ b/src/nm-act-request.h @@ -63,6 +63,7 @@ typedef void (*NMActRequestSecretsFunc) (NMActRequest *req, gpointer user_data); NMActRequestGetSecretsCallId nm_act_request_get_secrets (NMActRequest *req, + gboolean take_ref, const char *setting_name, NMSecretAgentGetSecretsFlags flags, const char *hint, diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c index e33d9fe6fc..bf24552fb3 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/ppp/nm-ppp-manager.c @@ -346,6 +346,7 @@ impl_ppp_manager_need_secrets (NMPPPManager *manager, flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; priv->secrets_id = nm_act_request_get_secrets (priv->act_req, + FALSE, priv->secrets_setting_name, flags, hints ? g_ptr_array_index (hints, 0) : NULL,