1 /* Wireless extensions support.
3 * See copyright notice in main.c
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>
16 #include "hermes_rid.h"
26 #define MAX_RID_LEN 1024
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
)
34 kzfree(priv
->keys
[index
].key
);
35 kzfree(priv
->keys
[index
].seq
);
38 priv
->keys
[index
].key
= kzalloc(key_len
, GFP_ATOMIC
);
39 if (!priv
->keys
[index
].key
)
42 priv
->keys
[index
].key
= NULL
;
45 priv
->keys
[index
].seq
= kzalloc(seq_len
, GFP_ATOMIC
);
46 if (!priv
->keys
[index
].seq
)
49 priv
->keys
[index
].seq
= NULL
;
51 priv
->keys
[index
].key_len
= key_len
;
52 priv
->keys
[index
].seq_len
= seq_len
;
55 memcpy(priv
->keys
[index
].key
, key
, key_len
);
57 memcpy(priv
->keys
[index
].seq
, seq
, seq_len
);
60 case ORINOCO_ALG_TKIP
:
61 priv
->keys
[index
].cipher
= WLAN_CIPHER_SUITE_TKIP
;
65 priv
->keys
[index
].cipher
= (key_len
> SMALL_KEY_SIZE
) ?
66 WLAN_CIPHER_SUITE_WEP104
: WLAN_CIPHER_SUITE_WEP40
;
69 case ORINOCO_ALG_NONE
:
71 priv
->keys
[index
].cipher
= 0;
78 kfree(priv
->keys
[index
].key
);
79 priv
->keys
[index
].key
= NULL
;
82 priv
->keys
[index
].key_len
= 0;
83 priv
->keys
[index
].seq_len
= 0;
84 priv
->keys
[index
].cipher
= 0;
89 static struct iw_statistics
*orinoco_get_wireless_stats(struct net_device
*dev
)
91 struct orinoco_private
*priv
= ndev_priv(dev
);
92 struct hermes
*hw
= &priv
->hw
;
93 struct iw_statistics
*wstats
= &priv
->wstats
;
97 if (!netif_device_present(dev
)) {
98 printk(KERN_WARNING
"%s: get_wireless_stats() called while device not present\n",
100 return NULL
; /* FIXME: Can we do better than this? */
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)
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
);
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
;
132 __le16 qual
, signal
, noise
, unused
;
135 err
= HERMES_READ_RECORD(hw
, USER_BAP
,
136 HERMES_RID_COMMSQUALITY
, &cq
);
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
=
143 IW_QUAL_ALL_UPDATED
| IW_QUAL_DBM
;
147 orinoco_unlock(priv
, &flags
);
151 /********************************************************************/
152 /* Wireless extensions */
153 /********************************************************************/
155 static int orinoco_ioctl_setwap(struct net_device
*dev
,
156 struct iw_request_info
*info
,
157 struct sockaddr
*ap_addr
,
160 struct orinoco_private
*priv
= ndev_priv(dev
);
161 int err
= -EINPROGRESS
; /* Call commit handler */
164 if (orinoco_lock(priv
, &flags
) != 0)
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
);
173 /* "off" means keep existing connection */
174 if (ap_addr
->sa_data
[0] == 0) {
175 __orinoco_hw_set_wap(priv
);
181 if (priv
->firmware_type
== FIRMWARE_TYPE_AGERE
) {
182 printk(KERN_WARNING
"%s: Lucent/Agere firmware doesn't "
183 "support manual roaming\n",
189 if (priv
->iw_mode
!= NL80211_IFTYPE_STATION
) {
190 printk(KERN_WARNING
"%s: Manual roaming supported only in "
191 "managed mode\n", dev
->name
);
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
);
205 /* Finally, enable manual roaming */
206 priv
->bssid_fixed
= 1;
207 memcpy(priv
->desired_bssid
, &ap_addr
->sa_data
, ETH_ALEN
);
210 orinoco_unlock(priv
, &flags
);
214 static int orinoco_ioctl_getwap(struct net_device
*dev
,
215 struct iw_request_info
*info
,
216 struct sockaddr
*ap_addr
,
219 struct orinoco_private
*priv
= ndev_priv(dev
);
224 if (orinoco_lock(priv
, &flags
) != 0)
227 ap_addr
->sa_family
= ARPHRD_ETHER
;
228 err
= orinoco_hw_get_current_bssid(priv
, ap_addr
->sa_data
);
230 orinoco_unlock(priv
, &flags
);
235 static int orinoco_ioctl_setiwencode(struct net_device
*dev
,
236 struct iw_request_info
*info
,
237 struct iw_point
*erq
,
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 */
252 /* We actually have a key to set - check its length */
253 if (erq
->length
> LARGE_KEY_SIZE
)
256 if ((erq
->length
> SMALL_KEY_SIZE
) && !priv
->has_big_wep
)
260 if (orinoco_lock(priv
, &flags
) != 0)
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
);
267 if (erq
->length
> 0) {
268 if ((index
< 0) || (index
>= ORINOCO_MAX_KEYS
))
269 index
= priv
->tx_key
;
271 /* Switch on WEP if off */
272 if (encode_alg
!= ORINOCO_ALG_WEP
) {
274 encode_alg
= ORINOCO_ALG_WEP
;
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)) {
286 /* Set the index : Check that the key is valid */
287 if (priv
->keys
[index
].key_len
== 0) {
295 if (erq
->flags
& IW_ENCODE_DISABLED
)
296 encode_alg
= ORINOCO_ALG_NONE
;
297 if (erq
->flags
& IW_ENCODE_OPEN
)
299 if (erq
->flags
& IW_ENCODE_RESTRICTED
)
302 if (erq
->pointer
&& erq
->length
> 0) {
303 err
= orinoco_set_key(priv
, index
, ORINOCO_ALG_WEP
, keybuf
,
304 erq
->length
, NULL
, 0);
306 priv
->tx_key
= setindex
;
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 */
317 priv
->encode_alg
= encode_alg
;
318 priv
->wep_restrict
= restricted
;
321 orinoco_unlock(priv
, &flags
);
326 static int orinoco_ioctl_getiwencode(struct net_device
*dev
,
327 struct iw_request_info
*info
,
328 struct iw_point
*erq
,
331 struct orinoco_private
*priv
= ndev_priv(dev
);
332 int index
= (erq
->flags
& IW_ENCODE_INDEX
) - 1;
338 if (orinoco_lock(priv
, &flags
) != 0)
341 if ((index
< 0) || (index
>= ORINOCO_MAX_KEYS
))
342 index
= priv
->tx_key
;
345 if (!priv
->encode_alg
)
346 erq
->flags
|= IW_ENCODE_DISABLED
;
347 erq
->flags
|= index
+ 1;
349 if (priv
->wep_restrict
)
350 erq
->flags
|= IW_ENCODE_RESTRICTED
;
352 erq
->flags
|= IW_ENCODE_OPEN
;
354 erq
->length
= priv
->keys
[index
].key_len
;
356 memcpy(keybuf
, priv
->keys
[index
].key
, erq
->length
);
358 orinoco_unlock(priv
, &flags
);
362 static int orinoco_ioctl_setessid(struct net_device
*dev
,
363 struct iw_request_info
*info
,
364 struct iw_point
*erq
,
367 struct orinoco_private
*priv
= ndev_priv(dev
);
370 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
371 * anyway... - Jean II */
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
)
378 if (orinoco_lock(priv
, &flags
) != 0)
381 /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
382 memset(priv
->desired_essid
, 0, sizeof(priv
->desired_essid
));
384 /* If not ANY, get the new ESSID */
386 memcpy(priv
->desired_essid
, essidbuf
, erq
->length
);
388 orinoco_unlock(priv
, &flags
);
390 return -EINPROGRESS
; /* Call commit handler */
393 static int orinoco_ioctl_getessid(struct net_device
*dev
,
394 struct iw_request_info
*info
,
395 struct iw_point
*erq
,
398 struct orinoco_private
*priv
= ndev_priv(dev
);
403 if (netif_running(dev
)) {
404 err
= orinoco_hw_get_essid(priv
, &active
, essidbuf
);
409 if (orinoco_lock(priv
, &flags
) != 0)
411 memcpy(essidbuf
, priv
->desired_essid
, IW_ESSID_MAX_SIZE
);
412 erq
->length
= strlen(priv
->desired_essid
);
413 orinoco_unlock(priv
, &flags
);
421 static int orinoco_ioctl_setfreq(struct net_device
*dev
,
422 struct iw_request_info
*info
,
426 struct orinoco_private
*priv
= ndev_priv(dev
);
429 int err
= -EINPROGRESS
; /* Call commit handler */
431 /* In infrastructure mode the AP sets the channel */
432 if (priv
->iw_mode
== NL80211_IFTYPE_STATION
)
435 if ((frq
->e
== 0) && (frq
->m
<= 1000)) {
436 /* Setting by channel number */
439 /* Setting by frequency */
443 /* Calculate denominator to rescale to MHz */
444 for (i
= 0; i
< (6 - frq
->e
); i
++)
447 chan
= ieee80211_frequency_to_channel(frq
->m
/ denom
);
450 if ((chan
< 1) || (chan
> NUM_CHANNELS
) ||
451 !(priv
->channel_mask
& (1 << (chan
- 1))))
454 if (orinoco_lock(priv
, &flags
) != 0)
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
|
462 HERMES_TEST_SET_CHANNEL
,
465 orinoco_unlock(priv
, &flags
);
470 static int orinoco_ioctl_getfreq(struct net_device
*dev
,
471 struct iw_request_info
*info
,
475 struct orinoco_private
*priv
= ndev_priv(dev
);
478 /* Locking done in there */
479 tmp
= orinoco_hw_get_freq(priv
);
483 frq
->m
= tmp
* 100000;
489 static int orinoco_ioctl_getsens(struct net_device
*dev
,
490 struct iw_request_info
*info
,
491 struct iw_param
*srq
,
494 struct orinoco_private
*priv
= ndev_priv(dev
);
495 struct hermes
*hw
= &priv
->hw
;
500 if (!priv
->has_sensitivity
)
503 if (orinoco_lock(priv
, &flags
) != 0)
505 err
= hermes_read_wordrec(hw
, USER_BAP
,
506 HERMES_RID_CNFSYSTEMSCALE
, &val
);
507 orinoco_unlock(priv
, &flags
);
513 srq
->fixed
= 0; /* auto */
518 static int orinoco_ioctl_setsens(struct net_device
*dev
,
519 struct iw_request_info
*info
,
520 struct iw_param
*srq
,
523 struct orinoco_private
*priv
= ndev_priv(dev
);
524 int val
= srq
->value
;
527 if (!priv
->has_sensitivity
)
530 if ((val
< 1) || (val
> 3))
533 if (orinoco_lock(priv
, &flags
) != 0)
535 priv
->ap_density
= val
;
536 orinoco_unlock(priv
, &flags
);
538 return -EINPROGRESS
; /* Call commit handler */
541 static int orinoco_ioctl_setrate(struct net_device
*dev
,
542 struct iw_request_info
*info
,
543 struct iw_param
*rrq
,
546 struct orinoco_private
*priv
= ndev_priv(dev
);
548 int bitrate
; /* 100s of kilobits */
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)
557 if (rrq
->value
% 100000)
559 bitrate
= rrq
->value
/ 100000;
562 ratemode
= orinoco_get_bitratemode(bitrate
, !rrq
->fixed
);
567 if (orinoco_lock(priv
, &flags
) != 0)
569 priv
->bitratemode
= ratemode
;
570 orinoco_unlock(priv
, &flags
);
575 static int orinoco_ioctl_getrate(struct net_device
*dev
,
576 struct iw_request_info
*info
,
577 struct iw_param
*rrq
,
580 struct orinoco_private
*priv
= ndev_priv(dev
);
582 int bitrate
, automatic
;
585 if (orinoco_lock(priv
, &flags
) != 0)
588 orinoco_get_ratemode_cfg(priv
->bitratemode
, &bitrate
, &automatic
);
590 /* If the interface is running we try to find more about the
592 if (netif_running(dev
)) {
596 /* Ignore errors if we can't get the actual bitrate */
597 lerr
= orinoco_hw_get_act_bitrate(priv
, &act_bitrate
);
599 bitrate
= act_bitrate
;
602 orinoco_unlock(priv
, &flags
);
604 rrq
->value
= bitrate
;
605 rrq
->fixed
= !automatic
;
611 static int orinoco_ioctl_setpower(struct net_device
*dev
,
612 struct iw_request_info
*info
,
613 struct iw_param
*prq
,
616 struct orinoco_private
*priv
= ndev_priv(dev
);
617 int err
= -EINPROGRESS
; /* Call commit handler */
620 if (orinoco_lock(priv
, &flags
) != 0)
626 switch (prq
->flags
& IW_POWER_MODE
) {
627 case IW_POWER_UNICAST_R
:
636 /* No flags : but we may have a value - Jean II */
643 if (prq
->flags
& IW_POWER_TIMEOUT
) {
645 priv
->pm_timeout
= prq
->value
/ 1000;
647 if (prq
->flags
& IW_POWER_PERIOD
) {
649 priv
->pm_period
= prq
->value
/ 1000;
651 /* It's valid to not have a value if we are just toggling
652 * the flags... Jean II */
660 orinoco_unlock(priv
, &flags
);
665 static int orinoco_ioctl_getpower(struct net_device
*dev
,
666 struct iw_request_info
*info
,
667 struct iw_param
*prq
,
670 struct orinoco_private
*priv
= ndev_priv(dev
);
671 struct hermes
*hw
= &priv
->hw
;
673 u16 enable
, period
, timeout
, mcast
;
676 if (orinoco_lock(priv
, &flags
) != 0)
679 err
= hermes_read_wordrec(hw
, USER_BAP
,
680 HERMES_RID_CNFPMENABLED
, &enable
);
684 err
= hermes_read_wordrec(hw
, USER_BAP
,
685 HERMES_RID_CNFMAXSLEEPDURATION
, &period
);
689 err
= hermes_read_wordrec(hw
, USER_BAP
,
690 HERMES_RID_CNFPMHOLDOVERDURATION
, &timeout
);
694 err
= hermes_read_wordrec(hw
, USER_BAP
,
695 HERMES_RID_CNFMULTICASTRECEIVE
, &mcast
);
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;
705 prq
->flags
= IW_POWER_PERIOD
;
706 prq
->value
= period
* 1000;
709 prq
->flags
|= IW_POWER_ALL_R
;
711 prq
->flags
|= IW_POWER_UNICAST_R
;
714 orinoco_unlock(priv
, &flags
);
719 static int orinoco_ioctl_set_encodeext(struct net_device
*dev
,
720 struct iw_request_info
*info
,
721 union iwreq_data
*wrqu
,
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;
731 if (orinoco_lock(priv
, &flags
) != 0)
734 /* Determine and validate the key index */
735 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
737 if ((idx
< 1) || (idx
> 4))
743 if (encoding
->flags
& IW_ENCODE_DISABLED
)
744 alg
= IW_ENCODE_ALG_NONE
;
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
);
751 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
753 set_key
= ((alg
== IW_ENCODE_ALG_TKIP
) ||
754 (ext
->key_len
> 0)) ? 1 : 0;
758 /* Set the requested key first */
760 case IW_ENCODE_ALG_NONE
:
761 priv
->encode_alg
= ORINOCO_ALG_NONE
;
762 err
= orinoco_set_key(priv
, idx
, ORINOCO_ALG_NONE
,
766 case IW_ENCODE_ALG_WEP
:
767 if (ext
->key_len
<= 0)
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);
775 case IW_ENCODE_ALG_TKIP
:
779 if (!priv
->has_wpa
||
780 (ext
->key_len
> sizeof(struct orinoco_tkip_key
)))
783 priv
->encode_alg
= ORINOCO_ALG_TKIP
;
785 if (ext
->ext_flags
& IW_ENCODE_EXT_RX_SEQ_VALID
)
786 tkip_iv
= &ext
->rx_seq
[0];
788 err
= orinoco_set_key(priv
, idx
, ORINOCO_ALG_TKIP
,
789 ext
->key
, ext
->key_len
, tkip_iv
,
792 err
= __orinoco_hw_set_tkip_key(priv
, idx
,
793 ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
,
795 tkip_iv
, ORINOCO_SEQ_LEN
, NULL
, 0);
797 printk(KERN_ERR
"%s: Error %d setting TKIP key"
798 "\n", dev
->name
, err
);
808 orinoco_unlock(priv
, &flags
);
813 static int orinoco_ioctl_get_encodeext(struct net_device
*dev
,
814 struct iw_request_info
*info
,
815 union iwreq_data
*wrqu
,
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
;
825 if (orinoco_lock(priv
, &flags
) != 0)
829 max_key_len
= encoding
->length
- sizeof(*ext
);
833 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
835 if ((idx
< 1) || (idx
> 4))
841 encoding
->flags
= idx
+ 1;
842 memset(ext
, 0, sizeof(*ext
));
844 switch (priv
->encode_alg
) {
845 case ORINOCO_ALG_NONE
:
846 ext
->alg
= IW_ENCODE_ALG_NONE
;
848 encoding
->flags
|= IW_ENCODE_DISABLED
;
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
;
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
;
866 orinoco_unlock(priv
, &flags
);
871 static int orinoco_ioctl_set_auth(struct net_device
*dev
,
872 struct iw_request_info
*info
,
873 union iwreq_data
*wrqu
, char *extra
)
875 struct orinoco_private
*priv
= ndev_priv(dev
);
876 struct hermes
*hw
= &priv
->hw
;
877 struct iw_param
*param
= &wrqu
->param
;
879 int ret
= -EINPROGRESS
;
881 if (orinoco_lock(priv
, &flags
) != 0)
884 switch (param
->flags
& IW_AUTH_INDEX
) {
885 case IW_AUTH_WPA_VERSION
:
886 case IW_AUTH_CIPHER_PAIRWISE
:
887 case IW_AUTH_CIPHER_GROUP
:
888 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
889 case IW_AUTH_PRIVACY_INVOKED
:
890 case IW_AUTH_DROP_UNENCRYPTED
:
892 * orinoco does not use these parameters
897 /* Management Frame Protection not supported.
898 * Only fail if set to required.
900 if (param
->value
== IW_AUTH_MFP_REQUIRED
)
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 :(
909 priv
->key_mgmt
= param
->value
;
912 case IW_AUTH_TKIP_COUNTERMEASURES
:
913 /* When countermeasures are enabled, shut down the
914 * card; when disabled, re-enable the card. This must
915 * take effect immediately.
917 * TODO: Make sure that the EAPOL message is getting
918 * out before card disabled
921 priv
->tkip_cm_active
= 1;
922 ret
= hermes_disable_port(hw
, 0);
924 priv
->tkip_cm_active
= 0;
925 ret
= hermes_enable_port(hw
, 0);
929 case IW_AUTH_80211_AUTH_ALG
:
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;
938 case IW_AUTH_WPA_ENABLED
:
940 priv
->wpa_enabled
= param
->value
? 1 : 0;
944 /* else silently accept disable of WPA */
945 priv
->wpa_enabled
= 0;
953 orinoco_unlock(priv
, &flags
);
957 static int orinoco_ioctl_get_auth(struct net_device
*dev
,
958 struct iw_request_info
*info
,
959 union iwreq_data
*wrqu
, char *extra
)
961 struct orinoco_private
*priv
= ndev_priv(dev
);
962 struct iw_param
*param
= &wrqu
->param
;
966 if (orinoco_lock(priv
, &flags
) != 0)
969 switch (param
->flags
& IW_AUTH_INDEX
) {
970 case IW_AUTH_KEY_MGMT
:
971 param
->value
= priv
->key_mgmt
;
974 case IW_AUTH_TKIP_COUNTERMEASURES
:
975 param
->value
= priv
->tkip_cm_active
;
978 case IW_AUTH_80211_AUTH_ALG
:
979 if (priv
->wep_restrict
)
980 param
->value
= IW_AUTH_ALG_SHARED_KEY
;
982 param
->value
= IW_AUTH_ALG_OPEN_SYSTEM
;
985 case IW_AUTH_WPA_ENABLED
:
986 param
->value
= priv
->wpa_enabled
;
993 orinoco_unlock(priv
, &flags
);
997 static int orinoco_ioctl_set_genie(struct net_device
*dev
,
998 struct iw_request_info
*info
,
999 union iwreq_data
*wrqu
, char *extra
)
1001 struct orinoco_private
*priv
= ndev_priv(dev
);
1003 unsigned long flags
;
1005 /* cut off at IEEE80211_MAX_DATA_LEN */
1006 if ((wrqu
->data
.length
> IEEE80211_MAX_DATA_LEN
) ||
1007 (wrqu
->data
.length
&& (extra
== NULL
)))
1010 if (wrqu
->data
.length
) {
1011 buf
= kmemdup(extra
, wrqu
->data
.length
, GFP_KERNEL
);
1017 if (orinoco_lock(priv
, &flags
) != 0) {
1022 kfree(priv
->wpa_ie
);
1024 priv
->wpa_ie_len
= wrqu
->data
.length
;
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.
1034 orinoco_unlock(priv
, &flags
);
1038 static int orinoco_ioctl_get_genie(struct net_device
*dev
,
1039 struct iw_request_info
*info
,
1040 union iwreq_data
*wrqu
, char *extra
)
1042 struct orinoco_private
*priv
= ndev_priv(dev
);
1043 unsigned long flags
;
1046 if (orinoco_lock(priv
, &flags
) != 0)
1049 if ((priv
->wpa_ie_len
== 0) || (priv
->wpa_ie
== NULL
)) {
1050 wrqu
->data
.length
= 0;
1054 if (wrqu
->data
.length
< priv
->wpa_ie_len
) {
1059 wrqu
->data
.length
= priv
->wpa_ie_len
;
1060 memcpy(extra
, priv
->wpa_ie
, priv
->wpa_ie_len
);
1063 orinoco_unlock(priv
, &flags
);
1067 static int orinoco_ioctl_set_mlme(struct net_device
*dev
,
1068 struct iw_request_info
*info
,
1069 union iwreq_data
*wrqu
, char *extra
)
1071 struct orinoco_private
*priv
= ndev_priv(dev
);
1072 struct iw_mlme
*mlme
= (struct iw_mlme
*)extra
;
1073 unsigned long flags
;
1076 if (orinoco_lock(priv
, &flags
) != 0)
1079 switch (mlme
->cmd
) {
1080 case IW_MLME_DEAUTH
:
1081 /* silently ignore */
1084 case IW_MLME_DISASSOC
:
1086 ret
= orinoco_hw_disassociate(priv
, mlme
->addr
.sa_data
,
1094 orinoco_unlock(priv
, &flags
);
1098 static int orinoco_ioctl_reset(struct net_device
*dev
,
1099 struct iw_request_info
*info
,
1103 struct orinoco_private
*priv
= ndev_priv(dev
);
1105 if (!capable(CAP_NET_ADMIN
))
1108 if (info
->cmd
== (SIOCIWFIRSTPRIV
+ 0x1)) {
1109 printk(KERN_DEBUG
"%s: Forcing reset!\n", dev
->name
);
1111 /* Firmware reset */
1112 orinoco_reset(&priv
->reset_work
);
1114 printk(KERN_DEBUG
"%s: Force scheduling reset!\n", dev
->name
);
1116 schedule_work(&priv
->reset_work
);
1122 static int orinoco_ioctl_setibssport(struct net_device
*dev
,
1123 struct iw_request_info
*info
,
1128 struct orinoco_private
*priv
= ndev_priv(dev
);
1129 int val
= *((int *) extra
);
1130 unsigned long flags
;
1132 if (orinoco_lock(priv
, &flags
) != 0)
1135 priv
->ibss_port
= val
;
1137 /* Actually update the mode we are using */
1138 set_port_type(priv
);
1140 orinoco_unlock(priv
, &flags
);
1141 return -EINPROGRESS
; /* Call commit handler */
1144 static int orinoco_ioctl_getibssport(struct net_device
*dev
,
1145 struct iw_request_info
*info
,
1149 struct orinoco_private
*priv
= ndev_priv(dev
);
1150 int *val
= (int *) extra
;
1152 *val
= priv
->ibss_port
;
1156 static int orinoco_ioctl_setport3(struct net_device
*dev
,
1157 struct iw_request_info
*info
,
1161 struct orinoco_private
*priv
= ndev_priv(dev
);
1162 int val
= *((int *) extra
);
1164 unsigned long flags
;
1166 if (orinoco_lock(priv
, &flags
) != 0)
1170 case 0: /* Try to do IEEE ad-hoc mode */
1171 if (!priv
->has_ibss
) {
1175 priv
->prefer_port3
= 0;
1179 case 1: /* Try to do Lucent proprietary ad-hoc mode */
1180 if (!priv
->has_port3
) {
1184 priv
->prefer_port3
= 1;
1192 /* Actually update the mode we are using */
1193 set_port_type(priv
);
1197 orinoco_unlock(priv
, &flags
);
1202 static int orinoco_ioctl_getport3(struct net_device
*dev
,
1203 struct iw_request_info
*info
,
1207 struct orinoco_private
*priv
= ndev_priv(dev
);
1208 int *val
= (int *) extra
;
1210 *val
= priv
->prefer_port3
;
1214 static int orinoco_ioctl_setpreamble(struct net_device
*dev
,
1215 struct iw_request_info
*info
,
1219 struct orinoco_private
*priv
= ndev_priv(dev
);
1220 unsigned long flags
;
1223 if (!priv
->has_preamble
)
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
);
1233 if (orinoco_lock(priv
, &flags
) != 0)
1241 orinoco_unlock(priv
, &flags
);
1243 return -EINPROGRESS
; /* Call commit handler */
1246 static int orinoco_ioctl_getpreamble(struct net_device
*dev
,
1247 struct iw_request_info
*info
,
1251 struct orinoco_private
*priv
= ndev_priv(dev
);
1252 int *val
= (int *) extra
;
1254 if (!priv
->has_preamble
)
1257 *val
= priv
->preamble
;
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
,
1271 struct orinoco_private
*priv
= ndev_priv(dev
);
1272 struct hermes
*hw
= &priv
->hw
;
1273 int rid
= data
->flags
;
1276 unsigned long flags
;
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
))
1283 if (rid
< 0xfc00 || rid
> 0xffff)
1286 if (orinoco_lock(priv
, &flags
) != 0)
1289 err
= hw
->ops
->read_ltv(hw
, USER_BAP
, rid
, MAX_RID_LEN
, &length
,
1294 data
->length
= min_t(u16
, HERMES_RECLEN_TO_BYTES(length
),
1298 orinoco_unlock(priv
, &flags
);
1303 /* Commit handler, called after set operations */
1304 static int orinoco_ioctl_commit(struct net_device
*dev
,
1305 struct iw_request_info
*info
,
1309 struct orinoco_private
*priv
= ndev_priv(dev
);
1310 unsigned long flags
;
1316 if (orinoco_lock(priv
, &flags
) != 0)
1319 err
= orinoco_commit(priv
);
1321 orinoco_unlock(priv
, &flags
);
1325 static const struct iw_priv_args orinoco_privtab
[] = {
1326 { SIOCIWFIRSTPRIV
+ 0x0, 0, 0, "force_reset" },
1327 { SIOCIWFIRSTPRIV
+ 0x1, 0, 0, "card_reset" },
1328 { SIOCIWFIRSTPRIV
+ 0x2, IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1330 { SIOCIWFIRSTPRIV
+ 0x3, 0, IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1332 { SIOCIWFIRSTPRIV
+ 0x4, IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1333 0, "set_preamble" },
1334 { SIOCIWFIRSTPRIV
+ 0x5, 0, IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1336 { SIOCIWFIRSTPRIV
+ 0x6, IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1337 0, "set_ibssport" },
1338 { SIOCIWFIRSTPRIV
+ 0x7, 0, IW_PRIV_TYPE_INT
| IW_PRIV_SIZE_FIXED
| 1,
1340 { SIOCIWFIRSTPRIV
+ 0x9, 0, IW_PRIV_TYPE_BYTE
| MAX_RID_LEN
,
1346 * Structures to export the Wireless Handlers
1349 static const iw_handler orinoco_handler
[] = {
1350 IW_HANDLER(SIOCSIWCOMMIT
, (iw_handler
)orinoco_ioctl_commit
),
1351 IW_HANDLER(SIOCGIWNAME
, (iw_handler
)cfg80211_wext_giwname
),
1352 IW_HANDLER(SIOCSIWFREQ
, (iw_handler
)orinoco_ioctl_setfreq
),
1353 IW_HANDLER(SIOCGIWFREQ
, (iw_handler
)orinoco_ioctl_getfreq
),
1354 IW_HANDLER(SIOCSIWMODE
, (iw_handler
)cfg80211_wext_siwmode
),
1355 IW_HANDLER(SIOCGIWMODE
, (iw_handler
)cfg80211_wext_giwmode
),
1356 IW_HANDLER(SIOCSIWSENS
, (iw_handler
)orinoco_ioctl_setsens
),
1357 IW_HANDLER(SIOCGIWSENS
, (iw_handler
)orinoco_ioctl_getsens
),
1358 IW_HANDLER(SIOCGIWRANGE
, (iw_handler
)cfg80211_wext_giwrange
),
1359 IW_HANDLER(SIOCSIWSPY
, iw_handler_set_spy
),
1360 IW_HANDLER(SIOCGIWSPY
, iw_handler_get_spy
),
1361 IW_HANDLER(SIOCSIWTHRSPY
, iw_handler_set_thrspy
),
1362 IW_HANDLER(SIOCGIWTHRSPY
, iw_handler_get_thrspy
),
1363 IW_HANDLER(SIOCSIWAP
, (iw_handler
)orinoco_ioctl_setwap
),
1364 IW_HANDLER(SIOCGIWAP
, (iw_handler
)orinoco_ioctl_getwap
),
1365 IW_HANDLER(SIOCSIWSCAN
, (iw_handler
)cfg80211_wext_siwscan
),
1366 IW_HANDLER(SIOCGIWSCAN
, (iw_handler
)cfg80211_wext_giwscan
),
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
),
1371 IW_HANDLER(SIOCSIWRTS
, (iw_handler
)cfg80211_wext_siwrts
),
1372 IW_HANDLER(SIOCGIWRTS
, (iw_handler
)cfg80211_wext_giwrts
),
1373 IW_HANDLER(SIOCSIWFRAG
, (iw_handler
)cfg80211_wext_siwfrag
),
1374 IW_HANDLER(SIOCGIWFRAG
, (iw_handler
)cfg80211_wext_giwfrag
),
1375 IW_HANDLER(SIOCGIWRETRY
, (iw_handler
)cfg80211_wext_giwretry
),
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
),
1391 Added typecasting since we no longer use iwreq_data -- Moustafa
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
,
1405 const struct iw_handler_def orinoco_handler_def
= {
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
,