summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-11-17 21:35:38 +0200
committerJohn W. Linville <linville@tuxdriver.com>2009-11-18 17:09:24 -0500
commit24b6b15f7d07d26330f73057d618089976a08792 (patch)
tree52bf74ad76afae6fecce3f5ff75dfc027971d9b2
parentaf65cd96dd4ea8ea5adc6ee850e61a407cd1067a (diff)
downloadlinux-24b6b15f7d07d26330f73057d618089976a08792.tar.bz2
cfg80211: Allow reassociation in associated state
cfg80211 rejects all association requests when in associated state. This prevents clean roaming within an ESS since one would first need to disassociate before being able to request reassociation. Accept the reassociation request and let the old association to be dropped when the new one is completed. This fixes nl80211-based roaming with the current snapshot version of wpa_supplicant (that has code for requesting reassociation explicitly withthe previous BSSID attribute). Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/wireless/mlme.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 2610b746effa..622af5649b9a 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -446,12 +446,23 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct cfg80211_assoc_request req;
struct cfg80211_internal_bss *bss;
int i, err, slot = -1;
+ bool was_connected = false;
ASSERT_WDEV_LOCK(wdev);
memset(&req, 0, sizeof(req));
- if (wdev->current_bss)
+ if (wdev->current_bss && prev_bssid &&
+ memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
+ /*
+ * Trying to reassociate: Allow this to proceed and let the old
+ * association to be dropped when the new one is completed.
+ */
+ if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+ was_connected = true;
+ wdev->sme_state = CFG80211_SME_CONNECTING;
+ }
+ } else if (wdev->current_bss)
return -EALREADY;
req.ie = ie;
@@ -461,8 +472,11 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
req.prev_bssid = prev_bssid;
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
- if (!req.bss)
+ if (!req.bss) {
+ if (was_connected)
+ wdev->sme_state = CFG80211_SME_CONNECTED;
return -ENOENT;
+ }
bss = bss_from_pub(req.bss);
@@ -480,6 +494,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
out:
+ if (err && was_connected)
+ wdev->sme_state = CFG80211_SME_CONNECTED;
/* still a reference in wdev->auth_bsses[slot] */
cfg80211_put_bss(req.bss);
return err;