diff options
Diffstat (limited to 'net/wireless/wext-compat.c')
-rw-r--r-- | net/wireless/wext-compat.c | 163 |
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 | } |
454 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); | 454 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); |
455 | 455 | ||
456 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 456 | static 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 | |||
557 | static 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 | ||
521 | int cfg80211_wext_siwencode(struct net_device *dev, | 572 | int 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 | } |
657 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); | 721 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); |
658 | 722 | ||
659 | struct giwencode_cookie { | ||
660 | size_t buflen; | ||
661 | char *keybuf; | ||
662 | }; | ||
663 | |||
664 | static 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 | |||
677 | int cfg80211_wext_giwencode(struct net_device *dev, | 723 | int 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 | } |
720 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); | 759 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); |
721 | 760 | ||