aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg2013-04-10 14:38:36 -0500
committerGreg Kroah-Hartman2013-04-25 14:51:22 -0500
commit7ac7dd50d62c02b055f4e7f53b39040f863ff48a (patch)
tree03eea3c334384c655d06117ef2c1014f10a46cb1 /net
parent42a2d01229b66c76d96fc2e5eb96e8d9c3caaac0 (diff)
downloadkernel-video-7ac7dd50d62c02b055f4e7f53b39040f863ff48a.tar.gz
kernel-video-7ac7dd50d62c02b055f4e7f53b39040f863ff48a.tar.xz
kernel-video-7ac7dd50d62c02b055f4e7f53b39040f863ff48a.zip
mac80211: fix cfg80211 interaction on auth/assoc request
commit 7b119dc06d871405fc7c3e9a73a6c987409ba639 upstream. 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. Reported-by: Anders Kaseorg <andersk@mit.edu> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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 e14e676d3bd..a1a799755c7 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3723,8 +3723,16 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
3723 /* prep auth_data so we don't go into idle on disassoc */ 3723 /* prep auth_data so we don't go into idle on disassoc */
3724 ifmgd->auth_data = auth_data; 3724 ifmgd->auth_data = auth_data;
3725 3725
3726 if (ifmgd->associated) 3726 if (ifmgd->associated) {
3727 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 3727 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3728
3729 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3730 WLAN_REASON_UNSPECIFIED,
3731 false, frame_buf);
3732
3733 __cfg80211_send_deauth(sdata->dev, frame_buf,
3734 sizeof(frame_buf));
3735 }
3728 3736
3729 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); 3737 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
3730 3738
@@ -3783,8 +3791,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3783 3791
3784 mutex_lock(&ifmgd->mtx); 3792 mutex_lock(&ifmgd->mtx);
3785 3793
3786 if (ifmgd->associated) 3794 if (ifmgd->associated) {
3787 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 3795 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3796
3797 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3798 WLAN_REASON_UNSPECIFIED,
3799 false, frame_buf);
3800
3801 __cfg80211_send_deauth(sdata->dev, frame_buf,
3802 sizeof(frame_buf));
3803 }
3788 3804
3789 if (ifmgd->auth_data && !ifmgd->auth_data->done) { 3805 if (ifmgd->auth_data && !ifmgd->auth_data->done) {
3790 err = -EBUSY; 3806 err = -EBUSY;