summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-04-10 21:38:36 +0200
committerJohannes Berg <johannes.berg@intel.com>2013-04-10 21:38:36 +0200
commit7b119dc06d871405fc7c3e9a73a6c987409ba639 (patch)
tree310fd45cbc44001b696b447ed64cb92792c0c2ec
parent62a40a15554d6924a58b3e9f8756e0d683dc9c0c (diff)
mac80211: fix cfg80211 interaction on auth/assoc request
If authentication (or association with FT) is requested by userspace, mac80211 currently doesn't tell cfg80211 that it disconnected from the AP. That leaves inconsistent state: cfg80211 thinks it's connected while mac80211 thinks it's not. Typically this won't last long, as soon as mac80211 reports the new association to cfg80211 the old one goes away. If, however, the new authentication or association doesn't succeed, then cfg80211 will forever think the old one still exists and will refuse attempts to authenticate or associate with the AP it thinks it's connected to. Anders reported that this leads to it taking a very long time to reconnect to a network, or never even succeeding. I tested this with an AP hacked to never respond to auth frames, and one that works, and with just those two the system never recovers because one won't work and cfg80211 thinks it's connected to the other so refuses connections to it. To fix this, simply make mac80211 tell cfg80211 when it is no longer connected to the old AP, while authenticating or associating to a new one. Cc: stable@vger.kernel.org Reported-by: Anders Kaseorg <andersk@mit.edu> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/mlme.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 82cc30318a86..346ad4cfb013 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3964,8 +3964,16 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
/* prep auth_data so we don't go into idle on disassoc */
ifmgd->auth_data = auth_data;
- if (ifmgd->associated)
- ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+ if (ifmgd->associated) {
+ u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+ ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_UNSPECIFIED,
+ false, frame_buf);
+
+ __cfg80211_send_deauth(sdata->dev, frame_buf,
+ sizeof(frame_buf));
+ }
sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
@@ -4025,8 +4033,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
mutex_lock(&ifmgd->mtx);
- if (ifmgd->associated)
- ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+ if (ifmgd->associated) {
+ u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+ ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_UNSPECIFIED,
+ false, frame_buf);
+
+ __cfg80211_send_deauth(sdata->dev, frame_buf,
+ sizeof(frame_buf));
+ }
if (ifmgd->auth_data && !ifmgd->auth_data->done) {
err = -EBUSY;