From: Jouni Malinen Date: Mon, 16 May 2022 16:39:57 +0000 (+0300) Subject: EHT: Do not check HE PHY capability info reserved fields X-Git-Tag: hostap_2_11~1904 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1142b6e4155e025f64f881d7a41b60cb8e7a0b82;p=thirdparty%2Fhostap.git 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 --- diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c index dbbf9a60e..0b7454f3e 100644 --- a/src/ap/ieee802_11_eht.c +++ b/src/ap/ieee802_11_eht.c @@ -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; + + 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 ((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 | - HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G | - HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) == 0) + 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] & - (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G | - HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) - sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; + 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))) + 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;