diff options
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r-- | net/wireless/mlme.c | 333 |
1 files changed, 59 insertions, 274 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 438dfc105b4a..f5a7ac3a0939 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -20,40 +20,18 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; - u8 *bssid = mgmt->bssid; - int i; - u16 status = le16_to_cpu(mgmt->u.auth.status_code); - bool done = false; wdev_lock(wdev); - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] && - memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, - ETH_ALEN) == 0) { - if (status == WLAN_STATUS_SUCCESS) { - wdev->auth_bsses[i] = wdev->authtry_bsses[i]; - } else { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - } - wdev->authtry_bsses[i] = NULL; - done = true; - break; - } - } - - if (done) { - nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); - cfg80211_sme_rx_auth(dev, buf, len); - } + nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); + cfg80211_sme_rx_auth(dev, buf, len); wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_rx_auth); -void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) +void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, + const u8 *buf, size_t len) { u16 status_code; struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -61,8 +39,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; u8 *ie = mgmt->u.assoc_resp.variable; - int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - struct cfg80211_internal_bss *bss = NULL; + int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); wdev_lock(wdev); @@ -75,43 +52,20 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) * frame instead of reassoc. */ if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && - cfg80211_sme_failed_reassoc(wdev)) + cfg80211_sme_failed_reassoc(wdev)) { + cfg80211_put_bss(bss); goto out; + } nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); - if (status_code == WLAN_STATUS_SUCCESS) { - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (!wdev->auth_bsses[i]) - continue; - if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, - ETH_ALEN) == 0) { - bss = wdev->auth_bsses[i]; - wdev->auth_bsses[i] = NULL; - /* additional reference to drop hold */ - cfg80211_ref_bss(bss); - break; - } - } - - /* - * We might be coming here because the driver reported - * a successful association at the same time as the - * user requested a deauth. In that case, we will have - * removed the BSS from the auth_bsses list due to the - * deauth request when the assoc response makes it. If - * the two code paths acquire the lock the other way - * around, that's just the standard situation of a - * deauth being requested while connected. - */ - if (!bss) - goto out; - } else if (wdev->conn) { + if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) { cfg80211_sme_failed_assoc(wdev); /* * do not call connect_result() now because the * sme will schedule work that does it later. */ + cfg80211_put_bss(bss); goto out; } @@ -124,17 +78,10 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) wdev->sme_state = CFG80211_SME_CONNECTING; } - /* this consumes one bss reference (unless bss is NULL) */ + /* this consumes the bss reference */ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, - status_code == WLAN_STATUS_SUCCESS, - bss ? &bss->pub : NULL); - /* drop hold now, and also reference acquired above */ - if (bss) { - cfg80211_unhold_bss(bss); - cfg80211_put_bss(&bss->pub); - } - + status_code == WLAN_STATUS_SUCCESS, bss); out: wdev_unlock(wdev); } @@ -148,8 +95,7 @@ void __cfg80211_send_deauth(struct net_device *dev, struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; - int i; - bool found = false, was_current = false; + bool was_current = false; ASSERT_WDEV_LOCK(wdev); @@ -158,32 +104,9 @@ void __cfg80211_send_deauth(struct net_device *dev, cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; - found = true; was_current = true; - } else for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i] && - memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->auth_bsses[i]); - cfg80211_put_bss(&wdev->auth_bsses[i]->pub); - wdev->auth_bsses[i] = NULL; - found = true; - break; - } - if (wdev->authtry_bsses[i] && - memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, - ETH_ALEN) == 0 && - memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - wdev->authtry_bsses[i] = NULL; - found = true; - break; - } } - if (!found) - return; - nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { @@ -220,10 +143,8 @@ void __cfg80211_send_disassoc(struct net_device *dev, struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; - int i; u16 reason_code; bool from_ap; - bool done = false; ASSERT_WDEV_LOCK(wdev); @@ -234,16 +155,10 @@ void __cfg80211_send_disassoc(struct net_device *dev, if (wdev->current_bss && memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) - continue; - wdev->auth_bsses[i] = wdev->current_bss; - wdev->current_bss = NULL; - done = true; - cfg80211_sme_disassoc(dev, i); - break; - } - WARN_ON(!done); + cfg80211_sme_disassoc(dev, wdev->current_bss); + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(&wdev->current_bss->pub); + wdev->current_bss = NULL; } else WARN_ON(1); @@ -287,34 +202,6 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, } EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); -static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) -{ - int i; - bool done = false; - - ASSERT_WDEV_LOCK(wdev); - - for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] && - memcmp(wdev->authtry_bsses[i]->pub.bssid, - addr, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - wdev->authtry_bsses[i] = NULL; - done = true; - break; - } - } - - WARN_ON(!done); -} - -void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) -{ - __cfg80211_auth_remove(dev->ieee80211_ptr, addr); -} -EXPORT_SYMBOL(__cfg80211_auth_canceled); - void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) { struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -329,8 +216,6 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); - __cfg80211_auth_remove(wdev, addr); - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_auth_timeout); @@ -340,8 +225,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - int i; - bool done = false; wdev_lock(wdev); @@ -351,20 +234,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); - for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i] && - memcmp(wdev->auth_bsses[i]->pub.bssid, - addr, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->auth_bsses[i]); - cfg80211_put_bss(&wdev->auth_bsses[i]->pub); - wdev->auth_bsses[i] = NULL; - done = true; - break; - } - } - - WARN_ON(!done); - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_assoc_timeout); @@ -403,13 +272,11 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - bool local_state_change) + const u8 *key, int key_len, int key_idx) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req; - struct cfg80211_internal_bss *bss; - int i, err, slot = -1, nfree = 0; + int err; ASSERT_WDEV_LOCK(wdev); @@ -421,20 +288,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) return -EALREADY; - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] && - memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, - ETH_ALEN) == 0) - return -EALREADY; - if (wdev->auth_bsses[i] && - memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, - ETH_ALEN) == 0) - return -EALREADY; - } - memset(&req, 0, sizeof(req)); - req.local_state_change = local_state_change; req.ie = ie; req.ie_len = ie_len; req.auth_type = auth_type; @@ -446,39 +301,9 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, if (!req.bss) return -ENOENT; - bss = bss_from_pub(req.bss); - - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) { - slot = i; - nfree++; - } - } - - /* we need one free slot for disassoc and one for this auth */ - if (nfree < 2) { - err = -ENOSPC; - goto out; - } - - if (local_state_change) - wdev->auth_bsses[slot] = bss; - else - wdev->authtry_bsses[slot] = bss; - cfg80211_hold_bss(bss); - err = rdev->ops->auth(&rdev->wiphy, dev, &req); - if (err) { - if (local_state_change) - wdev->auth_bsses[slot] = NULL; - else - wdev->authtry_bsses[slot] = NULL; - cfg80211_unhold_bss(bss); - } - out: - if (err) - cfg80211_put_bss(req.bss); + cfg80211_put_bss(req.bss); return err; } @@ -487,15 +312,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - bool local_state_change) + const u8 *key, int key_len, int key_idx) { int err; wdev_lock(dev->ieee80211_ptr); err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, ssid, ssid_len, ie, ie_len, - key, key_len, key_idx, local_state_change); + key, key_len, key_idx); wdev_unlock(dev->ieee80211_ptr); return err; @@ -530,8 +354,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_assoc_request req; - struct cfg80211_internal_bss *bss; - int i, err, slot = -1; + int err; bool was_connected = false; ASSERT_WDEV_LOCK(wdev); @@ -573,26 +396,14 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, return -ENOENT; } - bss = bss_from_pub(req.bss); - - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (bss == wdev->auth_bsses[i]) { - slot = i; - break; - } - } + err = rdev->ops->assoc(&rdev->wiphy, dev, &req); - if (slot < 0) { - err = -ENOTCONN; - goto out; + if (err) { + if (was_connected) + wdev->sme_state = CFG80211_SME_CONNECTED; + cfg80211_put_bss(req.bss); } - 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; } @@ -624,36 +435,27 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_deauth_request req; - int i; + struct cfg80211_deauth_request req = { + .bssid = bssid, + .reason_code = reason, + .ie = ie, + .ie_len = ie_len, + }; ASSERT_WDEV_LOCK(wdev); - memset(&req, 0, sizeof(req)); - req.reason_code = reason; - req.local_state_change = local_state_change; - req.ie = ie; - req.ie_len = ie_len; - if (wdev->current_bss && - memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { - req.bss = &wdev->current_bss->pub; - } else for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i] && - memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) { - req.bss = &wdev->auth_bsses[i]->pub; - break; - } - if (wdev->authtry_bsses[i] && - memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) { - req.bss = &wdev->authtry_bsses[i]->pub; - break; + if (local_state_change) { + if (wdev->current_bss && + memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(&wdev->current_bss->pub); + wdev->current_bss = NULL; } - } - if (!req.bss) - return -ENOTCONN; + return 0; + } - return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); + return rdev->ops->deauth(&rdev->wiphy, dev, &req); } int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, @@ -698,7 +500,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, else return -ENOTCONN; - return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev); + return rdev->ops->disassoc(&rdev->wiphy, dev, &req); } int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, @@ -722,7 +524,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_deauth_request req; - int i; + u8 bssid[ETH_ALEN]; ASSERT_WDEV_LOCK(wdev); @@ -734,35 +536,17 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, req.ie = NULL; req.ie_len = 0; - if (wdev->current_bss) { - req.bss = &wdev->current_bss->pub; - rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); - if (wdev->current_bss) { - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(&wdev->current_bss->pub); - wdev->current_bss = NULL; - } - } + if (!wdev->current_bss) + return; - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i]) { - req.bss = &wdev->auth_bsses[i]->pub; - rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); - if (wdev->auth_bsses[i]) { - cfg80211_unhold_bss(wdev->auth_bsses[i]); - cfg80211_put_bss(&wdev->auth_bsses[i]->pub); - wdev->auth_bsses[i] = NULL; - } - } - if (wdev->authtry_bsses[i]) { - req.bss = &wdev->authtry_bsses[i]->pub; - rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); - if (wdev->authtry_bsses[i]) { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - wdev->authtry_bsses[i] = NULL; - } - } + memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); + req.bssid = bssid; + rdev->ops->deauth(&rdev->wiphy, dev, &req); + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(&wdev->current_bss->pub); + wdev->current_bss = NULL; } } @@ -1030,8 +814,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, cookie); } -bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, - size_t len, gfp_t gfp) +bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm, + const u8 *buf, size_t len, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -1070,7 +854,8 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, /* found match! */ /* Indicate the received Action frame to user space */ - if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq, + if (nl80211_send_mgmt(rdev, dev, reg->nlpid, + freq, sig_mbm, buf, len, gfp)) continue; |