diff options
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r-- | net/wireless/mlme.c | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 2610b746effa..1001db4912f7 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -243,21 +243,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
243 | } | 243 | } |
244 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 244 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
245 | 245 | ||
246 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 246 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) |
247 | { | 247 | { |
248 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
249 | struct wiphy *wiphy = wdev->wiphy; | ||
250 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
251 | int i; | 248 | int i; |
252 | bool done = false; | 249 | bool done = false; |
253 | 250 | ||
254 | wdev_lock(wdev); | 251 | ASSERT_WDEV_LOCK(wdev); |
255 | |||
256 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); | ||
257 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | ||
258 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | ||
259 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
260 | false, NULL); | ||
261 | 252 | ||
262 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 253 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
263 | if (wdev->authtry_bsses[i] && | 254 | if (wdev->authtry_bsses[i] && |
@@ -272,6 +263,29 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
272 | } | 263 | } |
273 | 264 | ||
274 | WARN_ON(!done); | 265 | WARN_ON(!done); |
266 | } | ||
267 | |||
268 | void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) | ||
269 | { | ||
270 | __cfg80211_auth_remove(dev->ieee80211_ptr, addr); | ||
271 | } | ||
272 | EXPORT_SYMBOL(__cfg80211_auth_canceled); | ||
273 | |||
274 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | ||
275 | { | ||
276 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
277 | struct wiphy *wiphy = wdev->wiphy; | ||
278 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
279 | |||
280 | wdev_lock(wdev); | ||
281 | |||
282 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); | ||
283 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | ||
284 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | ||
285 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
286 | false, NULL); | ||
287 | |||
288 | __cfg80211_auth_remove(wdev, addr); | ||
275 | 289 | ||
276 | wdev_unlock(wdev); | 290 | wdev_unlock(wdev); |
277 | } | 291 | } |
@@ -446,12 +460,23 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
446 | struct cfg80211_assoc_request req; | 460 | struct cfg80211_assoc_request req; |
447 | struct cfg80211_internal_bss *bss; | 461 | struct cfg80211_internal_bss *bss; |
448 | int i, err, slot = -1; | 462 | int i, err, slot = -1; |
463 | bool was_connected = false; | ||
449 | 464 | ||
450 | ASSERT_WDEV_LOCK(wdev); | 465 | ASSERT_WDEV_LOCK(wdev); |
451 | 466 | ||
452 | memset(&req, 0, sizeof(req)); | 467 | memset(&req, 0, sizeof(req)); |
453 | 468 | ||
454 | if (wdev->current_bss) | 469 | if (wdev->current_bss && prev_bssid && |
470 | memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) { | ||
471 | /* | ||
472 | * Trying to reassociate: Allow this to proceed and let the old | ||
473 | * association to be dropped when the new one is completed. | ||
474 | */ | ||
475 | if (wdev->sme_state == CFG80211_SME_CONNECTED) { | ||
476 | was_connected = true; | ||
477 | wdev->sme_state = CFG80211_SME_CONNECTING; | ||
478 | } | ||
479 | } else if (wdev->current_bss) | ||
455 | return -EALREADY; | 480 | return -EALREADY; |
456 | 481 | ||
457 | req.ie = ie; | 482 | req.ie = ie; |
@@ -461,8 +486,11 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
461 | req.prev_bssid = prev_bssid; | 486 | req.prev_bssid = prev_bssid; |
462 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 487 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
463 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 488 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
464 | if (!req.bss) | 489 | if (!req.bss) { |
490 | if (was_connected) | ||
491 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
465 | return -ENOENT; | 492 | return -ENOENT; |
493 | } | ||
466 | 494 | ||
467 | bss = bss_from_pub(req.bss); | 495 | bss = bss_from_pub(req.bss); |
468 | 496 | ||
@@ -480,6 +508,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
480 | 508 | ||
481 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); | 509 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); |
482 | out: | 510 | out: |
511 | if (err && was_connected) | ||
512 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
483 | /* still a reference in wdev->auth_bsses[slot] */ | 513 | /* still a reference in wdev->auth_bsses[slot] */ |
484 | cfg80211_put_bss(req.bss); | 514 | cfg80211_put_bss(req.bss); |
485 | return err; | 515 | return err; |