diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-10-05 13:39:30 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-10-06 16:30:40 -0400 |
commit | e31b82136d1adc7a599b6e99d3321e5831841f5a (patch) | |
tree | c72d78d4cccfd08587e909c7efe59956f1cbc23e /net/wireless/wext-compat.c | |
parent | 53f73c09d64f1fa7d7e6e8b6bb7468d42eddc92d (diff) |
cfg80211/mac80211: allow per-station GTKs
This adds API to allow adding per-station GTKs,
updates mac80211 to support it, and also allows
drivers to remove a key from hwaccel again when
this may be necessary due to multiple GTKs.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/wext-compat.c')
-rw-r--r-- | net/wireless/wext-compat.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 7e5c3a45f811..6002265289c6 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -432,14 +432,17 @@ int cfg80211_wext_giwretry(struct net_device *dev, | |||
432 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); | 432 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); |
433 | 433 | ||
434 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 434 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, |
435 | struct net_device *dev, const u8 *addr, | 435 | struct net_device *dev, bool pairwise, |
436 | bool remove, bool tx_key, int idx, | 436 | const u8 *addr, bool remove, bool tx_key, |
437 | struct key_params *params) | 437 | int idx, struct key_params *params) |
438 | { | 438 | { |
439 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 439 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
440 | int err, i; | 440 | int err, i; |
441 | bool rejoin = false; | 441 | bool rejoin = false; |
442 | 442 | ||
443 | if (pairwise && !addr) | ||
444 | return -EINVAL; | ||
445 | |||
443 | if (!wdev->wext.keys) { | 446 | if (!wdev->wext.keys) { |
444 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), | 447 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), |
445 | GFP_KERNEL); | 448 | GFP_KERNEL); |
@@ -478,7 +481,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
478 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | 481 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); |
479 | rejoin = true; | 482 | rejoin = true; |
480 | } | 483 | } |
481 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); | 484 | |
485 | if (!pairwise && addr && | ||
486 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
487 | err = -ENOENT; | ||
488 | else | ||
489 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, | ||
490 | pairwise, addr); | ||
482 | } | 491 | } |
483 | wdev->wext.connect.privacy = false; | 492 | wdev->wext.connect.privacy = false; |
484 | /* | 493 | /* |
@@ -507,12 +516,13 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
507 | if (addr) | 516 | if (addr) |
508 | tx_key = false; | 517 | tx_key = false; |
509 | 518 | ||
510 | if (cfg80211_validate_key_settings(rdev, params, idx, addr)) | 519 | if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr)) |
511 | return -EINVAL; | 520 | return -EINVAL; |
512 | 521 | ||
513 | err = 0; | 522 | err = 0; |
514 | if (wdev->current_bss) | 523 | if (wdev->current_bss) |
515 | err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); | 524 | err = rdev->ops->add_key(&rdev->wiphy, dev, idx, |
525 | pairwise, addr, params); | ||
516 | if (err) | 526 | if (err) |
517 | return err; | 527 | return err; |
518 | 528 | ||
@@ -563,17 +573,17 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
563 | } | 573 | } |
564 | 574 | ||
565 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 575 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, |
566 | struct net_device *dev, const u8 *addr, | 576 | struct net_device *dev, bool pairwise, |
567 | bool remove, bool tx_key, int idx, | 577 | const u8 *addr, bool remove, bool tx_key, |
568 | struct key_params *params) | 578 | int idx, struct key_params *params) |
569 | { | 579 | { |
570 | int err; | 580 | int err; |
571 | 581 | ||
572 | /* devlist mutex needed for possible IBSS re-join */ | 582 | /* devlist mutex needed for possible IBSS re-join */ |
573 | mutex_lock(&rdev->devlist_mtx); | 583 | mutex_lock(&rdev->devlist_mtx); |
574 | wdev_lock(dev->ieee80211_ptr); | 584 | wdev_lock(dev->ieee80211_ptr); |
575 | err = __cfg80211_set_encryption(rdev, dev, addr, remove, | 585 | err = __cfg80211_set_encryption(rdev, dev, pairwise, addr, |
576 | tx_key, idx, params); | 586 | remove, tx_key, idx, params); |
577 | wdev_unlock(dev->ieee80211_ptr); | 587 | wdev_unlock(dev->ieee80211_ptr); |
578 | mutex_unlock(&rdev->devlist_mtx); | 588 | mutex_unlock(&rdev->devlist_mtx); |
579 | 589 | ||
@@ -635,7 +645,7 @@ int cfg80211_wext_siwencode(struct net_device *dev, | |||
635 | else if (!remove) | 645 | else if (!remove) |
636 | return -EINVAL; | 646 | return -EINVAL; |
637 | 647 | ||
638 | return cfg80211_set_encryption(rdev, dev, NULL, remove, | 648 | return cfg80211_set_encryption(rdev, dev, false, NULL, remove, |
639 | wdev->wext.default_key == -1, | 649 | wdev->wext.default_key == -1, |
640 | idx, ¶ms); | 650 | idx, ¶ms); |
641 | } | 651 | } |
@@ -725,7 +735,9 @@ int cfg80211_wext_siwencodeext(struct net_device *dev, | |||
725 | } | 735 | } |
726 | 736 | ||
727 | return cfg80211_set_encryption( | 737 | return cfg80211_set_encryption( |
728 | rdev, dev, addr, remove, | 738 | rdev, dev, |
739 | !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY), | ||
740 | addr, remove, | ||
729 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, | 741 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, |
730 | idx, ¶ms); | 742 | idx, ¶ms); |
731 | } | 743 | } |