diff options
author | Dan Williams <dcbw@redhat.com> | 2009-01-24 09:12:15 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:01:40 -0500 |
commit | c0380693520b1a1e4f756799a0edc379378b462a (patch) | |
tree | 256ee51b0af360abc35cbe0d6999fd8a572e39c9 | |
parent | 138c0c688262b7f4ed07cdc6d0592299c4f12998 (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>
-rw-r--r-- | drivers/net/wireless/airo.c | 202 |
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 | */ |
5179 | static int get_wep_key(struct airo_info *ai, u16 index) { | 5178 | static 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 | |||
5201 | static 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 | ||
5198 | static int set_wep_key(struct airo_info *ai, u16 index, | 5221 | static 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 | |||
5247 | static 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 | ||
5226 | static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { | 5269 | 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 | 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 | ||
5267 | static int proc_wepkey_open( struct inode *inode, struct file *file ) | 5320 | static 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 | } |