diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index b428bb163..2ebb3373b 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1915,7 +1915,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, goto fail; wpa_printf(MSG_DEBUG, "Completing interface initialization"); - if (iface->conf->channel) { + if (iface->freq) { #ifdef NEED_AP_MLME int res; #endif /* NEED_AP_MLME */ diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index a8bec4fcd..ba10752eb 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -227,13 +227,25 @@ int hostapd_prepare_rates(struct hostapd_iface *iface, #ifdef CONFIG_IEEE80211N static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) { - int pri_chan, sec_chan; + int pri_freq, sec_freq; + struct hostapd_channel_data *p_chan, *s_chan; - pri_chan = iface->conf->channel; - sec_chan = pri_chan + iface->conf->secondary_channel * 4; + pri_freq = iface->freq; + sec_freq = pri_freq + iface->conf->secondary_channel * 20; - return allowed_ht40_channel_pair(iface->current_mode, pri_chan, - sec_chan); + if (!iface->current_mode) + return 0; + + p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL, + iface->hw_features, + iface->num_hw_features); + + s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL, + iface->hw_features, + iface->num_hw_features); + + return allowed_ht40_channel_pair(iface->current_mode->mode, + p_chan, s_chan); } @@ -241,9 +253,11 @@ static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) { if (iface->conf->secondary_channel > 0) { iface->conf->channel += 4; + iface->freq += 20; iface->conf->secondary_channel = -1; } else { iface->conf->channel -= 4; + iface->freq -= 20; iface->conf->secondary_channel = 1; } } @@ -252,13 +266,23 @@ static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, struct wpa_scan_results *scan_res) { - int pri_chan, sec_chan; + unsigned int pri_freq, sec_freq; int res; + struct hostapd_channel_data *pri_chan, *sec_chan; - pri_chan = iface->conf->channel; - sec_chan = pri_chan + iface->conf->secondary_channel * 4; + pri_freq = iface->freq; + sec_freq = pri_freq + iface->conf->secondary_channel * 20; - res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan); + if (!iface->current_mode) + return 0; + pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, + NULL, iface->hw_features, + iface->num_hw_features); + sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, + NULL, iface->hw_features, + iface->num_hw_features); + + res = check_40mhz_5g(scan_res, pri_chan, sec_chan); if (res == 2) { if (iface->conf->no_pri_sec_switch) { @@ -352,7 +376,7 @@ static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, if (iface->current_mode == NULL) return; - pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + pri_freq = iface->freq; if (iface->conf->secondary_channel > 0) sec_freq = pri_freq + 20; else @@ -397,7 +421,7 @@ static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, if (iface->current_mode == NULL) return; - pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + pri_freq = iface->freq; if (iface->conf->secondary_channel > 0) { affected_start = pri_freq - 10; affected_end = pri_freq + 30; @@ -734,14 +758,15 @@ int hostapd_check_edmg_capab(struct hostapd_iface *iface) static int hostapd_is_usable_chan(struct hostapd_iface *iface, - int channel, int primary) + int frequency, int primary) { struct hostapd_channel_data *chan; if (!iface->current_mode) return 0; - chan = hw_get_channel_chan(iface->current_mode, channel, NULL); + chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL, + iface->hw_features, iface->num_hw_features); if (!chan) return 0; @@ -750,8 +775,8 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface, return 1; wpa_printf(MSG_INFO, - "Channel %d (%s) not allowed for AP mode, flags: 0x%x%s%s", - channel, primary ? "primary" : "secondary", + "Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s", + frequency, primary ? "primary" : "secondary", chan->flag, chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "", chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); @@ -765,19 +790,28 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface) int num_of_enabled = 0; int max_contiguous = 0; struct ieee80211_edmg_config edmg; + struct hostapd_channel_data *pri_chan; if (!iface->conf->enable_edmg) return 1; + if (!iface->current_mode) + return 0; + pri_chan = hw_get_channel_freq(iface->current_mode->mode, + iface->freq, NULL, + iface->hw_features, + iface->num_hw_features); hostapd_encode_edmg_chan(iface->conf->enable_edmg, iface->conf->edmg_channel, - iface->conf->channel, + pri_chan->chan, &edmg); - if (!(edmg.channels & BIT(iface->conf->channel - 1))) + if (!(edmg.channels & BIT(pri_chan->chan - 1))) return 0; /* 60 GHz channels 1..6 */ for (i = 0; i < 6; i++) { + int freq = 56160 + 2160 * i; + if (edmg.channels & BIT(i)) { contiguous++; num_of_enabled++; @@ -792,7 +826,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface) if (num_of_enabled > 4) return 0; - if (!hostapd_is_usable_chan(iface, i + 1, 1)) + if (!hostapd_is_usable_chan(iface, freq, 1)) return 0; if (contiguous > max_contiguous) @@ -822,17 +856,23 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface) static int hostapd_is_usable_chans(struct hostapd_iface *iface) { - int secondary_chan; + int secondary_freq; struct hostapd_channel_data *pri_chan; - pri_chan = hw_get_channel_chan(iface->current_mode, - iface->conf->channel, NULL); - if (!pri_chan) + if (!iface->current_mode) return 0; - - if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) + pri_chan = hw_get_channel_freq(iface->current_mode->mode, + iface->freq, NULL, + iface->hw_features, + iface->num_hw_features); + if (!pri_chan) { + wpa_printf(MSG_ERROR, "Primary frequency not present"); return 0; - + } + if (!hostapd_is_usable_chan(iface, pri_chan->freq, 1)) { + wpa_printf(MSG_ERROR, "Primary frequency not allowed"); + return 0; + } if (!hostapd_is_usable_edmg(iface)) return 0; @@ -841,19 +881,19 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface) if (!iface->conf->ht40_plus_minus_allowed) return hostapd_is_usable_chan( - iface, iface->conf->channel + - iface->conf->secondary_channel * 4, 0); + iface, + iface->freq + iface->conf->secondary_channel * 20, 0); /* Both HT40+ and HT40- are set, pick a valid secondary channel */ - secondary_chan = iface->conf->channel + 4; - if (hostapd_is_usable_chan(iface, secondary_chan, 0) && + secondary_freq = iface->freq + 20; + if (hostapd_is_usable_chan(iface, secondary_freq, 0) && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) { iface->conf->secondary_channel = 1; return 1; } - secondary_chan = iface->conf->channel - 4; - if (hostapd_is_usable_chan(iface, secondary_chan, 0) && + secondary_freq = iface->freq - 20; + if (hostapd_is_usable_chan(iface, secondary_freq, 0) && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) { iface->conf->secondary_channel = -1; return 1; @@ -866,7 +906,7 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface) static enum hostapd_chan_status hostapd_check_chans(struct hostapd_iface *iface) { - if (iface->conf->channel) { + if (iface->freq) { if (hostapd_is_usable_chans(iface)) return HOSTAPD_CHAN_VALID; else @@ -900,9 +940,9 @@ static void hostapd_notify_bad_chans(struct hostapd_iface *iface) hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_WARNING, - "Configured channel (%d) not found from the " - "channel list of current mode (%d) %s", + "Configured channel (%d) or frequency (%d) not found from the channel list of the current mode (%d) %s", iface->conf->channel, + iface->freq, iface->current_mode->mode, hostapd_hw_mode_txt(iface->current_mode->mode)); hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c index 706f20415..4da58c421 100644 --- a/src/common/hw_features_common.c +++ b/src/common/hw_features_common.c @@ -94,19 +94,22 @@ int hw_get_chan(enum hostapd_hw_mode mode, int freq, } -int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, - int sec_chan) +int allowed_ht40_channel_pair(enum hostapd_hw_mode mode, + struct hostapd_channel_data *p_chan, + struct hostapd_channel_data *s_chan) { int ok, first; int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140, 149, 157, 165, 184, 192 }; size_t k; - struct hostapd_channel_data *p_chan, *s_chan; - const int ht40_plus = pri_chan < sec_chan; + int ht40_plus, pri_chan, sec_chan; - p_chan = hw_get_channel_chan(mode, pri_chan, NULL); - if (!p_chan) + if (!p_chan || !s_chan) return 0; + pri_chan = p_chan->chan; + sec_chan = s_chan->chan; + + ht40_plus = pri_chan < sec_chan; if (pri_chan == sec_chan || !sec_chan) { if (chan_pri_allowed(p_chan)) @@ -117,13 +120,9 @@ int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, return 0; } - s_chan = hw_get_channel_chan(mode, sec_chan, NULL); - if (!s_chan) - return 0; - wpa_printf(MSG_DEBUG, - "HT40: control channel: %d secondary channel: %d", - pri_chan, sec_chan); + "HT40: control channel: %d (%d MHz), secondary channel: %d (%d MHz)", + pri_chan, p_chan->freq, sec_chan, s_chan->freq); /* Verify that HT40 secondary channel is an allowed 20 MHz * channel */ @@ -141,7 +140,7 @@ int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, * 2.4 GHz rules allow all cases where the secondary channel fits into * the list of allowed channels (already checked above). */ - if (mode->mode != HOSTAPD_MODE_IEEE80211A) + if (mode != HOSTAPD_MODE_IEEE80211A) return 1; first = pri_chan < sec_chan ? pri_chan : sec_chan; @@ -186,22 +185,19 @@ void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan) } -int check_40mhz_5g(struct hostapd_hw_modes *mode, - struct wpa_scan_results *scan_res, int pri_chan, - int sec_chan) +int check_40mhz_5g(struct wpa_scan_results *scan_res, + struct hostapd_channel_data *pri_chan, + struct hostapd_channel_data *sec_chan) { - int pri_freq, sec_freq, pri_bss, sec_bss; + int pri_bss, sec_bss; int bss_pri_chan, bss_sec_chan; size_t i; int match; - if (!mode || !scan_res || !pri_chan || !sec_chan || - pri_chan == sec_chan) + if (!scan_res || !pri_chan || !sec_chan || + pri_chan->freq == sec_chan->freq) return 0; - pri_freq = hw_get_freq(mode, pri_chan); - sec_freq = hw_get_freq(mode, sec_chan); - /* * Switch PRI/SEC channels if Beacons were detected on selected SEC * channel, but not on selected PRI channel. @@ -209,9 +205,9 @@ int check_40mhz_5g(struct hostapd_hw_modes *mode, pri_bss = sec_bss = 0; for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; - if (bss->freq == pri_freq) + if (bss->freq == pri_chan->freq) pri_bss++; - else if (bss->freq == sec_freq) + else if (bss->freq == sec_chan->freq) sec_bss++; } if (sec_bss && !pri_bss) { @@ -229,8 +225,8 @@ int check_40mhz_5g(struct hostapd_hw_modes *mode, for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); - if (pri_chan == bss_pri_chan && - sec_chan == bss_sec_chan) { + if (pri_chan->chan == bss_pri_chan && + sec_chan->chan == bss_sec_chan) { match = 1; break; } @@ -239,8 +235,8 @@ int check_40mhz_5g(struct hostapd_hw_modes *mode, for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); - if (pri_chan == bss_sec_chan && - sec_chan == bss_pri_chan) { + if (pri_chan->chan == bss_sec_chan && + sec_chan->chan == bss_pri_chan) { wpa_printf(MSG_INFO, "Switch own primary and " "secondary channel due to BSS " "overlap with " MACSTR, diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h index 7eb4ca170..2dba34b3e 100644 --- a/src/common/hw_features_common.h +++ b/src/common/hw_features_common.h @@ -22,12 +22,13 @@ int hw_get_freq(struct hostapd_hw_modes *mode, int chan); int hw_get_chan(enum hostapd_hw_mode mode, int freq, struct hostapd_hw_modes *hw_features, int num_hw_features); -int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, - int sec_chan); +int allowed_ht40_channel_pair(enum hostapd_hw_mode mode, + struct hostapd_channel_data *p_chan, + struct hostapd_channel_data *s_chan); void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan); -int check_40mhz_5g(struct hostapd_hw_modes *mode, - struct wpa_scan_results *scan_res, int pri_chan, - int sec_chan); +int check_40mhz_5g(struct wpa_scan_results *scan_res, + struct hostapd_channel_data *pri_chan, + struct hostapd_channel_data *sec_chan); int check_40mhz_2g4(struct hostapd_hw_modes *mode, struct wpa_scan_results *scan_res, int pri_chan, int sec_chan); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 0fee3c951..195ff74b0 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2382,8 +2382,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, return; } - res = check_40mhz_5g(mode, scan_res, pri_chan->chan, - sec_chan->chan); + res = check_40mhz_5g(scan_res, pri_chan, sec_chan); switch (res) { case 0: /* Back to HT20 */