From ee22af6961bf6fb9e80d53c6eb87ac9a336a7a0f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 12 Sep 2012 11:58:41 -0500 Subject: [PATCH] wifi: handle supplicant's deauthentication disconnect reason Recent versions of wpa_supplicant have a "DisconnectReason" property that, upon a deauthentication event, contains an IEEE 802.11 "Reason Code" for why the disconnect may have occurred. We may want to use this in the future, so add the infrastructure to pass it around to supplicant listeners. --- src/nm-device-ethernet.c | 1 + src/nm-device-wifi.c | 9 ++++-- .../nm-supplicant-interface.c | 29 +++++++++++++++++-- .../nm-supplicant-interface.h | 3 +- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index cbea9efde1..648f364e13 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -826,6 +826,7 @@ static void supplicant_iface_state_cb (NMSupplicantInterface *iface, guint32 new_state, guint32 old_state, + int disconnect_reason, gpointer user_data) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 06abfa97ea..3c33be6d2e 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -173,6 +173,7 @@ static void remove_supplicant_timeouts (NMDeviceWifi *self); static void supplicant_iface_state_cb (NMSupplicantInterface *iface, guint32 new_state, guint32 old_state, + int disconnect_reason, gpointer user_data); static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface, @@ -2298,7 +2299,10 @@ need_new_wpa_psk (NMDeviceWifi *self, } static gboolean -handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, guint32 new_state, guint32 old_state) +handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, + guint32 new_state, + guint32 old_state, + int disconnect_reason) { NMDevice *device = NM_DEVICE (self); NMActRequest *req; @@ -2342,6 +2346,7 @@ static void supplicant_iface_state_cb (NMSupplicantInterface *iface, guint32 new_state, guint32 old_state, + int disconnect_reason, gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); @@ -2416,7 +2421,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, * have more information from wpa_supplicant about why the * disconnect happened this is the best we can do. */ - if (handle_8021x_or_psk_auth_fail (self, new_state, old_state)) + if (handle_8021x_or_psk_auth_fail (self, new_state, old_state, disconnect_reason)) break; } diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index cbe7032f0a..39d5ad3bb7 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -92,6 +92,7 @@ typedef struct { char * object_path; guint32 state; + int disconnect_reason; NMCallStore * assoc_pcalls; NMCallStore * other_pcalls; @@ -468,7 +469,14 @@ set_state (NMSupplicantInterface *self, guint32 new_state) || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) priv->last_scan = time (NULL); - g_signal_emit (self, signals[STATE], 0, priv->state, old_state); + /* Disconnect reason is no longer relevant when not in the DISCONNECTED state */ + if (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED) + priv->disconnect_reason = 0; + + g_signal_emit (self, signals[STATE], 0, + priv->state, + old_state, + priv->disconnect_reason); } static void @@ -607,6 +615,21 @@ wpas_iface_properties_changed (DBusGProxy *proxy, value = g_hash_table_lookup (props, "Capabilities"); if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_MAP_OF_VARIANT)) parse_capabilities (self, g_value_get_boxed (value)); + + /* Disconnect reason is currently only given for deauthentication events, + * not disassociation; currently they are IEEE 802.11 "reason codes", + * defined by (IEEE 802.11-2007, 7.3.1.7, Table 7-22). Any locally caused + * deauthentication will be negative, while authentications caused by the + * AP will be positive. + */ + value = g_hash_table_lookup (props, "DisconnectReason"); + if (value && G_VALUE_HOLDS (value, G_TYPE_INT)) { + priv->disconnect_reason = g_value_get_int (value); + if (priv->disconnect_reason != 0) { + nm_log_warn (LOGD_SUPPLICANT, "Connection disconnected (reason %d)", + priv->disconnect_reason); + } + } } static void @@ -1539,8 +1562,8 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state), NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + _nm_marshal_VOID__UINT_UINT_INT, + G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INT); signals[REMOVED] = g_signal_new (NM_SUPPLICANT_INTERFACE_REMOVED, diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index b99c0f2690..73cf5b524e 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -76,7 +76,8 @@ typedef struct { /* change in the interface's state */ void (*state) (NMSupplicantInterface * iface, guint32 new_state, - guint32 old_state); + guint32 old_state, + int disconnect_reason); /* interface was removed by the supplicant */ void (*removed) (NMSupplicantInterface * iface);