mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-07 00:30:32 +01:00
core: connections failed due to missing secrets are re-tried when an secret agent registers (rh #706204)
Use case: A user has an auto-activatable connection with secrets in a keyring. While booting NM starts and tries to activate the connection, but it fails because of missing secrets. Then the user logs in, but the connection is marked as invalid and is not tried again. This commit solves the issue by removing invalid flag and activating the connection when a secret agent registers. Signed-off-by: Jiří Klimeš <jklimes@redhat.com>
This commit is contained in:
parent
18b81930ce
commit
69b767bbf0
5 changed files with 96 additions and 1 deletions
|
|
@ -76,6 +76,7 @@ struct NMPolicy {
|
|||
#define RETRIES_DEFAULT 4
|
||||
#define RESET_RETRIES_TIMESTAMP_TAG "reset-retries-timestamp-tag"
|
||||
#define RESET_RETRIES_TIMER 300
|
||||
#define FAILURE_REASON_TAG "failure-reason"
|
||||
|
||||
static NMDevice *
|
||||
get_best_ip4_device (NMManager *manager, NMActRequest **out_req)
|
||||
|
|
@ -837,6 +838,23 @@ reset_retries_all (NMSettings *settings, NMDevice *device)
|
|||
g_slist_free (connections);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_retries_for_failed_secrets (NMSettings *settings)
|
||||
{
|
||||
GSList *connections, *iter;
|
||||
|
||||
connections = nm_settings_get_connections (settings);
|
||||
for (iter = connections; iter; iter = g_slist_next (iter)) {
|
||||
NMDeviceStateReason reason = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (iter->data), FAILURE_REASON_TAG));
|
||||
|
||||
if (reason == NM_DEVICE_STATE_REASON_NO_SECRETS) {
|
||||
set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT);
|
||||
g_object_set_data (G_OBJECT (iter->data), FAILURE_REASON_TAG, GUINT_TO_POINTER (0));
|
||||
}
|
||||
}
|
||||
g_slist_free (connections);
|
||||
}
|
||||
|
||||
static void
|
||||
sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
|
|
@ -927,6 +945,9 @@ device_state_changed (NMDevice *device,
|
|||
NMPolicy *policy = (NMPolicy *) user_data;
|
||||
NMConnection *connection = get_device_connection (device);
|
||||
|
||||
if (connection)
|
||||
g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (0));
|
||||
|
||||
switch (new_state) {
|
||||
case NM_DEVICE_STATE_FAILED:
|
||||
/* Mark the connection invalid if it failed during activation so that
|
||||
|
|
@ -941,6 +962,11 @@ device_state_changed (NMDevice *device,
|
|||
* automatically retrying because it's just going to fail anyway.
|
||||
*/
|
||||
set_connection_auto_retries (connection, 0);
|
||||
|
||||
/* Mark the connection as failed due to missing secrets so that we can reset
|
||||
* RETRIES_TAG and automatically re-try when an secret agent registers.
|
||||
*/
|
||||
g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (NM_DEVICE_STATE_REASON_NO_SECRETS));
|
||||
} else if (tries > 0) {
|
||||
/* Otherwise if it's a random failure, just decrease the number
|
||||
* of automatic retries so that the connection gets tried again
|
||||
|
|
@ -1172,6 +1198,19 @@ connection_visibility_changed (NMSettings *settings,
|
|||
_deactivate_if_active (policy->manager, NM_CONNECTION (connection));
|
||||
}
|
||||
|
||||
static void
|
||||
secret_agent_registered (NMSettings *settings,
|
||||
NMSecretAgent *agent,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* The registered secret agent may provide some missing secrets. Thus we
|
||||
* reset retries count here and schedule activation, so that the
|
||||
* connections failed due to missing secrets may re-try auto-connection.
|
||||
*/
|
||||
reset_retries_for_failed_secrets (settings);
|
||||
schedule_activate_all ((NMPolicy *) user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_connect_manager_signal (NMPolicy *policy, const char *name, gpointer callback)
|
||||
{
|
||||
|
|
@ -1240,6 +1279,7 @@ nm_policy_new (NMManager *manager,
|
|||
_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed);
|
||||
_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED,
|
||||
connection_visibility_changed);
|
||||
_connect_settings_signal (policy, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered);
|
||||
|
||||
/* Initialize connections' auto-retries */
|
||||
reset_retries_all (policy->settings, NULL);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,14 @@ typedef struct {
|
|||
GHashTable *requests;
|
||||
} NMAgentManagerPrivate;
|
||||
|
||||
enum {
|
||||
AGENT_REGISTERED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
||||
typedef struct _Request Request;
|
||||
|
||||
static void request_add_agent (Request *req,
|
||||
|
|
@ -277,6 +285,9 @@ impl_agent_manager_register (NMAgentManager *self,
|
|||
nm_secret_agent_get_description (agent));
|
||||
dbus_g_method_return (context);
|
||||
|
||||
/* Signal an agent was registered */
|
||||
g_signal_emit (self, signals[AGENT_REGISTERED], 0, agent);
|
||||
|
||||
/* Add this agent to any in-progress secrets requests */
|
||||
g_hash_table_iter_init (&iter, priv->requests);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||
|
|
@ -1363,6 +1374,17 @@ nm_agent_manager_class_init (NMAgentManagerClass *agent_manager_class)
|
|||
/* virtual methods */
|
||||
object_class->dispose = dispose;
|
||||
|
||||
/* Signals */
|
||||
signals[AGENT_REGISTERED] =
|
||||
g_signal_new ("agent-registered",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMAgentManagerClass, agent_registered),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_OBJECT);
|
||||
|
||||
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (agent_manager_class),
|
||||
&dbus_glib_nm_agent_manager_object_info);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <glib-object.h>
|
||||
#include <nm-connection.h>
|
||||
#include "nm-settings-flags.h"
|
||||
#include "nm-secret-agent.h"
|
||||
|
||||
#define NM_TYPE_AGENT_MANAGER (nm_agent_manager_get_type ())
|
||||
#define NM_AGENT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AGENT_MANAGER, NMAgentManager))
|
||||
|
|
@ -39,6 +40,9 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
/* Signals */
|
||||
void (*agent_registered) (NMAgentManager *agent_mgr, NMSecretAgent *agent);
|
||||
} NMAgentManagerClass;
|
||||
|
||||
GType nm_agent_manager_get_type (void);
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ enum {
|
|||
CONNECTION_REMOVED,
|
||||
CONNECTION_VISIBILITY_CHANGED,
|
||||
CONNECTIONS_LOADED,
|
||||
AGENT_REGISTERED,
|
||||
|
||||
NEW_CONNECTION, /* exported, not used internally */
|
||||
LAST_SIGNAL
|
||||
|
|
@ -699,6 +700,18 @@ connection_visibility_changed (NMSettingsConnection *connection,
|
|||
connection);
|
||||
}
|
||||
|
||||
static void
|
||||
secret_agent_registered (NMAgentManager *agent_mgr,
|
||||
NMSecretAgent *agent,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* Re-emit for listeners like NMPolicy */
|
||||
g_signal_emit (NM_SETTINGS (user_data),
|
||||
signals[AGENT_REGISTERED],
|
||||
0,
|
||||
agent);
|
||||
}
|
||||
|
||||
#define NM_DBUS_SERVICE_OPENCONNECT "org.freedesktop.NetworkManager.openconnect"
|
||||
#define NM_OPENCONNECT_KEY_GATEWAY "gateway"
|
||||
#define NM_OPENCONNECT_KEY_COOKIE "cookie"
|
||||
|
|
@ -1530,6 +1543,8 @@ nm_settings_init (NMSettings *self)
|
|||
* recreated often.
|
||||
*/
|
||||
priv->agent_mgr = nm_agent_manager_get ();
|
||||
|
||||
g_signal_connect (priv->agent_mgr, "agent-registered", G_CALLBACK (secret_agent_registered), self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1693,6 +1708,16 @@ nm_settings_class_init (NMSettingsClass *class)
|
|||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[AGENT_REGISTERED] =
|
||||
g_signal_new (NM_SETTINGS_SIGNAL_AGENT_REGISTERED,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMSettingsClass, agent_registered),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, G_TYPE_OBJECT);
|
||||
|
||||
|
||||
signals[NEW_CONNECTION] =
|
||||
g_signal_new ("new-connection",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* (C) Copyright 2007 - 2010 Red Hat, Inc.
|
||||
* (C) Copyright 2007 - 2011 Red Hat, Inc.
|
||||
* (C) Copyright 2008 Novell, Inc.
|
||||
*/
|
||||
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include "nm-settings-connection.h"
|
||||
#include "nm-system-config-interface.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-secret-agent.h"
|
||||
|
||||
#define NM_TYPE_SETTINGS (nm_settings_get_type ())
|
||||
#define NM_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS, NMSettings))
|
||||
|
|
@ -48,6 +49,7 @@
|
|||
#define NM_SETTINGS_SIGNAL_CONNECTION_REMOVED "connection-removed"
|
||||
#define NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED "connection-visibility-changed"
|
||||
#define NM_SETTINGS_SIGNAL_CONNECTIONS_LOADED "connections-loaded"
|
||||
#define NM_SETTINGS_SIGNAL_AGENT_REGISTERED "agent-registered"
|
||||
|
||||
typedef struct {
|
||||
GObject parent_instance;
|
||||
|
|
@ -68,6 +70,8 @@ typedef struct {
|
|||
void (*connection_visibility_changed) (NMSettings *self, NMSettingsConnection *connection);
|
||||
|
||||
void (*connections_loaded) (NMSettings *self);
|
||||
|
||||
void (*agent_registered) (NMSettings *self, NMSecretAgent *agent);
|
||||
} NMSettingsClass;
|
||||
|
||||
GType nm_settings_get_type (void);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue