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>
This commit is contained in:
parent
a23ace5f22
commit
56d81bd3c7
|
@ -718,32 +718,32 @@ typedef struct {
|
|||
} APListRid;
|
||||
|
||||
typedef struct {
|
||||
u16 len;
|
||||
__le16 len;
|
||||
char oui[3];
|
||||
char zero;
|
||||
u16 prodNum;
|
||||
__le16 prodNum;
|
||||
char manName[32];
|
||||
char prodName[16];
|
||||
char prodVer[8];
|
||||
char factoryAddr[ETH_ALEN];
|
||||
char aironetAddr[ETH_ALEN];
|
||||
u16 radioType;
|
||||
u16 country;
|
||||
__le16 radioType;
|
||||
__le16 country;
|
||||
char callid[ETH_ALEN];
|
||||
char supportedRates[8];
|
||||
char rxDiversity;
|
||||
char txDiversity;
|
||||
u16 txPowerLevels[8];
|
||||
u16 hardVer;
|
||||
u16 hardCap;
|
||||
u16 tempRange;
|
||||
u16 softVer;
|
||||
u16 softSubVer;
|
||||
u16 interfaceVer;
|
||||
u16 softCap;
|
||||
u16 bootBlockVer;
|
||||
u16 requiredHard;
|
||||
u16 extSoftCap;
|
||||
__le16 txPowerLevels[8];
|
||||
__le16 hardVer;
|
||||
__le16 hardCap;
|
||||
__le16 tempRange;
|
||||
__le16 softVer;
|
||||
__le16 softSubVer;
|
||||
__le16 interfaceVer;
|
||||
__le16 softCap;
|
||||
__le16 bootBlockVer;
|
||||
__le16 requiredHard;
|
||||
__le16 extSoftCap;
|
||||
} CapabilityRid;
|
||||
|
||||
|
||||
|
@ -1877,17 +1877,10 @@ static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) {
|
|||
rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
|
||||
return rc;
|
||||
}
|
||||
static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) {
|
||||
int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
|
||||
u16 *s;
|
||||
|
||||
capr->len = le16_to_cpu(capr->len);
|
||||
capr->prodNum = le16_to_cpu(capr->prodNum);
|
||||
capr->radioType = le16_to_cpu(capr->radioType);
|
||||
capr->country = le16_to_cpu(capr->country);
|
||||
for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++)
|
||||
*s = le16_to_cpu(*s);
|
||||
return rc;
|
||||
static int readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock)
|
||||
{
|
||||
return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
|
||||
}
|
||||
|
||||
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)
|
|||
if (status != SUCCESS) return 0;
|
||||
|
||||
/* Only firmware versions 5.30.17 or better can do WPA */
|
||||
if ((cap_rid.softVer > 0x530)
|
||||
|| ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
|
||||
if (le16_to_cpu(cap_rid.softVer) > 0x530
|
||||
|| (le16_to_cpu(cap_rid.softVer) == 0x530
|
||||
&& le16_to_cpu(cap_rid.softSubVer) >= 17)) {
|
||||
airo_print_info("", "WPA is supported.");
|
||||
return 1;
|
||||
}
|
||||
|
@ -3809,7 +3803,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
|
|||
else {
|
||||
kfree(ai->rssi);
|
||||
ai->rssi = NULL;
|
||||
if (cap_rid.softCap & 8)
|
||||
if (cap_rid.softCap & cpu_to_le16(8))
|
||||
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
|
||||
else
|
||||
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)
|
|||
ai->config.authType = AUTH_OPEN;
|
||||
ai->config.modulation = MOD_CCK;
|
||||
|
||||
if ((cap_rid.len>=sizeof(cap_rid)) &&
|
||||
if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) &&
|
||||
(cap_rid.extSoftCap & cpu_to_le16(1)) &&
|
||||
(micsetup(ai) == SUCCESS)) {
|
||||
micsetup(ai) == SUCCESS) {
|
||||
ai->config.opmode |= MODE_MIC;
|
||||
set_bit(FLAG_MIC_CAPABLE, &ai->flags);
|
||||
}
|
||||
|
@ -4717,12 +4711,12 @@ static int proc_status_open( struct inode *inode, struct file *file ) {
|
|||
cap_rid.prodName,
|
||||
cap_rid.manName,
|
||||
cap_rid.prodVer,
|
||||
cap_rid.radioType,
|
||||
cap_rid.country,
|
||||
cap_rid.hardVer,
|
||||
(int)cap_rid.softVer,
|
||||
(int)cap_rid.softSubVer,
|
||||
(int)cap_rid.bootBlockVer );
|
||||
le16_to_cpu(cap_rid.radioType),
|
||||
le16_to_cpu(cap_rid.country),
|
||||
le16_to_cpu(cap_rid.hardVer),
|
||||
le16_to_cpu(cap_rid.softVer),
|
||||
le16_to_cpu(cap_rid.softSubVer),
|
||||
le16_to_cpu(cap_rid.bootBlockVer));
|
||||
data->readlen = strlen( data->rbuffer );
|
||||
return 0;
|
||||
}
|
||||
|
@ -5734,20 +5728,24 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
|
|||
{
|
||||
int quality = 0;
|
||||
|
||||
if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
|
||||
if (memcmp(cap_rid->prodName, "350", 3))
|
||||
if (status_rid->signalQuality > 0x20)
|
||||
quality = 0;
|
||||
else
|
||||
quality = 0x20 - status_rid->signalQuality;
|
||||
if ((status_rid->mode & 0x3f) != 0x3f)
|
||||
return 0;
|
||||
|
||||
if (!(cap_rid->hardCap & cpu_to_le16(8)))
|
||||
return 0;
|
||||
|
||||
if (memcmp(cap_rid->prodName, "350", 3))
|
||||
if (status_rid->signalQuality > 0x20)
|
||||
quality = 0;
|
||||
else
|
||||
if (status_rid->signalQuality > 0xb0)
|
||||
quality = 0;
|
||||
else if (status_rid->signalQuality < 0x10)
|
||||
quality = 0xa0;
|
||||
else
|
||||
quality = 0xb0 - status_rid->signalQuality;
|
||||
}
|
||||
quality = 0x20 - status_rid->signalQuality;
|
||||
else
|
||||
if (status_rid->signalQuality > 0xb0)
|
||||
quality = 0;
|
||||
else if (status_rid->signalQuality < 0x10)
|
||||
quality = 0xa0;
|
||||
else
|
||||
quality = 0xb0 - status_rid->signalQuality;
|
||||
return quality;
|
||||
}
|
||||
|
||||
|
@ -6289,6 +6287,13 @@ static int airo_get_mode(struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int valid_index(CapabilityRid *p, int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return 0;
|
||||
return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/*
|
||||
* Wireless Handler : set Encryption Key
|
||||
|
@ -6306,7 +6311,7 @@ static int airo_set_encode(struct net_device *dev,
|
|||
/* Is WEP supported ? */
|
||||
readCapabilityRid(local, &cap_rid, 1);
|
||||
/* Older firmware doesn't support this...
|
||||
if(!(cap_rid.softCap & 2)) {
|
||||
if(!(cap_rid.softCap & cpu_to_le16(2))) {
|
||||
return -EOPNOTSUPP;
|
||||
} */
|
||||
readConfigRid(local, 1);
|
||||
|
@ -6326,7 +6331,7 @@ static int airo_set_encode(struct net_device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
/* Check the index (none -> use current) */
|
||||
if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4:1)))
|
||||
if (!valid_index(&cap_rid, index))
|
||||
index = current_index;
|
||||
/* Set the length */
|
||||
if (dwrq->length > MIN_KEY_SIZE)
|
||||
|
@ -6356,7 +6361,7 @@ static int airo_set_encode(struct net_device *dev,
|
|||
} else {
|
||||
/* Do we want to just set the transmit key index ? */
|
||||
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
|
||||
if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) {
|
||||
if (valid_index(&cap_rid, index)) {
|
||||
set_wep_key(local, index, NULL, 0, perm, 1);
|
||||
} else
|
||||
/* Don't complain if only change the mode */
|
||||
|
@ -6391,7 +6396,7 @@ static int airo_get_encode(struct net_device *dev,
|
|||
|
||||
/* Is it supported ? */
|
||||
readCapabilityRid(local, &cap_rid, 1);
|
||||
if(!(cap_rid.softCap & 2)) {
|
||||
if(!(cap_rid.softCap & cpu_to_le16(2))) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
readConfigRid(local, 1);
|
||||
|
@ -6413,7 +6418,7 @@ static int airo_get_encode(struct net_device *dev,
|
|||
memset(extra, 0, 16);
|
||||
|
||||
/* Which key do we want ? -1 -> tx index */
|
||||
if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4 : 1)))
|
||||
if (!valid_index(&cap_rid, index))
|
||||
index = get_wep_key(local, 0xffff);
|
||||
dwrq->flags |= index + 1;
|
||||
/* Copy the key to the user buffer */
|
||||
|
@ -6445,7 +6450,7 @@ static int airo_set_encodeext(struct net_device *dev,
|
|||
/* Is WEP supported ? */
|
||||
readCapabilityRid(local, &cap_rid, 1);
|
||||
/* Older firmware doesn't support this...
|
||||
if(!(cap_rid.softCap & 2)) {
|
||||
if(!(cap_rid.softCap & cpu_to_le16(2))) {
|
||||
return -EOPNOTSUPP;
|
||||
} */
|
||||
readConfigRid(local, 1);
|
||||
|
@ -6453,7 +6458,7 @@ static int airo_set_encodeext(struct net_device *dev,
|
|||
/* Determine and validate the key index */
|
||||
idx = encoding->flags & IW_ENCODE_INDEX;
|
||||
if (idx) {
|
||||
if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
|
||||
if (!valid_index(&cap_rid, idx - 1))
|
||||
return -EINVAL;
|
||||
idx--;
|
||||
} else
|
||||
|
@ -6527,7 +6532,7 @@ static int airo_get_encodeext(struct net_device *dev,
|
|||
|
||||
/* Is it supported ? */
|
||||
readCapabilityRid(local, &cap_rid, 1);
|
||||
if(!(cap_rid.softCap & 2)) {
|
||||
if(!(cap_rid.softCap & cpu_to_le16(2))) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
readConfigRid(local, 1);
|
||||
|
@ -6538,7 +6543,7 @@ static int airo_get_encodeext(struct net_device *dev,
|
|||
|
||||
idx = encoding->flags & IW_ENCODE_INDEX;
|
||||
if (idx) {
|
||||
if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
|
||||
if (!valid_index(&cap_rid, idx - 1))
|
||||
return -EINVAL;
|
||||
idx--;
|
||||
} else
|
||||
|
@ -6716,7 +6721,7 @@ static int airo_set_txpow(struct net_device *dev,
|
|||
}
|
||||
clear_bit (FLAG_RADIO_OFF, &local->flags);
|
||||
for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
|
||||
if ((vwrq->value==cap_rid.txPowerLevels[i])) {
|
||||
if (vwrq->value == le16_to_cpu(cap_rid.txPowerLevels[i])) {
|
||||
readConfigRid(local, 1);
|
||||
local->config.txPower = vwrq->value;
|
||||
set_bit (FLAG_COMMIT, &local->flags);
|
||||
|
@ -6888,16 +6893,17 @@ static int airo_get_range(struct net_device *dev,
|
|||
range->min_frag = 256;
|
||||
range->max_frag = AIRO_DEF_MTU;
|
||||
|
||||
if(cap_rid.softCap & 2) {
|
||||
if(cap_rid.softCap & cpu_to_le16(2)) {
|
||||
// WEP: RC4 40 bits
|
||||
range->encoding_size[0] = 5;
|
||||
// RC4 ~128 bits
|
||||
if (cap_rid.softCap & 0x100) {
|
||||
if (cap_rid.softCap & cpu_to_le16(0x100)) {
|
||||
range->encoding_size[1] = 13;
|
||||
range->num_encoding_sizes = 2;
|
||||
} else
|
||||
range->num_encoding_sizes = 1;
|
||||
range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1;
|
||||
range->max_encoding_tokens =
|
||||
cap_rid.softCap & cpu_to_le16(0x80) ? 4 : 1;
|
||||
} else {
|
||||
range->num_encoding_sizes = 0;
|
||||
range->max_encoding_tokens = 0;
|
||||
|
@ -6912,7 +6918,7 @@ static int airo_get_range(struct net_device *dev,
|
|||
|
||||
/* Transmit Power - values are in mW */
|
||||
for(i = 0 ; i < 8 ; i++) {
|
||||
range->txpower[i] = cap_rid.txPowerLevels[i];
|
||||
range->txpower[i] = le16_to_cpu(cap_rid.txPowerLevels[i]);
|
||||
if(range->txpower[i] == 0)
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue