aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext-compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/wext-compat.c')
-rw-r--r--net/wireless/wext-compat.c163
1 files changed, 101 insertions, 62 deletions
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 5088d89a30fc..5d0176338539 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -453,15 +453,32 @@ int cfg80211_wext_giwretry(struct net_device *dev,
453} 453}
454EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 454EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
455 455
456static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 456static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
457 struct net_device *dev, const u8 *addr, 457 struct net_device *dev, const u8 *addr,
458 bool remove, bool tx_key, int idx, 458 bool remove, bool tx_key, int idx,
459 struct key_params *params) 459 struct key_params *params)
460{ 460{
461 struct wireless_dev *wdev = dev->ieee80211_ptr; 461 struct wireless_dev *wdev = dev->ieee80211_ptr;
462 int err; 462 int err, i;
463
464 if (!wdev->wext.keys) {
465 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
466 GFP_KERNEL);
467 if (!wdev->wext.keys)
468 return -ENOMEM;
469 for (i = 0; i < 6; i++)
470 wdev->wext.keys->params[i].key =
471 wdev->wext.keys->data[i];
472 }
473
474 if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
475 wdev->iftype != NL80211_IFTYPE_STATION)
476 return -EOPNOTSUPP;
463 477
464 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 478 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
479 if (!wdev->current_bss)
480 return -ENOLINK;
481
465 if (!rdev->ops->set_default_mgmt_key) 482 if (!rdev->ops->set_default_mgmt_key)
466 return -EOPNOTSUPP; 483 return -EOPNOTSUPP;
467 484
@@ -471,8 +488,14 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
471 return -EINVAL; 488 return -EINVAL;
472 489
473 if (remove) { 490 if (remove) {
474 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 491 err = 0;
492 if (wdev->current_bss)
493 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
475 if (!err) { 494 if (!err) {
495 if (!addr) {
496 wdev->wext.keys->params[idx].key_len = 0;
497 wdev->wext.keys->params[idx].cipher = 0;
498 }
476 if (idx == wdev->wext.default_key) 499 if (idx == wdev->wext.default_key)
477 wdev->wext.default_key = -1; 500 wdev->wext.default_key = -1;
478 else if (idx == wdev->wext.default_mgmt_key) 501 else if (idx == wdev->wext.default_mgmt_key)
@@ -486,36 +509,64 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
486 return 0; 509 return 0;
487 510
488 return err; 511 return err;
489 } else { 512 }
490 if (addr)
491 tx_key = false;
492 513
493 if (cfg80211_validate_key_settings(params, idx, addr)) 514 if (addr)
494 return -EINVAL; 515 tx_key = false;
495 516
517 if (cfg80211_validate_key_settings(rdev, params, idx, addr))
518 return -EINVAL;
519
520 err = 0;
521 if (wdev->current_bss)
496 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); 522 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
497 if (err) 523 if (err)
498 return err; 524 return err;
525
526 if (!addr) {
527 wdev->wext.keys->params[idx] = *params;
528 memcpy(wdev->wext.keys->data[idx],
529 params->key, params->key_len);
530 wdev->wext.keys->params[idx].key =
531 wdev->wext.keys->data[idx];
532 }
499 533
500 if (tx_key || (!addr && wdev->wext.default_key == -1)) { 534 if (params->cipher != WLAN_CIPHER_SUITE_AES_CMAC &&
535 (tx_key || (!addr && wdev->wext.default_key == -1))) {
536 if (wdev->current_bss)
501 err = rdev->ops->set_default_key(&rdev->wiphy, 537 err = rdev->ops->set_default_key(&rdev->wiphy,
502 dev, idx); 538 dev, idx);
503 if (!err) 539 if (!err)
504 wdev->wext.default_key = idx; 540 wdev->wext.default_key = idx;
505 return err; 541 return err;
506 } 542 }
507 543
508 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC && 544 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
509 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) { 545 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
546 if (wdev->current_bss)
510 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, 547 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
511 dev, idx); 548 dev, idx);
512 if (!err) 549 if (!err)
513 wdev->wext.default_mgmt_key = idx; 550 wdev->wext.default_mgmt_key = idx;
514 return err; 551 return err;
515 }
516
517 return 0;
518 } 552 }
553
554 return 0;
555}
556
557static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
558 struct net_device *dev, const u8 *addr,
559 bool remove, bool tx_key, int idx,
560 struct key_params *params)
561{
562 int err;
563
564 wdev_lock(dev->ieee80211_ptr);
565 err = __cfg80211_set_encryption(rdev, dev, addr, remove,
566 tx_key, idx, params);
567 wdev_unlock(dev->ieee80211_ptr);
568
569 return err;
519} 570}
520 571
521int cfg80211_wext_siwencode(struct net_device *dev, 572int cfg80211_wext_siwencode(struct net_device *dev,
@@ -528,6 +579,10 @@ int cfg80211_wext_siwencode(struct net_device *dev,
528 bool remove = false; 579 bool remove = false;
529 struct key_params params; 580 struct key_params params;
530 581
582 if (wdev->iftype != NL80211_IFTYPE_STATION &&
583 wdev->iftype != NL80211_IFTYPE_ADHOC)
584 return -EOPNOTSUPP;
585
531 /* no use -- only MFP (set_default_mgmt_key) is optional */ 586 /* no use -- only MFP (set_default_mgmt_key) is optional */
532 if (!rdev->ops->del_key || 587 if (!rdev->ops->del_key ||
533 !rdev->ops->add_key || 588 !rdev->ops->add_key ||
@@ -548,9 +603,14 @@ int cfg80211_wext_siwencode(struct net_device *dev,
548 remove = true; 603 remove = true;
549 else if (erq->length == 0) { 604 else if (erq->length == 0) {
550 /* No key data - just set the default TX key index */ 605 /* No key data - just set the default TX key index */
551 err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx); 606 err = 0;
607 wdev_lock(wdev);
608 if (wdev->current_bss)
609 err = rdev->ops->set_default_key(&rdev->wiphy,
610 dev, idx);
552 if (!err) 611 if (!err)
553 wdev->wext.default_key = idx; 612 wdev->wext.default_key = idx;
613 wdev_unlock(wdev);
554 return err; 614 return err;
555 } 615 }
556 616
@@ -583,6 +643,10 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
583 struct key_params params; 643 struct key_params params;
584 u32 cipher; 644 u32 cipher;
585 645
646 if (wdev->iftype != NL80211_IFTYPE_STATION &&
647 wdev->iftype != NL80211_IFTYPE_ADHOC)
648 return -EOPNOTSUPP;
649
586 /* no use -- only MFP (set_default_mgmt_key) is optional */ 650 /* no use -- only MFP (set_default_mgmt_key) is optional */
587 if (!rdev->ops->del_key || 651 if (!rdev->ops->del_key ||
588 !rdev->ops->add_key || 652 !rdev->ops->add_key ||
@@ -656,37 +720,15 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
656} 720}
657EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); 721EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
658 722
659struct giwencode_cookie {
660 size_t buflen;
661 char *keybuf;
662};
663
664static void giwencode_get_key_cb(void *cookie, struct key_params *params)
665{
666 struct giwencode_cookie *data = cookie;
667
668 if (!params->key) {
669 data->buflen = 0;
670 return;
671 }
672
673 data->buflen = min_t(size_t, data->buflen, params->key_len);
674 memcpy(data->keybuf, params->key, data->buflen);
675}
676
677int cfg80211_wext_giwencode(struct net_device *dev, 723int cfg80211_wext_giwencode(struct net_device *dev,
678 struct iw_request_info *info, 724 struct iw_request_info *info,
679 struct iw_point *erq, char *keybuf) 725 struct iw_point *erq, char *keybuf)
680{ 726{
681 struct wireless_dev *wdev = dev->ieee80211_ptr; 727 struct wireless_dev *wdev = dev->ieee80211_ptr;
682 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 728 int idx;
683 int idx, err;
684 struct giwencode_cookie data = {
685 .keybuf = keybuf,
686 .buflen = erq->length,
687 };
688 729
689 if (!rdev->ops->get_key) 730 if (wdev->iftype != NL80211_IFTYPE_STATION &&
731 wdev->iftype != NL80211_IFTYPE_ADHOC)
690 return -EOPNOTSUPP; 732 return -EOPNOTSUPP;
691 733
692 idx = erq->flags & IW_ENCODE_INDEX; 734 idx = erq->flags & IW_ENCODE_INDEX;
@@ -701,21 +743,18 @@ int cfg80211_wext_giwencode(struct net_device *dev,
701 743
702 erq->flags = idx + 1; 744 erq->flags = idx + 1;
703 745
704 err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data, 746 if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
705 giwencode_get_key_cb);
706 if (!err) {
707 erq->length = data.buflen;
708 erq->flags |= IW_ENCODE_ENABLED;
709 return 0;
710 }
711
712 if (err == -ENOENT) {
713 erq->flags |= IW_ENCODE_DISABLED; 747 erq->flags |= IW_ENCODE_DISABLED;
714 erq->length = 0; 748 erq->length = 0;
715 return 0; 749 return 0;
716 } 750 }
717 751
718 return err; 752 erq->length = min_t(size_t, erq->length,
753 wdev->wext.keys->params[idx].key_len);
754 memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
755 erq->flags |= IW_ENCODE_ENABLED;
756
757 return 0;
719} 758}
720EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); 759EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
721 760