diff options
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r-- | drivers/net/wireless/orinoco.c | 93 |
1 files changed, 57 insertions, 36 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index d7947358e49d..8de49fe57233 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -1053,8 +1053,9 @@ static void orinoco_join_ap(struct net_device *dev) | |||
1053 | u16 channel; | 1053 | u16 channel; |
1054 | } __attribute__ ((packed)) req; | 1054 | } __attribute__ ((packed)) req; |
1055 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); | 1055 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); |
1056 | struct prism2_scan_apinfo *atom; | 1056 | struct prism2_scan_apinfo *atom = NULL; |
1057 | int offset = 4; | 1057 | int offset = 4; |
1058 | int found = 0; | ||
1058 | u8 *buf; | 1059 | u8 *buf; |
1059 | u16 len; | 1060 | u16 len; |
1060 | 1061 | ||
@@ -1089,15 +1090,18 @@ static void orinoco_join_ap(struct net_device *dev) | |||
1089 | * we were requested to join */ | 1090 | * we were requested to join */ |
1090 | for (; offset + atom_len <= len; offset += atom_len) { | 1091 | for (; offset + atom_len <= len; offset += atom_len) { |
1091 | atom = (struct prism2_scan_apinfo *) (buf + offset); | 1092 | atom = (struct prism2_scan_apinfo *) (buf + offset); |
1092 | if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) | 1093 | if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) { |
1093 | goto found; | 1094 | found = 1; |
1095 | break; | ||
1096 | } | ||
1094 | } | 1097 | } |
1095 | 1098 | ||
1096 | DEBUG(1, "%s: Requested AP not found in scan results\n", | 1099 | if (! found) { |
1097 | dev->name); | 1100 | DEBUG(1, "%s: Requested AP not found in scan results\n", |
1098 | goto out; | 1101 | dev->name); |
1102 | goto out; | ||
1103 | } | ||
1099 | 1104 | ||
1100 | found: | ||
1101 | memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); | 1105 | memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); |
1102 | req.channel = atom->channel; /* both are little-endian */ | 1106 | req.channel = atom->channel; /* both are little-endian */ |
1103 | err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, | 1107 | err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, |
@@ -1284,8 +1288,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
1284 | /* Read scan data */ | 1288 | /* Read scan data */ |
1285 | err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, | 1289 | err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, |
1286 | infofid, sizeof(info)); | 1290 | infofid, sizeof(info)); |
1287 | if (err) | 1291 | if (err) { |
1292 | kfree(buf); | ||
1288 | break; | 1293 | break; |
1294 | } | ||
1289 | 1295 | ||
1290 | #ifdef ORINOCO_DEBUG | 1296 | #ifdef ORINOCO_DEBUG |
1291 | { | 1297 | { |
@@ -4021,7 +4027,8 @@ static int orinoco_ioctl_setscan(struct net_device *dev, | |||
4021 | } | 4027 | } |
4022 | 4028 | ||
4023 | /* Translate scan data returned from the card to a card independant | 4029 | /* Translate scan data returned from the card to a card independant |
4024 | * format that the Wireless Tools will understand - Jean II */ | 4030 | * format that the Wireless Tools will understand - Jean II |
4031 | * Return message length or -errno for fatal errors */ | ||
4025 | static inline int orinoco_translate_scan(struct net_device *dev, | 4032 | static inline int orinoco_translate_scan(struct net_device *dev, |
4026 | char *buffer, | 4033 | char *buffer, |
4027 | char *scan, | 4034 | char *scan, |
@@ -4061,13 +4068,19 @@ static inline int orinoco_translate_scan(struct net_device *dev, | |||
4061 | break; | 4068 | break; |
4062 | case FIRMWARE_TYPE_INTERSIL: | 4069 | case FIRMWARE_TYPE_INTERSIL: |
4063 | offset = 4; | 4070 | offset = 4; |
4064 | if (priv->has_hostscan) | 4071 | if (priv->has_hostscan) { |
4065 | atom_len = scan[0] + (scan[1] << 8); | 4072 | atom_len = le16_to_cpup((u16 *)scan); |
4066 | else | 4073 | /* Sanity check for atom_len */ |
4074 | if (atom_len < sizeof(struct prism2_scan_apinfo)) { | ||
4075 | printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n", | ||
4076 | dev->name, atom_len); | ||
4077 | return -EIO; | ||
4078 | } | ||
4079 | } else | ||
4067 | atom_len = offsetof(struct prism2_scan_apinfo, atim); | 4080 | atom_len = offsetof(struct prism2_scan_apinfo, atim); |
4068 | break; | 4081 | break; |
4069 | default: | 4082 | default: |
4070 | return 0; | 4083 | return -EOPNOTSUPP; |
4071 | } | 4084 | } |
4072 | 4085 | ||
4073 | /* Check that we got an whole number of atoms */ | 4086 | /* Check that we got an whole number of atoms */ |
@@ -4075,7 +4088,7 @@ static inline int orinoco_translate_scan(struct net_device *dev, | |||
4075 | printk(KERN_ERR "%s: Unexpected scan data length %d, " | 4088 | printk(KERN_ERR "%s: Unexpected scan data length %d, " |
4076 | "atom_len %d, offset %d\n", dev->name, scan_len, | 4089 | "atom_len %d, offset %d\n", dev->name, scan_len, |
4077 | atom_len, offset); | 4090 | atom_len, offset); |
4078 | return 0; | 4091 | return -EIO; |
4079 | } | 4092 | } |
4080 | 4093 | ||
4081 | /* Read the entries one by one */ | 4094 | /* Read the entries one by one */ |
@@ -4210,33 +4223,41 @@ static int orinoco_ioctl_getscan(struct net_device *dev, | |||
4210 | /* We have some results to push back to user space */ | 4223 | /* We have some results to push back to user space */ |
4211 | 4224 | ||
4212 | /* Translate to WE format */ | 4225 | /* Translate to WE format */ |
4213 | srq->length = orinoco_translate_scan(dev, extra, | 4226 | int ret = orinoco_translate_scan(dev, extra, |
4214 | priv->scan_result, | 4227 | priv->scan_result, |
4215 | priv->scan_len); | 4228 | priv->scan_len); |
4216 | 4229 | ||
4217 | /* Return flags */ | 4230 | if (ret < 0) { |
4218 | srq->flags = (__u16) priv->scan_mode; | 4231 | err = ret; |
4232 | kfree(priv->scan_result); | ||
4233 | priv->scan_result = NULL; | ||
4234 | } else { | ||
4235 | srq->length = ret; | ||
4219 | 4236 | ||
4220 | /* Results are here, so scan no longer in progress */ | 4237 | /* Return flags */ |
4221 | priv->scan_inprogress = 0; | 4238 | srq->flags = (__u16) priv->scan_mode; |
4222 | 4239 | ||
4223 | /* In any case, Scan results will be cleaned up in the | 4240 | /* In any case, Scan results will be cleaned up in the |
4224 | * reset function and when exiting the driver. | 4241 | * reset function and when exiting the driver. |
4225 | * The person triggering the scanning may never come to | 4242 | * The person triggering the scanning may never come to |
4226 | * pick the results, so we need to do it in those places. | 4243 | * pick the results, so we need to do it in those places. |
4227 | * Jean II */ | 4244 | * Jean II */ |
4228 | 4245 | ||
4229 | #ifdef SCAN_SINGLE_READ | 4246 | #ifdef SCAN_SINGLE_READ |
4230 | /* If you enable this option, only one client (the first | 4247 | /* If you enable this option, only one client (the first |
4231 | * one) will be able to read the result (and only one | 4248 | * one) will be able to read the result (and only one |
4232 | * time). If there is multiple concurent clients that | 4249 | * time). If there is multiple concurent clients that |
4233 | * want to read scan results, this behavior is not | 4250 | * want to read scan results, this behavior is not |
4234 | * advisable - Jean II */ | 4251 | * advisable - Jean II */ |
4235 | kfree(priv->scan_result); | 4252 | kfree(priv->scan_result); |
4236 | priv->scan_result = NULL; | 4253 | priv->scan_result = NULL; |
4237 | #endif /* SCAN_SINGLE_READ */ | 4254 | #endif /* SCAN_SINGLE_READ */ |
4238 | /* Here, if too much time has elapsed since last scan, | 4255 | /* Here, if too much time has elapsed since last scan, |
4239 | * we may want to clean up scan results... - Jean II */ | 4256 | * we may want to clean up scan results... - Jean II */ |
4257 | } | ||
4258 | |||
4259 | /* Scan is no longer in progress */ | ||
4260 | priv->scan_inprogress = 0; | ||
4240 | } | 4261 | } |
4241 | 4262 | ||
4242 | orinoco_unlock(priv, &flags); | 4263 | orinoco_unlock(priv, &flags); |