summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2012-09-12 11:58:41 -0500
committerDan Williams <dcbw@redhat.com>2012-09-20 10:11:36 -0500
commitee22af6961bf6fb9e80d53c6eb87ac9a336a7a0f (patch)
tree569136862666e459dcdc48171c2236b9f9fc5435
parent80122cf9625949256a7cd0f398340458c8b606d3 (diff)
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.
-rw-r--r--src/nm-device-ethernet.c1
-rw-r--r--src/nm-device-wifi.c9
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c29
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.h3
4 files changed, 36 insertions, 6 deletions
diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c
index cbea9efd..648f364e 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 06abfa97..3c33be6d 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 cbe7032f..39d5ad3b 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 b99c0f26..73cf5b52 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);