From dbfb8e82ff69e6c7969b7cd23e53fd39b3e896e7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Dec 2013 11:22:23 +0200 Subject: [PATCH] Remove unnecessary EVENT_RX_ACTION This driver event was used separately for some Action frames, but all the driver wrappers converted to this from information that would have been enough to indicate an EVENT_RX_MGMT event. In addition, the received event was then converted back to a full IEEE 802.11 management frame for processing in most cases. This is unnecessary complexity, so get rid of the extra path and use EVENT_RX_MGMT for Action frames as well as other management frame subtypes. Signed-hostap: Jouni Malinen --- src/ap/drv_callbacks.c | 108 +++++++---------------- src/ap/ieee802_11.c | 24 +----- src/ap/wnm_ap.c | 30 ++++--- src/ap/wnm_ap.h | 3 +- src/drivers/driver.h | 56 +----------- src/drivers/driver_atheros.c | 24 ++---- src/drivers/driver_common.c | 1 - src/drivers/driver_nl80211.c | 29 ++----- wpa_supplicant/events.c | 163 +++++++++++++++++++---------------- wpa_supplicant/wnm_sta.c | 27 +++--- wpa_supplicant/wnm_sta.h | 5 +- 11 files changed, 173 insertions(+), 297 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 60d8268a1..9af964686 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -558,39 +558,48 @@ fail: static void hostapd_action_rx(struct hostapd_data *hapd, - struct rx_action *action) + struct rx_mgmt *drv_mgmt) { + struct ieee80211_mgmt *mgmt; struct sta_info *sta; + size_t plen __maybe_unused; + u16 fc; + + if (drv_mgmt->frame_len < 24 + 1) + return; + + plen = drv_mgmt->frame_len - 24 - 1; + + mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; + fc = le_to_host16(mgmt->frame_control); + if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION) + return; /* handled by the driver */ wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d", - action->category, (int) action->len); + mgmt->u.action.category, (int) plen); - sta = ap_get_sta(hapd, action->sa); + sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { wpa_printf(MSG_DEBUG, "%s: station not found", __func__); return; } #ifdef CONFIG_IEEE80211R - if (action->category == WLAN_ACTION_FT) { - wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d", - __func__, (int) action->len); - wpa_ft_action_rx(sta->wpa_sm, action->data, action->len); + if (mgmt->u.action.category == WLAN_ACTION_FT) { + const u8 *payload = drv_mgmt->frame + 24 + 1; + wpa_ft_action_rx(sta->wpa_sm, payload, plen); } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W - if (action->category == WLAN_ACTION_SA_QUERY && action->len >= 4) { - wpa_printf(MSG_DEBUG, "%s: SA_QUERY_ACTION length %d", - __func__, (int) action->len); - ieee802_11_sa_query_action(hapd, action->sa, - *(action->data + 1), - action->data + 2); + if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) { + ieee802_11_sa_query_action( + hapd, mgmt->sa, + mgmt->u.action.u.sa_query_resp.action, + mgmt->u.action.u.sa_query_resp.trans_id); } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WNM - if (action->category == WLAN_ACTION_WNM) { - wpa_printf(MSG_DEBUG, "%s: WNM_ACTION length %d", - __func__, (int) action->len); - ieee802_11_rx_wnm_action_ap(hapd, action); + if (mgmt->u.action.category == WLAN_ACTION_WNM) { + ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len); } #endif /* CONFIG_WNM */ } @@ -683,51 +692,6 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) } -static int hostapd_rx_action(struct hostapd_data *hapd, - struct rx_action *rx_action) -{ - struct rx_mgmt rx_mgmt; - u8 *buf; - struct ieee80211_hdr *hdr; - int ret; - - wpa_printf(MSG_DEBUG, "EVENT_RX_ACTION DA=" MACSTR " SA=" MACSTR - " BSSID=" MACSTR " category=%u", - MAC2STR(rx_action->da), MAC2STR(rx_action->sa), - MAC2STR(rx_action->bssid), rx_action->category); - wpa_hexdump(MSG_MSGDUMP, "Received action frame contents", - rx_action->data, rx_action->len); - - buf = os_zalloc(24 + 1 + rx_action->len); - if (buf == NULL) - return -1; - hdr = (struct ieee80211_hdr *) buf; - hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - if (rx_action->protected == 1) - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); - else if (rx_action->category == WLAN_ACTION_SA_QUERY) { - /* - * Assume frame was protected; it would have been dropped if - * not. - */ - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); - } - os_memcpy(hdr->addr1, rx_action->da, ETH_ALEN); - os_memcpy(hdr->addr2, rx_action->sa, ETH_ALEN); - os_memcpy(hdr->addr3, rx_action->bssid, ETH_ALEN); - buf[24] = rx_action->category; - os_memcpy(buf + 24 + 1, rx_action->data, rx_action->len); - os_memset(&rx_mgmt, 0, sizeof(rx_mgmt)); - rx_mgmt.frame = buf; - rx_mgmt.frame_len = 24 + 1 + rx_action->len; - ret = hostapd_mgmt_rx(hapd, &rx_mgmt); - os_free(buf); - - return ret; -} - - static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, u16 stype, int ok) { @@ -966,10 +930,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->rx_from_unknown.addr, data->rx_from_unknown.wds); break; - case EVENT_RX_MGMT: - hostapd_mgmt_rx(hapd, &data->rx_mgmt); - break; #endif /* NEED_AP_MLME */ + case EVENT_RX_MGMT: +#ifdef NEED_AP_MLME + if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0) + break; +#endif /* NEED_AP_MLME */ + hostapd_action_rx(hapd, &data->rx_mgmt); + break; case EVENT_RX_PROBE_REQ: if (data->rx_probe_req.sa == NULL || data->rx_probe_req.ie == NULL) @@ -1008,16 +976,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; hostapd_event_sta_low_ack(hapd, data->low_ack.addr); break; - case EVENT_RX_ACTION: - if (data->rx_action.da == NULL || data->rx_action.sa == NULL || - data->rx_action.bssid == NULL) - break; -#ifdef NEED_AP_MLME - if (hostapd_rx_action(hapd, &data->rx_action) > 0) - break; -#endif /* NEED_AP_MLME */ - hostapd_action_rx(hapd, &data->rx_action); - break; case EVENT_AUTH: hostapd_notif_auth(hapd, &data->auth); break; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 8fee2f960..1e3693d16 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1564,27 +1564,6 @@ static int robust_action_frame(u8 category) #endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WNM -static int hostapd_wnm_action(struct hostapd_data *hapd, struct sta_info *sta, - const struct ieee80211_mgmt *mgmt, size_t len) -{ - struct rx_action action; - if (len < IEEE80211_HDRLEN + 2) - return 0; - os_memset(&action, 0, sizeof(action)); - action.da = mgmt->da; - action.sa = mgmt->sa; - action.bssid = mgmt->bssid; - action.category = mgmt->u.action.category; - action.data = (const u8 *) &mgmt->u.action.u.wnm_sleep_req.action; - action.len = len - IEEE80211_HDRLEN - 1; - action.freq = hapd->iface->freq; - ieee802_11_rx_wnm_action_ap(hapd, &action); - return 1; -} -#endif /* CONFIG_WNM */ - - static int handle_action(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { @@ -1636,7 +1615,8 @@ static int handle_action(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WNM case WLAN_ACTION_WNM: - return hostapd_wnm_action(hapd, sta, mgmt, len); + ieee802_11_rx_wnm_action_ap(hapd, mgmt, len); + return 1; #endif /* CONFIG_WNM */ case WLAN_ACTION_PUBLIC: if (hapd->public_action_cb) { diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 417fd0e5c..825520464 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -367,30 +367,36 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd, - struct rx_action *action) + const struct ieee80211_mgmt *mgmt, size_t len) { - if (action->len < 1 || action->data == NULL) + u8 action; + const u8 *payload; + size_t plen; + + if (len < IEEE80211_HDRLEN + 2) return -1; - switch (action->data[0]) { + payload = &mgmt->u.action.category; + payload++; + action = *payload++; + plen = (((const u8 *) mgmt) + len) - payload; + + switch (action) { case WNM_BSS_TRANS_MGMT_QUERY: - ieee802_11_rx_bss_trans_mgmt_query(hapd, action->sa, - action->data + 1, - action->len - 1); + ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload, + plen); return 0; case WNM_BSS_TRANS_MGMT_RESP: - ieee802_11_rx_bss_trans_mgmt_resp(hapd, action->sa, - action->data + 1, - action->len - 1); + ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload, + plen); return 0; case WNM_SLEEP_MODE_REQ: - ieee802_11_rx_wnmsleep_req(hapd, action->sa, action->data + 1, - action->len - 1); + ieee802_11_rx_wnmsleep_req(hapd, mgmt->sa, payload, plen); return 0; } wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR, - action->data[0], MAC2STR(action->sa)); + action, MAC2STR(mgmt->sa)); return -1; } diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h index 78b1c6be6..eeaf5eca3 100644 --- a/src/ap/wnm_ap.h +++ b/src/ap/wnm_ap.h @@ -9,11 +9,10 @@ #ifndef WNM_AP_H #define WNM_AP_H -struct rx_action; struct sta_info; int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd, - struct rx_action *action); + const struct ieee80211_mgmt *mgmt, size_t len); int wnm_send_disassoc_imminent(struct hostapd_data *hapd, struct sta_info *sta, int disassoc_timer); int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd, diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 03a5b5705..3a5985136 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2216,7 +2216,7 @@ struct wpa_driver_ops { * * This command is used to request the driver to remain awake on the * specified channel for the specified duration and report received - * Action frames with EVENT_RX_ACTION events. Optionally, received + * Action frames with EVENT_RX_MGMT events. Optionally, received * Probe Request frames may also be requested to be reported by calling * probe_req_report(). These will be reported with EVENT_RX_PROBE_REQ. * @@ -3101,15 +3101,6 @@ enum wpa_event_type { */ EVENT_RX_MGMT, - /** - * EVENT_RX_ACTION - Action frame received - * - * This event is used to indicate when an Action frame has been - * received. Information about the received frame is included in - * union wpa_event_data::rx_action. - */ - EVENT_RX_ACTION, - /** * EVENT_REMAIN_ON_CHANNEL - Remain-on-channel duration started * @@ -3763,42 +3754,6 @@ union wpa_event_data { const u8 *frame; size_t frame_len; u32 datarate; - int ssi_signal; /* dBm */ - } rx_mgmt; - - /** - * struct rx_action - Data for EVENT_RX_ACTION events - */ - struct rx_action { - /** - * da - Destination address of the received Action frame - */ - const u8 *da; - - /** - * sa - Source address of the received Action frame - */ - const u8 *sa; - - /** - * bssid - Address 3 of the received Action frame - */ - const u8 *bssid; - - /** - * category - Action frame category - */ - u8 category; - - /** - * data - Action frame body after category field - */ - const u8 *data; - - /** - * len - Length of data in octets - */ - size_t len; /** * freq - Frequency (in MHz) on which the frame was received @@ -3809,14 +3764,7 @@ union wpa_event_data { * ssi_signal - Signal strength in dBm (or 0 if not available) */ int ssi_signal; - - /** - * protected - Whether frame was protected (PMF) - * - * 0 = unknown, 1 = yes, -1 = not - */ - int protected; - } rx_action; + } rx_mgmt; /** * struct remain_on_channel - Data for EVENT_REMAIN_ON_CHANNEL events diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c index 7d301f790..23a4e2b95 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -806,16 +806,10 @@ static void atheros_raw_recv_11r(void *ctx, const u8 *src_addr, const u8 *buf, drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 1); break; case WLAN_FC_STYPE_ACTION: - if (&mgmt->u.action.category > buf + len) - break; os_memset(&event, 0, sizeof(event)); - event.rx_action.da = mgmt->da; - event.rx_action.sa = mgmt->sa; - event.rx_action.bssid = mgmt->bssid; - event.rx_action.category = mgmt->u.action.category; - event.rx_action.data = &mgmt->u.action.category; - event.rx_action.len = buf + len - event.rx_action.data; - wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event); + event.rx_mgmt.frame = buf; + event.rx_mgmt.frame_len = len; + wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event); break; case WLAN_FC_STYPE_AUTH: if (len - IEEE80211_HDRLEN < sizeof(mgmt->u.auth)) @@ -954,16 +948,10 @@ static void atheros_raw_recv_11v(void *ctx, const u8 *src_addr, const u8 *buf, switch (stype) { case WLAN_FC_STYPE_ACTION: - if (&mgmt->u.action.category > buf + len) - break; os_memset(&event, 0, sizeof(event)); - event.rx_action.da = mgmt->da; - event.rx_action.sa = mgmt->sa; - event.rx_action.bssid = mgmt->bssid; - event.rx_action.category = mgmt->u.action.category; - event.rx_action.data = &mgmt->u.action.category; - event.rx_action.len = buf + len - event.rx_action.data; - wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event); + event.rx_mgmt.frame = buf; + event.rx_mgmt.frame_len = len; + wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event); break; default: break; diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 8a6b438a1..c07ec5719 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -49,7 +49,6 @@ const char * event_to_string(enum wpa_event_type event) E2S(TX_STATUS); E2S(RX_FROM_UNKNOWN); E2S(RX_MGMT); - E2S(RX_ACTION); E2S(REMAIN_ON_CHANNEL); E2S(CANCEL_REMAIN_ON_CHANNEL); E2S(MLME_RX); diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index b605ccaae..e1f586009 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1602,7 +1602,7 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv, wpa_printf(MSG_MSGDUMP, "nl80211: Frame event"); mgmt = (const struct ieee80211_mgmt *) frame; if (len < 24) { - wpa_printf(MSG_DEBUG, "nl80211: Too short action frame"); + wpa_printf(MSG_DEBUG, "nl80211: Too short management frame"); return; } @@ -1614,31 +1614,16 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv, os_memset(&event, 0, sizeof(event)); if (freq) { - event.rx_action.freq = nla_get_u32(freq); - rx_freq = drv->last_mgmt_freq = event.rx_action.freq; + event.rx_mgmt.freq = nla_get_u32(freq); + rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq; } wpa_printf(MSG_DEBUG, "nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u", rx_freq, ssi_signal, stype, (unsigned int) len); - if (stype == WLAN_FC_STYPE_ACTION) { - event.rx_action.da = mgmt->da; - event.rx_action.sa = mgmt->sa; - event.rx_action.bssid = mgmt->bssid; - event.rx_action.category = mgmt->u.action.category; - event.rx_action.data = &mgmt->u.action.category + 1; - event.rx_action.len = frame + len - event.rx_action.data; - event.rx_action.ssi_signal = ssi_signal; - if (host_to_le16(WLAN_FC_ISWEP) & mgmt->frame_control) - event.rx_action.protected = 1; - else - event.rx_action.protected = -1; - wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event); - } else { - event.rx_mgmt.frame = frame; - event.rx_mgmt.frame_len = len; - event.rx_mgmt.ssi_signal = ssi_signal; - wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); - } + event.rx_mgmt.frame = frame; + event.rx_mgmt.frame_len = len; + event.rx_mgmt.ssi_signal = ssi_signal; + wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index ae05a37e3..f9e2d19e9 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2707,6 +2707,87 @@ static void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s) } +static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, + size_t len, int freq) +{ + const u8 *payload; + size_t plen; + u8 category; + + if (len < IEEE80211_HDRLEN + 2) + return; + + payload = &mgmt->u.action.category; + category = *payload++; + plen = (((const u8 *) mgmt) + len) - payload; + + wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR + " Category=%u DataLen=%d freq=%d MHz", + MAC2STR(mgmt->sa), category, (int) plen, freq); + +#ifdef CONFIG_IEEE80211R + if (category == WLAN_ACTION_FT) { + ft_rx_action(wpa_s, payload, plen); + return; + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211W +#ifdef CONFIG_SME + if (category == WLAN_ACTION_SA_QUERY) { + sme_sa_query_rx(wpa_s, mgmt->sa, payload, plen); + return; + } +#endif /* CONFIG_SME */ +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_WNM + if (mgmt->u.action.category == WLAN_ACTION_WNM) { + ieee802_11_rx_wnm_action(wpa_s, mgmt, len); + return; + } +#endif /* CONFIG_WNM */ + +#ifdef CONFIG_GAS + if (mgmt->u.action.category == WLAN_ACTION_PUBLIC && + gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid, + payload, plen, freq) == 0) + return; +#endif /* CONFIG_GAS */ + +#ifdef CONFIG_TDLS + if (category == WLAN_ACTION_PUBLIC && plen >= 4 && + payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) { + wpa_dbg(wpa_s, MSG_DEBUG, + "TDLS: Received Discovery Response from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_TDLS */ + +#ifdef CONFIG_INTERWORKING + if (category == WLAN_ACTION_QOS && plen >= 1 && + payload[0] == QOS_QOS_MAP_CONFIG) { + const u8 *pos = payload + 1; + size_t qlen = plen - 1; + wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from " + MACSTR, MAC2STR(mgmt->sa)); + if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) == 0 && + qlen > 2 && pos[0] == WLAN_EID_QOS_MAP_SET && + pos[1] <= qlen - 2 && pos[1] >= 16) + wpas_qos_map_set(wpa_s, pos + 2, pos[1]); + return; + } +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_P2P + wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, + category, payload, plen, freq); +#endif /* CONFIG_P2P */ +} + + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { @@ -2956,7 +3037,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->ch_switch.cf2); break; #endif /* CONFIG_AP */ -#if defined(CONFIG_AP) || defined(CONFIG_IBSS_RSN) case EVENT_RX_MGMT: { u16 fc, stype; const struct ieee80211_mgmt *mgmt; @@ -2991,6 +3071,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; } #endif /* CONFIG_IBSS_RSN */ + + if (stype == WLAN_FC_STYPE_ACTION) { + wpas_event_rx_mgmt_action( + wpa_s, mgmt, data->rx_mgmt.frame_len, + data->rx_mgmt.freq); + break; + } + wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received " "management frame in non-AP mode"); break; @@ -3013,79 +3101,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #endif /* CONFIG_AP */ break; } -#endif /* CONFIG_AP || CONFIG_IBSS_RSN */ - case EVENT_RX_ACTION: - wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR - " Category=%u DataLen=%d freq=%d MHz", - MAC2STR(data->rx_action.sa), - data->rx_action.category, (int) data->rx_action.len, - data->rx_action.freq); -#ifdef CONFIG_IEEE80211R - if (data->rx_action.category == WLAN_ACTION_FT) { - ft_rx_action(wpa_s, data->rx_action.data, - data->rx_action.len); - break; - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W -#ifdef CONFIG_SME - if (data->rx_action.category == WLAN_ACTION_SA_QUERY) { - sme_sa_query_rx(wpa_s, data->rx_action.sa, - data->rx_action.data, - data->rx_action.len); - break; - } -#endif /* CONFIG_SME */ -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WNM - if (data->rx_action.category == WLAN_ACTION_WNM) { - ieee802_11_rx_wnm_action(wpa_s, &data->rx_action); - break; - } -#endif /* CONFIG_WNM */ -#ifdef CONFIG_GAS - if (data->rx_action.category == WLAN_ACTION_PUBLIC && - gas_query_rx(wpa_s->gas, data->rx_action.da, - data->rx_action.sa, data->rx_action.bssid, - data->rx_action.data, data->rx_action.len, - data->rx_action.freq) == 0) - break; -#endif /* CONFIG_GAS */ -#ifdef CONFIG_TDLS - if (data->rx_action.category == WLAN_ACTION_PUBLIC && - data->rx_action.len >= 4 && - data->rx_action.data[0] == WLAN_TDLS_DISCOVERY_RESPONSE) { - wpa_dbg(wpa_s, MSG_DEBUG, "TDLS: Received Discovery " - "Response from " MACSTR, - MAC2STR(data->rx_action.sa)); - break; - } -#endif /* CONFIG_TDLS */ -#ifdef CONFIG_INTERWORKING - if (data->rx_action.category == WLAN_ACTION_QOS && - data->rx_action.len >= 1 && - data->rx_action.data[0] == QOS_QOS_MAP_CONFIG) { - const u8 *pos = data->rx_action.data + 1; - size_t len = data->rx_action.len - 1; - wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from " - MACSTR, MAC2STR(data->rx_action.sa)); - if (os_memcmp(data->rx_action.sa, wpa_s->bssid, - ETH_ALEN) == 0 && - len > 2 && pos[0] == WLAN_EID_QOS_MAP_SET && - pos[1] <= len - 2 && pos[1] >= 16) - wpas_qos_map_set(wpa_s, pos + 2, pos[1]); - break; - } -#endif /* CONFIG_INTERWORKING */ -#ifdef CONFIG_P2P - wpas_p2p_rx_action(wpa_s, data->rx_action.da, - data->rx_action.sa, - data->rx_action.bssid, - data->rx_action.category, - data->rx_action.data, - data->rx_action.len, data->rx_action.freq); -#endif /* CONFIG_P2P */ - break; case EVENT_RX_PROBE_REQ: if (data->rx_probe_req.sa == NULL || data->rx_probe_req.ie == NULL) diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 1c6c715df..65b278383 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -181,7 +181,7 @@ static void wnm_sleep_mode_exit_success(struct wpa_supplicant *wpa_s, /* Install GTK/IGTK */ /* point to key data field */ - ptr = (u8 *) frm + 1 + 1 + 2; + ptr = (u8 *) frm + 1 + 2; end = ptr + key_len_total; wpa_hexdump_key(MSG_DEBUG, "WNM: Key Data", ptr, key_len_total); @@ -237,16 +237,16 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s, * Action [1] | Diaglog Token [1] | Key Data Len [2] | Key Data | * WNM-Sleep Mode IE | TFS Response IE */ - u8 *pos = (u8 *) frm; /* point to action field */ + u8 *pos = (u8 *) frm; /* point to payload after the action field */ u16 key_len_total = le_to_host16(*((u16 *)(frm+2))); struct wnm_sleep_element *wnmsleep_ie = NULL; /* multiple TFS Resp IE (assuming consecutive) */ u8 *tfsresp_ie_start = NULL; u8 *tfsresp_ie_end = NULL; - wpa_printf(MSG_DEBUG, "action=%d token = %d key_len_total = %d", - frm[0], frm[1], key_len_total); - pos += 4 + key_len_total; + wpa_printf(MSG_DEBUG, "WNM-Sleep Mode Response token=%u key_len_total=%d", + frm[0], key_len_total); + pos += 3 + key_len_total; if (pos > frm + len) { wpa_printf(MSG_INFO, "WNM: Too short frame for Key Data field"); return; @@ -752,22 +752,23 @@ int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s, void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s, - struct rx_action *action) + const struct ieee80211_mgmt *mgmt, size_t len) { const u8 *pos, *end; u8 act; - if (action->data == NULL || action->len == 0) + if (len < IEEE80211_HDRLEN + 2) return; - pos = action->data; - end = pos + action->len; + pos = &mgmt->u.action.category; + pos++; act = *pos++; + end = ((const u8 *) mgmt) + len; wpa_printf(MSG_DEBUG, "WNM: RX action %u from " MACSTR, - act, MAC2STR(action->sa)); + act, MAC2STR(mgmt->sa)); if (wpa_s->wpa_state < WPA_ASSOCIATED || - os_memcmp(action->sa, wpa_s->bssid, ETH_ALEN) != 0) { + os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WNM: Ignore unexpected WNM Action " "frame"); return; @@ -776,10 +777,10 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s, switch (act) { case WNM_BSS_TRANS_MGMT_REQ: ieee802_11_rx_bss_trans_mgmt_req(wpa_s, pos, end, - !(action->da[0] & 0x01)); + !(mgmt->da[0] & 0x01)); break; case WNM_SLEEP_MODE_RESP: - ieee802_11_rx_wnmsleep_resp(wpa_s, action->data, action->len); + ieee802_11_rx_wnmsleep_resp(wpa_s, pos, end - pos); break; default: wpa_printf(MSG_ERROR, "WNM: Unknown request"); diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h index 2933926c0..de8730156 100644 --- a/wpa_supplicant/wnm_sta.h +++ b/wpa_supplicant/wnm_sta.h @@ -9,9 +9,6 @@ #ifndef WNM_STA_H #define WNM_STA_H -struct rx_action; -struct wpa_supplicant; - struct tsf_info { u8 present; u8 tsf_offset[2]; @@ -78,7 +75,7 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, u8 action, u16 intval, struct wpabuf *tfs_req); void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s, - struct rx_action *action); + const struct ieee80211_mgmt *mgmt, size_t len); void wnm_scan_response(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res);