aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/wext.c
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2009-08-05 16:23:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:12:45 -0400
commit4af198fb7a99b07980b1bd52df550ba3f24688df (patch)
tree8955b89e70dbf82bcf7537130f43a8a1ab2350e3 /drivers/net/wireless/orinoco/wext.c
parent2b2603515e26466685895e93cae59bc061389f11 (diff)
orinoco: consolidate storage of WEP and TKIP keys
When TKIP support was added, we stored the keys separately to avoid issues when both TKIP and WEP keys are sent to the driver. We need to consolidate the storage to convert to cfg80211, so do this first and try iron out the issues. Signed-off-by: David Kilroy <kilroyd@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco/wext.c')
-rw-r--r--drivers/net/wireless/orinoco/wext.c122
1 files changed, 81 insertions, 41 deletions
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index f68bbe383e0f..3e56f7643df5 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -22,6 +22,67 @@
22 22
23#define MAX_RID_LEN 1024 23#define MAX_RID_LEN 1024
24 24
25/* Helper routine to record keys
26 * Do not call from interrupt context */
27static int orinoco_set_key(struct orinoco_private *priv, int index,
28 enum orinoco_alg alg, const u8 *key, int key_len,
29 const u8 *seq, int seq_len)
30{
31 kzfree(priv->keys[index].key);
32 kzfree(priv->keys[index].seq);
33
34 if (key_len) {
35 priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
36 if (!priv->keys[index].key)
37 goto nomem;
38 } else
39 priv->keys[index].key = NULL;
40
41 if (seq_len) {
42 priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
43 if (!priv->keys[index].seq)
44 goto free_key;
45 } else
46 priv->keys[index].seq = NULL;
47
48 priv->keys[index].key_len = key_len;
49 priv->keys[index].seq_len = seq_len;
50
51 if (key_len)
52 memcpy(priv->keys[index].key, key, key_len);
53 if (seq_len)
54 memcpy(priv->keys[index].seq, seq, seq_len);
55
56 switch (alg) {
57 case ORINOCO_ALG_TKIP:
58 priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
59 break;
60
61 case ORINOCO_ALG_WEP:
62 priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
63 WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
64 break;
65
66 case ORINOCO_ALG_NONE:
67 default:
68 priv->keys[index].cipher = 0;
69 break;
70 }
71
72 return 0;
73
74free_key:
75 kfree(priv->keys[index].key);
76 priv->keys[index].key = NULL;
77
78nomem:
79 priv->keys[index].key_len = 0;
80 priv->keys[index].seq_len = 0;
81 priv->keys[index].cipher = 0;
82
83 return -ENOMEM;
84}
85
25static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) 86static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
26{ 87{
27 struct orinoco_private *priv = ndev_priv(dev); 88 struct orinoco_private *priv = ndev_priv(dev);
@@ -180,7 +241,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
180 int setindex = priv->tx_key; 241 int setindex = priv->tx_key;
181 enum orinoco_alg encode_alg = priv->encode_alg; 242 enum orinoco_alg encode_alg = priv->encode_alg;
182 int restricted = priv->wep_restrict; 243 int restricted = priv->wep_restrict;
183 u16 xlen = 0;
184 int err = -EINPROGRESS; /* Call commit handler */ 244 int err = -EINPROGRESS; /* Call commit handler */
185 unsigned long flags; 245 unsigned long flags;
186 246
@@ -207,12 +267,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
207 if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) 267 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
208 index = priv->tx_key; 268 index = priv->tx_key;
209 269
210 /* Adjust key length to a supported value */
211 if (erq->length > SMALL_KEY_SIZE)
212 xlen = LARGE_KEY_SIZE;
213 else /* (erq->length > 0) */
214 xlen = SMALL_KEY_SIZE;
215
216 /* Switch on WEP if off */ 270 /* Switch on WEP if off */
217 if (encode_alg != ORINOCO_ALG_WEP) { 271 if (encode_alg != ORINOCO_ALG_WEP) {
218 setindex = index; 272 setindex = index;
@@ -229,7 +283,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
229 } 283 }
230 } else { 284 } else {
231 /* Set the index : Check that the key is valid */ 285 /* Set the index : Check that the key is valid */
232 if (priv->keys[index].len == 0) { 286 if (priv->keys[index].key_len == 0) {
233 err = -EINVAL; 287 err = -EINVAL;
234 goto out; 288 goto out;
235 } 289 }
@@ -245,10 +299,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
245 restricted = 1; 299 restricted = 1;
246 300
247 if (erq->pointer && erq->length > 0) { 301 if (erq->pointer && erq->length > 0) {
248 priv->keys[index].len = cpu_to_le16(xlen); 302 err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
249 memset(priv->keys[index].data, 0, 303 erq->length, NULL, 0);
250 sizeof(priv->keys[index].data));
251 memcpy(priv->keys[index].data, keybuf, erq->length);
252 } 304 }
253 priv->tx_key = setindex; 305 priv->tx_key = setindex;
254 306
@@ -277,7 +329,6 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
277{ 329{
278 struct orinoco_private *priv = ndev_priv(dev); 330 struct orinoco_private *priv = ndev_priv(dev);
279 int index = (erq->flags & IW_ENCODE_INDEX) - 1; 331 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
280 u16 xlen = 0;
281 unsigned long flags; 332 unsigned long flags;
282 333
283 if (!priv->has_wep) 334 if (!priv->has_wep)
@@ -299,11 +350,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
299 else 350 else
300 erq->flags |= IW_ENCODE_OPEN; 351 erq->flags |= IW_ENCODE_OPEN;
301 352
302 xlen = le16_to_cpu(priv->keys[index].len); 353 erq->length = priv->keys[index].key_len;
303 354
304 erq->length = xlen; 355 memcpy(keybuf, priv->keys[index].key, erq->length);
305
306 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
307 356
308 orinoco_unlock(priv, &flags); 357 orinoco_unlock(priv, &flags);
309 return 0; 358 return 0;
@@ -789,7 +838,6 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
789 int idx, alg = ext->alg, set_key = 1; 838 int idx, alg = ext->alg, set_key = 1;
790 unsigned long flags; 839 unsigned long flags;
791 int err = -EINVAL; 840 int err = -EINVAL;
792 u16 key_len;
793 841
794 if (orinoco_lock(priv, &flags) != 0) 842 if (orinoco_lock(priv, &flags) != 0)
795 return -EBUSY; 843 return -EBUSY;
@@ -822,24 +870,17 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
822 switch (alg) { 870 switch (alg) {
823 case IW_ENCODE_ALG_NONE: 871 case IW_ENCODE_ALG_NONE:
824 priv->encode_alg = ORINOCO_ALG_NONE; 872 priv->encode_alg = ORINOCO_ALG_NONE;
825 priv->keys[idx].len = 0; 873 err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
874 NULL, 0, NULL, 0);
826 break; 875 break;
827 876
828 case IW_ENCODE_ALG_WEP: 877 case IW_ENCODE_ALG_WEP:
829 if (ext->key_len > SMALL_KEY_SIZE) 878 if (ext->key_len <= 0)
830 key_len = LARGE_KEY_SIZE;
831 else if (ext->key_len > 0)
832 key_len = SMALL_KEY_SIZE;
833 else
834 goto out; 879 goto out;
835 880
836 priv->encode_alg = ORINOCO_ALG_WEP; 881 priv->encode_alg = ORINOCO_ALG_WEP;
837 priv->keys[idx].len = cpu_to_le16(key_len); 882 err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
838 883 ext->key, ext->key_len, NULL, 0);
839 key_len = min(ext->key_len, key_len);
840
841 memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
842 memcpy(priv->keys[idx].data, ext->key, key_len);
843 break; 884 break;
844 885
845 case IW_ENCODE_ALG_TKIP: 886 case IW_ENCODE_ALG_TKIP:
@@ -847,20 +888,21 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
847 u8 *tkip_iv = NULL; 888 u8 *tkip_iv = NULL;
848 889
849 if (!priv->has_wpa || 890 if (!priv->has_wpa ||
850 (ext->key_len > sizeof(priv->tkip_key[0]))) 891 (ext->key_len > sizeof(struct orinoco_tkip_key)))
851 goto out; 892 goto out;
852 893
853 priv->encode_alg = ORINOCO_ALG_TKIP; 894 priv->encode_alg = ORINOCO_ALG_TKIP;
854 memset(&priv->tkip_key[idx], 0,
855 sizeof(priv->tkip_key[idx]));
856 memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
857 895
858 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) 896 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
859 tkip_iv = &ext->rx_seq[0]; 897 tkip_iv = &ext->rx_seq[0];
860 898
899 err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
900 ext->key, ext->key_len, tkip_iv,
901 ORINOCO_SEQ_LEN);
902
861 err = __orinoco_hw_set_tkip_key(priv, idx, 903 err = __orinoco_hw_set_tkip_key(priv, idx,
862 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 904 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
863 (u8 *) &priv->tkip_key[idx], 905 priv->keys[idx].key,
864 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0); 906 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
865 if (err) 907 if (err)
866 printk(KERN_ERR "%s: Error %d setting TKIP key" 908 printk(KERN_ERR "%s: Error %d setting TKIP key"
@@ -918,16 +960,14 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
918 break; 960 break;
919 case ORINOCO_ALG_WEP: 961 case ORINOCO_ALG_WEP:
920 ext->alg = IW_ENCODE_ALG_WEP; 962 ext->alg = IW_ENCODE_ALG_WEP;
921 ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len), 963 ext->key_len = min(priv->keys[idx].key_len, max_key_len);
922 max_key_len); 964 memcpy(ext->key, priv->keys[idx].key, ext->key_len);
923 memcpy(ext->key, priv->keys[idx].data, ext->key_len);
924 encoding->flags |= IW_ENCODE_ENABLED; 965 encoding->flags |= IW_ENCODE_ENABLED;
925 break; 966 break;
926 case ORINOCO_ALG_TKIP: 967 case ORINOCO_ALG_TKIP:
927 ext->alg = IW_ENCODE_ALG_TKIP; 968 ext->alg = IW_ENCODE_ALG_TKIP;
928 ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key), 969 ext->key_len = min(priv->keys[idx].key_len, max_key_len);
929 max_key_len); 970 memcpy(ext->key, priv->keys[idx].key, ext->key_len);
930 memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
931 encoding->flags |= IW_ENCODE_ENABLED; 971 encoding->flags |= IW_ENCODE_ENABLED;
932 break; 972 break;
933 } 973 }