aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r--net/wireless/mlme.c214
1 files changed, 168 insertions, 46 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 960bf60e44e5..1b2ca1fea7a1 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -23,7 +23,7 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
23 u16 status = le16_to_cpu(mgmt->u.auth.status_code); 23 u16 status = le16_to_cpu(mgmt->u.auth.status_code);
24 bool done = false; 24 bool done = false;
25 25
26 might_sleep(); 26 wdev_lock(wdev);
27 27
28 for (i = 0; i < MAX_AUTH_BSSES; i++) { 28 for (i = 0; i < MAX_AUTH_BSSES; i++) {
29 if (wdev->authtry_bsses[i] && 29 if (wdev->authtry_bsses[i] &&
@@ -45,6 +45,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
45 45
46 nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); 46 nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
47 cfg80211_sme_rx_auth(dev, buf, len); 47 cfg80211_sme_rx_auth(dev, buf, len);
48
49 wdev_unlock(wdev);
48} 50}
49EXPORT_SYMBOL(cfg80211_send_rx_auth); 51EXPORT_SYMBOL(cfg80211_send_rx_auth);
50 52
@@ -59,14 +61,15 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
59 int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); 61 int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
60 bool done; 62 bool done;
61 63
62 might_sleep(); 64 wdev_lock(wdev);
63 65
64 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); 66 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
65 67
66 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); 68 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
67 69
68 cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, 70 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
69 status_code, GFP_KERNEL); 71 status_code,
72 status_code == WLAN_STATUS_SUCCESS);
70 73
71 if (status_code == WLAN_STATUS_SUCCESS) { 74 if (status_code == WLAN_STATUS_SUCCESS) {
72 for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) { 75 for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) {
@@ -81,10 +84,13 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
81 84
82 WARN_ON(!done); 85 WARN_ON(!done);
83 } 86 }
87
88 wdev_unlock(wdev);
84} 89}
85EXPORT_SYMBOL(cfg80211_send_rx_assoc); 90EXPORT_SYMBOL(cfg80211_send_rx_assoc);
86 91
87void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) 92static void __cfg80211_send_deauth(struct net_device *dev,
93 const u8 *buf, size_t len)
88{ 94{
89 struct wireless_dev *wdev = dev->ieee80211_ptr; 95 struct wireless_dev *wdev = dev->ieee80211_ptr;
90 struct wiphy *wiphy = wdev->wiphy; 96 struct wiphy *wiphy = wdev->wiphy;
@@ -94,7 +100,7 @@ void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
94 int i; 100 int i;
95 bool done = false; 101 bool done = false;
96 102
97 might_sleep(); 103 ASSERT_WDEV_LOCK(wdev);
98 104
99 nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); 105 nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
100 106
@@ -132,17 +138,35 @@ void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
132 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); 138 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
133 139
134 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; 140 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
135 __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 141 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
136 reason_code, from_ap);
137 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { 142 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
138 cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, 143 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
139 WLAN_STATUS_UNSPECIFIED_FAILURE, 144 WLAN_STATUS_UNSPECIFIED_FAILURE,
140 GFP_KERNEL); 145 false);
146 }
147}
148
149
150void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
151 void *cookie)
152{
153 struct wireless_dev *wdev = dev->ieee80211_ptr;
154
155 BUG_ON(cookie && wdev != cookie);
156
157 if (cookie) {
158 /* called within callback */
159 __cfg80211_send_deauth(dev, buf, len);
160 } else {
161 wdev_lock(wdev);
162 __cfg80211_send_deauth(dev, buf, len);
163 wdev_unlock(wdev);
141 } 164 }
142} 165}
143EXPORT_SYMBOL(cfg80211_send_deauth); 166EXPORT_SYMBOL(cfg80211_send_deauth);
144 167
145void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) 168static void __cfg80211_send_disassoc(struct net_device *dev,
169 const u8 *buf, size_t len)
146{ 170{
147 struct wireless_dev *wdev = dev->ieee80211_ptr; 171 struct wireless_dev *wdev = dev->ieee80211_ptr;
148 struct wiphy *wiphy = wdev->wiphy; 172 struct wiphy *wiphy = wdev->wiphy;
@@ -154,12 +178,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
154 bool from_ap; 178 bool from_ap;
155 bool done = false; 179 bool done = false;
156 180
157 might_sleep(); 181 wdev_lock(wdev);
158 182
159 nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); 183 nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
160 184
161 if (!wdev->sme_state == CFG80211_SME_CONNECTED) 185 if (!wdev->sme_state == CFG80211_SME_CONNECTED)
162 return; 186 goto out;
163 187
164 if (wdev->current_bss && 188 if (wdev->current_bss &&
165 memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) { 189 memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) {
@@ -180,8 +204,26 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
180 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); 204 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
181 205
182 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; 206 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0;
183 __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 207 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
184 reason_code, from_ap); 208 out:
209 wdev_unlock(wdev);
210}
211
212void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
213 void *cookie)
214{
215 struct wireless_dev *wdev = dev->ieee80211_ptr;
216
217 BUG_ON(cookie && wdev != cookie);
218
219 if (cookie) {
220 /* called within callback */
221 __cfg80211_send_disassoc(dev, buf, len);
222 } else {
223 wdev_lock(wdev);
224 __cfg80211_send_disassoc(dev, buf, len);
225 wdev_unlock(wdev);
226 }
185} 227}
186EXPORT_SYMBOL(cfg80211_send_disassoc); 228EXPORT_SYMBOL(cfg80211_send_disassoc);
187 229
@@ -193,13 +235,13 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
193 int i; 235 int i;
194 bool done = false; 236 bool done = false;
195 237
196 might_sleep(); 238 wdev_lock(wdev);
197 239
198 nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); 240 nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
199 if (wdev->sme_state == CFG80211_SME_CONNECTING) 241 if (wdev->sme_state == CFG80211_SME_CONNECTING)
200 cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, 242 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
201 WLAN_STATUS_UNSPECIFIED_FAILURE, 243 WLAN_STATUS_UNSPECIFIED_FAILURE,
202 GFP_KERNEL); 244 false);
203 245
204 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { 246 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
205 if (wdev->authtry_bsses[i] && 247 if (wdev->authtry_bsses[i] &&
@@ -214,6 +256,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
214 } 256 }
215 257
216 WARN_ON(!done); 258 WARN_ON(!done);
259
260 wdev_unlock(wdev);
217} 261}
218EXPORT_SYMBOL(cfg80211_send_auth_timeout); 262EXPORT_SYMBOL(cfg80211_send_auth_timeout);
219 263
@@ -225,13 +269,13 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
225 int i; 269 int i;
226 bool done = false; 270 bool done = false;
227 271
228 might_sleep(); 272 wdev_lock(wdev);
229 273
230 nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); 274 nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
231 if (wdev->sme_state == CFG80211_SME_CONNECTING) 275 if (wdev->sme_state == CFG80211_SME_CONNECTING)
232 cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, 276 __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
233 WLAN_STATUS_UNSPECIFIED_FAILURE, 277 WLAN_STATUS_UNSPECIFIED_FAILURE,
234 GFP_KERNEL); 278 false);
235 279
236 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { 280 for (i = 0; addr && i < MAX_AUTH_BSSES; i++) {
237 if (wdev->auth_bsses[i] && 281 if (wdev->auth_bsses[i] &&
@@ -246,6 +290,8 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
246 } 290 }
247 291
248 WARN_ON(!done); 292 WARN_ON(!done);
293
294 wdev_unlock(wdev);
249} 295}
250EXPORT_SYMBOL(cfg80211_send_assoc_timeout); 296EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
251 297
@@ -276,17 +322,21 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
276EXPORT_SYMBOL(cfg80211_michael_mic_failure); 322EXPORT_SYMBOL(cfg80211_michael_mic_failure);
277 323
278/* some MLME handling for userspace SME */ 324/* some MLME handling for userspace SME */
279int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 325int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
280 struct net_device *dev, struct ieee80211_channel *chan, 326 struct net_device *dev,
281 enum nl80211_auth_type auth_type, const u8 *bssid, 327 struct ieee80211_channel *chan,
282 const u8 *ssid, int ssid_len, 328 enum nl80211_auth_type auth_type,
283 const u8 *ie, int ie_len) 329 const u8 *bssid,
330 const u8 *ssid, int ssid_len,
331 const u8 *ie, int ie_len)
284{ 332{
285 struct wireless_dev *wdev = dev->ieee80211_ptr; 333 struct wireless_dev *wdev = dev->ieee80211_ptr;
286 struct cfg80211_auth_request req; 334 struct cfg80211_auth_request req;
287 struct cfg80211_internal_bss *bss; 335 struct cfg80211_internal_bss *bss;
288 int i, err, slot = -1, nfree = 0; 336 int i, err, slot = -1, nfree = 0;
289 337
338 ASSERT_WDEV_LOCK(wdev);
339
290 if (wdev->current_bss && 340 if (wdev->current_bss &&
291 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) 341 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
292 return -EALREADY; 342 return -EALREADY;
@@ -342,18 +392,37 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
342 return err; 392 return err;
343} 393}
344 394
345int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 395int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
346 struct net_device *dev, struct ieee80211_channel *chan, 396 struct net_device *dev, struct ieee80211_channel *chan,
347 const u8 *bssid, const u8 *prev_bssid, 397 enum nl80211_auth_type auth_type, const u8 *bssid,
348 const u8 *ssid, int ssid_len, 398 const u8 *ssid, int ssid_len,
349 const u8 *ie, int ie_len, bool use_mfp, 399 const u8 *ie, int ie_len)
350 struct cfg80211_crypto_settings *crypt) 400{
401 int err;
402
403 wdev_lock(dev->ieee80211_ptr);
404 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
405 ssid, ssid_len, ie, ie_len);
406 wdev_unlock(dev->ieee80211_ptr);
407
408 return err;
409}
410
411int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
412 struct net_device *dev,
413 struct ieee80211_channel *chan,
414 const u8 *bssid, const u8 *prev_bssid,
415 const u8 *ssid, int ssid_len,
416 const u8 *ie, int ie_len, bool use_mfp,
417 struct cfg80211_crypto_settings *crypt)
351{ 418{
352 struct wireless_dev *wdev = dev->ieee80211_ptr; 419 struct wireless_dev *wdev = dev->ieee80211_ptr;
353 struct cfg80211_assoc_request req; 420 struct cfg80211_assoc_request req;
354 struct cfg80211_internal_bss *bss; 421 struct cfg80211_internal_bss *bss;
355 int i, err, slot = -1; 422 int i, err, slot = -1;
356 423
424 ASSERT_WDEV_LOCK(wdev);
425
357 memset(&req, 0, sizeof(req)); 426 memset(&req, 0, sizeof(req));
358 427
359 if (wdev->current_bss) 428 if (wdev->current_bss)
@@ -390,14 +459,35 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
390 return err; 459 return err;
391} 460}
392 461
393int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 462int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
394 struct net_device *dev, const u8 *bssid, 463 struct net_device *dev,
395 const u8 *ie, int ie_len, u16 reason) 464 struct ieee80211_channel *chan,
465 const u8 *bssid, const u8 *prev_bssid,
466 const u8 *ssid, int ssid_len,
467 const u8 *ie, int ie_len, bool use_mfp,
468 struct cfg80211_crypto_settings *crypt)
469{
470 struct wireless_dev *wdev = dev->ieee80211_ptr;
471 int err;
472
473 wdev_lock(wdev);
474 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
475 ssid, ssid_len, ie, ie_len, use_mfp, crypt);
476 wdev_unlock(wdev);
477
478 return err;
479}
480
481int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
482 struct net_device *dev, const u8 *bssid,
483 const u8 *ie, int ie_len, u16 reason)
396{ 484{
397 struct wireless_dev *wdev = dev->ieee80211_ptr; 485 struct wireless_dev *wdev = dev->ieee80211_ptr;
398 struct cfg80211_deauth_request req; 486 struct cfg80211_deauth_request req;
399 int i; 487 int i;
400 488
489 ASSERT_WDEV_LOCK(wdev);
490
401 memset(&req, 0, sizeof(req)); 491 memset(&req, 0, sizeof(req));
402 req.reason_code = reason; 492 req.reason_code = reason;
403 req.ie = ie; 493 req.ie = ie;
@@ -421,16 +511,32 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
421 if (!req.bss) 511 if (!req.bss)
422 return -ENOTCONN; 512 return -ENOTCONN;
423 513
424 return rdev->ops->deauth(&rdev->wiphy, dev, &req); 514 return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
425} 515}
426 516
427int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 517int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
428 struct net_device *dev, const u8 *bssid, 518 struct net_device *dev, const u8 *bssid,
429 const u8 *ie, int ie_len, u16 reason) 519 const u8 *ie, int ie_len, u16 reason)
520{
521 struct wireless_dev *wdev = dev->ieee80211_ptr;
522 int err;
523
524 wdev_lock(wdev);
525 err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason);
526 wdev_unlock(wdev);
527
528 return err;
529}
530
531static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
532 struct net_device *dev, const u8 *bssid,
533 const u8 *ie, int ie_len, u16 reason)
430{ 534{
431 struct wireless_dev *wdev = dev->ieee80211_ptr; 535 struct wireless_dev *wdev = dev->ieee80211_ptr;
432 struct cfg80211_disassoc_request req; 536 struct cfg80211_disassoc_request req;
433 537
538 ASSERT_WDEV_LOCK(wdev);
539
434 memset(&req, 0, sizeof(req)); 540 memset(&req, 0, sizeof(req));
435 req.reason_code = reason; 541 req.reason_code = reason;
436 req.ie = ie; 542 req.ie = ie;
@@ -440,7 +546,21 @@ int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
440 else 546 else
441 return -ENOTCONN; 547 return -ENOTCONN;
442 548
443 return rdev->ops->disassoc(&rdev->wiphy, dev, &req); 549 return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev);
550}
551
552int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
553 struct net_device *dev, const u8 *bssid,
554 const u8 *ie, int ie_len, u16 reason)
555{
556 struct wireless_dev *wdev = dev->ieee80211_ptr;
557 int err;
558
559 wdev_lock(wdev);
560 err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason);
561 wdev_unlock(wdev);
562
563 return err;
444} 564}
445 565
446void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, 566void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
@@ -450,6 +570,8 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
450 struct cfg80211_deauth_request req; 570 struct cfg80211_deauth_request req;
451 int i; 571 int i;
452 572
573 ASSERT_WDEV_LOCK(wdev);
574
453 if (!rdev->ops->deauth) 575 if (!rdev->ops->deauth)
454 return; 576 return;
455 577
@@ -460,7 +582,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
460 582
461 if (wdev->current_bss) { 583 if (wdev->current_bss) {
462 req.bss = &wdev->current_bss->pub; 584 req.bss = &wdev->current_bss->pub;
463 rdev->ops->deauth(&rdev->wiphy, dev, &req); 585 rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
464 if (wdev->current_bss) { 586 if (wdev->current_bss) {
465 cfg80211_unhold_bss(wdev->current_bss); 587 cfg80211_unhold_bss(wdev->current_bss);
466 cfg80211_put_bss(&wdev->current_bss->pub); 588 cfg80211_put_bss(&wdev->current_bss->pub);
@@ -471,7 +593,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
471 for (i = 0; i < MAX_AUTH_BSSES; i++) { 593 for (i = 0; i < MAX_AUTH_BSSES; i++) {
472 if (wdev->auth_bsses[i]) { 594 if (wdev->auth_bsses[i]) {
473 req.bss = &wdev->auth_bsses[i]->pub; 595 req.bss = &wdev->auth_bsses[i]->pub;
474 rdev->ops->deauth(&rdev->wiphy, dev, &req); 596 rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
475 if (wdev->auth_bsses[i]) { 597 if (wdev->auth_bsses[i]) {
476 cfg80211_unhold_bss(wdev->auth_bsses[i]); 598 cfg80211_unhold_bss(wdev->auth_bsses[i]);
477 cfg80211_put_bss(&wdev->auth_bsses[i]->pub); 599 cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
@@ -480,7 +602,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
480 } 602 }
481 if (wdev->authtry_bsses[i]) { 603 if (wdev->authtry_bsses[i]) {
482 req.bss = &wdev->authtry_bsses[i]->pub; 604 req.bss = &wdev->authtry_bsses[i]->pub;
483 rdev->ops->deauth(&rdev->wiphy, dev, &req); 605 rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev);
484 if (wdev->authtry_bsses[i]) { 606 if (wdev->authtry_bsses[i]) {
485 cfg80211_unhold_bss(wdev->authtry_bsses[i]); 607 cfg80211_unhold_bss(wdev->authtry_bsses[i]);
486 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); 608 cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);