cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wext.c (34783B)


      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 */
     30static 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	kfree_sensitive(priv->keys[index].key);
     35	kfree_sensitive(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((void *)priv->keys[index].key, key, key_len);
     56	if (seq_len)
     57		memcpy((void *)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) ?
     66			WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
     67		break;
     68
     69	case ORINOCO_ALG_NONE:
     70	default:
     71		priv->keys[index].cipher = 0;
     72		break;
     73	}
     74
     75	return 0;
     76
     77free_key:
     78	kfree(priv->keys[index].key);
     79	priv->keys[index].key = NULL;
     80
     81nomem:
     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
     89static 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,
    136					 HERMES_RID_COMMSQUALITY, &cq);
    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 =
    143				IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
    144		}
    145	}
    146
    147	orinoco_unlock(priv, &flags);
    148	return wstats;
    149}
    150
    151/********************************************************************/
    152/* Wireless extensions                                              */
    153/********************************************************************/
    154
    155static 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		eth_zero_addr(priv->desired_bssid);
    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
    214static 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
    235static 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
    326static 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
    362static 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
    393static 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
    421static 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_frequency_to_channel(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 |
    462					    HERMES_TEST_SET_CHANNEL,
    463					chan, NULL);
    464	}
    465	orinoco_unlock(priv, &flags);
    466
    467	return err;
    468}
    469
    470static 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
    489static 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,
    506				  HERMES_RID_CNFSYSTEMSCALE, &val);
    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
    518static 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
    541static 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
    575static 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
    611static 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
    665static 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,
    685				  HERMES_RID_CNFMAXSLEEPDURATION, &period);
    686	if (err)
    687		goto out;
    688
    689	err = hermes_read_wordrec(hw, USER_BAP,
    690				  HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
    691	if (err)
    692		goto out;
    693
    694	err = hermes_read_wordrec(hw, USER_BAP,
    695				  HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
    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
    719static 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:
    761			priv->encode_alg = ORINOCO_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
    783			priv->encode_alg = ORINOCO_ALG_TKIP;
    784
    785			if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
    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,
    790					      ORINOCO_SEQ_LEN);
    791
    792			err = __orinoco_hw_set_tkip_key(priv, idx,
    793				 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
    794				 priv->keys[idx].key, priv->keys[idx].key_len,
    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
    813static 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
    871static 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:
    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:
    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
    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.
    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
    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;
    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
    957static 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
    974	case IW_AUTH_TKIP_COUNTERMEASURES:
    975		param->value = priv->tkip_cm_active;
    976		break;
    977
    978	case IW_AUTH_80211_AUTH_ALG:
    979		if (priv->wep_restrict)
    980			param->value = IW_AUTH_ALG_SHARED_KEY;
    981		else
    982			param->value = IW_AUTH_ALG_OPEN_SYSTEM;
    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
    997static 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
   1038static 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
   1062out:
   1063	orinoco_unlock(priv, &flags);
   1064	return err;
   1065}
   1066
   1067static 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
   1098static 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
   1122static 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
   1144static 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
   1156static 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
   1202static 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
   1214static 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
   1246static 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. */
   1266static 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 */
   1304static 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
   1325static 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,
   1329	  0, "set_port3" },
   1330	{ SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
   1331	  "get_port3" },
   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,
   1335	  "get_preamble" },
   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,
   1339	  "get_ibssport" },
   1340	{ SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
   1341	  "get_rid" },
   1342};
   1343
   1344
   1345/*
   1346 * Structures to export the Wireless Handlers
   1347 */
   1348
   1349static 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),
   1387};
   1388
   1389
   1390/*
   1391  Added typecasting since we no longer use iwreq_data -- Moustafa
   1392 */
   1393static 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
   1405const 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,
   1413};