aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco.c93
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 */
4025static inline int orinoco_translate_scan(struct net_device *dev, 4032static 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);