From eee0d242bb8ec56fa93367ba4b39d7086aac12e2 Mon Sep 17 00:00:00 2001 From: Shay Bar Date: Tue, 30 Jun 2020 17:23:46 +0300 Subject: [PATCH] hostapd: Add ability to disable HT/VHT/HE per BSS Add the ability to disable HT/VHT/HE for specific BSS from hostapd.conf. - Add disable_11ax boolean to hostapd_bss_config. - Change disable_11n and disable_11ac to bool in hostapd_bss_config. - Add configuration option to set these disable_11* parameters (which were previously used only automatically based on incompatible security parameters to disable HT/VHT). Signed-off-by: Shay Bar --- hostapd/config_file.c | 6 ++++++ hostapd/hostapd.conf | 9 +++++++++ src/ap/ap_config.c | 10 +++++----- src/ap/ap_config.h | 5 +++-- src/ap/beacon.c | 12 ++++++------ src/ap/ctrl_iface_ap.c | 5 +++-- src/ap/ieee802_11.c | 4 ++-- src/ap/ieee802_11_he.c | 2 ++ src/ap/neighbor_db.c | 2 +- 9 files changed, 37 insertions(+), 18 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index ce32f3c04..af2445563 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4569,6 +4569,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, } bss->mka_psk_set |= MKA_PSK_SET_CKN; #endif /* CONFIG_MACSEC */ + } else if (os_strcmp(buf, "disable_11n") == 0) { + bss->disable_11n = !!atoi(pos); + } else if (os_strcmp(buf, "disable_11ac") == 0) { + bss->disable_11ac = !!atoi(pos); + } else if (os_strcmp(buf, "disable_11ax") == 0) { + bss->disable_11ax = !!atoi(pos); } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index bf89fbcda..21f7b1e13 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -580,6 +580,9 @@ wmm_ac_vo_acm=0 # Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band. #ieee80211n=1 +# disable_11n: Boolean (0/1) to disable HT for a specific BSS +#disable_11n=0 + # ht_capab: HT capabilities (list of flags) # LDPC coding capability: [LDPC] = supported # Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary @@ -632,6 +635,9 @@ wmm_ac_vo_acm=0 # Note: hw_mode=a is used to specify that 5 GHz band is used with VHT. #ieee80211ac=1 +# disable_11ac: Boolean (0/1) to disable VHT for a specific BSS +#disable_11ac=0 + # vht_capab: VHT capabilities (list of flags) # # vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454] @@ -786,6 +792,9 @@ wmm_ac_vo_acm=0 # 1 = enabled #ieee80211ax=1 +# disable_11ax: Boolean (0/1) to disable HE for a specific BSS +#disable_11ax=0 + #he_su_beamformer: HE single user beamformer support # 0 = not supported (default) # 1 = supported diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 04535a163..f82468ac8 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -1229,7 +1229,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, if (full_config && conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " "allowed, disabling HT capabilities"); } @@ -1237,7 +1237,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #ifdef CONFIG_WEP if (full_config && conf->ieee80211n && bss->ssid.security_policy == SECURITY_STATIC_WEP) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " "allowed, disabling HT capabilities"); } @@ -1248,7 +1248,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " "requires CCMP/GCMP to be enabled, disabling HT " "capabilities"); @@ -1258,7 +1258,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #ifdef CONFIG_WEP if (full_config && conf->ieee80211ac && bss->ssid.security_policy == SECURITY_STATIC_WEP) { - bss->disable_11ac = 1; + bss->disable_11ac = true; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities"); } @@ -1269,7 +1269,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) { - bss->disable_11ac = 1; + bss->disable_11ac = true; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities"); } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index bada04c3e..b6937cbc0 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -531,8 +531,9 @@ struct hostapd_bss_config { #define TDLS_PROHIBIT BIT(0) #define TDLS_PROHIBIT_CHAN_SWITCH BIT(1) int tdls; - int disable_11n; - int disable_11ac; + bool disable_11n; + bool disable_11ac; + bool disable_11ax; /* IEEE 802.11v */ int time_advertisement; diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 6d5bb7106..807fe0ff9 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -458,7 +458,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, } #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { buflen += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + @@ -564,14 +564,14 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || - hapd->iconf->ieee80211ax) + (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)) pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); pos = hostapd_eid_fils_indic(hapd, pos, 0); pos = hostapd_get_rsnxe(hapd, pos, epos - pos); #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP); pos = hostapd_eid_he_operation(hapd, pos); pos = hostapd_eid_spatial_reuse(hapd, pos); @@ -1163,7 +1163,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { tail_len += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + @@ -1288,14 +1288,14 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || - hapd->iconf->ieee80211ax) + (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)) tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0); tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos); #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { tailpos = hostapd_eid_he_capab(hapd, tailpos, IEEE80211_MODE_AP); tailpos = hostapd_eid_he_operation(hapd, tailpos); diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index ef53a8254..b3d6d62e4 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -748,7 +748,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, iface->conf->ieee80211n && !hapd->conf->disable_11n, iface->conf->ieee80211ac && !hapd->conf->disable_11ac, - iface->conf->ieee80211ax, + iface->conf->ieee80211ax && + !hapd->conf->disable_11ax, iface->conf->beacon_int, hapd->conf->dtim_period); if (os_snprintf_error(buflen - len, ret)) @@ -756,7 +757,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, len += ret; #ifdef CONFIG_IEEE80211AX - if (iface->conf->ieee80211ax) { + if (iface->conf->ieee80211ax && !hapd->conf->disable_11ax) { ret = os_snprintf(buf + len, buflen - len, "he_oper_chwidth=%d\n" "he_oper_centr_freq_seg0_idx=%d\n" diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index de715a04c..114d1f574 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3254,7 +3254,7 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP, elems.he_capabilities, elems.he_capabilities_len); @@ -3870,7 +3870,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP); p = hostapd_eid_he_operation(hapd, p); p = hostapd_eid_spatial_reuse(hapd, p); diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 85b714090..dad68ac43 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -419,6 +419,7 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, size_t he_capab_len) { if (!he_capab || !hapd->iconf->ieee80211ax || + hapd->conf->disable_11ax || !check_valid_he_mcs(hapd, he_capab, opmode) || ieee80211_invalid_he_cap_size(he_capab, he_capab_len) || he_capab_len > sizeof(struct ieee80211_he_capabilities)) { @@ -448,6 +449,7 @@ u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta, const u8 *he_6ghz_capab) { if (!he_6ghz_capab || !hapd->iconf->ieee80211ax || + hapd->conf->disable_11ax || !is_6ghz_op_class(hapd->iconf->op_class)) { sta->flags &= ~WLAN_STA_6GHZ; os_free(sta->he_6ghz_capab); diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c index 01bf88623..2bbe31859 100644 --- a/src/ap/neighbor_db.c +++ b/src/ap/neighbor_db.c @@ -220,7 +220,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd) u16 capab = hostapd_own_capab_info(hapd); int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n; int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac; - int he = hapd->iconf->ieee80211ax; + int he = hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax; struct wpa_ssid_value ssid; u8 channel, op_class; u8 center_freq1_idx = 0, center_freq2_idx = 0;