diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/orinoco.c | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index d7947358e49d..223d35795350 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -4021,7 +4021,8 @@ static int orinoco_ioctl_setscan(struct net_device *dev, | |||
4021 | } | 4021 | } |
4022 | 4022 | ||
4023 | /* Translate scan data returned from the card to a card independant | 4023 | /* Translate scan data returned from the card to a card independant |
4024 | * format that the Wireless Tools will understand - Jean II */ | 4024 | * format that the Wireless Tools will understand - Jean II |
4025 | * Return message length or -errno for fatal errors */ | ||
4025 | static inline int orinoco_translate_scan(struct net_device *dev, | 4026 | static inline int orinoco_translate_scan(struct net_device *dev, |
4026 | char *buffer, | 4027 | char *buffer, |
4027 | char *scan, | 4028 | char *scan, |
@@ -4061,13 +4062,19 @@ static inline int orinoco_translate_scan(struct net_device *dev, | |||
4061 | break; | 4062 | break; |
4062 | case FIRMWARE_TYPE_INTERSIL: | 4063 | case FIRMWARE_TYPE_INTERSIL: |
4063 | offset = 4; | 4064 | offset = 4; |
4064 | if (priv->has_hostscan) | 4065 | if (priv->has_hostscan) { |
4065 | atom_len = scan[0] + (scan[1] << 8); | 4066 | atom_len = le16_to_cpup((u16 *)scan); |
4066 | else | 4067 | /* Sanity check for atom_len */ |
4068 | if (atom_len < sizeof(struct prism2_scan_apinfo)) { | ||
4069 | printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n", | ||
4070 | dev->name, atom_len); | ||
4071 | return -EIO; | ||
4072 | } | ||
4073 | } else | ||
4067 | atom_len = offsetof(struct prism2_scan_apinfo, atim); | 4074 | atom_len = offsetof(struct prism2_scan_apinfo, atim); |
4068 | break; | 4075 | break; |
4069 | default: | 4076 | default: |
4070 | return 0; | 4077 | return -EOPNOTSUPP; |
4071 | } | 4078 | } |
4072 | 4079 | ||
4073 | /* Check that we got an whole number of atoms */ | 4080 | /* Check that we got an whole number of atoms */ |
@@ -4075,7 +4082,7 @@ static inline int orinoco_translate_scan(struct net_device *dev, | |||
4075 | printk(KERN_ERR "%s: Unexpected scan data length %d, " | 4082 | printk(KERN_ERR "%s: Unexpected scan data length %d, " |
4076 | "atom_len %d, offset %d\n", dev->name, scan_len, | 4083 | "atom_len %d, offset %d\n", dev->name, scan_len, |
4077 | atom_len, offset); | 4084 | atom_len, offset); |
4078 | return 0; | 4085 | return -EIO; |
4079 | } | 4086 | } |
4080 | 4087 | ||
4081 | /* Read the entries one by one */ | 4088 | /* Read the entries one by one */ |
@@ -4210,33 +4217,41 @@ static int orinoco_ioctl_getscan(struct net_device *dev, | |||
4210 | /* We have some results to push back to user space */ | 4217 | /* We have some results to push back to user space */ |
4211 | 4218 | ||
4212 | /* Translate to WE format */ | 4219 | /* Translate to WE format */ |
4213 | srq->length = orinoco_translate_scan(dev, extra, | 4220 | int ret = orinoco_translate_scan(dev, extra, |
4214 | priv->scan_result, | 4221 | priv->scan_result, |
4215 | priv->scan_len); | 4222 | priv->scan_len); |
4216 | 4223 | ||
4217 | /* Return flags */ | 4224 | if (ret < 0) { |
4218 | srq->flags = (__u16) priv->scan_mode; | 4225 | err = ret; |
4226 | kfree(priv->scan_result); | ||
4227 | priv->scan_result = NULL; | ||
4228 | } else { | ||
4229 | srq->length = ret; | ||
4219 | 4230 | ||
4220 | /* Results are here, so scan no longer in progress */ | 4231 | /* Return flags */ |
4221 | priv->scan_inprogress = 0; | 4232 | srq->flags = (__u16) priv->scan_mode; |
4222 | 4233 | ||
4223 | /* In any case, Scan results will be cleaned up in the | 4234 | /* In any case, Scan results will be cleaned up in the |
4224 | * reset function and when exiting the driver. | 4235 | * reset function and when exiting the driver. |
4225 | * The person triggering the scanning may never come to | 4236 | * The person triggering the scanning may never come to |
4226 | * pick the results, so we need to do it in those places. | 4237 | * pick the results, so we need to do it in those places. |
4227 | * Jean II */ | 4238 | * Jean II */ |
4228 | 4239 | ||
4229 | #ifdef SCAN_SINGLE_READ | 4240 | #ifdef SCAN_SINGLE_READ |
4230 | /* If you enable this option, only one client (the first | 4241 | /* If you enable this option, only one client (the first |
4231 | * one) will be able to read the result (and only one | 4242 | * one) will be able to read the result (and only one |
4232 | * time). If there is multiple concurent clients that | 4243 | * time). If there is multiple concurent clients that |
4233 | * want to read scan results, this behavior is not | 4244 | * want to read scan results, this behavior is not |
4234 | * advisable - Jean II */ | 4245 | * advisable - Jean II */ |
4235 | kfree(priv->scan_result); | 4246 | kfree(priv->scan_result); |
4236 | priv->scan_result = NULL; | 4247 | priv->scan_result = NULL; |
4237 | #endif /* SCAN_SINGLE_READ */ | 4248 | #endif /* SCAN_SINGLE_READ */ |
4238 | /* Here, if too much time has elapsed since last scan, | 4249 | /* Here, if too much time has elapsed since last scan, |
4239 | * we may want to clean up scan results... - Jean II */ | 4250 | * we may want to clean up scan results... - Jean II */ |
4251 | } | ||
4252 | |||
4253 | /* Scan is no longer in progress */ | ||
4254 | priv->scan_inprogress = 0; | ||
4240 | } | 4255 | } |
4241 | 4256 | ||
4242 | orinoco_unlock(priv, &flags); | 4257 | orinoco_unlock(priv, &flags); |