diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 656aacc7d..ca8c705ea 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -38,6 +38,7 @@ #endif /* CONFIG_DPP */ #include "common/wpa_ctrl.h" #include "common/ptksa_cache.h" +#include "common/hw_features_common.h" #include "crypto/tls.h" #include "drivers/driver.h" #include "eapol_auth/eapol_auth_sm.h" @@ -2431,8 +2432,11 @@ static int hostapd_ctrl_register_frame(struct hostapd_data *hapd, #ifdef NEED_AP_MLME -static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) +static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params, + u16 punct_bitmap) { + u32 start_freq; + switch (params->bandwidth) { case 0: /* bandwidth not specified: use 20 MHz by default */ @@ -2444,11 +2448,17 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) if (params->center_freq2 || params->sec_channel_offset) return -1; + + if (punct_bitmap) + return -1; break; case 40: if (params->center_freq2 || !params->sec_channel_offset) return -1; + if (punct_bitmap) + return -1; + if (!params->center_freq1) break; switch (params->sec_channel_offset) { @@ -2483,6 +2493,9 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) return -1; } + if (params->center_freq2 && punct_bitmap) + return -1; + /* Adjacent and overlapped are not allowed for 80+80 */ if (params->center_freq2 && params->center_freq1 - params->center_freq2 <= 80 && @@ -2517,6 +2530,29 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) return -1; } + if (!punct_bitmap) + return 0; + + if (!params->eht_enabled) { + wpa_printf(MSG_ERROR, + "Preamble puncturing supported only in EHT"); + return -1; + } + + if (params->freq >= 2412 && params->freq <= 2484) { + wpa_printf(MSG_ERROR, + "Preamble puncturing is not supported in 2.4 GHz"); + return -1; + } + + start_freq = params->center_freq1 - (params->bandwidth / 2); + if (!is_punct_bitmap_valid(params->bandwidth, + (params->freq - start_freq) / 20, + punct_bitmap)) { + wpa_printf(MSG_ERROR, "Invalid preamble puncturing bitmap"); + return -1; + } + return 0; } #endif /* NEED_AP_MLME */ @@ -2537,7 +2573,8 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, if (ret) return ret; - ret = hostapd_ctrl_check_freq_params(&settings.freq_params); + ret = hostapd_ctrl_check_freq_params(&settings.freq_params, + settings.punct_bitmap); if (ret) { wpa_printf(MSG_INFO, "chanswitch: invalid frequency settings provided"); diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 45f31d9a0..6934a732a 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -980,16 +980,27 @@ int hostapd_parse_csa_settings(const char *pos, } \ } while (0) +#define SET_CSA_SETTING_EXT(str) \ + do { \ + const char *pos2 = os_strstr(pos, " " #str "="); \ + if (pos2) { \ + pos2 += sizeof(" " #str "=") - 1; \ + settings->str = atoi(pos2); \ + } \ + } while (0) + SET_CSA_SETTING(center_freq1); SET_CSA_SETTING(center_freq2); SET_CSA_SETTING(bandwidth); SET_CSA_SETTING(sec_channel_offset); + SET_CSA_SETTING_EXT(punct_bitmap); settings->freq_params.ht_enabled = !!os_strstr(pos, " ht"); settings->freq_params.vht_enabled = !!os_strstr(pos, " vht"); settings->freq_params.he_enabled = !!os_strstr(pos, " he"); settings->freq_params.eht_enabled = !!os_strstr(pos, " eht"); settings->block_tx = !!os_strstr(pos, " blocktx"); #undef SET_CSA_SETTING +#undef SET_CSA_SETTING_EXT return 0; } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 366b5a195..141c77f4b 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -3655,6 +3655,9 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd, struct hostapd_iface *iface = hapd->iface; struct hostapd_freq_params old_freq; int ret; +#ifdef CONFIG_IEEE80211BE + u16 old_punct_bitmap; +#endif /* CONFIG_IEEE80211BE */ u8 chan, bandwidth; os_memset(&old_freq, 0, sizeof(old_freq)); @@ -3700,9 +3703,16 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd, if (ret) return ret; +#ifdef CONFIG_IEEE80211BE + old_punct_bitmap = iface->conf->punct_bitmap; + iface->conf->punct_bitmap = settings->punct_bitmap; +#endif /* CONFIG_IEEE80211BE */ ret = hostapd_build_beacon_data(hapd, &settings->beacon_after); /* change back the configuration */ +#ifdef CONFIG_IEEE80211BE + iface->conf->punct_bitmap = old_punct_bitmap; +#endif /* CONFIG_IEEE80211BE */ hostapd_change_config_freq(iface->bss[0], iface->conf, &old_freq, NULL); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index a3ce31f60..a79e0fb89 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2589,6 +2589,7 @@ struct beacon_data { * @beacon_after: Next beacon/probe resp/asooc resp info * @counter_offset_beacon: Offset to the count field in beacon's tail * @counter_offset_presp: Offset to the count field in probe resp. + * @punct_bitmap - Preamble puncturing bitmap */ struct csa_settings { u8 cs_count; @@ -2600,6 +2601,8 @@ struct csa_settings { u16 counter_offset_beacon[2]; u16 counter_offset_presp[2]; + + u16 punct_bitmap; }; /**