diff --git a/include/NetworkManager.h b/include/NetworkManager.h index 91076c203..c8d5074a1 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -362,6 +362,9 @@ typedef enum { /* The device's existing connection was assumed */ NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, + /* The supplicant is now available */ + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + /* Unused */ NM_DEVICE_STATE_REASON_LAST = 0xFFFF } NMDeviceStateReason; diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index 3dbb6e229..a8362acba 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -380,6 +380,11 @@ The device's existing connection was assumed. + + + + The 802.1x supplicant is now available. + diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index bb94c35b8..508ff6a44 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -38,8 +38,6 @@ typedef struct { guint32 ip_method; char *device; - guint state_to_disconnected_id; - /* PPP stats */ guint32 in_bytes; guint32 out_bytes; @@ -415,15 +413,6 @@ real_get_generic_capabilities (NMDevice *dev) return NM_DEVICE_CAP_NM_SUPPORTED; } -static gboolean -unavailable_to_disconnected (gpointer user_data) -{ - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - return FALSE; -} - static void device_state_changed (NMDeviceInterface *device, NMDeviceState new_state, @@ -434,19 +423,6 @@ device_state_changed (NMDeviceInterface *device, NMModem *self = NM_MODEM (user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - /* Remove any previous delayed transition to disconnected */ - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - - /* If transitioning to UNAVAILBLE and we have a carrier, transition to - * DISCONNECTED because the device is ready to use. Otherwise the carrier-on - * handler will handle the transition to DISCONNECTED when the carrier is detected. - */ - if (new_state == NM_DEVICE_STATE_UNAVAILABLE) - priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, user_data); - /* Make sure we don't leave the serial device open */ switch (new_state) { case NM_DEVICE_STATE_NEED_AUTH: @@ -601,11 +577,6 @@ finalize (GObject *object) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - if (priv->proxy) g_object_unref (priv->proxy); diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c index d50f4c3a7..0ced44fd2 100644 --- a/src/nm-device-bt.c +++ b/src/nm-device-bt.c @@ -51,7 +51,6 @@ typedef struct { char *name; guint32 capabilities; - guint state_to_disconnected_id; DBusGProxy *type_proxy; NMPPPManager *ppp_manager; @@ -715,55 +714,6 @@ nm_device_bt_init (NMDeviceBt *self) { } -static gboolean -unavailable_to_disconnected (gpointer user_data) -{ - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - return FALSE; -} - -static void -device_state_changed (NMDeviceInterface *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMDeviceBt *self = NM_DEVICE_BT (user_data); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - - /* Remove any previous delayed transition to disconnected */ - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - - /* Transition to DISCONNECTED from an idle handler */ - if (new_state == NM_DEVICE_STATE_UNAVAILABLE) - priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self); -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - - object = G_OBJECT_CLASS (nm_device_bt_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - g_signal_connect (NM_DEVICE (object), "state-changed", - G_CALLBACK (device_state_changed), NM_DEVICE_BT (object)); - - return object; -} - static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) @@ -822,11 +772,6 @@ finalize (GObject *object) g_free (priv->bdaddr); g_free (priv->name); - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object); } @@ -838,7 +783,6 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceBtPrivate)); - object_class->constructor = constructor; object_class->get_property = get_property; object_class->set_property = set_property; object_class->finalize = finalize; diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index b1b01204f..2d2e8fbbc 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -106,7 +106,6 @@ typedef struct { struct ether_addr hw_addr; gboolean carrier; guint32 ifindex; - guint state_to_disconnected_id; NMNetlinkMonitor * monitor; gulong link_connected_id; @@ -242,39 +241,6 @@ carrier_off (NMNetlinkMonitor *monitor, } } -static gboolean -unavailable_to_disconnected (gpointer user_data) -{ - nm_device_state_changed (NM_DEVICE (user_data), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); - return FALSE; -} - -static void -device_state_changed (NMDeviceInterface *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - /* Remove any previous delayed transition to disconnected */ - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - - /* If transitioning to UNAVAILBLE and we have a carrier, transition to - * DISCONNECTED because the device is ready to use. Otherwise the carrier-on - * handler will handle the transition to DISCONNECTED when the carrier is detected. - */ - if ((new_state == NM_DEVICE_STATE_UNAVAILABLE) && priv->carrier) { - priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self); - return; - } -} - static GObject* constructor (GType type, guint n_construct_params, @@ -319,8 +285,6 @@ constructor (GType type, priv->carrier = TRUE; } - g_signal_connect (self, "state-changed", G_CALLBACK (device_state_changed), self); - return object; } @@ -1698,11 +1662,6 @@ dispose (GObject *object) priv->monitor = NULL; } - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object); } diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index eefb1366a..b4cdc4448 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -156,7 +156,6 @@ struct _NMDeviceWifiPrivate { NMAccessPoint * current_ap; guint32 rate; gboolean enabled; /* rfkilled or not */ - guint state_to_disconnected_id; glong scheduled_scan_time; guint8 scan_interval; /* seconds */ @@ -2249,6 +2248,15 @@ supplicant_iface_state_cb_handler (gpointer user_data) /* Request a scan to get latest results */ cancel_pending_scan (self); request_wireless_scan (self); + + /* If the interface can now be activated because the supplicant is now + * available, transition to DISCONNECTED. + */ + if ( (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_UNAVAILABLE) + && nm_device_can_activate (NM_DEVICE (self))) { + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE); + } } else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { cleanup_association_attempt (self, FALSE); supplicant_interface_release (self); @@ -3224,15 +3232,6 @@ spec_match_list (NMDevice *device, const GSList *specs) return matched; } -static gboolean -unavailable_to_disconnected (gpointer user_data) -{ - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - return FALSE; -} - static void device_state_changed (NMDevice *device, NMDeviceState new_state, @@ -3244,12 +3243,6 @@ device_state_changed (NMDevice *device, NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); gboolean clear_aps = FALSE; - /* Remove any previous delayed transition to disconnected */ - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { /* Clean up the supplicant interface because in these states the * device cannot be used. @@ -3276,9 +3269,6 @@ device_state_changed (NMDevice *device, if (!priv->supplicant.iface) supplicant_interface_acquire (self); - - if (priv->supplicant.iface) - priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self); } clear_aps = TRUE; break; @@ -3459,11 +3449,6 @@ dispose (GObject *object) set_current_ap (self, NULL); remove_all_aps (self); - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); } diff --git a/src/nm-device.c b/src/nm-device.c index f2367163c..d5a1b55c1 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -77,6 +77,7 @@ typedef struct { NMDeviceState state; guint failed_to_disconnected_id; + guint unavailable_to_disconnected_id; char * udi; char * path; @@ -1960,6 +1961,21 @@ clear_act_request (NMDevice *self) priv->act_request = NULL; } +static void +delayed_transitions_clear (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->failed_to_disconnected_id) { + g_source_remove (priv->failed_to_disconnected_id); + priv->failed_to_disconnected_id = 0; + } + if (priv->unavailable_to_disconnected_id) { + g_source_remove (priv->unavailable_to_disconnected_id); + priv->unavailable_to_disconnected_id = 0; + } +} + /* * nm_device_deactivate_quickly * @@ -1981,10 +1997,8 @@ nm_device_deactivate_quickly (NMDevice *self) activation_source_clear (self, TRUE, AF_INET); activation_source_clear (self, TRUE, AF_INET6); - if (priv->failed_to_disconnected_id) { - g_source_remove (priv->failed_to_disconnected_id); - priv->failed_to_disconnected_id = 0; - } + /* Clear any delayed transitions */ + delayed_transitions_clear (self); /* Stop any ongoing DHCP transaction on this device */ if (nm_device_get_act_request (self)) { @@ -2723,10 +2737,8 @@ dispose (GObject *object) } } - if (priv->failed_to_disconnected_id) { - g_source_remove (priv->failed_to_disconnected_id); - priv->failed_to_disconnected_id = 0; - } + /* Clear any delayed transitions */ + delayed_transitions_clear (self); if (priv->managed && take_down) { NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; @@ -2985,6 +2997,17 @@ failed_to_disconnected (gpointer user_data) return FALSE; } +static gboolean +unavailable_to_disconnected (gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->unavailable_to_disconnected_id = 0; + nm_device_state_changed (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); + return FALSE; +} + void nm_device_state_changed (NMDevice *device, NMDeviceState state, @@ -3006,10 +3029,8 @@ nm_device_state_changed (NMDevice *device, nm_info ("(%s): device state change: %d -> %d (reason %d)", nm_device_get_iface (device), old_state, state, reason); - if (priv->failed_to_disconnected_id) { - g_source_remove (priv->failed_to_disconnected_id); - priv->failed_to_disconnected_id = 0; - } + /* Clear any delayed transitions */ + delayed_transitions_clear (device); /* Cache the activation request for the dispatcher */ req = priv->act_request ? g_object_ref (priv->act_request) : NULL; @@ -3049,12 +3070,26 @@ nm_device_state_changed (NMDevice *device, /* Post-process the event after internal notification */ switch (state) { + case NM_DEVICE_STATE_UNAVAILABLE: + /* If the device can activate now (ie, it's got a carrier, the supplicant + * is active, or whatever) schedule a delayed transition to DISCONNECTED + * to get things rolling. The device can't transition immediately becuase + * we can't change states again from the state handler for a variety of + * reasons. + */ + if (nm_device_can_activate (device)) + priv->unavailable_to_disconnected_id = g_idle_add (unavailable_to_disconnected, device); + break; case NM_DEVICE_STATE_ACTIVATED: nm_info ("Activation (%s) successful, device activated.", nm_device_get_iface (device)); nm_utils_call_dispatcher ("up", nm_act_request_get_connection (req), device, NULL); break; case NM_DEVICE_STATE_FAILED: nm_info ("Activation (%s) failed.", nm_device_get_iface (device)); + /* Schedule the transition to DISCONNECTED. The device can't transition + * immediately becuase we can't change states again from the state + * handler for a variety of reasons. + */ priv->failed_to_disconnected_id = g_idle_add (failed_to_disconnected, device); break; default: