}
+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,
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));
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);
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);
}
-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
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);
}
union wpa_event_data *data)
{
struct wpa_supplicant *wpa_s = ctx;
+ u16 reason_code = 0;
switch (event) {
case EVENT_AUTH:
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],
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);