[PATCH RFC 2/9] AP/STA: introduce support for freq_offset
Lachlan Hodges
lachlan.hodges at morsemicro.com
Thu Oct 8 20:31:59 PDT 2026
80211ah or S1G sits below 1GHz with channel granularity of 500KHz,
meaning MHz alone is not enough to correctly represent a channels
center frequency. This requires the introduction of a 'freq_offset'
parameter that sits alongside the 'freq' parameter. Where `freq_offset`
exists as a KHz component to be added to `freq`. This parameter is
introduced anywhere we pass `freq` such that an S1G channel
can be correctly defined.
Signed-off-by: Lachlan Hodges <lachlan.hodges at morsemicro.com>
---
src/ap/ap_drv_ops.c | 6 ++--
src/ap/ap_drv_ops.h | 3 +-
src/ap/beacon.c | 1 +
src/ap/dfs.c | 2 +-
src/ap/drv_callbacks.c | 6 ++--
src/ap/hostapd.c | 27 ++++++++++--------
src/ap/hostapd.h | 1 +
src/ap/hw_features.c | 46 +++++++++++++++++--------------
src/ap/hw_features.h | 3 +-
src/ap/interference.c | 2 +-
src/common/defs.h | 1 +
src/common/hw_features_common.c | 21 +++++++++-----
src/common/hw_features_common.h | 11 +++++---
src/common/privsep_commands.h | 1 +
src/drivers/driver.h | 45 ++++++++++++++++++++++++++++--
src/drivers/driver_nl80211.c | 2 +-
src/drivers/driver_privsep.c | 7 +++--
wpa_supplicant/ap.c | 4 ++-
wpa_supplicant/bss.c | 5 ++--
wpa_supplicant/bss.h | 2 ++
wpa_supplicant/config.c | 1 +
wpa_supplicant/config_file.c | 1 +
wpa_supplicant/config_ssid.h | 12 ++++++++
wpa_supplicant/ctrl_iface.c | 1 +
wpa_supplicant/driver_i.h | 9 +++---
wpa_supplicant/events.c | 9 ++++--
wpa_supplicant/ibss_rsn.c | 2 +-
wpa_supplicant/nan_supplicant.c | 2 +-
wpa_supplicant/p2p_supplicant.c | 4 +--
wpa_supplicant/pasn_supplicant.c | 4 +--
wpa_supplicant/scan.c | 10 ++++---
wpa_supplicant/sme.c | 14 ++++++----
wpa_supplicant/wpa_priv.c | 1 +
wpa_supplicant/wpa_supplicant.c | 7 ++++-
wpa_supplicant/wpa_supplicant_i.h | 2 ++
35 files changed, 192 insertions(+), 83 deletions(-)
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index dd2f5c542785..90d2909cbe90 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -676,7 +676,8 @@ int hostapd_flush(struct hostapd_data *hapd)
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
- int freq, int channel, int edmg, u8 edmg_channel,
+ int freq, int freq_offset, int channel,
+ int edmg, u8 edmg_channel,
int ht_enabled, int vht_enabled,
int he_enabled, bool eht_enabled,
int sec_channel_offset, int oper_chwidth,
@@ -687,6 +688,7 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
struct hostapd_channel_info info = {
.mode = mode,
.freq = freq,
+ .freq_offset = freq_offset,
.channel = channel,
.edmg.enabled = edmg,
.edmg.channel = edmg_channel,
@@ -922,7 +924,7 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd,
if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
return 0;
- return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
+ return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, 0,
csa_offs, csa_offs_len, no_encrypt, 0,
link_id);
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index cd86fb762315..972514d38f72 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -73,7 +73,8 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
const u8 *addr, int idx, int link_id, u8 *seq);
int hostapd_flush(struct hostapd_data *hapd);
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
- int freq, int channel, int edmg, u8 edmg_channel,
+ int freq, int freq_offset,
+ int channel, int edmg, u8 edmg_channel,
int ht_enabled, int vht_enabled, int he_enabled,
bool eht_enabled, int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1);
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index be8e1153d6d0..3a886e00544b 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -2894,6 +2894,7 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd)
info = (struct hostapd_channel_info) {
.mode = iconf->hw_mode,
.freq = iface->freq,
+ .freq_offset = iface->freq_offset,
.channel = iconf->channel,
.edmg.enabled = iconf->enable_edmg,
.edmg.channel = iconf->edmg_channel,
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 8b85a25558b4..caba71537b5b 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1143,7 +1143,7 @@ hostapd_is_freq_in_current_hw_info(struct hostapd_iface *iface, int freq)
if (!iface->current_mode)
return false;
- chan = hw_mode_get_channel(iface->current_mode, freq, NULL);
+ chan = hw_mode_get_channel(iface->current_mode, freq, 0, NULL);
/* If channel data is not found for the given frequency, consider it is
* out of the current hardware info. */
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 7f2ef4b0d021..04da5da0ea75 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -1283,7 +1283,7 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
is_dfs0 = hostapd_is_dfs_required(hapd->iface);
hapd->iface->freq = freq;
- channel = hostapd_hw_get_channel(hapd, freq);
+ channel = hostapd_hw_get_channel(hapd, freq, 0);
if (!channel) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
@@ -1536,7 +1536,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
if (mode->mode == acs_res->hw_mode) {
if (hapd->iface->freq > 0 &&
!hw_mode_get_channel(mode,
- hapd->iface->freq,
+ hapd->iface->freq, 0,
NULL))
continue;
hapd->iface->current_mode = mode;
@@ -1560,7 +1560,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
goto out;
}
pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode,
- acs_res->pri_freq, NULL,
+ acs_res->pri_freq, 0, NULL,
hapd->iface->hw_features,
hapd->iface->num_hw_features);
if (!pri_chan) {
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index a4394f73d94f..0503322d5d88 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2021,7 +2021,7 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
if (mode->mode == iface->conf->hw_mode) {
if (iface->freq > 0 &&
- !hw_mode_get_channel(mode, iface->freq, NULL)) {
+ !hw_mode_get_channel(mode, iface->freq, iface->freq_offset, NULL)) {
mode = NULL;
continue;
}
@@ -2046,7 +2046,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
struct hostapd_channel_data *chan;
chan = hw_get_channel_freq(mode->mode,
- iface->freq, NULL,
+ iface->freq,
+ iface->freq_offset, NULL,
hw_features,
num_hw_features);
@@ -2081,7 +2082,8 @@ static int hostapd_no_ir_channel_list_updated(struct hostapd_iface *iface,
struct hostapd_channel_data *chan;
chan = hw_get_channel_freq(mode->mode,
- iface->freq, NULL,
+ iface->freq,
+ iface->freq_offset, NULL,
hw_features,
num_hw_features);
if (!chan) {
@@ -2222,20 +2224,21 @@ static int setup_interface(struct hostapd_iface *iface)
static int configured_fixed_chan_to_freq(struct hostapd_iface *iface)
{
- int freq, i, j;
+ int freq_khz, i, j;
if (!iface->conf->channel)
return 0;
if (iface->conf->op_class) {
- freq = ieee80211_chan_to_freq(NULL, iface->conf->op_class,
- iface->conf->channel);
- if (freq < 0) {
+ freq_khz = ieee80211_chan_to_freq_khz(NULL, iface->conf->op_class,
+ iface->conf->channel);
+ if (freq_khz < 0) {
wpa_printf(MSG_INFO,
"Could not convert op_class %u channel %u to operating frequency",
iface->conf->op_class, iface->conf->channel);
return -1;
}
- iface->freq = freq;
+ iface->freq = KHZ_TO_MHZ(freq_khz);
+ iface->freq_offset = KHZ_TO_S1G_OFFSET(freq_khz);
return 0;
}
@@ -2702,7 +2705,8 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
#endif /* CONFIG_IEEE80211AX */
if (!delay_apply_cfg &&
- hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
+ hostapd_set_freq(hapd, hapd->iconf->hw_mode,
+ iface->freq, iface->freq_offset,
hapd->iconf->channel,
hapd->iconf->enable_edmg,
hapd->iconf->edmg_channel,
@@ -4565,7 +4569,7 @@ int hostapd_change_config_freq(struct hostapd_data *hapd,
if (!params->channel) {
/* check if the new channel is supported by hw */
- params->channel = hostapd_hw_get_channel(hapd, params->freq);
+ params->channel = hostapd_hw_get_channel(hapd, params->freq, 0);
}
channel = params->channel;
@@ -4911,7 +4915,8 @@ int hostapd_force_channel_switch(struct hostapd_iface *iface,
if (!settings->freq_params.channel) {
/* Check if the new channel is supported */
settings->freq_params.channel = hostapd_hw_get_channel(
- iface->bss[0], settings->freq_params.freq);
+ iface->bss[0], settings->freq_params.freq,
+ settings->freq_params.freq_offset);
if (!settings->freq_params.channel)
return -1;
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 6ce29653b2ad..8383b164d32b 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -645,6 +645,7 @@ struct hostapd_iface {
int num_hw_features;
struct hostapd_hw_modes *current_mode;
int freq;
+ int freq_offset;
bool radar_detected;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 9fe84f70add2..d7715206ce9e 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -197,10 +197,11 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
continue;
wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
- "chan=%d freq=%d MHz max_tx_power=%d dBm%s",
+ "chan=%d freq=%d MHz freq_offset=%d KHz max_tx_power=%d dBm%s",
feature->mode,
feature->channels[j].chan,
feature->channels[j].freq,
+ feature->channels[j].freq_offset,
feature->channels[j].max_tx_power,
dfs ? dfs_info(&feature->channels[j]) : "");
}
@@ -335,11 +336,11 @@ static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
if (!iface->current_mode)
return 0;
- p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL,
+ p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, 0, NULL,
iface->hw_features,
iface->num_hw_features);
- s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL,
+ s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, 0, NULL,
iface->hw_features,
iface->num_hw_features);
@@ -374,10 +375,10 @@ static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
if (!iface->current_mode)
return 0;
- pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq,
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, 0,
NULL, iface->hw_features,
iface->num_hw_features);
- sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq,
+ sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, 0,
NULL, iface->hw_features,
iface->num_hw_features);
@@ -922,15 +923,16 @@ int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface)
* -1 = not currently usable due to 6 GHz NO-IR
*/
static int hostapd_is_usable_chan(struct hostapd_iface *iface,
- int frequency, int primary)
+ int frequency, int freq_offset, int primary)
{
struct hostapd_channel_data *chan;
if (!iface->current_mode)
return 0;
- chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL,
- iface->hw_features, iface->num_hw_features);
+ chan = hw_get_channel_freq(iface->current_mode->mode, frequency,
+ freq_offset, NULL, iface->hw_features,
+ iface->num_hw_features);
if (!chan)
return 0;
@@ -967,7 +969,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
if (!iface->current_mode)
return 0;
pri_chan = hw_get_channel_freq(iface->current_mode->mode,
- iface->freq, NULL,
+ iface->freq, 0, NULL,
iface->hw_features,
iface->num_hw_features);
if (!pri_chan)
@@ -997,7 +999,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
if (num_of_enabled > 4)
return 0;
- err = hostapd_is_usable_chan(iface, freq, 1);
+ err = hostapd_is_usable_chan(iface, freq, 0, 1);
if (err <= 0)
return err;
@@ -1118,7 +1120,7 @@ static int hostapd_is_usable_chan_seg(struct hostapd_iface *iface)
for (i = 0; i < chan_num; i++) {
int freq = start_freq + i * 20;
- err = hostapd_is_usable_chan(iface, freq, freq == iface->freq);
+ err = hostapd_is_usable_chan(iface, freq, 0, freq == iface->freq);
if (err <= 0) {
wpa_printf(MSG_ERROR,
"Frequency %d is not allowed (seg0)",
@@ -1142,7 +1144,7 @@ static int hostapd_is_usable_chan_seg(struct hostapd_iface *iface)
for (i = 0; i < chan_num; i++) {
int freq = start_freq + i * 20;
- err = hostapd_is_usable_chan(iface, freq, freq == iface->freq);
+ err = hostapd_is_usable_chan(iface, freq, 0, freq == iface->freq);
if (err <= 0) {
wpa_printf(MSG_ERROR,
"Frequency %d is not allowed (seg1)",
@@ -1170,7 +1172,8 @@ int hostapd_is_usable_chans(struct hostapd_iface *iface)
if (!iface->current_mode)
return 0;
pri_chan = hw_get_channel_freq(iface->current_mode->mode,
- iface->freq, NULL,
+ iface->freq,
+ iface->freq_offset, NULL,
iface->hw_features,
iface->num_hw_features);
if (!pri_chan) {
@@ -1197,7 +1200,8 @@ int hostapd_is_usable_chans(struct hostapd_iface *iface)
oper_chwidth != CONF_OPER_CHWIDTH_USE_HT && central)
return hostapd_is_usable_chan_seg(iface);
- err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
+ err = hostapd_is_usable_chan(iface, pri_chan->freq,
+ pri_chan->freq_offset, 1);
if (err <= 0) {
wpa_printf(MSG_ERROR, "Primary frequency not allowed");
return err;
@@ -1207,7 +1211,7 @@ int hostapd_is_usable_chans(struct hostapd_iface *iface)
return 1;
err = hostapd_is_usable_chan(iface, iface->freq +
- iface->conf->secondary_channel * 20, 0);
+ iface->conf->secondary_channel * 20, 0, 0);
if (err > 0) {
if (iface->conf->secondary_channel == 1 &&
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))
@@ -1226,7 +1230,7 @@ int hostapd_is_usable_chans(struct hostapd_iface *iface)
HOSTAPD_CHAN_WIDTH_40P : HOSTAPD_CHAN_WIDTH_40M;
secondary_freq = iface->freq + new_sec * 20;
- err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
+ err2 = hostapd_is_usable_chan(iface, secondary_freq, 0, 0);
if (err2 <= 0)
return err;
@@ -1244,7 +1248,8 @@ static bool skip_mode(struct hostapd_iface *iface,
{
int chan;
- if (iface->freq > 0 && !hw_mode_get_channel(mode, iface->freq, &chan))
+ if (iface->freq > 0 &&
+ !hw_mode_get_channel(mode, iface->freq, iface->freq_offset, &chan))
return true;
if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
@@ -1514,13 +1519,14 @@ int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
}
-int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq, int freq_offset)
{
int i, channel;
struct hostapd_hw_modes *mode;
if (hapd->iface->current_mode) {
- channel = hw_get_chan(hapd->iface->current_mode->mode, freq,
+ channel = hw_get_chan(hapd->iface->current_mode->mode,
+ freq, freq_offset,
hapd->iface->hw_features,
hapd->iface->num_hw_features);
if (channel)
@@ -1533,7 +1539,7 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
return 0;
for (i = 0; i < hapd->iface->num_hw_features; i++) {
mode = &hapd->iface->hw_features[i];
- channel = hw_get_chan(mode->mode, freq,
+ channel = hw_get_chan(mode->mode, freq, freq_offset,
hapd->iface->hw_features,
hapd->iface->num_hw_features);
if (channel)
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 4993e68afd62..d49f532b5cad 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -20,7 +20,8 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err);
int hostapd_select_hw_mode(struct hostapd_iface *iface);
const char * hostapd_hw_mode_txt(int mode);
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
-int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
+int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq,
+ int freq_offset);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
int hostapd_check_edmg_capab(struct hostapd_iface *iface);
int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface);
diff --git a/src/ap/interference.c b/src/ap/interference.c
index c93cdc75f13f..44aa6c0019ef 100644
--- a/src/ap/interference.c
+++ b/src/ap/interference.c
@@ -552,7 +552,7 @@ int hostapd_incumbt_sig_intf_detected(struct hostapd_iface *iface, int freq,
goto exit;
}
if (hostapd_set_freq(
- iface->bss[0], iface->conf->hw_mode, iface->freq,
+ iface->bss[0], iface->conf->hw_mode, iface->freq, 0,
iface->conf->channel, iface->conf->enable_edmg,
iface->conf->edmg_channel, iface->conf->ieee80211n,
iface->conf->ieee80211ac,
diff --git a/src/common/defs.h b/src/common/defs.h
index 9f7ea34a2e5a..d6bd21b38baf 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -591,5 +591,6 @@ enum wpa_p2p_mode {
#define MHZ_TO_KHZ(x) ((x) * 1000)
#define KHZ_TO_MHZ(x) ((x) / 1000)
+#define KHZ_TO_S1G_OFFSET(x) ((x) % 1000)
#endif /* DEFS_H */
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index ce0074d10311..0d4f47cf796d 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -41,14 +41,16 @@ struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode,
struct hostapd_channel_data *
-hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan)
+hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq,
+ int freq_offset, int *chan)
{
int i;
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *ch = &mode->channels[i];
- if (ch->freq == freq) {
+ if (MHZ_TO_KHZ(ch->freq) + ch->freq_offset ==
+ MHZ_TO_KHZ(freq) + freq_offset) {
if (chan)
*chan = ch->chan;
return ch;
@@ -60,8 +62,9 @@ hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan)
struct hostapd_channel_data *
-hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
- struct hostapd_hw_modes *hw_features, int num_hw_features)
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int freq_offset,
+ int *chan, struct hostapd_hw_modes *hw_features,
+ int num_hw_features)
{
struct hostapd_channel_data *chan_data;
int i;
@@ -78,7 +81,8 @@ hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
if (curr_mode->mode != mode)
continue;
- chan_data = hw_mode_get_channel(curr_mode, freq, chan);
+ chan_data = hw_mode_get_channel(curr_mode, freq,
+ freq_offset, chan);
if (chan_data)
return chan_data;
}
@@ -97,12 +101,13 @@ int hw_get_freq(struct hostapd_hw_modes *mode, int chan)
}
-int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+int hw_get_chan(enum hostapd_hw_mode mode, int freq, int freq_offset,
struct hostapd_hw_modes *hw_features, int num_hw_features)
{
int chan;
- hw_get_channel_freq(mode, freq, &chan, hw_features, num_hw_features);
+ hw_get_channel_freq(mode, freq, freq_offset, &chan, hw_features,
+ num_hw_features);
return chan;
}
@@ -553,6 +558,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
{
enum hostapd_hw_mode mode = info->mode;
int freq = info->freq;
+ int freq_offset = info->freq_offset;
int channel = info->channel;
int enable_edmg = info->edmg.enabled;
u8 edmg_channel = info->edmg.channel;
@@ -582,6 +588,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
os_memset(data, 0, sizeof(*data));
data->mode = mode;
data->freq = freq;
+ data->freq_offset = freq_offset;
data->channel = channel;
data->ht_enabled = ht_enabled;
data->vht_enabled = vht_enabled;
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index 605739939e3d..47333a7bd7de 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -15,14 +15,16 @@
struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode,
int chan, int *freq);
struct hostapd_channel_data *
-hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq, int *chan);
+hw_mode_get_channel(struct hostapd_hw_modes *mode, int freq,
+ int freq_offset, int *chan);
struct hostapd_channel_data *
-hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
- struct hostapd_hw_modes *hw_features, int num_hw_features);
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int freq_offset,
+ int *chan, struct hostapd_hw_modes *hw_features,
+ int num_hw_features);
int hw_get_freq(struct hostapd_hw_modes *mode, int chan);
-int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+int hw_get_chan(enum hostapd_hw_mode mode, int freq, int freq_offset,
struct hostapd_hw_modes *hw_features, int num_hw_features);
int allowed_ht40_channel_pair(enum hostapd_hw_mode mode,
@@ -43,6 +45,7 @@ struct hostapd_channel_info {
enum hostapd_hw_mode mode;
int freq;
+ int freq_offset;
int channel;
enum oper_chan_width oper_chwidth;
diff --git a/src/common/privsep_commands.h b/src/common/privsep_commands.h
index d2c4bbd5e8b6..85e1e89977b2 100644
--- a/src/common/privsep_commands.h
+++ b/src/common/privsep_commands.h
@@ -63,6 +63,7 @@ struct privsep_cmd_associate {
size_t ssid_len;
int hwmode;
int freq;
+ int freq_offset;
int channel;
int pairwise_suite;
int group_suite;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index e957a56ae093..f8c854227011 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -126,6 +126,11 @@ struct hostapd_channel_data {
*/
int freq;
+ /**
+ * freq_offset - Frequency offset from @freq in KHz
+ */
+ int freq_offset;
+
/**
* flag - Channel flags (HOSTAPD_CHAN_*)
*/
@@ -386,6 +391,7 @@ struct hostapd_multi_hw_info {
* @flags: information flags about the BSS/IBSS (WPA_SCAN_*)
* @bssid: BSSID
* @freq: frequency of the channel in MHz (e.g., 2412 = channel 1)
+ * @freq_offset: frequency offset of the channel from @freq in KHz
* @max_cw: the max channel width of the connection (calculated during scan
* result processing)
* @beacon_int: beacon interval in TUs (host byte order)
@@ -426,6 +432,7 @@ struct wpa_scan_res {
unsigned int flags;
u8 bssid[ETH_ALEN];
int freq;
+ int freq_offset;
enum chan_width max_cw;
u16 beacon_int;
u16 caps;
@@ -533,6 +540,13 @@ struct wpa_driver_scan_params {
*/
int *freqs;
+ /**
+ * freq_offset - Frequency offset in KHz
+ *
+ * Each @freqs value will have this frequency offset applied.
+ */
+ int freq_offset;
+
/**
* filter_ssids - Filter for reporting SSIDs
*
@@ -771,6 +785,7 @@ struct wpa_driver_scan_params {
*/
struct wpa_driver_auth_params {
int freq;
+ int freq_offset;
const u8 *bssid;
const u8 *ssid;
size_t ssid_len;
@@ -851,6 +866,11 @@ struct hostapd_freq_params {
*/
int freq;
+ /**
+ * freq_offset - Frequency offset in KHz from @freq
+ */
+ int freq_offset;
+
/**
* channel - Channel number
*/
@@ -887,6 +907,13 @@ struct hostapd_freq_params {
*/
int center_freq1;
+ /**
+ * center_freq1_offset - Segment 0 center frequency offset in KHz
+ *
+ * Valid for S1G.
+ */
+ int center_freq1_offset;
+
/**
* center_freq2 - Segment 1 center frequency in MHz
*
@@ -3957,6 +3984,7 @@ struct wpa_driver_ops {
* @noack: Do not wait for this frame to be acked (disable retries)
* @freq: Frequency (in MHz) to send the frame on, or 0 to let the
* driver decide
+ * @freq_offset: Frequency offset (in KHz) from @freq to send the frame on
* @csa_offs: Array of CSA offsets or %NULL
* @csa_offs_len: Number of elements in csa_offs
* @no_encrypt: Do not encrypt frame even if appropriate key exists
@@ -3966,8 +3994,8 @@ struct wpa_driver_ops {
* Returns: 0 on success, -1 on failure
*/
int (*send_mlme)(void *priv, const u8 *data, size_t data_len,
- int noack, unsigned int freq, const u16 *csa_offs,
- size_t csa_offs_len, int no_encrypt,
+ int noack, unsigned int freq, unsigned int freq_offset,
+ const u16 *csa_offs, size_t csa_offs_len, int no_encrypt,
unsigned int wait, int link_id);
/**
@@ -6937,6 +6965,11 @@ union wpa_event_data {
*/
unsigned int freq;
+ /**
+ * freq_offset - Frequency offset from @freq in KHz
+ */
+ unsigned int freq_offset;
+
/**
* wmm_params - WMM parameters used in this association.
*/
@@ -7330,6 +7363,12 @@ union wpa_event_data {
*/
int freq;
+ /**
+ * freq_offset - Frequency offset (in KHz) from @freq on which
+ * the frame was received
+ */
+ int freq_offset;
+
/**
* ssi_signal - Signal strength in dBm (or 0 if not available)
*/
@@ -7533,6 +7572,7 @@ union wpa_event_data {
/**
* struct ch_switch
* @freq: Frequency of new channel in MHz
+ * @freq_offset: Frequency offset from @freq in KHz
* @ht_enabled: Whether this is an HT channel
* @ch_offset: Secondary channel offset
* @ch_width: Channel width
@@ -7543,6 +7583,7 @@ union wpa_event_data {
*/
struct ch_switch {
int freq;
+ int freq_offset;
int ht_enabled;
int ch_offset;
enum chan_width ch_width;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 84540d6c0063..5839a8f9be08 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -12015,7 +12015,7 @@ static bool nl80211_is_drv_shared(void *priv, int link_id)
static int driver_nl80211_send_mlme(void *priv, const u8 *data,
size_t data_len, int noack,
- unsigned int freq,
+ unsigned int freq, unsigned int freq_offset,
const u16 *csa_offs, size_t csa_offs_len,
int no_encrypt, unsigned int wait,
int link_id)
diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c
index d7c6b01a317e..e53421179d01 100644
--- a/src/drivers/driver_privsep.c
+++ b/src/drivers/driver_privsep.c
@@ -306,10 +306,10 @@ static int wpa_driver_privsep_associate(
int res;
size_t buflen;
- wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
+ wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d freq_offset=%d pairwise_suite=%d "
"group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
- __func__, priv, params->freq.freq, params->pairwise_suite,
- params->group_suite, params->key_mgmt_suite,
+ __func__, priv, params->freq.freq, params->freq.freq_offset,
+ params->pairwise_suite, params->group_suite, params->key_mgmt_suite,
params->auth_alg, params->mode);
buflen = sizeof(*data) + params->wpa_ie_len;
@@ -323,6 +323,7 @@ static int wpa_driver_privsep_associate(
data->ssid_len = params->ssid_len;
data->hwmode = params->freq.mode;
data->freq = params->freq.freq;
+ data->freq_offset = params->freq.freq_offset;
data->channel = params->freq.channel;
data->pairwise_suite = params->pairwise_suite;
data->group_suite = params->group_suite;
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index aa3eef9b68a8..460b44ced891 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -457,7 +457,8 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
{
if (iface == wpa_s ||
iface->wpa_state < WPA_AUTHENTICATING ||
- (int) iface->assoc_freq != ssid->frequency)
+ MHZ_TO_KHZ(iface->assoc_freq) + iface->assoc_freq_offset !=
+ MHZ_TO_KHZ(ssid->frequency) + ssid->freq_offset)
continue;
/*
@@ -1196,6 +1197,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
wpa_s->assoc_freq = ssid->frequency;
+ wpa_s->assoc_freq_offset = ssid->freq_offset;
wpa_s->ap_iface->conf->enable_edmg = ssid->enable_edmg;
wpa_s->ap_iface->conf->edmg_channel = ssid->edmg_channel;
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index b534cab1cd88..987297dd3146 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -384,6 +384,7 @@ static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
dst->flags = src->flags;
os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
dst->freq = src->freq;
+ dst->freq_offset = src->freq_offset;
dst->max_cw = src->max_cw;
dst->beacon_int = src->beacon_int;
dst->caps = src->caps;
@@ -635,9 +636,9 @@ static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
}
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
- " SSID '%s' freq %d%s",
+ " SSID '%s' freq %d freq_offset %d%s",
bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len),
- bss->freq, extra);
+ bss->freq, bss->freq_offset, extra);
wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
return bss;
}
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index d9d0401cef32..5580fc0d32c4 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -93,6 +93,8 @@ struct wpa_bss {
size_t ssid_len;
/** Frequency of the channel in MHz (e.g., 2412 = channel 1) */
int freq;
+ /** Frequency offset from @freq of the channel in KHz */
+ int freq_offset;
/** The max channel width supported by both the AP and the STA */
enum chan_width max_cw;
/** Beacon interval in TUs (host byte order) */
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index afe770b584a5..dce75ae074a2 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3018,6 +3018,7 @@ static const struct parse_data ssid_fields[] = {
#endif /* CONFIG_PASN */
{ FUNC(security_profiles) },
{ BOOL(disable_pmksa_caching) },
+ { INT_RANGE(scan_freq_offset, 0, 999)},
};
#undef OFFSET
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index b01134945e13..7e4328410fe3 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -826,6 +826,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid,
STR(bgscan);
STR(autoscan);
STR(scan_freq);
+ INT(scan_freq_offset);
STR(freq_list);
#ifdef IEEE8021X_EAPOL
write_eap(f, ssid);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 86bd8d6172c4..a6932c2dcd98 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -547,6 +547,11 @@ struct wpa_ssid {
*/
int frequency;
+ /**
+ * freq_offset - Channel frequency offset from @frequency in KHz
+ */
+ int freq_offset;
+
/**
* enable_edmg - Enable EDMG feature in STA/AP mode
*
@@ -653,6 +658,13 @@ struct wpa_ssid {
*/
int *scan_freq;
+ /**
+ * scan_freq_offset - Frequency offset in KHz
+ *
+ * To be applied to each entry in @scan_freq array.
+ */
+ int scan_freq_offset;
+
/**
* bgscan - Background scan and roaming parameters or %NULL if none
*
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 0d995bb60e9f..027baa25de90 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -10714,6 +10714,7 @@ static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s)
params.ssid = wpa_s->sme.ssid;
params.ssid_len = wpa_s->sme.ssid_len;
params.freq.freq = wpa_s->sme.freq;
+ params.freq.freq_offset = wpa_s->sme.freq_offset;
if (wpa_s->last_assoc_req_wpa_ie) {
params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie);
params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie);
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 9122b9353b25..a2d30f87975e 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -336,12 +336,13 @@ static inline int wpa_drv_set_country(struct wpa_supplicant *wpa_s,
static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
const u8 *data, size_t data_len, int noack,
- unsigned int freq, unsigned int wait)
+ unsigned int freq, unsigned int freq_offset,
+ unsigned int wait)
{
if (wpa_s->driver->send_mlme)
- return wpa_s->driver->send_mlme(wpa_s->drv_priv,
- data, data_len, noack,
- freq, NULL, 0, 0, wait, -1);
+ return wpa_s->driver->send_mlme(wpa_s->drv_priv, data, data_len,
+ noack, freq, freq_offset, NULL,
+ 0, 0, wait, -1);
return -1;
}
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index b2d9558aa183..4f92fe039f42 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1864,11 +1864,11 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
if (debug_print) {
wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR
- " ssid='%s' wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s",
+ " ssid='%s' wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d freq_offset=%d %s%s",
i, MAC2STR(bss->bssid),
wpa_ssid_txt(bss->ssid, bss->ssid_len),
wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
- bss->freq,
+ bss->freq, bss->freq_offset,
wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ?
" wps" : "",
(wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
@@ -4334,6 +4334,7 @@ no_pfs:
}
wpa_s->assoc_freq = data->assoc_info.freq;
+ wpa_s->assoc_freq_offset = data->assoc_info.freq_offset;
#ifdef CONFIG_P2P
if (wpa_s->allow_p2p_assisted_dfs &&
@@ -5815,8 +5816,10 @@ static void ft_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
{
struct wpa_bss *bss;
bss = wpa_bss_get_bssid(wpa_s, target_ap_addr);
- if (bss)
+ if (bss) {
wpa_s->sme.freq = bss->freq;
+ wpa_s->sme.freq_offset = bss->freq_offset;
+ }
wpa_s->sme.auth_alg = WPA_AUTH_ALG_FT;
sme_associate(wpa_s, WPAS_MODE_INFRA, target_ap_addr,
WLAN_AUTH_FT);
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index e4f592399f15..16518706e8c3 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -534,7 +534,7 @@ static int ibss_rsn_send_auth(struct ibss_rsn *ibss_rsn, const u8 *da, int seq)
wpa_printf(MSG_DEBUG, "RSN: IBSS TX Auth frame (SEQ %d) to " MACSTR,
seq, MAC2STR(da));
- return wpa_drv_send_mlme(wpa_s, (u8 *) &auth, auth_length, 0, 0, 0);
+ return wpa_drv_send_mlme(wpa_s, (u8 *) &auth, auth_length, 0, 0, 0, 0);
}
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index 173d2a0cedd7..ffdaa874fd9f 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -1079,7 +1079,7 @@ static int wpas_nan_pasn_send_cb(void *ctx, const u8 *data, size_t data_len,
{
struct wpa_supplicant *wpa_s = ctx;
- return wpa_drv_send_mlme(wpa_s, data, data_len, 0, freq, 0);
+ return wpa_drv_send_mlme(wpa_s, data, data_len, 0, freq, 0, 0);
}
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 648b08bab945..6a9fc41eb0eb 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -3410,7 +3410,7 @@ static int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf,
{
struct wpa_supplicant *wpa_s = ctx;
return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
- freq, 0);
+ freq, 0, 0);
}
@@ -5800,7 +5800,7 @@ static int wpas_p2p_pasn_send_mgmt(void *ctx, const u8 *data, size_t data_len,
{
struct wpa_supplicant *wpa_s = ctx;
- return wpa_drv_send_mlme(wpa_s, data, data_len, noack, freq, wait);
+ return wpa_drv_send_mlme(wpa_s, data, data_len, noack, freq, 0, wait);
}
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index 76415fdbeed4..0d12dc99a3f6 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -77,7 +77,7 @@ static int wpas_pasn_send_mlme(void *ctx, const u8 *data, size_t data_len,
{
struct wpa_supplicant *wpa_s = ctx;
- return wpa_drv_send_mlme(wpa_s, data, data_len, noack, freq, wait);
+ return wpa_drv_send_mlme(wpa_s, data, data_len, noack, freq, 0, wait);
}
@@ -1789,7 +1789,7 @@ int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *own_addr,
* without a radio work.
*/
ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
- bss->freq, 0);
+ bss->freq, 0, 0);
wpabuf_free(buf);
wpa_printf(MSG_DEBUG, "PASN: deauth: send_mlme ret=%d", ret);
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index f02d8cbcd60b..376761417acf 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1338,6 +1338,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
os_free(params.freqs);
params.freqs = NULL;
}
+ params.freq_offset = tssid->scan_freq_offset;
freqs_set = 1;
}
int_array_sort_unique(params.freqs);
@@ -2563,20 +2564,20 @@ static void dump_scan_res(struct wpa_scan_results *scan_res)
int noise_valid = !(r->flags & WPA_SCAN_NOISE_INVALID);
wpa_printf(MSG_EXCESSIVE, MACSTR
- " ssid=%s freq=%d qual=%d noise=%d%s level=%d snr=%d%s flags=0x%x age=%u est=%u",
+ " ssid=%s freq=%d freq_offset=%d qual=%d noise=%d%s level=%d snr=%d%s flags=0x%x age=%u est=%u",
MAC2STR(r->bssid),
wpa_ssid_txt(ssid, ssid_len),
- r->freq, r->qual,
+ r->freq, r->freq_offset, r->qual,
r->noise, noise_valid ? "" : "~", r->level,
r->snr, r->snr >= GREAT_SNR ? "*" : "",
r->flags,
r->age, r->est_throughput);
} else {
wpa_printf(MSG_EXCESSIVE, MACSTR
- " ssid=%s freq=%d qual=%d noise=%d level=%d flags=0x%x age=%u est=%u",
+ " ssid=%s freq=%d freq_offset=%d qual=%d noise=%d level=%d flags=0x%x age=%u est=%u",
MAC2STR(r->bssid),
wpa_ssid_txt(ssid, ssid_len),
- r->freq, r->qual,
+ r->freq, r->freq_offset, r->qual,
r->noise, r->level, r->flags, r->age,
r->est_throughput);
}
@@ -3882,6 +3883,7 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->p2p_include_6ghz = src->p2p_include_6ghz;
params->non_coloc_6ghz = src->non_coloc_6ghz;
params->min_probe_req_content = src->min_probe_req_content;
+ params->freq_offset = src->freq_offset;
return params;
failed:
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 1279a29af915..8070b8b826fb 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1589,6 +1589,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpa_s->reassociate = 0;
params.freq = bss->freq;
+ params.freq_offset = bss->freq_offset;
params.bssid = bss->bssid;
params.ssid = bss->ssid;
params.ssid_len = bss->ssid_len;
@@ -1599,6 +1600,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpa_s->sme.prev_bssid_set = 0;
wpa_s->sme.freq = params.freq;
+ wpa_s->sme.freq_offset = params.freq_offset;
os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
wpa_s->sme.ssid_len = params.ssid_len;
@@ -2300,8 +2302,9 @@ no_fils:
wpa_supplicant_cancel_scan(wpa_s);
wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
- " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
- wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
+ " (SSID='%s' freq=%d freq_offset=%d)", MAC2STR(params.bssid),
+ wpa_ssid_txt(params.ssid, params.ssid_len),
+ params.freq, params.freq_offset);
eapol_sm_notify_portValid(wpa_s->eapol, false);
wpa_clear_keys(wpa_s, bss->bssid);
@@ -2561,7 +2564,7 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
wpa_s->sme.ext_ml_auth ?
wpa_s->own_addr : NULL);
wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
- wpa_s->sme.ext_auth_freq, 0);
+ wpa_s->sme.ext_auth_freq, 0, 0);
wpabuf_free(resp);
wpabuf_free(buf);
@@ -2680,7 +2683,7 @@ static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
wpa_s->own_addr : NULL);
wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
- wpa_s->sme.ext_auth_freq, 0);
+ wpa_s->sme.ext_auth_freq, 0, 0);
wpabuf_free(resp);
wpabuf_free(buf);
}
@@ -2884,7 +2887,7 @@ static int sme_external_auth_send_802_1x(struct wpa_supplicant *wpa_s,
wpa_s->own_addr : NULL);
if (wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf),
- 0, 0, 0) < 0) {
+ 0, 0, 0, 0) < 0) {
wpa_printf(MSG_INFO,
"IEEE 802.1X: Failed to send Authentication frame");
goto fail;
@@ -4980,6 +4983,7 @@ mscs_fail:
params.ssid = wpa_s->sme.ssid;
params.ssid_len = wpa_s->sme.ssid_len;
params.freq.freq = wpa_s->sme.freq;
+ params.freq.freq_offset = wpa_s->sme.freq_offset;
params.bg_scan_period = ssid ? ssid->bg_scan_period : -1;
params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
wpa_s->sme.assoc_req_ie : NULL;
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index 88f3f2a52356..b49da9f299d1 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -325,6 +325,7 @@ static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
params.ssid_len = assoc->ssid_len;
params.freq.mode = assoc->hwmode;
params.freq.freq = assoc->freq;
+ params.freq.freq_offset = assoc->freq_offset;
params.freq.channel = assoc->channel;
if (assoc->wpa_ie_len) {
params.wpa_ie = (u8 *) (assoc + 1);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index aa455c2041f8..71a099f9a4ed 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3557,8 +3557,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
"Driver does not support mesh mode");
return;
}
- if (bss)
+ if (bss) {
ssid->frequency = bss->freq;
+ ssid->freq_offset = bss->freq_offset;
+ }
if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
@@ -4132,6 +4134,7 @@ skip_80mhz:
info = (struct hostapd_channel_info) {
.mode = mode->mode,
.freq = freq->freq,
+ .freq_offset = freq->freq_offset,
.channel = freq->channel,
.edmg.enabled = ssid->enable_edmg,
.edmg.channel = ssid->edmg_channel,
@@ -4170,6 +4173,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
bool is_6ghz, is_24ghz;
freq->freq = ssid->frequency;
+ freq->freq_offset = ssid->freq_offset;
if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
@@ -5587,6 +5591,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
params.bssid = bss->bssid;
params.freq.freq = bss->freq;
+ params.freq.freq_offset = bss->freq_offset;
}
params.bssid_hint = bss->bssid;
params.freq_hint = bss->freq;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 4f30cff1c921..47522e33601e 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -805,6 +805,7 @@ struct wpa_supplicant {
struct wpa_bss *current_bss;
int ap_ies_from_associnfo;
unsigned int assoc_freq;
+ unsigned int assoc_freq_offset;
u8 ap_mld_addr[ETH_ALEN];
u8 mlo_assoc_link_id;
u16 valid_links; /* bitmap of valid MLO link IDs */
@@ -1110,6 +1111,7 @@ struct wpa_supplicant {
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
int freq;
+ int freq_offset;
u8 assoc_req_ie[1500];
size_t assoc_req_ie_len;
int mfp;
--
2.43.0
More information about the Hostap
mailing list