diff options
Diffstat (limited to 'net/wireless/sme.c')
-rw-r--r-- | net/wireless/sme.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index d2b5d4ce0a00..8a7dcbf90602 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <net/cfg80211.h> | 13 | #include <net/cfg80211.h> |
14 | #include <net/rtnetlink.h> | 14 | #include <net/rtnetlink.h> |
15 | #include "nl80211.h" | 15 | #include "nl80211.h" |
16 | #include "reg.h" | ||
16 | 17 | ||
17 | struct cfg80211_conn { | 18 | struct cfg80211_conn { |
18 | struct cfg80211_connect_params params; | 19 | struct cfg80211_connect_params params; |
@@ -182,7 +183,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
182 | wdev->conn->params.bssid, | 183 | wdev->conn->params.bssid, |
183 | NULL, 0, NULL, 0, | 184 | NULL, 0, NULL, 0, |
184 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 185 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
185 | false); | 186 | false, NULL); |
186 | wdev_unlock(wdev); | 187 | wdev_unlock(wdev); |
187 | } | 188 | } |
188 | 189 | ||
@@ -247,7 +248,7 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) | |||
247 | wdev->conn->params.bssid, | 248 | wdev->conn->params.bssid, |
248 | NULL, 0, NULL, 0, | 249 | NULL, 0, NULL, 0, |
249 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 250 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
250 | false); | 251 | false, NULL); |
251 | } | 252 | } |
252 | } | 253 | } |
253 | 254 | ||
@@ -305,7 +306,7 @@ void cfg80211_sme_rx_auth(struct net_device *dev, | |||
305 | schedule_work(&rdev->conn_work); | 306 | schedule_work(&rdev->conn_work); |
306 | } else if (status_code != WLAN_STATUS_SUCCESS) { | 307 | } else if (status_code != WLAN_STATUS_SUCCESS) { |
307 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, | 308 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, |
308 | status_code, false); | 309 | status_code, false, NULL); |
309 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING && | 310 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING && |
310 | wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { | 311 | wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { |
311 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; | 312 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; |
@@ -316,10 +317,11 @@ void cfg80211_sme_rx_auth(struct net_device *dev, | |||
316 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 317 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
317 | const u8 *req_ie, size_t req_ie_len, | 318 | const u8 *req_ie, size_t req_ie_len, |
318 | const u8 *resp_ie, size_t resp_ie_len, | 319 | const u8 *resp_ie, size_t resp_ie_len, |
319 | u16 status, bool wextev) | 320 | u16 status, bool wextev, |
321 | struct cfg80211_bss *bss) | ||
320 | { | 322 | { |
321 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 323 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
322 | struct cfg80211_bss *bss; | 324 | u8 *country_ie; |
323 | #ifdef CONFIG_WIRELESS_EXT | 325 | #ifdef CONFIG_WIRELESS_EXT |
324 | union iwreq_data wrqu; | 326 | union iwreq_data wrqu; |
325 | #endif | 327 | #endif |
@@ -361,6 +363,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
361 | } | 363 | } |
362 | #endif | 364 | #endif |
363 | 365 | ||
366 | if (wdev->current_bss) { | ||
367 | cfg80211_unhold_bss(wdev->current_bss); | ||
368 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
369 | wdev->current_bss = NULL; | ||
370 | } | ||
371 | |||
364 | if (status == WLAN_STATUS_SUCCESS && | 372 | if (status == WLAN_STATUS_SUCCESS && |
365 | wdev->sme_state == CFG80211_SME_IDLE) | 373 | wdev->sme_state == CFG80211_SME_IDLE) |
366 | goto success; | 374 | goto success; |
@@ -368,12 +376,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
368 | if (wdev->sme_state != CFG80211_SME_CONNECTING) | 376 | if (wdev->sme_state != CFG80211_SME_CONNECTING) |
369 | return; | 377 | return; |
370 | 378 | ||
371 | if (wdev->current_bss) { | ||
372 | cfg80211_unhold_bss(wdev->current_bss); | ||
373 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
374 | wdev->current_bss = NULL; | ||
375 | } | ||
376 | |||
377 | if (wdev->conn) | 379 | if (wdev->conn) |
378 | wdev->conn->state = CFG80211_CONN_IDLE; | 380 | wdev->conn->state = CFG80211_CONN_IDLE; |
379 | 381 | ||
@@ -383,13 +385,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
383 | wdev->conn = NULL; | 385 | wdev->conn = NULL; |
384 | kfree(wdev->connect_keys); | 386 | kfree(wdev->connect_keys); |
385 | wdev->connect_keys = NULL; | 387 | wdev->connect_keys = NULL; |
388 | wdev->ssid_len = 0; | ||
386 | return; | 389 | return; |
387 | } | 390 | } |
388 | 391 | ||
389 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 392 | success: |
390 | wdev->ssid, wdev->ssid_len, | 393 | if (!bss) |
391 | WLAN_CAPABILITY_ESS, | 394 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, |
392 | WLAN_CAPABILITY_ESS); | 395 | wdev->ssid, wdev->ssid_len, |
396 | WLAN_CAPABILITY_ESS, | ||
397 | WLAN_CAPABILITY_ESS); | ||
393 | 398 | ||
394 | if (WARN_ON(!bss)) | 399 | if (WARN_ON(!bss)) |
395 | return; | 400 | return; |
@@ -397,9 +402,22 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
397 | cfg80211_hold_bss(bss_from_pub(bss)); | 402 | cfg80211_hold_bss(bss_from_pub(bss)); |
398 | wdev->current_bss = bss_from_pub(bss); | 403 | wdev->current_bss = bss_from_pub(bss); |
399 | 404 | ||
400 | success: | ||
401 | wdev->sme_state = CFG80211_SME_CONNECTED; | 405 | wdev->sme_state = CFG80211_SME_CONNECTED; |
402 | cfg80211_upload_connect_keys(wdev); | 406 | cfg80211_upload_connect_keys(wdev); |
407 | |||
408 | country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); | ||
409 | |||
410 | if (!country_ie) | ||
411 | return; | ||
412 | |||
413 | /* | ||
414 | * ieee80211_bss_get_ie() ensures we can access: | ||
415 | * - country_ie + 2, the start of the country ie data, and | ||
416 | * - and country_ie[1] which is the IE length | ||
417 | */ | ||
418 | regulatory_hint_11d(wdev->wiphy, | ||
419 | country_ie + 2, | ||
420 | country_ie[1]); | ||
403 | } | 421 | } |
404 | 422 | ||
405 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 423 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
@@ -549,6 +567,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
549 | 567 | ||
550 | wdev->current_bss = NULL; | 568 | wdev->current_bss = NULL; |
551 | wdev->sme_state = CFG80211_SME_IDLE; | 569 | wdev->sme_state = CFG80211_SME_IDLE; |
570 | wdev->ssid_len = 0; | ||
552 | 571 | ||
553 | if (wdev->conn) { | 572 | if (wdev->conn) { |
554 | kfree(wdev->conn->ie); | 573 | kfree(wdev->conn->ie); |
@@ -704,6 +723,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
704 | wdev->conn = NULL; | 723 | wdev->conn = NULL; |
705 | wdev->sme_state = CFG80211_SME_IDLE; | 724 | wdev->sme_state = CFG80211_SME_IDLE; |
706 | wdev->connect_keys = NULL; | 725 | wdev->connect_keys = NULL; |
726 | wdev->ssid_len = 0; | ||
707 | } | 727 | } |
708 | 728 | ||
709 | return err; | 729 | return err; |
@@ -768,6 +788,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
768 | wdev->sme_state = CFG80211_SME_IDLE; | 788 | wdev->sme_state = CFG80211_SME_IDLE; |
769 | kfree(wdev->conn); | 789 | kfree(wdev->conn); |
770 | wdev->conn = NULL; | 790 | wdev->conn = NULL; |
791 | wdev->ssid_len = 0; | ||
771 | return 0; | 792 | return 0; |
772 | } | 793 | } |
773 | 794 | ||
@@ -788,7 +809,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
788 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) | 809 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) |
789 | __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, | 810 | __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, |
790 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 811 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
791 | wextev); | 812 | wextev, NULL); |
792 | 813 | ||
793 | return 0; | 814 | return 0; |
794 | } | 815 | } |