Skip to content

Commit 9cc899a

Browse files
jmberg-intelopsiff
authored andcommitted
wifi: mac80211: improve CSA/ECSA connection refusal
mainline inclusion from mainline-v6.8-rc4 category: bugfix As mentioned in the previous commit, we pretty quickly found that some APs have ECSA elements stuck in their probe response, so using that to not attempt to connect while CSA is happening we never connect to such an AP. Improve this situation by checking more carefully and ignoring the ECSA if cfg80211 has previously detected the ECSA element being stuck in the probe response. Additionally, allow connecting to an AP that's switching to a channel it's already using, unless it's using quiet mode. In this case, we may just have to adjust bandwidth later. If it's actually switching channels, it's better not to try to connect in the middle of that. Reported-by: coldolt <andypalmadi@gmail.com> Closes: https://lore.kernel.org/linux-wireless/CAJvGw+DQhBk_mHXeu6RTOds5iramMW2FbMB01VbKRA4YbHHDTA@mail.gmail.com/ Fixes: c09c4f3 ("wifi: mac80211: don't connect to an AP while it's in a CSA process") Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com> Link: https://msgid.link/20240129131413.cc2d0a26226e.I682c016af76e35b6c47007db50e8554c5a426910@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com> (cherry picked from commit 35e2385) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
1 parent cb5da4a commit 9cc899a

1 file changed

Lines changed: 76 additions & 27 deletions

File tree

net/mac80211/mlme.c

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7126,14 +7126,82 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
71267126
return err;
71277127
}
71287128

7129+
static bool ieee80211_mgd_csa_present(struct ieee80211_sub_if_data *sdata,
7130+
const struct cfg80211_bss_ies *ies,
7131+
u8 cur_channel, bool ignore_ecsa)
7132+
{
7133+
const struct element *csa_elem, *ecsa_elem;
7134+
struct ieee80211_channel_sw_ie *csa = NULL;
7135+
struct ieee80211_ext_chansw_ie *ecsa = NULL;
7136+
7137+
if (!ies)
7138+
return false;
7139+
7140+
csa_elem = cfg80211_find_elem(WLAN_EID_CHANNEL_SWITCH,
7141+
ies->data, ies->len);
7142+
if (csa_elem && csa_elem->datalen == sizeof(*csa))
7143+
csa = (void *)csa_elem->data;
7144+
7145+
ecsa_elem = cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN,
7146+
ies->data, ies->len);
7147+
if (ecsa_elem && ecsa_elem->datalen == sizeof(*ecsa))
7148+
ecsa = (void *)ecsa_elem->data;
7149+
7150+
if (csa && csa->count == 0)
7151+
csa = NULL;
7152+
if (csa && !csa->mode && csa->new_ch_num == cur_channel)
7153+
csa = NULL;
7154+
7155+
if (ecsa && ecsa->count == 0)
7156+
ecsa = NULL;
7157+
if (ecsa && !ecsa->mode && ecsa->new_ch_num == cur_channel)
7158+
ecsa = NULL;
7159+
7160+
if (ignore_ecsa && ecsa) {
7161+
sdata_info(sdata,
7162+
"Ignoring ECSA in probe response - was considered stuck!\n");
7163+
return csa;
7164+
}
7165+
7166+
return csa || ecsa;
7167+
}
7168+
7169+
static bool ieee80211_mgd_csa_in_process(struct ieee80211_sub_if_data *sdata,
7170+
struct cfg80211_bss *bss)
7171+
{
7172+
u8 cur_channel;
7173+
bool ret;
7174+
7175+
cur_channel = ieee80211_frequency_to_channel(bss->channel->center_freq);
7176+
7177+
rcu_read_lock();
7178+
if (ieee80211_mgd_csa_present(sdata,
7179+
rcu_dereference(bss->beacon_ies),
7180+
cur_channel, false)) {
7181+
ret = true;
7182+
goto out;
7183+
}
7184+
7185+
if (ieee80211_mgd_csa_present(sdata,
7186+
rcu_dereference(bss->proberesp_ies),
7187+
cur_channel, bss->proberesp_ecsa_stuck)) {
7188+
ret = true;
7189+
goto out;
7190+
}
7191+
7192+
ret = false;
7193+
out:
7194+
rcu_read_unlock();
7195+
return ret;
7196+
}
7197+
71297198
/* config hooks */
71307199
int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
71317200
struct cfg80211_auth_request *req)
71327201
{
71337202
struct ieee80211_local *local = sdata->local;
71347203
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
71357204
struct ieee80211_mgd_auth_data *auth_data;
7136-
const struct element *csa_elem, *ecsa_elem;
71377205
u16 auth_alg;
71387206
int err;
71397207
bool cont_auth;
@@ -7174,21 +7242,10 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
71747242
if (ifmgd->assoc_data)
71757243
return -EBUSY;
71767244

7177-
rcu_read_lock();
7178-
csa_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_CHANNEL_SWITCH);
7179-
ecsa_elem = ieee80211_bss_get_elem(req->bss,
7180-
WLAN_EID_EXT_CHANSWITCH_ANN);
7181-
if ((csa_elem &&
7182-
csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) &&
7183-
((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) ||
7184-
(ecsa_elem &&
7185-
ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) &&
7186-
((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) {
7187-
rcu_read_unlock();
7245+
if (ieee80211_mgd_csa_in_process(sdata, req->bss)) {
71887246
sdata_info(sdata, "AP is in CSA process, reject auth\n");
71897247
return -EINVAL;
71907248
}
7191-
rcu_read_unlock();
71927249

71937250
auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
71947251
req->ie_len, GFP_KERNEL);
@@ -7483,7 +7540,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
74837540
struct ieee80211_local *local = sdata->local;
74847541
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
74857542
struct ieee80211_mgd_assoc_data *assoc_data;
7486-
const struct element *ssid_elem, *csa_elem, *ecsa_elem;
7543+
const struct element *ssid_elem;
74877544
struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
74887545
ieee80211_conn_flags_t conn_flags = 0;
74897546
struct ieee80211_link_data *link;
@@ -7506,23 +7563,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
75067563

75077564
cbss = req->link_id < 0 ? req->bss : req->links[req->link_id].bss;
75087565

7509-
rcu_read_lock();
7510-
ssid_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_SSID);
7511-
if (!ssid_elem || ssid_elem->datalen > sizeof(assoc_data->ssid)) {
7512-
rcu_read_unlock();
7566+
if (ieee80211_mgd_csa_in_process(sdata, cbss)) {
7567+
sdata_info(sdata, "AP is in CSA process, reject assoc\n");
75137568
kfree(assoc_data);
75147569
return -EINVAL;
75157570
}
75167571

7517-
csa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_CHANNEL_SWITCH);
7518-
ecsa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_EXT_CHANSWITCH_ANN);
7519-
if ((csa_elem &&
7520-
csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) &&
7521-
((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) ||
7522-
(ecsa_elem &&
7523-
ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) &&
7524-
((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) {
7525-
sdata_info(sdata, "AP is in CSA process, reject assoc\n");
7572+
rcu_read_lock();
7573+
ssid_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_SSID);
7574+
if (!ssid_elem || ssid_elem->datalen > sizeof(assoc_data->ssid)) {
75267575
rcu_read_unlock();
75277576
kfree(assoc_data);
75287577
return -EINVAL;

0 commit comments

Comments
 (0)