diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-01-20 07:55:25 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-02-06 14:50:37 -0500 |
commit | 95de817b9034d50860319f6033ec85d25024694c (patch) | |
tree | 8dc100ec6a5ee527a6e86b33e904f5f9d14181ab /net/wireless/mlme.c | |
parent | 7852e36186d2a1983c215836d7e3d7b8927c930d (diff) |
cfg80211: stop tracking authenticated state
To track authenticated state seems to have been
a design mistake in cfg80211. It is possible to
have out of band authentication (FT), tracking
multiple authentications caused more problems
than it ever helped, and the implementation in
mac80211 is too complex.
Remove all this complexity, and let userspace
do whatever it wants to, mac80211 can deal with
that just fine. Association is still tracked of
course, but authentication no longer is. Local
auth state changes are thus no longer of value,
so ignore them completely.
This will also help implement SAE -- asking the
driver to do an authentication is now almost
equivalent to sending an authentication frame,
with the exception of shared key authentication
which is still handled completely.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r-- | net/wireless/mlme.c | 322 |
1 files changed, 53 insertions, 269 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 438dfc105b4a..d553d365e751 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) | |||
20 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 20 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
21 | struct wiphy *wiphy = wdev->wiphy; | 21 | struct wiphy *wiphy = wdev->wiphy; |
22 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 22 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
23 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | ||
24 | u8 *bssid = mgmt->bssid; | ||
25 | int i; | ||
26 | u16 status = le16_to_cpu(mgmt->u.auth.status_code); | ||
27 | bool done = false; | ||
28 | 23 | ||
29 | wdev_lock(wdev); | 24 | wdev_lock(wdev); |
30 | 25 | ||
31 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 26 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); |
32 | if (wdev->authtry_bsses[i] && | 27 | cfg80211_sme_rx_auth(dev, buf, len); |
33 | memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, | ||
34 | ETH_ALEN) == 0) { | ||
35 | if (status == WLAN_STATUS_SUCCESS) { | ||
36 | wdev->auth_bsses[i] = wdev->authtry_bsses[i]; | ||
37 | } else { | ||
38 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
39 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
40 | } | ||
41 | wdev->authtry_bsses[i] = NULL; | ||
42 | done = true; | ||
43 | break; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | if (done) { | ||
48 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); | ||
49 | cfg80211_sme_rx_auth(dev, buf, len); | ||
50 | } | ||
51 | 28 | ||
52 | wdev_unlock(wdev); | 29 | wdev_unlock(wdev); |
53 | } | 30 | } |
54 | EXPORT_SYMBOL(cfg80211_send_rx_auth); | 31 | EXPORT_SYMBOL(cfg80211_send_rx_auth); |
55 | 32 | ||
56 | void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | 33 | void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, |
34 | const u8 *buf, size_t len) | ||
57 | { | 35 | { |
58 | u16 status_code; | 36 | u16 status_code; |
59 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 37 | 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) | |||
61 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 39 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
62 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 40 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
63 | u8 *ie = mgmt->u.assoc_resp.variable; | 41 | u8 *ie = mgmt->u.assoc_resp.variable; |
64 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | 42 | int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); |
65 | struct cfg80211_internal_bss *bss = NULL; | ||
66 | 43 | ||
67 | wdev_lock(wdev); | 44 | wdev_lock(wdev); |
68 | 45 | ||
@@ -75,43 +52,20 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
75 | * frame instead of reassoc. | 52 | * frame instead of reassoc. |
76 | */ | 53 | */ |
77 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && | 54 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && |
78 | cfg80211_sme_failed_reassoc(wdev)) | 55 | cfg80211_sme_failed_reassoc(wdev)) { |
56 | cfg80211_put_bss(bss); | ||
79 | goto out; | 57 | goto out; |
58 | } | ||
80 | 59 | ||
81 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); | 60 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); |
82 | 61 | ||
83 | if (status_code == WLAN_STATUS_SUCCESS) { | 62 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) { |
84 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
85 | if (!wdev->auth_bsses[i]) | ||
86 | continue; | ||
87 | if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, | ||
88 | ETH_ALEN) == 0) { | ||
89 | bss = wdev->auth_bsses[i]; | ||
90 | wdev->auth_bsses[i] = NULL; | ||
91 | /* additional reference to drop hold */ | ||
92 | cfg80211_ref_bss(bss); | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * We might be coming here because the driver reported | ||
99 | * a successful association at the same time as the | ||
100 | * user requested a deauth. In that case, we will have | ||
101 | * removed the BSS from the auth_bsses list due to the | ||
102 | * deauth request when the assoc response makes it. If | ||
103 | * the two code paths acquire the lock the other way | ||
104 | * around, that's just the standard situation of a | ||
105 | * deauth being requested while connected. | ||
106 | */ | ||
107 | if (!bss) | ||
108 | goto out; | ||
109 | } else if (wdev->conn) { | ||
110 | cfg80211_sme_failed_assoc(wdev); | 63 | cfg80211_sme_failed_assoc(wdev); |
111 | /* | 64 | /* |
112 | * do not call connect_result() now because the | 65 | * do not call connect_result() now because the |
113 | * sme will schedule work that does it later. | 66 | * sme will schedule work that does it later. |
114 | */ | 67 | */ |
68 | cfg80211_put_bss(bss); | ||
115 | goto out; | 69 | goto out; |
116 | } | 70 | } |
117 | 71 | ||
@@ -124,17 +78,10 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
124 | wdev->sme_state = CFG80211_SME_CONNECTING; | 78 | wdev->sme_state = CFG80211_SME_CONNECTING; |
125 | } | 79 | } |
126 | 80 | ||
127 | /* this consumes one bss reference (unless bss is NULL) */ | 81 | /* this consumes the bss reference */ |
128 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | 82 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, |
129 | status_code, | 83 | status_code, |
130 | status_code == WLAN_STATUS_SUCCESS, | 84 | status_code == WLAN_STATUS_SUCCESS, bss); |
131 | bss ? &bss->pub : NULL); | ||
132 | /* drop hold now, and also reference acquired above */ | ||
133 | if (bss) { | ||
134 | cfg80211_unhold_bss(bss); | ||
135 | cfg80211_put_bss(&bss->pub); | ||
136 | } | ||
137 | |||
138 | out: | 85 | out: |
139 | wdev_unlock(wdev); | 86 | wdev_unlock(wdev); |
140 | } | 87 | } |
@@ -148,8 +95,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
148 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 95 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
149 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 96 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
150 | const u8 *bssid = mgmt->bssid; | 97 | const u8 *bssid = mgmt->bssid; |
151 | int i; | 98 | bool was_current = false; |
152 | bool found = false, was_current = false; | ||
153 | 99 | ||
154 | ASSERT_WDEV_LOCK(wdev); | 100 | ASSERT_WDEV_LOCK(wdev); |
155 | 101 | ||
@@ -158,32 +104,9 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
158 | cfg80211_unhold_bss(wdev->current_bss); | 104 | cfg80211_unhold_bss(wdev->current_bss); |
159 | cfg80211_put_bss(&wdev->current_bss->pub); | 105 | cfg80211_put_bss(&wdev->current_bss->pub); |
160 | wdev->current_bss = NULL; | 106 | wdev->current_bss = NULL; |
161 | found = true; | ||
162 | was_current = true; | 107 | was_current = true; |
163 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
164 | if (wdev->auth_bsses[i] && | ||
165 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { | ||
166 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | ||
167 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | ||
168 | wdev->auth_bsses[i] = NULL; | ||
169 | found = true; | ||
170 | break; | ||
171 | } | ||
172 | if (wdev->authtry_bsses[i] && | ||
173 | memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, | ||
174 | ETH_ALEN) == 0 && | ||
175 | memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) { | ||
176 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
177 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
178 | wdev->authtry_bsses[i] = NULL; | ||
179 | found = true; | ||
180 | break; | ||
181 | } | ||
182 | } | 108 | } |
183 | 109 | ||
184 | if (!found) | ||
185 | return; | ||
186 | |||
187 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); | 110 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); |
188 | 111 | ||
189 | if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { | 112 | if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { |
@@ -220,10 +143,8 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
220 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 143 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
221 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 144 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
222 | const u8 *bssid = mgmt->bssid; | 145 | const u8 *bssid = mgmt->bssid; |
223 | int i; | ||
224 | u16 reason_code; | 146 | u16 reason_code; |
225 | bool from_ap; | 147 | bool from_ap; |
226 | bool done = false; | ||
227 | 148 | ||
228 | ASSERT_WDEV_LOCK(wdev); | 149 | ASSERT_WDEV_LOCK(wdev); |
229 | 150 | ||
@@ -234,16 +155,10 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
234 | 155 | ||
235 | if (wdev->current_bss && | 156 | if (wdev->current_bss && |
236 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | 157 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { |
237 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 158 | cfg80211_sme_disassoc(dev, wdev->current_bss); |
238 | if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) | 159 | cfg80211_unhold_bss(wdev->current_bss); |
239 | continue; | 160 | cfg80211_put_bss(&wdev->current_bss->pub); |
240 | wdev->auth_bsses[i] = wdev->current_bss; | 161 | wdev->current_bss = NULL; |
241 | wdev->current_bss = NULL; | ||
242 | done = true; | ||
243 | cfg80211_sme_disassoc(dev, i); | ||
244 | break; | ||
245 | } | ||
246 | WARN_ON(!done); | ||
247 | } else | 162 | } else |
248 | WARN_ON(1); | 163 | WARN_ON(1); |
249 | 164 | ||
@@ -287,34 +202,6 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | |||
287 | } | 202 | } |
288 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | 203 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); |
289 | 204 | ||
290 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) | ||
291 | { | ||
292 | int i; | ||
293 | bool done = false; | ||
294 | |||
295 | ASSERT_WDEV_LOCK(wdev); | ||
296 | |||
297 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | ||
298 | if (wdev->authtry_bsses[i] && | ||
299 | memcmp(wdev->authtry_bsses[i]->pub.bssid, | ||
300 | addr, ETH_ALEN) == 0) { | ||
301 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
302 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
303 | wdev->authtry_bsses[i] = NULL; | ||
304 | done = true; | ||
305 | break; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | WARN_ON(!done); | ||
310 | } | ||
311 | |||
312 | void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) | ||
313 | { | ||
314 | __cfg80211_auth_remove(dev->ieee80211_ptr, addr); | ||
315 | } | ||
316 | EXPORT_SYMBOL(__cfg80211_auth_canceled); | ||
317 | |||
318 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 205 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) |
319 | { | 206 | { |
320 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 207 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -329,8 +216,6 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
329 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 216 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
330 | false, NULL); | 217 | false, NULL); |
331 | 218 | ||
332 | __cfg80211_auth_remove(wdev, addr); | ||
333 | |||
334 | wdev_unlock(wdev); | 219 | wdev_unlock(wdev); |
335 | } | 220 | } |
336 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); | 221 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); |
@@ -340,8 +225,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
340 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 225 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
341 | struct wiphy *wiphy = wdev->wiphy; | 226 | struct wiphy *wiphy = wdev->wiphy; |
342 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 227 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
343 | int i; | ||
344 | bool done = false; | ||
345 | 228 | ||
346 | wdev_lock(wdev); | 229 | wdev_lock(wdev); |
347 | 230 | ||
@@ -351,20 +234,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
351 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 234 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
352 | false, NULL); | 235 | false, NULL); |
353 | 236 | ||
354 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | ||
355 | if (wdev->auth_bsses[i] && | ||
356 | memcmp(wdev->auth_bsses[i]->pub.bssid, | ||
357 | addr, ETH_ALEN) == 0) { | ||
358 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | ||
359 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | ||
360 | wdev->auth_bsses[i] = NULL; | ||
361 | done = true; | ||
362 | break; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | WARN_ON(!done); | ||
367 | |||
368 | wdev_unlock(wdev); | 237 | wdev_unlock(wdev); |
369 | } | 238 | } |
370 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); | 239 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); |
@@ -403,13 +272,11 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
403 | const u8 *bssid, | 272 | const u8 *bssid, |
404 | const u8 *ssid, int ssid_len, | 273 | const u8 *ssid, int ssid_len, |
405 | const u8 *ie, int ie_len, | 274 | const u8 *ie, int ie_len, |
406 | const u8 *key, int key_len, int key_idx, | 275 | const u8 *key, int key_len, int key_idx) |
407 | bool local_state_change) | ||
408 | { | 276 | { |
409 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 277 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
410 | struct cfg80211_auth_request req; | 278 | struct cfg80211_auth_request req; |
411 | struct cfg80211_internal_bss *bss; | 279 | int err; |
412 | int i, err, slot = -1, nfree = 0; | ||
413 | 280 | ||
414 | ASSERT_WDEV_LOCK(wdev); | 281 | ASSERT_WDEV_LOCK(wdev); |
415 | 282 | ||
@@ -421,20 +288,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
421 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) | 288 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) |
422 | return -EALREADY; | 289 | return -EALREADY; |
423 | 290 | ||
424 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
425 | if (wdev->authtry_bsses[i] && | ||
426 | memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, | ||
427 | ETH_ALEN) == 0) | ||
428 | return -EALREADY; | ||
429 | if (wdev->auth_bsses[i] && | ||
430 | memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, | ||
431 | ETH_ALEN) == 0) | ||
432 | return -EALREADY; | ||
433 | } | ||
434 | |||
435 | memset(&req, 0, sizeof(req)); | 291 | memset(&req, 0, sizeof(req)); |
436 | 292 | ||
437 | req.local_state_change = local_state_change; | ||
438 | req.ie = ie; | 293 | req.ie = ie; |
439 | req.ie_len = ie_len; | 294 | req.ie_len = ie_len; |
440 | req.auth_type = auth_type; | 295 | req.auth_type = auth_type; |
@@ -446,39 +301,9 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
446 | if (!req.bss) | 301 | if (!req.bss) |
447 | return -ENOENT; | 302 | return -ENOENT; |
448 | 303 | ||
449 | bss = bss_from_pub(req.bss); | ||
450 | |||
451 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
452 | if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) { | ||
453 | slot = i; | ||
454 | nfree++; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | /* we need one free slot for disassoc and one for this auth */ | ||
459 | if (nfree < 2) { | ||
460 | err = -ENOSPC; | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | if (local_state_change) | ||
465 | wdev->auth_bsses[slot] = bss; | ||
466 | else | ||
467 | wdev->authtry_bsses[slot] = bss; | ||
468 | cfg80211_hold_bss(bss); | ||
469 | |||
470 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); | 304 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); |
471 | if (err) { | ||
472 | if (local_state_change) | ||
473 | wdev->auth_bsses[slot] = NULL; | ||
474 | else | ||
475 | wdev->authtry_bsses[slot] = NULL; | ||
476 | cfg80211_unhold_bss(bss); | ||
477 | } | ||
478 | 305 | ||
479 | out: | 306 | cfg80211_put_bss(req.bss); |
480 | if (err) | ||
481 | cfg80211_put_bss(req.bss); | ||
482 | return err; | 307 | return err; |
483 | } | 308 | } |
484 | 309 | ||
@@ -487,15 +312,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
487 | enum nl80211_auth_type auth_type, const u8 *bssid, | 312 | enum nl80211_auth_type auth_type, const u8 *bssid, |
488 | const u8 *ssid, int ssid_len, | 313 | const u8 *ssid, int ssid_len, |
489 | const u8 *ie, int ie_len, | 314 | const u8 *ie, int ie_len, |
490 | const u8 *key, int key_len, int key_idx, | 315 | const u8 *key, int key_len, int key_idx) |
491 | bool local_state_change) | ||
492 | { | 316 | { |
493 | int err; | 317 | int err; |
494 | 318 | ||
495 | wdev_lock(dev->ieee80211_ptr); | 319 | wdev_lock(dev->ieee80211_ptr); |
496 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 320 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
497 | ssid, ssid_len, ie, ie_len, | 321 | ssid, ssid_len, ie, ie_len, |
498 | key, key_len, key_idx, local_state_change); | 322 | key, key_len, key_idx); |
499 | wdev_unlock(dev->ieee80211_ptr); | 323 | wdev_unlock(dev->ieee80211_ptr); |
500 | 324 | ||
501 | return err; | 325 | return err; |
@@ -530,8 +354,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
530 | { | 354 | { |
531 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 355 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
532 | struct cfg80211_assoc_request req; | 356 | struct cfg80211_assoc_request req; |
533 | struct cfg80211_internal_bss *bss; | 357 | int err; |
534 | int i, err, slot = -1; | ||
535 | bool was_connected = false; | 358 | bool was_connected = false; |
536 | 359 | ||
537 | ASSERT_WDEV_LOCK(wdev); | 360 | ASSERT_WDEV_LOCK(wdev); |
@@ -573,26 +396,14 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
573 | return -ENOENT; | 396 | return -ENOENT; |
574 | } | 397 | } |
575 | 398 | ||
576 | bss = bss_from_pub(req.bss); | 399 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); |
577 | |||
578 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
579 | if (bss == wdev->auth_bsses[i]) { | ||
580 | slot = i; | ||
581 | break; | ||
582 | } | ||
583 | } | ||
584 | 400 | ||
585 | if (slot < 0) { | 401 | if (err) { |
586 | err = -ENOTCONN; | 402 | if (was_connected) |
587 | goto out; | 403 | wdev->sme_state = CFG80211_SME_CONNECTED; |
404 | cfg80211_put_bss(req.bss); | ||
588 | } | 405 | } |
589 | 406 | ||
590 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); | ||
591 | out: | ||
592 | if (err && was_connected) | ||
593 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
594 | /* still a reference in wdev->auth_bsses[slot] */ | ||
595 | cfg80211_put_bss(req.bss); | ||
596 | return err; | 407 | return err; |
597 | } | 408 | } |
598 | 409 | ||
@@ -624,34 +435,25 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
624 | bool local_state_change) | 435 | bool local_state_change) |
625 | { | 436 | { |
626 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 437 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
627 | struct cfg80211_deauth_request req; | 438 | struct cfg80211_deauth_request req = { |
628 | int i; | 439 | .bssid = bssid, |
440 | .reason_code = reason, | ||
441 | .ie = ie, | ||
442 | .ie_len = ie_len, | ||
443 | }; | ||
629 | 444 | ||
630 | ASSERT_WDEV_LOCK(wdev); | 445 | ASSERT_WDEV_LOCK(wdev); |
631 | 446 | ||
632 | memset(&req, 0, sizeof(req)); | 447 | if (local_state_change) { |
633 | req.reason_code = reason; | 448 | if (wdev->current_bss && |
634 | req.local_state_change = local_state_change; | 449 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { |
635 | req.ie = ie; | 450 | cfg80211_unhold_bss(wdev->current_bss); |
636 | req.ie_len = ie_len; | 451 | cfg80211_put_bss(&wdev->current_bss->pub); |
637 | if (wdev->current_bss && | 452 | wdev->current_bss = NULL; |
638 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | ||
639 | req.bss = &wdev->current_bss->pub; | ||
640 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
641 | if (wdev->auth_bsses[i] && | ||
642 | memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) { | ||
643 | req.bss = &wdev->auth_bsses[i]->pub; | ||
644 | break; | ||
645 | } | ||
646 | if (wdev->authtry_bsses[i] && | ||
647 | memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) { | ||
648 | req.bss = &wdev->authtry_bsses[i]->pub; | ||
649 | break; | ||
650 | } | 453 | } |
651 | } | ||
652 | 454 | ||
653 | if (!req.bss) | 455 | return 0; |
654 | return -ENOTCONN; | 456 | } |
655 | 457 | ||
656 | return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | 458 | return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
657 | } | 459 | } |
@@ -722,7 +524,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
722 | { | 524 | { |
723 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 525 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
724 | struct cfg80211_deauth_request req; | 526 | struct cfg80211_deauth_request req; |
725 | int i; | 527 | u8 bssid[ETH_ALEN]; |
726 | 528 | ||
727 | ASSERT_WDEV_LOCK(wdev); | 529 | ASSERT_WDEV_LOCK(wdev); |
728 | 530 | ||
@@ -734,35 +536,17 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
734 | req.ie = NULL; | 536 | req.ie = NULL; |
735 | req.ie_len = 0; | 537 | req.ie_len = 0; |
736 | 538 | ||
737 | if (wdev->current_bss) { | 539 | if (!wdev->current_bss) |
738 | req.bss = &wdev->current_bss->pub; | 540 | return; |
739 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | ||
740 | if (wdev->current_bss) { | ||
741 | cfg80211_unhold_bss(wdev->current_bss); | ||
742 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
743 | wdev->current_bss = NULL; | ||
744 | } | ||
745 | } | ||
746 | 541 | ||
747 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 542 | memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); |
748 | if (wdev->auth_bsses[i]) { | 543 | req.bssid = bssid; |
749 | req.bss = &wdev->auth_bsses[i]->pub; | 544 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
750 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | 545 | |
751 | if (wdev->auth_bsses[i]) { | 546 | if (wdev->current_bss) { |
752 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | 547 | cfg80211_unhold_bss(wdev->current_bss); |
753 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | 548 | cfg80211_put_bss(&wdev->current_bss->pub); |
754 | wdev->auth_bsses[i] = NULL; | 549 | wdev->current_bss = NULL; |
755 | } | ||
756 | } | ||
757 | if (wdev->authtry_bsses[i]) { | ||
758 | req.bss = &wdev->authtry_bsses[i]->pub; | ||
759 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | ||
760 | if (wdev->authtry_bsses[i]) { | ||
761 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
762 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
763 | wdev->authtry_bsses[i] = NULL; | ||
764 | } | ||
765 | } | ||
766 | } | 550 | } |
767 | } | 551 | } |
768 | 552 | ||