aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.h15
-rw-r--r--net/wireless/mlme.c39
-rw-r--r--net/wireless/nl80211.c19
-rw-r--r--net/wireless/sme.c15
4 files changed, 63 insertions, 25 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index d52da913145a..b2234b436ead 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -293,13 +293,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
293 const u8 *bssid, 293 const u8 *bssid,
294 const u8 *ssid, int ssid_len, 294 const u8 *ssid, int ssid_len,
295 const u8 *ie, int ie_len, 295 const u8 *ie, int ie_len,
296 const u8 *key, int key_len, int key_idx); 296 const u8 *key, int key_len, int key_idx,
297 bool local_state_change);
297int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 298int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
298 struct net_device *dev, struct ieee80211_channel *chan, 299 struct net_device *dev, struct ieee80211_channel *chan,
299 enum nl80211_auth_type auth_type, const u8 *bssid, 300 enum nl80211_auth_type auth_type, const u8 *bssid,
300 const u8 *ssid, int ssid_len, 301 const u8 *ssid, int ssid_len,
301 const u8 *ie, int ie_len, 302 const u8 *ie, int ie_len,
302 const u8 *key, int key_len, int key_idx); 303 const u8 *key, int key_len, int key_idx,
304 bool local_state_change);
303int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 305int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
304 struct net_device *dev, 306 struct net_device *dev,
305 struct ieee80211_channel *chan, 307 struct ieee80211_channel *chan,
@@ -315,13 +317,16 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
315 struct cfg80211_crypto_settings *crypt); 317 struct cfg80211_crypto_settings *crypt);
316int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 318int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
317 struct net_device *dev, const u8 *bssid, 319 struct net_device *dev, const u8 *bssid,
318 const u8 *ie, int ie_len, u16 reason); 320 const u8 *ie, int ie_len, u16 reason,
321 bool local_state_change);
319int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 322int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
320 struct net_device *dev, const u8 *bssid, 323 struct net_device *dev, const u8 *bssid,
321 const u8 *ie, int ie_len, u16 reason); 324 const u8 *ie, int ie_len, u16 reason,
325 bool local_state_change);
322int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 326int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
323 struct net_device *dev, const u8 *bssid, 327 struct net_device *dev, const u8 *bssid,
324 const u8 *ie, int ie_len, u16 reason); 328 const u8 *ie, int ie_len, u16 reason,
329 bool local_state_change);
325void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, 330void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
326 struct net_device *dev); 331 struct net_device *dev);
327void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 332void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 0855f0d32349..387dd2a27d2f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -377,7 +377,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
377 const u8 *bssid, 377 const u8 *bssid,
378 const u8 *ssid, int ssid_len, 378 const u8 *ssid, int ssid_len,
379 const u8 *ie, int ie_len, 379 const u8 *ie, int ie_len,
380 const u8 *key, int key_len, int key_idx) 380 const u8 *key, int key_len, int key_idx,
381 bool local_state_change)
381{ 382{
382 struct wireless_dev *wdev = dev->ieee80211_ptr; 383 struct wireless_dev *wdev = dev->ieee80211_ptr;
383 struct cfg80211_auth_request req; 384 struct cfg80211_auth_request req;
@@ -407,6 +408,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
407 408
408 memset(&req, 0, sizeof(req)); 409 memset(&req, 0, sizeof(req));
409 410
411 req.local_state_change = local_state_change;
410 req.ie = ie; 412 req.ie = ie;
411 req.ie_len = ie_len; 413 req.ie_len = ie_len;
412 req.auth_type = auth_type; 414 req.auth_type = auth_type;
@@ -433,12 +435,18 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
433 goto out; 435 goto out;
434 } 436 }
435 437
436 wdev->authtry_bsses[slot] = bss; 438 if (local_state_change)
439 wdev->auth_bsses[slot] = bss;
440 else
441 wdev->authtry_bsses[slot] = bss;
437 cfg80211_hold_bss(bss); 442 cfg80211_hold_bss(bss);
438 443
439 err = rdev->ops->auth(&rdev->wiphy, dev, &req); 444 err = rdev->ops->auth(&rdev->wiphy, dev, &req);
440 if (err) { 445 if (err) {
441 wdev->authtry_bsses[slot] = NULL; 446 if (local_state_change)
447 wdev->auth_bsses[slot] = NULL;
448 else
449 wdev->authtry_bsses[slot] = NULL;
442 cfg80211_unhold_bss(bss); 450 cfg80211_unhold_bss(bss);
443 } 451 }
444 452
@@ -453,14 +461,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
453 enum nl80211_auth_type auth_type, const u8 *bssid, 461 enum nl80211_auth_type auth_type, const u8 *bssid,
454 const u8 *ssid, int ssid_len, 462 const u8 *ssid, int ssid_len,
455 const u8 *ie, int ie_len, 463 const u8 *ie, int ie_len,
456 const u8 *key, int key_len, int key_idx) 464 const u8 *key, int key_len, int key_idx,
465 bool local_state_change)
457{ 466{
458 int err; 467 int err;
459 468
460 wdev_lock(dev->ieee80211_ptr); 469 wdev_lock(dev->ieee80211_ptr);
461 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 470 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
462 ssid, ssid_len, ie, ie_len, 471 ssid, ssid_len, ie, ie_len,
463 key, key_len, key_idx); 472 key, key_len, key_idx, local_state_change);
464 wdev_unlock(dev->ieee80211_ptr); 473 wdev_unlock(dev->ieee80211_ptr);
465 474
466 return err; 475 return err;
@@ -554,7 +563,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
554 563
555int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 564int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
556 struct net_device *dev, const u8 *bssid, 565 struct net_device *dev, const u8 *bssid,
557 const u8 *ie, int ie_len, u16 reason) 566 const u8 *ie, int ie_len, u16 reason,
567 bool local_state_change)
558{ 568{
559 struct wireless_dev *wdev = dev->ieee80211_ptr; 569 struct wireless_dev *wdev = dev->ieee80211_ptr;
560 struct cfg80211_deauth_request req; 570 struct cfg80211_deauth_request req;
@@ -564,6 +574,7 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
564 574
565 memset(&req, 0, sizeof(req)); 575 memset(&req, 0, sizeof(req));
566 req.reason_code = reason; 576 req.reason_code = reason;
577 req.local_state_change = local_state_change;
567 req.ie = ie; 578 req.ie = ie;
568 req.ie_len = ie_len; 579 req.ie_len = ie_len;
569 if (wdev->current_bss && 580 if (wdev->current_bss &&
@@ -590,13 +601,15 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
590 601
591int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 602int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
592 struct net_device *dev, const u8 *bssid, 603 struct net_device *dev, const u8 *bssid,
593 const u8 *ie, int ie_len, u16 reason) 604 const u8 *ie, int ie_len, u16 reason,
605 bool local_state_change)
594{ 606{
595 struct wireless_dev *wdev = dev->ieee80211_ptr; 607 struct wireless_dev *wdev = dev->ieee80211_ptr;
596 int err; 608 int err;
597 609
598 wdev_lock(wdev); 610 wdev_lock(wdev);
599 err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); 611 err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
612 local_state_change);
600 wdev_unlock(wdev); 613 wdev_unlock(wdev);
601 614
602 return err; 615 return err;
@@ -604,7 +617,8 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
604 617
605static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 618static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
606 struct net_device *dev, const u8 *bssid, 619 struct net_device *dev, const u8 *bssid,
607 const u8 *ie, int ie_len, u16 reason) 620 const u8 *ie, int ie_len, u16 reason,
621 bool local_state_change)
608{ 622{
609 struct wireless_dev *wdev = dev->ieee80211_ptr; 623 struct wireless_dev *wdev = dev->ieee80211_ptr;
610 struct cfg80211_disassoc_request req; 624 struct cfg80211_disassoc_request req;
@@ -619,6 +633,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
619 633
620 memset(&req, 0, sizeof(req)); 634 memset(&req, 0, sizeof(req));
621 req.reason_code = reason; 635 req.reason_code = reason;
636 req.local_state_change = local_state_change;
622 req.ie = ie; 637 req.ie = ie;
623 req.ie_len = ie_len; 638 req.ie_len = ie_len;
624 if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) 639 if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0)
@@ -631,13 +646,15 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
631 646
632int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 647int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
633 struct net_device *dev, const u8 *bssid, 648 struct net_device *dev, const u8 *bssid,
634 const u8 *ie, int ie_len, u16 reason) 649 const u8 *ie, int ie_len, u16 reason,
650 bool local_state_change)
635{ 651{
636 struct wireless_dev *wdev = dev->ieee80211_ptr; 652 struct wireless_dev *wdev = dev->ieee80211_ptr;
637 int err; 653 int err;
638 654
639 wdev_lock(wdev); 655 wdev_lock(wdev);
640 err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); 656 err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
657 local_state_change);
641 wdev_unlock(wdev); 658 wdev_unlock(wdev);
642 659
643 return err; 660 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 95149f303409..df5505b3930c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -150,6 +150,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
150 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, 150 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
151 [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, 151 [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
152 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, 152 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
153 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
153}; 154};
154 155
155/* policy for the attributes */ 156/* policy for the attributes */
@@ -3393,6 +3394,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3393 int err, ssid_len, ie_len = 0; 3394 int err, ssid_len, ie_len = 0;
3394 enum nl80211_auth_type auth_type; 3395 enum nl80211_auth_type auth_type;
3395 struct key_parse key; 3396 struct key_parse key;
3397 bool local_state_change;
3396 3398
3397 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3399 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3398 return -EINVAL; 3400 return -EINVAL;
@@ -3471,9 +3473,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3471 goto out; 3473 goto out;
3472 } 3474 }
3473 3475
3476 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3477
3474 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 3478 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3475 ssid, ssid_len, ie, ie_len, 3479 ssid, ssid_len, ie, ie_len,
3476 key.p.key, key.p.key_len, key.idx); 3480 key.p.key, key.p.key_len, key.idx,
3481 local_state_change);
3477 3482
3478out: 3483out:
3479 cfg80211_unlock_rdev(rdev); 3484 cfg80211_unlock_rdev(rdev);
@@ -3650,6 +3655,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3650 const u8 *ie = NULL, *bssid; 3655 const u8 *ie = NULL, *bssid;
3651 int err, ie_len = 0; 3656 int err, ie_len = 0;
3652 u16 reason_code; 3657 u16 reason_code;
3658 bool local_state_change;
3653 3659
3654 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3660 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3655 return -EINVAL; 3661 return -EINVAL;
@@ -3695,7 +3701,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
3695 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3701 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3696 } 3702 }
3697 3703
3698 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code); 3704 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3705
3706 err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
3707 local_state_change);
3699 3708
3700out: 3709out:
3701 cfg80211_unlock_rdev(rdev); 3710 cfg80211_unlock_rdev(rdev);
@@ -3712,6 +3721,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3712 const u8 *ie = NULL, *bssid; 3721 const u8 *ie = NULL, *bssid;
3713 int err, ie_len = 0; 3722 int err, ie_len = 0;
3714 u16 reason_code; 3723 u16 reason_code;
3724 bool local_state_change;
3715 3725
3716 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3726 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3717 return -EINVAL; 3727 return -EINVAL;
@@ -3757,7 +3767,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
3757 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 3767 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3758 } 3768 }
3759 3769
3760 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code); 3770 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
3771
3772 err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
3773 local_state_change);
3761 3774
3762out: 3775out:
3763 cfg80211_unlock_rdev(rdev); 3776 cfg80211_unlock_rdev(rdev);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 17fde0da1b08..17465777eb47 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -170,7 +170,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
170 params->ssid, params->ssid_len, 170 params->ssid, params->ssid_len,
171 NULL, 0, 171 NULL, 0,
172 params->key, params->key_len, 172 params->key, params->key_len,
173 params->key_idx); 173 params->key_idx, false);
174 case CFG80211_CONN_ASSOCIATE_NEXT: 174 case CFG80211_CONN_ASSOCIATE_NEXT:
175 BUG_ON(!rdev->ops->assoc); 175 BUG_ON(!rdev->ops->assoc);
176 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 176 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -185,12 +185,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
185 if (err) 185 if (err)
186 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 186 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
187 NULL, 0, 187 NULL, 0,
188 WLAN_REASON_DEAUTH_LEAVING); 188 WLAN_REASON_DEAUTH_LEAVING,
189 false);
189 return err; 190 return err;
190 case CFG80211_CONN_DEAUTH_ASSOC_FAIL: 191 case CFG80211_CONN_DEAUTH_ASSOC_FAIL:
191 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 192 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
192 NULL, 0, 193 NULL, 0,
193 WLAN_REASON_DEAUTH_LEAVING); 194 WLAN_REASON_DEAUTH_LEAVING, false);
194 /* return an error so that we call __cfg80211_connect_result() */ 195 /* return an error so that we call __cfg80211_connect_result() */
195 return -EINVAL; 196 return -EINVAL;
196 default: 197 default:
@@ -675,7 +676,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
675 continue; 676 continue;
676 bssid = wdev->auth_bsses[i]->pub.bssid; 677 bssid = wdev->auth_bsses[i]->pub.bssid;
677 ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, 678 ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
678 WLAN_REASON_DEAUTH_LEAVING); 679 WLAN_REASON_DEAUTH_LEAVING,
680 false);
679 WARN(ret, "deauth failed: %d\n", ret); 681 WARN(ret, "deauth failed: %d\n", ret);
680 } 682 }
681 } 683 }
@@ -934,7 +936,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
934 /* wdev->conn->params.bssid must be set if > SCANNING */ 936 /* wdev->conn->params.bssid must be set if > SCANNING */
935 err = __cfg80211_mlme_deauth(rdev, dev, 937 err = __cfg80211_mlme_deauth(rdev, dev,
936 wdev->conn->params.bssid, 938 wdev->conn->params.bssid,
937 NULL, 0, reason); 939 NULL, 0, reason, false);
938 if (err) 940 if (err)
939 return err; 941 return err;
940 } else { 942 } else {
@@ -990,7 +992,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx)
990 992
991 memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); 993 memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN);
992 if (__cfg80211_mlme_deauth(rdev, dev, bssid, 994 if (__cfg80211_mlme_deauth(rdev, dev, bssid,
993 NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { 995 NULL, 0, WLAN_REASON_DEAUTH_LEAVING,
996 false)) {
994 /* whatever -- assume gone anyway */ 997 /* whatever -- assume gone anyway */
995 cfg80211_unhold_bss(wdev->auth_bsses[idx]); 998 cfg80211_unhold_bss(wdev->auth_bsses[idx]);
996 cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); 999 cfg80211_put_bss(&wdev->auth_bsses[idx]->pub);