aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/airo.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-01-24 09:12:15 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:01:40 -0500
commitc0380693520b1a1e4f756799a0edc379378b462a (patch)
tree256ee51b0af360abc35cbe0d6999fd8a572e39c9 /drivers/net/wireless/airo.c
parent138c0c688262b7f4ed07cdc6d0592299c4f12998 (diff)
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>
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r--drivers/net/wireless/airo.c202
1 files changed, 146 insertions, 56 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index e4ca5f84d610..2306b1a3325c 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5172,55 +5172,98 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
5172 return rc; 5172 return rc;
5173} 5173}
5174 5174
5175/* Returns the length of the key at the index. If index == 0xffff 5175/* Returns the WEP key at the specified index, or -1 if that key does
5176 * the index of the transmit key is returned. If the key doesn't exist, 5176 * not exist. The buffer is assumed to be at least 16 bytes in length.
5177 * -1 will be returned.
5178 */ 5177 */
5179static int get_wep_key(struct airo_info *ai, u16 index) { 5178static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen)
5179{
5180 WepKeyRid wkr; 5180 WepKeyRid wkr;
5181 int rc; 5181 int rc;
5182 __le16 lastindex; 5182 __le16 lastindex;
5183 5183
5184 rc = readWepKeyRid(ai, &wkr, 1, 1); 5184 rc = readWepKeyRid(ai, &wkr, 1, 1);
5185 if (rc == SUCCESS) do { 5185 if (rc != SUCCESS)
5186 return -1;
5187 do {
5186 lastindex = wkr.kindex; 5188 lastindex = wkr.kindex;
5187 if (wkr.kindex == cpu_to_le16(index)) { 5189 if (le16_to_cpu(wkr.kindex) == index) {
5188 if (index == 0xffff) { 5190 int klen = min_t(int, buflen, le16_to_cpu(wkr.klen));
5189 return wkr.mac[0]; 5191 memcpy(buf, wkr.key, klen);
5190 } 5192 return klen;
5191 return le16_to_cpu(wkr.klen);
5192 } 5193 }
5193 readWepKeyRid(ai, &wkr, 0, 1); 5194 rc = readWepKeyRid(ai, &wkr, 0, 1);
5195 if (rc != SUCCESS)
5196 return -1;
5197 } while (lastindex != wkr.kindex);
5198 return -1;
5199}
5200
5201static int get_wep_tx_idx(struct airo_info *ai)
5202{
5203 WepKeyRid wkr;
5204 int rc;
5205 __le16 lastindex;
5206
5207 rc = readWepKeyRid(ai, &wkr, 1, 1);
5208 if (rc != SUCCESS)
5209 return -1;
5210 do {
5211 lastindex = wkr.kindex;
5212 if (wkr.kindex == cpu_to_le16(0xffff))
5213 return wkr.mac[0];
5214 rc = readWepKeyRid(ai, &wkr, 0, 1);
5215 if (rc != SUCCESS)
5216 return -1;
5194 } while (lastindex != wkr.kindex); 5217 } while (lastindex != wkr.kindex);
5195 return -1; 5218 return -1;
5196} 5219}
5197 5220
5198static int set_wep_key(struct airo_info *ai, u16 index, 5221static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
5199 const char *key, u16 keylen, int perm, int lock ) 5222 u16 keylen, int perm, int lock)
5200{ 5223{
5201 static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; 5224 static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
5202 WepKeyRid wkr; 5225 WepKeyRid wkr;
5226 int rc;
5203 5227
5204 memset(&wkr, 0, sizeof(wkr));
5205 if (keylen == 0) { 5228 if (keylen == 0) {
5206// We are selecting which key to use 5229 airo_print_err(ai->dev->name, "%s: key length to set was zero",
5207 wkr.len = cpu_to_le16(sizeof(wkr)); 5230 __func__);
5208 wkr.kindex = cpu_to_le16(0xffff); 5231 return -1;
5209 wkr.mac[0] = (char)index;
5210 if (perm) ai->defindex = (char)index;
5211 } else {
5212// We are actually setting the key
5213 wkr.len = cpu_to_le16(sizeof(wkr));
5214 wkr.kindex = cpu_to_le16(index);
5215 wkr.klen = cpu_to_le16(keylen);
5216 memcpy( wkr.key, key, keylen );
5217 memcpy( wkr.mac, macaddr, ETH_ALEN );
5218 } 5232 }
5219 5233
5234 memset(&wkr, 0, sizeof(wkr));
5235 wkr.len = cpu_to_le16(sizeof(wkr));
5236 wkr.kindex = cpu_to_le16(index);
5237 wkr.klen = cpu_to_le16(keylen);
5238 memcpy(wkr.key, key, keylen);
5239 memcpy(wkr.mac, macaddr, ETH_ALEN);
5240
5220 if (perm) disable_MAC(ai, lock); 5241 if (perm) disable_MAC(ai, lock);
5221 writeWepKeyRid(ai, &wkr, perm, lock); 5242 rc = writeWepKeyRid(ai, &wkr, perm, lock);
5222 if (perm) enable_MAC(ai, lock); 5243 if (perm) enable_MAC(ai, lock);
5223 return 0; 5244 return rc;
5245}
5246
5247static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock)
5248{
5249 WepKeyRid wkr;
5250 int rc;
5251
5252 memset(&wkr, 0, sizeof(wkr));
5253 wkr.len = cpu_to_le16(sizeof(wkr));
5254 wkr.kindex = cpu_to_le16(0xffff);
5255 wkr.mac[0] = (char)index;
5256
5257 if (perm) {
5258 ai->defindex = (char)index;
5259 disable_MAC(ai, lock);
5260 }
5261
5262 rc = writeWepKeyRid(ai, &wkr, perm, lock);
5263
5264 if (perm)
5265 enable_MAC(ai, lock);
5266 return rc;
5224} 5267}
5225 5268
5226static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { 5269static 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 struct proc_dir_entry *dp = PDE(inode); 5271 struct proc_dir_entry *dp = PDE(inode);
5229 struct net_device *dev = dp->data; 5272 struct net_device *dev = dp->data;
5230 struct airo_info *ai = dev->ml_priv; 5273 struct airo_info *ai = dev->ml_priv;
5231 int i; 5274 int i, rc;
5232 char key[16]; 5275 char key[16];
5233 u16 index = 0; 5276 u16 index = 0;
5234 int j = 0; 5277 int j = 0;
@@ -5242,7 +5285,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
5242 (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { 5285 (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
5243 index = data->wbuffer[0] - '0'; 5286 index = data->wbuffer[0] - '0';
5244 if (data->wbuffer[1] == '\n') { 5287 if (data->wbuffer[1] == '\n') {
5245 set_wep_key(ai, index, NULL, 0, 1, 1); 5288 rc = set_wep_tx_idx(ai, index, 1, 1);
5289 if (rc < 0) {
5290 airo_print_err(ai->dev->name, "failed to set "
5291 "WEP transmit index to %d: %d.",
5292 index, rc);
5293 }
5246 return; 5294 return;
5247 } 5295 }
5248 j = 2; 5296 j = 2;
@@ -5261,7 +5309,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
5261 break; 5309 break;
5262 } 5310 }
5263 } 5311 }
5264 set_wep_key(ai, index, key, i/3, 1, 1); 5312
5313 rc = set_wep_key(ai, index, key, i/3, 1, 1);
5314 if (rc < 0) {
5315 airo_print_err(ai->dev->name, "failed to set WEP key at index "
5316 "%d: %d.", index, rc);
5317 }
5265} 5318}
5266 5319
5267static int proc_wepkey_open( struct inode *inode, struct file *file ) 5320static int proc_wepkey_open( struct inode *inode, struct file *file )
@@ -5492,13 +5545,13 @@ static void timer_func( struct net_device *dev ) {
5492 break; 5545 break;
5493 case AUTH_SHAREDKEY: 5546 case AUTH_SHAREDKEY:
5494 if (apriv->keyindex < auto_wep) { 5547 if (apriv->keyindex < auto_wep) {
5495 set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0); 5548 set_wep_tx_idx(apriv, apriv->keyindex, 0, 0);
5496 apriv->config.authType = AUTH_SHAREDKEY; 5549 apriv->config.authType = AUTH_SHAREDKEY;
5497 apriv->keyindex++; 5550 apriv->keyindex++;
5498 } else { 5551 } else {
5499 /* Drop to ENCRYPT */ 5552 /* Drop to ENCRYPT */
5500 apriv->keyindex = 0; 5553 apriv->keyindex = 0;
5501 set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0); 5554 set_wep_tx_idx(apriv, apriv->defindex, 0, 0);
5502 apriv->config.authType = AUTH_ENCRYPT; 5555 apriv->config.authType = AUTH_ENCRYPT;
5503 } 5556 }
5504 break; 5557 break;
@@ -6286,8 +6339,9 @@ static int airo_set_encode(struct net_device *dev,
6286 char *extra) 6339 char *extra)
6287{ 6340{
6288 struct airo_info *local = dev->ml_priv; 6341 struct airo_info *local = dev->ml_priv;
6289 int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 ); 6342 int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1);
6290 __le16 currentAuthType = local->config.authType; 6343 __le16 currentAuthType = local->config.authType;
6344 int rc = 0;
6291 6345
6292 if (!local->wep_capable) 6346 if (!local->wep_capable)
6293 return -EOPNOTSUPP; 6347 return -EOPNOTSUPP;
@@ -6303,13 +6357,17 @@ static int airo_set_encode(struct net_device *dev,
6303 if (dwrq->length > 0) { 6357 if (dwrq->length > 0) {
6304 wep_key_t key; 6358 wep_key_t key;
6305 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; 6359 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6306 int current_index = get_wep_key(local, 0xffff); 6360 int current_index;
6307 6361
6308 /* Check the size of the key */ 6362 /* Check the size of the key */
6309 if (dwrq->length > MAX_KEY_SIZE) { 6363 if (dwrq->length > MAX_KEY_SIZE) {
6310 return -EINVAL; 6364 return -EINVAL;
6311 } 6365 }
6312 6366
6367 current_index = get_wep_tx_idx(local);
6368 if (current_index < 0)
6369 current_index = 0;
6370
6313 /* Check the index (none -> use current) */ 6371 /* Check the index (none -> use current) */
6314 if (!valid_index(local, index)) 6372 if (!valid_index(local, index))
6315 index = current_index; 6373 index = current_index;
@@ -6330,7 +6388,13 @@ static int airo_set_encode(struct net_device *dev,
6330 /* Copy the key in the driver */ 6388 /* Copy the key in the driver */
6331 memcpy(key.key, extra, dwrq->length); 6389 memcpy(key.key, extra, dwrq->length);
6332 /* Send the key to the card */ 6390 /* Send the key to the card */
6333 set_wep_key(local, index, key.key, key.len, perm, 1); 6391 rc = set_wep_key(local, index, key.key, key.len, perm, 1);
6392 if (rc < 0) {
6393 airo_print_err(local->dev->name, "failed to set"
6394 " WEP key at index %d: %d.",
6395 index, rc);
6396 return rc;
6397 }
6334 } 6398 }
6335 /* WE specify that if a valid key is set, encryption 6399 /* WE specify that if a valid key is set, encryption
6336 * should be enabled (user may turn it off later) 6400 * should be enabled (user may turn it off later)
@@ -6342,9 +6406,15 @@ static int airo_set_encode(struct net_device *dev,
6342 } else { 6406 } else {
6343 /* Do we want to just set the transmit key index ? */ 6407 /* Do we want to just set the transmit key index ? */
6344 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; 6408 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6345 if (valid_index(local, index)) 6409 if (valid_index(local, index)) {
6346 set_wep_key(local, index, NULL, 0, perm, 1); 6410 rc = set_wep_tx_idx(local, index, perm, 1);
6347 else { 6411 if (rc < 0) {
6412 airo_print_err(local->dev->name, "failed to set"
6413 " WEP transmit index to %d: %d.",
6414 index, rc);
6415 return rc;
6416 }
6417 } else {
6348 /* Don't complain if only change the mode */ 6418 /* Don't complain if only change the mode */
6349 if (!(dwrq->flags & IW_ENCODE_MODE)) 6419 if (!(dwrq->flags & IW_ENCODE_MODE))
6350 return -EINVAL; 6420 return -EINVAL;
@@ -6374,6 +6444,7 @@ static int airo_get_encode(struct net_device *dev,
6374{ 6444{
6375 struct airo_info *local = dev->ml_priv; 6445 struct airo_info *local = dev->ml_priv;
6376 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; 6446 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6447 u8 buf[16];
6377 6448
6378 if (!local->wep_capable) 6449 if (!local->wep_capable)
6379 return -EOPNOTSUPP; 6450 return -EOPNOTSUPP;
@@ -6398,14 +6469,17 @@ static int airo_get_encode(struct net_device *dev,
6398 memset(extra, 0, 16); 6469 memset(extra, 0, 16);
6399 6470
6400 /* Which key do we want ? -1 -> tx index */ 6471 /* Which key do we want ? -1 -> tx index */
6401 if (!valid_index(local, index)) 6472 if (!valid_index(local, index)) {
6402 index = get_wep_key(local, 0xffff); 6473 index = get_wep_tx_idx(local);
6474 if (index < 0)
6475 index = 0;
6476 }
6403 dwrq->flags |= index + 1; 6477 dwrq->flags |= index + 1;
6478
6404 /* Copy the key to the user buffer */ 6479 /* Copy the key to the user buffer */
6405 dwrq->length = get_wep_key(local, index); 6480 dwrq->length = get_wep_key(local, index, &buf[0], sizeof(buf));
6406 if (dwrq->length > 16) { 6481 memcpy(extra, buf, dwrq->length);
6407 dwrq->length=0; 6482
6408 }
6409 return 0; 6483 return 0;
6410} 6484}
6411 6485
@@ -6423,7 +6497,7 @@ static int airo_set_encodeext(struct net_device *dev,
6423 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 6497 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
6424 int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); 6498 int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
6425 __le16 currentAuthType = local->config.authType; 6499 __le16 currentAuthType = local->config.authType;
6426 int idx, key_len, alg = ext->alg, set_key = 1; 6500 int idx, key_len, alg = ext->alg, set_key = 1, rc;
6427 wep_key_t key; 6501 wep_key_t key;
6428 6502
6429 if (!local->wep_capable) 6503 if (!local->wep_capable)
@@ -6437,8 +6511,11 @@ static int airo_set_encodeext(struct net_device *dev,
6437 if (!valid_index(local, idx - 1)) 6511 if (!valid_index(local, idx - 1))
6438 return -EINVAL; 6512 return -EINVAL;
6439 idx--; 6513 idx--;
6440 } else 6514 } else {
6441 idx = get_wep_key(local, 0xffff); 6515 idx = get_wep_tx_idx(local);
6516 if (idx < 0)
6517 idx = 0;
6518 }
6442 6519
6443 if (encoding->flags & IW_ENCODE_DISABLED) 6520 if (encoding->flags & IW_ENCODE_DISABLED)
6444 alg = IW_ENCODE_ALG_NONE; 6521 alg = IW_ENCODE_ALG_NONE;
@@ -6447,7 +6524,13 @@ static int airo_set_encodeext(struct net_device *dev,
6447 /* Only set transmit key index here, actual 6524 /* Only set transmit key index here, actual
6448 * key is set below if needed. 6525 * key is set below if needed.
6449 */ 6526 */
6450 set_wep_key(local, idx, NULL, 0, perm, 1); 6527 rc = set_wep_tx_idx(local, idx, perm, 1);
6528 if (rc < 0) {
6529 airo_print_err(local->dev->name, "failed to set "
6530 "WEP transmit index to %d: %d.",
6531 idx, rc);
6532 return rc;
6533 }
6451 set_key = ext->key_len > 0 ? 1 : 0; 6534 set_key = ext->key_len > 0 ? 1 : 0;
6452 } 6535 }
6453 6536
@@ -6473,7 +6556,12 @@ static int airo_set_encodeext(struct net_device *dev,
6473 return -EINVAL; 6556 return -EINVAL;
6474 } 6557 }
6475 /* Send the key to the card */ 6558 /* Send the key to the card */
6476 set_wep_key(local, idx, key.key, key.len, perm, 1); 6559 rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
6560 if (rc < 0) {
6561 airo_print_err(local->dev->name, "failed to set WEP key"
6562 " at index %d: %d.", idx, rc);
6563 return rc;
6564 }
6477 } 6565 }
6478 6566
6479 /* Read the flags */ 6567 /* Read the flags */
@@ -6504,6 +6592,7 @@ static int airo_get_encodeext(struct net_device *dev,
6504 struct iw_point *encoding = &wrqu->encoding; 6592 struct iw_point *encoding = &wrqu->encoding;
6505 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 6593 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
6506 int idx, max_key_len; 6594 int idx, max_key_len;
6595 u8 buf[16];
6507 6596
6508 if (!local->wep_capable) 6597 if (!local->wep_capable)
6509 return -EOPNOTSUPP; 6598 return -EOPNOTSUPP;
@@ -6519,8 +6608,11 @@ static int airo_get_encodeext(struct net_device *dev,
6519 if (!valid_index(local, idx - 1)) 6608 if (!valid_index(local, idx - 1))
6520 return -EINVAL; 6609 return -EINVAL;
6521 idx--; 6610 idx--;
6522 } else 6611 } else {
6523 idx = get_wep_key(local, 0xffff); 6612 idx = get_wep_tx_idx(local);
6613 if (idx < 0)
6614 idx = 0;
6615 }
6524 6616
6525 encoding->flags = idx + 1; 6617 encoding->flags = idx + 1;
6526 memset(ext, 0, sizeof(*ext)); 6618 memset(ext, 0, sizeof(*ext));
@@ -6543,10 +6635,8 @@ static int airo_get_encodeext(struct net_device *dev,
6543 memset(extra, 0, 16); 6635 memset(extra, 0, 16);
6544 6636
6545 /* Copy the key to the user buffer */ 6637 /* Copy the key to the user buffer */
6546 ext->key_len = get_wep_key(local, idx); 6638 ext->key_len = get_wep_key(local, idx, &buf[0], sizeof(buf));
6547 if (ext->key_len > 16) { 6639 memcpy(extra, buf, ext->key_len);
6548 ext->key_len=0;
6549 }
6550 6640
6551 return 0; 6641 return 0;
6552} 6642}