summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/wext.c
diff options
context:
space:
mode:
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 @@
#define MAX_RID_LEN 1024
+/* Helper routine to record keys
+ * Do not call from interrupt context */
+static int orinoco_set_key(struct orinoco_private *priv, int index,
+ enum orinoco_alg alg, const u8 *key, int key_len,
+ const u8 *seq, int seq_len)
+{
+ kzfree(priv->keys[index].key);
+ kzfree(priv->keys[index].seq);
+
+ if (key_len) {
+ priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
+ if (!priv->keys[index].key)
+ goto nomem;
+ } else
+ priv->keys[index].key = NULL;
+
+ if (seq_len) {
+ priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
+ if (!priv->keys[index].seq)
+ goto free_key;
+ } else
+ priv->keys[index].seq = NULL;
+
+ priv->keys[index].key_len = key_len;
+ priv->keys[index].seq_len = seq_len;
+
+ if (key_len)
+ memcpy(priv->keys[index].key, key, key_len);
+ if (seq_len)
+ memcpy(priv->keys[index].seq, seq, seq_len);
+
+ switch (alg) {
+ case ORINOCO_ALG_TKIP:
+ priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
+ break;
+
+ case ORINOCO_ALG_WEP:
+ priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
+ WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
+ break;
+
+ case ORINOCO_ALG_NONE:
+ default:
+ priv->keys[index].cipher = 0;
+ break;
+ }
+
+ return 0;
+
+free_key:
+ kfree(priv->keys[index].key);
+ priv->keys[index].key = NULL;
+
+nomem:
+ priv->keys[index].key_len = 0;
+ priv->keys[index].seq_len = 0;
+ priv->keys[index].cipher = 0;
+
+ return -ENOMEM;
+}
+
static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
{
struct orinoco_private *priv = ndev_priv(dev);
@@ -180,7 +241,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
int setindex = priv->tx_key;
enum orinoco_alg encode_alg = priv->encode_alg;
int restricted = priv->wep_restrict;
- u16 xlen = 0;
int err = -EINPROGRESS; /* Call commit handler */
unsigned long flags;
@@ -207,12 +267,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
index = priv->tx_key;
- /* Adjust key length to a supported value */
- if (erq->length > SMALL_KEY_SIZE)
- xlen = LARGE_KEY_SIZE;
- else /* (erq->length > 0) */
- xlen = SMALL_KEY_SIZE;
-
/* Switch on WEP if off */
if (encode_alg != ORINOCO_ALG_WEP) {
setindex = index;
@@ -229,7 +283,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
}
} else {
/* Set the index : Check that the key is valid */
- if (priv->keys[index].len == 0) {
+ if (priv->keys[index].key_len == 0) {
err = -EINVAL;
goto out;
}
@@ -245,10 +299,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
restricted = 1;
if (erq->pointer && erq->length > 0) {
- priv->keys[index].len = cpu_to_le16(xlen);
- memset(priv->keys[index].data, 0,
- sizeof(priv->keys[index].data));
- memcpy(priv->keys[index].data, keybuf, erq->length);
+ err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
+ erq->length, NULL, 0);
}
priv->tx_key = setindex;
@@ -277,7 +329,6 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
{
struct orinoco_private *priv = ndev_priv(dev);
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
- u16 xlen = 0;
unsigned long flags;
if (!priv->has_wep)
@@ -299,11 +350,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
else
erq->flags |= IW_ENCODE_OPEN;
- xlen = le16_to_cpu(priv->keys[index].len);
+ erq->length = priv->keys[index].key_len;
- erq->length = xlen;
-
- memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
+ memcpy(keybuf, priv->keys[index].key, erq->length);
orinoco_unlock(priv, &flags);
return 0;
@@ -789,7 +838,6 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
int idx, alg = ext->alg, set_key = 1;
unsigned long flags;
int err = -EINVAL;
- u16 key_len;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
@@ -822,24 +870,17 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
switch (alg) {
case IW_ENCODE_ALG_NONE:
priv->encode_alg = ORINOCO_ALG_NONE;
- priv->keys[idx].len = 0;
+ err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
+ NULL, 0, NULL, 0);
break;
case IW_ENCODE_ALG_WEP:
- if (ext->key_len > SMALL_KEY_SIZE)
- key_len = LARGE_KEY_SIZE;
- else if (ext->key_len > 0)
- key_len = SMALL_KEY_SIZE;
- else
+ if (ext->key_len <= 0)
goto out;
priv->encode_alg = ORINOCO_ALG_WEP;
- priv->keys[idx].len = cpu_to_le16(key_len);
-
- key_len = min(ext->key_len, key_len);
-
- memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
- memcpy(priv->keys[idx].data, ext->key, key_len);
+ err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
+ ext->key, ext->key_len, NULL, 0);
break;
case IW_ENCODE_ALG_TKIP:
@@ -847,20 +888,21 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
u8 *tkip_iv = NULL;
if (!priv->has_wpa ||
- (ext->key_len > sizeof(priv->tkip_key[0])))
+ (ext->key_len > sizeof(struct orinoco_tkip_key)))
goto out;
priv->encode_alg = ORINOCO_ALG_TKIP;
- memset(&priv->tkip_key[idx], 0,
- sizeof(priv->tkip_key[idx]));
- memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
tkip_iv = &ext->rx_seq[0];
+ err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
+ ext->key, ext->key_len, tkip_iv,
+ ORINOCO_SEQ_LEN);
+
err = __orinoco_hw_set_tkip_key(priv, idx,
ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
- (u8 *) &priv->tkip_key[idx],
+ priv->keys[idx].key,
tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
if (err)
printk(KERN_ERR "%s: Error %d setting TKIP key"
@@ -918,16 +960,14 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
break;
case ORINOCO_ALG_WEP:
ext->alg = IW_ENCODE_ALG_WEP;
- ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
- max_key_len);
- memcpy(ext->key, priv->keys[idx].data, ext->key_len);
+ ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+ memcpy(ext->key, priv->keys[idx].key, ext->key_len);
encoding->flags |= IW_ENCODE_ENABLED;
break;
case ORINOCO_ALG_TKIP:
ext->alg = IW_ENCODE_ALG_TKIP;
- ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
- max_key_len);
- memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
+ ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+ memcpy(ext->key, priv->keys[idx].key, ext->key_len);
encoding->flags |= IW_ENCODE_ENABLED;
break;
}
OpenPOWER on IntegriCloud