aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-07 08:51:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:43 -0400
commitf401a6f7ede753e56b84025e7d2db0d5ef560ce6 (patch)
tree12b077096234ba0f990c637665d11e0afa608b17 /net/wireless/sme.c
parent59bbb6f7574bc693ed8313b98eac641116c95b94 (diff)
cfg80211: use reassociation when possible
With the move of everything related to the SME from mac80211 to cfg80211, we lost the ability to send reassociation frames. This adds them back, but only for wireless extensions. With the userspace SME, it shall control assoc vs. reassoc (it already can do so with the nl80211 interface). I haven't touched the connect() implementation, so it is not possible to reassociate with the nl80211 connect primitive. I think that should be done with the NL80211_CMD_ROAM command, but we'll have to see how that can be handled in the future, especially with fullmac chips. This patch addresses only the immediate regression we had in mac80211, which previously sent reassoc. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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