[svn-upgrade] new version madwifi (0.9.4+r4139.20110504)
[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 4139 2011-05-03 22:07:34Z 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                 if (ic->ic_flags & IEEE80211_F_PMGTON)
1242                         ic->ic_flags &= ~IEEE80211_F_PMGTON;
1243         } else {
1244         switch (wrq->flags & IW_POWER_MODE) {
1245         case IW_POWER_UNICAST_R:
1246         case IW_POWER_ALL_R:
1247         case IW_POWER_ON:
1248                         if (wrq->flags & IW_POWER_PERIOD) {
1249                                 if (IEEE80211_BINTVAL_VALID(wrq->value))
1250                                         ic->ic_lintval = IEEE80211_MS_TO_TU(wrq->value);
1251                                 else
1252                 return -EINVAL;
1253         }
1254                         if (wrq->flags & IW_POWER_TIMEOUT)
1255                 ic->ic_holdover = IEEE80211_MS_TO_TU(wrq->value);
1256                         
1257                 ic->ic_flags |= IEEE80211_F_PMGTON;
1258                         break;
1259                 default:
1260                         return -EINVAL;
1261         }
1262         }
1263         
1264         return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;
1265 }
1266
1267 static int
1268 ieee80211_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info,
1269         struct iw_param *rrq, char *extra)
1270 {
1271         struct ieee80211vap *vap = netdev_priv(dev);
1272         struct ieee80211com *ic = vap->iv_ic;
1273
1274         rrq->disabled = (ic->ic_flags & IEEE80211_F_PMGTON) == 0;
1275         if (!rrq->disabled) {
1276                 switch (rrq->flags & IW_POWER_TYPE) {
1277                 case IW_POWER_TIMEOUT:
1278                         rrq->flags = IW_POWER_TIMEOUT;
1279                         rrq->value = IEEE80211_TU_TO_MS(ic->ic_holdover);
1280                         break;
1281                 case IW_POWER_PERIOD:
1282                         rrq->flags = IW_POWER_PERIOD;
1283                         rrq->value = IEEE80211_TU_TO_MS(ic->ic_lintval);
1284                         break;
1285                 }
1286                 rrq->flags |= IW_POWER_ALL_R;
1287         }
1288         return 0;
1289 }
1290
1291 static int
1292 ieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info,
1293         struct iw_param *rrq, char *extra)
1294 {
1295         struct ieee80211vap *vap = netdev_priv(dev);
1296         struct ieee80211com *ic = vap->iv_ic;
1297
1298         if (rrq->disabled) {
1299                 if (vap->iv_flags & IEEE80211_F_SWRETRY) {
1300                         vap->iv_flags &= ~IEEE80211_F_SWRETRY;
1301                         goto done;
1302                 }
1303                 return 0;
1304         }
1305
1306         if ((vap->iv_caps & IEEE80211_C_SWRETRY) == 0)
1307                 return -EOPNOTSUPP;
1308         if (rrq->flags == IW_RETRY_LIMIT) {
1309                 if (rrq->value >= 0) {
1310                         vap->iv_txmin = rrq->value;
1311                         vap->iv_txmax = rrq->value;     /* XXX */
1312                         vap->iv_txlifetime = 0;         /* XXX */
1313                         vap->iv_flags |= IEEE80211_F_SWRETRY;
1314                 } else {
1315                         vap->iv_flags &= ~IEEE80211_F_SWRETRY;
1316                 }
1317                 return 0;
1318         }
1319 done:
1320         return IS_UP(vap->iv_dev) ? ic->ic_reset(vap->iv_dev) : 0;
1321 }
1322
1323 static int
1324 ieee80211_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info,
1325         struct iw_param *rrq, char *extra)
1326 {
1327         struct ieee80211vap *vap = netdev_priv(dev);
1328
1329         rrq->disabled = (vap->iv_flags & IEEE80211_F_SWRETRY) == 0;
1330         if (!rrq->disabled) {
1331                 switch (rrq->flags & IW_RETRY_TYPE) {
1332                 case IW_RETRY_LIFETIME:
1333                         rrq->flags = IW_RETRY_LIFETIME;
1334                         rrq->value = IEEE80211_TU_TO_MS(vap->iv_txlifetime);
1335                         break;
1336                 case IW_RETRY_LIMIT:
1337                         rrq->flags = IW_RETRY_LIMIT;
1338                         switch (rrq->flags & IW_RETRY_MODIFIER) {
1339                         case IW_RETRY_MIN:
1340                                 rrq->flags |= IW_RETRY_MAX;
1341                                 rrq->value = vap->iv_txmin;
1342                                 break;
1343                         case IW_RETRY_MAX:
1344                                 rrq->flags |= IW_RETRY_MAX;
1345                                 rrq->value = vap->iv_txmax;
1346                                 break;
1347                         }
1348                         break;
1349                 }
1350         }
1351         return 0;
1352 }
1353
1354 static int
1355 ieee80211_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info,
1356         struct iw_param *rrq, char *extra)
1357 {
1358         struct ieee80211vap *vap = netdev_priv(dev);
1359         struct ieee80211com *ic = vap->iv_ic;
1360         int fixed, disabled;
1361
1362         fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED);
1363         disabled = (fixed && vap->iv_bss->ni_txpower == 0);
1364         if (rrq->disabled) {
1365                 if (!disabled) {
1366                         if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
1367                                 return -EOPNOTSUPP;
1368                         ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
1369                         vap->iv_bss->ni_txpower = 0;
1370                         goto done;
1371                 }
1372                 return 0;
1373         }
1374
1375         if (rrq->fixed) {
1376                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
1377                         return -EOPNOTSUPP;
1378                 if (rrq->flags != IW_TXPOW_DBM)
1379                         return -EOPNOTSUPP;
1380                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
1381                         if (ic->ic_bsschan->ic_maxregpower >= rrq->value &&
1382                             ic->ic_txpowlimit/2 >= rrq->value) {
1383                                 vap->iv_bss->ni_txpower = 2 * rrq->value;
1384                                 ic->ic_newtxpowlimit = 2 * rrq->value;
1385                                 ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
1386                         } else
1387                                 return -EINVAL;
1388                 } else {
1389                         /*
1390                          * No channel set yet
1391                          */
1392                         if (ic->ic_txpowlimit/2 >= rrq->value) {
1393                                 vap->iv_bss->ni_txpower = 2 * rrq->value;
1394                                 ic->ic_newtxpowlimit = 2 * rrq->value;
1395                                 ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
1396                         }
1397                         else
1398                                 return -EINVAL;
1399                 }
1400         } else {
1401                 if (!fixed)             /* no change */
1402                         return 0;
1403                 ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED;
1404         }
1405 done:
1406         return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;
1407 }
1408
1409 static int
1410 ieee80211_ioctl_giwtxpow(struct net_device *dev, struct iw_request_info *info,
1411         struct iw_param *rrq, char *extra)
1412 {
1413         struct ieee80211vap *vap = netdev_priv(dev);
1414         struct ieee80211com *ic = vap->iv_ic;
1415
1416         rrq->value = vap->iv_bss->ni_txpower / 2;
1417         rrq->fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) != 0;
1418         rrq->disabled = (rrq->fixed && rrq->value == 0);
1419         rrq->flags = IW_TXPOW_DBM;
1420         return 0;
1421 }
1422
1423 struct waplistreq {     /* XXX: not the right place for declaration? */
1424         struct ieee80211vap *vap;
1425         struct sockaddr addr[IW_MAX_AP];
1426         struct iw_quality qual[IW_MAX_AP];
1427         int i;
1428 };
1429
1430 static int
1431 waplist_cb(void *arg, const struct ieee80211_scan_entry *se)
1432 {
1433         struct waplistreq *req = arg;
1434         int i = req->i;
1435
1436         if (i >= IW_MAX_AP)
1437                 return 0;
1438         req->addr[i].sa_family = ARPHRD_ETHER;
1439         if (req->vap->iv_opmode == IEEE80211_M_HOSTAP)
1440                 IEEE80211_ADDR_COPY(req->addr[i].sa_data, se->se_macaddr);
1441         else
1442                 IEEE80211_ADDR_COPY(req->addr[i].sa_data, se->se_bssid);
1443         set_quality(&req->qual[i], se->se_rssi, ATH_DEFAULT_NOISE);
1444         req->i = i + 1;
1445
1446         return 0;
1447 }
1448
1449 static int
1450 ieee80211_ioctl_iwaplist(struct net_device *dev, struct iw_request_info *info,
1451         struct iw_point *data, char *extra)
1452 {
1453         struct ieee80211vap *vap = netdev_priv(dev);
1454         struct ieee80211com *ic = vap->iv_ic;
1455         struct waplistreq *req;
1456
1457         req = kmalloc(sizeof(struct waplistreq), GFP_KERNEL);
1458         if (!req)
1459                 return -ENOMEM;
1460
1461         req->vap = vap;
1462         req->i = 0;
1463         ieee80211_scan_iterate(ic, waplist_cb, req);
1464
1465         data->length = req->i;
1466         memcpy(extra, &req->addr, req->i * sizeof(req->addr[0]));
1467         data->flags = 1;                /* signal quality present (sort of) */
1468         memcpy(extra + req->i * sizeof(req->addr[0]), &req->qual,
1469                 req->i * sizeof(req->qual[0]));
1470
1471         return 0;
1472 }
1473
1474 #ifdef SIOCGIWSCAN
1475 static int
1476 ieee80211_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info,
1477         struct iw_point *data, char *extra)
1478 {
1479         struct ieee80211vap *vap = netdev_priv(dev);
1480
1481         /*
1482          * XXX don't permit a scan to be started unless we
1483          * know the device is ready.  For the moment this means
1484          * the device is marked up as this is the required to
1485          * initialize the hardware.  It would be better to permit
1486          * scanning prior to being up but that'll require some
1487          * changes to the infrastructure.
1488          */
1489         if (!IS_UP(vap->iv_dev))
1490                 return -ENETDOWN;       /* XXX */
1491         /* XXX always manual... */
1492         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1493                 "%s: active scan request\n", __func__);
1494         preempt_scan(dev, 100, 100);
1495 #if WIRELESS_EXT > 17
1496         if (data && (data->flags & IW_SCAN_THIS_ESSID)) {
1497                 struct iw_scan_req req;
1498                 struct ieee80211_scan_ssid ssid;
1499                 int copyLength;
1500                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1501                         "%s: SCAN_THIS_ESSID requested\n", __func__);
1502                 if (data->length > sizeof req) {
1503                         copyLength = sizeof req;
1504                 } else {
1505                         copyLength = data->length;
1506                 }
1507                 memset(&req, 0, sizeof req);
1508                 if (copy_from_user(&req, data->pointer, copyLength))
1509                         return -EFAULT;
1510                 memcpy(&ssid.ssid, req.essid, sizeof ssid.ssid);
1511                 ssid.len = req.essid_len;
1512                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1513                                   "%s: requesting scan of essid '%s'\n", __func__, ssid.ssid);
1514                 (void) ieee80211_start_scan(vap,
1515                         IEEE80211_SCAN_ACTIVE |
1516                         IEEE80211_SCAN_NOPICK |
1517                         IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
1518                         1, &ssid);
1519                 return 0;
1520         }
1521 #endif           
1522         (void) ieee80211_start_scan(vap, IEEE80211_SCAN_ACTIVE |
1523                 IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_ONCE,
1524                 IEEE80211_SCAN_FOREVER,
1525                 /* XXX use ioctl params */
1526                 vap->iv_des_nssid, vap->iv_des_ssid);
1527         return 0;
1528 }
1529
1530 #if WIRELESS_EXT > 14
1531 /*
1532  * Encode a WPA or RSN information element as a custom
1533  * element using the hostap format.
1534  */
1535 static u_int
1536 encode_ie(void *buf, size_t bufsize, const u_int8_t *ie, size_t ielen,
1537         const char *leader, size_t leader_len)
1538 {
1539         u_int8_t *p;
1540         int i;
1541
1542         if (bufsize < leader_len)
1543                 return 0;
1544         p = buf;
1545         memcpy(p, leader, leader_len);
1546         bufsize -= leader_len;
1547         p += leader_len;
1548         for (i = 0; i < ielen && bufsize > 2; i++) {
1549                 p += sprintf(p, "%02x", ie[i]);
1550                 bufsize -= 2;
1551         }
1552         return (i == ielen ? p - (u_int8_t *)buf : 0);
1553 }
1554 #endif /* WIRELESS_EXT > 14 */
1555
1556 struct iwscanreq {              /* XXX: right place for this declaration? */
1557         struct ieee80211vap *vap;
1558         struct iw_request_info *info;
1559         char *current_ev;
1560         char *end_buf;
1561         int mode;
1562 };
1563
1564 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) && !defined(IW_REQUEST_FLAG_COMPAT)
1565 #define iwe_stream_add_event(a, b, c, d, e)     iwe_stream_add_event(b, c, d, e)
1566 #define iwe_stream_add_point(a, b, c, d, e)     iwe_stream_add_point(b, c, d, e)
1567 #define iwe_stream_add_value(a, b, c, d, e, f)  \
1568         iwe_stream_add_value(b, c, d, e, f)
1569 #define iwe_stream_lcp_len(a)                   IW_EV_LCP_LEN
1570 #endif
1571 static int
1572 giwscan_cb(void *arg, const struct ieee80211_scan_entry *se)
1573 {
1574         struct iwscanreq *req = arg;
1575         struct ieee80211vap *vap = req->vap;
1576         char *current_ev = req->current_ev;
1577         char *end_buf = req->end_buf;
1578         char *last_ev;
1579 #if WIRELESS_EXT > 14
1580 #define MAX_IE_LENGTH 64 * 2 + 30
1581         char buf[MAX_IE_LENGTH];
1582 #ifndef IWEVGENIE
1583         static const char rsn_leader[] = "rsn_ie=";
1584         static const char wpa_leader[] = "wpa_ie=";
1585 #endif
1586 #endif
1587         struct iw_event iwe;
1588         char *current_val;
1589         int j;
1590
1591         if (current_ev >= end_buf)
1592                 return E2BIG;
1593         /* WPA/!WPA sort criteria */
1594         if ((req->mode != 0) ^ (se->se_wpa_ie != NULL))
1595                 return 0;
1596
1597         memset(&iwe, 0, sizeof(iwe));
1598         last_ev = current_ev;
1599         iwe.cmd = SIOCGIWAP;
1600         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1601         if (vap->iv_opmode == IEEE80211_M_HOSTAP)
1602                 IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_macaddr);
1603         else
1604                 IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_bssid);
1605         current_ev = iwe_stream_add_event(req->info, current_ev, end_buf,
1606                                         &iwe, IW_EV_ADDR_LEN);
1607
1608         /* We ran out of space in the buffer. */
1609         if (last_ev == current_ev)
1610           return E2BIG;
1611
1612         memset(&iwe, 0, sizeof(iwe));
1613         last_ev = current_ev;
1614         iwe.cmd = SIOCGIWESSID;
1615         iwe.u.data.flags = 1;
1616         if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
1617                 iwe.u.data.length = vap->iv_des_nssid > 0 ?
1618                         vap->iv_des_ssid[0].len : 0;
1619                 current_ev = iwe_stream_add_point(req->info, current_ev,
1620                         end_buf, &iwe, vap->iv_des_ssid[0].ssid);
1621         } else {
1622                 iwe.u.data.length = se->se_ssid[1];
1623                 current_ev = iwe_stream_add_point(req->info, current_ev,
1624                         end_buf, &iwe, (char *) se->se_ssid+2);
1625         }
1626
1627         /* We ran out of space in the buffer. */
1628         if (last_ev == current_ev)
1629           return E2BIG;
1630
1631         if (se->se_capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
1632                 memset(&iwe, 0, sizeof(iwe));
1633                 last_ev = current_ev;
1634                 iwe.cmd = SIOCGIWMODE;
1635                 iwe.u.mode = se->se_capinfo & IEEE80211_CAPINFO_ESS ?
1636                         IW_MODE_MASTER : IW_MODE_ADHOC;
1637                 current_ev = iwe_stream_add_event(req->info, current_ev,
1638                                 end_buf, &iwe, IW_EV_UINT_LEN);
1639
1640                 /* We ran out of space in the buffer. */
1641                 if (last_ev == current_ev)
1642                   return E2BIG;
1643         }
1644
1645         memset(&iwe, 0, sizeof(iwe));
1646         last_ev = current_ev;
1647         iwe.cmd = SIOCGIWFREQ;
1648         iwe.u.freq.m = se->se_chan->ic_freq * 100000;
1649         iwe.u.freq.e = 1;
1650         current_ev = iwe_stream_add_event(req->info, current_ev,
1651                         end_buf, &iwe, IW_EV_FREQ_LEN);
1652
1653         /* We ran out of space in the buffer. */
1654         if (last_ev == current_ev)
1655           return E2BIG;
1656
1657         memset(&iwe, 0, sizeof(iwe));
1658         last_ev = current_ev;
1659         iwe.cmd = IWEVQUAL;
1660         set_quality(&iwe.u.qual, se->se_rssi, ATH_DEFAULT_NOISE);
1661         current_ev = iwe_stream_add_event(req->info, current_ev,
1662                         end_buf, &iwe, IW_EV_QUAL_LEN);
1663
1664         /* We ran out of space in the buffer */
1665         if (last_ev == current_ev)
1666           return E2BIG;
1667
1668         memset(&iwe, 0, sizeof(iwe));
1669         last_ev = current_ev;
1670         iwe.cmd = SIOCGIWENCODE;
1671         if (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY)
1672                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1673         else
1674                 iwe.u.data.flags = IW_ENCODE_DISABLED;
1675         iwe.u.data.length = 0;
1676         current_ev = iwe_stream_add_point(req->info, current_ev,
1677                                         end_buf, &iwe, "");
1678
1679         /* We ran out of space in the buffer. */
1680         if (last_ev == current_ev)
1681           return E2BIG;
1682
1683         memset(&iwe, 0, sizeof(iwe));
1684         last_ev = current_ev;
1685         iwe.cmd = SIOCGIWRATE;
1686         current_val = current_ev + iwe_stream_lcp_len(req->info);
1687         /* NB: not sorted, does it matter? */
1688         for (j = 0; j < se->se_rates[1]; j++) {
1689                 int r = se->se_rates[2 + j] & IEEE80211_RATE_VAL;
1690                 if (r != 0) {
1691                         iwe.u.bitrate.value = r * (1000000 / 2);
1692                         current_val = iwe_stream_add_value(req->info,
1693                                         current_ev, current_val, end_buf,
1694                                         &iwe, IW_EV_PARAM_LEN);
1695                 }
1696         }
1697         for (j = 0; j < se->se_xrates[1]; j++) {
1698                 int r = se->se_xrates[2+j] & IEEE80211_RATE_VAL;
1699                 if (r != 0) {
1700                         iwe.u.bitrate.value = r * (1000000 / 2);
1701                         current_val = iwe_stream_add_value(req->info,
1702                                         current_ev, current_val, end_buf,
1703                                         &iwe, IW_EV_PARAM_LEN);
1704                 }
1705         }
1706         /* remove fixed header if no rates were added */
1707         if ((current_val - current_ev) > iwe_stream_lcp_len(req->info)) {
1708                 current_ev = current_val;
1709         } else {
1710           /* We ran out of space in the buffer. */
1711           if (last_ev == current_ev)
1712             return E2BIG;
1713         }
1714
1715 #if WIRELESS_EXT > 14
1716         memset(&iwe, 0, sizeof(iwe));
1717         last_ev = current_ev;
1718         iwe.cmd = IWEVCUSTOM;
1719         snprintf(buf, sizeof(buf), "bcn_int=%d", se->se_intval);
1720         iwe.u.data.length = strlen(buf);
1721         current_ev = iwe_stream_add_point(req->info, current_ev,
1722                                         end_buf, &iwe, buf);
1723
1724         /* We ran out of space in the buffer. */
1725         if (last_ev == current_ev)
1726           return E2BIG;
1727
1728         if (se->se_rsn_ie != NULL) {
1729           last_ev = current_ev;
1730 #ifdef IWEVGENIE
1731                 memset(&iwe, 0, sizeof(iwe));
1732                 if ((se->se_rsn_ie[1] + 2) > MAX_IE_LENGTH)
1733                         return E2BIG;
1734                 memcpy(buf, se->se_rsn_ie, se->se_rsn_ie[1] + 2);
1735                 iwe.cmd = IWEVGENIE;
1736                 iwe.u.data.length = se->se_rsn_ie[1] + 2;
1737 #else   
1738                 memset(&iwe, 0, sizeof(iwe));
1739                 iwe.cmd = IWEVCUSTOM;
1740                 if (se->se_rsn_ie[0] == IEEE80211_ELEMID_RSN)
1741                         iwe.u.data.length = encode_ie(buf, sizeof(buf),
1742                                 se->se_rsn_ie, se->se_rsn_ie[1] + 2,
1743                                 rsn_leader, sizeof(rsn_leader) - 1);
1744 #endif
1745                 if (iwe.u.data.length != 0) {
1746                         current_ev = iwe_stream_add_point(req->info,
1747                                         current_ev, end_buf, &iwe, buf);
1748                         
1749                         /* We ran out of space in the buffer */
1750                         if (last_ev == current_ev)
1751                           return E2BIG;
1752                 }
1753         }
1754
1755         if (se->se_wpa_ie != NULL) {
1756           last_ev = current_ev;
1757 #ifdef IWEVGENIE
1758                 memset(&iwe, 0, sizeof(iwe));
1759                 if ((se->se_wpa_ie[1] + 2) > MAX_IE_LENGTH)
1760                         return E2BIG;
1761                 memcpy(buf, se->se_wpa_ie, se->se_wpa_ie[1] + 2);
1762                 iwe.cmd = IWEVGENIE;
1763                 iwe.u.data.length = se->se_wpa_ie[1] + 2;
1764 #else
1765                 memset(&iwe, 0, sizeof(iwe));
1766                 iwe.cmd = IWEVCUSTOM;
1767                 iwe.u.data.length = encode_ie(buf, sizeof(buf),
1768                         se->se_wpa_ie, se->se_wpa_ie[1] + 2,
1769                         wpa_leader, sizeof(wpa_leader) - 1);
1770 #endif
1771                 if (iwe.u.data.length != 0) {
1772                         current_ev = iwe_stream_add_point(req->info,
1773                                         current_ev, end_buf, &iwe, buf);
1774                         
1775                         /* We ran out of space in the buffer. */
1776                         if (last_ev == current_ev)
1777                           return E2BIG;
1778                 }
1779
1780         }
1781         if (se->se_wme_ie != NULL) {
1782                 static const char wme_leader[] = "wme_ie=";
1783
1784                 memset(&iwe, 0, sizeof(iwe));
1785                 last_ev = current_ev;
1786                 iwe.cmd = IWEVCUSTOM;
1787                 iwe.u.data.length = encode_ie(buf, sizeof(buf),
1788                         se->se_wme_ie, se->se_wme_ie[1] + 2,
1789                         wme_leader, sizeof(wme_leader) - 1);
1790                 if (iwe.u.data.length != 0) {
1791                         current_ev = iwe_stream_add_point(req->info,
1792                                         current_ev, end_buf, &iwe, buf);
1793
1794                         /* We ran out of space in the buffer. */
1795                         if (last_ev == current_ev)
1796                           return E2BIG;
1797                 }
1798         }
1799         if (se->se_ath_ie != NULL) {
1800                 static const char ath_leader[] = "ath_ie=";
1801
1802                 memset(&iwe, 0, sizeof(iwe));
1803                 last_ev = current_ev;
1804                 iwe.cmd = IWEVCUSTOM;
1805                 iwe.u.data.length = encode_ie(buf, sizeof(buf),
1806                         se->se_ath_ie, se->se_ath_ie[1] + 2,
1807                         ath_leader, sizeof(ath_leader) - 1);
1808                 if (iwe.u.data.length != 0) {
1809                         current_ev = iwe_stream_add_point(req->info,
1810                                         current_ev, end_buf, &iwe, buf);
1811
1812                         /* We ran out of space in the buffer. */
1813                         if (last_ev == current_ev)
1814                           return E2BIG;
1815                 }
1816         }
1817 #endif /* WIRELESS_EXT > 14 */
1818         req->current_ev = current_ev;
1819
1820         return 0;
1821 }
1822
1823 static int
1824 ieee80211_ioctl_giwscan(struct net_device *dev, struct iw_request_info *info,
1825         struct iw_point *data, char *extra)
1826 {
1827         struct ieee80211vap *vap = netdev_priv(dev);
1828         struct ieee80211com *ic = vap->iv_ic;
1829         struct iwscanreq req;
1830         int res = 0;
1831
1832         req.vap = vap;
1833         req.info = info;
1834         req.current_ev = extra;
1835         if (data->length == 0) {
1836           req.end_buf = extra + IW_SCAN_MAX_DATA;
1837         } else {
1838           req.end_buf = extra + data->length;
1839         }
1840
1841         /*
1842          * NB: This is no longer needed, as long as the caller supports
1843          * large scan results.
1844          *
1845          * Do two passes to ensure WPA/non-WPA scan candidates
1846          * are sorted to the front.  This is a hack to deal with
1847          * the wireless extensions capping scan results at
1848          * IW_SCAN_MAX_DATA bytes.  In densely populated environments
1849          * it's easy to overflow this buffer (especially with WPA/RSN
1850          * information elements).  Note this sorting hack does not
1851          * guarantee we won't overflow anyway.
1852          */
1853         req.mode = vap->iv_flags & IEEE80211_F_WPA;
1854         res = ieee80211_scan_iterate(ic, giwscan_cb, &req);
1855         if (res == 0) {
1856           req.mode = req.mode ? 0 : IEEE80211_F_WPA;
1857           res = ieee80211_scan_iterate(ic, giwscan_cb, &req);
1858         }
1859
1860         data->length = req.current_ev - extra;
1861
1862         if (res != 0) {
1863           return -res;
1864         }
1865
1866         return res;
1867 }
1868 #endif /* SIOCGIWSCAN */
1869
1870 static int
1871 cipher2cap(int cipher)
1872 {
1873         switch (cipher) {
1874         case IEEE80211_CIPHER_WEP:      return IEEE80211_C_WEP;
1875         case IEEE80211_CIPHER_AES_OCB:  return IEEE80211_C_AES;
1876         case IEEE80211_CIPHER_AES_CCM:  return IEEE80211_C_AES_CCM;
1877         case IEEE80211_CIPHER_CKIP:     return IEEE80211_C_CKIP;
1878         case IEEE80211_CIPHER_TKIP:     return IEEE80211_C_TKIP;
1879         }
1880         return 0;
1881 }
1882
1883 #define IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX
1884
1885 static int
1886 ieee80211_convert_mode(const char *mode)
1887 {
1888 #define TOUPPER(c) ((((c) > 0x60) && ((c) < 0x7b)) ? ((c) - 0x20) : (c))
1889         static const struct {
1890                 char *name;
1891                 int mode;
1892         } mappings[] = {
1893                 /* NB: need to order longest strings first for overlaps */ 
1894                 { "11AST" , IEEE80211_MODE_TURBO_STATIC_A },
1895                 { "AUTO"  , IEEE80211_MODE_AUTO },
1896                 { "11A"   , IEEE80211_MODE_11A },
1897                 { "11B"   , IEEE80211_MODE_11B },
1898                 { "11G"   , IEEE80211_MODE_11G },
1899                 { "FH"    , IEEE80211_MODE_FH },
1900                 { "0"     , IEEE80211_MODE_AUTO },
1901                 { "1"     , IEEE80211_MODE_11A },
1902                 { "2"     , IEEE80211_MODE_11B },
1903                 { "3"     , IEEE80211_MODE_11G },
1904                 { "4"     , IEEE80211_MODE_FH },
1905                 { "5"     , IEEE80211_MODE_TURBO_STATIC_A },
1906                 { NULL }
1907         };
1908         int i, j;
1909         const char *cp;
1910
1911         for (i = 0; mappings[i].name != NULL; i++) {
1912                 cp = mappings[i].name;
1913                 for (j = 0; j < strlen(mode) + 1; j++) {
1914                         /* convert user-specified string to upper case */
1915                         if (TOUPPER(mode[j]) != cp[j])
1916                                 break;
1917                         if (cp[j] == '\0')
1918                                 return mappings[i].mode;
1919                 }
1920         }
1921         return -1;
1922 #undef TOUPPER
1923 }
1924
1925 static int
1926 ieee80211_ioctl_setmode(struct net_device *dev, struct iw_request_info *info,
1927         struct iw_point *wri, char *extra)
1928 {
1929         struct ieee80211vap *vap = netdev_priv(dev);
1930         struct ieee80211com *ic = vap->iv_ic;
1931         struct ifreq ifr;
1932         char s[6];              /* big enough for ``11adt'' */
1933         int retv, mode, ifr_mode, itr_count;
1934
1935         if (ic->ic_media.ifm_cur == NULL)
1936                 return -EINVAL;
1937         if (wri->length > sizeof(s))            /* silently truncate */
1938                 wri->length = sizeof(s);
1939         if (copy_from_user(s, wri->pointer, wri->length))
1940                 return -EINVAL;
1941         s[sizeof(s)-1] = '\0';                  /* ensure null termination */
1942         mode = ieee80211_convert_mode(s);
1943         if (mode < 0)
1944                 return -EINVAL;
1945
1946         if(ieee80211_check_mode_consistency(ic,mode,vap->iv_des_chan)) { 
1947                 /*
1948                  * error in AP mode.
1949                  * overwrite channel selection in other modes.
1950                  */
1951                 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
1952                         return -EINVAL;
1953                 else
1954                         vap->iv_des_chan=IEEE80211_CHAN_ANYC;
1955         }
1956
1957         ifr_mode = mode;
1958         memset(&ifr, 0, sizeof(ifr));
1959         ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media &~ IFM_MMASK;
1960         if (mode == IEEE80211_MODE_TURBO_STATIC_A)
1961                 ifr_mode = IEEE80211_MODE_11A;
1962         ifr.ifr_media |= IFM_MAKEMODE(ifr_mode);
1963         retv = ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA);
1964         if ((!retv || retv == -ENETRESET) &&  mode != vap->iv_des_mode) {
1965                 ieee80211_scan_flush(ic);       /* NB: could optimize */
1966                 vap->iv_des_mode = mode;
1967                 if (IS_UP_AUTO(vap)) {
1968                         ieee80211_cancel_scan(vap);
1969                         itr_count = 0;
1970                         while((ic->ic_flags & IEEE80211_F_SCAN) != 0) {
1971                                 mdelay(1);
1972                                 if (itr_count < 100) {
1973                                         itr_count++;
1974                                         continue;
1975                                 }
1976                                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
1977                                   "%s: Timeout canceling current scan.\n",
1978                                   __func__);
1979                                 return -ETIMEDOUT;
1980                         }
1981                         ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1982                 }
1983                 retv = 0;
1984         }
1985 #ifdef ATH_SUPERG_XR
1986         /* set the same params on the xr vap device if exists */
1987         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
1988                 vap->iv_xrvap->iv_des_mode = mode;
1989 #endif
1990         return -retv;
1991 }
1992 #undef IEEE80211_MODE_TURBO_STATIC_A
1993
1994 #ifdef ATH_SUPERG_XR
1995 static void
1996 ieee80211_setupxr(struct ieee80211vap *vap)
1997 {
1998         struct net_device *dev = vap->iv_dev;
1999         struct ieee80211com *ic = vap->iv_ic;
2000         if (!(vap->iv_flags & IEEE80211_F_XR)) {
2001                 if ((vap->iv_ath_cap & IEEE80211_ATHC_XR) && !vap->iv_xrvap) { 
2002                         char name[IFNAMSIZ];
2003                         strcpy(name, dev->name);
2004                         strcat(name, "-xr");
2005                         /*
2006                          * create a new XR vap. if the normal VAP is already up,
2007                          * bring up the XR vap aswell.
2008                          */
2009                         vap->iv_ath_cap &= ~IEEE80211_ATHC_TURBOP; /* turn off turbo */ 
2010                         ieee80211_scan_flush(ic);       /* NB: could optimize */
2011                          
2012                         vap->iv_xrvap = ic->ic_vap_create(ic, name, vap->iv_unit,
2013                                 IEEE80211_M_HOSTAP,IEEE80211_VAP_XR |
2014                                 IEEE80211_CLONE_BSSID, dev);
2015                         if (!vap->iv_xrvap)
2016                                 return;
2017                         vap->iv_xrvap->iv_fragthreshold = IEEE80211_XR_FRAG_THRESHOLD;
2018                         copy_des_ssid(vap->iv_xrvap, vap);
2019                         vap->iv_xrvap->iv_des_mode = vap->iv_des_mode;
2020                 } else if (!(vap->iv_ath_cap & IEEE80211_ATHC_XR) && vap->iv_xrvap) { 
2021                         /*
2022                          * destroy the XR vap. if the XR VAP is up , bring
2023                          * it down before destroying.
2024                          */
2025                         if (vap->iv_xrvap) {
2026                                 ieee80211_stop(vap->iv_xrvap->iv_dev);
2027                                 ic->ic_vap_delete(vap->iv_xrvap);
2028                         }
2029                         vap->iv_xrvap = NULL;
2030                 }
2031         }
2032 }
2033 #endif
2034
2035 static int
2036 ieee80211_setathcap(struct ieee80211vap *vap, int cap, int setting)
2037 {
2038         struct ieee80211com *ic = vap->iv_ic;
2039         int ocap;
2040
2041         if ((ic->ic_ath_cap & cap) == 0)
2042                 return -EINVAL;
2043         ocap = vap->iv_ath_cap;
2044         if (setting)
2045                 vap->iv_ath_cap |= cap;
2046         else
2047                 vap->iv_ath_cap &= ~cap;
2048         return (vap->iv_ath_cap != ocap ? ENETRESET : 0);
2049 }
2050
2051 static int
2052 ieee80211_set_turbo(struct net_device *dev, int flag)
2053 {
2054         struct ieee80211vap *vap = netdev_priv(dev);
2055         struct ieee80211com *ic = vap->iv_ic;
2056         struct ifreq ifr;
2057         struct ieee80211vap *tmpvap = netdev_priv(dev);
2058         int nvap = 0;
2059
2060         TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next)
2061                 nvap++;
2062         if (nvap > 1 && flag )
2063                 return -EINVAL;
2064         ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media &~ IFM_MMASK;
2065         if (flag)
2066                 ifr.ifr_media |= IFM_IEEE80211_TURBO;
2067         else
2068                 ifr.ifr_media &= ~IFM_IEEE80211_TURBO;
2069         (void) ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA);
2070
2071         return 0;
2072 }
2073
2074 static int
2075 ieee80211_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
2076         void *w, char *extra)
2077 {
2078         struct ieee80211vap *vap = netdev_priv(dev);
2079         struct ieee80211com *ic = vap->iv_ic;
2080         struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
2081         int *i = (int *) extra;
2082         int param = i[0];               /* parameter id is 1st */
2083         int value = i[1];               /* NB: most values are TYPE_INT */
2084         int retv = 0;
2085         int j, caps;
2086         const struct ieee80211_authenticator *auth;
2087         const struct ieee80211_aclator *acl;
2088
2089         switch (param) {
2090         case IEEE80211_PARAM_AUTHMODE:
2091                 switch (value) {
2092                 case IEEE80211_AUTH_WPA:        /* WPA */
2093                 case IEEE80211_AUTH_8021X:      /* 802.1x */
2094                 case IEEE80211_AUTH_OPEN:       /* open */
2095                 case IEEE80211_AUTH_SHARED:     /* shared-key */
2096                 case IEEE80211_AUTH_AUTO:       /* auto */
2097                         auth = ieee80211_authenticator_get(value);
2098                         if (auth == NULL)
2099                                 return -EINVAL;
2100                         break;
2101                 default:
2102                         return -EINVAL;
2103                 }
2104                 switch (value) {
2105                 case IEEE80211_AUTH_WPA:        /* WPA w/ 802.1x */
2106                         value = IEEE80211_AUTH_8021X;
2107                         break;
2108                 case IEEE80211_AUTH_OPEN:       /* open */
2109                         vap->iv_flags &= ~(IEEE80211_F_WPA);
2110                         break;
2111                 case IEEE80211_AUTH_SHARED:     /* shared-key */
2112                 case IEEE80211_AUTH_AUTO:       /* auto */
2113                 case IEEE80211_AUTH_8021X:      /* 802.1x */
2114                         vap->iv_flags &= ~IEEE80211_F_WPA;
2115                         break;
2116                 }
2117                 /* NB: authenticator attach/detach happens on state change */
2118                 vap->iv_bss->ni_authmode = value;
2119                 /* XXX mixed/mode/usage? */
2120                 vap->iv_auth = auth;
2121                 retv = ENETRESET;
2122                 break;
2123         case IEEE80211_PARAM_PROTMODE:
2124                 if (value > IEEE80211_PROT_RTSCTS)
2125                         return -EINVAL;
2126                 ic->ic_protmode = value;
2127                 /* NB: if not operating in 11g this can wait */
2128                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2129                     IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2130                         retv = ENETRESET;
2131                 break;
2132         case IEEE80211_PARAM_MCASTCIPHER:
2133                 if ((vap->iv_caps & cipher2cap(value)) == 0 &&
2134                     !ieee80211_crypto_available(value))
2135                         return -EINVAL;
2136                 rsn->rsn_mcastcipher = value;
2137                 if (vap->iv_flags & IEEE80211_F_WPA)
2138                         retv = ENETRESET;
2139                 break;
2140         case IEEE80211_PARAM_MCASTKEYLEN:
2141                 if (!(0 < value && value <= IEEE80211_KEYBUF_SIZE))
2142                         return -EINVAL;
2143                 /* XXX no way to verify driver capability */
2144                 rsn->rsn_mcastkeylen = value;
2145                 if (vap->iv_flags & IEEE80211_F_WPA)
2146                         retv = ENETRESET;
2147                 break;
2148         case IEEE80211_PARAM_UCASTCIPHERS:
2149                 /*
2150                  * NB: this logic intentionally ignores unknown and
2151                  * unsupported ciphers so folks can specify 0xff or
2152                  * similar and get all available ciphers.
2153                  */
2154                 /* caps are really ciphers */
2155                 caps = 0;
2156                 for (j = 1; j < 32; j++)        /* NB: skip WEP */
2157                         if ((value & (1 << j)) &&
2158                             ((vap->iv_caps & cipher2cap(j)) ||
2159                              ieee80211_crypto_available(j)))
2160                                 caps |= 1 << j;
2161                 if (caps == 0)                  /* nothing available */
2162                         return -EINVAL;
2163                 /* XXX verify ciphers ok for unicast use? */
2164                 /* XXX disallow if running as it'll have no effect */
2165                 rsn->rsn_ucastcipherset = caps;
2166                 if (vap->iv_flags & IEEE80211_F_WPA)
2167                         retv = ENETRESET;
2168                 break;
2169         case IEEE80211_PARAM_UCASTCIPHER:
2170                 if ((vap->iv_caps & cipher2cap(value)) == 0 &&
2171                     !ieee80211_crypto_available(value))
2172                         return -EINVAL;
2173                 rsn->rsn_ucastcipher = value;
2174                 if (vap->iv_flags & IEEE80211_F_WPA)
2175                         retv = ENETRESET;
2176                 break;
2177         case IEEE80211_PARAM_UCASTKEYLEN:
2178                 if (!(0 < value && value <= IEEE80211_KEYBUF_SIZE))
2179                         return -EINVAL;
2180                 /* XXX no way to verify driver capability */
2181                 rsn->rsn_ucastkeylen = value;
2182                 break;
2183         case IEEE80211_PARAM_KEYMGTALGS:
2184                 /* XXX check */
2185                 rsn->rsn_keymgmtset = value;
2186                 if (vap->iv_flags & IEEE80211_F_WPA)
2187                         retv = ENETRESET;
2188                 break;
2189         case IEEE80211_PARAM_RSNCAPS:
2190                 /* XXX check */
2191                 rsn->rsn_caps = value;
2192                 if (vap->iv_flags & IEEE80211_F_WPA)
2193                         retv = ENETRESET;
2194                 break;
2195         case IEEE80211_PARAM_WPA:
2196                 if (value > 3)
2197                         return -EINVAL;
2198                 /* XXX verify ciphers available */
2199                 vap->iv_flags &= ~IEEE80211_F_WPA;
2200                 switch (value) {
2201                 case 1:
2202                         vap->iv_flags |= IEEE80211_F_WPA1;
2203                         break;
2204                 case 2:
2205                         vap->iv_flags |= IEEE80211_F_WPA2;
2206                         break;
2207                 case 3:
2208                         vap->iv_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2209                         break;
2210                 }
2211                 retv = ENETRESET;               /* XXX? */
2212                 break;
2213         case IEEE80211_PARAM_ROAMING:
2214                 if (!(IEEE80211_ROAMING_DEVICE <= value &&
2215                     value <= IEEE80211_ROAMING_MANUAL))
2216                         return -EINVAL;
2217                 ic->ic_roaming = value;
2218                 break;
2219         case IEEE80211_PARAM_PRIVACY:
2220                 if (value) {
2221                         /* XXX check for key state? */
2222                         vap->iv_flags |= IEEE80211_F_PRIVACY;
2223                 } else
2224                         vap->iv_flags &= ~IEEE80211_F_PRIVACY;
2225                 break;
2226         case IEEE80211_PARAM_DROPUNENCRYPTED:
2227                 if (value)
2228                         vap->iv_flags |= IEEE80211_F_DROPUNENC;
2229                 else
2230                         vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2231                 break;
2232         case IEEE80211_PARAM_DROPUNENC_EAPOL:
2233                 if (value)
2234                         IEEE80211_VAP_DROPUNENC_EAPOL_ENABLE(vap);
2235                 else
2236                         IEEE80211_VAP_DROPUNENC_EAPOL_DISABLE(vap);
2237                 break;
2238         case IEEE80211_PARAM_COUNTERMEASURES:
2239                 if (value) {
2240                         if ((vap->iv_flags & IEEE80211_F_WPA) == 0)
2241                                 return -EINVAL;
2242                         vap->iv_flags |= IEEE80211_F_COUNTERM;
2243                 } else
2244                         vap->iv_flags &= ~IEEE80211_F_COUNTERM;
2245                 break;
2246         case IEEE80211_PARAM_DRIVER_CAPS:
2247                 vap->iv_caps = value;           /* NB: for testing */
2248                 break;
2249         case IEEE80211_PARAM_MACCMD:
2250                 acl = vap->iv_acl;
2251                 switch (value) {
2252                 case IEEE80211_MACCMD_POLICY_OPEN:
2253                 case IEEE80211_MACCMD_POLICY_ALLOW:
2254                 case IEEE80211_MACCMD_POLICY_DENY:
2255                         if (acl == NULL) {
2256                                 acl = ieee80211_aclator_get("mac");
2257                                 if (acl == NULL || !acl->iac_attach(vap))
2258                                         return -EINVAL;
2259                                 vap->iv_acl = acl;
2260                         }
2261                         acl->iac_setpolicy(vap, value);
2262                         break;
2263                 case IEEE80211_MACCMD_FLUSH:
2264                         if (acl != NULL)
2265                                 acl->iac_flush(vap);
2266                         /* NB: silently ignore when not in use */
2267                         break;
2268                 case IEEE80211_MACCMD_DETACH:
2269                         if (acl != NULL) {
2270                                 vap->iv_acl = NULL;
2271                                 acl->iac_detach(vap);
2272                         }
2273                         break;
2274                 }
2275                 break;
2276         case IEEE80211_PARAM_WMM:
2277                 if (ic->ic_caps & IEEE80211_C_WME){
2278                         if (value) {
2279                                 vap->iv_flags |= IEEE80211_F_WME;
2280                                 vap->iv_ic->ic_flags |= IEEE80211_F_WME; /* XXX needed by ic_reset */
2281                         } else {
2282                                 vap->iv_flags &= ~IEEE80211_F_WME;
2283                                 vap->iv_ic->ic_flags &= ~IEEE80211_F_WME; /* XXX needed by ic_reset */
2284                         }
2285                         retv = ENETRESET;       /* Renegotiate for capabilities */
2286                 }
2287                 break;
2288         case IEEE80211_PARAM_HIDESSID:
2289                 if (value)
2290                         vap->iv_flags |= IEEE80211_F_HIDESSID;
2291                 else
2292                         vap->iv_flags &= ~IEEE80211_F_HIDESSID;
2293                 retv = ENETRESET;
2294                 break;
2295         case IEEE80211_PARAM_APBRIDGE:
2296                 if (value == 0)
2297                         vap->iv_flags |= IEEE80211_F_NOBRIDGE;
2298                 else
2299                         vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
2300                 break;
2301         case IEEE80211_PARAM_INACT:
2302                 vap->iv_inact_run = value / IEEE80211_INACT_WAIT;
2303                 break;
2304         case IEEE80211_PARAM_INACT_AUTH:
2305                 vap->iv_inact_auth = value / IEEE80211_INACT_WAIT;
2306                 break;
2307         case IEEE80211_PARAM_INACT_INIT:
2308                 vap->iv_inact_init = value / IEEE80211_INACT_WAIT;
2309                 break;
2310         case IEEE80211_PARAM_ABOLT:
2311                 caps = 0;
2312                 /*
2313                  * Map abolt settings to capability bits;
2314                  * this also strips unknown/unwanted bits.
2315                  */
2316                 if (value & IEEE80211_ABOLT_TURBO_PRIME)
2317                         caps |= IEEE80211_ATHC_TURBOP;
2318                 if (value & IEEE80211_ABOLT_COMPRESSION)
2319                         caps |= IEEE80211_ATHC_COMP;
2320                 if (value & IEEE80211_ABOLT_FAST_FRAME)
2321                         caps |= IEEE80211_ATHC_FF;
2322                 if (value & IEEE80211_ABOLT_XR)
2323                         caps |= IEEE80211_ATHC_XR;
2324                 if (value & IEEE80211_ABOLT_AR)
2325                         caps |= IEEE80211_ATHC_AR;
2326                 if (value & IEEE80211_ABOLT_BURST)
2327                         caps |= IEEE80211_ATHC_BURST;
2328                 /* verify requested capabilities are supported */
2329                 if ((caps & ic->ic_ath_cap) != caps)
2330                         return -EINVAL;
2331                 if (vap->iv_ath_cap != caps) {
2332                         if ((vap->iv_ath_cap ^ caps) & IEEE80211_ATHC_TURBOP) {
2333                                 /* no turbo and XR at the same time */
2334                                 if ((caps & IEEE80211_ATHC_TURBOP) && (caps & IEEE80211_ATHC_XR))
2335                                         return -EINVAL;
2336                                 if (ieee80211_set_turbo(dev,  caps & IEEE80211_ATHC_TURBOP))
2337                                         return -EINVAL;
2338                                 ieee80211_scan_flush(ic);
2339                         }
2340                         vap->iv_ath_cap = caps;
2341 #ifdef ATH_SUPERG_XR
2342                         ieee80211_setupxr(vap);
2343 #endif
2344                         retv = ENETRESET;
2345                 }
2346                 break;
2347         case IEEE80211_PARAM_DTIM_PERIOD:
2348                 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2349                     vap->iv_opmode != IEEE80211_M_IBSS)
2350                         return -EINVAL;
2351                 if (IEEE80211_DTIM_MIN <= value &&
2352                     value <= IEEE80211_DTIM_MAX) {
2353                         vap->iv_dtim_period = value;
2354                         retv = ENETRESET;               /* requires restart */
2355                 } else
2356                         retv = EINVAL;
2357                 break;
2358         case IEEE80211_PARAM_BEACON_INTERVAL:
2359                 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2360                     vap->iv_opmode != IEEE80211_M_IBSS)
2361                         return -EINVAL;
2362                 if (IEEE80211_BINTVAL_VALID(value)) {
2363                         ic->ic_lintval = value;         /* XXX multi-bss */
2364                         retv = ENETRESET;               /* requires restart */
2365                 } else
2366                         retv = EINVAL;
2367                 break;
2368         case IEEE80211_PARAM_DOTH:
2369                 if (value)
2370                         ic->ic_flags |= IEEE80211_F_DOTH;
2371                 else
2372                         ic->ic_flags &= ~IEEE80211_F_DOTH;
2373                 retv = ENETRESET;       /* XXX: need something this drastic? */
2374                 break;
2375         case IEEE80211_PARAM_SHPREAMBLE:
2376                 if (value) {
2377                         ic->ic_caps |= IEEE80211_C_SHPREAMBLE;
2378                         ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
2379                         ic->ic_flags &= ~IEEE80211_F_USEBARKER;
2380                 } else {
2381                         ic->ic_caps &= ~IEEE80211_C_SHPREAMBLE;
2382                         ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
2383                         ic->ic_flags |= IEEE80211_F_USEBARKER;
2384                 }       
2385                 retv = ENETRESET;       /* requires restart */
2386                 break;
2387         case IEEE80211_PARAM_PWRTARGET:
2388                 ic->ic_curchanmaxpwr = value;
2389                 break;
2390         case IEEE80211_PARAM_GENREASSOC:
2391                 IEEE80211_SEND_MGMT(vap->iv_bss, IEEE80211_FC0_SUBTYPE_REASSOC_REQ, 0);
2392                 break;
2393         case IEEE80211_PARAM_COMPRESSION:
2394                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_COMP, value);
2395                 break;
2396         case IEEE80211_PARAM_FF:
2397                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_FF, value);
2398                 break;
2399         case IEEE80211_PARAM_TURBO:
2400                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_TURBOP, value);
2401                 if (retv == ENETRESET) {
2402                         /* no turbo and XR at the same time */
2403                         if ((vap->iv_ath_cap & IEEE80211_ATHC_XR) && value)
2404                                 return -EINVAL;
2405                         if (ieee80211_set_turbo(dev,value))
2406                                 return -EINVAL;
2407                         ieee80211_scan_flush(ic);
2408                 }
2409                 break;
2410         case IEEE80211_PARAM_XR:
2411                 /* no turbo and XR at the same time */
2412                 if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) && value)
2413                         return -EINVAL;
2414                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_XR, value);
2415 #ifdef ATH_SUPERG_XR
2416                 ieee80211_setupxr(vap);
2417 #endif
2418                 break;
2419         case IEEE80211_PARAM_BURST:
2420                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_BURST, value);
2421                 break;
2422         case IEEE80211_PARAM_AR:
2423                 retv = ieee80211_setathcap(vap, IEEE80211_ATHC_AR, value);
2424                 break;
2425         case IEEE80211_PARAM_PUREG:
2426                 if (value)
2427                         vap->iv_flags |= IEEE80211_F_PUREG;
2428                 else
2429                         vap->iv_flags &= ~IEEE80211_F_PUREG;
2430                 /* NB: reset only if we're operating on an 11g channel */
2431                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2432                     IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2433                         retv = ENETRESET;
2434                 break;
2435         case IEEE80211_PARAM_WDS:
2436                 if (value)
2437                         vap->iv_flags_ext |= IEEE80211_FEXT_WDS;
2438                 else
2439                         vap->iv_flags_ext &= ~IEEE80211_FEXT_WDS;
2440                 break;
2441         case IEEE80211_PARAM_BGSCAN:
2442                 if (value) {
2443                         if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
2444                                 return -EINVAL;
2445                         vap->iv_flags |= IEEE80211_F_BGSCAN;
2446                 } else {
2447                         /* XXX racey? */
2448                         vap->iv_flags &= ~IEEE80211_F_BGSCAN;
2449                         ieee80211_cancel_scan(vap);     /* anything current */
2450                 }
2451                 break;
2452         case IEEE80211_PARAM_BGSCAN_IDLE:
2453                 if (value >= IEEE80211_BGSCAN_IDLE_MIN)
2454                         vap->iv_bgscanidle = msecs_to_jiffies(value);
2455                 else
2456                         retv = EINVAL;
2457                 break;
2458         case IEEE80211_PARAM_BGSCAN_INTERVAL:
2459                 if (value >= IEEE80211_BGSCAN_INTVAL_MIN)
2460                         vap->iv_bgscanintvl = value * HZ;
2461                 else
2462                         retv = EINVAL;
2463                 break;
2464         case IEEE80211_PARAM_MCAST_RATE:
2465                 /* units are in KILObits per second */
2466                 if (value >= 256 && value <= 54000)
2467                         vap->iv_mcast_rate = value;
2468                 else
2469                         retv = EINVAL;
2470                 break;
2471         case IEEE80211_PARAM_COVERAGE_CLASS:
2472                 if (value >= 0 && value <= IEEE80211_COVERAGE_CLASS_MAX) {
2473                         ic->ic_coverageclass = value;
2474                         if (IS_UP_AUTO(vap))
2475                                 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2476                         retv = 0;
2477                 } else
2478                         retv = EINVAL;
2479                 break;
2480         case IEEE80211_PARAM_COUNTRY_IE:
2481                 if (value)
2482                         ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE;
2483                 else
2484                         ic->ic_flags_ext &= ~IEEE80211_FEXT_COUNTRYIE;
2485                 retv = ENETRESET;
2486                 break;
2487         case IEEE80211_PARAM_REGCLASS:
2488                 if (value)
2489                         ic->ic_flags_ext |= IEEE80211_FEXT_REGCLASS;
2490                 else
2491                         ic->ic_flags_ext &= ~IEEE80211_FEXT_REGCLASS;
2492                 retv = ENETRESET;
2493                 break;
2494         case IEEE80211_PARAM_SCANVALID:
2495                 vap->iv_scanvalid = value * HZ;
2496                 break;
2497         case IEEE80211_PARAM_ROAM_RSSI_11A:
2498                 vap->iv_roam.rssi11a = value;
2499                 break;
2500         case IEEE80211_PARAM_ROAM_RSSI_11B:
2501                 vap->iv_roam.rssi11bOnly = value;
2502                 break;
2503         case IEEE80211_PARAM_ROAM_RSSI_11G:
2504                 vap->iv_roam.rssi11b = value;
2505                 break;
2506         case IEEE80211_PARAM_ROAM_RATE_11A:
2507                 vap->iv_roam.rate11a = value;
2508                 break;
2509         case IEEE80211_PARAM_ROAM_RATE_11B:
2510                 vap->iv_roam.rate11bOnly = value;
2511                 break;
2512         case IEEE80211_PARAM_ROAM_RATE_11G:
2513                 vap->iv_roam.rate11b = value;
2514                 break;
2515         case IEEE80211_PARAM_UAPSDINFO:
2516                 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
2517                         if (ic->ic_caps & IEEE80211_C_UAPSD) {
2518                                 if (value)
2519                                         IEEE80211_VAP_UAPSD_ENABLE(vap);
2520                                 else
2521                                         IEEE80211_VAP_UAPSD_DISABLE(vap);
2522                                 retv = ENETRESET;
2523                         }
2524                 } else if (vap->iv_opmode == IEEE80211_M_STA) {
2525                         vap->iv_uapsdinfo = value;
2526                         IEEE80211_VAP_UAPSD_ENABLE(vap);
2527                         retv = ENETRESET;
2528                 }
2529                 break;
2530         case IEEE80211_PARAM_SLEEP:
2531                 /* XXX: Forced sleep for testing. Does not actually place the
2532                  *      HW in sleep mode yet. this only makes sense for STAs.
2533                  */
2534                 if (value) {
2535                         /* goto sleep */
2536                         IEEE80211_VAP_GOTOSLEEP(vap);
2537                 } else {
2538                         /* wakeup */
2539                         IEEE80211_VAP_WAKEUP(vap);
2540                 }
2541                 ieee80211_send_nulldata(ieee80211_ref_node(vap->iv_bss));
2542                 break;
2543         case IEEE80211_PARAM_QOSNULL:
2544                 /* Force a QoS Null for testing. */
2545                 ieee80211_send_qosnulldata(vap->iv_bss, value);
2546                 break;
2547         case IEEE80211_PARAM_PSPOLL:
2548                 /* Force a PS-POLL for testing. */
2549                 ieee80211_send_pspoll(vap->iv_bss);
2550                 break;
2551         case IEEE80211_PARAM_EOSPDROP:
2552                 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
2553                         if (value)
2554                                 IEEE80211_VAP_EOSPDROP_ENABLE(vap);
2555                         else
2556                                 IEEE80211_VAP_EOSPDROP_DISABLE(vap);
2557                 }
2558                 break;
2559         case IEEE80211_PARAM_MARKDFS:
2560                 if (value)
2561                         ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS;
2562                 else
2563                         ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS;
2564                 break;
2565         default:
2566                 retv = EOPNOTSUPP;
2567                 break;
2568         }
2569 #ifdef ATH_SUPERG_XR
2570         /* set the same params on the xr vap device if exists */
2571         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR)) {
2572                 ieee80211_ioctl_setparam(vap->iv_xrvap->iv_dev,info,w,extra);
2573                 vap->iv_xrvap->iv_ath_cap &= IEEE80211_ATHC_XR; /* XR vap does not support  any superG features */
2574         } 
2575         /*
2576          * do not reset the xr vap , which is automatically 
2577          * reset by the state machine now.
2578          */
2579         if (!vap->iv_xrvap || (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))) {
2580                 if (retv == ENETRESET)
2581                         retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
2582         }
2583 #else
2584         /* XXX should any of these cause a rescan? */
2585         if (retv == ENETRESET)
2586                 retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
2587 #endif
2588         return -retv;
2589 }
2590
2591 #if 0
2592 static int
2593 cap2cipher(int flag)
2594 {
2595         switch (flag) {
2596         case IEEE80211_C_WEP:           return IEEE80211_CIPHER_WEP;
2597         case IEEE80211_C_AES:           return IEEE80211_CIPHER_AES_OCB;
2598         case IEEE80211_C_AES_CCM:       return IEEE80211_CIPHER_AES_CCM;
2599         case IEEE80211_C_CKIP:          return IEEE80211_CIPHER_CKIP;
2600         case IEEE80211_C_TKIP:          return IEEE80211_CIPHER_TKIP;
2601         }
2602         return -1;
2603 }
2604 #endif
2605
2606 static int
2607 ieee80211_ioctl_getmode(struct net_device *dev, struct iw_request_info *info,
2608         struct iw_point *wri, char *extra)
2609 {
2610         struct ieee80211vap *vap = netdev_priv(dev);
2611         struct ieee80211com *ic = vap->iv_ic;
2612         struct ifmediareq imr;
2613
2614         ic->ic_media.ifm_status(ic->ic_dev, &imr);
2615         switch (IFM_MODE(imr.ifm_active)) {
2616         case IFM_IEEE80211_11A:
2617                 strcpy(extra, "11a");
2618                 break;
2619         case IFM_IEEE80211_11B:
2620                 strcpy(extra, "11b");
2621                 break;
2622         case IFM_IEEE80211_11G:
2623                 strcpy(extra, "11g");
2624                 break;
2625         case IFM_IEEE80211_FH:
2626                 strcpy(extra, "FH");
2627                 break;
2628         case IFM_AUTO:
2629                 strcpy(extra, "auto");
2630                 break;
2631         default:
2632                 return -EINVAL;
2633         }
2634         if (ic->ic_media.ifm_media & IFM_IEEE80211_TURBO) {
2635                 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP)
2636                         strcat(extra, "T");
2637                 else
2638                         strcat(extra, "ST");
2639         }
2640         wri->length = strlen(extra);
2641         return 0;
2642 }
2643
2644 static int
2645 ieee80211_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
2646         void *w, char *extra)
2647 {
2648         struct ieee80211vap *vap = netdev_priv(dev);
2649         struct ieee80211com *ic = vap->iv_ic;
2650         struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
2651         int *param = (int *) extra;
2652         
2653         switch (param[0]) {
2654         case IEEE80211_PARAM_AUTHMODE:
2655                 if (vap->iv_flags & IEEE80211_F_WPA)
2656                         param[0] = IEEE80211_AUTH_WPA;
2657                 else
2658                         param[0] = vap->iv_bss->ni_authmode;
2659                 break;
2660         case IEEE80211_PARAM_PROTMODE:
2661                 param[0] = ic->ic_protmode;
2662                 break;
2663         case IEEE80211_PARAM_MCASTCIPHER:
2664                 param[0] = rsn->rsn_mcastcipher;
2665                 break;
2666         case IEEE80211_PARAM_MCASTKEYLEN:
2667                 param[0] = rsn->rsn_mcastkeylen;
2668                 break;
2669         case IEEE80211_PARAM_UCASTCIPHERS:
2670                 param[0] = rsn->rsn_ucastcipherset;
2671                 break;
2672         case IEEE80211_PARAM_UCASTCIPHER:
2673                 param[0] = rsn->rsn_ucastcipher;
2674                 break;
2675         case IEEE80211_PARAM_UCASTKEYLEN:
2676                 param[0] = rsn->rsn_ucastkeylen;
2677                 break;
2678         case IEEE80211_PARAM_KEYMGTALGS:
2679                 param[0] = rsn->rsn_keymgmtset;
2680                 break;
2681         case IEEE80211_PARAM_RSNCAPS:
2682                 param[0] = rsn->rsn_caps;
2683                 break;
2684         case IEEE80211_PARAM_WPA:
2685                 switch (vap->iv_flags & IEEE80211_F_WPA) {
2686                 case IEEE80211_F_WPA1:
2687                         param[0] = 1;
2688                         break;
2689                 case IEEE80211_F_WPA2:
2690                         param[0] = 2;
2691                         break;
2692                 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
2693                         param[0] = 3;
2694                         break;
2695                 default:
2696                         param[0] = 0;
2697                         break;
2698                 }
2699                 break;
2700         case IEEE80211_PARAM_ROAMING:
2701                 param[0] = ic->ic_roaming;
2702                 break;
2703         case IEEE80211_PARAM_PRIVACY:
2704                 param[0] = (vap->iv_flags & IEEE80211_F_PRIVACY) != 0;
2705                 break;
2706         case IEEE80211_PARAM_DROPUNENCRYPTED:
2707                 param[0] = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0;
2708                 break;
2709         case IEEE80211_PARAM_DROPUNENC_EAPOL:
2710                 param[0] = IEEE80211_VAP_DROPUNENC_EAPOL(vap);
2711                 break;
2712         case IEEE80211_PARAM_COUNTERMEASURES:
2713                 param[0] = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0;
2714                 break;
2715         case IEEE80211_PARAM_DRIVER_CAPS:
2716                 param[0] = vap->iv_caps;
2717                 break;
2718         case IEEE80211_PARAM_WMM:
2719                 param[0] = (vap->iv_flags & IEEE80211_F_WME) != 0;
2720                 break;
2721         case IEEE80211_PARAM_HIDESSID:
2722                 param[0] = (vap->iv_flags & IEEE80211_F_HIDESSID) != 0;
2723                 break;
2724         case IEEE80211_PARAM_APBRIDGE:
2725                 param[0] = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0;
2726                 break;
2727         case IEEE80211_PARAM_INACT:
2728                 param[0] = vap->iv_inact_run * IEEE80211_INACT_WAIT;
2729                 break;
2730         case IEEE80211_PARAM_INACT_AUTH:
2731                 param[0] = vap->iv_inact_auth * IEEE80211_INACT_WAIT;
2732                 break;
2733         case IEEE80211_PARAM_INACT_INIT:
2734                 param[0] = vap->iv_inact_init * IEEE80211_INACT_WAIT;
2735                 break;
2736         case IEEE80211_PARAM_ABOLT:
2737                 /*
2738                  * Map capability bits to abolt settings.
2739                  */
2740                 param[0] = 0;
2741                 if (vap->iv_ath_cap & IEEE80211_ATHC_COMP)
2742                         param[0] |= IEEE80211_ABOLT_COMPRESSION;
2743                 if (vap->iv_ath_cap & IEEE80211_ATHC_FF)
2744                         param[0] |= IEEE80211_ABOLT_FAST_FRAME;
2745                 if (vap->iv_ath_cap & IEEE80211_ATHC_XR)
2746                         param[0] |= IEEE80211_ABOLT_XR;
2747                 if (vap->iv_ath_cap & IEEE80211_ATHC_BURST)
2748                         param[0] |= IEEE80211_ABOLT_BURST;
2749                 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP)
2750                         param[0] |= IEEE80211_ABOLT_TURBO_PRIME;
2751                 if (vap->iv_ath_cap & IEEE80211_ATHC_AR)
2752                         param[0] |= IEEE80211_ABOLT_AR;
2753                 break;
2754         case IEEE80211_PARAM_COMPRESSION:
2755                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_COMP) != 0;
2756                 break;
2757         case IEEE80211_PARAM_FF:
2758                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_FF) != 0;
2759                 break;
2760         case IEEE80211_PARAM_XR:
2761                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_XR) != 0;
2762                 break;
2763         case IEEE80211_PARAM_BURST:
2764                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_BURST) != 0;
2765                 break;
2766         case IEEE80211_PARAM_AR:
2767                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_AR) != 0;
2768                 break;
2769         case IEEE80211_PARAM_TURBO:
2770                 param[0] = (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) != 0;
2771                 break;
2772         case IEEE80211_PARAM_DTIM_PERIOD:
2773                 param[0] = vap->iv_dtim_period;
2774                 break;
2775         case IEEE80211_PARAM_BEACON_INTERVAL:
2776                 /* NB: get from ic_bss for station mode */
2777                 param[0] = vap->iv_bss->ni_intval;
2778                 break;
2779         case IEEE80211_PARAM_DOTH:
2780                 param[0] = (ic->ic_flags & IEEE80211_F_DOTH) != 0;
2781                 break;
2782         case IEEE80211_PARAM_SHPREAMBLE:
2783                 param[0] = (ic->ic_caps & IEEE80211_C_SHPREAMBLE) != 0;
2784                 break;
2785         case IEEE80211_PARAM_PWRTARGET:
2786                 param[0] = ic->ic_curchanmaxpwr;
2787                 break;
2788         case IEEE80211_PARAM_PUREG:
2789                 param[0] = (vap->iv_flags & IEEE80211_F_PUREG) != 0;
2790                 break;
2791         case IEEE80211_PARAM_WDS:
2792                 param[0] = ((vap->iv_flags_ext & IEEE80211_FEXT_WDS) == IEEE80211_FEXT_WDS);
2793                 break;
2794         case IEEE80211_PARAM_BGSCAN:
2795                 param[0] = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0;
2796                 break;
2797         case IEEE80211_PARAM_BGSCAN_IDLE:
2798                 param[0] = jiffies_to_msecs(vap->iv_bgscanidle); /* ms */
2799                 break;
2800         case IEEE80211_PARAM_BGSCAN_INTERVAL:
2801                 param[0] = vap->iv_bgscanintvl / HZ;    /* seconds */
2802                 break;
2803         case IEEE80211_PARAM_MCAST_RATE:
2804                 param[0] = vap->iv_mcast_rate;  /* seconds */
2805                 break;
2806         case IEEE80211_PARAM_COVERAGE_CLASS:
2807                 param[0] = ic->ic_coverageclass;
2808                 break;
2809         case IEEE80211_PARAM_COUNTRY_IE:
2810                 param[0] = (ic->ic_flags_ext & IEEE80211_FEXT_COUNTRYIE) != 0;
2811                 break;
2812         case IEEE80211_PARAM_REGCLASS:
2813                 param[0] = (ic->ic_flags_ext & IEEE80211_FEXT_REGCLASS) != 0;
2814                 break;
2815         case IEEE80211_PARAM_SCANVALID:
2816                 param[0] = vap->iv_scanvalid / HZ;      /* seconds */
2817                 break;
2818         case IEEE80211_PARAM_ROAM_RSSI_11A:
2819                 param[0] = vap->iv_roam.rssi11a;
2820                 break;
2821         case IEEE80211_PARAM_ROAM_RSSI_11B:
2822                 param[0] = vap->iv_roam.rssi11bOnly;
2823                 break;
2824         case IEEE80211_PARAM_ROAM_RSSI_11G:
2825                 param[0] = vap->iv_roam.rssi11b;
2826                 break;
2827         case IEEE80211_PARAM_ROAM_RATE_11A:
2828                 param[0] = vap->iv_roam.rate11a;
2829                 break;
2830         case IEEE80211_PARAM_ROAM_RATE_11B:
2831                 param[0] = vap->iv_roam.rate11bOnly;
2832                 break;
2833         case IEEE80211_PARAM_ROAM_RATE_11G:
2834                 param[0] = vap->iv_roam.rate11b;
2835                 break;
2836         case IEEE80211_PARAM_UAPSDINFO:
2837                 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
2838                         if (IEEE80211_VAP_UAPSD_ENABLED(vap))
2839                                 param[0] = 1;
2840                         else
2841                                 param[0] = 0;
2842                 } else if (vap->iv_opmode == IEEE80211_M_STA)
2843                         param[0] = vap->iv_uapsdinfo;
2844                 break;
2845         case IEEE80211_PARAM_SLEEP:
2846                 param[0] = vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT;
2847                 break;
2848         case IEEE80211_PARAM_EOSPDROP:
2849                 param[0] = IEEE80211_VAP_EOSPDROP_ENABLED(vap);
2850                 break;
2851         case IEEE80211_PARAM_MARKDFS:
2852                 if (ic->ic_flags_ext & IEEE80211_FEXT_MARKDFS)
2853                         param[0] = 1;
2854                 else
2855                         param[0] = 0;
2856                 break;
2857         default:
2858                 return -EOPNOTSUPP;
2859         }
2860         return 0;
2861 }
2862
2863 /* returns non-zero if ID is for a system IE (not for app use) */
2864 static int
2865 is_sys_ie(u_int8_t ie_id)
2866 {
2867         /* XXX review this list */
2868         switch (ie_id) {
2869         case IEEE80211_ELEMID_SSID:
2870         case IEEE80211_ELEMID_RATES:
2871         case IEEE80211_ELEMID_FHPARMS:
2872         case IEEE80211_ELEMID_DSPARMS:
2873         case IEEE80211_ELEMID_CFPARMS:
2874         case IEEE80211_ELEMID_TIM:
2875         case IEEE80211_ELEMID_IBSSPARMS:
2876         case IEEE80211_ELEMID_COUNTRY:
2877         case IEEE80211_ELEMID_REQINFO:
2878         case IEEE80211_ELEMID_CHALLENGE:
2879         case IEEE80211_ELEMID_PWRCNSTR:
2880         case IEEE80211_ELEMID_PWRCAP:
2881         case IEEE80211_ELEMID_TPCREQ:
2882         case IEEE80211_ELEMID_TPCREP:
2883         case IEEE80211_ELEMID_SUPPCHAN:
2884         case IEEE80211_ELEMID_CHANSWITCHANN:
2885         case IEEE80211_ELEMID_MEASREQ:
2886         case IEEE80211_ELEMID_MEASREP:
2887         case IEEE80211_ELEMID_QUIET:
2888         case IEEE80211_ELEMID_IBSSDFS:
2889         case IEEE80211_ELEMID_ERP:
2890         case IEEE80211_ELEMID_RSN:
2891         case IEEE80211_ELEMID_XRATES:
2892         case IEEE80211_ELEMID_TPC:
2893         case IEEE80211_ELEMID_CCKM:
2894                 return 1;
2895         default:
2896                 return 0;
2897         }
2898 }
2899
2900 /* returns non-zero if the buffer appears to contain a valid IE list */
2901 static int
2902 is_valid_ie_list(u_int32_t buf_len, void *buf, int exclude_sys_ies)
2903 {
2904         struct ieee80211_ie *ie = (struct ieee80211_ie *)buf;
2905
2906         while (buf_len >= sizeof(*ie)) {
2907                 int ie_elem_len = sizeof(*ie) + ie->len;
2908                 if (buf_len < ie_elem_len)
2909                         break;
2910                 if (exclude_sys_ies && is_sys_ie(ie->id))
2911                         break;
2912                 buf_len -= ie_elem_len;
2913                 ie = (struct ieee80211_ie *)(ie->info + ie->len);
2914         }
2915
2916         return (buf_len == 0) ? 1 : 0;
2917 }
2918
2919 static int
2920 ieee80211_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
2921         struct iw_point *wri, char *extra)
2922 {
2923         struct ieee80211vap *vap = netdev_priv(dev);
2924         void *ie;
2925
2926         /*
2927          * NB: Doing this for ap operation could be useful (e.g. for
2928          *     WPA and/or WME) except that it typically is worthless
2929          *     without being able to intervene when processing
2930          *     association response frames--so disallow it for now.
2931          */
2932         if (vap->iv_opmode != IEEE80211_M_STA)
2933                 return -EINVAL;
2934         if (! is_valid_ie_list(wri->length, extra, 0))
2935                 return -EINVAL;
2936         /* NB: wri->length is validated by the wireless extensions code */
2937         MALLOC(ie, void *, wri->length, M_DEVBUF, M_WAITOK);
2938         if (ie == NULL)
2939                 return -ENOMEM;
2940         memcpy(ie, extra, wri->length);
2941         if (vap->iv_opt_ie != NULL)
2942                 FREE(vap->iv_opt_ie, M_DEVBUF);
2943         vap->iv_opt_ie = ie;
2944         vap->iv_opt_ie_len = wri->length;
2945 #ifdef ATH_SUPERG_XR
2946         /* set the same params on the xr vap device if exists */
2947         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
2948                 ieee80211_ioctl_setoptie(vap->iv_xrvap->iv_dev, info, wri, extra);
2949 #endif
2950         return 0;
2951 }
2952
2953 static int
2954 ieee80211_ioctl_getoptie(struct net_device *dev, struct iw_request_info *info,
2955         struct iw_point *wri, char *extra)
2956 {
2957         struct ieee80211vap *vap = netdev_priv(dev);
2958
2959         if (vap->iv_opt_ie == NULL) {
2960                 wri->length = 0;
2961                 return 0;
2962         }
2963         wri->length = vap->iv_opt_ie_len;
2964         memcpy(extra, vap->iv_opt_ie, vap->iv_opt_ie_len);
2965         return 0;
2966 }
2967
2968 /* the following functions are used by the set/get appiebuf functions */
2969 static int
2970 add_app_ie(unsigned int frame_type_index, struct ieee80211vap *vap,
2971         struct ieee80211req_getset_appiebuf *iebuf)
2972 {
2973         struct ieee80211_ie *ie;
2974
2975         if (! is_valid_ie_list(iebuf->app_buflen, iebuf->app_buf, 1))
2976                 return -EINVAL;
2977         /* NB: data.length is validated by the wireless extensions code */
2978         MALLOC(ie, struct ieee80211_ie *, iebuf->app_buflen, M_DEVBUF, M_WAITOK);
2979         if (ie == NULL)
2980                 return -ENOMEM;
2981
2982         memcpy(ie, iebuf->app_buf, iebuf->app_buflen);
2983         if (vap->app_ie[frame_type_index].ie != NULL)
2984                 FREE(vap->app_ie[frame_type_index].ie, M_DEVBUF);
2985         vap->app_ie[frame_type_index].ie = ie;
2986         vap->app_ie[frame_type_index].length = iebuf->app_buflen;
2987
2988         return 0;
2989 }
2990
2991 static int
2992 remove_app_ie(unsigned int frame_type_index, struct ieee80211vap *vap)
2993 {
2994         struct ieee80211_app_ie_t *app_ie = &vap->app_ie[frame_type_index];
2995         if (app_ie->ie != NULL) {
2996                 FREE(app_ie->ie, M_DEVBUF);
2997                 app_ie->ie = NULL;
2998                 app_ie->length = 0;
2999         }
3000         return 0;
3001 }
3002
3003 static int
3004 get_app_ie(unsigned int frame_type_index, struct ieee80211vap *vap,
3005         struct ieee80211req_getset_appiebuf *iebuf)
3006 {
3007         struct ieee80211_app_ie_t *app_ie = &vap->app_ie[frame_type_index];
3008         if (iebuf->app_buflen < app_ie->length)
3009                 return -EINVAL;
3010
3011         iebuf->app_buflen = app_ie->length;
3012         memcpy(iebuf->app_buf, app_ie->ie, app_ie->length);
3013         return 0;
3014 }
3015
3016 static int
3017 ieee80211_ioctl_setappiebuf(struct net_device *dev,
3018         struct iw_request_info *info,
3019         struct iw_point *data, char *extra)
3020 {
3021         struct ieee80211vap *vap = netdev_priv(dev);
3022         struct ieee80211req_getset_appiebuf *iebuf =
3023                 (struct ieee80211req_getset_appiebuf *)extra;
3024         enum ieee80211_opmode chk_opmode;
3025         int iebuf_len;
3026         int rc = 0;
3027
3028         iebuf_len = data->length - sizeof(struct ieee80211req_getset_appiebuf);
3029         if ( iebuf_len < 0 || iebuf_len != iebuf->app_buflen ||
3030                  iebuf->app_buflen > IEEE80211_APPIE_MAX )
3031                 return -EINVAL;
3032
3033         switch (iebuf->app_frmtype) {
3034         case IEEE80211_APPIE_FRAME_BEACON:
3035         case IEEE80211_APPIE_FRAME_PROBE_RESP:
3036         case IEEE80211_APPIE_FRAME_ASSOC_RESP:
3037                 chk_opmode = IEEE80211_M_HOSTAP;
3038                 break;
3039         case IEEE80211_APPIE_FRAME_PROBE_REQ:
3040         case IEEE80211_APPIE_FRAME_ASSOC_REQ:
3041                 chk_opmode = IEEE80211_M_STA;
3042                 break;
3043         default:
3044                 return -EINVAL;
3045         }
3046         if (vap->iv_opmode != chk_opmode)
3047                 return -EINVAL;
3048
3049         if (iebuf->app_buflen)
3050                 rc = add_app_ie(iebuf->app_frmtype, vap, iebuf);
3051         else
3052                 rc = remove_app_ie(iebuf->app_frmtype, vap);
3053         if ((iebuf->app_frmtype == IEEE80211_APPIE_FRAME_BEACON) && (rc == 0))
3054                 vap->iv_flags_ext |= IEEE80211_FEXT_APPIE_UPDATE;
3055
3056         return rc;
3057 }
3058
3059 static int
3060 ieee80211_ioctl_getappiebuf(struct net_device *dev, struct iw_request_info *info,
3061         struct iw_point *data, char *extra)
3062 {
3063         struct ieee80211vap *vap = netdev_priv(dev);
3064         struct ieee80211req_getset_appiebuf *iebuf =
3065                 (struct ieee80211req_getset_appiebuf *)extra;
3066         int max_iebuf_len;
3067         int rc = 0;
3068
3069         max_iebuf_len = data->length - sizeof(struct ieee80211req_getset_appiebuf);
3070         if (max_iebuf_len < 0)
3071                 return -EINVAL;
3072         if (copy_from_user(iebuf, data->pointer, sizeof(struct ieee80211req_getset_appiebuf)))
3073                 return -EFAULT;         
3074         if (iebuf->app_buflen > max_iebuf_len)
3075                 iebuf->app_buflen = max_iebuf_len;
3076
3077         switch (iebuf->app_frmtype) {
3078         case IEEE80211_APPIE_FRAME_BEACON:
3079         case IEEE80211_APPIE_FRAME_PROBE_RESP:
3080         case IEEE80211_APPIE_FRAME_ASSOC_RESP:
3081                 if (vap->iv_opmode == IEEE80211_M_STA)
3082                         return -EINVAL;
3083                 break;
3084         case IEEE80211_APPIE_FRAME_PROBE_REQ:
3085         case IEEE80211_APPIE_FRAME_ASSOC_REQ:
3086                 if (vap->iv_opmode != IEEE80211_M_STA)
3087                         return -EINVAL;
3088                 break;
3089         default:
3090                 return -EINVAL;
3091         }
3092
3093         rc = get_app_ie(iebuf->app_frmtype, vap, iebuf);
3094         
3095         data->length = sizeof(struct ieee80211req_getset_appiebuf) + iebuf->app_buflen;
3096         
3097         return rc;
3098 }
3099
3100 static int
3101 ieee80211_ioctl_setfilter(struct net_device *dev, struct iw_request_info *info,
3102         void *w, char *extra)
3103 {
3104         struct ieee80211vap *vap = netdev_priv(dev);
3105         struct ieee80211req_set_filter *app_filter = (struct ieee80211req_set_filter *)extra;
3106
3107         if ((extra == NULL) || (app_filter->app_filterype & ~IEEE80211_FILTER_TYPE_ALL))
3108                 return -EINVAL;
3109
3110         vap->app_filter = app_filter->app_filterype;
3111
3112         return 0;
3113 }
3114
3115 static int
3116 ieee80211_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
3117         void *w, char *extra)
3118 {
3119         struct ieee80211vap *vap = netdev_priv(dev);
3120         struct ieee80211com *ic = vap->iv_ic;
3121         struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
3122         struct ieee80211_node *ni;
3123         struct ieee80211_key *wk;
3124         u_int16_t kid;
3125         int error, flags,i;
3126
3127         /* NB: cipher support is verified by ieee80211_crypt_newkey */
3128         /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
3129         if (ik->ik_keylen > sizeof(ik->ik_keydata))
3130                 return -E2BIG;
3131         kid = ik->ik_keyix;
3132         if (kid == IEEE80211_KEYIX_NONE) {
3133                 /* XXX unicast keys currently must be tx/rx */
3134                 if (ik->ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
3135                         return -EINVAL;
3136                 if (vap->iv_opmode == IEEE80211_M_STA) {
3137                         ni = ieee80211_ref_node(vap->iv_bss);
3138                         if (!IEEE80211_ADDR_EQ(ik->ik_macaddr, ni->ni_bssid))
3139                                 return -EADDRNOTAVAIL;
3140                 } else
3141                         ni = ieee80211_find_node(&ic->ic_sta, ik->ik_macaddr);
3142                 if (ni == NULL)
3143                         return -ENOENT;
3144                 wk = &ni->ni_ucastkey;
3145         } else {
3146                 if (kid >= IEEE80211_WEP_NKID)
3147                         return -EINVAL;
3148                 wk = &vap->iv_nw_keys[kid];
3149                 ni = NULL;
3150                 /* XXX auto-add group key flag until applications are updated */
3151                 if ((ik->ik_flags & IEEE80211_KEY_XMIT) == 0)   /* XXX */
3152                         ik->ik_flags |= IEEE80211_KEY_GROUP;    /* XXX */
3153         }
3154         error = 0;
3155         flags = ik->ik_flags & IEEE80211_KEY_COMMON;
3156         ieee80211_key_update_begin(vap);
3157         if (ieee80211_crypto_newkey(vap, ik->ik_type, flags, wk)) {
3158                 wk->wk_keylen = ik->ik_keylen;
3159                 /* NB: MIC presence is implied by cipher type */
3160                 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
3161                         wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
3162                 for(i = 0; i < IEEE80211_TID_SIZE; i++)
3163                         wk->wk_keyrsc[i] = ik->ik_keyrsc;
3164                 wk->wk_keytsc = 0;                      /* new key, reset */
3165                 memset(wk->wk_key, 0, sizeof(wk->wk_key));
3166                 memcpy(wk->wk_key, ik->ik_keydata, ik->ik_keylen);
3167                 if (!ieee80211_crypto_setkey(vap, wk,
3168                     ni != NULL ? ni->ni_macaddr : ik->ik_macaddr, ni))
3169                         error = -EIO;
3170                 else if ((ik->ik_flags & IEEE80211_KEY_DEFAULT))
3171                         vap->iv_def_txkey = kid;
3172         } else
3173                 error = -ENXIO;
3174         ieee80211_key_update_end(vap);
3175         if (ni != NULL)
3176                 ieee80211_free_node(ni);
3177 #ifdef ATH_SUPERG_XR
3178         /* set the same params on the xr vap device if exists */
3179         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
3180                 ieee80211_ioctl_setkey(vap->iv_xrvap->iv_dev, info, w, extra);
3181 #endif
3182         return error;
3183 }
3184
3185 static int
3186 ieee80211_ioctl_getkey(struct net_device *dev, struct iwreq *iwr)
3187 {
3188         struct ieee80211vap *vap = netdev_priv(dev);
3189         struct ieee80211com *ic = vap->iv_ic;
3190         struct ieee80211_node *ni;
3191         struct ieee80211req_key ik;
3192         struct ieee80211_key *wk;
3193         const struct ieee80211_cipher *cip;
3194         u_int kid;
3195
3196         if (iwr->u.data.length != sizeof(ik))
3197                 return -EINVAL;
3198         if (copy_from_user(&ik, iwr->u.data.pointer, sizeof(ik)))
3199                 return -EFAULT;
3200         kid = ik.ik_keyix;
3201         if (kid == IEEE80211_KEYIX_NONE) {
3202                 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
3203                 if (ni == NULL)
3204                         return -EINVAL;         /* XXX */
3205                 wk = &ni->ni_ucastkey;
3206         } else {
3207                 if (kid >= IEEE80211_WEP_NKID)
3208                         return -EINVAL;
3209                 wk = &vap->iv_nw_keys[kid];
3210                 IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr);
3211                 ni = NULL;
3212         }
3213         cip = wk->wk_cipher;
3214         ik.ik_type = cip->ic_cipher;
3215         ik.ik_keylen = wk->wk_keylen;
3216         ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
3217         if (wk->wk_keyix == vap->iv_def_txkey)
3218                 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
3219         if (capable(CAP_NET_ADMIN)) {
3220                 /* NB: only root can read key data */
3221                 ik.ik_keyrsc = wk->wk_keyrsc[0];
3222                 ik.ik_keytsc = wk->wk_keytsc;
3223                 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
3224                 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
3225                         memcpy(ik.ik_keydata+wk->wk_keylen,
3226                                 wk->wk_key + IEEE80211_KEYBUF_SIZE,
3227                                 IEEE80211_MICBUF_SIZE);
3228                         ik.ik_keylen += IEEE80211_MICBUF_SIZE;
3229                 }
3230         } else {
3231                 ik.ik_keyrsc = 0;
3232                 ik.ik_keytsc = 0;
3233                 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
3234         }
3235         if (ni != NULL)
3236                 ieee80211_free_node(ni);
3237         return (copy_to_user(iwr->u.data.pointer, &ik, sizeof(ik)) ? -EFAULT : 0);
3238 }
3239
3240 static int
3241 ieee80211_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
3242         void *w, char *extra)
3243 {
3244         struct ieee80211vap *vap = netdev_priv(dev);
3245         struct ieee80211com *ic = vap->iv_ic;
3246         struct ieee80211req_del_key *dk = (struct ieee80211req_del_key *)extra;
3247         int kid;
3248
3249         kid = dk->idk_keyix;
3250         /* XXX u_int8_t -> u_int16_t */
3251         if (dk->idk_keyix == (u_int8_t) IEEE80211_KEYIX_NONE) {
3252                 struct ieee80211_node *ni;
3253
3254                 ni = ieee80211_find_node(&ic->ic_sta, dk->idk_macaddr);
3255                 if (ni == NULL)
3256                         return -EINVAL;         /* XXX */
3257                 /* XXX error return */
3258                 ieee80211_crypto_delkey(vap, &ni->ni_ucastkey, ni);
3259                 ieee80211_free_node(ni);
3260         } else {
3261                 if (kid >= IEEE80211_WEP_NKID)
3262                         return -EINVAL;
3263                 /* XXX error return */
3264                 ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid], NULL);
3265         }
3266         return 0;
3267 }
3268
3269 static void
3270 domlme(void *arg, struct ieee80211_node *ni)
3271 {
3272         struct ieee80211req_mlme *mlme = arg;
3273
3274         if (ni->ni_associd != 0) {
3275                 IEEE80211_SEND_MGMT(ni,
3276                         mlme->im_op == IEEE80211_MLME_DEAUTH ?
3277                                 IEEE80211_FC0_SUBTYPE_DEAUTH :
3278                                 IEEE80211_FC0_SUBTYPE_DISASSOC,
3279                         mlme->im_reason);
3280         }
3281         ieee80211_node_leave(ni);
3282 }
3283
3284 struct scanlookup {             /* XXX: right place for declaration? */
3285         const u_int8_t *mac;
3286         int esslen;
3287         const u_int8_t *essid;
3288         const struct ieee80211_scan_entry *se;
3289 };
3290
3291 /*
3292  * Match mac address and any ssid.
3293  */
3294 static int
3295 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
3296 {
3297         struct scanlookup *look = arg;
3298
3299         if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
3300                 return 0;
3301         if (look->esslen != 0) {
3302                 if (se->se_ssid[1] != look->esslen)
3303                         return 0;
3304                 if (memcmp(look->essid, se->se_ssid + 2, look->esslen))
3305                         return 0;
3306         }
3307         look->se = se;
3308
3309         return 0;
3310 }
3311
3312 static int
3313 ieee80211_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
3314         void *w, char *extra)
3315 {
3316         struct ieee80211vap *vap = netdev_priv(dev);
3317         struct ieee80211com *ic = vap->iv_ic;
3318         struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
3319         struct ieee80211_node *ni;
3320
3321         if (!IS_UP(dev)) {
3322                 switch (mlme->im_op) {
3323                 case IEEE80211_MLME_DISASSOC:
3324                 case IEEE80211_MLME_DEAUTH:
3325                 case IEEE80211_MLME_UNAUTHORIZE:
3326                         return 0;
3327                 default:
3328                         return -ENETDOWN;
3329                 }
3330         }
3331         switch (mlme->im_op) {
3332         case IEEE80211_MLME_ASSOC:
3333                 if (vap->iv_opmode == IEEE80211_M_STA) {
3334                         struct scanlookup lookup;
3335
3336                         lookup.se = NULL;
3337                         lookup.mac = mlme->im_macaddr;
3338                         /* XXX use revised api w/ explicit ssid */
3339                         lookup.esslen = vap->iv_des_ssid[0].len;
3340                         lookup.essid = vap->iv_des_ssid[0].ssid;
3341                         ieee80211_scan_iterate(ic, mlmelookup, &lookup);
3342                         if (lookup.se != NULL) {
3343                                 vap->iv_nsdone = 0;
3344                                 vap->iv_nsparams.result = 0;
3345                                 if (ieee80211_sta_join(vap, lookup.se))
3346                                         while (!vap->iv_nsdone)
3347                                                 IEEE80211_RESCHEDULE();
3348                                 if (vap->iv_nsparams.result)
3349                                         return 0;
3350                         }
3351                 }
3352                 return -EINVAL;
3353         case IEEE80211_MLME_DISASSOC:
3354         case IEEE80211_MLME_DEAUTH:
3355                 switch (vap->iv_opmode) {
3356                 case IEEE80211_M_STA:
3357                         /* XXX not quite right */
3358                         ieee80211_new_state(vap, IEEE80211_S_INIT,
3359                                 mlme->im_reason);
3360                         break;
3361                 case IEEE80211_M_HOSTAP:
3362                         /* NB: the broadcast address means do 'em all */
3363                         if (!IEEE80211_ADDR_EQ(mlme->im_macaddr, vap->iv_dev->broadcast)) {
3364                                 ni = ieee80211_find_node(&ic->ic_sta,
3365                                         mlme->im_macaddr);
3366                                 if (ni == NULL)
3367                                         return -EINVAL;
3368                                 if (dev == ni->ni_vap->iv_dev)
3369                                         domlme(mlme, ni);
3370                                 ieee80211_free_node(ni);
3371                         } else
3372                                 ieee80211_iterate_dev_nodes(dev, &ic->ic_sta, domlme, mlme);
3373                         break;
3374                 default:
3375                         return -EINVAL;
3376                 }
3377                 break;
3378         case IEEE80211_MLME_AUTHORIZE:
3379         case IEEE80211_MLME_UNAUTHORIZE:
3380                 if (vap->iv_opmode != IEEE80211_M_HOSTAP)
3381                         return -EINVAL;
3382                 ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
3383                 if (ni == NULL)
3384                         return -EINVAL;
3385                 if (mlme->im_op == IEEE80211_MLME_AUTHORIZE)
3386                         ieee80211_node_authorize(ni);
3387                 else
3388                         ieee80211_node_unauthorize(ni);
3389                 ieee80211_free_node(ni);
3390                 break;
3391         case IEEE80211_MLME_CLEAR_STATS:
3392                 if (vap->iv_opmode != IEEE80211_M_HOSTAP)
3393                         return -EINVAL;
3394                 ni = ieee80211_find_node(&ic->ic_sta, mlme->im_macaddr);
3395                 if (ni == NULL)
3396                         return -ENOENT;
3397                 
3398                 /* clear statistics */
3399                 memset(&ni->ni_stats, 0, sizeof(struct ieee80211_nodestats));
3400                 ieee80211_free_node(ni);
3401                 break;
3402         default:
3403                 return -EINVAL;
3404         }
3405         return 0;
3406 }
3407
3408 static int
3409 ieee80211_ioctl_wdsmac(struct net_device *dev, struct iw_request_info *info,
3410         void *w, char *extra)
3411 {
3412         struct ieee80211vap *vap = netdev_priv(dev);
3413         struct sockaddr *sa = (struct sockaddr *)extra;
3414         struct ieee80211com *ic = vap->iv_ic;
3415
3416         if (!IEEE80211_ADDR_NULL(vap->wds_mac)) {
3417                 printk("%s: Failed to add WDS MAC: %s\n", dev->name,
3418                         ether_sprintf(sa->sa_data));
3419                 printk("%s: Device already has WDS mac address attached,"
3420                         " remove first\n", dev->name);
3421                 return -1;
3422         }
3423
3424         memcpy(vap->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN);
3425
3426         printk("%s: Added WDS MAC: %s\n", dev->name,
3427                 ether_sprintf(vap->wds_mac));
3428
3429         if (IS_UP(vap->iv_dev))
3430                 return ic->ic_reset(ic->ic_dev);
3431
3432         return 0;
3433 }
3434
3435 static int
3436 ieee80211_ioctl_wdsdelmac(struct net_device *dev, struct iw_request_info *info,
3437         void *w, char *extra)
3438 {
3439         struct ieee80211vap *vap = netdev_priv(dev);
3440         struct sockaddr *sa = (struct sockaddr *)extra;
3441         struct ieee80211com *ic = vap->iv_ic;
3442
3443         /* WDS Mac address filed already? */
3444         if (IEEE80211_ADDR_NULL(vap->wds_mac))
3445                 return 0;
3446
3447         /* Compare suplied MAC address with WDS MAC of this interface 
3448          * remove when mac address is known
3449          */
3450         if (memcmp(vap->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN) == 0) {
3451                 memset(vap->wds_mac, 0x00, IEEE80211_ADDR_LEN);
3452                 if (IS_UP(vap->iv_dev))
3453                         return ic->ic_reset(ic->ic_dev);
3454                 return 0;                        
3455         }
3456
3457         printk("%s: WDS MAC address %s is not known by this interface\n",
3458                dev->name, ether_sprintf(sa->sa_data));
3459
3460         return -1;
3461 }
3462
3463 /*
3464  * kick associated station with the given MAC address.
3465  */
3466 static int
3467 ieee80211_ioctl_kickmac(struct net_device *dev, struct iw_request_info *info,
3468         void *w, char *extra)
3469 {
3470         struct sockaddr *sa = (struct sockaddr *)extra;
3471         struct ieee80211req_mlme mlme;
3472         
3473         if (sa->sa_family != ARPHRD_ETHER)
3474                 return -EINVAL;
3475
3476         /* Setup a MLME request for disassociation of the given MAC */
3477         mlme.im_op = IEEE80211_MLME_DISASSOC;
3478         mlme.im_reason = IEEE80211_REASON_UNSPECIFIED;
3479         IEEE80211_ADDR_COPY(&(mlme.im_macaddr), sa->sa_data);
3480
3481         /* Send the MLME request and return the result. */
3482         return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme);
3483 }
3484
3485 static int
3486 ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
3487         void *w, char *extra)
3488 {
3489         struct ieee80211vap *vap = netdev_priv(dev);
3490         struct sockaddr *sa = (struct sockaddr *)extra;
3491         const struct ieee80211_aclator *acl = vap->iv_acl;
3492
3493         if (acl == NULL) {
3494                 acl = ieee80211_aclator_get("mac");
3495                 if (acl == NULL || !acl->iac_attach(vap))
3496                         return -EINVAL;
3497                 vap->iv_acl = acl;
3498         }
3499         acl->iac_add(vap, sa->sa_data);
3500         return 0;
3501 }
3502
3503 static int
3504 ieee80211_ioctl_delmac(struct net_device *dev, struct iw_request_info *info,
3505         void *w, char *extra)
3506 {
3507         struct ieee80211vap *vap = netdev_priv(dev);
3508         struct sockaddr *sa = (struct sockaddr *)extra;
3509         const struct ieee80211_aclator *acl = vap->iv_acl;
3510
3511         if (acl == NULL) {
3512                 acl = ieee80211_aclator_get("mac");
3513                 if (acl == NULL || !acl->iac_attach(vap))
3514                         return -EINVAL;
3515                 vap->iv_acl = acl;
3516         }
3517         acl->iac_remove(vap, sa->sa_data);
3518         return 0;
3519 }
3520
3521 static int
3522 ieee80211_ioctl_setchanlist(struct net_device *dev,
3523         struct iw_request_info *info, void *w, char *extra)
3524 {
3525         struct ieee80211vap *vap = netdev_priv(dev);
3526         struct ieee80211com *ic = vap->iv_ic;
3527         struct ieee80211req_chanlist *list =
3528                 (struct ieee80211req_chanlist *)extra;
3529         u_char chanlist[IEEE80211_CHAN_BYTES];
3530         int i, j, nchan;
3531
3532         memset(chanlist, 0, sizeof(chanlist));
3533         /*
3534          * Since channel 0 is not available for DS, channel 1
3535          * is assigned to LSB on WaveLAN.
3536          */
3537         if (ic->ic_phytype == IEEE80211_T_DS)
3538                 i = 1;
3539         else
3540                 i = 0;
3541         nchan = 0;
3542         for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
3543                 /*
3544                  * NB: silently discard unavailable channels so users
3545                  *     can specify 1-255 to get all available channels.
3546                  */
3547                 if (isset(list->ic_channels, j) && isset(ic->ic_chan_avail, i)) {
3548                         setbit(chanlist, i);
3549                         nchan++;
3550                 }
3551         }
3552         if (nchan == 0)                 /* no valid channels, disallow */
3553                 return -EINVAL;
3554         if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&    /* XXX */
3555             isclr(chanlist, ic->ic_bsschan->ic_ieee))
3556                 ic->ic_bsschan = IEEE80211_CHAN_ANYC;   /* invalidate */
3557         memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
3558         if (IS_UP_AUTO(vap))
3559                 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
3560         return 0;
3561 }
3562
3563 static int
3564 ieee80211_ioctl_getchanlist(struct net_device *dev,
3565         struct iw_request_info *info, void *w, char *extra)
3566 {
3567         struct ieee80211vap *vap = netdev_priv(dev);
3568         struct ieee80211com *ic = vap->iv_ic;
3569
3570         memcpy(extra, ic->ic_chan_active, sizeof(ic->ic_chan_active));
3571         return 0;
3572 }
3573
3574 static int
3575 ieee80211_ioctl_getchaninfo(struct net_device *dev,
3576         struct iw_request_info *info, void *w, char *extra)
3577 {
3578         struct ieee80211vap *vap = netdev_priv(dev);
3579         struct ieee80211com *ic = vap->iv_ic;
3580         struct ieee80211req_chaninfo *chans =
3581                 (struct ieee80211req_chaninfo *) extra;
3582         u_int8_t reported[IEEE80211_CHAN_BYTES];        /* XXX stack usage? */
3583         int i;
3584
3585         memset(chans, 0, sizeof(*chans));
3586         memset(reported, 0, sizeof(reported));
3587         for (i = 0; i < ic->ic_nchans; i++) {
3588                 const struct ieee80211_channel *c = &ic->ic_channels[i];
3589                 const struct ieee80211_channel *c1 = c;
3590
3591                 if (isclr(reported, c->ic_ieee)) {
3592                         setbit(reported, c->ic_ieee);
3593
3594                         /* pick turbo channel over non-turbo channel, and
3595                          * 11g channel over 11b channel */
3596                         if (IEEE80211_IS_CHAN_A(c))
3597                                 c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_A);
3598                         if (IEEE80211_IS_CHAN_ANYG(c))
3599                                 c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G);
3600                         else if (IEEE80211_IS_CHAN_B(c)) {
3601                                 c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G);
3602                                 if (!c1)
3603                                         c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_11G);
3604                         }
3605
3606                         if (c1)
3607                                 c = c1;
3608                         chans->ic_chans[chans->ic_nchans].ic_ieee = c->ic_ieee;
3609                         chans->ic_chans[chans->ic_nchans].ic_freq = c->ic_freq;
3610                         chans->ic_chans[chans->ic_nchans].ic_flags = c->ic_flags;
3611                         if (++chans->ic_nchans >= IEEE80211_CHAN_MAX)
3612                                 break;
3613                 }
3614         }
3615         return 0;
3616 }
3617
3618 static int
3619 ieee80211_ioctl_setwmmparams(struct net_device *dev,
3620         struct iw_request_info *info, void *w, char *extra)
3621 {
3622         struct ieee80211vap *vap = netdev_priv(dev);
3623         int *param = (int *) extra;
3624         int ac = (param[1] >= 0 && param[1] < WME_NUM_AC) ?
3625                 param[1] : WME_AC_BE;
3626         int bss = param[2]; 
3627         struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme;
3628
3629         switch (param[0]) {
3630         case IEEE80211_WMMPARAMS_CWMIN:
3631                 if (param[3] < 0 || param[3] > 15) 
3632                         return -EINVAL;
3633                 if (bss) {
3634                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3635                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3636                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3637                 } else {
3638                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3639                         wme->wme_chanParams.cap_wmeParams[ac].wmep_logcwmin = param[3];
3640                 }
3641                 ieee80211_wme_updateparams(vap);        
3642                 break;
3643         case IEEE80211_WMMPARAMS_CWMAX:
3644                 if (param[3] < 0 || param[3] > 15) 
3645                         return -EINVAL;
3646                 if (bss) {
3647                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3648                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3649                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3650                 } else {
3651                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3652                         wme->wme_chanParams.cap_wmeParams[ac].wmep_logcwmax = param[3];
3653                 }
3654                 ieee80211_wme_updateparams(vap);        
3655                 break;
3656         case IEEE80211_WMMPARAMS_AIFS:
3657                 if (param[3] < 0 || param[3] > 15) 
3658                         return -EINVAL; 
3659                 if (bss) {
3660                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3661                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3662                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3663                 } else {
3664                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3665                         wme->wme_chanParams.cap_wmeParams[ac].wmep_aifsn = param[3];
3666                 }
3667                 ieee80211_wme_updateparams(vap);        
3668                 break;
3669         case IEEE80211_WMMPARAMS_TXOPLIMIT:
3670                 if (param[3] < 0 || param[3] > 8192) 
3671                         return -EINVAL;
3672                 if (bss) {
3673                         wme->wme_wmeBssChanParams.cap_wmeParams[ac].wmep_txopLimit 
3674                                 = IEEE80211_US_TO_TXOP(param[3]);
3675                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
3676                                 wme->wme_bssChanParams.cap_wmeParams[ac].wmep_txopLimit =
3677                                         IEEE80211_US_TO_TXOP(param[3]);
3678                 } else {
3679                         wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_txopLimit 
3680                                 = IEEE80211_US_TO_TXOP(param[3]);
3681                         wme->wme_chanParams.cap_wmeParams[ac].wmep_txopLimit 
3682                                 = IEEE80211_US_TO_TXOP(param[3]);
3683                 }
3684                 ieee80211_wme_updateparams(vap);        
3685                 break;
3686         case IEEE80211_WMMPARAMS_ACM: