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_emit_recheck_auto_activate (NMDevice *device);
void nm_device_queue_recheck_assume (NMDevice *device);
#endif /* NM_DEVICE_PRIVATE_H */

View File

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

View File

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

View File

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