core: re-attempt connection assumption when the device state changes
If the initial attempt to assume a connection on a device fails, and the device remains un-activated, but then something changes its configuration externally, try to generate a new connection and assume that.
This commit is contained in:
@@ -97,5 +97,6 @@ void nm_device_master_check_slave_physical_port (NMDevice *dev, NMDevice *slave,
|
|||||||
void nm_device_set_carrier (NMDevice *device, gboolean carrier);
|
void nm_device_set_carrier (NMDevice *device, gboolean carrier);
|
||||||
|
|
||||||
void nm_device_emit_recheck_auto_activate (NMDevice *device);
|
void nm_device_emit_recheck_auto_activate (NMDevice *device);
|
||||||
|
void nm_device_queue_recheck_assume (NMDevice *device);
|
||||||
|
|
||||||
#endif /* NM_DEVICE_PRIVATE_H */
|
#endif /* NM_DEVICE_PRIVATE_H */
|
||||||
|
@@ -105,6 +105,7 @@ enum {
|
|||||||
IP6_CONFIG_CHANGED,
|
IP6_CONFIG_CHANGED,
|
||||||
REMOVED,
|
REMOVED,
|
||||||
RECHECK_AUTO_ACTIVATE,
|
RECHECK_AUTO_ACTIVATE,
|
||||||
|
RECHECK_ASSUME,
|
||||||
LAST_SIGNAL,
|
LAST_SIGNAL,
|
||||||
};
|
};
|
||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
@@ -237,6 +238,7 @@ typedef struct {
|
|||||||
gpointer act_source_func;
|
gpointer act_source_func;
|
||||||
guint act_source6_id;
|
guint act_source6_id;
|
||||||
gpointer act_source6_func;
|
gpointer act_source6_func;
|
||||||
|
guint recheck_assume_id;
|
||||||
|
|
||||||
/* Link stuff */
|
/* Link stuff */
|
||||||
guint link_connected_id;
|
guint link_connected_id;
|
||||||
@@ -2016,6 +2018,26 @@ nm_device_can_assume_connections (NMDevice *device)
|
|||||||
return !!NM_DEVICE_GET_CLASS (device)->update_connection;
|
return !!NM_DEVICE_GET_CLASS (device)->update_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
nm_device_emit_recheck_assume (gpointer self)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
priv->recheck_assume_id = 0;
|
||||||
|
if (!nm_device_get_act_request (self) && (priv->ip4_config || priv->ip6_config))
|
||||||
|
g_signal_emit (self, signals[RECHECK_ASSUME], 0);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_device_queue_recheck_assume (NMDevice *self)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if (nm_device_can_assume_connections (self) && !priv->recheck_assume_id)
|
||||||
|
priv->recheck_assume_id = g_idle_add (nm_device_emit_recheck_assume, self);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nm_device_emit_recheck_auto_activate (NMDevice *self)
|
nm_device_emit_recheck_auto_activate (NMDevice *self)
|
||||||
{
|
{
|
||||||
@@ -5243,6 +5265,8 @@ nm_device_set_ip4_config (NMDevice *self,
|
|||||||
nm_connection_add_setting (connection, s_ip4);
|
nm_connection_add_setting (connection, s_ip4);
|
||||||
g_object_thaw_notify (G_OBJECT (connection));
|
g_object_thaw_notify (G_OBJECT (connection));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nm_device_queue_recheck_assume (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reason)
|
if (reason)
|
||||||
@@ -5345,6 +5369,8 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||||||
nm_connection_add_setting (connection, s_ip6);
|
nm_connection_add_setting (connection, s_ip6);
|
||||||
g_object_thaw_notify (G_OBJECT (connection));
|
g_object_thaw_notify (G_OBJECT (connection));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nm_device_queue_recheck_assume (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reason)
|
if (reason)
|
||||||
@@ -5789,6 +5815,11 @@ dispose (GObject *object)
|
|||||||
|
|
||||||
g_clear_pointer (&priv->ip6_saved_properties, g_hash_table_unref);
|
g_clear_pointer (&priv->ip6_saved_properties, g_hash_table_unref);
|
||||||
|
|
||||||
|
if (priv->recheck_assume_id) {
|
||||||
|
g_source_remove (priv->recheck_assume_id);
|
||||||
|
priv->recheck_assume_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
link_disconnect_action_cancel (self);
|
link_disconnect_action_cancel (self);
|
||||||
|
|
||||||
if (priv->con_provider) {
|
if (priv->con_provider) {
|
||||||
@@ -6437,6 +6468,13 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||||||
0, NULL, NULL, NULL,
|
0, NULL, NULL, NULL,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals[RECHECK_ASSUME] =
|
||||||
|
g_signal_new (NM_DEVICE_RECHECK_ASSUME,
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0, NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
&dbus_glib_nm_device_object_info);
|
&dbus_glib_nm_device_object_info);
|
||||||
|
@@ -76,6 +76,7 @@
|
|||||||
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
|
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
|
||||||
#define NM_DEVICE_REMOVED "removed"
|
#define NM_DEVICE_REMOVED "removed"
|
||||||
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
||||||
|
#define NM_DEVICE_RECHECK_ASSUME "recheck-assume"
|
||||||
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
127
src/nm-manager.c
127
src/nm-manager.c
@@ -1586,6 +1586,89 @@ get_existing_connection (NMManager *manager, NMDevice *device)
|
|||||||
return added ? NM_CONNECTION (added) : NULL;
|
return added ? NM_CONNECTION (added) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
assume_connection (NMManager *self, NMDevice *device, NMConnection *connection)
|
||||||
|
{
|
||||||
|
NMActiveConnection *active, *master_ac;
|
||||||
|
NMAuthSubject *subject;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume connection",
|
||||||
|
nm_device_get_iface (device));
|
||||||
|
|
||||||
|
/* Move device to DISCONNECTED to activate the connection */
|
||||||
|
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) {
|
||||||
|
nm_device_state_changed (device,
|
||||||
|
NM_DEVICE_STATE_DISCONNECTED,
|
||||||
|
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||||
|
}
|
||||||
|
g_return_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED);
|
||||||
|
|
||||||
|
subject = nm_auth_subject_new_internal ();
|
||||||
|
active = _new_active_connection (self, connection, NULL, device, subject, &error);
|
||||||
|
g_object_unref (subject);
|
||||||
|
|
||||||
|
if (!active) {
|
||||||
|
nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s",
|
||||||
|
nm_connection_get_path (connection),
|
||||||
|
error ? error->code : -1,
|
||||||
|
error && error->message ? error->message : "(unknown)");
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the device is a slave or VLAN, find the master ActiveConnection */
|
||||||
|
master_ac = NULL;
|
||||||
|
if (find_master (self, connection, device, NULL, NULL, &master_ac, NULL) && master_ac)
|
||||||
|
nm_active_connection_set_master (active, master_ac);
|
||||||
|
|
||||||
|
nm_active_connection_set_assumed (active, TRUE);
|
||||||
|
nm_active_connection_export (active);
|
||||||
|
active_connection_add (self, active);
|
||||||
|
nm_device_queue_activation (device, NM_ACT_REQUEST (active));
|
||||||
|
g_object_unref (active);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
recheck_assume_connection (NMDevice *device, gpointer user_data)
|
||||||
|
{
|
||||||
|
NMManager *self = user_data;
|
||||||
|
NMConnection *connection;
|
||||||
|
gboolean was_unmanaged = FALSE;
|
||||||
|
|
||||||
|
if (manager_sleeping (self))
|
||||||
|
return;
|
||||||
|
if (nm_device_get_unmanaged_flag (device, NM_UNMANAGED_USER))
|
||||||
|
return;
|
||||||
|
|
||||||
|
connection = get_existing_connection (self, device);
|
||||||
|
if (!connection) {
|
||||||
|
nm_log_dbg (LOGD_DEVICE, "(%s): can't assume; no connection",
|
||||||
|
nm_device_get_iface (device));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
|
||||||
|
was_unmanaged = TRUE;
|
||||||
|
nm_device_state_changed (device,
|
||||||
|
NM_DEVICE_STATE_UNAVAILABLE,
|
||||||
|
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assume_connection (self, device, connection)) {
|
||||||
|
if (was_unmanaged) {
|
||||||
|
nm_device_state_changed (device,
|
||||||
|
NM_DEVICE_STATE_UNAVAILABLE,
|
||||||
|
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||||
|
nm_device_state_changed (device,
|
||||||
|
NM_DEVICE_STATE_UNMANAGED,
|
||||||
|
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add_device:
|
* add_device:
|
||||||
* @self: the #NMManager
|
* @self: the #NMManager
|
||||||
@@ -1708,42 +1791,14 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con)
|
|||||||
*/
|
*/
|
||||||
system_create_virtual_devices (self);
|
system_create_virtual_devices (self);
|
||||||
|
|
||||||
/* If the device has a connection it can assume, do that now */
|
/* If the device has a connection it can assume, do that now. If it's a
|
||||||
if (connection) {
|
* device that we might ever want to assume a connection on, then set that up.
|
||||||
NMActiveConnection *active;
|
*/
|
||||||
NMAuthSubject *subject;
|
if (connection)
|
||||||
GError *error = NULL;
|
assume_connection (self, device, connection);
|
||||||
|
if (generate_con) {
|
||||||
nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume connection",
|
g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME,
|
||||||
nm_device_get_iface (device));
|
G_CALLBACK (recheck_assume_connection), self);
|
||||||
|
|
||||||
/* Move device to DISCONNECTED to activate the connection */
|
|
||||||
nm_device_state_changed (device,
|
|
||||||
NM_DEVICE_STATE_DISCONNECTED,
|
|
||||||
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
|
||||||
|
|
||||||
subject = nm_auth_subject_new_internal ();
|
|
||||||
active = _new_active_connection (self, connection, NULL, device, subject, &error);
|
|
||||||
if (active) {
|
|
||||||
NMActiveConnection *master_ac = NULL;
|
|
||||||
|
|
||||||
/* If the device is a slave or VLAN, find the master ActiveConnection */
|
|
||||||
if (find_master (self, connection, device, NULL, NULL, &master_ac, NULL) && master_ac)
|
|
||||||
nm_active_connection_set_master (active, master_ac);
|
|
||||||
|
|
||||||
nm_active_connection_set_assumed (active, TRUE);
|
|
||||||
nm_active_connection_export (active);
|
|
||||||
active_connection_add (self, active);
|
|
||||||
nm_device_queue_activation (device, NM_ACT_REQUEST (active));
|
|
||||||
g_object_unref (active);
|
|
||||||
} else {
|
|
||||||
nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s",
|
|
||||||
nm_connection_get_path (connection),
|
|
||||||
error ? error->code : -1,
|
|
||||||
error && error->message ? error->message : "(unknown)");
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
g_object_unref (subject);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user