Commit c09c4f31 authored by Ayala Beker's avatar Ayala Beker Committed by Johannes Berg

wifi: mac80211: don't connect to an AP while it's in a CSA process

Connection to an AP that is running a CSA flow may end up with a
failure as the AP might change its channel during the connection
flow while we do not track the channel change yet.
Avoid that by rejecting a connection to such an AP.
Signed-off-by: default avatarAyala Beker <ayala.beker@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230920211508.e5001a762a4a.I9745c695f3403b259ad000ce94110588a836c04a@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2bf57b00
...@@ -7015,6 +7015,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, ...@@ -7015,6 +7015,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_mgd_auth_data *auth_data; struct ieee80211_mgd_auth_data *auth_data;
struct ieee80211_link_data *link; struct ieee80211_link_data *link;
const struct element *csa_elem, *ecsa_elem;
u16 auth_alg; u16 auth_alg;
int err; int err;
bool cont_auth; bool cont_auth;
...@@ -7057,6 +7058,22 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, ...@@ -7057,6 +7058,22 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
if (ifmgd->assoc_data) if (ifmgd->assoc_data)
return -EBUSY; return -EBUSY;
rcu_read_lock();
csa_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_CHANNEL_SWITCH);
ecsa_elem = ieee80211_bss_get_elem(req->bss,
WLAN_EID_EXT_CHANSWITCH_ANN);
if ((csa_elem &&
csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) &&
((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) ||
(ecsa_elem &&
ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) &&
((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) {
rcu_read_unlock();
sdata_info(sdata, "AP is in CSA process, reject auth\n");
return -EINVAL;
}
rcu_read_unlock();
auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len + auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
req->ie_len, GFP_KERNEL); req->ie_len, GFP_KERNEL);
if (!auth_data) if (!auth_data)
...@@ -7364,7 +7381,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -7364,7 +7381,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_mgd_assoc_data *assoc_data; struct ieee80211_mgd_assoc_data *assoc_data;
const struct element *ssid_elem; const struct element *ssid_elem, *csa_elem, *ecsa_elem;
struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg; struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
ieee80211_conn_flags_t conn_flags = 0; ieee80211_conn_flags_t conn_flags = 0;
struct ieee80211_link_data *link; struct ieee80211_link_data *link;
...@@ -7394,6 +7411,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ...@@ -7394,6 +7411,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
kfree(assoc_data); kfree(assoc_data);
return -EINVAL; return -EINVAL;
} }
csa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_CHANNEL_SWITCH);
ecsa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_EXT_CHANSWITCH_ANN);
if ((csa_elem &&
csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) &&
((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) ||
(ecsa_elem &&
ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) &&
((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) {
sdata_info(sdata, "AP is in CSA process, reject assoc\n");
rcu_read_unlock();
kfree(assoc_data);
return -EINVAL;
}
memcpy(assoc_data->ssid, ssid_elem->data, ssid_elem->datalen); memcpy(assoc_data->ssid, ssid_elem->data, ssid_elem->datalen);
assoc_data->ssid_len = ssid_elem->datalen; assoc_data->ssid_len = ssid_elem->datalen;
memcpy(vif_cfg->ssid, assoc_data->ssid, assoc_data->ssid_len); memcpy(vif_cfg->ssid, assoc_data->ssid, assoc_data->ssid_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment