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:
Dan Winship
2014-05-28 10:18:34 -04:00
parent a9a25973cc
commit f229f4e201
4 changed files with 131 additions and 36 deletions

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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

View File

@@ -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);
} }
} }