From: Jouni Malinen Date: Tue, 9 Dec 2025 10:06:12 +0000 (+0200) Subject: Fix the check for valid supported VHT-MCS values X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26a88e04d0c65bcd9532bb7a062443c8ce85bdfa;p=thirdparty%2Fhostap.git Fix the check for valid supported VHT-MCS values 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 --- diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index e7a7f8696..229cad1f9 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -21,28 +21,35 @@ #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);