diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2007-12-20 22:58:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:09:04 -0500 |
commit | 329e2c0067d5a2da88aa844bf57b2aaba9fceb2f (patch) | |
tree | 1830ac50a1e9ca708f20ba658de8d5b75606c794 | |
parent | a749716ecc85743f04f7117e3b373266b63edf7e (diff) |
airo: sanitize handling of StatusRid
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/airo.c | 132 |
1 files changed, 67 insertions, 65 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 306a1d1c1c22..f4a32a323642 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -648,30 +648,30 @@ typedef struct { | |||
648 | } ConfigRid; | 648 | } ConfigRid; |
649 | 649 | ||
650 | typedef struct { | 650 | typedef struct { |
651 | u16 len; | 651 | __le16 len; |
652 | u8 mac[ETH_ALEN]; | 652 | u8 mac[ETH_ALEN]; |
653 | u16 mode; | 653 | __le16 mode; |
654 | u16 errorCode; | 654 | __le16 errorCode; |
655 | u16 sigQuality; | 655 | __le16 sigQuality; |
656 | u16 SSIDlen; | 656 | __le16 SSIDlen; |
657 | char SSID[32]; | 657 | char SSID[32]; |
658 | char apName[16]; | 658 | char apName[16]; |
659 | u8 bssid[4][ETH_ALEN]; | 659 | u8 bssid[4][ETH_ALEN]; |
660 | u16 beaconPeriod; | 660 | __le16 beaconPeriod; |
661 | u16 dimPeriod; | 661 | __le16 dimPeriod; |
662 | u16 atimDuration; | 662 | __le16 atimDuration; |
663 | u16 hopPeriod; | 663 | __le16 hopPeriod; |
664 | u16 channelSet; | 664 | __le16 channelSet; |
665 | u16 channel; | 665 | __le16 channel; |
666 | u16 hopsToBackbone; | 666 | __le16 hopsToBackbone; |
667 | u16 apTotalLoad; | 667 | __le16 apTotalLoad; |
668 | u16 generatedLoad; | 668 | __le16 generatedLoad; |
669 | u16 accumulatedArl; | 669 | __le16 accumulatedArl; |
670 | u16 signalQuality; | 670 | __le16 signalQuality; |
671 | u16 currentXmitRate; | 671 | __le16 currentXmitRate; |
672 | u16 apDevExtensions; | 672 | __le16 apDevExtensions; |
673 | u16 normalizedSignalStrength; | 673 | __le16 normalizedSignalStrength; |
674 | u16 shortPreamble; | 674 | __le16 shortPreamble; |
675 | u8 apIP[4]; | 675 | u8 apIP[4]; |
676 | u8 noisePercent; /* Noise percent in last second */ | 676 | u8 noisePercent; /* Noise percent in last second */ |
677 | u8 noisedBm; /* Noise dBm in last second */ | 677 | u8 noisedBm; /* Noise dBm in last second */ |
@@ -679,9 +679,9 @@ typedef struct { | |||
679 | u8 noiseAvedBm; /* Noise dBm in last minute */ | 679 | u8 noiseAvedBm; /* Noise dBm in last minute */ |
680 | u8 noiseMaxPercent; /* Highest noise percent in last minute */ | 680 | u8 noiseMaxPercent; /* Highest noise percent in last minute */ |
681 | u8 noiseMaxdBm; /* Highest noise dbm in last minute */ | 681 | u8 noiseMaxdBm; /* Highest noise dbm in last minute */ |
682 | u16 load; | 682 | __le16 load; |
683 | u8 carrier[4]; | 683 | u8 carrier[4]; |
684 | u16 assocStatus; | 684 | __le16 assocStatus; |
685 | #define STAT_NOPACKETS 0 | 685 | #define STAT_NOPACKETS 0 |
686 | #define STAT_NOCARRIERSET 10 | 686 | #define STAT_NOCARRIERSET 10 |
687 | #define STAT_GOTCARRIERSET 11 | 687 | #define STAT_GOTCARRIERSET 11 |
@@ -1853,18 +1853,10 @@ static int writeConfigRid(struct airo_info*ai, int lock) { | |||
1853 | 1853 | ||
1854 | return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock); | 1854 | return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock); |
1855 | } | 1855 | } |
1856 | static int readStatusRid(struct airo_info*ai, StatusRid *statr, int lock) { | ||
1857 | int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); | ||
1858 | u16 *s; | ||
1859 | |||
1860 | statr->len = le16_to_cpu(statr->len); | ||
1861 | for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s); | ||
1862 | 1856 | ||
1863 | for(s = &statr->beaconPeriod; s <= &statr->shortPreamble; s++) | 1857 | static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock) |
1864 | *s = le16_to_cpu(*s); | 1858 | { |
1865 | statr->load = le16_to_cpu(statr->load); | 1859 | return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); |
1866 | statr->assocStatus = le16_to_cpu(statr->assocStatus); | ||
1867 | return rc; | ||
1868 | } | 1860 | } |
1869 | 1861 | ||
1870 | static int readAPListRid(struct airo_info *ai, APListRid *aplr) | 1862 | static int readAPListRid(struct airo_info *ai, APListRid *aplr) |
@@ -4656,13 +4648,15 @@ static ssize_t proc_write( struct file *file, | |||
4656 | return len; | 4648 | return len; |
4657 | } | 4649 | } |
4658 | 4650 | ||
4659 | static int proc_status_open( struct inode *inode, struct file *file ) { | 4651 | static int proc_status_open(struct inode *inode, struct file *file) |
4652 | { | ||
4660 | struct proc_data *data; | 4653 | struct proc_data *data; |
4661 | struct proc_dir_entry *dp = PDE(inode); | 4654 | struct proc_dir_entry *dp = PDE(inode); |
4662 | struct net_device *dev = dp->data; | 4655 | struct net_device *dev = dp->data; |
4663 | struct airo_info *apriv = dev->priv; | 4656 | struct airo_info *apriv = dev->priv; |
4664 | CapabilityRid cap_rid; | 4657 | CapabilityRid cap_rid; |
4665 | StatusRid status_rid; | 4658 | StatusRid status_rid; |
4659 | u16 mode; | ||
4666 | int i; | 4660 | int i; |
4667 | 4661 | ||
4668 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) | 4662 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) |
@@ -4676,16 +4670,18 @@ static int proc_status_open( struct inode *inode, struct file *file ) { | |||
4676 | readStatusRid(apriv, &status_rid, 1); | 4670 | readStatusRid(apriv, &status_rid, 1); |
4677 | readCapabilityRid(apriv, &cap_rid, 1); | 4671 | readCapabilityRid(apriv, &cap_rid, 1); |
4678 | 4672 | ||
4673 | mode = le16_to_cpu(status_rid.mode); | ||
4674 | |||
4679 | i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n", | 4675 | i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n", |
4680 | status_rid.mode & 1 ? "CFG ": "", | 4676 | mode & 1 ? "CFG ": "", |
4681 | status_rid.mode & 2 ? "ACT ": "", | 4677 | mode & 2 ? "ACT ": "", |
4682 | status_rid.mode & 0x10 ? "SYN ": "", | 4678 | mode & 0x10 ? "SYN ": "", |
4683 | status_rid.mode & 0x20 ? "LNK ": "", | 4679 | mode & 0x20 ? "LNK ": "", |
4684 | status_rid.mode & 0x40 ? "LEAP ": "", | 4680 | mode & 0x40 ? "LEAP ": "", |
4685 | status_rid.mode & 0x80 ? "PRIV ": "", | 4681 | mode & 0x80 ? "PRIV ": "", |
4686 | status_rid.mode & 0x100 ? "KEY ": "", | 4682 | mode & 0x100 ? "KEY ": "", |
4687 | status_rid.mode & 0x200 ? "WEP ": "", | 4683 | mode & 0x200 ? "WEP ": "", |
4688 | status_rid.mode & 0x8000 ? "ERR ": ""); | 4684 | mode & 0x8000 ? "ERR ": ""); |
4689 | sprintf( data->rbuffer+i, "Mode: %x\n" | 4685 | sprintf( data->rbuffer+i, "Mode: %x\n" |
4690 | "Signal Strength: %d\n" | 4686 | "Signal Strength: %d\n" |
4691 | "Signal Quality: %d\n" | 4687 | "Signal Quality: %d\n" |
@@ -4698,14 +4694,14 @@ static int proc_status_open( struct inode *inode, struct file *file ) { | |||
4698 | "Radio type: %x\nCountry: %x\nHardware Version: %x\n" | 4694 | "Radio type: %x\nCountry: %x\nHardware Version: %x\n" |
4699 | "Software Version: %x\nSoftware Subversion: %x\n" | 4695 | "Software Version: %x\nSoftware Subversion: %x\n" |
4700 | "Boot block version: %x\n", | 4696 | "Boot block version: %x\n", |
4701 | (int)status_rid.mode, | 4697 | le16_to_cpu(status_rid.mode), |
4702 | (int)status_rid.normalizedSignalStrength, | 4698 | le16_to_cpu(status_rid.normalizedSignalStrength), |
4703 | (int)status_rid.signalQuality, | 4699 | le16_to_cpu(status_rid.signalQuality), |
4704 | (int)status_rid.SSIDlen, | 4700 | le16_to_cpu(status_rid.SSIDlen), |
4705 | status_rid.SSID, | 4701 | status_rid.SSID, |
4706 | status_rid.apName, | 4702 | status_rid.apName, |
4707 | (int)status_rid.channel, | 4703 | le16_to_cpu(status_rid.channel), |
4708 | (int)status_rid.currentXmitRate/2, | 4704 | le16_to_cpu(status_rid.currentXmitRate) / 2, |
4709 | version, | 4705 | version, |
4710 | cap_rid.prodName, | 4706 | cap_rid.prodName, |
4711 | cap_rid.manName, | 4707 | cap_rid.manName, |
@@ -5726,25 +5722,27 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) | |||
5726 | static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) | 5722 | static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) |
5727 | { | 5723 | { |
5728 | int quality = 0; | 5724 | int quality = 0; |
5725 | u16 sq; | ||
5729 | 5726 | ||
5730 | if ((status_rid->mode & 0x3f) != 0x3f) | 5727 | if ((status_rid->mode & cpu_to_le16(0x3f)) != cpu_to_le16(0x3f)) |
5731 | return 0; | 5728 | return 0; |
5732 | 5729 | ||
5733 | if (!(cap_rid->hardCap & cpu_to_le16(8))) | 5730 | if (!(cap_rid->hardCap & cpu_to_le16(8))) |
5734 | return 0; | 5731 | return 0; |
5735 | 5732 | ||
5733 | sq = le16_to_cpu(status_rid->signalQuality); | ||
5736 | if (memcmp(cap_rid->prodName, "350", 3)) | 5734 | if (memcmp(cap_rid->prodName, "350", 3)) |
5737 | if (status_rid->signalQuality > 0x20) | 5735 | if (sq > 0x20) |
5738 | quality = 0; | 5736 | quality = 0; |
5739 | else | 5737 | else |
5740 | quality = 0x20 - status_rid->signalQuality; | 5738 | quality = 0x20 - sq; |
5741 | else | 5739 | else |
5742 | if (status_rid->signalQuality > 0xb0) | 5740 | if (sq > 0xb0) |
5743 | quality = 0; | 5741 | quality = 0; |
5744 | else if (status_rid->signalQuality < 0x10) | 5742 | else if (sq < 0x10) |
5745 | quality = 0xa0; | 5743 | quality = 0xa0; |
5746 | else | 5744 | else |
5747 | quality = 0xb0 - status_rid->signalQuality; | 5745 | quality = 0xb0 - sq; |
5748 | return quality; | 5746 | return quality; |
5749 | } | 5747 | } |
5750 | 5748 | ||
@@ -5824,11 +5822,11 @@ static int airo_get_freq(struct net_device *dev, | |||
5824 | 5822 | ||
5825 | readConfigRid(local, 1); | 5823 | readConfigRid(local, 1); |
5826 | if ((local->config.opmode & 0xFF) == MODE_STA_ESS) | 5824 | if ((local->config.opmode & 0xFF) == MODE_STA_ESS) |
5827 | status_rid.channel = local->config.channelSet; | 5825 | status_rid.channel = cpu_to_le16(local->config.channelSet); |
5828 | else | 5826 | else |
5829 | readStatusRid(local, &status_rid, 1); | 5827 | readStatusRid(local, &status_rid, 1); |
5830 | 5828 | ||
5831 | ch = (int)status_rid.channel; | 5829 | ch = le16_to_cpu(status_rid.channel); |
5832 | if((ch > 0) && (ch < 15)) { | 5830 | if((ch > 0) && (ch < 15)) { |
5833 | fwrq->m = frequency_list[ch - 1] * 100000; | 5831 | fwrq->m = frequency_list[ch - 1] * 100000; |
5834 | fwrq->e = 1; | 5832 | fwrq->e = 1; |
@@ -5904,11 +5902,11 @@ static int airo_get_essid(struct net_device *dev, | |||
5904 | * get the relevant SSID from the SSID list... */ | 5902 | * get the relevant SSID from the SSID list... */ |
5905 | 5903 | ||
5906 | /* Get the current SSID */ | 5904 | /* Get the current SSID */ |
5907 | memcpy(extra, status_rid.SSID, status_rid.SSIDlen); | 5905 | memcpy(extra, status_rid.SSID, le16_to_cpu(status_rid.SSIDlen)); |
5908 | /* If none, we may want to get the one that was set */ | 5906 | /* If none, we may want to get the one that was set */ |
5909 | 5907 | ||
5910 | /* Push it out ! */ | 5908 | /* Push it out ! */ |
5911 | dwrq->length = status_rid.SSIDlen; | 5909 | dwrq->length = le16_to_cpu(status_rid.SSIDlen); |
5912 | dwrq->flags = 1; /* active */ | 5910 | dwrq->flags = 1; /* active */ |
5913 | 5911 | ||
5914 | return 0; | 5912 | return 0; |
@@ -6098,7 +6096,7 @@ static int airo_get_rate(struct net_device *dev, | |||
6098 | 6096 | ||
6099 | readStatusRid(local, &status_rid, 1); | 6097 | readStatusRid(local, &status_rid, 1); |
6100 | 6098 | ||
6101 | vwrq->value = status_rid.currentXmitRate * 500000; | 6099 | vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000; |
6102 | /* If more than one rate, set auto */ | 6100 | /* If more than one rate, set auto */ |
6103 | readConfigRid(local, 1); | 6101 | readConfigRid(local, 1); |
6104 | vwrq->fixed = (local->config.rates[1] == 0); | 6102 | vwrq->fixed = (local->config.rates[1] == 0); |
@@ -7646,18 +7644,22 @@ static void airo_read_wireless_stats(struct airo_info *local) | |||
7646 | up(&local->sem); | 7644 | up(&local->sem); |
7647 | 7645 | ||
7648 | /* The status */ | 7646 | /* The status */ |
7649 | local->wstats.status = status_rid.mode; | 7647 | local->wstats.status = le16_to_cpu(status_rid.mode); |
7650 | 7648 | ||
7651 | /* Signal quality and co */ | 7649 | /* Signal quality and co */ |
7652 | if (local->rssi) { | 7650 | if (local->rssi) { |
7653 | local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality ); | 7651 | local->wstats.qual.level = |
7652 | airo_rssi_to_dbm(local->rssi, | ||
7653 | le16_to_cpu(status_rid.sigQuality)); | ||
7654 | /* normalizedSignalStrength appears to be a percentage */ | 7654 | /* normalizedSignalStrength appears to be a percentage */ |
7655 | local->wstats.qual.qual = status_rid.normalizedSignalStrength; | 7655 | local->wstats.qual.qual = |
7656 | le16_to_cpu(status_rid.normalizedSignalStrength); | ||
7656 | } else { | 7657 | } else { |
7657 | local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2; | 7658 | local->wstats.qual.level = |
7659 | (le16_to_cpu(status_rid.normalizedSignalStrength) + 321) / 2; | ||
7658 | local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); | 7660 | local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); |
7659 | } | 7661 | } |
7660 | if (status_rid.len >= 124) { | 7662 | if (le16_to_cpu(status_rid.len) >= 124) { |
7661 | local->wstats.qual.noise = 0x100 - status_rid.noisedBm; | 7663 | local->wstats.qual.noise = 0x100 - status_rid.noisedBm; |
7662 | local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; | 7664 | local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
7663 | } else { | 7665 | } else { |