Commit c0380693 authored by Dan Williams's avatar Dan Williams Committed by John W. Linville

airo: clean up WEP key operations

get_wep_key() and set_wep_key() combind both get/set of the actual WEP
key and get/set of the transmit index into the same functions.  Split those
out so it's clearer what is going one where.  Add error checking to WEP
key hardware operations too.
Signed-off-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 138c0c68
...@@ -5172,55 +5172,98 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, ...@@ -5172,55 +5172,98 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
return rc; return rc;
} }
/* Returns the length of the key at the index. If index == 0xffff /* Returns the WEP key at the specified index, or -1 if that key does
* the index of the transmit key is returned. If the key doesn't exist, * not exist. The buffer is assumed to be at least 16 bytes in length.
* -1 will be returned.
*/ */
static int get_wep_key(struct airo_info *ai, u16 index) { static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen)
{
WepKeyRid wkr; WepKeyRid wkr;
int rc; int rc;
__le16 lastindex; __le16 lastindex;
rc = readWepKeyRid(ai, &wkr, 1, 1); rc = readWepKeyRid(ai, &wkr, 1, 1);
if (rc == SUCCESS) do { if (rc != SUCCESS)
return -1;
do {
lastindex = wkr.kindex; lastindex = wkr.kindex;
if (wkr.kindex == cpu_to_le16(index)) { if (le16_to_cpu(wkr.kindex) == index) {
if (index == 0xffff) { int klen = min_t(int, buflen, le16_to_cpu(wkr.klen));
return wkr.mac[0]; memcpy(buf, wkr.key, klen);
} return klen;
return le16_to_cpu(wkr.klen);
} }
readWepKeyRid(ai, &wkr, 0, 1); rc = readWepKeyRid(ai, &wkr, 0, 1);
if (rc != SUCCESS)
return -1;
} while (lastindex != wkr.kindex);
return -1;
}
static int get_wep_tx_idx(struct airo_info *ai)
{
WepKeyRid wkr;
int rc;
__le16 lastindex;
rc = readWepKeyRid(ai, &wkr, 1, 1);
if (rc != SUCCESS)
return -1;
do {
lastindex = wkr.kindex;
if (wkr.kindex == cpu_to_le16(0xffff))
return wkr.mac[0];
rc = readWepKeyRid(ai, &wkr, 0, 1);
if (rc != SUCCESS)
return -1;
} while (lastindex != wkr.kindex); } while (lastindex != wkr.kindex);
return -1; return -1;
} }
static int set_wep_key(struct airo_info *ai, u16 index, static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
const char *key, u16 keylen, int perm, int lock ) u16 keylen, int perm, int lock)
{ {
static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
WepKeyRid wkr; WepKeyRid wkr;
int rc;
memset(&wkr, 0, sizeof(wkr));
if (keylen == 0) { if (keylen == 0) {
// We are selecting which key to use airo_print_err(ai->dev->name, "%s: key length to set was zero",
wkr.len = cpu_to_le16(sizeof(wkr)); __func__);
wkr.kindex = cpu_to_le16(0xffff); return -1;
wkr.mac[0] = (char)index;
if (perm) ai->defindex = (char)index;
} else {
// We are actually setting the key
wkr.len = cpu_to_le16(sizeof(wkr));
wkr.kindex = cpu_to_le16(index);
wkr.klen = cpu_to_le16(keylen);
memcpy( wkr.key, key, keylen );
memcpy( wkr.mac, macaddr, ETH_ALEN );
} }
memset(&wkr, 0, sizeof(wkr));
wkr.len = cpu_to_le16(sizeof(wkr));
wkr.kindex = cpu_to_le16(index);
wkr.klen = cpu_to_le16(keylen);
memcpy(wkr.key, key, keylen);
memcpy(wkr.mac, macaddr, ETH_ALEN);
if (perm) disable_MAC(ai, lock); if (perm) disable_MAC(ai, lock);
writeWepKeyRid(ai, &wkr, perm, lock); rc = writeWepKeyRid(ai, &wkr, perm, lock);
if (perm) enable_MAC(ai, lock); if (perm) enable_MAC(ai, lock);
return 0; return rc;
}
static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock)
{
WepKeyRid wkr;
int rc;
memset(&wkr, 0, sizeof(wkr));
wkr.len = cpu_to_le16(sizeof(wkr));
wkr.kindex = cpu_to_le16(0xffff);
wkr.mac[0] = (char)index;
if (perm) {
ai->defindex = (char)index;
disable_MAC(ai, lock);
}
rc = writeWepKeyRid(ai, &wkr, perm, lock);
if (perm)
enable_MAC(ai, lock);
return rc;
} }
static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
...@@ -5228,7 +5271,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { ...@@ -5228,7 +5271,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
struct proc_dir_entry *dp = PDE(inode); struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data; struct net_device *dev = dp->data;
struct airo_info *ai = dev->ml_priv; struct airo_info *ai = dev->ml_priv;
int i; int i, rc;
char key[16]; char key[16];
u16 index = 0; u16 index = 0;
int j = 0; int j = 0;
...@@ -5242,7 +5285,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { ...@@ -5242,7 +5285,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
(data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
index = data->wbuffer[0] - '0'; index = data->wbuffer[0] - '0';
if (data->wbuffer[1] == '\n') { if (data->wbuffer[1] == '\n') {
set_wep_key(ai, index, NULL, 0, 1, 1); rc = set_wep_tx_idx(ai, index, 1, 1);
if (rc < 0) {
airo_print_err(ai->dev->name, "failed to set "
"WEP transmit index to %d: %d.",
index, rc);
}
return; return;
} }
j = 2; j = 2;
...@@ -5261,7 +5309,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { ...@@ -5261,7 +5309,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
break; break;
} }
} }
set_wep_key(ai, index, key, i/3, 1, 1);
rc = set_wep_key(ai, index, key, i/3, 1, 1);
if (rc < 0) {
airo_print_err(ai->dev->name, "failed to set WEP key at index "
"%d: %d.", index, rc);
}
} }
static int proc_wepkey_open( struct inode *inode, struct file *file ) static int proc_wepkey_open( struct inode *inode, struct file *file )
...@@ -5492,13 +5545,13 @@ static void timer_func( struct net_device *dev ) { ...@@ -5492,13 +5545,13 @@ static void timer_func( struct net_device *dev ) {
break; break;
case AUTH_SHAREDKEY: case AUTH_SHAREDKEY:
if (apriv->keyindex < auto_wep) { if (apriv->keyindex < auto_wep) {
set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0); set_wep_tx_idx(apriv, apriv->keyindex, 0, 0);
apriv->config.authType = AUTH_SHAREDKEY; apriv->config.authType = AUTH_SHAREDKEY;
apriv->keyindex++; apriv->keyindex++;
} else { } else {
/* Drop to ENCRYPT */ /* Drop to ENCRYPT */
apriv->keyindex = 0; apriv->keyindex = 0;
set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0); set_wep_tx_idx(apriv, apriv->defindex, 0, 0);
apriv->config.authType = AUTH_ENCRYPT; apriv->config.authType = AUTH_ENCRYPT;
} }
break; break;
...@@ -6286,8 +6339,9 @@ static int airo_set_encode(struct net_device *dev, ...@@ -6286,8 +6339,9 @@ static int airo_set_encode(struct net_device *dev,
char *extra) char *extra)
{ {
struct airo_info *local = dev->ml_priv; struct airo_info *local = dev->ml_priv;
int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 ); int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1);
__le16 currentAuthType = local->config.authType; __le16 currentAuthType = local->config.authType;
int rc = 0;
if (!local->wep_capable) if (!local->wep_capable)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -6303,13 +6357,17 @@ static int airo_set_encode(struct net_device *dev, ...@@ -6303,13 +6357,17 @@ static int airo_set_encode(struct net_device *dev,
if (dwrq->length > 0) { if (dwrq->length > 0) {
wep_key_t key; wep_key_t key;
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
int current_index = get_wep_key(local, 0xffff); int current_index;
/* Check the size of the key */ /* Check the size of the key */
if (dwrq->length > MAX_KEY_SIZE) { if (dwrq->length > MAX_KEY_SIZE) {
return -EINVAL; return -EINVAL;
} }
current_index = get_wep_tx_idx(local);
if (current_index < 0)
current_index = 0;
/* Check the index (none -> use current) */ /* Check the index (none -> use current) */
if (!valid_index(local, index)) if (!valid_index(local, index))
index = current_index; index = current_index;
...@@ -6330,7 +6388,13 @@ static int airo_set_encode(struct net_device *dev, ...@@ -6330,7 +6388,13 @@ static int airo_set_encode(struct net_device *dev,
/* Copy the key in the driver */ /* Copy the key in the driver */
memcpy(key.key, extra, dwrq->length); memcpy(key.key, extra, dwrq->length);
/* Send the key to the card */ /* Send the key to the card */
set_wep_key(local, index, key.key, key.len, perm, 1); rc = set_wep_key(local, index, key.key, key.len, perm, 1);
if (rc < 0) {
airo_print_err(local->dev->name, "failed to set"
" WEP key at index %d: %d.",
index, rc);
return rc;
}
} }
/* WE specify that if a valid key is set, encryption /* WE specify that if a valid key is set, encryption
* should be enabled (user may turn it off later) * should be enabled (user may turn it off later)
...@@ -6342,9 +6406,15 @@ static int airo_set_encode(struct net_device *dev, ...@@ -6342,9 +6406,15 @@ static int airo_set_encode(struct net_device *dev,
} else { } else {
/* Do we want to just set the transmit key index ? */ /* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if (valid_index(local, index)) if (valid_index(local, index)) {
set_wep_key(local, index, NULL, 0, perm, 1); rc = set_wep_tx_idx(local, index, perm, 1);
else { if (rc < 0) {
airo_print_err(local->dev->name, "failed to set"
" WEP transmit index to %d: %d.",
index, rc);
return rc;
}
} else {
/* Don't complain if only change the mode */ /* Don't complain if only change the mode */
if (!(dwrq->flags & IW_ENCODE_MODE)) if (!(dwrq->flags & IW_ENCODE_MODE))
return -EINVAL; return -EINVAL;
...@@ -6374,6 +6444,7 @@ static int airo_get_encode(struct net_device *dev, ...@@ -6374,6 +6444,7 @@ static int airo_get_encode(struct net_device *dev,
{ {
struct airo_info *local = dev->ml_priv; struct airo_info *local = dev->ml_priv;
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
u8 buf[16];
if (!local->wep_capable) if (!local->wep_capable)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -6398,14 +6469,17 @@ static int airo_get_encode(struct net_device *dev, ...@@ -6398,14 +6469,17 @@ static int airo_get_encode(struct net_device *dev,
memset(extra, 0, 16); memset(extra, 0, 16);
/* Which key do we want ? -1 -> tx index */ /* Which key do we want ? -1 -> tx index */
if (!valid_index(local, index)) if (!valid_index(local, index)) {
index = get_wep_key(local, 0xffff); index = get_wep_tx_idx(local);
if (index < 0)
index = 0;
}
dwrq->flags |= index + 1; dwrq->flags |= index + 1;
/* Copy the key to the user buffer */ /* Copy the key to the user buffer */
dwrq->length = get_wep_key(local, index); dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf));
if (dwrq->length > 16) { memcpy(extra, buf, dwrq->length);
dwrq->length=0;
}
return 0; return 0;
} }
...@@ -6423,7 +6497,7 @@ static int airo_set_encodeext(struct net_device *dev, ...@@ -6423,7 +6497,7 @@ static int airo_set_encodeext(struct net_device *dev,
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
__le16 currentAuthType = local->config.authType; __le16 currentAuthType = local->config.authType;
int idx, key_len, alg = ext->alg, set_key = 1; int idx, key_len, alg = ext->alg, set_key = 1, rc;
wep_key_t key; wep_key_t key;
if (!local->wep_capable) if (!local->wep_capable)
...@@ -6437,8 +6511,11 @@ static int airo_set_encodeext(struct net_device *dev, ...@@ -6437,8 +6511,11 @@ static int airo_set_encodeext(struct net_device *dev,
if (!valid_index(local, idx - 1)) if (!valid_index(local, idx - 1))
return -EINVAL; return -EINVAL;
idx--; idx--;
} else } else {
idx = get_wep_key(local, 0xffff); idx = get_wep_tx_idx(local);
if (idx < 0)
idx = 0;
}
if (encoding->flags & IW_ENCODE_DISABLED) if (encoding->flags & IW_ENCODE_DISABLED)
alg = IW_ENCODE_ALG_NONE; alg = IW_ENCODE_ALG_NONE;
...@@ -6447,7 +6524,13 @@ static int airo_set_encodeext(struct net_device *dev, ...@@ -6447,7 +6524,13 @@ static int airo_set_encodeext(struct net_device *dev,
/* Only set transmit key index here, actual /* Only set transmit key index here, actual
* key is set below if needed. * key is set below if needed.
*/ */
set_wep_key(local, idx, NULL, 0, perm, 1); rc = set_wep_tx_idx(local, idx, perm, 1);
if (rc < 0) {
airo_print_err(local->dev->name, "failed to set "
"WEP transmit index to %d: %d.",
idx, rc);
return rc;
}
set_key = ext->key_len > 0 ? 1 : 0; set_key = ext->key_len > 0 ? 1 : 0;
} }
...@@ -6473,7 +6556,12 @@ static int airo_set_encodeext(struct net_device *dev, ...@@ -6473,7 +6556,12 @@ static int airo_set_encodeext(struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
/* Send the key to the card */ /* Send the key to the card */
set_wep_key(local, idx, key.key, key.len, perm, 1); rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
if (rc < 0) {
airo_print_err(local->dev->name, "failed to set WEP key"
" at index %d: %d.", idx, rc);
return rc;
}
} }
/* Read the flags */ /* Read the flags */
...@@ -6504,6 +6592,7 @@ static int airo_get_encodeext(struct net_device *dev, ...@@ -6504,6 +6592,7 @@ static int airo_get_encodeext(struct net_device *dev,
struct iw_point *encoding = &wrqu->encoding; struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int idx, max_key_len; int idx, max_key_len;
u8 buf[16];
if (!local->wep_capable) if (!local->wep_capable)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -6519,8 +6608,11 @@ static int airo_get_encodeext(struct net_device *dev, ...@@ -6519,8 +6608,11 @@ static int airo_get_encodeext(struct net_device *dev,
if (!valid_index(local, idx - 1)) if (!valid_index(local, idx - 1))
return -EINVAL; return -EINVAL;
idx--; idx--;
} else } else {
idx = get_wep_key(local, 0xffff); idx = get_wep_tx_idx(local);
if (idx < 0)
idx = 0;
}
encoding->flags = idx + 1; encoding->flags = idx + 1;
memset(ext, 0, sizeof(*ext)); memset(ext, 0, sizeof(*ext));
...@@ -6543,10 +6635,8 @@ static int airo_get_encodeext(struct net_device *dev, ...@@ -6543,10 +6635,8 @@ static int airo_get_encodeext(struct net_device *dev,
memset(extra, 0, 16); memset(extra, 0, 16);
/* Copy the key to the user buffer */ /* Copy the key to the user buffer */
ext->key_len = get_wep_key(local, idx); ext->key_len = get_wep_key(local, idx, &buf[0], sizeof(buf));
if (ext->key_len > 16) { memcpy(extra, buf, ext->key_len);
ext->key_len=0;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment