diff options
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 | ||