diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c index f54942178..3f299f3ee 100644 --- a/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c @@ -211,7 +211,8 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd, struct ieee80211_2040_intol_chan_report *ic_report; int is_ht_allowed = 1; int i; - const u8 *data = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 1; + const u8 *start = (const u8 *) mgmt; + const u8 *data = start + IEEE80211_HDRLEN + 2; hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "hostapd_public_action - action=%d", @@ -220,14 +221,22 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd, if (!(iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) return; - if (len < IEEE80211_HDRLEN + 1) + if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) return; - data++; - bc_ie = (struct ieee80211_2040_bss_coex_ie *) &data[0]; - ic_report = (struct ieee80211_2040_intol_chan_report *) - (&data[0] + sizeof(*bc_ie)); + bc_ie = (struct ieee80211_2040_bss_coex_ie *) data; + if (bc_ie->element_id != WLAN_EID_20_40_BSS_COEXISTENCE || + bc_ie->length < 1) { + wpa_printf(MSG_DEBUG, "Unexpected IE (%u,%u) in coex report", + bc_ie->element_id, bc_ie->length); + return; + } + if (len < IEEE80211_HDRLEN + 2 + 2 + bc_ie->length) + return; + data += 2 + bc_ie->length; + wpa_printf(MSG_DEBUG, "20/40 BSS Coexistence Information field: 0x%x", + bc_ie->coex_param); if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, @@ -244,22 +253,34 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd, is_ht_allowed = 0; } - if (ic_report && - (ic_report->element_id == WLAN_EID_20_40_BSS_INTOLERANT)) { + if (start + len - data >= 3 && + data[0] == WLAN_EID_20_40_BSS_INTOLERANT && data[1] >= 1) { + u8 ielen = data[1]; + + if (ielen > start + len - data - 2) + return; + ic_report = (struct ieee80211_2040_intol_chan_report *) data; + wpa_printf(MSG_DEBUG, + "20/40 BSS Intolerant Channel Report: Operating Class %u", + ic_report->op_class); + /* Go through the channel report to find any BSS there in the * affected channel range */ - for (i = 0; i < ic_report->length - 1; i++) { - if (is_40_allowed(iface, ic_report->variable[i])) + for (i = 0; i < ielen - 1; i++) { + u8 chan = ic_report->variable[i]; + + if (is_40_allowed(iface, chan)) continue; hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "20_40_INTOLERANT channel %d reported", - ic_report->variable[i]); + chan); is_ht_allowed = 0; - break; } } + wpa_printf(MSG_DEBUG, "is_ht_allowed=%d num_sta_ht40_intolerant=%d", + is_ht_allowed, iface->num_sta_ht40_intolerant); if (!is_ht_allowed && (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { @@ -279,6 +300,9 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd, NULL); eloop_register_timeout(delay_time, 0, ap_ht2040_timeout, hapd->iface, NULL); + wpa_printf(MSG_DEBUG, + "Reschedule HT 20/40 timeout to occur in %u seconds", + delay_time); } } }