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: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
138c0c6882
commit
c038069352
@@ -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);
|
rc = readWepKeyRid(ai, &wkr, 0, 1);
|
||||||
}
|
if (rc != SUCCESS)
|
||||||
readWepKeyRid(ai, &wkr, 0, 1);
|
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 get_wep_tx_idx(struct airo_info *ai)
|
||||||
const char *key, u16 keylen, int perm, int lock )
|
{
|
||||||
|
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);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (keylen == 0) {
|
||||||
|
airo_print_err(ai->dev->name, "%s: key length to set was zero",
|
||||||
|
__func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&wkr, 0, sizeof(wkr));
|
memset(&wkr, 0, sizeof(wkr));
|
||||||
if (keylen == 0) {
|
|
||||||
// We are selecting which key to use
|
|
||||||
wkr.len = cpu_to_le16(sizeof(wkr));
|
|
||||||
wkr.kindex = cpu_to_le16(0xffff);
|
|
||||||
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.len = cpu_to_le16(sizeof(wkr));
|
||||||
wkr.kindex = cpu_to_le16(index);
|
wkr.kindex = cpu_to_le16(index);
|
||||||
wkr.klen = cpu_to_le16(keylen);
|
wkr.klen = cpu_to_le16(keylen);
|
||||||
memcpy(wkr.key, key, keylen);
|
memcpy(wkr.key, key, keylen);
|
||||||
memcpy(wkr.mac, macaddr, ETH_ALEN);
|
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 ) {
|
|||||||
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 ) {
|
|||||||
(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 ) {
|
|||||||
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 ) {
|
|||||||
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;
|
||||||
@@ -6288,6 +6341,7 @@ static int airo_set_encode(struct net_device *dev,
|
|||||||
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,
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
} 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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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);
|
||||||
dwrq->flags |= index + 1;
|
if (index < 0)
|
||||||
/* Copy the key to the user buffer */
|
index = 0;
|
||||||
dwrq->length = get_wep_key(local, index);
|
|
||||||
if (dwrq->length > 16) {
|
|
||||||
dwrq->length=0;
|
|
||||||
}
|
}
|
||||||
|
dwrq->flags |= index + 1;
|
||||||
|
|
||||||
|
/* Copy the key to the user buffer */
|
||||||
|
dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf));
|
||||||
|
memcpy(extra, buf, dwrq->length);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user