aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/sme.c')
-rw-r--r--net/wireless/sme.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 219c3bc2c37d..104b33e34d22 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -27,10 +27,10 @@ struct cfg80211_conn {
27 CFG80211_CONN_ASSOCIATE_NEXT, 27 CFG80211_CONN_ASSOCIATE_NEXT,
28 CFG80211_CONN_ASSOCIATING, 28 CFG80211_CONN_ASSOCIATING,
29 } state; 29 } state;
30 u8 bssid[ETH_ALEN]; 30 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
31 u8 *ie; 31 u8 *ie;
32 size_t ie_len; 32 size_t ie_len;
33 bool auto_auth; 33 bool auto_auth, prev_bssid_valid;
34}; 34};
35 35
36 36
@@ -110,6 +110,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
110{ 110{
111 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 111 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
112 struct cfg80211_connect_params *params; 112 struct cfg80211_connect_params *params;
113 const u8 *prev_bssid = NULL;
113 int err; 114 int err;
114 115
115 ASSERT_WDEV_LOCK(wdev); 116 ASSERT_WDEV_LOCK(wdev);
@@ -135,15 +136,11 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
135 case CFG80211_CONN_ASSOCIATE_NEXT: 136 case CFG80211_CONN_ASSOCIATE_NEXT:
136 BUG_ON(!rdev->ops->assoc); 137 BUG_ON(!rdev->ops->assoc);
137 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 138 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
138 /* 139 if (wdev->conn->prev_bssid_valid)
139 * We could, later, implement roaming here and then actually 140 prev_bssid = wdev->conn->prev_bssid;
140 * set prev_bssid to non-NULL. But then we need to be aware
141 * that some APs don't like that -- so we'd need to retry
142 * the association.
143 */
144 err = __cfg80211_mlme_assoc(rdev, wdev->netdev, 141 err = __cfg80211_mlme_assoc(rdev, wdev->netdev,
145 params->channel, params->bssid, 142 params->channel, params->bssid,
146 NULL, 143 prev_bssid,
147 params->ssid, params->ssid_len, 144 params->ssid, params->ssid_len,
148 params->ie, params->ie_len, 145 params->ie, params->ie_len,
149 false, &params->crypto); 146 false, &params->crypto);
@@ -316,6 +313,28 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
316 } 313 }
317} 314}
318 315
316bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
317{
318 struct wiphy *wiphy = wdev->wiphy;
319 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
320
321 if (WARN_ON(!wdev->conn))
322 return false;
323
324 if (!wdev->conn->prev_bssid_valid)
325 return false;
326
327 /*
328 * Some stupid APs don't accept reassoc, so we
329 * need to fall back to trying regular assoc.
330 */
331 wdev->conn->prev_bssid_valid = false;
332 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
333 schedule_work(&rdev->conn_work);
334
335 return true;
336}
337
319void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 338void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
320 const u8 *req_ie, size_t req_ie_len, 339 const u8 *req_ie, size_t req_ie_len,
321 const u8 *resp_ie, size_t resp_ie_len, 340 const u8 *resp_ie, size_t resp_ie_len,
@@ -359,8 +378,11 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
359 378
360 memset(&wrqu, 0, sizeof(wrqu)); 379 memset(&wrqu, 0, sizeof(wrqu));
361 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 380 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
362 if (bssid && status == WLAN_STATUS_SUCCESS) 381 if (bssid && status == WLAN_STATUS_SUCCESS) {
363 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 382 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
383 memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
384 wdev->wext.prev_bssid_valid = true;
385 }
364 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 386 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
365 } 387 }
366#endif 388#endif
@@ -511,6 +533,8 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
511 memset(&wrqu, 0, sizeof(wrqu)); 533 memset(&wrqu, 0, sizeof(wrqu));
512 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 534 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
513 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 535 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
536 memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
537 wdev->wext.prev_bssid_valid = true;
514 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL); 538 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
515#endif 539#endif
516} 540}
@@ -643,7 +667,8 @@ EXPORT_SYMBOL(cfg80211_disconnected);
643int __cfg80211_connect(struct cfg80211_registered_device *rdev, 667int __cfg80211_connect(struct cfg80211_registered_device *rdev,
644 struct net_device *dev, 668 struct net_device *dev,
645 struct cfg80211_connect_params *connect, 669 struct cfg80211_connect_params *connect,
646 struct cfg80211_cached_keys *connkeys) 670 struct cfg80211_cached_keys *connkeys,
671 const u8 *prev_bssid)
647{ 672{
648 struct wireless_dev *wdev = dev->ieee80211_ptr; 673 struct wireless_dev *wdev = dev->ieee80211_ptr;
649 struct ieee80211_channel *chan; 674 struct ieee80211_channel *chan;
@@ -742,6 +767,11 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
742 wdev->sme_state = CFG80211_SME_CONNECTING; 767 wdev->sme_state = CFG80211_SME_CONNECTING;
743 wdev->connect_keys = connkeys; 768 wdev->connect_keys = connkeys;
744 769
770 if (prev_bssid) {
771 memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
772 wdev->conn->prev_bssid_valid = true;
773 }
774
745 /* we're good if we have both BSSID and channel */ 775 /* we're good if we have both BSSID and channel */
746 if (wdev->conn->params.bssid && wdev->conn->params.channel) { 776 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
747 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; 777 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
@@ -794,7 +824,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
794 824
795 mutex_lock(&rdev->devlist_mtx); 825 mutex_lock(&rdev->devlist_mtx);
796 wdev_lock(dev->ieee80211_ptr); 826 wdev_lock(dev->ieee80211_ptr);
797 err = __cfg80211_connect(rdev, dev, connect, connkeys); 827 err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
798 wdev_unlock(dev->ieee80211_ptr); 828 wdev_unlock(dev->ieee80211_ptr);
799 mutex_unlock(&rdev->devlist_mtx); 829 mutex_unlock(&rdev->devlist_mtx);
800 830