New upstream snapshot.
[debian/madwifi.git] / net80211 / ieee80211_wireless.c
1 /*-
2  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  * 3. Neither the names of the above-listed copyright holders nor the names
16  *    of any contributors may be used to endorse or promote products derived
17  *    from this software without specific prior written permission.
18  *
19  * Alternatively, this software may be distributed under the terms of the
20  * GNU General Public License ("GPL") version 2 as published by the Free
21  * Software Foundation.
22  *
23  * NO WARRANTY
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34  * THE POSSIBILITY OF SUCH DAMAGES.
35  *
36  * $Id: ieee80211_wireless.c 4156 2011-08-03 01:07:44Z proski $
37  */
38
39 /*
40  * Wireless extensions support for 802.11 common code.
41  */
42 #if !defined(AUTOCONF_INCLUDED) && !defined(CONFIG_LOCALVERSION)
43 #include <linux/config.h>
44 #endif
45
46 #include <linux/version.h>
47 #include <linux/module.h>
48 #include <linux/netdevice.h>
49 #include <linux/utsname.h>
50 #include <linux/if_arp.h>               /* XXX for ARPHRD_ETHER */
51 #include <linux/delay.h>
52
53 #include <linux/wireless.h>
54 #include <net/iw_handler.h>
55
56 #if WIRELESS_EXT < 14
57 #error "Wireless extensions v14 or better is needed."
58 #endif
59
60 #include <asm/uaccess.h>
61
62 #include <net80211/if_media.h>
63 #include <net80211/if_athproto.h>
64
65 #include <net80211/ieee80211_var.h>
66 #include <net80211/ieee80211_linux.h>
67
68 #define IS_UP(_dev) \
69         (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
70 #define IS_UP_AUTO(_vap) \
71         (IS_UP((_vap)->iv_dev) && \
72          (_vap)->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO)
73 #define RESCAN  1
74
75 static void
76 pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt);
77
78 static void
79 preempt_scan(struct net_device *dev, int max_grace, int max_wait)
80 {
81         struct ieee80211vap *vap = netdev_priv(dev);
82         struct ieee80211com *ic = vap->iv_ic;
83         int total_delay = 0;
84         int canceled = 0, ready = 0;
85         while (!ready && total_delay < max_grace + max_wait) {
86           if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
87             ready = 1;
88           } else {
89             if (!canceled && total_delay > max_grace) {
90               /* 
91                  Cancel any existing active scan, so that any new parameters
92                  in this scan ioctl (or the defaults) can be honored, then
93                  wait around a while to see if the scan cancels properly.
94               */
95               IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
96                                 "%s: cancel pending scan request\n", __func__);
97               (void) ieee80211_cancel_scan(vap);
98               canceled = 1;
99             }
100             mdelay (1);
101             total_delay += 1;
102           }
103         }
104         if (!ready) {
105           IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 
106                             "%s: Timeout canceling current scan.\n", 
107                             __func__); 
108         }
109 }
110         
111 static struct iw_statistics *
112 ieee80211_iw_getstats(struct net_device *dev)
113 {
114         struct ieee80211vap *vap = netdev_priv(dev);
115         struct iw_statistics *is = &vap->iv_iwstats;
116         struct ieee80211com *ic = vap->iv_ic;
117         
118         set_quality(&is->qual, ieee80211_getrssi(vap->iv_ic), 
119                         ic->ic_channoise);
120         is->status = vap->iv_state;
121         is->discard.nwid = vap->iv_stats.is_rx_wrongbss +
122                 vap->iv_stats.is_rx_ssidmismatch;
123         is->discard.code = vap->iv_stats.is_rx_wepfail +
124                 vap->iv_stats.is_rx_decryptcrc;
125         is->discard.fragment = 0;
126         is->discard.retries = 0;
127         is->discard.misc = 0;
128
129         is->miss.beacon = 0;
130
131         return is;
132 }
133
134 static int
135 ieee80211_ioctl_giwname(struct net_device *dev, struct iw_request_info *info,
136         char *name, char *extra)
137 {
138         struct ieee80211vap *vap = netdev_priv(dev);
139         struct ieee80211_channel *c = vap->iv_ic->ic_curchan;
140
141         if (IEEE80211_IS_CHAN_108G(c))
142                 strncpy(name, "IEEE 802.11Tg", IFNAMSIZ);
143         else if (IEEE80211_IS_CHAN_108A(c))
144                 strncpy(name, "IEEE 802.11Ta", IFNAMSIZ);
145         else if (IEEE80211_IS_CHAN_TURBO(c))
146                 strncpy(name, "IEEE 802.11T", IFNAMSIZ);
147         else if (IEEE80211_IS_CHAN_ANYG(c))
148                 strncpy(name, "IEEE 802.11g", IFNAMSIZ);
149         else if (IEEE80211_IS_CHAN_A(c))
150                 strncpy(name, "IEEE 802.11a", IFNAMSIZ);
151         else if (IEEE80211_IS_CHAN_B(c))
152                 strncpy(name, "IEEE 802.11b", IFNAMSIZ);
153         else
154                 strncpy(name, "IEEE 802.11", IFNAMSIZ);
155         /* XXX FHSS */
156         return 0;
157 }
158
159 /*
160  * Get a key index from a request.  If nothing is
161  * specified in the request we use the current xmit
162  * key index.  Otherwise we just convert the index
163  * to be base zero.
164  */
165 static int
166 getiwkeyix(struct ieee80211vap *vap, const struct iw_point* erq, int *kix)
167 {
168         int kid;
169
170         kid = erq->flags & IW_ENCODE_INDEX;
171         if (kid < 1 || kid > IEEE80211_WEP_NKID) {
172                 kid = vap->iv_def_txkey;
173                 if (kid == IEEE80211_KEYIX_NONE)
174                         kid = 0;
175         } else
176                 --kid;
177         if (0 <= kid && kid < IEEE80211_WEP_NKID) {
178                 *kix = kid;
179                 return 0;
180         } else
181                 return -EINVAL;
182 }
183
184 static int
185 ieee80211_ioctl_siwencode(struct net_device *dev,
186         struct iw_request_info *info, struct iw_point *erq, char *keybuf)
187 {
188         struct ieee80211vap *vap = netdev_priv(dev);
189         int kid, error;
190         int wepchange = 0;
191
192         if ((erq->flags & IW_ENCODE_DISABLED) == 0) {
193                 /*
194                  * Enable crypto, set key contents, and
195                  * set the default transmit key.
196                  */
197                 error = getiwkeyix(vap, erq, &kid);
198                 if (error < 0)
199                         return error;
200                 if (erq->length > IEEE80211_KEYBUF_SIZE)
201                         return -EINVAL;
202                 /* XXX no way to install 0-length key */
203                 ieee80211_key_update_begin(vap);
204                 if (erq->length > 0) {
205                         struct ieee80211_key *k = &vap->iv_nw_keys[kid];
206
207                         /*
208                          * Set key contents.  This interface only supports WEP.
209                          * Indicate intended key index.                  
210                          */
211                         k->wk_keyix = kid;
212                         if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP,
213                             IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
214                                 k->wk_keylen = erq->length;
215                                 memcpy(k->wk_key, keybuf, erq->length);
216                                 memset(k->wk_key + erq->length, 0,
217                                         IEEE80211_KEYBUF_SIZE - erq->length);
218                                 if (!ieee80211_crypto_setkey(vap, k, vap->iv_myaddr, NULL))
219                                         error = -EINVAL;                /* XXX */
220                         } else
221                                 error = -EINVAL;
222                 } else {
223                         /*
224                          * When the length is zero the request only changes
225                          * the default transmit key.  Verify the new key has
226                          * a non-zero length.
227                          */
228                         if (vap->iv_nw_keys[kid].wk_keylen == 0)
229                                 error = -EINVAL;
230                 }
231                 if (error == 0) {
232                         /*
233                          * The default transmit key is only changed when:
234                          * 1. Privacy is enabled and no key matter is
235                          *    specified.
236                          * 2. Privacy is currently disabled.
237                          * This is deduced from the iwconfig man page.
238                          */
239                         if (erq->length == 0 ||
240                             (vap->iv_flags & IEEE80211_F_PRIVACY) == 0)
241                                 vap->iv_def_txkey = kid;
242                         wepchange = (vap->iv_flags & IEEE80211_F_PRIVACY) == 0;
243                         vap->iv_flags |= IEEE80211_F_PRIVACY;
244                 }
245                 ieee80211_key_update_end(vap);
246         } else {
247                 if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0)
248                         return 0;
249                 vap->iv_flags &= ~IEEE80211_F_PRIVACY;
250                 wepchange = 1;
251                 error = 0;
252         }
253         if (error == 0) {
254                 /* Set policy for unencrypted frames */ 
255                 if ((erq->flags & IW_ENCODE_OPEN) && 
256                     (!(erq->flags & IW_ENCODE_RESTRICTED))) {
257                         vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
258                 } else if (!(erq->flags & IW_ENCODE_OPEN) && 
259                          (erq->flags & IW_ENCODE_RESTRICTED)) {
260                         vap->iv_flags |= IEEE80211_F_DROPUNENC;
261                 } else {
262                         /* Default policy */
263                         if (vap->iv_flags & IEEE80211_F_PRIVACY) 
264                                 vap->iv_flags |= IEEE80211_F_DROPUNENC;
265                         else
266                                 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
267                 }       
268         }
269         if (error == 0 && IS_UP(vap->iv_dev)) {
270                 /*
271                  * Device is up and running; we must kick it to
272                  * effect the change.  If we're enabling/disabling
273                  * crypto use then we must re-initialize the device
274                  * so the 802.11 state machine is reset.  Otherwise
275                  * the key state should have been updated above.
276                  */
277                 if (wepchange && IS_UP_AUTO(vap))
278                         ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
279         }
280 #ifdef ATH_SUPERG_XR
281         /* set the same params on the xr vap device if exists */
282         if (!error && vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
283                 ieee80211_ioctl_siwencode(vap->iv_xrvap->iv_dev, info, erq, keybuf);
284 #endif
285         return error;
286 }
287
288 static int
289 ieee80211_ioctl_giwencode(struct net_device *dev, struct iw_request_info *info,
290         struct iw_point *erq, char *key)
291 {
292         struct ieee80211vap *vap = netdev_priv(dev);
293         struct ieee80211_key *k;
294         int error, kid;
295
296         if (vap->iv_flags & IEEE80211_F_PRIVACY) {
297                 error = getiwkeyix(vap, erq, &kid);
298                 if (error < 0)
299                         return error;
300                 k = &vap->iv_nw_keys[kid];
301                 /* XXX no way to return cipher/key type */
302
303                 erq->flags = kid + 1;                   /* NB: base 1 */
304                 if (erq->length > k->wk_keylen)
305                         erq->length = k->wk_keylen;
306                 memcpy(key, k->wk_key, erq->length);
307                 erq->flags |= IW_ENCODE_ENABLED;
308         } else {
309                 erq->length = 0;
310                 erq->flags = IW_ENCODE_DISABLED;
311         }
312         if (vap->iv_flags & IEEE80211_F_DROPUNENC)
313                 erq->flags |= IW_ENCODE_RESTRICTED;
314         else
315                 erq->flags |= IW_ENCODE_OPEN;
316         return 0;
317 }
318
319 #ifndef ifr_media
320 #define ifr_media       ifr_ifru.ifru_ivalue
321 #endif
322
323 static int
324 ieee80211_ioctl_siwrate(struct net_device *dev, struct iw_request_info *info,
325         struct iw_param *rrq, char *extra)
326 {
327         static const u_int mopts[] = {
328                 IFM_AUTO,
329                 IFM_IEEE80211_11A,
330                 IFM_IEEE80211_11B,
331                 IFM_IEEE80211_11G,
332                 IFM_IEEE80211_FH,
333                 IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
334                 IFM_IEEE80211_11G | IFM_IEEE80211_TURBO,
335         };
336         struct ieee80211vap *vap = netdev_priv(dev);
337         struct ieee80211com *ic = vap->iv_ic;
338         struct ifreq ifr;
339         int rate, retv;
340
341         if (vap->iv_media.ifm_cur == NULL)
342                 return -EINVAL;
343         memset(&ifr, 0, sizeof(ifr));
344         ifr.ifr_media = vap->iv_media.ifm_cur->ifm_media &~ (IFM_MMASK|IFM_TMASK);
345         ifr.ifr_media |= mopts[vap->iv_des_mode];
346         if (rrq->fixed) {
347                 /* XXX fudge checking rates */
348                 rate = ieee80211_rate2media(ic, 2 * rrq->value / 1000000,
349                         vap->iv_des_mode);
350                 if (rate == IFM_AUTO)           /* NB: unknown rate */
351                         return -EINVAL;
352         } else
353                 rate = IFM_AUTO;
354         ifr.ifr_media |= IFM_SUBTYPE(rate);
355
356         /* refresh media capabilities based on channel */
357         ifmedia_removeall(&vap->iv_media);
358         (void) ieee80211_media_setup(ic, &vap->iv_media,
359                 vap->iv_caps, vap->iv_media.ifm_change, vap->iv_media.ifm_status);
360
361         retv = ifmedia_ioctl(vap->iv_dev, &ifr, &vap->iv_media, SIOCSIFMEDIA);
362         if (retv == -ENETRESET)
363                 retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
364         return retv;
365 }
366
367 static int
368 ieee80211_ioctl_giwrate(struct net_device *dev, struct iw_request_info *info,
369         struct iw_param *rrq, char *extra)
370 {
371         struct ieee80211vap *vap = netdev_priv(dev);
372         struct ifmediareq imr;
373         int rate;
374
375         memset(&imr, 0, sizeof(imr));
376         vap->iv_media.ifm_status(vap->iv_dev, &imr);
377
378         rrq->fixed = IFM_SUBTYPE(vap->iv_media.ifm_media) != IFM_AUTO;
379         /* media status will have the current xmit rate if available */
380         rate = ieee80211_media2rate(imr.ifm_active);
381         if (rate == -1)         /* IFM_AUTO */
382                 rate = 0;
383         rrq->value = 1000000 * (rate / 2);
384
385         return 0;
386 }
387
388 static int
389 ieee80211_ioctl_siwsens(struct net_device *dev, struct iw_request_info *info,
390         struct iw_param *sens, char *extra)
391 {
392         return -EOPNOTSUPP;
393 }
394
395 static int
396 ieee80211_ioctl_giwsens(struct net_device *dev, struct iw_request_info *info,
397         struct iw_param *sens, char *extra)
398 {
399         sens->value = 1;
400         sens->fixed = 1;
401
402         return 0;
403 }
404
405 static int
406 ieee80211_ioctl_siwrts(struct net_device *dev, struct iw_request_info *info,
407         struct iw_param *rts, char *extra)
408 {
409         struct ieee80211vap *vap = netdev_priv(dev);
410         struct ieee80211com *ic = vap->iv_ic;
411         u16 val;
412
413         if (rts->disabled)
414                 val = IEEE80211_RTS_MAX;
415         else if (IEEE80211_RTS_MIN <= rts->value &&
416             rts->value <= IEEE80211_RTS_MAX)
417                 val = rts->value;
418         else
419                 return -EINVAL;
420         if (val != vap->iv_rtsthreshold) {
421                 vap->iv_rtsthreshold = val;
422                 if (IS_UP(vap->iv_dev))
423                         return ic->ic_reset(ic->ic_dev);
424         }
425         return 0;
426 }
427
428 static int
429 ieee80211_ioctl_giwrts(struct net_device *dev, struct iw_request_info *info,
430         struct iw_param *rts, char *extra)
431 {
432         struct ieee80211vap *vap = netdev_priv(dev);
433
434         rts->value = vap->iv_rtsthreshold;
435         rts->disabled = (rts->value == IEEE80211_RTS_MAX);
436         rts->fixed = 1;
437
438         return 0;
439 }
440
441 static int
442 ieee80211_ioctl_siwfrag(struct net_device *dev, struct iw_request_info *info,
443         struct iw_param *rts, char *extra)
444 {
445         struct ieee80211vap *vap = netdev_priv(dev);
446         struct ieee80211com *ic = vap->iv_ic;
447         u16 val;
448
449         if (rts->disabled)
450                 val = 2346;
451         else if (rts->value < 256 || rts->value > 2346)
452                 return -EINVAL;
453         else
454                 val = (rts->value & ~0x1);
455
456         if (val != vap->iv_fragthreshold) {
457                 vap->iv_fragthreshold = val;
458                 if (IS_UP(ic->ic_dev))
459                         return ic->ic_reset(ic->ic_dev);
460         }
461         return 0;
462 }
463
464 static int
465 ieee80211_ioctl_giwfrag(struct net_device *dev, struct iw_request_info *info,
466         struct iw_param *rts, char *extra)
467 {
468         struct ieee80211vap *vap = netdev_priv(dev);
469
470         rts->value = vap->iv_fragthreshold;
471         rts->disabled = (rts->value == 2346);
472         rts->fixed = 1;
473
474         return 0;
475 }
476
477 static int
478 ieee80211_ioctl_siwap(struct net_device *dev, struct iw_request_info *info,
479         struct sockaddr *ap_addr, char *extra)
480 {
481         struct ieee80211vap *vap = netdev_priv(dev);
482
483         /* NB: should not be set when in AP mode */
484         if (vap->iv_opmode == IEEE80211_M_HOSTAP)
485                 return -EINVAL;
486
487         if (vap->iv_opmode == IEEE80211_M_WDS)
488                 IEEE80211_ADDR_COPY(vap->wds_mac, &ap_addr->sa_data);
489
490         /* 
491          * zero address corresponds to 'iwconfig ath0 ap off', which means 
492          * enable automatic choice of AP without actually forcing a
493          * reassociation.  
494          *
495          * broadcast address corresponds to 'iwconfig ath0 ap any', which
496          * means scan for the current best AP.
497          *
498          * anything else specifies a particular AP.
499          */
500         vap->iv_flags &= ~IEEE80211_F_DESBSSID;
501         if (!IEEE80211_ADDR_NULL(&ap_addr->sa_data)) {
502                 if (!IEEE80211_ADDR_EQ(vap->iv_des_bssid, (u_int8_t*) "\xff\xff\xff\xff\xff\xff"))
503                         vap->iv_flags |= IEEE80211_F_DESBSSID;
504                 
505                 IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data);
506                 if (IS_UP_AUTO(vap))
507                         ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
508         }
509         return 0;
510 }
511
512 static int
513 ieee80211_ioctl_giwap(struct net_device *dev, struct iw_request_info *info,
514         struct sockaddr *ap_addr, char *extra)
515 {
516         struct ieee80211vap *vap = netdev_priv(dev);
517
518         if (vap->iv_flags & IEEE80211_F_DESBSSID)
519                 IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_des_bssid);
520         else {
521                 if (vap->iv_state == IEEE80211_S_RUN)
522                         if (vap->iv_opmode != IEEE80211_M_WDS) 
523                                 IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_bss->ni_bssid);
524                         else
525                                 IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->wds_mac);
526                 else
527                         IEEE80211_ADDR_SET_NULL(&ap_addr->sa_data);
528         }
529         ap_addr->sa_family = ARPHRD_ETHER;
530         return 0;
531 }
532
533 static int
534 ieee80211_ioctl_siwnickn(struct net_device *dev, struct iw_request_info *info,
535         struct iw_point *data, char *nickname)
536 {
537         struct ieee80211vap *vap = netdev_priv(dev);
538
539         if (data->length > IEEE80211_NWID_LEN)
540                 return -EINVAL;
541
542         memset(vap->iv_nickname, 0, IEEE80211_NWID_LEN);
543         memcpy(vap->iv_nickname, nickname, data->length);
544         vap->iv_nicknamelen = data->length;
545
546         return 0;
547 }
548
549 static int
550 ieee80211_ioctl_giwnickn(struct net_device *dev, struct iw_request_info *info,
551         struct iw_point *data, char *nickname)
552 {
553         struct ieee80211vap *vap = netdev_priv(dev);
554
555         if (data->length > vap->iv_nicknamelen + 1)
556                 data->length = vap->iv_nicknamelen + 1;
557         if (data->length > 0) {
558                 memcpy(nickname, vap->iv_nickname, data->length - 1); /* XXX: strcpy? */
559                 nickname[data->length-1] = '\0';
560         }
561         return 0;
562 }
563
564 static int
565 find11gchannel(struct ieee80211com *ic, int i, int freq)
566 {
567         for (; i < ic->ic_nchans; i++) {
568                 const struct ieee80211_channel *c = &ic->ic_channels[i];
569                 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
570                         return 1;
571         }
572         return 0;
573 }
574
575 static struct ieee80211_channel *
576 findchannel(struct ieee80211com *ic, int ieee, int mode)
577 {
578         static const u_int chanflags[] = {
579                 0,                      /* IEEE80211_MODE_AUTO */
580                 IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
581                 IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
582                 IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
583                 IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
584                 IEEE80211_CHAN_108A,    /* IEEE80211_MODE_TURBO_A */
585                 IEEE80211_CHAN_108G,    /* IEEE80211_MODE_TURBO_G */
586                 IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */
587         };
588         u_int modeflags;
589         int i;
590
591         modeflags = chanflags[mode];
592         for (i = 0; i < ic->ic_nchans; i++) {
593                 struct ieee80211_channel *c = &ic->ic_channels[i];
594
595                 if (c->ic_ieee != ieee)
596                         continue;
597                 if (mode == IEEE80211_MODE_AUTO) {
598                         /* ignore turbo channels for autoselect */
599                         if (!(ic->ic_ath_cap & IEEE80211_ATHC_TURBOP) &&
600                             IEEE80211_IS_CHAN_TURBO(c))
601                                 continue;
602                         /*
603                          * XXX special-case 11b/g channels so we
604                          *     always select the g channel if both
605                          *     are present.
606                          */
607                         if (!IEEE80211_IS_CHAN_B(c) ||
608                             !find11gchannel(ic, i + 1, c->ic_freq))
609                                 return c;
610                 } else {
611                         if ((c->ic_flags & modeflags) == modeflags)
612                                 return c;
613                 }
614         }
615         return NULL;
616 }
617
618 #define IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX
619 static int
620 ieee80211_check_mode_consistency(struct ieee80211com *ic, int mode,
621         struct ieee80211_channel *c)
622 {
623         if (c == IEEE80211_CHAN_ANYC)
624                 return 0;
625         switch (mode) {
626         case IEEE80211_MODE_11B:
627                 if (IEEE80211_IS_CHAN_B(c)) 
628                         return 0;
629                 else
630                         return 1;
631                 break;
632         case IEEE80211_MODE_11G:
633                 if (IEEE80211_IS_CHAN_ANYG(c)) 
634                         return 0;
635                 else
636                         return 1;
637                 break;
638         case IEEE80211_MODE_11A:
639                 if (IEEE80211_IS_CHAN_A(c)) 
640                         return 0;
641                 else
642                         return 1;
643                 break;
644         case IEEE80211_MODE_TURBO_STATIC_A:
645                 if (IEEE80211_IS_CHAN_A(c) && IEEE80211_IS_CHAN_STURBO(c)) 
646                         return 0;
647                 else
648                         return 1;
649                 break;
650         case IEEE80211_MODE_AUTO:
651                 return 0;
652                 break;
653         }
654         return 1;
655 }
656 #undef  IEEE80211_MODE_TURBO_STATIC_A
657
658 static int
659 ieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
660         struct iw_freq *freq, char *extra)
661 {
662         struct ieee80211vap *vap = netdev_priv(dev);
663         struct ieee80211com *ic = vap->iv_ic;
664         struct ieee80211_channel *c, *c2;
665         int i;
666         
667         if (freq->e > 1)
668                 return -EINVAL;
669         if (freq->e == 1)
670                 i = (ic->ic_mhz2ieee)(ic, freq->m / 100000, 0);
671         else
672                 i = freq->m;
673         if (i != 0) {
674                 if (i > IEEE80211_CHAN_MAX)
675                         return -EINVAL;
676                 c = findchannel(ic, i, vap->iv_des_mode);
677                 if (c == NULL) {
678                         c = findchannel(ic, i, IEEE80211_MODE_AUTO);
679                         if (c == NULL)                  /* no channel */
680                                 return -EINVAL;
681                 }
682                 /*
683                  * Fine tune channel selection based on desired mode:
684                  *   if 11b is requested, find the 11b version of any
685                  *      11g channel returned,
686                  *   if static turbo, find the turbo version of any
687                  *      11a channel return,
688                  *   otherwise we should be ok with what we've got.
689                  */
690                 switch (vap->iv_des_mode) {
691                 case IEEE80211_MODE_11B:
692                         if (IEEE80211_IS_CHAN_ANYG(c)) {
693                                 c2 = findchannel(ic, i, IEEE80211_MODE_11B);
694                                 /* NB: should not happen, =>'s 11g w/o 11b */
695                                 if (c2 != NULL)
696                                         c = c2;
697                         }
698                         break;
699                 case IEEE80211_MODE_TURBO_A:
700                         if (IEEE80211_IS_CHAN_A(c)) {
701                                 c2 = findchannel(ic, i, IEEE80211_MODE_TURBO_A);
702                                 if (c2 != NULL)
703                                         c = c2;
704                         }
705                         break;
706                 default:                /* NB: no static turboG */
707                         break;
708                 }
709                 if (ieee80211_check_mode_consistency(ic,vap->iv_des_mode,c)) {
710                         if (vap->iv_opmode == IEEE80211_M_HOSTAP)
711                                 return -EINVAL;
712                 }
713                 if (vap->iv_state == IEEE80211_S_RUN && c == ic->ic_bsschan)
714                         return 0;                       /* no change, return */
715
716                 /* Don't allow to change to channel with radar found */
717                 if (c->ic_flags & IEEE80211_CHAN_RADAR)
718                         return -EINVAL;
719
720                 /*
721                  * Mark desired channel and if running force a
722                  * radio change.
723                  */
724                 vap->iv_des_chan = c;
725         } else {
726                 /*
727                  * Intepret channel 0 to mean "no desired channel";
728                  * otherwise there's no way to undo fixing the desired
729                  * channel.
730                  */
731                 if (vap->iv_des_chan == IEEE80211_CHAN_ANYC)
732                         return 0;
733                 vap->iv_des_chan = IEEE80211_CHAN_ANYC;
734         }
735 #if 0
736         if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
737                 int mode = ieee80211_chan2mode(vap->iv_des_chan);
738                 if (mode != ic->ic_curmode)
739                         ieee80211_setmode(ic, mode);
740         }
741 #endif
742         if ((vap->iv_opmode == IEEE80211_M_MONITOR ||
743             vap->iv_opmode == IEEE80211_M_WDS) &&
744             vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
745                 /* Monitor and wds modes can switch directly. */
746                 ic->ic_curchan = vap->iv_des_chan;
747                 if (vap->iv_state == IEEE80211_S_RUN) {
748                         ic->ic_set_channel(ic);
749                 }
750         } else if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
751                 /* Need to use channel switch announcement on beacon if we are 
752                  * up and running.  We use ic_set_channel directly if we are 
753                  * "running" but not "up".  Otherwise, iv_des_chan will take
754                  * effect when we are transitioned to RUN state later. */
755                 if (IS_UP(vap->iv_dev)) {
756                         pre_announced_chanswitch(dev, ieee80211_chan2ieee(ic, vap->iv_des_chan), IEEE80211_DEFAULT_CHANCHANGE_TBTT_COUNT);
757                 }
758                 else if (vap->iv_state == IEEE80211_S_RUN) {
759                         ic->ic_curchan = vap->iv_des_chan;
760                         ic->ic_set_channel(ic);
761                 }
762         } else {
763                 /* Need to go through the state machine in case we need
764                  * to reassociate or the like.  The state machine will
765                  * pickup the desired channel and avoid scanning. */
766                 if (IS_UP_AUTO(vap))
767                         ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
768         }
769         return 0;
770 }
771
772 static int
773 ieee80211_ioctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
774         struct iw_freq *freq, char *extra)
775 {
776         struct ieee80211vap *vap = netdev_priv(dev);
777         struct ieee80211com *ic = vap->iv_ic;
778
779         if (vap->iv_state == IEEE80211_S_RUN &&
780             vap->iv_opmode != IEEE80211_M_MONITOR) {
781                 /*
782                  * NB: use curchan for monitor mode so you can see
783                  *     manual scanning by apps like kismet.
784                  */
785                 KASSERT(ic->ic_bsschan != IEEE80211_CHAN_ANYC,
786                         ("bss channel not set"));
787                 freq->m = ic->ic_bsschan->ic_freq;
788         } else if (vap->iv_state != IEEE80211_S_INIT)   /* e.g. when scanning */
789                 freq->m = ic->ic_curchan->ic_freq;
790         else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC)
791                 freq->m = vap->iv_des_chan->ic_freq;
792         else
793                 freq->m = 0;
794         freq->m *= 100000;
795         freq->e = 1;
796
797         return 0;
798 }
799
800 #ifdef ATH_SUPERG_XR 
801 /*
802  * Copy desired ssid state from one vap to another.
803  */
804 static void
805 copy_des_ssid(struct ieee80211vap *dst, const struct ieee80211vap *src)
806 {
807         dst->iv_des_nssid = src->iv_des_nssid;
808         memcpy(dst->iv_des_ssid, src->iv_des_ssid,
809             src->iv_des_nssid * sizeof(src->iv_des_ssid[0]));
810 }
811 #endif /* ATH_SUPERG_XR */
812
813 static int
814 ieee80211_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info,
815         struct iw_point *data, char *ssid)
816 {
817         struct ieee80211vap *vap = netdev_priv(dev);
818
819         if (vap->iv_opmode == IEEE80211_M_WDS)
820                 return -EOPNOTSUPP;
821
822         if (data->flags == 0)           /* ANY */
823                 vap->iv_des_nssid = 0;
824         else {
825                 if (data->length > IEEE80211_NWID_LEN)
826                         data->length = IEEE80211_NWID_LEN;
827                 /* NB: always use entry 0 */
828                 memcpy(vap->iv_des_ssid[0].ssid, ssid, data->length);
829                 vap->iv_des_ssid[0].len = data->length;
830                 vap->iv_des_nssid = 1;
831                 /*
832                  * Deduct a trailing \0 since iwconfig passes a string
833                  * length that includes this.  Unfortunately this means
834                  * that specifying a string with multiple trailing \0's
835                  * won't be handled correctly.  Not sure there's a good
836                  * solution; the API is botched (the length should be
837                  * exactly those bytes that are meaningful and not include
838                  * extraneous stuff).
839                  */
840                 if (data->length > 0 &&
841                     vap->iv_des_ssid[0].ssid[data->length - 1] == '\0')
842                         vap->iv_des_ssid[0].len--;
843         }
844 #ifdef ATH_SUPERG_XR 
845         if (vap->iv_xrvap != NULL && !(vap->iv_flags & IEEE80211_F_XR)) {
846                 if (data->flags == 0)
847                         vap->iv_des_nssid = 0;
848                 else
849                         copy_des_ssid(vap->iv_xrvap, vap);
850         }
851 #endif
852         return IS_UP_AUTO(vap) ? ieee80211_init(vap->iv_dev, RESCAN) : 0;
853 }
854
855 static int
856 ieee80211_ioctl_giwessid(struct net_device *dev, struct iw_request_info *info,
857         struct iw_point *data, char *essid)
858 {
859         struct ieee80211vap *vap = netdev_priv(dev);
860
861         if (vap->iv_opmode == IEEE80211_M_WDS)
862                 return -EOPNOTSUPP;
863
864         data->flags = 1;                /* active */
865         if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
866                 if (vap->iv_des_nssid > 0) {
867                         if (data->length > vap->iv_des_ssid[0].len)
868                                 data->length = vap->iv_des_ssid[0].len;
869                         memcpy(essid, vap->iv_des_ssid[0].ssid, data->length);
870                 } else
871                         data->length = 0;
872         } else {
873                 if (vap->iv_des_nssid == 0) {
874                         if (data->length > vap->iv_bss->ni_esslen)
875                                 data->length = vap->iv_bss->ni_esslen;
876                         memcpy(essid, vap->iv_bss->ni_essid, data->length);
877                 } else {
878                         if (data->length > vap->iv_des_ssid[0].len)
879                                 data->length = vap->iv_des_ssid[0].len;
880                         memcpy(essid, vap->iv_des_ssid[0].ssid, data->length);
881                 }
882         }
883         return 0;
884 }
885
886 static int
887 ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,
888         struct iw_point *data, char *extra)
889 {
890         struct ieee80211vap *vap = netdev_priv(dev);
891         struct ieee80211com *ic = vap->iv_ic;
892         struct ieee80211_node *ni = vap->iv_bss;
893         struct iw_range *range = (struct iw_range *) extra;
894         struct ieee80211_rateset *rs;
895         u_int8_t reported[IEEE80211_CHAN_BYTES];        /* XXX stack usage? */
896         int i, r;
897         int step = 0;
898
899         data->length = sizeof(struct iw_range);
900         memset(range, 0, sizeof(struct iw_range));
901
902         /* txpower (128 values, but will print out only IW_MAX_TXPOWER) */
903 #if WIRELESS_EXT >= 10
904         range->num_txpower = (ic->ic_txpowlimit >= 8) ? IW_MAX_TXPOWER : ic->ic_txpowlimit;
905         step = ic->ic_txpowlimit / (2 * (IW_MAX_TXPOWER - 1));
906  
907         range->txpower[0] = 0;
908         for (i = 1; i < IW_MAX_TXPOWER; i++)
909                 range->txpower[i] = (ic->ic_txpowlimit/2)
910                         - (IW_MAX_TXPOWER - i - 1) * step;
911 #endif
912
913
914         range->txpower_capa = IW_TXPOW_DBM;
915
916         if (vap->iv_opmode == IEEE80211_M_STA ||
917             vap->iv_opmode == IEEE80211_M_IBSS) {
918                 range->min_pmp = 1 * 1024;
919                 range->max_pmp = 65535 * 1024;
920                 range->min_pmt = 1 * 1024;
921                 range->max_pmt = 1000 * 1024;
922                 range->pmp_flags = IW_POWER_PERIOD;
923                 range->pmt_flags = IW_POWER_TIMEOUT;
924                 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
925                         IW_POWER_UNICAST_R | IW_POWER_ALL_R;
926         }
927
928         range->we_version_compiled = WIRELESS_EXT;
929         range->we_version_source = 13;
930
931         range->retry_capa = IW_RETRY_LIMIT;
932         range->retry_flags = IW_RETRY_LIMIT;
933         range->min_retry = 0;
934         range->max_retry = 255;
935
936         range->num_channels = ic->ic_nchans;
937
938         range->num_frequency = 0;
939         memset(reported, 0, sizeof(reported));
940         for (i = 0; i < ic->ic_nchans; i++) {
941                 const struct ieee80211_channel *c = &ic->ic_channels[i];
942
943                 /* discard if previously reported (e.g. b/g) */
944                 if (isclr(reported, c->ic_ieee)) {
945                         setbit(reported, c->ic_ieee);
946                         range->freq[range->num_frequency].i = c->ic_ieee;
947                         range->freq[range->num_frequency].m =
948                                 ic->ic_channels[i].ic_freq * 100000;
949                         range->freq[range->num_frequency].e = 1;
950                         if (++range->num_frequency == IW_MAX_FREQUENCIES)
951                                 break;
952                 }
953         }
954
955         /* Atheros' RSSI value is SNR: 0 -> 60 for old chipsets. Range 
956          * for newer chipsets is unknown. This value is arbitarily chosen 
957          * to give an indication that full rate will be available and to be 
958          * a practicable maximum. */
959         range->max_qual.qual  = 70;
960 #if WIRELESS_EXT >= 19
961         /* XXX: This should be updated to use the current noise floor. */
962         /* These are negative full bytes.
963          * Min. quality is noise + 1 */
964         range->max_qual.updated |= IW_QUAL_DBM;
965         range->max_qual.level = ATH_DEFAULT_NOISE + 1;
966         range->max_qual.noise = ATH_DEFAULT_NOISE;
967 #else
968         /* Values larger than the maximum are assumed to be absolute */
969         range->max_qual.level = 0;
970         range->max_qual.noise = 0;
971 #endif
972
973         range->sensitivity = 1;
974
975         range->max_encoding_tokens = IEEE80211_WEP_NKID;
976         /* XXX query driver to find out supported key sizes */
977         range->num_encoding_sizes = 3;
978         range->encoding_size[0] = 5;            /* 40-bit */
979         range->encoding_size[1] = 13;           /* 104-bit */
980         range->encoding_size[2] = 16;           /* 128-bit */
981
982         /* XXX this only works for station mode */
983         rs = &ni->ni_rates;
984         range->num_bitrates = rs->rs_nrates;
985         if (range->num_bitrates > IW_MAX_BITRATES)
986                 range->num_bitrates = IW_MAX_BITRATES;
987         for (i = 0; i < range->num_bitrates; i++) {
988                 r = rs->rs_rates[i] & IEEE80211_RATE_VAL;
989                 range->bitrate[i] = (r * 1000000) / 2;
990         }
991
992         /* estimated maximum TCP throughput values (bps) */
993         range->throughput = 5500000;
994
995         range->min_rts = 0;
996         range->max_rts = 2347;
997         range->min_frag = 256;
998         range->max_frag = 2346;
999
1000 #if WIRELESS_EXT >= 17
1001         /* Event capability (kernel) */
1002         IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
1003    
1004         /* Event capability (driver) */
1005         if (vap->iv_opmode == IEEE80211_M_STA ||
1006                  vap->iv_opmode == IEEE80211_M_IBSS ||
1007                  vap->iv_opmode == IEEE80211_M_AHDEMO) {
1008                 /* for now, only ibss, ahdemo, sta has this cap */
1009                 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
1010         }
1011
1012         if (vap->iv_opmode == IEEE80211_M_STA) {
1013                 /* for sta only */
1014                 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); 
1015                 IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED);
1016                 IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED);
1017         }
1018         
1019         /* this is used for reporting replay failure, which is used by the different encoding schemes */
1020         IW_EVENT_CAPA_SET(range->event_capa, IWEVCUSTOM);
1021 #endif
1022
1023 #if WIRELESS_EXT >= 18
1024         /* report supported WPA/WPA2 capabilities to userspace */
1025         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1026                IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1027 #endif
1028         
1029         return 0;
1030 }
1031
1032 static int
1033 ieee80211_ioctl_setspy(struct net_device *dev, struct iw_request_info *info,
1034         struct iw_point *data, char *extra)
1035 {
1036         /* save the list of node addresses */
1037         struct ieee80211vap *vap = netdev_priv(dev);
1038         struct sockaddr address[IW_MAX_SPY];
1039         unsigned int number = data->length;
1040         int i;
1041
1042         if (number > IW_MAX_SPY)
1043                 return -E2BIG;
1044         
1045         /* get the addresses into the driver */
1046         if (data->pointer) {
1047                 if (copy_from_user(address, data->pointer,
1048                     sizeof(struct sockaddr) * number))
1049                         return -EFAULT;
1050         } else
1051                 return -EFAULT;
1052
1053         /* copy the MAC addresses into a list */
1054         if (number > 0) {
1055                 /* extract the MAC addresses */
1056                 for (i = 0; i < number; i++)
1057                         memcpy(&vap->iv_spy.mac[i * IEEE80211_ADDR_LEN],
1058                                 address[i].sa_data, IEEE80211_ADDR_LEN);
1059                 /* init rssi timestamps */
1060                 memset(vap->iv_spy.ts_rssi, 0, IW_MAX_SPY * sizeof(u_int32_t));
1061         }
1062         vap->iv_spy.num = number;
1063
1064         return 0;
1065 }
1066
1067 static int
1068 ieee80211_ioctl_getspy(struct net_device *dev, struct iw_request_info *info,
1069         struct iw_point *data, char *extra)
1070 {
1071         /*
1072          * locate nodes by mac (ieee80211_find_node()),
1073          * copy out rssi, set updated flag appropriately
1074          */
1075         struct ieee80211vap *vap = netdev_priv(dev);
1076         struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
1077         struct ieee80211_node *ni;
1078         struct ieee80211com *ic = vap->iv_ic;
1079         struct sockaddr *address;
1080         struct iw_quality *spy_stat;
1081         unsigned int number = vap->iv_spy.num;
1082         int i;
1083
1084         address = (struct sockaddr *) extra;
1085         spy_stat = (struct iw_quality *) (extra + number * sizeof(struct sockaddr));
1086
1087         for (i = 0; i < number; i++) {
1088                 memcpy(address[i].sa_data, &vap->iv_spy.mac[i * IEEE80211_ADDR_LEN],
1089                         IEEE80211_ADDR_LEN);
1090                 address[i].sa_family = AF_PACKET;
1091         }
1092
1093         /* locate a node, read its rssi, check if updated, convert to dBm */
1094         for (i = 0; i < number; i++) {
1095                 ni = ieee80211_find_node(nt, &vap->iv_spy.mac[i * IEEE80211_ADDR_LEN]);
1096                 /* TODO: free node ? */
1097                 /* check we are associated w/ this vap */
1098                 if (ni && (ni->ni_vap == vap)) {
1099                         set_quality(&spy_stat[i], ni->ni_rssi, ic->ic_channoise);
1100                         if (ni->ni_rstamp != vap->iv_spy.ts_rssi[i]) {
1101                                 vap->iv_spy.ts_rssi[i] = ni->ni_rstamp;
1102                         } else {
1103                                 spy_stat[i].updated = 0;
1104                         }
1105                 } else {
1106                         spy_stat[i].updated = IW_QUAL_ALL_INVALID;
1107                 }
1108         }
1109
1110         /* copy results to userspace */
1111         data->length = number;
1112         return 0;
1113 }
1114
1115 #if WIRELESS_EXT >= 16
1116 /* Enhanced iwspy support */
1117 static int
1118 ieee80211_ioctl_setthrspy(struct net_device *dev, struct iw_request_info *info,
1119         struct iw_point *data, char *extra)
1120 {
1121         struct ieee80211vap *vap = netdev_priv(dev);
1122         struct iw_thrspy threshold;
1123
1124         if (data->length != 1)
1125                 return -EINVAL;
1126         
1127         /* get the threshold values into the driver */
1128         if (data->pointer) {
1129                 if (copy_from_user(&threshold, data->pointer,
1130                     sizeof(struct iw_thrspy)))
1131                         return -EFAULT;
1132         } else
1133                 return -EINVAL;
1134                 
1135         if (threshold.low.level == 0) {
1136                 /* disable threshold */
1137                 vap->iv_spy.thr_low = 0;
1138                 vap->iv_spy.thr_high = 0;
1139                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG,
1140                         "%s: disabled iw_spy threshold\n", __func__);
1141         } else {
1142                 /* We are passed a signal level/strength - calculate 
1143                  * corresponding RSSI values */
1144                 /* XXX: We should use current noise value. */
1145                 vap->iv_spy.thr_low = threshold.low.level + ATH_DEFAULT_NOISE;
1146                 vap->iv_spy.thr_high = threshold.high.level + ATH_DEFAULT_NOISE;
1147                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG,
1148                         "%s: enabled iw_spy threshold\n", __func__);
1149         }
1150
1151         return 0;
1152 }
1153
1154 static int
1155 ieee80211_ioctl_getthrspy(struct net_device *dev, struct iw_request_info *info,
1156         struct iw_point *data, char *extra)
1157 {
1158         struct ieee80211vap *vap = netdev_priv(dev);
1159         struct ieee80211com *ic = vap->iv_ic;
1160         struct iw_thrspy *threshold;    
1161         
1162         threshold = (struct iw_thrspy *) extra;
1163
1164         /* set threshold values */
1165         set_quality(&(threshold->low), vap->iv_spy.thr_low, ic->ic_channoise);
1166         set_quality(&(threshold->high), vap->iv_spy.thr_high, ic->ic_channoise);
1167
1168         /* copy results to userspace */
1169         data->length = 1;
1170         
1171         return 0;
1172 }
1173 #endif
1174
1175 static int
1176 ieee80211_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info,
1177         __u32 *mode, char *extra)
1178 {
1179         struct ieee80211vap *vap = netdev_priv(dev);
1180         struct ifmediareq imr;
1181         int valid = 0;
1182         
1183         memset(&imr, 0, sizeof(imr));
1184         vap->iv_media.ifm_status(vap->iv_dev, &imr);
1185         
1186         if (imr.ifm_active & IFM_IEEE80211_HOSTAP)
1187                 valid = (*mode == IW_MODE_MASTER);
1188 #if WIRELESS_EXT >= 15
1189         else if (imr.ifm_active & IFM_IEEE80211_MONITOR)
1190                 valid = (*mode == IW_MODE_MONITOR);
1191 #endif
1192         else if (imr.ifm_active & IFM_IEEE80211_ADHOC)
1193                 valid = (*mode == IW_MODE_ADHOC);
1194         else if (imr.ifm_active & IFM_IEEE80211_WDS)
1195                 valid = (*mode == IW_MODE_REPEAT);
1196         else
1197                 valid = (*mode == IW_MODE_INFRA);
1198                 
1199         return valid ? 0 : -EINVAL;     
1200 }
1201
1202 static int
1203 ieee80211_ioctl_giwmode(struct net_device *dev, struct iw_request_info *info,
1204         __u32 *mode, char *extra)
1205 {
1206         struct ieee80211vap *vap = netdev_priv(dev);
1207         struct ifmediareq imr;
1208
1209         memset(&imr, 0, sizeof(imr));
1210         vap->iv_media.ifm_status(vap->iv_dev, &imr);
1211
1212         if (imr.ifm_active & IFM_IEEE80211_HOSTAP)
1213                 *mode = IW_MODE_MASTER;
1214 #if WIRELESS_EXT >= 15
1215         else if (imr.ifm_active & IFM_IEEE80211_MONITOR)
1216                 *mode = IW_MODE_MONITOR;
1217 #endif
1218         else if (imr.ifm_active & IFM_IEEE80211_ADHOC)
1219                 *mode = IW_MODE_ADHOC;
1220         else if (imr.ifm_active & IFM_IEEE80211_WDS)
1221                 *mode = IW_MODE_REPEAT;
1222         else
1223                 *mode = IW_MODE_INFRA;
1224         return 0;
1225 }
1226
1227 static int
1228 ieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info,
1229         struct iw_param *wrq, char *extra)
1230 {
1231         struct ieee80211vap *vap = netdev_priv(dev);
1232         struct ieee80211com *ic = vap->iv_ic;
1233
1234         /* XXX: These values, flags, and caps do not seem to be used elsewhere 
1235          * at all? */
1236
1237         if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
1238                 return -EOPNOTSUPP;
1239
1240         if (wrq->disabled) {
1241                 ic->ic_flags &= ~IEEE80211_F_PMGTON;
1242         } else {
1243                 switch (wrq->flags & IW_POWER_MODE) {
1244                 case IW_POWER_UNICAST_R:
1245                 case IW_POWER_ALL_R:
1246                 case IW_POWER_ON:
1247                         if (wrq->flags & IW_POWER_PERIOD) {
1248                                 if (IEEE80211_BINTVAL_VALID(wrq->value))
1249                                         ic->ic_lintval = IEEE80211_MS_TO_TU(wrq->value);
1250                                 else
1251                                         return -EINVAL;
1252                         }
1253                         if (wrq->flags & IW_POWER_TIMEOUT)
1254                                 ic->ic_holdover = IEEE80211_MS_TO_TU(wrq->value);
1255
1256                         ic->ic_flags |= IEEE80211_F_PMGTON;
1257                         break;
1258                 default:
1259                         return -EINVAL;
1260                 }
1261         }
1262
1263         return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;
1264 }
1265
1266 static int
1267 ieee80211_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info,
1268         struct iw_param *rrq, char *extra)
1269 {
1270         struct ieee80211vap *vap = netdev_priv(dev);
1271         struct ieee80211com *ic = vap->iv_ic;
1272
1273         rrq->disabled = (ic->ic_flags & IEEE80211_F_PMGTON) == 0;
1274         if (!rrq->disabled) {
1275                 switch (rrq->flags & IW_POWER_TYPE) {
1276                 case IW_POWER_TIMEOUT:
1277                         rrq->flags = IW_POWER_TIMEOUT;
1278                         rrq->value = IEEE80211_TU_TO_MS(ic->ic_holdover);
1279                         break;
1280                 case IW_POWER_PERIOD:
1281                         rrq->flags = IW_POWER_PERIOD;
1282                         rrq->value = IEEE80211_TU_TO_MS(ic->ic_lintval);
1283                         break;
1284                 }
1285                 rrq->flags |= IW_POWER_ALL_R;
1286         }
1287         return 0;
1288 }
1289
1290 static int
1291 ieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info,
1292         struct iw_param *rrq, char *extra)
1293 {
1294         struct ieee80211vap *vap = netdev_priv(dev);
1295         struct ieee80211com *ic = vap->iv_ic;
1296
1297         if (rrq->disabled) {
1298                 if (vap->iv_flags & IEEE80211_F_SWRETRY) {
1299                         vap->iv_flags &= ~IEEE80211_F_SWRETRY;
1300                         goto done;
1301                 }
1302                 return 0;
1303         }
1304
1305         if ((vap->iv_caps & IEEE80211_C_SWRETRY) == 0)
1306                 return -EOPNOTSUPP;
1307         if (rrq->flags == IW_RETRY_LIMIT) {
1308                 if (rrq->value >= 0) {
1309                         vap->iv_txmin = rrq->value;
1310                         vap->iv_txmax = rrq->value;     /* XXX */
1311                         vap->iv_txlifetime = 0;         /* XXX */
1312                         vap->iv_flags |= IEEE80211_F_SWRETRY;
1313                 } else {
1314                         vap->iv_flags &= ~IEEE80211_F_SWRETRY;
1315                 }
1316                 return 0;
1317         }
1318 done:
1319         return IS_UP(vap->iv_dev) ? ic->ic_reset(vap->iv_dev) : 0;
1320 }
1321
1322 static int
1323 ieee80211_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info,
1324         struct iw_param *rrq, char *extra)
1325 {
1326         struct ieee80211vap *vap = netdev_priv(dev);
1327
1328         rrq->disabled = (vap->iv_flags & IEEE80211_F_SWRETRY) == 0;
1329         if (!rrq->disabled) {
1330                 switch (rrq->flags & IW_RETRY_TYPE) {
1331                 case IW_RETRY_LIFETIME:
1332                         rrq->flags = IW_RETRY_LIFETIME;
1333                         rrq->value = IEEE80211_TU_TO_MS(vap->iv_txlifetime);
1334                         break;
1335                 case IW_RETRY_LIMIT:
1336                         rrq->flags = IW_RETRY_LIMIT;
1337                         switch (rrq->flags & IW_RETRY_MODIFIER) {
1338                         case IW_RETRY_MIN:
1339                                 rrq->flags |= IW_RETRY_MAX;
1340                                 rrq->value = vap->iv_txmin;
1341                                 break;
1342                         case IW_RETRY_MAX:
1343                                 rrq->flags |= IW_RETRY_MAX;
1344                                 rrq->value = vap->iv_txmax;
1345                                 break;
1346                         }
1347                         break;
1348                 }
1349         }
1350         return 0;
1351 }
1352
1353 static int
1354 ieee80211_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info,
1355         struct iw_param *rrq, char *extra)
1356 {
1357         struct ieee80211vap *vap = netdev_priv(dev);
1358         struct ieee80211com *ic = vap->iv_ic;
1359         int fixed, disabled;
1360
1361         fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED);
1362         disabled = (fixed && vap->iv_bss->ni_txpower == 0);
1363         if (rrq->disabled) {
1364                 if (!disabled) {
1365                         if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
1366                                 return -EOPNOTSUPP;
1367                         ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
1368                         vap->iv_bss->ni_txpower = 0;
1369                         goto done;
1370                 }
1371                 return 0;
1372         }
1373
1374         if (rrq->fixed) {
1375                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
1376                         return -EOPNOTSUPP;
1377                 if (rrq->flags != IW_TXPOW_DBM)
1378                         return -EOPNOTSUPP;
1379                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
1380                         if (ic->ic_bsschan->ic_maxregpower >= rrq->value &&
1381                             ic->ic_txpowlimit/2 >= rrq->value) {
1382                                 vap->iv_bss->ni_txpower = 2 * rrq->value;
1383                                 ic->ic_newtxpowlimit = 2 * rrq->value;
1384                                 ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
1385                         } else
1386                                 return -EINVAL;
1387                 } else {
1388                         /*
1389                          * No channel set yet
1390                          */
1391                         if (ic->ic_txpowlimit/2 >= rrq->value) {
1392                                 vap->iv_bss->ni_txpower = 2 * rrq->value;
1393                                 ic->ic_newtxpowlimit = 2 * rrq->value;
1394                                 ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
1395                         }
1396                         else
1397                                 return -EINVAL;
1398                 }
1399         } else {
1400                 if (!fixed)             /* no change */
1401                         return 0;
1402                 ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED;
1403         }
1404 done:
1405         return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;
1406 }
1407
1408 static int
1409 ieee80211_ioctl_giwtxpow(struct net_device *dev, struct iw_request_info *info,
1410         struct iw_param *rrq, char *extra)
1411 {
1412         struct ieee80211vap *vap = netdev_priv(dev);
1413         struct ieee80211com *ic = vap->iv_ic;
1414
1415         rrq->value = vap->iv_bss->ni_txpower / 2;
1416         rrq->fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) != 0;
1417         rrq->disabled = (rrq->fixed && rrq->value == 0);
1418         rrq->flags = IW_TXPOW_DBM;
1419         return 0;
1420 }
1421
1422 struct waplistreq {     /* XXX: not the right place for declaration? */
1423         struct ieee80211vap *vap;
1424         struct sockaddr addr[IW_MAX_AP];
1425         struct iw_quality qual[IW_MAX_AP];
1426         int i;
1427 };
1428
1429 static int
1430 waplist_cb(void *arg, const struct ieee80211_scan_entry *se)
1431 {
1432         struct waplistreq *req = arg;
1433         int i = req->i;
1434
1435         if (i >= IW_MAX_AP)
1436                 return 0;
1437         req->addr[i].sa_family = ARPHRD_ETHER;
1438         if (req->vap->iv_opmode == IEEE80211_M_HOSTAP)
1439                 IEEE80211_ADDR_COPY(req->addr[i].sa_data, se->se_macaddr);
1440         else
1441                 IEEE80211_ADDR_COPY(req->addr[i].sa_data, se->se_bssid);
1442         set_quality(&req->qual[i], se->se_rssi, ATH_DEFAULT_NOISE);
1443         req->i = i + 1;
1444
1445         return 0;
1446 }
1447
1448 static int
1449 ieee80211_ioctl_iwaplist(struct net_device *dev, struct iw_request_info *info,
1450         struct iw_point *data, char *extra)
1451 {
1452         struct ieee80211vap *vap = netdev_priv(dev);
1453         struct ieee80211com *ic = vap->iv_ic;
1454         struct waplistreq *req;
1455
1456         req = kmalloc(sizeof(struct waplistreq), GFP_KERNEL);
1457         if (!req)
1458                 return -ENOMEM;
1459
1460         req->vap = vap;
1461         req->i = 0;
1462         ieee80211_scan_iterate(ic, waplist_cb, req);
1463
1464         data->length = req->i;
1465         memcpy(extra, &req->addr, req->i * sizeof(req->addr[0]));
1466         data->flags = 1;                /* signal quality present (sort of) */
1467         memcpy(extra + req->i * sizeof(req->addr[0]), &req->qual,
1468                 req->i * sizeof(req->qual[0]));
1469
1470         return 0;
1471 }
1472
1473 #ifdef SIOCGIWSCAN
1474 static int
1475 ieee80211_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info,
1476         struct iw_point *data, char *extra)
1477 {
1478         struct ieee80211vap *vap = netdev_priv(dev);
1479
1480         /*
1481          * XXX don't permit a scan to be started unless we
1482          * know the device is ready.  For the moment this means
1483          * the device is marked up as this is the required to
1484          * initialize the hardware.  It would be better to permit
1485          * scanning prior to being up but that'll require some
1486          * changes to the infrastructure.
1487          */
1488         if (!IS_UP(vap->iv_dev))
1489                 return -ENETDOWN;       /* XXX */
1490         /* XXX always manual... */
1491         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1492                 "%s: active scan request\n", __func__);
1493         preempt_scan(dev, 100, 100);
1494 #if WIRELESS_EXT > 17
1495         if (data && (data->flags & IW_SCAN_THIS_ESSID)) {
1496                 struct iw_scan_req req;
1497                 struct ieee80211_scan_ssid ssid;
1498                 int copyLength;
1499                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1500                         "%s: SCAN_THIS_ESSID requested\n", __func__);
1501                 if (data->length > sizeof req) {
1502                         copyLength = sizeof req;
1503                 } else {
1504                         copyLength = data->length;
1505                 }
1506                 memset(&req, 0, sizeof req);
1507                 if (copy_from_user(&req, data->pointer, copyLength))
1508                         return -EFAULT;
1509                 memcpy(&ssid.ssid, req.essid, sizeof ssid.ssid);
1510                 ssid.len = req.essid_len;
1511                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1512                                   "%s: requesting scan of essid '%s'\n", __func__, ssid.ssid);
1513                 (void) ieee80211_start_scan(vap,
1514                         IEEE80211_SCAN_ACTIVE |
1515                         IEEE80211_SCAN_NOPICK |
1516                         IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
1517                         1, &ssid);
1518                 return 0;
1519         }
1520 #endif           
1521         (void) ieee80211_start_scan(vap, IEEE80211_SCAN_ACTIVE |
1522                 IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_ONCE,
1523                 IEEE80211_SCAN_FOREVER,
1524                 /* XXX use ioctl params */
1525                 vap->iv_des_nssid, vap->iv_des_ssid);
1526         return 0;
1527 }
1528
1529 #if WIRELESS_EXT > 14
1530 /*
1531  * Encode a WPA or RSN information element as a custom
1532  * element using the hostap format.
1533  */
1534 static u_int
1535 encode_ie(void *buf, size_t bufsize, const u_int8_t *ie, size_t ielen,
1536         const char *leader, size_t leader_len)
1537 {
1538         u_int8_t *p;
1539         int i;
1540
1541         if (bufsize < leader_len)
1542                 return 0;
1543         p = buf;
1544         memcpy(p, leader, leader_len);
1545         bufsize -= leader_len;
1546         p += leader_len;
1547         for (i = 0; i < ielen && bufsize > 2; i++) {
1548                 p += sprintf(p, "%02x", ie[i]);
1549                 bufsize -= 2;
1550         }
1551         return (i == ielen ? p - (u_int8_t *)buf : 0);
1552 }
1553 #endif /* WIRELESS_EXT > 14 */
1554
1555 struct iwscanreq {              /* XXX: right place for this declaration? */
1556         struct ieee80211vap *vap;
1557         struct iw_request_info *info;
1558         char *current_ev;
1559         char *end_buf;
1560         int mode;
1561 };
1562
1563 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) && !defined(IW_REQUEST_FLAG_COMPAT)
1564 #define iwe_stream_add_event(a, b, c, d, e)     iwe_stream_add_event(b, c, d, e)
1565 #define iwe_stream_add_point(a, b, c, d, e)     iwe_stream_add_point(b, c, d, e)
1566 #define iwe_stream_add_value(a, b, c, d, e, f)  \
1567         iwe_stream_add_value(b, c, d, e, f)
1568 #define iwe_stream_lcp_len(a)                   IW_EV_LCP_LEN
1569 #endif
1570 static int
1571 giwscan_cb(void *arg, const struct ieee80211_scan_entry *se)
1572 {
1573         struct iwscanreq *req = arg;
1574         struct ieee80211vap *vap = req->vap;
1575         char *current_ev = req->current_ev;
1576         char *end_buf = req->end_buf;
1577         char *last_ev;
1578 #if WIRELESS_EXT > 14
1579 #define MAX_IE_LENGTH 64 * 2 + 30
1580         char buf[MAX_IE_LENGTH];
1581 #ifndef IWEVGENIE
1582         static const char rsn_leader[] = "rsn_ie=";
1583         static const char wpa_leader[] = "wpa_ie=";
1584 #endif
1585 #endif
1586         struct iw_event iwe;
1587         char *current_val;
1588         int j;
1589
1590         if (current_ev >= end_buf)
1591                 return E2BIG;
1592         /* WPA/!WPA sort criteria */
1593         if ((req->mode != 0) ^ (se->se_wpa_ie != NULL))
1594                 return 0;
1595
1596         memset(&iwe, 0, sizeof(iwe));
1597         last_ev = current_ev;
1598         iwe.cmd = SIOCGIWAP;
1599         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1600         if (vap->iv_opmode == IEEE80211_M_HOSTAP)
1601                 IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_macaddr);
1602         else
1603                 IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_bssid);
1604         current_ev = iwe_stream_add_event(req->info, current_ev, end_buf,
1605                                         &iwe, IW_EV_ADDR_LEN);
1606
1607         /* We ran out of space in the buffer. */
1608         if (last_ev == current_ev)
1609           return E2BIG;
1610
1611         memset(&iwe, 0, sizeof(iwe));
1612         last_ev = current_ev;
1613         iwe.cmd = SIOCGIWESSID;
1614         iwe.u.data.flags = 1;
1615         if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
1616                 iwe.u.data.length = vap->iv_des_nssid > 0 ?
1617                         vap->iv_des_ssid[0].len : 0;
1618                 current_ev = iwe_stream_add_point(req->info, current_ev,
1619                         end_buf, &iwe, vap->iv_des_ssid[0].ssid);
1620         } else {
1621                 iwe.u.data.length = se->se_ssid[1];
1622                 current_ev = iwe_stream_add_point(req->info, current_ev,
1623                         end_buf, &iwe, (char *) se->se_ssid+2);
1624         }
1625
1626         /* We ran out of space in the buffer. */
1627         if (last_ev == current_ev)
1628           return E2BIG;
1629
1630         if (se->se_capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
1631                 memset(&iwe, 0, sizeof(iwe));
1632                 last_ev = current_ev;
1633                 iwe.cmd = SIOCGIWMODE;
1634                 iwe.u.mode = se->se_capinfo & IEEE80211_CAPINFO_ESS ?
1635                         IW_MODE_MASTER : IW_MODE_ADHOC;
1636                 current_ev = iwe_stream_add_event(req->info, current_ev,
1637                                 end_buf, &iwe, IW_EV_UINT_LEN);
1638
1639                 /* We ran out of space in the buffer. */
1640                 if (last_ev == current_ev)
1641                   return E2BIG;
1642         }
1643
1644         memset(&iwe, 0, sizeof(iwe));
1645         last_ev = current_ev;
1646         iwe.cmd = SIOCGIWFREQ;
1647         iwe.u.freq.m = se->se_chan->ic_freq * 100000;
1648         iwe.u.freq.e = 1;
1649         current_ev = iwe_stream_add_event(req->info, current_ev,
1650                         end_buf, &iwe, IW_EV_FREQ_LEN);
1651
1652         /* We ran out of space in the buffer. */
1653         if (last_ev == current_ev)
1654           return E2BIG;
1655
1656         memset(&iwe, 0, sizeof(iwe));
1657         last_ev = current_ev;
1658         iwe.cmd = IWEVQUAL;
1659         set_quality(&iwe.u.qual, se->se_rssi, ATH_DEFAULT_NOISE);
1660         current_ev = iwe_stream_add_event(req->info, current_ev,
1661                         end_buf, &iwe, IW_EV_QUAL_LEN);
1662
1663         /* We ran out of space in the buffer */
1664         if (last_ev == current_ev)
1665           return E2BIG;
1666
1667         memset(&iwe, 0, sizeof(iwe));
1668         last_ev = current_ev;
1669         iwe.cmd = SIOCGIWENCODE;
1670         if (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY)
1671                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1672         else
1673                 iwe.u.data.flags = IW_ENCODE_DISABLED;
1674         iwe.u.data.length = 0;
1675         current_ev = iwe_stream_add_point(req->info, current_ev,
1676                                         end_buf, &iwe, "");
1677
1678         /* We ran out of space in the buffer. */
1679         if (last_ev == current_ev)
1680           return E2BIG;
1681
1682         memset(&iwe, 0, sizeof(iwe));
1683         last_ev = current_ev;
1684         iwe.cmd = SIOCGIWRATE;
1685         current_val = current_ev + iwe_stream_lcp_len(req->info);
1686         /* NB: not sorted, does it matter? */
1687         for (j = 0; j < se->se_rates[1]; j++) {
1688                 int r = se->se_rates[2 + j] & IEEE80211_RATE_VAL;
1689                 if (r != 0) {
1690                         iwe.u.bitrate.value = r * (1000000 / 2);
1691                         current_val = iwe_stream_add_value(req->info,
1692                                         current_ev, current_val, end_buf,
1693                                         &iwe, IW_EV_PARAM_LEN);
1694                 }
1695         }
1696         for (j = 0; j < se->se_xrates[1]; j++) {
1697                 int r = se->se_xrates[2+j] & IEEE80211_RATE_VAL;
1698                 if (r != 0) {
1699                         iwe.u.bitrate.value = r * (1000000 / 2);
1700                         current_val = iwe_stream_add_value(req->info,
1701                                         current_ev, current_val, end_buf,
1702                                         &iwe, IW_EV_PARAM_LEN);
1703                 }
1704         }
1705         /* remove fixed header if no rates were added */
1706         if ((current_val - current_ev) > iwe_stream_lcp_len(req->info)) {
1707                 current_ev = current_val;
1708         } else {
1709           /* We ran out of space in the buffer. */
1710           if (last_ev == current_ev)
1711             return E2BIG;
1712         }
1713
1714 #if WIRELESS_EXT > 14
1715         memset(&iwe, 0, sizeof(iwe));
1716         last_ev = current_ev;
1717         iwe.cmd = IWEVCUSTOM;
1718         snprintf(buf, sizeof(buf), "bcn_int=%d", se->se_intval);
1719         iwe.u.data.length = strlen(buf);
1720         current_ev = iwe_stream_add_point(req->info, current_ev,
1721                                         end_buf, &iwe, buf);
1722
1723         /* We ran out of space in the buffer. */
1724         if (last_ev == current_ev)
1725           return E2BIG;
1726
1727         if (se->se_rsn_ie != NULL) {
1728           last_ev = current_ev;
1729 #ifdef IWEVGENIE
1730                 memset(&iwe, 0, sizeof(iwe));
1731                 if ((se->se_rsn_ie[1] + 2) > MAX_IE_LENGTH)
1732                         return E2BIG;
1733                 memcpy(buf, se->se_rsn_ie, se->se_rsn_ie[1] + 2);
1734                 iwe.cmd = IWEVGENIE;
1735                 iwe.u.data.length = se->se_rsn_ie[1] + 2;
1736 #else   
1737                 memset(&iwe, 0, sizeof(iwe));
1738                 iwe.cmd = IWEVCUSTOM;
1739                 if (se->se_rsn_ie[0] == IEEE80211_ELEMID_RSN)
1740                         iwe.u.data.length = encode_ie(buf, sizeof(buf),
1741                                 se->se_rsn_ie, se->se_rsn_ie[1] + 2,
1742                                 rsn_leader, sizeof(rsn_leader) - 1);
1743 #endif
1744                 if (iwe.u.data.length != 0) {
1745                         current_ev = iwe_stream_add_point(req->info,
1746                                         current_ev, end_buf, &iwe, buf);
1747                         
1748                         /* We ran out of space in the buffer */
1749                         if (last_ev == current_ev)
1750                           return E2BIG;
1751                 }
1752         }
1753
1754         if (se->se_wpa_ie != NULL) {
1755           last_ev = current_ev;
1756 #ifdef IWEVGENIE
1757                 memset(&iwe, 0, sizeof(iwe));
1758                 if ((se->se_wpa_ie[1] + 2) > MAX_IE_LENGTH)
1759                         return E2BIG;
1760                 memcpy(buf, se->se_wpa_ie, se->se_wpa_ie[1] + 2);
1761                 iwe.cmd = IWEVGENIE;
1762                 iwe.u.data.length = se->se_wpa_ie[1] + 2;
1763 #else
1764                 memset(&iwe, 0, sizeof(iwe));
1765                 iwe.cmd = IWEVCUSTOM;
1766                 iwe.u.data.length = encode_ie(buf, sizeof(buf),
1767                         se->se_wpa_ie, se->se_wpa_ie[1] + 2,
1768                         wpa_leader, sizeof(wpa_leader) - 1);
1769 #endif
1770                 if (iwe.u.data.length != 0) {
1771                         current_ev = iwe_stream_add_point(req->info,
1772                                         current_ev, end_buf, &iwe, buf);
1773                         
1774                         /* We ran out of space in the buffer. */
1775                         if (last_ev == current_ev)
1776                           return E2BIG;
1777                 }
1778
1779         }
1780         if (se->se_wme_ie != NULL) {
1781                 static const char wme_leader[] = "wme_ie=";
1782
1783                 memset(&iwe, 0, sizeof(iwe));
1784                 last_ev = current_ev;
1785                 iwe.cmd = IWEVCUSTOM;
1786                 iwe.u.data.length = encode_ie(buf, sizeof(buf),
1787                         se->se_wme_ie, se->se_wme_ie[1] + 2,
1788                         wme_leader, sizeof(wme_leader) - 1);
1789                 if (iwe.u.data.length != 0) {
1790                         current_ev = iwe_stream_add_point(req->info,
1791                                         current_ev, end_buf, &iwe, buf);
1792
1793                         /* We ran out of space in the buffer. */
1794                         if (last_ev == current_ev)
1795                           return E2BIG;
1796                 }
1797         }
1798         if (se->se_ath_ie != NULL) {
1799                 static const char ath_leader[] = "ath_ie=";
1800
1801                 memset(&iwe, 0, sizeof(iwe));
1802                 last_ev = current_ev;
1803                 iwe.cmd = IWEVCUSTOM;
1804                 iwe.u.data.length = encode_ie(buf, sizeof(buf),
1805                         se->se_ath_ie, se->se_ath_ie[1] + 2,
1806                         ath_leader, sizeof(ath_leader) - 1);
1807                 if (iwe.u.data.length != 0) {
1808                         current_ev = iwe_stream_add_point(req->info,
1809                                         current_ev, end_buf, &iwe, buf);
1810
1811                         /* We ran out of space in the buffer. */
1812                         if (last_ev == current_ev)
1813                           return E2BIG;
1814                 }
1815         }
1816 #endif /* WIRELESS_EXT > 14 */
1817         req->current_ev = current_ev;
1818
1819         return 0;
1820 }
1821
1822 static int
1823 ieee80211_ioctl_giwscan(struct net_device *dev, struct iw_request_info *info,
1824         struct iw_point *data, char *extra)
1825 {
1826         struct ieee80211vap *vap = netdev_priv(dev);
1827         struct ieee80211com *ic = vap->iv_ic;
1828         struct iwscanreq req;
1829         int res = 0;
1830
1831         req.vap = vap;
1832         req.info = info;
1833         req.current_ev = extra;
1834         if (data->length == 0) {
1835           req.end_buf = extra + IW_SCAN_MAX_DATA;
1836         } else {
1837           req.end_buf = extra + data->length;
1838         }
1839
1840         /*
1841          * NB: This is no longer needed, as long as the caller supports
1842          * large scan results.
1843          *
1844          * Do two passes to ensure WPA/non-WPA scan candidates
1845          * are sorted to the front.  This is a hack to deal with
1846          * the wireless extensions capping scan results at
1847          * IW_SCAN_MAX_DATA bytes.  In densely populated environments
1848          * it's easy to overflow this buffer (especially with WPA/RSN
1849          * information elements).  Note this sorting hack does not
1850          * guarantee we won't overflow anyway.
1851          */
1852         req.mode = vap->iv_flags & IEEE80211_F_WPA;
1853         res = ieee80211_scan_iterate(ic, giwscan_cb, &req);
1854         if (res == 0) {
1855           req.mode = req.mode ? 0 : IEEE80211_F_WPA;
1856           res = ieee80211_scan_iterate(ic, giwscan_cb, &req);
1857         }
1858
1859         data->length = req.current_ev - extra;
1860
1861         if (res != 0) {
1862           return -res;
1863         }
1864
1865         return res;
1866 }
1867 #endif /* SIOCGIWSCAN */
1868
1869 static int
1870 cipher2cap(int cipher)
1871 {
1872         switch (cipher) {
1873         case IEEE80211_CIPHER_WEP:      return IEEE80211_C_WEP;
1874         case IEEE80211_CIPHER_AES_OCB:  return IEEE80211_C_AES;
1875         case IEEE80211_CIPHER_AES_CCM:  return IEEE80211_C_AES_CCM;
1876         case IEEE80211_CIPHER_CKIP:     return IEEE80211_C_CKIP;
1877         case IEEE80211_CIPHER_TKIP:     return IEEE80211_C_TKIP;
1878         }
1879         return 0;
1880 }
1881
1882 #define IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX
1883
1884 static int
1885 ieee80211_convert_mode(const char *mode)
1886 {
1887 #define TOUPPER(c) ((((c) > 0x60) && ((c) < 0x7b)) ? ((c) - 0x20) : (c))
1888         static const struct {
1889                 char *name;
1890                 int mode;
1891         } mappings[] = {
1892                 /* NB: need to order longest strings first for overlaps */ 
1893                 { "11AST" , IEEE80211_MODE_TURBO_STATIC_A },
1894                 { "AUTO"  , IEEE80211_MODE_AUTO },
1895                 { "11A"   , IEEE80211_MODE_11A },
1896                 { "11B"   , IEEE80211_MODE_11B },
1897                 { "11G"   , IEEE80211_MODE_11G },
1898                 { "FH"    , IEEE80211_MODE_FH },
1899                 { "0"     , IEEE80211_MODE_AUTO },
1900                 { "1"     , IEEE80211_MODE_11A },
1901                 { "2"     , IEEE80211_MODE_11B },
1902                 { "3"     , IEEE80211_MODE_11G },
1903                 { "4"     , IEEE80211_MODE_FH },
1904                 { "5"     , IEEE80211_MODE_TURBO_STATIC_A },
1905                 { NULL }
1906         };
1907         int i, j;
1908         const char *cp;
1909
1910         for (i = 0; mappings[i].name != NULL; i++) {
1911                 cp = mappings[i].name;
1912                 for (j = 0; j < strlen(mode) + 1; j++) {
1913                         /* convert user-specified string to upper case */
1914                         if (TOUPPER(mode[j]) != cp[j])
1915                                 break;
1916                         if (cp[j] == '\0')
1917                                 return mappings[i].mode;
1918                 }
1919         }
1920         return -1;
1921 #undef TOUPPER
1922 }
1923
1924 static int
1925 ieee80211_ioctl_setmode(struct net_device *dev, struct iw_request_info *info,
1926         struct iw_point *wri, char *extra)
1927 {
1928         struct ieee80211vap *vap = netdev_priv(dev);
1929         struct ieee80211com *ic = vap->iv_ic;
1930         struct ifreq ifr;
1931         char s[6];              /* big enough for ``11adt'' */
1932         int retv, mode, ifr_mode, itr_count;
1933
1934         if (ic->ic_media.ifm_cur == NULL)
1935                 return -EINVAL;
1936         if (wri->length > sizeof(s))            /* silently truncate */
1937                 wri->length = sizeof(s);
1938         if (copy_from_user(s, wri->pointer, wri->length))
1939                 return -EINVAL;
1940         s[sizeof(s)-1] = '\0';                  /* ensure null termination */
1941         mode = ieee80211_convert_mode(s);
1942         if (mode < 0)
1943                 return -EINVAL;
1944
1945         if(ieee80211_check_mode_consistency(ic,mode,vap->iv_des_chan)) { 
1946                 /*
1947                  * error in AP mode.
1948                  * overwrite channel selection in other modes.
1949                  */
1950                 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
1951                         return -EINVAL;
1952                 else
1953                         vap->iv_des_chan=IEEE80211_CHAN_ANYC;
1954         }
1955
1956         ifr_mode = mode;
1957         memset(&ifr, 0, sizeof(ifr));
1958         ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media &~ IFM_MMASK;
1959         if (mode == IEEE80211_MODE_TURBO_STATIC_A)
1960                 ifr_mode = IEEE80211_MODE_11A;
1961         ifr.ifr_media |= IFM_MAKEMODE(ifr_mode);
1962         retv = ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA);
1963         if ((!retv || retv == -ENETRESET) &&  mode != vap->iv_des_mode) {
1964                 ieee80211_scan_flush(ic);       /* NB: could optimize */
1965                 vap->iv_des_mode = mode;
1966                 if (IS_UP_AUTO(vap)) {
1967                         ieee80211_cancel_scan(vap);
1968                         itr_count = 0;
1969                         while((ic->ic_flags & IEEE80211_F_SCAN) != 0) {
1970                                 mdelay(1);
1971                                 if (itr_count < 100) {
1972                                         itr_count++;
1973                                         continue;
1974                                 }
1975                                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1976                                   "%s: Timeout canceling current scan.\n",
1977                                   __func__);
1978                                 return -ETIMEDOUT;
1979                         }
1980                         ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1981                 }
1982                 retv = 0;
1983         }
1984 #ifdef ATH_SUPERG_XR
1985         /* set the same params on the xr vap device if exists */
1986         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
1987                 vap->iv_xrvap->iv_des_mode = mode;
1988 #endif
1989         return -retv;
1990 }
1991 #undef IEEE80211_MODE_TURBO_STATIC_A
1992
1993 #ifdef ATH_SUPERG_XR
1994 static void
1995 ieee80211_setupxr(struct ieee80211vap *vap)
1996 {
1997         struct net_device *dev = vap->iv_dev;
1998         struct ieee80211com *ic = vap->iv_ic;
1999         if (!(vap->iv_flags & IEEE80211_F_XR)) {
2000                 if ((vap->iv_ath_cap & IEEE80211_ATHC_XR) && !vap->iv_xrvap) { 
2001                         char name[IFNAMSIZ];
2002                         strcpy(name, dev->name);
2003                         strcat(name, "-xr");
2004                         /*
2005                          * create a new XR vap. if the normal VAP is already up,
2006                          * bring up the XR vap aswell.
2007                          */
2008                         vap->iv_ath_cap &= ~IEEE80211_ATHC_TURBOP; /* turn off turbo */ 
2009                         ieee80211_scan_flush(ic);       /* NB: could optimize */
2010                          
2011                         vap->iv_xrvap = ic->ic_vap_create(ic, name, vap->iv_unit,
2012                                 IEEE80211_M_HOSTAP,IEEE80211_VAP_XR |
2013                                 IEEE80211_CLONE_BSSID, dev);
2014                         if (!vap->iv_xrvap)
2015                                 return;
2016                         vap->iv_xrvap->iv_fragthreshold = IEEE80211_XR_FRAG_THRESHOLD;
2017                         copy_des_ssid(vap->iv_xrvap, vap);
2018                         vap->iv_xrvap->iv_des_mode = vap->iv_des_mode;
2019                 } else if (!(vap->iv_ath_cap & IEEE80211_ATHC_XR) && vap->iv_xrvap) { 
2020                         /*
2021                          * destroy the XR vap. if the XR VAP is up , bring
2022                          * it down before destroying.
2023                          */
2024                         if (vap->iv_xrvap) {
2025                                 ieee80211_stop(vap->iv_xrvap->iv_dev);
2026                                 ic->ic_vap_delete(vap->iv_xrvap);
2027                         }
2028                         vap->iv_xrvap = NULL;
2029                 }
2030         }
2031 }
2032 #endif
2033
2034 static int
2035 ieee80211_setathcap(struct ieee80211vap *vap, int cap, int setting)
2036 {
2037         struct ieee80211com *ic = vap->iv_ic;
2038         int ocap;
2039
2040         if ((ic->ic_ath_cap & cap) == 0)
2041                 return -EINVAL;
2042         ocap = vap->iv_ath_cap;
2043         if (setting)
2044                 vap->iv_ath_cap |= cap;
2045         else
2046                 vap->iv_ath_cap &= ~cap;
2047         return (vap->iv_ath_cap != ocap ? ENETRESET : 0);
2048 }
2049
2050 static int
2051 ieee80211_set_turbo(struct net_device *dev, int flag)
2052 {
2053         struct ieee80211vap *vap = netdev_priv(dev);
2054         struct ieee80211com *ic = vap->iv_ic;
2055         struct ifreq ifr;
2056         struct ieee80211vap *tmpvap = netdev_priv(dev);
2057         int nvap = 0;
2058
2059         TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next)
2060                 nvap++;
2061         if (nvap > 1 && flag )
2062                 return -EINVAL;
2063         ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media &~ IFM_MMASK;
2064         if (flag)
2065                 ifr.ifr_media |= IFM_IEEE80211_TURBO;
2066         else
2067                 ifr.ifr_media &= ~IFM_IEEE80211_TURBO;
2068         (void) ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA);
2069
2070         return 0;
2071 }
2072
2073 static int
2074 ieee80211_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
2075         void *w, char *extra)
2076 {
2077         struct ieee80211vap *vap = netdev_priv(dev);
2078         struct ieee80211com *ic = vap->iv_ic;
2079         struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
2080         int *i = (int *) extra;
2081         int param = i[0];               /* parameter id is 1st */
2082         int value = i[1];               /* NB: most values are TYPE_INT */
2083         int retv = 0;
2084         int j, caps;
2085         const struct ieee80211_authenticator *auth;
2086         const struct ieee80211_aclator *acl;
2087
2088         switch (param) {
2089         case IEEE80211_PARAM_AUTHMODE:
2090                 switch (value) {
2091                 case IEEE80211_AUTH_WPA:        /* WPA */
2092                 case IEEE80211_AUTH_8021X:      /* 802.1x */
2093                 case IEEE80211_AUTH_OPEN:       /* open */
2094                 case IEEE80211_AUTH_SHARED:     /* shared-key */
2095                 case IEEE80211_AUTH_AUTO:       /* auto */
2096                         auth = ieee80211_authenticator_get(value);
2097                         if (auth == NULL)
2098                                 return -EINVAL;
2099                         break;
2100                 default:
2101                         return -EINVAL;
2102                 }
2103                 switch (value) {
2104                 case IEEE80211_AUTH_WPA:        /* WPA w/ 802.1x */
2105                         value = IEEE80211_AUTH_8021X;
2106                         break;
2107                 case IEEE80211_AUTH_OPEN:       /* open */
2108                         vap->iv_flags &= ~(IEEE80211_F_WPA);
2109                         break;
2110                 case IEEE80211_AUTH_SHARED:     /* shared-key */
2111                 case IEEE80211_AUTH_AUTO:       /* auto */
2112                 case IEEE80211_AUTH_8021X:      /* 802.1x */
2113                         vap->iv_flags &= ~IEEE80211_F_WPA;
2114                         break;
2115                 }
2116                 /* NB: authenticator attach/detach happens on state change */
2117                 vap->iv_bss->ni_authmode = value;
2118                 /* XXX mixed/mode/usage? */
2119                 vap->iv_auth = auth;
2120                 retv = ENETRESET;
2121                 break;
2122         case IEEE80211_PARAM_PROTMODE:
2123                 if (value > IEEE80211_PROT_RTSCTS)
2124                         return -EINVAL;
2125                 ic->ic_protmode = value;
2126                 /* NB: if not operating in 11g this can wait */
2127                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2128                     IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2129                         retv = ENETRESET;
2130                 break;
2131         case IEEE80211_PARAM_MCASTCIPHER:
2132                 if ((vap->iv_caps & cipher2cap(value)) == 0 &&
2133                     !ieee80211_crypto_available(value))
2134                         return -EINVAL;
2135                 rsn->rsn_mcastcipher = value;
2136                 if (vap->iv_flags & IEEE80211_F_WPA)
2137                         retv = ENETRESET;
2138                 break;
2139         case IEEE80211_PARAM_MCASTKEYLEN:
2140                 if (!(0 < value && value <= IEEE80211_KEYBUF_SIZE))
2141                         return -EINVAL;
2142                 /* XXX no way to verify driver capability */
2143                 rsn->rsn_mcastkeylen = value;
2144                 if (vap->iv_flags & IEEE80211_F_WPA)
2145                         retv = ENETRESET;
2146                 break;
2147         case IEEE80211_PARAM_UCASTCIPHERS:
2148                 /*
2149                  * NB: this logic intentionally ignores unknown and
2150                  * unsupported ciphers so folks can specify 0xff or
2151                  * similar and get all available ciphers.
2152                  */
2153                 /* caps are really ciphers */
2154                 caps = 0;
2155                 for (j = 1; j < 32; j++)        /* NB: skip WEP */
2156                         if ((value & (1 << j)) &&
2157                             ((vap->iv_caps & cipher2cap(j)) ||
2158                              ieee80211_crypto_available(j)))
2159                                 caps |= 1 << j;
2160                 if (caps == 0)                  /* nothing available */
2161                         return -EINVAL;
2162                 /* XXX verify ciphers ok for unicast use? */
2163                 /* XXX disallow if running as it'll have no effect */
2164                 rsn->rsn_ucastcipherset = caps;
2165                 if (vap->iv_flags & IEEE80211_F_WPA)
2166                         retv = ENETRESET;
2167                 break;
2168         case IEEE80211_PARAM_UCASTCIPHER:
2169                 if ((vap->iv_caps & cipher2cap(value)) == 0 &&
2170                     !ieee80211_crypto_available(value))
2171                         return -EINVAL;
2172                 rsn->rsn_ucastcipher = value;
2173                 if (vap->iv_flags & IEEE80211_F_WPA)
2174                         retv = ENETRESET;
2175                 break;
2176         case IEEE80211_PARAM_UCASTKEYLEN:
2177                 if (!(0 < value && value <= IEEE80211_KEYBUF_SIZE))
2178                         return -EINVAL;
2179                 /* XXX no way to verify driver capability */
2180                 rsn->rsn_ucastkeylen = value;
2181                 break;
2182         case IEEE80211_PARAM_KEYMGTALGS:
2183                 /* XXX check */
2184                 rsn->rsn_keymgmtset = value;
2185                 if (vap->iv_flags & IEEE80211_F_WPA)
2186                         retv = ENETRESET;
2187                 break;
2188         case IEEE80211_PARAM_RSNCAPS:
2189                 /* XXX check */
2190                 rsn->rsn_caps = value;
2191                 if (vap->iv_flags & IEEE80211_F_WPA)
2192                         retv = ENETRESET;
2193                 break;
2194         case IEEE80211_PARAM_WPA:
2195                 if (value > 3)
2196                         return -EINVAL;
2197                 /* XXX verify ciphers available */
2198                 vap->iv_flags &= ~IEEE80211_F_WPA;
2199                 switch (value) {
2200                 case 1:
2201                         vap->iv_flags |= IEEE80211_F_WPA1;
2202                         break;
2203                 case 2:
2204                         vap->iv_flags |= IEEE80211_F_WPA2;
2205                         break;
2206                 case 3:
2207                         vap->iv_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2208                         break;
2209                 }
2210                 retv = ENETRESET;               /* XXX? */
2211                 break;
2212         case IEEE80211_PARAM_ROAMING:
2213                 if (!(IEEE80211_ROAMING_DEVICE <= value &&
2214                     value <= IEEE80211_ROAMING_MANUAL))
2215                         return -EINVAL;
2216                 ic->ic_roaming = value;
2217                 break;
2218         case IEEE80211_PARAM_PRIVACY:
2219                 if (value) {
2220                         /* XXX check for key state? */
2221                         vap->iv_flags |= IEEE80211_F_PRIVACY;
2222                 } else
2223                         vap->iv_flags &= ~IEEE80211_F_PRIVACY;
2224                 break;
2225         case IEEE80211_PARAM_DROPUNENCRYPTED:
2226                 if (value)
2227                         vap->iv_flags |= IEEE80211_F_DROPUNENC;
2228                 else
2229                         vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2230                 break;
2231         case IEEE80211_PARAM_DROPUNENC_EAPOL:
2232                 if (value)
2233                         IEEE80211_VAP_DROPUNENC_EAPOL_ENABLE(vap);
2234                 else
2235                         IEEE80211_VAP_DROPUNENC_EAPOL_DISABLE(vap);
2236                 break;
2237         case IEEE80211_PARAM_COUNTERMEASURES:
2238                 if (value) {
2239                         if ((vap->iv_flags & IEEE80211_F_WPA) == 0)
2240                                 return -EINVAL;
2241                         vap->iv_flags |= IEEE80211_F_COUNTERM;
2242                 } else
2243                         vap->iv_flags &= ~IEEE80211_F_COUNTERM;
2244                 break;
2245         case IEEE80211_PARAM_DRIVER_CAPS:
2246                 vap->iv_caps = value;           /* NB: for testing */
2247                 break;
2248         case IEEE80211_PARAM_MACCMD:
2249                 acl = vap->iv_acl;
2250                 switch (value) {
2251                 case IEEE80211_MACCMD_POLICY_OPEN:
2252                 case IEEE80211_MACCMD_POLICY_ALLOW:
2253                 case IEEE80211_MACCMD_POLICY_DENY:
2254                         if (acl == NULL) {
2255                                 acl = ieee80211_aclator_get("mac");
2256                                 if (acl == NULL || !acl->iac_attach(vap))
2257                                         return -EINVAL;
2258                                 vap->iv_acl = acl;
2259                         }
2260                         acl->iac_setpolicy(vap, value);
2261                         break;
2262                 case IEEE80211_MACCMD_FLUSH:
2263                         if (acl != NULL)
2264                                 acl->iac_flush(vap);
2265                         /* NB: silently ignore when not in use */
2266                         break;
2267                 case IEEE80211_MACCMD_DETACH:
2268                         if (acl != NULL) {
2269                                 vap->iv_acl = NULL;
2270                                 acl->iac_detach(vap);
2271                         }
2272                         break;
2273                 }
2274                 break;
2275         case IEEE80211_PARAM_WMM:
2276                 if (ic->ic_caps & IEEE80211_C_WME){
2277                         if (value) {
2278                                 vap->iv_flags |= IEEE80211_F_WME;
2279                                 vap->iv_ic->ic_flags |= IEEE80211_F_WME; /* XXX needed by ic_reset */
2280                         } else {
2281                                 vap->iv_flags &= ~IEEE80211_F_WME;
2282                                 vap->iv_ic->ic_flags &= ~IEEE80211_F_WME; /* XXX needed by ic_reset */
2283                         }
2284                         retv = ENETRESET;       /* Renegotiate for capabilities */
2285                 }
2286                 break;
2287         case IEEE80211_PARAM_HIDESSID:
2288                 if (value)
2289                         vap->iv_flags |= IEEE80211_F_HIDESSID;
2290                 else
2291                         vap->iv_flags &= ~IEEE80211_F_HIDESSID;
2292                 retv = ENETRESET;
2293                 break;
2294         case IEEE80211_PARAM_APBRIDGE:
2295                 if (value == 0)
2296                         vap->iv_flags |= IEEE80211_F_NOBRIDGE;
2297                 else
2298                         vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
2299                 break;
2300         case IEEE80211_PARAM_INACT:
2301                 vap->iv_inact_run = value / IEEE80211_INACT_WAIT;
2302                 break;
2303         case IEEE80211_PARAM_INACT_AUTH:
2304                 vap->iv_inact_auth = value / IEEE80211_INACT_WAIT;
2305                 break;
2306         case IEEE80211_PARAM_INACT_INIT:
2307                 vap->iv_inact_init = value / IEEE80211_INACT_WAIT;
2308                 break;
2309         case IEEE80211_PARAM_ABOLT:
2310                 caps = 0;
2311                 /*
2312                  * Map abolt settings to capability bits;
2313                  * this also strips unknown/unwanted bits.
2314                  */
2315                 if (value & IEEE80211_ABOLT_TURBO_PRIME)
2316                         caps |= IEEE80211_ATHC_TURBOP;
2317                 if (value & IEEE80211_ABOLT_COMPRESSION)
2318                         caps |= IEEE80211_ATHC_COMP;
2319                 if (value & IEEE80211_ABOLT_FAST_FRAME)
2320                         caps |= IEEE80211_ATHC_FF;
2321                 if (value & IEEE80211_ABOLT_XR)
2322                         caps |= IEEE80211_ATHC_XR;
2323                 if (value & IEEE80211_ABOLT_AR)
2324                         caps |= IEEE80211_ATHC_AR;
2325                 if (value & IEEE80211_ABOLT_BURST)
2326                         caps |= IEEE80211_ATHC_BURST;
2327                 /* verify requested capabilities are supported */
2328                 if ((caps & ic->ic_ath_cap) != caps)
2329                         return -EINVAL;
2330                 if (vap->iv_ath_cap != caps) {
2331                         if ((vap->iv_ath_cap ^ caps) & IEEE80211_ATHC_TURBOP) {
2332                                 /* no turbo and XR at the same time */
2333                                 if ((caps & IEEE80211_ATHC_TURBOP) && (caps & IEEE80211_ATHC_XR))
2334                                         return -EINVAL;
2335                                 if (ieee80211_set_turbo(dev,  caps & IEEE80211_ATHC_TURBOP))
2336                                         return -EINVAL;
2337                                 ieee80211_scan_flush(ic);
2338                         }
2339                         vap->iv_ath_cap = caps;
2340 #ifdef ATH_SUPERG_XR
2341                         ieee80211_setupxr(vap);
2342 #endif
2343                         retv = ENETRESET;
2344                 }
2345                 break;
2346         case IEEE80211_PARAM_DTIM_PERIOD:
2347                 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2348                     vap->iv_opmode != IEEE80211_M_IBSS)
2349                         return -EINVAL;
2350                 if (IEEE80211_DTIM_MIN <= value &&
2351                     value <= IEEE80211_DTIM_MAX) {
2352                         vap->iv_dtim_period = value;
2353                         retv = ENETRESET;               /* requires restart */
2354                 } else
2355                         retv = EINVAL;
2356                 break;
2357         case IEEE80211_PARAM_BEACON_INTERVAL:
2358                 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2359                     vap->iv_opmode != IEEE80211_M_IBSS)
2360                         return -EINVAL;
2361                 if (IEEE80211_BINTVAL_VALID(value)) {
2362                         ic->ic_lintval = value;         /* XXX multi-bss */
2363                         retv = ENETRESET;               /* requires restart */
2364                 } else
2365                         retv = EINVAL;
2366                 break;
2367         case IEEE80211_PARAM_DOTH:
2368                 if (value)
2369                         ic->ic_flags |= IEEE80211_F_DOTH;
2370                 else
2371                         ic->ic_flags &= ~IEEE80211_F_DOTH;
2372                 retv = ENETRESET;       /* XXX: need something this drastic? */
2373                 break;
2374         case IEEE80211_PARAM_SHPREAMBLE:
2375                 if (value) {
2376                         ic->ic_caps |= IEEE80211_C_SHPREAMBLE;
2377                         ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
2378                         ic->ic_flags &= ~IEEE80211_F_USEBARKER;
2379                 } else {
2380                         ic->ic_caps &= ~IEEE80211_C_SHPREAMBLE;
2381                         ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
2382                         ic->ic_flags |= IEEE80211_F_USEBARKER;
2383                 }       
2384                 retv = ENETRESET;       /* requires restart */
2385                 break;
2386         case IEEE80211_PARAM_PWRTARGET:
2387                 ic->ic_curchanmaxpwr = value;
2388                 break;
2389         case IEEE80211_PARAM_GENREASSOC:
2390                 IEEE80211_SEND_MGMT(vap->iv_bss, IEEE80211_FC0_SUBTYPE_REASSOC_REQ, 0);
2391                 break;
2392         case IEEE80211_PARAM_COMPRESSION:
2393                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_COMP, value);
2394                 break;
2395         case IEEE80211_PARAM_FF:
2396                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_FF, value);
2397                 break;
2398         case IEEE80211_PARAM_TURBO:
2399                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_TURBOP, value);
2400                 if (retv == ENETRESET) {
2401                         /* no turbo and XR at the same time */
2402                         if ((vap->iv_ath_cap & IEEE80211_ATHC_XR) && value)
2403                                 return -EINVAL;
2404                         if (ieee80211_set_turbo(dev,value))
2405                                 return -EINVAL;
2406                         ieee80211_scan_flush(ic);
2407                 }
2408                 break;
2409         case IEEE80211_PARAM_XR:
2410                 /* no turbo and XR at the same time */
2411                 if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) && value)
2412                         return -EINVAL;
2413                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_XR, value);
2414 #ifdef ATH_SUPERG_XR
2415                 ieee80211_setupxr(vap);
2416 #endif
2417                 break;
2418         case IEEE80211_PARAM_BURST:
2419                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_BURST, value);
2420                 break;
2421         case IEEE80211_PARAM_AR:
2422                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_AR, value);
2423                 break;
2424         case IEEE80211_PARAM_PUREG:
2425                 if (value)
2426                         vap->iv_flags |= IEEE80211_F_PUREG;
2427                 else
2428                         vap->iv_flags &= ~IEEE80211_F_PUREG;
2429                 /* NB: reset only if we're operating on an 11g channel */
2430                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2431                     IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2432                         retv = ENETRESET;
2433                 break;
2434         case IEEE80211_PARAM_WDS:
2435                 if (value)
2436                         vap->iv_flags_ext |= IEEE80211_FEXT_WDS;
2437                 else
2438                         vap->iv_flags_ext &= ~IEEE80211_FEXT_WDS;
2439                 break;
2440         case IEEE80211_PARAM_BGSCAN:
2441                 if (value) {
2442                         if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
2443                                 return -EINVAL;
2444                         vap->iv_flags |= IEEE80211_F_BGSCAN;
2445                 } else {
2446                         /* XXX racey? */
2447                         vap->iv_flags &= ~IEEE80211_F_BGSCAN;
2448                         ieee80211_cancel_scan(vap);     /* anything current */
2449                 }
2450                 break;
2451         case IEEE80211_PARAM_BGSCAN_IDLE:
2452                 if (value >= IEEE80211_BGSCAN_IDLE_MIN)
2453                         vap->iv_bgscanidle = msecs_to_jiffies(value);
2454                 else
2455                         retv = EINVAL;
2456                 break;
2457         case IEEE80211_PARAM_BGSCAN_INTERVAL:
2458                 if (value >= IEEE80211_BGSCAN_INTVAL_MIN)
2459                         vap->iv_bgscanintvl = value * HZ;
2460                 else
2461                         retv = EINVAL;
2462                 break;
2463         case IEEE80211_PARAM_MCAST_RATE:
2464                 /* units are in KILObits per second */
2465                 if (value >= 256 && value <= 54000)
2466                         vap->iv_mcast_rate = value;
2467                 else
2468                         retv = EINVAL;
2469                 break;
2470         case IEEE80211_PARAM_COVERAGE_CLASS:
2471                 if (value >= 0 && value <= IEEE80211_COVERAGE_CLASS_MAX) {
2472                         ic->ic_coverageclass = value;
2473                         if (IS_UP_AUTO(vap))
2474                                 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2475                         retv = 0;
2476                 } else
2477                         retv = EINVAL;
2478                 break;
2479         case IEEE80211_PARAM_COUNTRY_IE:
2480                 if (value)
2481                         ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE;
2482                 else
2483                         ic->ic_flags_ext &= ~IEEE80211_FEXT_COUNTRYIE;
2484                 retv = ENETRESET;
2485                 break;
2486         case IEEE80211_PARAM_REGCLASS:
2487                 if (value)
2488                         ic->ic_flags_ext |= IEEE80211_FEXT_REGCLASS;
2489                 else
2490                         ic->ic_flags_ext &= ~IEEE80211_FEXT_REGCLASS;
2491                 retv = ENETRESET;
2492                 break;
2493         case IEEE80211_PARAM_SCANVALID:
2494                 vap->iv_scanvalid = value * HZ;
2495                 break;
2496         case IEEE80211_PARAM_ROAM_RSSI_11A:
2497                 vap->iv_roam.rssi11a = value;
2498                 break;
2499         case IEEE80211_PARAM_ROAM_RSSI_11B:
2500                 vap->iv_roam.rssi11bOnly = value;
2501                 break;
2502         case IEEE80211_PARAM_ROAM_RSSI_11G:
2503                 vap->iv_roam.rssi11b = value;
2504                 break;
2505         case IEEE80211_PARAM_ROAM_RATE_11A:
2506                 vap->iv_roam.rate11a = value;
2507                 break;
2508         case IEEE80211_PARAM_ROAM_RATE_11B:
2509                 vap->iv_roam.rate11bOnly = value;
2510                 break;
2511         case IEEE80211_PARAM_ROAM_RATE_11G:
2512                 vap->iv_roam.rate11b = value;
2513                 break;
2514         case IEEE80211_PARAM_UAPSDINFO:
2515                 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
2516                         if (ic->ic_caps & IEEE80211_C_UAPSD) {
2517                                 if (value)
2518                                         IEEE80211_VAP_UAPSD_ENABLE(vap);
2519                                 else
2520                                         IEEE80211_VAP_UAPSD_DISABLE(vap);
2521                                 retv = ENETRESET;
2522                         }
2523                 } else if (vap->iv_opmode == IEEE80211_M_STA) {
2524                         vap->iv_uapsdinfo = value;
2525                         IEEE80211_VAP_UAPSD_ENABLE(vap);
2526                         retv = ENETRESET;
2527                 }
2528                 break;
2529         case IEEE80211_PARAM_SLEEP:
2530                 /* XXX: Forced sleep for testing. Does not actually place the
2531                  *      HW in sleep mode yet. this only makes sense for STAs.
2532                  */
2533                 if (value) {
2534                         /* goto sleep */
2535                         IEEE80211_VAP_GOTOSLEEP(vap);
2536                 } else {
2537                         /* wakeup */
2538                         IEEE80211_VAP_WAKEUP(vap);
2539                 }
2540                 ieee80211_send_nulldata(ieee80211_ref_node(vap->iv_bss));
2541                 break;
2542         case IEEE80211_PARAM_QOSNULL:
2543                 /* Force a QoS Null for testing. */
2544                 ieee80211_send_qosnulldata(vap->iv_bss, value);
2545                 break;
2546         case IEEE80211_PARAM_PSPOLL:
2547                 /* Force a PS-POLL for testing. */
2548                 ieee80211_send_pspoll(vap->iv_bss);
2549                 break;
2550         case IEEE80211_PARAM_EOSPDROP:
2551                 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
2552                         if (value)
2553                                 IEEE80211_VAP_EOSPDROP_ENABLE(vap);
2554                         else
2555                                 IEEE80211_VAP_EOSPDROP_DISABLE(vap);
2556                 }
2557                 break;
2558         case IEEE80211_PARAM_MARKDFS:
2559                 if (value)
2560                         ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS;
2561                 else
2562                         ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS;
2563                 break;
2564         default:
2565                 retv = EOPNOTSUPP;
2566                 break;
2567         }
2568 #ifdef ATH_SUPERG_XR
2569         /* set the same params on the xr vap device if exists */
2570         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR)) {
2571                 ieee80211_ioctl_setparam(vap->iv_xrvap->iv_dev,info,w,extra);
2572                 vap->iv_xrvap->iv_ath_cap &= IEEE80211_ATHC_XR; /* XR vap does not support  any superG features */
2573         } 
2574         /*
2575          * do not reset the xr vap , which is automatically 
2576          * reset by the state machine now.
2577          */
2578         if (!vap->iv_xrvap || (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))) {
2579                 if (retv == ENETRESET)
2580                         retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
2581         }
2582 #else
2583         /* XXX should any of these cause a rescan? */
2584         if (retv == ENETRESET)
2585                 retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
2586 #endif
2587         return -retv;
2588 }
2589
2590 #if 0
2591 static int
2592 cap2cipher(int flag)
2593 {
2594         switch (flag) {
2595         case IEEE80211_C_WEP:           return IEEE80211_CIPHER_WEP;
2596         case IEEE80211_C_AES:           return IEEE80211_CIPHER_AES_OCB;
2597         case IEEE80211_C_AES_CCM:       return IEEE80211_CIPHER_AES_CCM;
2598         case IEEE80211_C_CKIP:          return IEEE80211_CIPHER_CKIP;
2599         case IEEE80211_C_TKIP:          return IEEE80211_CIPHER_TKIP;
2600         }
2601         return -1;
2602 }
2603 #endif
2604
2605 static int
2606 ieee80211_ioctl_getmode(struct net_device *dev, struct iw_request_info *info,
2607         struct iw_point *wri, char *extra)
2608 {
2609         struct ieee80211vap *vap = netdev_priv(dev);
2610         struct ieee80211com *ic = vap->iv_ic;
2611         struct ifmediareq imr;
2612
2613         ic->ic_media.ifm_status(ic->ic_dev, &imr);
2614         switch (IFM_MODE(imr.ifm_active)) {
2615         case IFM_IEEE80211_11A:
2616                 strcpy(extra, "11a");
2617                 break;
2618         case IFM_IEEE80211_11B:
2619                 strcpy(extra, "11b");
2620                 break;
2621         case IFM_IEEE80211_11G:
2622                 strcpy(extra, "11g");
2623                 break;
2624         case IFM_IEEE80211_FH:
2625                 strcpy(extra, "FH");
2626                 break;
2627         case IFM_AUTO:
2628                 strcpy(extra, "auto");
2629                 break;
2630         default:
2631                 return -EINVAL;
2632         }
2633         if (ic->ic_media.ifm_media & IFM_IEEE80211_TURBO) {
2634                 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP)
2635                         strcat(extra, "T");
2636                 else
2637                         strcat(extra, "ST");
2638         }
2639         wri->length = strlen(extra);
2640         return 0;
2641 }
2642
2643 static int
2644 ieee80211_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
2645         void *w, char *extra)
2646 {
2647         struct ieee80211vap *vap = netdev_priv(dev);
2648         struct ieee80211com *ic = vap->iv_ic;
2649         struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
2650         int *param = (int *) extra;
2651         
2652         switch (param[0]) {
2653         case IEEE80211_PARAM_AUTHMODE:
2654                 if (vap->iv_flags & IEEE80211_F_WPA)
2655                         param[0] = IEEE80211_AUTH_WPA;
2656                 else
2657                         param[0] = vap->iv_bss->ni_authmode;
2658                 break;
2659         case IEEE80211_PARAM_PROTMODE:
2660                 param[0] = ic->ic_protmode;
2661                 break;
2662         case IEEE80211_PARAM_MCASTCIPHER:
2663                 param[0] = rsn->rsn_mcastcipher;
2664                 break;
2665         case IEEE80211_PARAM_MCASTKEYLEN:
2666                 param[0] = rsn->rsn_mcastkeylen;
2667                 break;
2668         case IEEE80211_PARAM_UCASTCIPHERS:
2669                 param[0] = rsn->rsn_ucastcipherset;
2670                 break;
2671         case IEEE80211_PARAM_UCASTCIPHER:
2672                 param[0] = rsn->rsn_ucastcipher;
2673                 break;
2674         case IEEE80211_PARAM_UCASTKEYLEN:
2675                 param[0] = rsn->rsn_ucastkeylen;
2676                 break;
2677         case IEEE80211_PARAM_KEYMGTALGS:
2678                 param[0] = rsn->rsn_keymgmtset;
2679                 break;
2680         case IEEE80211_PARAM_RSNCAPS:
2681                 param[0] = rsn->rsn_caps;
2682                 break;
2683         case IEEE80211_PARAM_WPA:
2684                 switch (vap->iv_flags & IEEE80211_F_WPA) {
2685                 case IEEE80211_F_WPA1:
2686                         param[0] = 1;
2687                         break;
2688                 case IEEE80211_F_WPA2:
2689                         param[0] = 2;
2690                         break;
2691                 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
2692                         param[0] = 3;
2693                         break;
2694                 default:
2695                         param[0] = 0;
2696                         break;
2697                 }
2698                 break;
2699         case IEEE80211_PARAM_ROAMING:
2700                 param[0] = ic->ic_roaming;
2701                 break;
2702         case IEEE80211_PARAM_PRIVACY:
2703                 param[0] = (vap->iv_flags & IEEE80211_F_PRIVACY) != 0;
2704                 break;
2705         case IEEE80211_PARAM_DROPUNENCRYPTED:
2706                 param[0] = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0;
2707                 break;
2708         case IEEE80211_PARAM_DROPUNENC_EAPOL:
2709                 param[0] = IEEE80211_VAP_DROPUNENC_EAPOL(vap);
2710                 break;
2711         case IEEE80211_PARAM_COUNTERMEASURES:
2712                 param[0] = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0;
2713                 break;
2714         case IEEE80211_PARAM_DRIVER_CAPS:
2715                 param[0] = vap->iv_caps;
2716                 break;
2717         case IEEE80211_PARAM_WMM:
2718                 param[0] = (vap->iv_flags & IEEE80211_F_WME) != 0;
2719                 break;
2720         case IEEE80211_PARAM_HIDESSID:
2721                 param[0] = (vap->iv_flags & IEEE80211_F_HIDESSID) != 0;
2722                 break;
2723         case IEEE80211_PARAM_APBRIDGE:
2724                 param[0] = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0;
2725                 break;
2726         case IEEE80211_PARAM_INACT:
2727                 param[0] = vap->iv_inact_run * IEEE80211_INACT_WAIT;
2728                 break;
2729         case IEEE80211_PARAM_INACT_AUTH:
2730                 param[0] = vap->iv_inact_auth * IEEE80211_INACT_WAIT;
2731                 break;
2732         case IEEE80211_PARAM_INACT_INIT:
2733                 param[0] = vap->iv_inact_init * IEEE80211_INACT_WAIT;
2734                 break;
2735         case IEEE80211_PARAM_ABOLT:
2736                 /*
2737                  * Map capability bits to abolt settings.
2738                  */
2739                 param[0] = 0;
2740                 if (vap->iv_ath_cap & IEEE80211_ATHC_COMP)
2741                         param[0] |= IEEE80211_ABOLT_COMPRESSION;
2742                 if (vap->iv_ath_cap & IEEE80211_ATHC_FF)
2743                         param[0] |= IEEE80211_ABOLT_FAST_FRAME;
2744                 if (vap->iv_ath_cap & IEEE80211_ATHC_XR)
2745                         param[0] |= IEEE80211_ABOLT_XR;
2746                 if (vap->iv_ath_cap & IEEE80211_ATHC_BURST)
2747                         param[0] |= IEEE80211_ABOLT_BURST;
2748                 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP)
2749                         param[0] |= IEEE80211_ABOLT_TURBO_PRIME;
2750                 if (vap->iv_ath_cap & IEEE80211_ATHC_AR)
2751                         param[0] |= IEEE80211_ABOLT_AR;
2752                 break;
2753         case IEEE80211_PARAM_COMPRESSION:
2754                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_COMP) != 0;
2755                 break;
2756         case IEEE80211_PARAM_FF:
2757                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_FF) != 0;
2758                 break;
2759         case IEEE80211_PARAM_XR:
2760                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_XR) != 0;
2761                 break;
2762         case IEEE80211_PARAM_BURST:
2763                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_BURST) != 0;
2764                 break;
2765         case IEEE80211_PARAM_AR:
2766                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_AR) != 0;
2767                 break;
2768         case IEEE80211_PARAM_TURBO:
2769                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) != 0;
2770                 break;
2771         case IEEE80211_PARAM_DTIM_PERIOD:
2772                 param[0] = vap->iv_dtim_period;
2773                 break;
2774         case IEEE80211_PARAM_BEACON_INTERVAL:
2775                 /* NB: get from ic_bss for station mode */
2776                 param[0] = vap->iv_bss->ni_intval;
2777                 break;
2778         case IEEE80211_PARAM_DOTH:
2779                 param[0] = (ic->ic_flags & IEEE80211_F_DOTH) != 0;
2780                 break;
2781         case IEEE80211_PARAM_SHPREAMBLE:
2782                 param[0] = (ic->ic_caps & IEEE80211_C_SHPREAMBLE) != 0;
2783                 break;
2784         case IEEE80211_PARAM_PWRTARGET:
2785                 param[0] = ic->ic_curchanmaxpwr;
2786                 break;
2787         case IEEE80211_PARAM_PUREG:
2788                 param[0] = (vap->iv_flags & IEEE80211_F_PUREG) != 0;
2789                 break;
2790         case IEEE80211_PARAM_WDS:
2791                 param[0] = ((vap->iv_flags_ext & IEEE80211_FEXT_WDS) == IEEE80211_FEXT_WDS);
2792                 break;
2793         case IEEE80211_PARAM_BGSCAN:
2794                 param[0] = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0;
2795                 break;
2796         case IEEE80211_PARAM_BGSCAN_IDLE:
2797                 param[0] = jiffies_to_msecs(vap->iv_bgscanidle); /* ms */
2798                 break;
2799         case IEEE80211_PARAM_BGSCAN_INTERVAL:
2800                 param[0] = vap->iv_bgscanintvl / HZ;    /* seconds */
2801                 break;
2802         case IEEE80211_PARAM_MCAST_RATE:
2803                 param[0] = vap->iv_mcast_rate;  /* seconds */
2804                 break;
2805         case IEEE80211_PARAM_COVERAGE_CLASS:
2806                 param[0] = ic->ic_coverageclass;
2807                 break;
2808         case IEEE80211_PARAM_COUNTRY_IE:
2809                 param[0] = (ic->ic_flags_ext & IEEE80211_FEXT_COUNTRYIE) != 0;
2810                 break;
2811         case IEEE80211_PARAM_REGCLASS:
2812                 param[0] = (ic->ic_flags_ext & IEEE80211_FEXT_REGCLASS) != 0;
2813                 break;
2814         case IEEE80211_PARAM_SCANVALID:
2815                 param[0] = vap->iv_scanvalid / HZ;      /* seconds */
2816                 break;
2817         case IEEE80211_PARAM_ROAM_RSSI_11A:
2818                 param[0] = vap->iv_roam.rssi11a;
2819                 break;
2820         case IEEE80211_PARAM_ROAM_RSSI_11B:
2821                 param[0] = vap->iv_roam.rssi11bOnly;
2822                 break;
2823         case IEEE80211_PARAM_ROAM_RSSI_11G:
2824                 param[0] = vap->iv_roam.rssi11b;
2825                 break;
2826         case IEEE80211_PARAM_ROAM_RATE_11A:
2827                 param[0] = vap->iv_roam.rate11a;
2828                 break;
2829         case IEEE80211_PARAM_ROAM_RATE_11B:
2830                 param[0] = vap->iv_roam.rate11bOnly;
2831                 break;
2832         case IEEE80211_PARAM_ROAM_RATE_11G:
2833                 param[0] = vap->iv_roam.rate11b;
2834                 break;
2835         case IEEE80211_PARAM_UAPSDINFO:
2836                 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
2837                         if (IEEE80211_VAP_UAPSD_ENABLED(vap))
2838                                 param[0] = 1;
2839                         else
2840                                 param[0] = 0;
2841                 } else if (vap->iv_opmode == IEEE80211_M_STA)
2842                         param[0] = vap->iv_uapsdinfo;
2843                 break;
2844         case IEEE80211_PARAM_SLEEP:
2845                 param[0] = vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT;
2846                 break;
2847         case IEEE80211_PARAM_EOSPDROP:
2848                 param[0] = IEEE80211_VAP_EOSPDROP_ENABLED(vap);
2849                 break;
2850         case IEEE80211_PARAM_MARKDFS:
2851                 if (ic->ic_flags_ext & IEEE80211_FEXT_MARKDFS)
2852                         param[0] = 1;
2853                 else
2854                         param[0] = 0;
2855                 break;
2856         default:
2857                 return -EOPNOTSUPP;
2858         }
2859         return 0;
2860 }
2861
2862 /* returns non-zero if ID is for a system IE (not for app use) */
2863 static int
2864 is_sys_ie(u_int8_t ie_id)
2865 {
2866         /* XXX review this list */
2867         switch (ie_id) {
2868         case IEEE80211_ELEMID_SSID:
2869         case IEEE80211_ELEMID_RATES:
2870         case IEEE80211_ELEMID_FHPARMS:
2871         case IEEE80211_ELEMID_DSPARMS:
2872         case IEEE80211_ELEMID_CFPARMS:
2873         case IEEE80211_ELEMID_TIM:
2874         case IEEE80211_ELEMID_IBSSPARMS:
2875         case IEEE80211_ELEMID_COUNTRY:
2876         case IEEE80211_ELEMID_REQINFO:
2877         case IEEE80211_ELEMID_CHALLENGE:
2878         case IEEE80211_ELEMID_PWRCNSTR:
2879         case IEEE80211_ELEMID_PWRCAP:
2880         case IEEE80211_ELEMID_TPCREQ:
2881         case IEEE80211_ELEMID_TPCREP:
2882         case IEEE80211_ELEMID_SUPPCHAN:
2883         case IEEE80211_ELEMID_CHANSWITCHANN:
2884         case IEEE80211_ELEMID_MEASREQ:
2885         case IEEE80211_ELEMID_MEASREP:
2886         case IEEE80211_ELEMID_QUIET:
2887         case IEEE80211_ELEMID_IBSSDFS:
2888         case IEEE80211_ELEMID_ERP:
2889         case IEEE80211_ELEMID_RSN:
2890         case IEEE80211_ELEMID_XRATES:
2891         case IEEE80211_ELEMID_TPC:
2892         case IEEE80211_ELEMID_CCKM:
2893                 return 1;
2894         default:
2895                 return 0;
2896         }
2897 }
2898
2899 /* returns non-zero if the buffer appears to contain a valid IE list */
2900 static int
2901 is_valid_ie_list(u_int32_t buf_len, void *buf, int exclude_sys_ies)
2902 {
2903         struct ieee80211_ie *ie = (struct ieee80211_ie *)buf;
2904
2905         while (buf_len >= sizeof(*ie)) {
2906                 int ie_elem_len = sizeof(*ie) + ie->len;
2907                 if (buf_len < ie_elem_len)
2908                         break;
2909                 if (exclude_sys_ies && is_sys_ie(ie->id))
2910                         break;
2911                 buf_len -= ie_elem_len;
2912                 ie = (struct ieee80211_ie *)(ie->info + ie->len);
2913         }
2914
2915         return (buf_len == 0) ? 1 : 0;
2916 }
2917
2918 static int
2919 ieee80211_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
2920         struct iw_point *wri, char *extra)
2921 {
2922         struct ieee80211vap *vap = netdev_priv(dev);
2923         void *ie;
2924
2925         /*
2926          * NB: Doing this for ap operation could be useful (e.g. for
2927          *     WPA and/or WME) except that it typically is worthless
2928          *     without being able to intervene when processing
2929          *     association response frames--so disallow it for now.
2930          */
2931         if (vap->iv_opmode != IEEE80211_M_STA)
2932                 return -EINVAL;
2933         if (! is_valid_ie_list(wri->length, extra, 0))
2934                 return -EINVAL;
2935         /* NB: wri->length is validated by the wireless extensions code */
2936         MALLOC(ie, void *, wri->length, M_DEVBUF, M_WAITOK);
2937         if (ie == NULL)
2938                 return -ENOMEM;
2939         memcpy(ie, extra, wri->length);
2940         if (vap->iv_opt_ie != NULL)
2941                 FREE(vap->iv_opt_ie, M_DEVBUF);
2942         vap->iv_opt_ie = ie;
2943         vap->iv_opt_ie_len = wri->length;
2944 #ifdef ATH_SUPERG_XR
2945         /* set the same params on the xr vap device if exists */
2946         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
2947                 ieee80211_ioctl_setoptie(vap->iv_xrvap->iv_dev, info, wri, extra);
2948 #endif
2949         return 0;
2950 }
2951
2952 static int
2953 ieee80211_ioctl_getoptie(struct net_device *dev, struct iw_request_info *info,
2954         struct iw_point *wri, char *extra)
2955 {
2956         struct ieee80211vap *vap = netdev_priv(dev);
2957
2958         if (vap->iv_opt_ie == NULL) {
2959                 wri->length = 0;
2960                 return 0;
2961         }
2962         wri->length = vap->iv_opt_ie_len;
2963         memcpy(extra, vap->iv_opt_ie, vap->iv_opt_ie_len);
2964         return 0;
2965 }
2966
2967 /* the following functions are used by the set/get appiebuf functions */
2968 static int
2969 add_app_ie(unsigned int frame_type_index, struct ieee80211vap *vap,
2970         struct ieee80211req_getset_appiebuf *iebuf)
2971 {
2972         struct ieee80211_ie *ie;
2973
2974         if (! is_valid_ie_list(iebuf->app_buflen, iebuf->app_buf, 1))
2975                 return -EINVAL;
2976         /* NB: data.length is validated by the wireless extensions code */
2977         MALLOC(ie, struct ieee80211_ie *, iebuf->app_buflen, M_DEVBUF, M_WAITOK);
2978         if (ie == NULL)
2979                 return -ENOMEM;
2980
2981         memcpy(ie, iebuf->app_buf, iebuf->app_buflen);
2982         if (vap->app_ie[frame_type_index].ie != NULL)
2983                 FREE(vap->app_ie[frame_type_index].ie, M_DEVBUF);
2984         vap->app_ie[frame_type_index].ie = ie;
2985         vap->app_ie[frame_type_index].length = iebuf->app_buflen;
2986
2987         return 0;
2988 }
2989
2990 static int
2991 remove_app_ie(unsigned int frame_type_index, struct ieee80211vap *vap)
2992 {
2993         struct ieee80211_app_ie_t *app_ie = &vap->app_ie[frame_type_index];
2994         if (app_ie->ie != NULL) {
2995                 FREE(app_ie->ie, M_DEVBUF);
2996                 app_ie->ie = NULL;
2997                 app_ie->length = 0;
2998         }
2999         return 0;
3000 }
3001
3002 static int
3003 get_app_ie(unsigned int frame_type_index, struct ieee80211vap *vap,
3004         struct ieee80211req_getset_appiebuf *iebuf)
3005 {
3006         struct ieee80211_app_ie_t *app_ie = &vap->app_ie[frame_type_index];
3007         if (iebuf->app_buflen < app_ie->length)
3008                 return -EINVAL;
3009
3010         iebuf->app_buflen = app_ie->length;
3011         memcpy(iebuf->app_buf, app_ie->ie, app_ie->length);
3012         return 0;
3013 }
3014
3015 static int
3016 ieee80211_ioctl_setappiebuf(struct net_device *dev,
3017         struct iw_request_info *info,
3018         struct iw_point *data, char *extra)
3019 {
3020         struct ieee80211vap *vap = netdev_priv(dev);
3021         struct ieee80211req_getset_appiebuf *iebuf =
3022                 (struct ieee80211req_getset_appiebuf *)extra;
3023         enum ieee80211_opmode chk_opmode;
3024         int iebuf_len;
3025         int rc = 0;
3026
3027         iebuf_len = data->length - sizeof(struct ieee80211req_getset_appiebuf);
3028         if ( iebuf_len < 0 || iebuf_len != iebuf->app_buflen ||
3029                  iebuf->app_buflen > IEEE80211_APPIE_MAX )
3030                 return -EINVAL;
3031
3032         switch (iebuf->app_frmtype) {
3033         case IEEE80211_APPIE_FRAME_BEACON:
3034         case IEEE80211_APPIE_FRAME_PROBE_RESP:
3035         case IEEE80211_APPIE_FRAME_ASSOC_RESP:
3036                 chk_opmode = IEEE80211_M_HOSTAP;
3037                 break;
3038         case IEEE80211_APPIE_FRAME_PROBE_REQ:
3039         case IEEE80211_APPIE_FRAME_ASSOC_REQ:
3040                 chk_opmode = IEEE80211_M_STA;
3041                 break;
3042         default:
3043                 return -EINVAL;
3044         }
3045         if (vap->iv_opmode != chk_opmode)
3046                 return -EINVAL;
3047
3048         if (iebuf->app_buflen)
3049                 rc = add_app_ie(iebuf->app_frmtype, vap, iebuf);
3050         else
3051                 rc = remove_app_ie(iebuf->app_frmtype, vap);
3052         if ((iebuf->app_frmtype == IEEE80211_APPIE_FRAME_BEACON) && (rc == 0))
3053                 vap->iv_flags_ext |= IEEE80211_FEXT_APPIE_UPDATE;
3054
3055         return rc;
3056 }
3057
3058 static int
3059 ieee80211_ioctl_getappiebuf(struct net_device *dev, struct iw_request_info *info,
3060         struct iw_point *data, char *extra)
3061 {
3062         struct ieee80211vap *vap = netdev_priv(dev);
3063         struct ieee80211req_getset_appiebuf *iebuf =
3064                 (struct ieee80211req_getset_appiebuf *)extra;
3065         int max_iebuf_len;
3066         int rc = 0;
3067
3068         max_iebuf_len = data->length - sizeof(struct ieee80211req_getset_appiebuf);
3069         if (max_iebuf_len < 0)
3070                 return -EINVAL;
3071         if (copy_from_user(iebuf, data->pointer, sizeof(struct ieee80211req_getset_appiebuf)))
3072                 return -EFAULT;         
3073         if (iebuf->app_buflen > max_iebuf_len)
3074                 iebuf->app_buflen = max_iebuf_len;
3075
3076         switch (iebuf->app_frmtype) {
3077         case IEEE80211_APPIE_FRAME_BEACON:
3078         case IEEE80211_APPIE_FRAME_PROBE_RESP:
3079         case IEEE80211_APPIE_FRAME_ASSOC_RESP:
3080                 if (vap->iv_opmode == IEEE80211_M_STA)
3081                         return -EINVAL;
3082                 break;
3083         case IEEE80211_APPIE_FRAME_PROBE_REQ:
3084         case IEEE80211_APPIE_FRAME_ASSOC_REQ:
3085                 if (vap->iv_opmode != IEEE80211_M_STA)
3086                         return -EINVAL;
3087                 break;
3088         default:
3089                 return -EINVAL;
3090         }
3091
3092         rc = get_app_ie(iebuf->app_frmtype, vap, iebuf);
3093         
3094         data->length = sizeof(struct ieee80211req_getset_appiebuf) + iebuf->app_buflen;
3095         
3096         return rc;
3097 }
3098
3099 static int
3100 ieee80211_ioctl_setfilter(struct net_device *dev, struct iw_request_info *info,
3101         void *w, char *extra)
3102 {
3103         struct ieee80211vap *vap = netdev_priv(dev);
3104         struct ieee80211req_set_filter *app_filter = (struct ieee80211req_set_filter *)extra;
3105
3106         if ((extra == NULL) || (app_filter->app_filterype & ~IEEE80211_FILTER_TYPE_ALL))
3107                 return -EINVAL;
3108
3109         vap->app_filter = app_filter->app_filterype;
3110
3111         return 0;
3112 }
3113
3114 static int
3115 ieee80211_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
3116         void *w, char *extra)
3117 {
3118         struct ieee80211vap *vap = netdev_priv(dev);
3119         struct ieee80211com *ic = vap->iv_ic;
3120         struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
3121         struct ieee80211_node *ni;
3122         struct ieee80211_key *wk;
3123         u_int16_t kid;
3124         int error, flags,i;
3125
3126         /* NB: cipher support is verified by ieee80211_crypt_newkey */
3127         /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
3128         if (ik->ik_keylen > sizeof(ik->ik_keydata))
3129                 return -E2BIG;
3130         kid = ik->ik_keyix;
3131         if (kid == IEEE80211_KEYIX_NONE) {
3132                 /* XXX unicast keys currently must be tx/rx */
3133                 if (ik->ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
3134                         return -EINVAL;
3135                 if (vap->iv_opmode == IEEE80211_M_STA) {
3136                         ni = ieee80211_ref_node(vap->iv_bss);
3137                         if (!IEEE80211_ADDR_EQ(ik->ik_macaddr, ni->ni_bssid))
3138                                 return -EADDRNOTAVAIL;
3139                 } else
3140                         ni = ieee80211_find_node(&ic->ic_sta, ik->ik_macaddr);
3141                 if (ni == NULL)
3142                         return -ENOENT;
3143                 wk = &ni->ni_ucastkey;
3144         } else {
3145                 if (kid >= IEEE80211_WEP_NKID)
3146                         return -EINVAL;
3147                 wk = &vap->iv_nw_keys[kid];
3148                 ni = NULL;
3149                 /* XXX auto-add group key flag until applications are updated */
3150                 if ((ik->ik_flags & IEEE80211_KEY_XMIT) == 0)   /* XXX */
3151                         ik->ik_flags |= IEEE80211_KEY_GROUP;    /* XXX */
3152         }
3153         error = 0;
3154         flags = ik->ik_flags & IEEE80211_KEY_COMMON;
3155         ieee80211_key_update_begin(vap);
3156         if (ieee80211_crypto_newkey(vap, ik->ik_type, flags, wk)) {
3157                 wk->wk_keylen = ik->ik_keylen;
3158                 /* NB: MIC presence is implied by cipher type */
3159                 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
3160                         wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
3161                 for(i = 0; i < IEEE80211_TID_SIZE; i++)
3162                         wk->wk_keyrsc[i] = ik->ik_keyrsc;
3163                 wk->wk_keytsc = 0;                      /* new key, reset */
3164                 memset(wk->wk_key, 0, sizeof(wk->wk_key));
3165                 memcpy(wk->wk_key, ik->ik_keydata, ik->ik_keylen);
3166                 if (!ieee80211_crypto_setkey(vap, wk,
3167                     ni != NULL ? ni->ni_macaddr : ik->ik_macaddr, ni))
3168                         error = -EIO;
3169                 else if ((ik->ik_flags & IEEE80211_KEY_DEFAULT))
3170                         vap->iv_def_txkey = kid;
3171         } else
3172                 error = -ENXIO;
3173         ieee80211_key_update_end(vap);
3174         if (ni != NULL)
3175                 ieee80211_free_node(ni);
3176 #ifdef ATH_SUPERG_XR
3177         /* set the same params on the xr vap device if exists */
3178         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
3179                 ieee80211_ioctl_setkey(vap->iv_xrvap->iv_dev, info, w, extra);
3180 #endif
3181         return error;
3182 }
3183
3184 static int
3185 ieee80211_ioctl_getkey(struct net_device *dev, struct iwreq *iwr)
3186 {
3187         struct ieee80211vap *vap = netdev_priv(dev);
3188         struct ieee80211com *ic = vap->iv_ic;
3189         struct ieee80211_node *ni;
3190         struct ieee80211req_key ik;
3191         struct ieee80211_key *wk;
3192         const struct ieee80211_cipher *cip;
3193         u_int kid;
3194
3195         if (iwr->u.data.length != sizeof(ik))
3196                 return -EINVAL;
3197         if (copy_from_user(&ik, iwr->u.data.pointer, sizeof(ik)))
3198                 return -EFAULT;
3199         kid = ik.ik_keyix;
3200         if (kid == IEEE80211_KEYIX_NONE) {
3201                 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
3202                 if (ni == NULL)
3203                         return -EINVAL;         /* XXX */
3204                 wk = &ni->ni_ucastkey;
3205         } else {
3206                 if (kid >= IEEE80211_WEP_NKID)
3207                         return -EINVAL;
3208                 wk = &vap->iv_nw_keys[kid];
3209                 IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr);
3210                 ni = NULL;
3211         }
3212         cip = wk->wk_cipher;
3213         ik.ik_type = cip->ic_cipher;
3214         ik.ik_keylen = wk->wk_keylen;
3215         ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
3216         if (wk->wk_keyix == vap->iv_def_txkey)
3217                 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
3218         if (capable(CAP_NET_ADMIN)) {
3219                 /* NB: only root can read key data */
3220                 ik.ik_keyrsc = wk->wk_keyrsc[0];
3221                 ik.ik_keytsc = wk->wk_keytsc;
3222                 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
3223                 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
3224                         memcpy(ik.ik_keydata+wk->wk_keylen,
3225                                 wk->wk_key + IEEE80211_KEYBUF_SIZE,
3226                                 IEEE80211_MICBUF_SIZE);
3227                         ik.ik_keylen += IEEE80211_MICBUF_SIZE;
3228                 }
3229         } else {
3230                 ik.ik_keyrsc = 0;
3231                 ik.ik_keytsc = 0;
3232                 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
3233         }
3234         if (ni != NULL)
3235                 ieee80211_free_node(ni);
3236         return (copy_to_user(iwr->u.data.pointer, &ik, sizeof(ik)) ? -EFAULT : 0);
3237 }
3238
3239 static int
3240 ieee80211_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
3241         void *w, char *extra)
3242 {
3243         struct ieee80211vap *vap = netdev_priv(dev);
3244         struct ieee80211com *ic = vap->iv_ic;
3245         struct ieee80211req_del_key *dk = (struct ieee80211req_del_key *)extra;
3246         int kid;
3247
3248         kid = dk->idk_keyix;
3249         /* XXX u_int8_t -> u_int16_t */
3250         if (dk->idk_keyix == (u_int8_t) IEEE80211_KEYIX_NONE) {
3251                 struct ieee80211_node *ni;
3252
3253                 ni = ieee80211_find_node(&ic->ic_sta, dk->idk_macaddr);
3254                 if (ni == NULL)
3255                         return -EINVAL;         /* XXX */
3256                 /* XXX error return */
3257                 ieee80211_crypto_delkey(vap, &ni->ni_ucastkey, ni);
3258                 ieee80211_free_node(ni);
3259         } else {
3260                 if (kid >= IEEE80211_WEP_NKID)
3261                         return -EINVAL;
3262                 /* XXX error return */
3263                 ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid], NULL);
3264         }
3265         return 0;
3266 }
3267
3268 static void
3269 domlme(void *arg, struct ieee80211_node *ni)
3270 {
3271         struct ieee80211req_mlme *mlme = arg;
3272
3273         if (ni->ni_associd != 0) {
3274                 IEEE80211_SEND_MGMT(ni,
3275                         mlme->im_op == IEEE80211_MLME_DEAUTH ?
3276                                 IEEE80211_FC0_SUBTYPE_DEAUTH :
3277                                 IEEE80211_FC0_SUBTYPE_DISASSOC,
3278                         mlme->im_reason);
3279         }
3280         ieee80211_node_leave(ni);
3281 }
3282
3283 struct scanlookup {             /* XXX: right place for declaration? */
3284         const u_int8_t *mac;
3285         int esslen;
3286         const u_int8_t *essid;
3287         const struct ieee80211_scan_entry *se;
3288 };
3289
3290 /*
3291  * Match mac address and any ssid.
3292  */
3293 static int
3294 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
3295 {
3296         struct scanlookup *look = arg;
3297
3298         if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
3299                 return 0;
3300         if (look->esslen != 0) {
3301                 if (se->se_ssid[1] != look->esslen)
3302                         return 0;
3303                 if (memcmp(look->essid, se->se_ssid + 2, look->esslen))
3304                         return 0;
3305         }
3306         look->se = se;
3307
3308         return 0;
3309 }
3310
3311 static int
3312 ieee80211_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
3313         void *w, char *extra)
3314 {
3315         struct ieee80211vap *vap = netdev_priv(dev);
3316         struct ieee80211com *ic = vap->iv_ic;
3317         struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
3318         struct ieee80211_node *ni;
3319
3320         if (!IS_UP(dev)) {
3321                 switch (mlme->im_op) {
3322                 case IEEE80211_MLME_DISASSOC:
3323                 case IEEE80211_MLME_DEAUTH:
3324                 case IEEE80211_MLME_UNAUTHORIZE:
3325                         return 0;
3326                 default:
3327                         return -ENETDOWN;
3328                 }
3329         }
3330         switch (mlme->im_op) {
3331         case IEEE80211_MLME_ASSOC:
3332                 if (vap->iv_opmode == IEEE80211_M_STA) {
3333                         struct scanlookup lookup;
3334
3335                         lookup.se = NULL;
3336                         lookup.mac = mlme->im_macaddr;
3337                         /* XXX use revised api w/ explicit ssid */
3338                         lookup.esslen = vap->iv_des_ssid[0].len;
3339                         lookup.essid = vap->iv_des_ssid[0].ssid;
3340                         ieee80211_scan_iterate(ic, mlmelookup, &lookup);
3341                         if (lookup.se != NULL) {
3342                                 vap->iv_nsdone = 0;
3343                                 vap->iv_nsparams.result = 0;
3344                                 if (ieee80211_sta_join(vap, lookup.se))
3345                                         while (!vap->iv_nsdone)
3346                                                 IEEE80211_RESCHEDULE();
3347                                 if (vap->iv_nsparams.result)
3348                                         return 0;
3349                         }
3350                 }
3351                 return -EINVAL;
3352         case IEEE80211_MLME_DISASSOC:
3353         case IEEE80211_MLME_DEAUTH:
3354                 switch (vap->iv_opmode) {
3355                 case IEEE80211_M_STA:
3356                         /* XXX not quite right */
3357                         ieee80211_new_state(vap, IEEE80211_S_INIT,
3358                                 mlme->im_reason);
3359                         break;
3360                 case IEEE80211_M_HOSTAP:
3361                         /* NB: the broadcast address means do 'em all */
3362                         if (!IEEE80211_ADDR_EQ(mlme->im_macaddr, vap->iv_dev->broadcast)) {
3363                                 ni = ieee80211_find_node(&ic->ic_sta,
3364                                         mlme->im_macaddr);
3365                                 if (ni == NULL)
3366                                         return -EINVAL;
3367                                 if (dev == ni->ni_vap->iv_dev)
3368                                         domlme(mlme, ni);
3369                                 ieee80211_free_node(ni);
3370                         } else
3371                                 ieee80211_iterate_dev_nodes(dev, &ic->ic_sta, domlme, mlme);
3372                         break;
3373                 default:
3374                         return -EINVAL;
3375                 }
3376                 break;
3377         case IEEE80211_MLME_AUTHORIZE:
3378         case IEEE80211_MLME_UNAUTHORIZE:
3379                 if (vap->iv_opmode != IEEE80211_M_HOSTAP)
3380                         return -EINVAL;
3381                 ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
3382                 if (ni == NULL)
3383                         return -EINVAL;
3384                 if (mlme->im_op == IEEE80211_MLME_AUTHORIZE)
3385                         ieee80211_node_authorize(ni);
3386                 else
3387                         ieee80211_node_unauthorize(ni);
3388                 ieee80211_free_node(ni);
3389                 break;
3390         case IEEE80211_MLME_CLEAR_STATS:
3391                 if (vap->iv_opmode != IEEE80211_M_HOSTAP)
3392                         return -EINVAL;
3393                 ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
3394                 if (ni == NULL)
3395                         return -ENOENT;
3396                 
3397                 /* clear statistics */
3398                 memset(&ni->ni_stats, 0, sizeof(struct ieee80211_nodestats));
3399                 ieee80211_free_node(ni);
3400                 break;
3401         default:
3402                 return -EINVAL;
3403         }
3404         return 0;
3405 }
3406
3407 static int
3408 ieee80211_ioctl_wdsmac(struct net_device *dev, struct iw_request_info *info,
3409         void *w, char *extra)
3410 {
3411         struct ieee80211vap *vap = netdev_priv(dev);
3412         struct sockaddr *sa = (struct sockaddr *)extra;
3413         struct ieee80211com *ic = vap->iv_ic;
3414
3415         if (!IEEE80211_ADDR_NULL(vap->wds_mac)) {
3416                 printk("%s: Failed to add WDS MAC: %s\n", dev->name,
3417                         ether_sprintf(sa->sa_data));
3418                 printk("%s: Device already has WDS mac address attached,"
3419                         " remove first\n", dev->name);
3420                 return -1;
3421         }
3422
3423         memcpy(vap->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN);
3424
3425         printk("%s: Added WDS MAC: %s\n", dev->name,
3426                 ether_sprintf(vap->wds_mac));
3427
3428         if (IS_UP(vap->iv_dev))
3429                 return ic->ic_reset(ic->ic_dev);
3430
3431         return 0;
3432 }
3433
3434 static int
3435 ieee80211_ioctl_wdsdelmac(struct net_device *dev, struct iw_request_info *info,
3436         void *w, char *extra)
3437 {
3438         struct ieee80211vap *vap = netdev_priv(dev);
3439         struct sockaddr *sa = (struct sockaddr *)extra;
3440         struct ieee80211com *ic = vap->iv_ic;
3441
3442         /* WDS Mac address filed already? */
3443         if (IEEE80211_ADDR_NULL(vap->wds_mac))
3444                 return 0;
3445
3446         /* Compare suplied MAC address with WDS MAC of this interface 
3447          * remove when mac address is known
3448          */
3449         if (memcmp(vap->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN) == 0) {
3450                 memset(vap->wds_mac, 0x00, IEEE80211_ADDR_LEN);
3451                 if (IS_UP(vap->iv_dev))
3452                         return ic->ic_reset(ic->ic_dev);
3453                 return 0;                        
3454         }
3455
3456         printk("%s: WDS MAC address %s is not known by this interface\n",
3457                dev->name, ether_sprintf(sa->sa_data));
3458
3459         return -1;
3460 }
3461
3462 /*
3463  * kick associated station with the given MAC address.
3464  */
3465 static int
3466 ieee80211_ioctl_kickmac(struct net_device *dev, struct iw_request_info *info,
3467         void *w, char *extra)
3468 {
3469         struct sockaddr *sa = (struct sockaddr *)extra;
3470         struct ieee80211req_mlme mlme;
3471         
3472         if (sa->sa_family != ARPHRD_ETHER)
3473                 return -EINVAL;
3474
3475         /* Setup a MLME request for disassociation of the given MAC */
3476         mlme.im_op = IEEE80211_MLME_DISASSOC;
3477         mlme.im_reason = IEEE80211_REASON_UNSPECIFIED;
3478         IEEE80211_ADDR_COPY(&(mlme.im_macaddr), sa->sa_data);
3479
3480         /* Send the MLME request and return the result. */
3481         return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme);
3482 }
3483
3484 static int
3485 ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
3486         void *w, char *extra)
3487 {
3488         struct ieee80211vap *vap = netdev_priv(dev);
3489         struct sockaddr *sa = (struct sockaddr *)extra;
3490         const struct ieee80211_aclator *acl = vap->iv_acl;
3491
3492         if (acl == NULL) {
3493                 acl = ieee80211_aclator_get("mac");
3494                 if (acl == NULL || !acl->iac_attach(vap))
3495                         return -EINVAL;
3496                 vap->iv_acl = acl;
3497         }
3498         acl->iac_add(vap, sa->sa_data);
3499         return 0;
3500 }
3501
3502 static int
3503 ieee80211_ioctl_delmac(struct net_device *dev, struct iw_request_info *info,
3504         void *w, char *extra)
3505 {
3506         struct ieee80211vap *vap = netdev_priv(dev);
3507         struct sockaddr *sa = (struct sockaddr *)extra;
3508         const struct ieee80211_aclator *acl = vap->iv_acl;
3509
3510         if (acl == NULL) {
3511                 acl = ieee80211_aclator_get("mac");
3512                 if (acl == NULL || !acl->iac_attach(vap))
3513                         return -EINVAL;
3514                 vap->iv_acl = acl;
3515         }
3516         acl->iac_remove(vap, sa->sa_data);
3517         return 0;
3518 }
3519
3520 static int
3521 ieee80211_ioctl_setchanlist(struct net_device *dev,
3522         struct iw_request_info *info, void *w, char *extra)
3523 {
3524         struct ieee80211vap *vap = netdev_priv(dev);
3525         struct ieee80211com *ic = vap->iv_ic;
3526         struct ieee80211req_chanlist *list =
3527                 (struct ieee80211req_chanlist *)extra;
3528         u_char chanlist[IEEE80211_CHAN_BYTES];
3529         int i, j, nchan;
3530
3531         memset(chanlist, 0, sizeof(chanlist));
3532         /*
3533          * Since channel 0 is not available for DS, channel 1
3534          * is assigned to LSB on WaveLAN.
3535          */
3536         if (ic->ic_phytype == IEEE80211_T_DS)
3537                 i = 1;
3538         else
3539                 i = 0;
3540         nchan = 0;
3541         for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
3542                 /*
3543                  * NB: silently discard unavailable channels so users
3544                  *     can specify 1-255 to get all available channels.
3545                  */
3546                 if (isset(list->ic_channels, j) && isset(ic->ic_chan_avail, i)) {
3547                         setbit(chanlist, i);
3548                         nchan++;
3549                 }
3550         }
3551         if (nchan == 0)                 /* no valid channels, disallow */
3552                 return -EINVAL;
3553         if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&    /* XXX */
3554             isclr(chanlist, ic->ic_bsschan->ic_ieee))
3555                 ic->ic_bsschan = IEEE80211_CHAN_ANYC;   /* invalidate */
3556         memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
3557         if (IS_UP_AUTO(vap))
3558                 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
3559         return 0;
3560 }
3561
3562 static int
3563 ieee80211_ioctl_getchanlist(struct net_device *dev,
3564         struct iw_request_info *info, void *w, char *extra)
3565 {
3566         struct ieee80211vap *vap = netdev_priv(dev);
3567         struct ieee80211com *ic = vap->iv_ic;
3568
3569         memcpy(extra, ic->ic_chan_active, sizeof(ic->ic_chan_active));
3570         return 0;
3571 }
3572
3573 static int
3574 ieee80211_ioctl_getchaninfo(struct net_device *dev,
3575         struct iw_request_info *info, void *w, char *extra)
3576 {
3577         struct ieee80211vap *vap = netdev_priv(dev);
3578         struct ieee80211com *ic = vap->iv_ic;
3579         struct ieee80211req_chaninfo *chans =
3580                 (struct ieee80211req_chaninfo *) extra;
3581         u_int8_t reported[IEEE80211_CHAN_BYTES];        /* XXX stack usage? */
3582         int i;
3583
3584         memset(chans, 0, sizeof(*chans));
3585         memset(reported, 0, sizeof(reported));
3586         for (i = 0; i < ic->ic_nchans; i++) {
3587                 const struct ieee80211_channel *c = &ic->ic_channels[i];
3588                 const struct ieee80211_channel *c1 = c;
3589
3590                 if (isclr(reported, c->ic_ieee)) {
3591                         setbit(reported, c->ic_ieee);
3592
3593                         /* pick turbo channel over non-turbo channel, and
3594                          * 11g channel over 11b channel */
3595                         if (IEEE80211_IS_CHAN_A(c))
3596                                 c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_A);
3597                         if (IEEE80211_IS_CHAN_ANYG(c))
3598                                 c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G);
3599                         else if (IEEE80211_IS_CHAN_B(c)) {
3600                                 c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G);
3601                                 if (!c1)
3602                                         c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_11G);
3603                         }
3604
3605                         if (c1)
3606                                 c = c1;
3607                         chans->ic_chans[chans->ic_nchans].ic_ieee = c->ic_ieee;
3608                         chans->ic_chans[chans->ic_nchans].ic_freq = c->ic_freq;
3609                         chans->ic_chans[chans->ic_nchans].ic_flags = c->ic_flags;
3610                         if (++chans->ic_nchans >= IEEE80211_CHAN_MAX)
3611                                 break;
3612                 }
3613         }
3614         return 0;
3615 }
3616
3617 static int
3618 ieee80211_ioctl_setwmmparams(struct net_device *dev,
3619         struct iw_request_info *info, void *w, char *extra)
3620 {
3621         struct ieee80211vap *vap = netdev_priv(dev);
3622         int *param = (int *) extra;
3623         int ac = (param[1] >= 0 && param[1] < WME_NUM_AC) ?
3624                 param[1] : WME_AC_BE;
3625         int bss = param[2]; 
3626         struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme;
3627
3628         switch (param[0]) {
3629         case IEEE80211_WMMPARAMS_CWMIN:
3630                 if (param[3] < 0 || param[3] > 15) 
3631                         return -EINVAL;
3632                 if (bss) {
3633                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3634                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3635                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3636                 } else {
3637                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3638                         wme->wme_chanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3639                 }
3640                 ieee80211_wme_updateparams(vap);        
3641                 break;
3642         case IEEE80211_WMMPARAMS_CWMAX:
3643                 if (param[3] < 0 || param[3] > 15) 
3644                         return -EINVAL;
3645                 if (bss) {
3646                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3647                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3648                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3649                 } else {
3650                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3651                         wme->wme_chanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3652                 }
3653                 ieee80211_wme_updateparams(vap);        
3654                 break;
3655         case IEEE80211_WMMPARAMS_AIFS:
3656                 if (param[3] < 0 || param[3] > 15) 
3657                         return -EINVAL; 
3658                 if (bss) {
3659                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3660                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3661                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3662                 } else {
3663                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3664                         wme->wme_chanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3665                 }
3666                 ieee80211_wme_updateparams(vap);        
3667                 break;
3668         case IEEE80211_WMMPARAMS_TXOPLIMIT:
3669                 if (param[3] < 0 || param[3] > 8192) 
3670                         return -EINVAL;
3671                 if (bss) {
3672                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_txopLimit 
3673                                 = IEEE80211_US_TO_TXOP(param[3]);
3674                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3675                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_txopLimit =
3676                                         IEEE80211_US_TO_TXOP(param[3]);
3677                 } else {
3678                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_txopLimit 
3679                                 = IEEE80211_US_TO_TXOP(param[3]);
3680                         wme->wme_chanParams.cap_wmeParams[ac].wmep_txopLimit 
3681                                 = IEEE80211_US_TO_TXOP(param[3]);
3682                 }
3683                 ieee80211_wme_updateparams(vap);        
3684                 break;
3685         case IEEE80211_WMMPARAMS_ACM:
3686