]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Fix the check for valid supported VHT-MCS values
authorJouni Malinen <jouni.malinen@oss.qualcomm.com>
Tue, 9 Dec 2025 10:06:12 +0000 (12:06 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 9 Dec 2025 10:39:15 +0000 (12:39 +0200)
These 16-bit fields consist of eight 2-bit fields and the comparison
here was supposed to check whether each such 2-bit field is set to 3
(i.e., not supported). Masking was shifted, but the comparison against 3
did not have matching shift. Fix this by shifting the field to the two
LSBs for the comparison.

In addition, the special vendor_vht=1 case on 2.4 GHz was not taken into
account in check_valid_vht_mcs(). It needs to use the 5 GHz mode
hardware capability similarly to the way hostapd_eid_vht_capabilities()
works. Fix this by using a shared helper function for both cases.

Fixes: d988ff76bfa9 ("hostapd: Disable VHT caps for STAs when no valid VHT MCS found")
Signed-off-by: Jouni Malinen <jouni.malinen@oss.qualcomm.com>
src/ap/ieee802_11_vht.c

index e7a7f8696a0850b940b143b716525a910fa5497b..229cad1f9c971051b4f623c1dfccee46253d9642 100644 (file)
 #include "dfs.h"
 
 
-u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
+static struct hostapd_hw_modes *
+mode_for_vht_capab(struct hostapd_data *hapd, struct hostapd_hw_modes *mode)
 {
-       struct ieee80211_vht_capabilities *cap;
-       struct hostapd_hw_modes *mode = hapd->iface->current_mode;
-       u8 *pos = eid;
-
-       if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
-               return eid;
-
        if (mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->conf->vendor_vht &&
            mode->vht_capab == 0 && hapd->iface->hw_features) {
                int i;
 
                for (i = 0; i < hapd->iface->num_hw_features; i++) {
                        if (hapd->iface->hw_features[i].mode ==
-                           HOSTAPD_MODE_IEEE80211A) {
-                               mode = &hapd->iface->hw_features[i];
-                               break;
-                       }
+                           HOSTAPD_MODE_IEEE80211A)
+                               return &hapd->iface->hw_features[i];
                }
        }
 
+       return mode;
+}
+
+
+u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
+{
+       struct ieee80211_vht_capabilities *cap;
+       struct hostapd_hw_modes *mode = hapd->iface->current_mode;
+       u8 *pos = eid;
+
+       if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
+               return eid;
+
+       mode = mode_for_vht_capab(hapd, mode);
+
        *pos++ = WLAN_EID_VHT_CAP;
        *pos++ = sizeof(*cap);
 
@@ -143,9 +150,10 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
 }
 
 
-static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
+static int check_valid_vht_mcs(struct hostapd_data *hapd,
                               const u8 *sta_vht_capab)
 {
+       struct hostapd_hw_modes *mode = hapd->iface->current_mode;
        const struct ieee80211_vht_capabilities *vht_cap;
        struct ieee80211_vht_capabilities ap_vht_cap;
        u16 sta_rx_mcs_set, ap_tx_mcs_set;
@@ -153,6 +161,7 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
 
        if (!mode)
                return 1;
+       mode = mode_for_vht_capab(hapd, mode);
 
        /*
         * Disable VHT caps for STAs for which there is not even a single
@@ -169,10 +178,10 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
        ap_tx_mcs_set = le_to_host16(ap_vht_cap.vht_supported_mcs_set.tx_map);
 
        for (i = 0; i < VHT_RX_NSS_MAX_STREAMS; i++) {
-               if ((ap_tx_mcs_set & (0x3 << (i * 2))) == 3)
+               if (((ap_tx_mcs_set >> (i * 2)) & 0x3) == 3)
                        continue;
 
-               if ((sta_rx_mcs_set & (0x3 << (i * 2))) == 3)
+               if (((sta_rx_mcs_set >> (i * 2)) & 0x3) == 3)
                        continue;
 
                return 1;
@@ -190,7 +199,7 @@ u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
        /* Disable VHT caps for STAs associated to no-VHT BSSes. */
        if (!vht_capab || !(sta->flags & WLAN_STA_WMM) ||
            !hapd->iconf->ieee80211ac || hapd->conf->disable_11ac ||
-           !check_valid_vht_mcs(hapd->iface->current_mode, vht_capab) ||
+           !check_valid_vht_mcs(hapd, vht_capab) ||
            !(sta->flags & WLAN_STA_HT)) {
                sta->flags &= ~WLAN_STA_VHT;
                os_free(sta->vht_capabilities);