aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-04-10 15:38:36 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-10 15:38:36 -0400
commit7b119dc06d871405fc7c3e9a73a6c987409ba639 (patch)
tree310fd45cbc44001b696b447ed64cb92792c0c2ec /net
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>
Diffstat (limited to 'net')
-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,
3964 /* prep auth_data so we don't go into idle on disassoc */ 3964 /* prep auth_data so we don't go into idle on disassoc */
3965 ifmgd->auth_data = auth_data; 3965 ifmgd->auth_data = auth_data;
3966 3966
3967 if (ifmgd->associated) 3967 if (ifmgd->associated) {
3968 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 3968 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3969
3970 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3971 WLAN_REASON_UNSPECIFIED,
3972 false, frame_buf);
3973
3974 __cfg80211_send_deauth(sdata->dev, frame_buf,
3975 sizeof(frame_buf));
3976 }
3969 3977
3970 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); 3978 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
3971 3979
@@ -4025,8 +4033,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4025 4033
4026 mutex_lock(&ifmgd->mtx); 4034 mutex_lock(&ifmgd->mtx);
4027 4035
4028 if (ifmgd->associated) 4036 if (ifmgd->associated) {
4029 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 4037 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
4038
4039 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
4040 WLAN_REASON_UNSPECIFIED,
4041 false, frame_buf);
4042
4043 __cfg80211_send_deauth(sdata->dev, frame_buf,
4044 sizeof(frame_buf));
4045 }
4030 4046
4031 if (ifmgd->auth_data && !ifmgd->auth_data->done) { 4047 if (ifmgd->auth_data && !ifmgd->auth_data->done) {
4032 err = -EBUSY; 4048 err = -EBUSY;