diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 53d1c25e7..d72c83b69 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1,6 +1,6 @@ /* * Driver interface definition - * Copyright (c) 2003-2010, Jouni Malinen + * Copyright (c) 2003-2012, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -3028,6 +3028,11 @@ union wpa_event_data { * ie_len - Length of ie buffer in octets */ size_t ie_len; + + /** + * locally_generated - Whether the frame was locally generated + */ + int locally_generated; } disassoc_info; /** @@ -3054,6 +3059,11 @@ union wpa_event_data { * ie_len - Length of ie buffer in octets */ size_t ie_len; + + /** + * locally_generated - Whether the frame was locally generated + */ + int locally_generated; } deauth_info; /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d407b0f5d..6af8cc9cb 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1,6 +1,6 @@ /* * Driver interaction with Linux nl80211/cfg80211 - * Copyright (c) 2002-2010, Jouni Malinen + * Copyright (c) 2002-2012, Jouni Malinen * Copyright (c) 2003-2004, Instant802 Networks, Inc. * Copyright (c) 2005-2006, Devicescape Software, Inc. * Copyright (c) 2007, Johannes Berg @@ -1151,7 +1151,8 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv, - struct nlattr *reason, struct nlattr *addr) + struct nlattr *reason, struct nlattr *addr, + struct nlattr *by_ap) { union wpa_event_data data; @@ -1169,6 +1170,7 @@ static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv, os_memset(&data, 0, sizeof(data)); if (reason) data.disassoc_info.reason_code = nla_get_u16(reason); + data.disassoc_info.locally_generated = by_ap == NULL; wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data); } @@ -1309,6 +1311,8 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv, reason_code = le_to_host16(mgmt->u.deauth.reason_code); if (type == EVENT_DISASSOC) { + event.disassoc_info.locally_generated = + !os_memcmp(mgmt->sa, drv->first_bss.addr, ETH_ALEN); event.disassoc_info.addr = bssid; event.disassoc_info.reason_code = reason_code; if (frame + len > mgmt->u.disassoc.variable) { @@ -1317,6 +1321,8 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv, mgmt->u.disassoc.variable; } } else { + event.deauth_info.locally_generated = + !os_memcmp(mgmt->sa, drv->first_bss.addr, ETH_ALEN); event.deauth_info.addr = bssid; event.deauth_info.reason_code = reason_code; if (frame + len > mgmt->u.deauth.variable) { @@ -2083,7 +2089,8 @@ static void do_process_drv_event(struct wpa_driver_nl80211_data *drv, break; case NL80211_CMD_DISCONNECT: mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE], - tb[NL80211_ATTR_MAC]); + tb[NL80211_ATTR_MAC], + tb[NL80211_ATTR_DISCONNECTED_BY_AP]); break; case NL80211_CMD_MICHAEL_MIC_FAILURE: mlme_event_michael_mic_failure(drv, tb); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 79136664f..c6538c9ed 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Driver event processing - * Copyright (c) 2003-2011, Jouni Malinen + * Copyright (c) 2003-2012, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1543,7 +1543,8 @@ static int disconnect_reason_recoverable(u16 reason_code) static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, - u16 reason_code) + u16 reason_code, + int locally_generated) { const u8 *bssid; int authenticating; @@ -1579,6 +1580,7 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, if (wpa_s->wpa_state == WPA_COMPLETED && wpa_s->current_ssid && wpa_s->current_ssid->mode == WPAS_MODE_INFRA && + !locally_generated && disconnect_reason_recoverable(reason_code)) { /* * It looks like the AP has dropped association with @@ -1991,6 +1993,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, { struct wpa_supplicant *wpa_s = ctx; u16 reason_code = 0; + int locally_generated = 0; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED && event != EVENT_INTERFACE_ENABLED && @@ -2032,8 +2035,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, case EVENT_DISASSOC: wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification"); if (data) { - wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u", - data->disassoc_info.reason_code); + wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", + data->disassoc_info.reason_code, + data->disassoc_info.locally_generated ? + " (locally generated)" : ""); if (data->disassoc_info.addr) wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR, MAC2STR(data->disassoc_info.addr)); @@ -2052,6 +2057,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #endif /* CONFIG_AP */ if (data) { reason_code = data->disassoc_info.reason_code; + locally_generated = + data->disassoc_info.locally_generated; wpa_hexdump(MSG_DEBUG, "Disassociation frame IE(s)", data->disassoc_info.ie, data->disassoc_info.ie_len); @@ -2071,8 +2078,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, "Deauthentication notification"); if (data) { reason_code = data->deauth_info.reason_code; - wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u", - data->deauth_info.reason_code); + locally_generated = + data->deauth_info.locally_generated; + wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", + data->deauth_info.reason_code, + data->deauth_info.locally_generated ? + " (locally generated)" : ""); if (data->deauth_info.addr) { wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR, @@ -2104,7 +2115,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; } #endif /* CONFIG_AP */ - wpa_supplicant_event_disassoc(wpa_s, reason_code); + wpa_supplicant_event_disassoc(wpa_s, reason_code, + locally_generated); break; case EVENT_MICHAEL_MIC_FAILURE: wpa_supplicant_event_michael_mic_failure(wpa_s, data);