aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/mlme.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-04-04 02:37:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-07 14:37:56 -0400
commitd5cdfacb35ed886271d1ccfffbded98d3447da17 (patch)
tree8233a713949c4c8da8c98e75868efc74d5613c3d /net/wireless/mlme.c
parent7590a550b88b8c3cb025f0a8ed58e279ad62e4c1 (diff)
cfg80211: Add local-state-change-only auth/deauth/disassoc
cfg80211 is quite strict on allowing authentication and association commands only in certain states. In order to meet these requirements, user space applications may need to clear authentication or association state in some cases. Currently, this can be done with deauth/disassoc command, but that ends up sending out Deauthentication or Disassociation frame unnecessarily. Add a new nl80211 attribute to allow this sending of the frame be skipped, but with all other deauth/disassoc operations being completed. Similar state change is also needed for IEEE 802.11r FT protocol in the FT-over-DS case which does not use Authentication frame exchange in a transition to another BSS. For this to work with cfg80211, an authentication entry needs to be created for the target BSS without sending out an Authentication frame. The nl80211 authentication command can be used for this purpose, too, with the new attribute to indicate that the command is only for changing local state. This enables wpa_supplicant to complete FT-over-DS transition successfully. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r--net/wireless/mlme.c39
1 files changed, 28 insertions, 11 deletions
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;