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_emit_recheck_auto_activate (NMDevice *device);
|
||||
void nm_device_queue_recheck_assume (NMDevice *device);
|
||||
|
||||
#endif /* NM_DEVICE_PRIVATE_H */
|
||||
|
@@ -105,6 +105,7 @@ enum {
|
||||
IP6_CONFIG_CHANGED,
|
||||
REMOVED,
|
||||
RECHECK_AUTO_ACTIVATE,
|
||||
RECHECK_ASSUME,
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
@@ -237,6 +238,7 @@ typedef struct {
|
||||
gpointer act_source_func;
|
||||
guint act_source6_id;
|
||||
gpointer act_source6_func;
|
||||
guint recheck_assume_id;
|
||||
|
||||
/* Link stuff */
|
||||
guint link_connected_id;
|
||||
@@ -2016,6 +2018,26 @@ nm_device_can_assume_connections (NMDevice *device)
|
||||
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
|
||||
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);
|
||||
g_object_thaw_notify (G_OBJECT (connection));
|
||||
}
|
||||
|
||||
nm_device_queue_recheck_assume (self);
|
||||
}
|
||||
|
||||
if (reason)
|
||||
@@ -5345,6 +5369,8 @@ nm_device_set_ip6_config (NMDevice *self,
|
||||
nm_connection_add_setting (connection, s_ip6);
|
||||
g_object_thaw_notify (G_OBJECT (connection));
|
||||
}
|
||||
|
||||
nm_device_queue_recheck_assume (self);
|
||||
}
|
||||
|
||||
if (reason)
|
||||
@@ -5789,6 +5815,11 @@ dispose (GObject *object)
|
||||
|
||||
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);
|
||||
|
||||
if (priv->con_provider) {
|
||||
@@ -6437,6 +6468,13 @@ nm_device_class_init (NMDeviceClass *klass)
|
||||
0, NULL, NULL, NULL,
|
||||
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 (),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
&dbus_glib_nm_device_object_info);
|
||||
|
@@ -76,6 +76,7 @@
|
||||
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
|
||||
#define NM_DEVICE_REMOVED "removed"
|
||||
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
||||
#define NM_DEVICE_RECHECK_ASSUME "recheck-assume"
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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:
|
||||
* @self: the #NMManager
|
||||
@@ -1708,42 +1791,14 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con)
|
||||
*/
|
||||
system_create_virtual_devices (self);
|
||||
|
||||
/* If the device has a connection it can assume, do that now */
|
||||
if (connection) {
|
||||
NMActiveConnection *active;
|
||||
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 */
|
||||
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);
|
||||
/* If the device has a connection it can assume, do that now. If it's a
|
||||
* device that we might ever want to assume a connection on, then set that up.
|
||||
*/
|
||||
if (connection)
|
||||
assume_connection (self, device, connection);
|
||||
if (generate_con) {
|
||||
g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME,
|
||||
G_CALLBACK (recheck_assume_connection), self);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user