diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2007-12-20 17:18:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:09:02 -0500 |
commit | 56d81bd3c76f3ac917a560c662a696aa5e29b980 (patch) | |
tree | 5ee5c7ac9268ff4434d857131597169957a18e3f /drivers/net/wireless/airo.c | |
parent | a23ace5f226aea6c8ba04794720502b1aad1dd92 (diff) |
airo: sanitize handling of CapabilityRid
Don't byteswap any fields, annotate. That has caught a bug,
BTW - will be handled in the next patch.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r-- | drivers/net/wireless/airo.c | 132 |
1 files changed, 69 insertions, 63 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 9b0714cea75e..e139a18c6acd 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -718,32 +718,32 @@ typedef struct { | |||
718 | } APListRid; | 718 | } APListRid; |
719 | 719 | ||
720 | typedef struct { | 720 | typedef struct { |
721 | u16 len; | 721 | __le16 len; |
722 | char oui[3]; | 722 | char oui[3]; |
723 | char zero; | 723 | char zero; |
724 | u16 prodNum; | 724 | __le16 prodNum; |
725 | char manName[32]; | 725 | char manName[32]; |
726 | char prodName[16]; | 726 | char prodName[16]; |
727 | char prodVer[8]; | 727 | char prodVer[8]; |
728 | char factoryAddr[ETH_ALEN]; | 728 | char factoryAddr[ETH_ALEN]; |
729 | char aironetAddr[ETH_ALEN]; | 729 | char aironetAddr[ETH_ALEN]; |
730 | u16 radioType; | 730 | __le16 radioType; |
731 | u16 country; | 731 | __le16 country; |
732 | char callid[ETH_ALEN]; | 732 | char callid[ETH_ALEN]; |
733 | char supportedRates[8]; | 733 | char supportedRates[8]; |
734 | char rxDiversity; | 734 | char rxDiversity; |
735 | char txDiversity; | 735 | char txDiversity; |
736 | u16 txPowerLevels[8]; | 736 | __le16 txPowerLevels[8]; |
737 | u16 hardVer; | 737 | __le16 hardVer; |
738 | u16 hardCap; | 738 | __le16 hardCap; |
739 | u16 tempRange; | 739 | __le16 tempRange; |
740 | u16 softVer; | 740 | __le16 softVer; |
741 | u16 softSubVer; | 741 | __le16 softSubVer; |
742 | u16 interfaceVer; | 742 | __le16 interfaceVer; |
743 | u16 softCap; | 743 | __le16 softCap; |
744 | u16 bootBlockVer; | 744 | __le16 bootBlockVer; |
745 | u16 requiredHard; | 745 | __le16 requiredHard; |
746 | u16 extSoftCap; | 746 | __le16 extSoftCap; |
747 | } CapabilityRid; | 747 | } CapabilityRid; |
748 | 748 | ||
749 | 749 | ||
@@ -1877,17 +1877,10 @@ static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) { | |||
1877 | rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); | 1877 | rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); |
1878 | return rc; | 1878 | return rc; |
1879 | } | 1879 | } |
1880 | static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) { | ||
1881 | int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock); | ||
1882 | u16 *s; | ||
1883 | 1880 | ||
1884 | capr->len = le16_to_cpu(capr->len); | 1881 | static int readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock) |
1885 | capr->prodNum = le16_to_cpu(capr->prodNum); | 1882 | { |
1886 | capr->radioType = le16_to_cpu(capr->radioType); | 1883 | return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock); |
1887 | capr->country = le16_to_cpu(capr->country); | ||
1888 | for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++) | ||
1889 | *s = le16_to_cpu(*s); | ||
1890 | return rc; | ||
1891 | } | 1884 | } |
1892 | 1885 | ||
1893 | static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) | 1886 | static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) |
@@ -2773,8 +2766,9 @@ static int airo_test_wpa_capable(struct airo_info *ai) | |||
2773 | if (status != SUCCESS) return 0; | 2766 | if (status != SUCCESS) return 0; |
2774 | 2767 | ||
2775 | /* Only firmware versions 5.30.17 or better can do WPA */ | 2768 | /* Only firmware versions 5.30.17 or better can do WPA */ |
2776 | if ((cap_rid.softVer > 0x530) | 2769 | if (le16_to_cpu(cap_rid.softVer) > 0x530 |
2777 | || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { | 2770 | || (le16_to_cpu(cap_rid.softVer) == 0x530 |
2771 | && le16_to_cpu(cap_rid.softSubVer) >= 17)) { | ||
2778 | airo_print_info("", "WPA is supported."); | 2772 | airo_print_info("", "WPA is supported."); |
2779 | return 1; | 2773 | return 1; |
2780 | } | 2774 | } |
@@ -3809,7 +3803,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) | |||
3809 | else { | 3803 | else { |
3810 | kfree(ai->rssi); | 3804 | kfree(ai->rssi); |
3811 | ai->rssi = NULL; | 3805 | ai->rssi = NULL; |
3812 | if (cap_rid.softCap & 8) | 3806 | if (cap_rid.softCap & cpu_to_le16(8)) |
3813 | ai->config.rmode |= RXMODE_NORMALIZED_RSSI; | 3807 | ai->config.rmode |= RXMODE_NORMALIZED_RSSI; |
3814 | else | 3808 | else |
3815 | airo_print_warn(ai->dev->name, "unknown received signal " | 3809 | airo_print_warn(ai->dev->name, "unknown received signal " |
@@ -3819,9 +3813,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) | |||
3819 | ai->config.authType = AUTH_OPEN; | 3813 | ai->config.authType = AUTH_OPEN; |
3820 | ai->config.modulation = MOD_CCK; | 3814 | ai->config.modulation = MOD_CCK; |
3821 | 3815 | ||
3822 | if ((cap_rid.len>=sizeof(cap_rid)) && | 3816 | if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) && |
3823 | (cap_rid.extSoftCap & cpu_to_le16(1)) && | 3817 | (cap_rid.extSoftCap & cpu_to_le16(1)) && |
3824 | (micsetup(ai) == SUCCESS)) { | 3818 | micsetup(ai) == SUCCESS) { |
3825 | ai->config.opmode |= MODE_MIC; | 3819 | ai->config.opmode |= MODE_MIC; |
3826 | set_bit(FLAG_MIC_CAPABLE, &ai->flags); | 3820 | set_bit(FLAG_MIC_CAPABLE, &ai->flags); |
3827 | } | 3821 | } |
@@ -4717,12 +4711,12 @@ static int proc_status_open( struct inode *inode, struct file *file ) { | |||
4717 | cap_rid.prodName, | 4711 | cap_rid.prodName, |
4718 | cap_rid.manName, | 4712 | cap_rid.manName, |
4719 | cap_rid.prodVer, | 4713 | cap_rid.prodVer, |
4720 | cap_rid.radioType, | 4714 | le16_to_cpu(cap_rid.radioType), |
4721 | cap_rid.country, | 4715 | le16_to_cpu(cap_rid.country), |
4722 | cap_rid.hardVer, | 4716 | le16_to_cpu(cap_rid.hardVer), |
4723 | (int)cap_rid.softVer, | 4717 | le16_to_cpu(cap_rid.softVer), |
4724 | (int)cap_rid.softSubVer, | 4718 | le16_to_cpu(cap_rid.softSubVer), |
4725 | (int)cap_rid.bootBlockVer ); | 4719 | le16_to_cpu(cap_rid.bootBlockVer)); |
4726 | data->readlen = strlen( data->rbuffer ); | 4720 | data->readlen = strlen( data->rbuffer ); |
4727 | return 0; | 4721 | return 0; |
4728 | } | 4722 | } |
@@ -5734,20 +5728,24 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) | |||
5734 | { | 5728 | { |
5735 | int quality = 0; | 5729 | int quality = 0; |
5736 | 5730 | ||
5737 | if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) { | 5731 | if ((status_rid->mode & 0x3f) != 0x3f) |
5738 | if (memcmp(cap_rid->prodName, "350", 3)) | 5732 | return 0; |
5739 | if (status_rid->signalQuality > 0x20) | 5733 | |
5740 | quality = 0; | 5734 | if (!(cap_rid->hardCap & cpu_to_le16(8))) |
5741 | else | 5735 | return 0; |
5742 | quality = 0x20 - status_rid->signalQuality; | 5736 | |
5737 | if (memcmp(cap_rid->prodName, "350", 3)) | ||
5738 | if (status_rid->signalQuality > 0x20) | ||
5739 | quality = 0; | ||
5743 | else | 5740 | else |
5744 | if (status_rid->signalQuality > 0xb0) | 5741 | quality = 0x20 - status_rid->signalQuality; |
5745 | quality = 0; | 5742 | else |
5746 | else if (status_rid->signalQuality < 0x10) | 5743 | if (status_rid->signalQuality > 0xb0) |
5747 | quality = 0xa0; | 5744 | quality = 0; |
5748 | else | 5745 | else if (status_rid->signalQuality < 0x10) |
5749 | quality = 0xb0 - status_rid->signalQuality; | 5746 | quality = 0xa0; |
5750 | } | 5747 | else |
5748 | quality = 0xb0 - status_rid->signalQuality; | ||
5751 | return quality; | 5749 | return quality; |
5752 | } | 5750 | } |
5753 | 5751 | ||
@@ -6289,6 +6287,13 @@ static int airo_get_mode(struct net_device *dev, | |||
6289 | return 0; | 6287 | return 0; |
6290 | } | 6288 | } |
6291 | 6289 | ||
6290 | static inline int valid_index(CapabilityRid *p, int index) | ||
6291 | { | ||
6292 | if (index < 0) | ||
6293 | return 0; | ||
6294 | return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1); | ||
6295 | } | ||
6296 | |||
6292 | /*------------------------------------------------------------------*/ | 6297 | /*------------------------------------------------------------------*/ |
6293 | /* | 6298 | /* |
6294 | * Wireless Handler : set Encryption Key | 6299 | * Wireless Handler : set Encryption Key |
@@ -6306,7 +6311,7 @@ static int airo_set_encode(struct net_device *dev, | |||
6306 | /* Is WEP supported ? */ | 6311 | /* Is WEP supported ? */ |
6307 | readCapabilityRid(local, &cap_rid, 1); | 6312 | readCapabilityRid(local, &cap_rid, 1); |
6308 | /* Older firmware doesn't support this... | 6313 | /* Older firmware doesn't support this... |
6309 | if(!(cap_rid.softCap & 2)) { | 6314 | if(!(cap_rid.softCap & cpu_to_le16(2))) { |
6310 | return -EOPNOTSUPP; | 6315 | return -EOPNOTSUPP; |
6311 | } */ | 6316 | } */ |
6312 | readConfigRid(local, 1); | 6317 | readConfigRid(local, 1); |
@@ -6326,7 +6331,7 @@ static int airo_set_encode(struct net_device *dev, | |||
6326 | return -EINVAL; | 6331 | return -EINVAL; |
6327 | } | 6332 | } |
6328 | /* Check the index (none -> use current) */ | 6333 | /* Check the index (none -> use current) */ |
6329 | if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4:1))) | 6334 | if (!valid_index(&cap_rid, index)) |
6330 | index = current_index; | 6335 | index = current_index; |
6331 | /* Set the length */ | 6336 | /* Set the length */ |
6332 | if (dwrq->length > MIN_KEY_SIZE) | 6337 | if (dwrq->length > MIN_KEY_SIZE) |
@@ -6356,7 +6361,7 @@ static int airo_set_encode(struct net_device *dev, | |||
6356 | } else { | 6361 | } else { |
6357 | /* Do we want to just set the transmit key index ? */ | 6362 | /* Do we want to just set the transmit key index ? */ |
6358 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 6363 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
6359 | if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) { | 6364 | if (valid_index(&cap_rid, index)) { |
6360 | set_wep_key(local, index, NULL, 0, perm, 1); | 6365 | set_wep_key(local, index, NULL, 0, perm, 1); |
6361 | } else | 6366 | } else |
6362 | /* Don't complain if only change the mode */ | 6367 | /* Don't complain if only change the mode */ |
@@ -6391,7 +6396,7 @@ static int airo_get_encode(struct net_device *dev, | |||
6391 | 6396 | ||
6392 | /* Is it supported ? */ | 6397 | /* Is it supported ? */ |
6393 | readCapabilityRid(local, &cap_rid, 1); | 6398 | readCapabilityRid(local, &cap_rid, 1); |
6394 | if(!(cap_rid.softCap & 2)) { | 6399 | if(!(cap_rid.softCap & cpu_to_le16(2))) { |
6395 | return -EOPNOTSUPP; | 6400 | return -EOPNOTSUPP; |
6396 | } | 6401 | } |
6397 | readConfigRid(local, 1); | 6402 | readConfigRid(local, 1); |
@@ -6413,7 +6418,7 @@ static int airo_get_encode(struct net_device *dev, | |||
6413 | memset(extra, 0, 16); | 6418 | memset(extra, 0, 16); |
6414 | 6419 | ||
6415 | /* Which key do we want ? -1 -> tx index */ | 6420 | /* Which key do we want ? -1 -> tx index */ |
6416 | if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4 : 1))) | 6421 | if (!valid_index(&cap_rid, index)) |
6417 | index = get_wep_key(local, 0xffff); | 6422 | index = get_wep_key(local, 0xffff); |
6418 | dwrq->flags |= index + 1; | 6423 | dwrq->flags |= index + 1; |
6419 | /* Copy the key to the user buffer */ | 6424 | /* Copy the key to the user buffer */ |
@@ -6445,7 +6450,7 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6445 | /* Is WEP supported ? */ | 6450 | /* Is WEP supported ? */ |
6446 | readCapabilityRid(local, &cap_rid, 1); | 6451 | readCapabilityRid(local, &cap_rid, 1); |
6447 | /* Older firmware doesn't support this... | 6452 | /* Older firmware doesn't support this... |
6448 | if(!(cap_rid.softCap & 2)) { | 6453 | if(!(cap_rid.softCap & cpu_to_le16(2))) { |
6449 | return -EOPNOTSUPP; | 6454 | return -EOPNOTSUPP; |
6450 | } */ | 6455 | } */ |
6451 | readConfigRid(local, 1); | 6456 | readConfigRid(local, 1); |
@@ -6453,7 +6458,7 @@ static int airo_set_encodeext(struct net_device *dev, | |||
6453 | /* Determine and validate the key index */ | 6458 | /* Determine and validate the key index */ |
6454 | idx = encoding->flags & IW_ENCODE_INDEX; | 6459 | idx = encoding->flags & IW_ENCODE_INDEX; |
6455 | if (idx) { | 6460 | if (idx) { |
6456 | if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) | 6461 | if (!valid_index(&cap_rid, idx - 1)) |
6457 | return -EINVAL; | 6462 | return -EINVAL; |
6458 | idx--; | 6463 | idx--; |
6459 | } else | 6464 | } else |
@@ -6527,7 +6532,7 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6527 | 6532 | ||
6528 | /* Is it supported ? */ | 6533 | /* Is it supported ? */ |
6529 | readCapabilityRid(local, &cap_rid, 1); | 6534 | readCapabilityRid(local, &cap_rid, 1); |
6530 | if(!(cap_rid.softCap & 2)) { | 6535 | if(!(cap_rid.softCap & cpu_to_le16(2))) { |
6531 | return -EOPNOTSUPP; | 6536 | return -EOPNOTSUPP; |
6532 | } | 6537 | } |
6533 | readConfigRid(local, 1); | 6538 | readConfigRid(local, 1); |
@@ -6538,7 +6543,7 @@ static int airo_get_encodeext(struct net_device *dev, | |||
6538 | 6543 | ||
6539 | idx = encoding->flags & IW_ENCODE_INDEX; | 6544 | idx = encoding->flags & IW_ENCODE_INDEX; |
6540 | if (idx) { | 6545 | if (idx) { |
6541 | if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) | 6546 | if (!valid_index(&cap_rid, idx - 1)) |
6542 | return -EINVAL; | 6547 | return -EINVAL; |
6543 | idx--; | 6548 | idx--; |
6544 | } else | 6549 | } else |
@@ -6716,7 +6721,7 @@ static int airo_set_txpow(struct net_device *dev, | |||
6716 | } | 6721 | } |
6717 | clear_bit (FLAG_RADIO_OFF, &local->flags); | 6722 | clear_bit (FLAG_RADIO_OFF, &local->flags); |
6718 | for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) | 6723 | for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) |
6719 | if ((vwrq->value==cap_rid.txPowerLevels[i])) { | 6724 | if (vwrq->value == le16_to_cpu(cap_rid.txPowerLevels[i])) { |
6720 | readConfigRid(local, 1); | 6725 | readConfigRid(local, 1); |
6721 | local->config.txPower = vwrq->value; | 6726 | local->config.txPower = vwrq->value; |
6722 | set_bit (FLAG_COMMIT, &local->flags); | 6727 | set_bit (FLAG_COMMIT, &local->flags); |
@@ -6888,16 +6893,17 @@ static int airo_get_range(struct net_device *dev, | |||
6888 | range->min_frag = 256; | 6893 | range->min_frag = 256; |
6889 | range->max_frag = AIRO_DEF_MTU; | 6894 | range->max_frag = AIRO_DEF_MTU; |
6890 | 6895 | ||
6891 | if(cap_rid.softCap & 2) { | 6896 | if(cap_rid.softCap & cpu_to_le16(2)) { |
6892 | // WEP: RC4 40 bits | 6897 | // WEP: RC4 40 bits |
6893 | range->encoding_size[0] = 5; | 6898 | range->encoding_size[0] = 5; |
6894 | // RC4 ~128 bits | 6899 | // RC4 ~128 bits |
6895 | if (cap_rid.softCap & 0x100) { | 6900 | if (cap_rid.softCap & cpu_to_le16(0x100)) { |
6896 | range->encoding_size[1] = 13; | 6901 | range->encoding_size[1] = 13; |
6897 | range->num_encoding_sizes = 2; | 6902 | range->num_encoding_sizes = 2; |
6898 | } else | 6903 | } else |
6899 | range->num_encoding_sizes = 1; | 6904 | range->num_encoding_sizes = 1; |
6900 | range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1; | 6905 | range->max_encoding_tokens = |
6906 | cap_rid.softCap & cpu_to_le16(0x80) ? 4 : 1; | ||
6901 | } else { | 6907 | } else { |
6902 | range->num_encoding_sizes = 0; | 6908 | range->num_encoding_sizes = 0; |
6903 | range->max_encoding_tokens = 0; | 6909 | range->max_encoding_tokens = 0; |
@@ -6912,7 +6918,7 @@ static int airo_get_range(struct net_device *dev, | |||
6912 | 6918 | ||
6913 | /* Transmit Power - values are in mW */ | 6919 | /* Transmit Power - values are in mW */ |
6914 | for(i = 0 ; i < 8 ; i++) { | 6920 | for(i = 0 ; i < 8 ; i++) { |
6915 | range->txpower[i] = cap_rid.txPowerLevels[i]; | 6921 | range->txpower[i] = le16_to_cpu(cap_rid.txPowerLevels[i]); |
6916 | if(range->txpower[i] == 0) | 6922 | if(range->txpower[i] == 0) |
6917 | break; | 6923 | break; |
6918 | } | 6924 | } |