EHT: Do not check HE PHY capability info reserved fields

Only use the bandwidth bits that are applicable for the current
operating band. This avoids use of reserved bits when determining the
length of the Support EHT-MCS And NSS Set field length.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-05-16 19:39:57 +03:00 committed by Jouni Malinen
parent 7173992b96
commit 1142b6e415

View file

@ -41,25 +41,41 @@ static u16 ieee80211_eht_ppet_size(u16 ppe_thres_hdr, const u8 *phy_cap_info)
}
static u8 ieee80211_eht_mcs_set_size(const u8 *he_phy_cap,
static u8 ieee80211_eht_mcs_set_size(enum hostapd_hw_mode mode, u8 opclass,
const u8 *he_phy_cap,
const u8 *eht_phy_cap)
{
u8 sz = EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
bool band24, band5, band6;
if ((he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
(HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
band24 = mode == HOSTAPD_MODE_IEEE80211B ||
mode == HOSTAPD_MODE_IEEE80211G ||
mode == NUM_HOSTAPD_MODES;
band5 = mode == HOSTAPD_MODE_IEEE80211A ||
mode == NUM_HOSTAPD_MODES;
band6 = is_6ghz_op_class(opclass);
if (band24 &&
(he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G) == 0)
return EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY;
if (band5 &&
(he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
(HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) == 0)
return EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY;
if (he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
if (band5 &&
(he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
(HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G))
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)))
sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
if (eht_phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)
if (band6 &&
(eht_phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK))
sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
return sz;
@ -81,7 +97,8 @@ size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
if (!eht_cap->eht_supported)
return 0;
len += ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
len += ieee80211_eht_mcs_set_size(mode->mode, hapd->iconf->op_class,
mode->he_capab[opmode].phy_cap,
eht_cap->phy_cap);
len += ieee80211_eht_ppet_size(WPA_GET_LE16(&eht_cap->ppet[0]),
eht_cap->phy_cap);
@ -133,7 +150,9 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid,
pos = cap->optional;
mcs_nss_len = ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
mcs_nss_len = ieee80211_eht_mcs_set_size(mode->mode,
hapd->iconf->op_class,
mode->he_capab[opmode].phy_cap,
eht_cap->phy_cap);
if (mcs_nss_len) {
os_memcpy(pos, eht_cap->mcs, mcs_nss_len);
@ -257,7 +276,8 @@ static bool check_valid_eht_mcs(struct hostapd_data *hapd,
capab = (const struct ieee80211_eht_capabilities *) sta_eht_capab;
sta_mcs = capab->optional;
if (ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
if (ieee80211_eht_mcs_set_size(mode->mode, hapd->iconf->op_class,
mode->he_capab[opmode].phy_cap,
mode->eht_capab[opmode].phy_cap) ==
EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY)
return check_valid_eht_mcs_nss(
@ -277,7 +297,9 @@ static bool check_valid_eht_mcs(struct hostapd_data *hapd,
}
static bool ieee80211_invalid_eht_cap_size(const u8 *he_cap, const u8 *eht_cap,
static bool ieee80211_invalid_eht_cap_size(enum hostapd_hw_mode mode,
u8 opclass,
const u8 *he_cap, const u8 *eht_cap,
size_t len)
{
const struct ieee80211_he_capabilities *he_capab;
@ -293,7 +315,8 @@ static bool ieee80211_invalid_eht_cap_size(const u8 *he_cap, const u8 *eht_cap,
if (len < cap_len)
return true;
cap_len += ieee80211_eht_mcs_set_size(he_phy_cap, cap->phy_cap);
cap_len += ieee80211_eht_mcs_set_size(mode, opclass, he_phy_cap,
cap->phy_cap);
if (len < cap_len)
return true;
@ -310,10 +333,14 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *he_capab, size_t he_capab_len,
const u8 *eht_capab, size_t eht_capab_len)
{
struct hostapd_hw_modes *c_mode = hapd->iface->current_mode;
enum hostapd_hw_mode mode = c_mode ? c_mode->mode : NUM_HOSTAPD_MODES;
if (!hapd->iconf->ieee80211be || hapd->conf->disable_11be ||
!he_capab || he_capab_len < IEEE80211_HE_CAPAB_MIN_LEN ||
!eht_capab ||
ieee80211_invalid_eht_cap_size(he_capab, eht_capab,
ieee80211_invalid_eht_cap_size(mode, hapd->iconf->op_class,
he_capab, eht_capab,
eht_capab_len) ||
!check_valid_eht_mcs(hapd, eht_capab, opmode)) {
sta->flags &= ~WLAN_STA_EHT;