aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-05-11 07:54:58 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-13 15:44:32 -0400
commit08645126dd24872c2e27014f93968f7312e29176 (patch)
tree2011cb3cb2f70d35278ef3b39ea696a058fb7b29 /net/mac80211
parent7be69c0b9aa93ef655db4d46e5654996489d62f5 (diff)
cfg80211: implement wext key handling
Move key handling wireless extension ioctls from mac80211 to cfg80211 so that all drivers that implement the cfg80211 operations get wext compatibility. Note that this drops the SIOCGIWENCODE ioctl support for getting IW_ENCODE_RESTRICTED/IW_ENCODE_OPEN. This means that iwconfig will no longer report "Security mode:open" or "Security mode:restricted" for mac80211. However, what we displayed there (the authentication algo used) was actually wrong -- linux/wireless.h states that this setting is meant to differentiate between "Refuse non-encoded packets" and "Accept non-encoded packets". (Combined with "cfg80211: fix a couple of bugs with key ioctls". -- JWL) Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/wext.c279
1 files changed, 3 insertions, 276 deletions
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 6b4eb8d43a4e..d84502644686 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -27,100 +27,6 @@
27#include "aes_ccm.h" 27#include "aes_ccm.h"
28 28
29 29
30static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr,
31 int idx, int alg, int remove,
32 int set_tx_key, const u8 *_key,
33 size_t key_len)
34{
35 struct ieee80211_local *local = sdata->local;
36 struct sta_info *sta;
37 struct ieee80211_key *key;
38 int err;
39
40 if (alg == ALG_AES_CMAC) {
41 if (idx < NUM_DEFAULT_KEYS ||
42 idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
43 printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
44 "(BIP)\n", sdata->dev->name, idx);
45 return -EINVAL;
46 }
47 } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
48 printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
49 sdata->dev->name, idx);
50 return -EINVAL;
51 }
52
53 if (remove) {
54 rcu_read_lock();
55
56 err = 0;
57
58 if (is_broadcast_ether_addr(sta_addr)) {
59 key = sdata->keys[idx];
60 } else {
61 sta = sta_info_get(local, sta_addr);
62 if (!sta) {
63 err = -ENOENT;
64 goto out_unlock;
65 }
66 key = sta->key;
67 }
68
69 ieee80211_key_free(key);
70 } else {
71 key = ieee80211_key_alloc(alg, idx, key_len, _key);
72 if (!key)
73 return -ENOMEM;
74
75 sta = NULL;
76 err = 0;
77
78 rcu_read_lock();
79
80 if (!is_broadcast_ether_addr(sta_addr)) {
81 set_tx_key = 0;
82 /*
83 * According to the standard, the key index of a
84 * pairwise key must be zero. However, some AP are
85 * broken when it comes to WEP key indices, so we
86 * work around this.
87 */
88 if (idx != 0 && alg != ALG_WEP) {
89 ieee80211_key_free(key);
90 err = -EINVAL;
91 goto out_unlock;
92 }
93
94 sta = sta_info_get(local, sta_addr);
95 if (!sta) {
96 ieee80211_key_free(key);
97 err = -ENOENT;
98 goto out_unlock;
99 }
100 }
101
102 if (alg == ALG_WEP &&
103 key_len != LEN_WEP40 && key_len != LEN_WEP104) {
104 ieee80211_key_free(key);
105 err = -EINVAL;
106 goto out_unlock;
107 }
108
109 ieee80211_key_link(key, sdata, sta);
110
111 if (set_tx_key || (!sta && !sdata->default_key && key))
112 ieee80211_set_default_key(sdata, idx);
113 if (alg == ALG_AES_CMAC &&
114 (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
115 ieee80211_set_default_mgmt_key(sdata, idx);
116 }
117
118 out_unlock:
119 rcu_read_unlock();
120
121 return err;
122}
123
124static int ieee80211_ioctl_siwgenie(struct net_device *dev, 30static int ieee80211_ioctl_siwgenie(struct net_device *dev,
125 struct iw_request_info *info, 31 struct iw_request_info *info,
126 struct iw_point *data, char *extra) 32 struct iw_point *data, char *extra)
@@ -472,109 +378,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
472 return 0; 378 return 0;
473} 379}
474 380
475static int ieee80211_ioctl_siwencode(struct net_device *dev,
476 struct iw_request_info *info,
477 struct iw_point *erq, char *keybuf)
478{
479 struct ieee80211_sub_if_data *sdata;
480 int idx, i, alg = ALG_WEP;
481 u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
482 int remove = 0, ret;
483
484 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
485
486 idx = erq->flags & IW_ENCODE_INDEX;
487 if (idx == 0) {
488 if (sdata->default_key)
489 for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
490 if (sdata->default_key == sdata->keys[i]) {
491 idx = i;
492 break;
493 }
494 }
495 } else if (idx < 1 || idx > 4)
496 return -EINVAL;
497 else
498 idx--;
499
500 if (erq->flags & IW_ENCODE_DISABLED)
501 remove = 1;
502 else if (erq->length == 0) {
503 /* No key data - just set the default TX key index */
504 ieee80211_set_default_key(sdata, idx);
505 return 0;
506 }
507
508 ret = ieee80211_set_encryption(
509 sdata, bcaddr,
510 idx, alg, remove,
511 !sdata->default_key,
512 keybuf, erq->length);
513
514 if (!ret && sdata->vif.type == NL80211_IFTYPE_STATION) {
515 if (remove)
516 sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
517 else
518 sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED;
519 }
520
521 return ret;
522}
523
524
525static int ieee80211_ioctl_giwencode(struct net_device *dev,
526 struct iw_request_info *info,
527 struct iw_point *erq, char *key)
528{
529 struct ieee80211_sub_if_data *sdata;
530 int idx, i;
531
532 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
533
534 idx = erq->flags & IW_ENCODE_INDEX;
535 if (idx < 1 || idx > 4) {
536 idx = -1;
537 if (!sdata->default_key)
538 idx = 0;
539 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
540 if (sdata->default_key == sdata->keys[i]) {
541 idx = i;
542 break;
543 }
544 }
545 if (idx < 0)
546 return -EINVAL;
547 } else
548 idx--;
549
550 erq->flags = idx + 1;
551
552 if (!sdata->keys[idx]) {
553 erq->length = 0;
554 erq->flags |= IW_ENCODE_DISABLED;
555 return 0;
556 }
557
558 memcpy(key, sdata->keys[idx]->conf.key,
559 min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
560 erq->length = sdata->keys[idx]->conf.keylen;
561 erq->flags |= IW_ENCODE_ENABLED;
562
563 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
564 switch (sdata->u.mgd.auth_alg) {
565 case WLAN_AUTH_OPEN:
566 case WLAN_AUTH_LEAP:
567 erq->flags |= IW_ENCODE_OPEN;
568 break;
569 case WLAN_AUTH_SHARED_KEY:
570 erq->flags |= IW_ENCODE_RESTRICTED;
571 break;
572 }
573 }
574
575 return 0;
576}
577
578static int ieee80211_ioctl_siwpower(struct net_device *dev, 381static int ieee80211_ioctl_siwpower(struct net_device *dev,
579 struct iw_request_info *info, 382 struct iw_request_info *info,
580 struct iw_param *wrq, 383 struct iw_param *wrq,
@@ -809,82 +612,6 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev,
809} 612}
810 613
811 614
812static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
813 struct iw_request_info *info,
814 struct iw_point *erq, char *extra)
815{
816 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
817 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
818 int uninitialized_var(alg), idx, i, remove = 0;
819
820 switch (ext->alg) {
821 case IW_ENCODE_ALG_NONE:
822 remove = 1;
823 break;
824 case IW_ENCODE_ALG_WEP:
825 alg = ALG_WEP;
826 break;
827 case IW_ENCODE_ALG_TKIP:
828 alg = ALG_TKIP;
829 break;
830 case IW_ENCODE_ALG_CCMP:
831 alg = ALG_CCMP;
832 break;
833 case IW_ENCODE_ALG_AES_CMAC:
834 alg = ALG_AES_CMAC;
835 break;
836 default:
837 return -EOPNOTSUPP;
838 }
839
840 if (erq->flags & IW_ENCODE_DISABLED)
841 remove = 1;
842
843 idx = erq->flags & IW_ENCODE_INDEX;
844 if (alg == ALG_AES_CMAC) {
845 if (idx < NUM_DEFAULT_KEYS + 1 ||
846 idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
847 idx = -1;
848 if (!sdata->default_mgmt_key)
849 idx = 0;
850 else for (i = NUM_DEFAULT_KEYS;
851 i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
852 i++) {
853 if (sdata->default_mgmt_key == sdata->keys[i])
854 {
855 idx = i;
856 break;
857 }
858 }
859 if (idx < 0)
860 return -EINVAL;
861 } else
862 idx--;
863 } else {
864 if (idx < 1 || idx > 4) {
865 idx = -1;
866 if (!sdata->default_key)
867 idx = 0;
868 else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
869 if (sdata->default_key == sdata->keys[i]) {
870 idx = i;
871 break;
872 }
873 }
874 if (idx < 0)
875 return -EINVAL;
876 } else
877 idx--;
878 }
879
880 return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
881 remove,
882 ext->ext_flags &
883 IW_ENCODE_EXT_SET_TX_KEY,
884 ext->key, ext->key_len);
885}
886
887
888/* Structures to export the Wireless Handlers */ 615/* Structures to export the Wireless Handlers */
889 616
890static const iw_handler ieee80211_handler[] = 617static const iw_handler ieee80211_handler[] =
@@ -931,8 +658,8 @@ static const iw_handler ieee80211_handler[] =
931 (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ 658 (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
932 (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ 659 (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
933 (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ 660 (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
934 (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ 661 (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
935 (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ 662 (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */
936 (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ 663 (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */
937 (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ 664 (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */
938 (iw_handler) NULL, /* -- hole -- */ 665 (iw_handler) NULL, /* -- hole -- */
@@ -941,7 +668,7 @@ static const iw_handler ieee80211_handler[] =
941 (iw_handler) NULL, /* SIOCGIWGENIE */ 668 (iw_handler) NULL, /* SIOCGIWGENIE */
942 (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */ 669 (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
943 (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */ 670 (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
944 (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ 671 (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
945 (iw_handler) NULL, /* SIOCGIWENCODEEXT */ 672 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
946 (iw_handler) NULL, /* SIOCSIWPMKSA */ 673 (iw_handler) NULL, /* SIOCSIWPMKSA */
947 (iw_handler) NULL, /* -- hole -- */ 674 (iw_handler) NULL, /* -- hole -- */