Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wext.c
Go to the documentation of this file.
1 /* Wireless extensions support.
2  *
3  * See copyright notice in main.c
4  */
5 #include <linux/slab.h>
6 #include <linux/kernel.h>
7 #include <linux/if_arp.h>
8 #include <linux/wireless.h>
9 #include <linux/ieee80211.h>
10 #include <linux/etherdevice.h>
11 #include <net/iw_handler.h>
12 #include <net/cfg80211.h>
13 #include <net/cfg80211-wext.h>
14 
15 #include "hermes.h"
16 #include "hermes_rid.h"
17 #include "orinoco.h"
18 
19 #include "hw.h"
20 #include "mic.h"
21 #include "scan.h"
22 #include "main.h"
23 
24 #include "wext.h"
25 
26 #define MAX_RID_LEN 1024
27 
28 /* Helper routine to record keys
29  * It is called under orinoco_lock so it may not sleep */
30 static int orinoco_set_key(struct orinoco_private *priv, int index,
31  enum orinoco_alg alg, const u8 *key, int key_len,
32  const u8 *seq, int seq_len)
33 {
34  kzfree(priv->keys[index].key);
35  kzfree(priv->keys[index].seq);
36 
37  if (key_len) {
38  priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
39  if (!priv->keys[index].key)
40  goto nomem;
41  } else
42  priv->keys[index].key = NULL;
43 
44  if (seq_len) {
45  priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
46  if (!priv->keys[index].seq)
47  goto free_key;
48  } else
49  priv->keys[index].seq = NULL;
50 
51  priv->keys[index].key_len = key_len;
52  priv->keys[index].seq_len = seq_len;
53 
54  if (key_len)
55  memcpy(priv->keys[index].key, key, key_len);
56  if (seq_len)
57  memcpy(priv->keys[index].seq, seq, seq_len);
58 
59  switch (alg) {
60  case ORINOCO_ALG_TKIP:
61  priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
62  break;
63 
64  case ORINOCO_ALG_WEP:
65  priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
67  break;
68 
69  case ORINOCO_ALG_NONE:
70  default:
71  priv->keys[index].cipher = 0;
72  break;
73  }
74 
75  return 0;
76 
77 free_key:
78  kfree(priv->keys[index].key);
79  priv->keys[index].key = NULL;
80 
81 nomem:
82  priv->keys[index].key_len = 0;
83  priv->keys[index].seq_len = 0;
84  priv->keys[index].cipher = 0;
85 
86  return -ENOMEM;
87 }
88 
89 static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
90 {
91  struct orinoco_private *priv = ndev_priv(dev);
92  struct hermes *hw = &priv->hw;
93  struct iw_statistics *wstats = &priv->wstats;
94  int err;
95  unsigned long flags;
96 
97  if (!netif_device_present(dev)) {
98  printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
99  dev->name);
100  return NULL; /* FIXME: Can we do better than this? */
101  }
102 
103  /* If busy, return the old stats. Returning NULL may cause
104  * the interface to disappear from /proc/net/wireless */
105  if (orinoco_lock(priv, &flags) != 0)
106  return wstats;
107 
108  /* We can't really wait for the tallies inquiry command to
109  * complete, so we just use the previous results and trigger
110  * a new tallies inquiry command for next time - Jean II */
111  /* FIXME: Really we should wait for the inquiry to come back -
112  * as it is the stats we give don't make a whole lot of sense.
113  * Unfortunately, it's not clear how to do that within the
114  * wireless extensions framework: I think we're in user
115  * context, but a lock seems to be held by the time we get in
116  * here so we're not safe to sleep here. */
117  hermes_inquire(hw, HERMES_INQ_TALLIES);
118 
119  if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
120  memset(&wstats->qual, 0, sizeof(wstats->qual));
121  /* If a spy address is defined, we report stats of the
122  * first spy address - Jean II */
123  if (SPY_NUMBER(priv)) {
124  wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
125  wstats->qual.level = priv->spy_data.spy_stat[0].level;
126  wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
127  wstats->qual.updated =
128  priv->spy_data.spy_stat[0].updated;
129  }
130  } else {
131  struct {
132  __le16 qual, signal, noise, unused;
133  } __packed cq;
134 
135  err = HERMES_READ_RECORD(hw, USER_BAP,
137 
138  if (!err) {
139  wstats->qual.qual = (int)le16_to_cpu(cq.qual);
140  wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
141  wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
142  wstats->qual.updated =
144  }
145  }
146 
147  orinoco_unlock(priv, &flags);
148  return wstats;
149 }
150 
151 /********************************************************************/
152 /* Wireless extensions */
153 /********************************************************************/
154 
155 static int orinoco_ioctl_setwap(struct net_device *dev,
156  struct iw_request_info *info,
157  struct sockaddr *ap_addr,
158  char *extra)
159 {
160  struct orinoco_private *priv = ndev_priv(dev);
161  int err = -EINPROGRESS; /* Call commit handler */
162  unsigned long flags;
163 
164  if (orinoco_lock(priv, &flags) != 0)
165  return -EBUSY;
166 
167  /* Enable automatic roaming - no sanity checks are needed */
168  if (is_zero_ether_addr(ap_addr->sa_data) ||
169  is_broadcast_ether_addr(ap_addr->sa_data)) {
170  priv->bssid_fixed = 0;
171  memset(priv->desired_bssid, 0, ETH_ALEN);
172 
173  /* "off" means keep existing connection */
174  if (ap_addr->sa_data[0] == 0) {
175  __orinoco_hw_set_wap(priv);
176  err = 0;
177  }
178  goto out;
179  }
180 
181  if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
182  printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
183  "support manual roaming\n",
184  dev->name);
185  err = -EOPNOTSUPP;
186  goto out;
187  }
188 
189  if (priv->iw_mode != NL80211_IFTYPE_STATION) {
190  printk(KERN_WARNING "%s: Manual roaming supported only in "
191  "managed mode\n", dev->name);
192  err = -EOPNOTSUPP;
193  goto out;
194  }
195 
196  /* Intersil firmware hangs without Desired ESSID */
197  if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
198  strlen(priv->desired_essid) == 0) {
199  printk(KERN_WARNING "%s: Desired ESSID must be set for "
200  "manual roaming\n", dev->name);
201  err = -EOPNOTSUPP;
202  goto out;
203  }
204 
205  /* Finally, enable manual roaming */
206  priv->bssid_fixed = 1;
207  memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
208 
209  out:
210  orinoco_unlock(priv, &flags);
211  return err;
212 }
213 
214 static int orinoco_ioctl_getwap(struct net_device *dev,
215  struct iw_request_info *info,
216  struct sockaddr *ap_addr,
217  char *extra)
218 {
219  struct orinoco_private *priv = ndev_priv(dev);
220 
221  int err = 0;
222  unsigned long flags;
223 
224  if (orinoco_lock(priv, &flags) != 0)
225  return -EBUSY;
226 
227  ap_addr->sa_family = ARPHRD_ETHER;
228  err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
229 
230  orinoco_unlock(priv, &flags);
231 
232  return err;
233 }
234 
235 static int orinoco_ioctl_setiwencode(struct net_device *dev,
236  struct iw_request_info *info,
237  struct iw_point *erq,
238  char *keybuf)
239 {
240  struct orinoco_private *priv = ndev_priv(dev);
241  int index = (erq->flags & IW_ENCODE_INDEX) - 1;
242  int setindex = priv->tx_key;
243  enum orinoco_alg encode_alg = priv->encode_alg;
244  int restricted = priv->wep_restrict;
245  int err = -EINPROGRESS; /* Call commit handler */
246  unsigned long flags;
247 
248  if (!priv->has_wep)
249  return -EOPNOTSUPP;
250 
251  if (erq->pointer) {
252  /* We actually have a key to set - check its length */
253  if (erq->length > LARGE_KEY_SIZE)
254  return -E2BIG;
255 
256  if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
257  return -E2BIG;
258  }
259 
260  if (orinoco_lock(priv, &flags) != 0)
261  return -EBUSY;
262 
263  /* Clear any TKIP key we have */
264  if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
265  (void) orinoco_clear_tkip_key(priv, setindex);
266 
267  if (erq->length > 0) {
268  if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
269  index = priv->tx_key;
270 
271  /* Switch on WEP if off */
272  if (encode_alg != ORINOCO_ALG_WEP) {
273  setindex = index;
274  encode_alg = ORINOCO_ALG_WEP;
275  }
276  } else {
277  /* Important note : if the user do "iwconfig eth0 enc off",
278  * we will arrive there with an index of -1. This is valid
279  * but need to be taken care off... Jean II */
280  if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
281  if ((index != -1) || (erq->flags == 0)) {
282  err = -EINVAL;
283  goto out;
284  }
285  } else {
286  /* Set the index : Check that the key is valid */
287  if (priv->keys[index].key_len == 0) {
288  err = -EINVAL;
289  goto out;
290  }
291  setindex = index;
292  }
293  }
294 
295  if (erq->flags & IW_ENCODE_DISABLED)
296  encode_alg = ORINOCO_ALG_NONE;
297  if (erq->flags & IW_ENCODE_OPEN)
298  restricted = 0;
299  if (erq->flags & IW_ENCODE_RESTRICTED)
300  restricted = 1;
301 
302  if (erq->pointer && erq->length > 0) {
303  err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
304  erq->length, NULL, 0);
305  }
306  priv->tx_key = setindex;
307 
308  /* Try fast key change if connected and only keys are changed */
309  if ((priv->encode_alg == encode_alg) &&
310  (priv->wep_restrict == restricted) &&
311  netif_carrier_ok(dev)) {
312  err = __orinoco_hw_setup_wepkeys(priv);
313  /* No need to commit if successful */
314  goto out;
315  }
316 
317  priv->encode_alg = encode_alg;
318  priv->wep_restrict = restricted;
319 
320  out:
321  orinoco_unlock(priv, &flags);
322 
323  return err;
324 }
325 
326 static int orinoco_ioctl_getiwencode(struct net_device *dev,
327  struct iw_request_info *info,
328  struct iw_point *erq,
329  char *keybuf)
330 {
331  struct orinoco_private *priv = ndev_priv(dev);
332  int index = (erq->flags & IW_ENCODE_INDEX) - 1;
333  unsigned long flags;
334 
335  if (!priv->has_wep)
336  return -EOPNOTSUPP;
337 
338  if (orinoco_lock(priv, &flags) != 0)
339  return -EBUSY;
340 
341  if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
342  index = priv->tx_key;
343 
344  erq->flags = 0;
345  if (!priv->encode_alg)
346  erq->flags |= IW_ENCODE_DISABLED;
347  erq->flags |= index + 1;
348 
349  if (priv->wep_restrict)
350  erq->flags |= IW_ENCODE_RESTRICTED;
351  else
352  erq->flags |= IW_ENCODE_OPEN;
353 
354  erq->length = priv->keys[index].key_len;
355 
356  memcpy(keybuf, priv->keys[index].key, erq->length);
357 
358  orinoco_unlock(priv, &flags);
359  return 0;
360 }
361 
362 static int orinoco_ioctl_setessid(struct net_device *dev,
363  struct iw_request_info *info,
364  struct iw_point *erq,
365  char *essidbuf)
366 {
367  struct orinoco_private *priv = ndev_priv(dev);
368  unsigned long flags;
369 
370  /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
371  * anyway... - Jean II */
372 
373  /* Hum... Should not use Wireless Extension constant (may change),
374  * should use our own... - Jean II */
375  if (erq->length > IW_ESSID_MAX_SIZE)
376  return -E2BIG;
377 
378  if (orinoco_lock(priv, &flags) != 0)
379  return -EBUSY;
380 
381  /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
382  memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
383 
384  /* If not ANY, get the new ESSID */
385  if (erq->flags)
386  memcpy(priv->desired_essid, essidbuf, erq->length);
387 
388  orinoco_unlock(priv, &flags);
389 
390  return -EINPROGRESS; /* Call commit handler */
391 }
392 
393 static int orinoco_ioctl_getessid(struct net_device *dev,
394  struct iw_request_info *info,
395  struct iw_point *erq,
396  char *essidbuf)
397 {
398  struct orinoco_private *priv = ndev_priv(dev);
399  int active;
400  int err = 0;
401  unsigned long flags;
402 
403  if (netif_running(dev)) {
404  err = orinoco_hw_get_essid(priv, &active, essidbuf);
405  if (err < 0)
406  return err;
407  erq->length = err;
408  } else {
409  if (orinoco_lock(priv, &flags) != 0)
410  return -EBUSY;
411  memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
412  erq->length = strlen(priv->desired_essid);
413  orinoco_unlock(priv, &flags);
414  }
415 
416  erq->flags = 1;
417 
418  return 0;
419 }
420 
421 static int orinoco_ioctl_setfreq(struct net_device *dev,
422  struct iw_request_info *info,
423  struct iw_freq *frq,
424  char *extra)
425 {
426  struct orinoco_private *priv = ndev_priv(dev);
427  int chan = -1;
428  unsigned long flags;
429  int err = -EINPROGRESS; /* Call commit handler */
430 
431  /* In infrastructure mode the AP sets the channel */
432  if (priv->iw_mode == NL80211_IFTYPE_STATION)
433  return -EBUSY;
434 
435  if ((frq->e == 0) && (frq->m <= 1000)) {
436  /* Setting by channel number */
437  chan = frq->m;
438  } else {
439  /* Setting by frequency */
440  int denom = 1;
441  int i;
442 
443  /* Calculate denominator to rescale to MHz */
444  for (i = 0; i < (6 - frq->e); i++)
445  denom *= 10;
446 
447  chan = ieee80211_freq_to_dsss_chan(frq->m / denom);
448  }
449 
450  if ((chan < 1) || (chan > NUM_CHANNELS) ||
451  !(priv->channel_mask & (1 << (chan - 1))))
452  return -EINVAL;
453 
454  if (orinoco_lock(priv, &flags) != 0)
455  return -EBUSY;
456 
457  priv->channel = chan;
458  if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
459  /* Fast channel change - no commit if successful */
460  struct hermes *hw = &priv->hw;
461  err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
463  chan, NULL);
464  }
465  orinoco_unlock(priv, &flags);
466 
467  return err;
468 }
469 
470 static int orinoco_ioctl_getfreq(struct net_device *dev,
471  struct iw_request_info *info,
472  struct iw_freq *frq,
473  char *extra)
474 {
475  struct orinoco_private *priv = ndev_priv(dev);
476  int tmp;
477 
478  /* Locking done in there */
479  tmp = orinoco_hw_get_freq(priv);
480  if (tmp < 0)
481  return tmp;
482 
483  frq->m = tmp * 100000;
484  frq->e = 1;
485 
486  return 0;
487 }
488 
489 static int orinoco_ioctl_getsens(struct net_device *dev,
490  struct iw_request_info *info,
491  struct iw_param *srq,
492  char *extra)
493 {
494  struct orinoco_private *priv = ndev_priv(dev);
495  struct hermes *hw = &priv->hw;
496  u16 val;
497  int err;
498  unsigned long flags;
499 
500  if (!priv->has_sensitivity)
501  return -EOPNOTSUPP;
502 
503  if (orinoco_lock(priv, &flags) != 0)
504  return -EBUSY;
505  err = hermes_read_wordrec(hw, USER_BAP,
507  orinoco_unlock(priv, &flags);
508 
509  if (err)
510  return err;
511 
512  srq->value = val;
513  srq->fixed = 0; /* auto */
514 
515  return 0;
516 }
517 
518 static int orinoco_ioctl_setsens(struct net_device *dev,
519  struct iw_request_info *info,
520  struct iw_param *srq,
521  char *extra)
522 {
523  struct orinoco_private *priv = ndev_priv(dev);
524  int val = srq->value;
525  unsigned long flags;
526 
527  if (!priv->has_sensitivity)
528  return -EOPNOTSUPP;
529 
530  if ((val < 1) || (val > 3))
531  return -EINVAL;
532 
533  if (orinoco_lock(priv, &flags) != 0)
534  return -EBUSY;
535  priv->ap_density = val;
536  orinoco_unlock(priv, &flags);
537 
538  return -EINPROGRESS; /* Call commit handler */
539 }
540 
541 static int orinoco_ioctl_setrate(struct net_device *dev,
542  struct iw_request_info *info,
543  struct iw_param *rrq,
544  char *extra)
545 {
546  struct orinoco_private *priv = ndev_priv(dev);
547  int ratemode;
548  int bitrate; /* 100s of kilobits */
549  unsigned long flags;
550 
551  /* As the user space doesn't know our highest rate, it uses -1
552  * to ask us to set the highest rate. Test it using "iwconfig
553  * ethX rate auto" - Jean II */
554  if (rrq->value == -1)
555  bitrate = 110;
556  else {
557  if (rrq->value % 100000)
558  return -EINVAL;
559  bitrate = rrq->value / 100000;
560  }
561 
562  ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed);
563 
564  if (ratemode == -1)
565  return -EINVAL;
566 
567  if (orinoco_lock(priv, &flags) != 0)
568  return -EBUSY;
569  priv->bitratemode = ratemode;
570  orinoco_unlock(priv, &flags);
571 
572  return -EINPROGRESS;
573 }
574 
575 static int orinoco_ioctl_getrate(struct net_device *dev,
576  struct iw_request_info *info,
577  struct iw_param *rrq,
578  char *extra)
579 {
580  struct orinoco_private *priv = ndev_priv(dev);
581  int err = 0;
582  int bitrate, automatic;
583  unsigned long flags;
584 
585  if (orinoco_lock(priv, &flags) != 0)
586  return -EBUSY;
587 
588  orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic);
589 
590  /* If the interface is running we try to find more about the
591  current mode */
592  if (netif_running(dev)) {
593  int act_bitrate;
594  int lerr;
595 
596  /* Ignore errors if we can't get the actual bitrate */
597  lerr = orinoco_hw_get_act_bitrate(priv, &act_bitrate);
598  if (!lerr)
599  bitrate = act_bitrate;
600  }
601 
602  orinoco_unlock(priv, &flags);
603 
604  rrq->value = bitrate;
605  rrq->fixed = !automatic;
606  rrq->disabled = 0;
607 
608  return err;
609 }
610 
611 static int orinoco_ioctl_setpower(struct net_device *dev,
612  struct iw_request_info *info,
613  struct iw_param *prq,
614  char *extra)
615 {
616  struct orinoco_private *priv = ndev_priv(dev);
617  int err = -EINPROGRESS; /* Call commit handler */
618  unsigned long flags;
619 
620  if (orinoco_lock(priv, &flags) != 0)
621  return -EBUSY;
622 
623  if (prq->disabled) {
624  priv->pm_on = 0;
625  } else {
626  switch (prq->flags & IW_POWER_MODE) {
627  case IW_POWER_UNICAST_R:
628  priv->pm_mcast = 0;
629  priv->pm_on = 1;
630  break;
631  case IW_POWER_ALL_R:
632  priv->pm_mcast = 1;
633  priv->pm_on = 1;
634  break;
635  case IW_POWER_ON:
636  /* No flags : but we may have a value - Jean II */
637  break;
638  default:
639  err = -EINVAL;
640  goto out;
641  }
642 
643  if (prq->flags & IW_POWER_TIMEOUT) {
644  priv->pm_on = 1;
645  priv->pm_timeout = prq->value / 1000;
646  }
647  if (prq->flags & IW_POWER_PERIOD) {
648  priv->pm_on = 1;
649  priv->pm_period = prq->value / 1000;
650  }
651  /* It's valid to not have a value if we are just toggling
652  * the flags... Jean II */
653  if (!priv->pm_on) {
654  err = -EINVAL;
655  goto out;
656  }
657  }
658 
659  out:
660  orinoco_unlock(priv, &flags);
661 
662  return err;
663 }
664 
665 static int orinoco_ioctl_getpower(struct net_device *dev,
666  struct iw_request_info *info,
667  struct iw_param *prq,
668  char *extra)
669 {
670  struct orinoco_private *priv = ndev_priv(dev);
671  struct hermes *hw = &priv->hw;
672  int err = 0;
673  u16 enable, period, timeout, mcast;
674  unsigned long flags;
675 
676  if (orinoco_lock(priv, &flags) != 0)
677  return -EBUSY;
678 
679  err = hermes_read_wordrec(hw, USER_BAP,
680  HERMES_RID_CNFPMENABLED, &enable);
681  if (err)
682  goto out;
683 
684  err = hermes_read_wordrec(hw, USER_BAP,
686  if (err)
687  goto out;
688 
689  err = hermes_read_wordrec(hw, USER_BAP,
691  if (err)
692  goto out;
693 
694  err = hermes_read_wordrec(hw, USER_BAP,
696  if (err)
697  goto out;
698 
699  prq->disabled = !enable;
700  /* Note : by default, display the period */
701  if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
702  prq->flags = IW_POWER_TIMEOUT;
703  prq->value = timeout * 1000;
704  } else {
705  prq->flags = IW_POWER_PERIOD;
706  prq->value = period * 1000;
707  }
708  if (mcast)
709  prq->flags |= IW_POWER_ALL_R;
710  else
711  prq->flags |= IW_POWER_UNICAST_R;
712 
713  out:
714  orinoco_unlock(priv, &flags);
715 
716  return err;
717 }
718 
719 static int orinoco_ioctl_set_encodeext(struct net_device *dev,
720  struct iw_request_info *info,
721  union iwreq_data *wrqu,
722  char *extra)
723 {
724  struct orinoco_private *priv = ndev_priv(dev);
725  struct iw_point *encoding = &wrqu->encoding;
726  struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
727  int idx, alg = ext->alg, set_key = 1;
728  unsigned long flags;
729  int err = -EINVAL;
730 
731  if (orinoco_lock(priv, &flags) != 0)
732  return -EBUSY;
733 
734  /* Determine and validate the key index */
735  idx = encoding->flags & IW_ENCODE_INDEX;
736  if (idx) {
737  if ((idx < 1) || (idx > 4))
738  goto out;
739  idx--;
740  } else
741  idx = priv->tx_key;
742 
743  if (encoding->flags & IW_ENCODE_DISABLED)
744  alg = IW_ENCODE_ALG_NONE;
745 
746  if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
747  /* Clear any TKIP TX key we had */
748  (void) orinoco_clear_tkip_key(priv, priv->tx_key);
749  }
750 
751  if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
752  priv->tx_key = idx;
753  set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
754  (ext->key_len > 0)) ? 1 : 0;
755  }
756 
757  if (set_key) {
758  /* Set the requested key first */
759  switch (alg) {
760  case IW_ENCODE_ALG_NONE:
762  err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
763  NULL, 0, NULL, 0);
764  break;
765 
766  case IW_ENCODE_ALG_WEP:
767  if (ext->key_len <= 0)
768  goto out;
769 
770  priv->encode_alg = ORINOCO_ALG_WEP;
771  err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
772  ext->key, ext->key_len, NULL, 0);
773  break;
774 
775  case IW_ENCODE_ALG_TKIP:
776  {
777  u8 *tkip_iv = NULL;
778 
779  if (!priv->has_wpa ||
780  (ext->key_len > sizeof(struct orinoco_tkip_key)))
781  goto out;
782 
784 
786  tkip_iv = &ext->rx_seq[0];
787 
788  err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
789  ext->key, ext->key_len, tkip_iv,
791 
792  err = __orinoco_hw_set_tkip_key(priv, idx,
794  priv->keys[idx].key,
795  tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
796  if (err)
797  printk(KERN_ERR "%s: Error %d setting TKIP key"
798  "\n", dev->name, err);
799 
800  goto out;
801  }
802  default:
803  goto out;
804  }
805  }
806  err = -EINPROGRESS;
807  out:
808  orinoco_unlock(priv, &flags);
809 
810  return err;
811 }
812 
813 static int orinoco_ioctl_get_encodeext(struct net_device *dev,
814  struct iw_request_info *info,
815  union iwreq_data *wrqu,
816  char *extra)
817 {
818  struct orinoco_private *priv = ndev_priv(dev);
819  struct iw_point *encoding = &wrqu->encoding;
820  struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
821  int idx, max_key_len;
822  unsigned long flags;
823  int err;
824 
825  if (orinoco_lock(priv, &flags) != 0)
826  return -EBUSY;
827 
828  err = -EINVAL;
829  max_key_len = encoding->length - sizeof(*ext);
830  if (max_key_len < 0)
831  goto out;
832 
833  idx = encoding->flags & IW_ENCODE_INDEX;
834  if (idx) {
835  if ((idx < 1) || (idx > 4))
836  goto out;
837  idx--;
838  } else
839  idx = priv->tx_key;
840 
841  encoding->flags = idx + 1;
842  memset(ext, 0, sizeof(*ext));
843 
844  switch (priv->encode_alg) {
845  case ORINOCO_ALG_NONE:
846  ext->alg = IW_ENCODE_ALG_NONE;
847  ext->key_len = 0;
848  encoding->flags |= IW_ENCODE_DISABLED;
849  break;
850  case ORINOCO_ALG_WEP:
851  ext->alg = IW_ENCODE_ALG_WEP;
852  ext->key_len = min(priv->keys[idx].key_len, max_key_len);
853  memcpy(ext->key, priv->keys[idx].key, ext->key_len);
854  encoding->flags |= IW_ENCODE_ENABLED;
855  break;
856  case ORINOCO_ALG_TKIP:
857  ext->alg = IW_ENCODE_ALG_TKIP;
858  ext->key_len = min(priv->keys[idx].key_len, max_key_len);
859  memcpy(ext->key, priv->keys[idx].key, ext->key_len);
860  encoding->flags |= IW_ENCODE_ENABLED;
861  break;
862  }
863 
864  err = 0;
865  out:
866  orinoco_unlock(priv, &flags);
867 
868  return err;
869 }
870 
871 static int orinoco_ioctl_set_auth(struct net_device *dev,
872  struct iw_request_info *info,
873  union iwreq_data *wrqu, char *extra)
874 {
875  struct orinoco_private *priv = ndev_priv(dev);
876  struct hermes *hw = &priv->hw;
877  struct iw_param *param = &wrqu->param;
878  unsigned long flags;
879  int ret = -EINPROGRESS;
880 
881  if (orinoco_lock(priv, &flags) != 0)
882  return -EBUSY;
883 
884  switch (param->flags & IW_AUTH_INDEX) {
885  case IW_AUTH_WPA_VERSION:
891  /*
892  * orinoco does not use these parameters
893  */
894  break;
895 
896  case IW_AUTH_MFP:
897  /* Management Frame Protection not supported.
898  * Only fail if set to required.
899  */
900  if (param->value == IW_AUTH_MFP_REQUIRED)
901  ret = -EINVAL;
902  break;
903 
904  case IW_AUTH_KEY_MGMT:
905  /* wl_lkm implies value 2 == PSK for Hermes I
906  * which ties in with WEXT
907  * no other hints tho :(
908  */
909  priv->key_mgmt = param->value;
910  break;
911 
913  /* When countermeasures are enabled, shut down the
914  * card; when disabled, re-enable the card. This must
915  * take effect immediately.
916  *
917  * TODO: Make sure that the EAPOL message is getting
918  * out before card disabled
919  */
920  if (param->value) {
921  priv->tkip_cm_active = 1;
922  ret = hermes_disable_port(hw, 0);
923  } else {
924  priv->tkip_cm_active = 0;
925  ret = hermes_enable_port(hw, 0);
926  }
927  break;
928 
930  if (param->value & IW_AUTH_ALG_SHARED_KEY)
931  priv->wep_restrict = 1;
932  else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
933  priv->wep_restrict = 0;
934  else
935  ret = -EINVAL;
936  break;
937 
938  case IW_AUTH_WPA_ENABLED:
939  if (priv->has_wpa) {
940  priv->wpa_enabled = param->value ? 1 : 0;
941  } else {
942  if (param->value)
943  ret = -EOPNOTSUPP;
944  /* else silently accept disable of WPA */
945  priv->wpa_enabled = 0;
946  }
947  break;
948 
949  default:
950  ret = -EOPNOTSUPP;
951  }
952 
953  orinoco_unlock(priv, &flags);
954  return ret;
955 }
956 
957 static int orinoco_ioctl_get_auth(struct net_device *dev,
958  struct iw_request_info *info,
959  union iwreq_data *wrqu, char *extra)
960 {
961  struct orinoco_private *priv = ndev_priv(dev);
962  struct iw_param *param = &wrqu->param;
963  unsigned long flags;
964  int ret = 0;
965 
966  if (orinoco_lock(priv, &flags) != 0)
967  return -EBUSY;
968 
969  switch (param->flags & IW_AUTH_INDEX) {
970  case IW_AUTH_KEY_MGMT:
971  param->value = priv->key_mgmt;
972  break;
973 
975  param->value = priv->tkip_cm_active;
976  break;
977 
979  if (priv->wep_restrict)
980  param->value = IW_AUTH_ALG_SHARED_KEY;
981  else
983  break;
984 
985  case IW_AUTH_WPA_ENABLED:
986  param->value = priv->wpa_enabled;
987  break;
988 
989  default:
990  ret = -EOPNOTSUPP;
991  }
992 
993  orinoco_unlock(priv, &flags);
994  return ret;
995 }
996 
997 static int orinoco_ioctl_set_genie(struct net_device *dev,
998  struct iw_request_info *info,
999  union iwreq_data *wrqu, char *extra)
1000 {
1001  struct orinoco_private *priv = ndev_priv(dev);
1002  u8 *buf;
1003  unsigned long flags;
1004 
1005  /* cut off at IEEE80211_MAX_DATA_LEN */
1006  if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
1007  (wrqu->data.length && (extra == NULL)))
1008  return -EINVAL;
1009 
1010  if (wrqu->data.length) {
1011  buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL);
1012  if (buf == NULL)
1013  return -ENOMEM;
1014  } else
1015  buf = NULL;
1016 
1017  if (orinoco_lock(priv, &flags) != 0) {
1018  kfree(buf);
1019  return -EBUSY;
1020  }
1021 
1022  kfree(priv->wpa_ie);
1023  priv->wpa_ie = buf;
1024  priv->wpa_ie_len = wrqu->data.length;
1025 
1026  if (priv->wpa_ie) {
1027  /* Looks like wl_lkm wants to check the auth alg, and
1028  * somehow pass it to the firmware.
1029  * Instead it just calls the key mgmt rid
1030  * - we do this in set auth.
1031  */
1032  }
1033 
1034  orinoco_unlock(priv, &flags);
1035  return 0;
1036 }
1037 
1038 static int orinoco_ioctl_get_genie(struct net_device *dev,
1039  struct iw_request_info *info,
1040  union iwreq_data *wrqu, char *extra)
1041 {
1042  struct orinoco_private *priv = ndev_priv(dev);
1043  unsigned long flags;
1044  int err = 0;
1045 
1046  if (orinoco_lock(priv, &flags) != 0)
1047  return -EBUSY;
1048 
1049  if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
1050  wrqu->data.length = 0;
1051  goto out;
1052  }
1053 
1054  if (wrqu->data.length < priv->wpa_ie_len) {
1055  err = -E2BIG;
1056  goto out;
1057  }
1058 
1059  wrqu->data.length = priv->wpa_ie_len;
1060  memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
1061 
1062 out:
1063  orinoco_unlock(priv, &flags);
1064  return err;
1065 }
1066 
1067 static int orinoco_ioctl_set_mlme(struct net_device *dev,
1068  struct iw_request_info *info,
1069  union iwreq_data *wrqu, char *extra)
1070 {
1071  struct orinoco_private *priv = ndev_priv(dev);
1072  struct iw_mlme *mlme = (struct iw_mlme *)extra;
1073  unsigned long flags;
1074  int ret = 0;
1075 
1076  if (orinoco_lock(priv, &flags) != 0)
1077  return -EBUSY;
1078 
1079  switch (mlme->cmd) {
1080  case IW_MLME_DEAUTH:
1081  /* silently ignore */
1082  break;
1083 
1084  case IW_MLME_DISASSOC:
1085 
1086  ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
1087  mlme->reason_code);
1088  break;
1089 
1090  default:
1091  ret = -EOPNOTSUPP;
1092  }
1093 
1094  orinoco_unlock(priv, &flags);
1095  return ret;
1096 }
1097 
1098 static int orinoco_ioctl_reset(struct net_device *dev,
1099  struct iw_request_info *info,
1100  void *wrqu,
1101  char *extra)
1102 {
1103  struct orinoco_private *priv = ndev_priv(dev);
1104 
1105  if (!capable(CAP_NET_ADMIN))
1106  return -EPERM;
1107 
1108  if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
1109  printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
1110 
1111  /* Firmware reset */
1112  orinoco_reset(&priv->reset_work);
1113  } else {
1114  printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
1115 
1116  schedule_work(&priv->reset_work);
1117  }
1118 
1119  return 0;
1120 }
1121 
1122 static int orinoco_ioctl_setibssport(struct net_device *dev,
1123  struct iw_request_info *info,
1124  void *wrqu,
1125  char *extra)
1126 
1127 {
1128  struct orinoco_private *priv = ndev_priv(dev);
1129  int val = *((int *) extra);
1130  unsigned long flags;
1131 
1132  if (orinoco_lock(priv, &flags) != 0)
1133  return -EBUSY;
1134 
1135  priv->ibss_port = val;
1136 
1137  /* Actually update the mode we are using */
1138  set_port_type(priv);
1139 
1140  orinoco_unlock(priv, &flags);
1141  return -EINPROGRESS; /* Call commit handler */
1142 }
1143 
1144 static int orinoco_ioctl_getibssport(struct net_device *dev,
1145  struct iw_request_info *info,
1146  void *wrqu,
1147  char *extra)
1148 {
1149  struct orinoco_private *priv = ndev_priv(dev);
1150  int *val = (int *) extra;
1151 
1152  *val = priv->ibss_port;
1153  return 0;
1154 }
1155 
1156 static int orinoco_ioctl_setport3(struct net_device *dev,
1157  struct iw_request_info *info,
1158  void *wrqu,
1159  char *extra)
1160 {
1161  struct orinoco_private *priv = ndev_priv(dev);
1162  int val = *((int *) extra);
1163  int err = 0;
1164  unsigned long flags;
1165 
1166  if (orinoco_lock(priv, &flags) != 0)
1167  return -EBUSY;
1168 
1169  switch (val) {
1170  case 0: /* Try to do IEEE ad-hoc mode */
1171  if (!priv->has_ibss) {
1172  err = -EINVAL;
1173  break;
1174  }
1175  priv->prefer_port3 = 0;
1176 
1177  break;
1178 
1179  case 1: /* Try to do Lucent proprietary ad-hoc mode */
1180  if (!priv->has_port3) {
1181  err = -EINVAL;
1182  break;
1183  }
1184  priv->prefer_port3 = 1;
1185  break;
1186 
1187  default:
1188  err = -EINVAL;
1189  }
1190 
1191  if (!err) {
1192  /* Actually update the mode we are using */
1193  set_port_type(priv);
1194  err = -EINPROGRESS;
1195  }
1196 
1197  orinoco_unlock(priv, &flags);
1198 
1199  return err;
1200 }
1201 
1202 static int orinoco_ioctl_getport3(struct net_device *dev,
1203  struct iw_request_info *info,
1204  void *wrqu,
1205  char *extra)
1206 {
1207  struct orinoco_private *priv = ndev_priv(dev);
1208  int *val = (int *) extra;
1209 
1210  *val = priv->prefer_port3;
1211  return 0;
1212 }
1213 
1214 static int orinoco_ioctl_setpreamble(struct net_device *dev,
1215  struct iw_request_info *info,
1216  void *wrqu,
1217  char *extra)
1218 {
1219  struct orinoco_private *priv = ndev_priv(dev);
1220  unsigned long flags;
1221  int val;
1222 
1223  if (!priv->has_preamble)
1224  return -EOPNOTSUPP;
1225 
1226  /* 802.11b has recently defined some short preamble.
1227  * Basically, the Phy header has been reduced in size.
1228  * This increase performance, especially at high rates
1229  * (the preamble is transmitted at 1Mb/s), unfortunately
1230  * this give compatibility troubles... - Jean II */
1231  val = *((int *) extra);
1232 
1233  if (orinoco_lock(priv, &flags) != 0)
1234  return -EBUSY;
1235 
1236  if (val)
1237  priv->preamble = 1;
1238  else
1239  priv->preamble = 0;
1240 
1241  orinoco_unlock(priv, &flags);
1242 
1243  return -EINPROGRESS; /* Call commit handler */
1244 }
1245 
1246 static int orinoco_ioctl_getpreamble(struct net_device *dev,
1247  struct iw_request_info *info,
1248  void *wrqu,
1249  char *extra)
1250 {
1251  struct orinoco_private *priv = ndev_priv(dev);
1252  int *val = (int *) extra;
1253 
1254  if (!priv->has_preamble)
1255  return -EOPNOTSUPP;
1256 
1257  *val = priv->preamble;
1258  return 0;
1259 }
1260 
1261 /* ioctl interface to hermes_read_ltv()
1262  * To use with iwpriv, pass the RID as the token argument, e.g.
1263  * iwpriv get_rid [0xfc00]
1264  * At least Wireless Tools 25 is required to use iwpriv.
1265  * For Wireless Tools 25 and 26 append "dummy" are the end. */
1266 static int orinoco_ioctl_getrid(struct net_device *dev,
1267  struct iw_request_info *info,
1268  struct iw_point *data,
1269  char *extra)
1270 {
1271  struct orinoco_private *priv = ndev_priv(dev);
1272  struct hermes *hw = &priv->hw;
1273  int rid = data->flags;
1274  u16 length;
1275  int err;
1276  unsigned long flags;
1277 
1278  /* It's a "get" function, but we don't want users to access the
1279  * WEP key and other raw firmware data */
1280  if (!capable(CAP_NET_ADMIN))
1281  return -EPERM;
1282 
1283  if (rid < 0xfc00 || rid > 0xffff)
1284  return -EINVAL;
1285 
1286  if (orinoco_lock(priv, &flags) != 0)
1287  return -EBUSY;
1288 
1289  err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
1290  extra);
1291  if (err)
1292  goto out;
1293 
1294  data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
1295  MAX_RID_LEN);
1296 
1297  out:
1298  orinoco_unlock(priv, &flags);
1299  return err;
1300 }
1301 
1302 
1303 /* Commit handler, called after set operations */
1304 static int orinoco_ioctl_commit(struct net_device *dev,
1305  struct iw_request_info *info,
1306  void *wrqu,
1307  char *extra)
1308 {
1309  struct orinoco_private *priv = ndev_priv(dev);
1310  unsigned long flags;
1311  int err = 0;
1312 
1313  if (!priv->open)
1314  return 0;
1315 
1316  if (orinoco_lock(priv, &flags) != 0)
1317  return err;
1318 
1319  err = orinoco_commit(priv);
1320 
1321  orinoco_unlock(priv, &flags);
1322  return err;
1323 }
1324 
1325 static const struct iw_priv_args orinoco_privtab[] = {
1326  { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
1327  { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
1329  0, "set_port3" },
1331  "get_port3" },
1333  0, "set_preamble" },
1335  "get_preamble" },
1337  0, "set_ibssport" },
1339  "get_ibssport" },
1341  "get_rid" },
1342 };
1343 
1344 
1345 /*
1346  * Structures to export the Wireless Handlers
1347  */
1348 
1349 static const iw_handler orinoco_handler[] = {
1350  IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)orinoco_ioctl_commit),
1352  IW_HANDLER(SIOCSIWFREQ, (iw_handler)orinoco_ioctl_setfreq),
1353  IW_HANDLER(SIOCGIWFREQ, (iw_handler)orinoco_ioctl_getfreq),
1356  IW_HANDLER(SIOCSIWSENS, (iw_handler)orinoco_ioctl_setsens),
1357  IW_HANDLER(SIOCGIWSENS, (iw_handler)orinoco_ioctl_getsens),
1363  IW_HANDLER(SIOCSIWAP, (iw_handler)orinoco_ioctl_setwap),
1364  IW_HANDLER(SIOCGIWAP, (iw_handler)orinoco_ioctl_getwap),
1367  IW_HANDLER(SIOCSIWESSID, (iw_handler)orinoco_ioctl_setessid),
1368  IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid),
1369  IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate),
1370  IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate),
1376  IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode),
1377  IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode),
1378  IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower),
1379  IW_HANDLER(SIOCGIWPOWER, (iw_handler)orinoco_ioctl_getpower),
1380  IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
1381  IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
1382  IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
1383  IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
1384  IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
1385  IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
1386  IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
1387 };
1388 
1389 
1390 /*
1391  Added typecasting since we no longer use iwreq_data -- Moustafa
1392  */
1393 static const iw_handler orinoco_private_handler[] = {
1394  [0] = (iw_handler)orinoco_ioctl_reset,
1395  [1] = (iw_handler)orinoco_ioctl_reset,
1396  [2] = (iw_handler)orinoco_ioctl_setport3,
1397  [3] = (iw_handler)orinoco_ioctl_getport3,
1398  [4] = (iw_handler)orinoco_ioctl_setpreamble,
1399  [5] = (iw_handler)orinoco_ioctl_getpreamble,
1400  [6] = (iw_handler)orinoco_ioctl_setibssport,
1401  [7] = (iw_handler)orinoco_ioctl_getibssport,
1402  [9] = (iw_handler)orinoco_ioctl_getrid,
1403 };
1404 
1406  .num_standard = ARRAY_SIZE(orinoco_handler),
1407  .num_private = ARRAY_SIZE(orinoco_private_handler),
1408  .num_private_args = ARRAY_SIZE(orinoco_privtab),
1409  .standard = orinoco_handler,
1410  .private = orinoco_private_handler,
1411  .private_args = orinoco_privtab,
1412  .get_wireless_stats = orinoco_get_wireless_stats,
1413 };