diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 5b614f605..fa49da454 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2140,6 +2140,12 @@ union wpa_event_data { * addr - Station address (for AP mode) */ const u8 *addr; + + /** + * reason_code - Reason Code (host byte order) used in + * Deauthentication frame + */ + u16 reason_code; } disassoc_info; /** @@ -2150,6 +2156,12 @@ union wpa_event_data { * addr - Station address (for AP mode) */ const u8 *addr; + + /** + * reason_code - Reason Code (host byte order) used in + * Deauthentication frame + */ + u16 reason_code; } deauth_info; /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index cbed98530..6ea2999c7 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -660,6 +660,37 @@ static void mlme_event_action_tx_status(struct wpa_driver_nl80211_data *drv, } +static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv, + enum wpa_event_type type, + const u8 *frame, size_t len) +{ + const struct ieee80211_mgmt *mgmt; + union wpa_event_data event; + const u8 *bssid = NULL; + u16 reason_code = 0; + + drv->associated = 0; + os_memset(&event, 0, sizeof(event)); + + mgmt = (const struct ieee80211_mgmt *) frame; + if (len >= 24) + bssid = mgmt->bssid; + /* Note: Same offset for Reason Code in both frame subtypes */ + if (len >= 24 + sizeof(mgmt->u.deauth)) + reason_code = le_to_host16(mgmt->u.deauth.reason_code); + + if (type == EVENT_DISASSOC) { + event.disassoc_info.addr = bssid; + event.disassoc_info.reason_code = reason_code; + } else { + event.deauth_info.addr = bssid; + event.deauth_info.reason_code = reason_code; + } + + wpa_supplicant_event(drv->ctx, type, &event); +} + + static void mlme_event(struct wpa_driver_nl80211_data *drv, enum nl80211_commands cmd, struct nlattr *frame, struct nlattr *addr, struct nlattr *timed_out, @@ -689,12 +720,12 @@ static void mlme_event(struct wpa_driver_nl80211_data *drv, mlme_event_assoc(drv, nla_data(frame), nla_len(frame)); break; case NL80211_CMD_DEAUTHENTICATE: - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DEAUTH, NULL); + mlme_event_deauth_disassoc(drv, EVENT_DEAUTH, + nla_data(frame), nla_len(frame)); break; case NL80211_CMD_DISASSOCIATE: - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); + mlme_event_deauth_disassoc(drv, EVENT_DISASSOC, + nla_data(frame), nla_len(frame)); break; case NL80211_CMD_ACTION: mlme_event_action(drv, freq, nla_data(frame), nla_len(frame)); @@ -895,6 +926,7 @@ static int process_event(struct nl_msg *msg, void *arg) struct wpa_driver_nl80211_data *drv = arg; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *tb[NL80211_ATTR_MAX + 1]; + union wpa_event_data data; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); @@ -968,7 +1000,11 @@ static int process_event(struct nl_msg *msg, void *arg) break; } drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); + os_memset(&data, 0, sizeof(data)); + if (tb[NL80211_ATTR_REASON_CODE]) + data.disassoc_info.reason_code = + nla_get_u16(tb[NL80211_ATTR_REASON_CODE]); + wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data); 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 67a164afd..2f3a303c4 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1264,7 +1264,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, } -static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s) +static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, + u16 reason_code) { const u8 *bssid; #ifdef CONFIG_SME @@ -1298,9 +1299,11 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s) bssid = wpa_s->pending_bssid; wpa_blacklist_add(wpa_s, bssid); wpa_sm_notify_disassoc(wpa_s->wpa); - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "- Disconnect event - " - "remove keys"); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR + " reason=%d", + MAC2STR(bssid), reason_code); if (wpa_supplicant_dynamic_keys(wpa_s)) { + wpa_printf(MSG_DEBUG, "Disconnect event - remove keys"); wpa_s->keys_cleared = 0; wpa_clear_keys(wpa_s, wpa_s->bssid); } @@ -1578,6 +1581,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { struct wpa_supplicant *wpa_s = ctx; + u16 reason_code = 0; switch (event) { case EVENT_AUTH: @@ -1595,12 +1599,17 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; } #endif /* CONFIG_AP */ + if (data) + reason_code = data->deauth_info.reason_code; if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) sme_event_disassoc(wpa_s, data); /* fall through */ case EVENT_DEAUTH: - if (event == EVENT_DEAUTH) + if (event == EVENT_DEAUTH) { wpa_printf(MSG_DEBUG, "Deauthentication notification"); + if (data) + reason_code = data->deauth_info.reason_code; + } #ifdef CONFIG_AP if (wpa_s->ap_iface && data) { hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], @@ -1608,7 +1617,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; } #endif /* CONFIG_AP */ - wpa_supplicant_event_disassoc(wpa_s); + wpa_supplicant_event_disassoc(wpa_s, reason_code); break; case EVENT_MICHAEL_MIC_FAILURE: wpa_supplicant_event_michael_mic_failure(wpa_s, data);