]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EHT: Do not check HE PHY capability info reserved fields
authorJouni Malinen <quic_jouni@quicinc.com>
Mon, 16 May 2022 16:39:57 +0000 (19:39 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 16 May 2022 16:39:57 +0000 (19:39 +0300)
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>
src/ap/ieee802_11_eht.c

index dbbf9a60e414fe31ad2b9d1a2cf467265069fbed..0b7454f3ec5b2bed70d5ec710332e4d2c2091d9e 100644 (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;
+
+       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;