]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/net80211/ieee80211_ioctl.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / net80211 / ieee80211_ioctl.c
1 /*-
2  * Copyright (c) 2001 Atsushi Onoe
3  * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_compat.h"
31
32 /*
33  * IEEE 802.11 ioctl support (FreeBSD-specific)
34  */
35
36 #include "opt_inet.h"
37 #include "opt_ipx.h"
38
39 #include <sys/endian.h>
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/priv.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/systm.h>
46  
47 #include <net/if.h>
48 #include <net/if_dl.h>
49 #include <net/if_media.h>
50 #include <net/ethernet.h>
51
52 #ifdef INET
53 #include <netinet/in.h>
54 #include <netinet/if_ether.h>
55 #endif
56
57 #ifdef IPX
58 #include <netipx/ipx.h>
59 #include <netipx/ipx_if.h>
60 #endif
61
62 #include <net80211/ieee80211_var.h>
63 #include <net80211/ieee80211_ioctl.h>
64
65 #define IS_UP(_ic) \
66         (((_ic)->ic_ifp->if_flags & IFF_UP) &&                  \
67             ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
68 #define IS_UP_AUTO(_ic) \
69         (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
70 #define RESCAN  1
71
72 static struct ieee80211_channel *findchannel(struct ieee80211com *,
73                 int ieee, int mode);
74
75 static int
76 cap2cipher(int flag)
77 {
78         switch (flag) {
79         case IEEE80211_C_WEP:           return IEEE80211_CIPHER_WEP;
80         case IEEE80211_C_AES:           return IEEE80211_CIPHER_AES_OCB;
81         case IEEE80211_C_AES_CCM:       return IEEE80211_CIPHER_AES_CCM;
82         case IEEE80211_C_CKIP:          return IEEE80211_CIPHER_CKIP;
83         case IEEE80211_C_TKIP:          return IEEE80211_CIPHER_TKIP;
84         }
85         return -1;
86 }
87
88 static int
89 ieee80211_ioctl_getkey(struct ieee80211com *ic, struct ieee80211req *ireq)
90 {
91         struct ieee80211_node *ni;
92         struct ieee80211req_key ik;
93         struct ieee80211_key *wk;
94         const struct ieee80211_cipher *cip;
95         u_int kid;
96         int error;
97
98         if (ireq->i_len != sizeof(ik))
99                 return EINVAL;
100         error = copyin(ireq->i_data, &ik, sizeof(ik));
101         if (error)
102                 return error;
103         kid = ik.ik_keyix;
104         if (kid == IEEE80211_KEYIX_NONE) {
105                 ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
106                 if (ni == NULL)
107                         return EINVAL;          /* XXX */
108                 wk = &ni->ni_ucastkey;
109         } else {
110                 if (kid >= IEEE80211_WEP_NKID)
111                         return EINVAL;
112                 wk = &ic->ic_nw_keys[kid];
113                 IEEE80211_ADDR_COPY(&ik.ik_macaddr, ic->ic_bss->ni_macaddr);
114                 ni = NULL;
115         }
116         cip = wk->wk_cipher;
117         ik.ik_type = cip->ic_cipher;
118         ik.ik_keylen = wk->wk_keylen;
119         ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
120         if (wk->wk_keyix == ic->ic_def_txkey)
121                 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
122         if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
123                 /* NB: only root can read key data */
124                 ik.ik_keyrsc = wk->wk_keyrsc;
125                 ik.ik_keytsc = wk->wk_keytsc;
126                 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
127                 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
128                         memcpy(ik.ik_keydata+wk->wk_keylen,
129                                 wk->wk_key + IEEE80211_KEYBUF_SIZE,
130                                 IEEE80211_MICBUF_SIZE);
131                         ik.ik_keylen += IEEE80211_MICBUF_SIZE;
132                 }
133         } else {
134                 ik.ik_keyrsc = 0;
135                 ik.ik_keytsc = 0;
136                 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
137         }
138         if (ni != NULL)
139                 ieee80211_free_node(ni);
140         return copyout(&ik, ireq->i_data, sizeof(ik));
141 }
142
143 static int
144 ieee80211_ioctl_getchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
145 {
146
147         if (sizeof(ic->ic_chan_active) < ireq->i_len)
148                 ireq->i_len = sizeof(ic->ic_chan_active);
149         return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
150 }
151
152 static int
153 ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq)
154 {
155         int space;
156
157         space = __offsetof(struct ieee80211req_chaninfo,
158                         ic_chans[ic->ic_nchans]);
159         if (space > ireq->i_len)
160                 space = ireq->i_len;
161         /* XXX assumes compatible layout */
162         return copyout(&ic->ic_nchans, ireq->i_data, space);
163 }
164
165 static int
166 ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq, int req)
167 {
168         struct ieee80211_node *ni;
169         struct ieee80211req_wpaie2 wpaie;
170         int error;
171
172         if (ireq->i_len < IEEE80211_ADDR_LEN)
173                 return EINVAL;
174         error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
175         if (error != 0)
176                 return error;
177         ni = ieee80211_find_node(&ic->ic_sta, wpaie.wpa_macaddr);
178         if (ni == NULL)
179                 return ENOENT;          /* XXX */
180         memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
181         if (ni->ni_ies.wpa_ie != NULL) {
182                 int ielen = ni->ni_ies.wpa_ie[1] + 2;
183                 if (ielen > sizeof(wpaie.wpa_ie))
184                         ielen = sizeof(wpaie.wpa_ie);
185                 memcpy(wpaie.wpa_ie, ni->ni_ies.wpa_ie, ielen);
186         }
187         if (req == IEEE80211_IOC_WPAIE2) {
188                 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie));
189                 if (ni->ni_ies.rsn_ie != NULL) {
190                         int ielen = ni->ni_ies.rsn_ie[1] + 2;
191                         if (ielen > sizeof(wpaie.rsn_ie))
192                                 ielen = sizeof(wpaie.rsn_ie);
193                         memcpy(wpaie.rsn_ie, ni->ni_ies.rsn_ie, ielen);
194                 }
195                 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
196                         ireq->i_len = sizeof(struct ieee80211req_wpaie2);
197         } else {
198                 /* compatibility op, may overwrite wpa ie */
199                 /* XXX check ic_flags? */
200                 if (ni->ni_ies.rsn_ie != NULL) {
201                         int ielen = ni->ni_ies.rsn_ie[1] + 2;
202                         if (ielen > sizeof(wpaie.wpa_ie))
203                                 ielen = sizeof(wpaie.wpa_ie);
204                         memcpy(wpaie.wpa_ie, ni->ni_ies.rsn_ie, ielen);
205                 }
206                 if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
207                         ireq->i_len = sizeof(struct ieee80211req_wpaie);
208         }
209         ieee80211_free_node(ni);
210         return copyout(&wpaie, ireq->i_data, ireq->i_len);
211 }
212
213 static int
214 ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
215 {
216         struct ieee80211_node *ni;
217         uint8_t macaddr[IEEE80211_ADDR_LEN];
218         const int off = __offsetof(struct ieee80211req_sta_stats, is_stats);
219         int error;
220
221         if (ireq->i_len < off)
222                 return EINVAL;
223         error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
224         if (error != 0)
225                 return error;
226         ni = ieee80211_find_node(&ic->ic_sta, macaddr);
227         if (ni == NULL)
228                 return EINVAL;
229         if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
230                 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
231         /* NB: copy out only the statistics */
232         error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off,
233                         ireq->i_len - off);
234         ieee80211_free_node(ni);
235         return error;
236 }
237
238 static __inline uint8_t *
239 copyie(uint8_t *cp, const uint8_t *ie)
240 {
241         if (ie != NULL) {
242                 memcpy(cp, ie, 2+ie[1]);
243                 cp += 2+ie[1];
244         }
245         return cp;
246 }
247
248 #ifdef COMPAT_FREEBSD6
249 #define IEEE80211_IOC_SCAN_RESULTS_OLD  24
250
251 struct scan_result_old {
252         uint16_t        isr_len;                /* length (mult of 4) */
253         uint16_t        isr_freq;               /* MHz */
254         uint16_t        isr_flags;              /* channel flags */
255         uint8_t         isr_noise;
256         uint8_t         isr_rssi;
257         uint8_t         isr_intval;             /* beacon interval */
258         uint8_t         isr_capinfo;            /* capabilities */
259         uint8_t         isr_erp;                /* ERP element */
260         uint8_t         isr_bssid[IEEE80211_ADDR_LEN];
261         uint8_t         isr_nrates;
262         uint8_t         isr_rates[IEEE80211_RATE_MAXSIZE];
263         uint8_t         isr_ssid_len;           /* SSID length */
264         uint8_t         isr_ie_len;             /* IE length */
265         uint8_t         isr_pad[5];
266         /* variable length SSID followed by IE data */
267 };
268
269 struct oscanreq {
270         struct scan_result_old *sr;
271         size_t space;
272 };
273
274 static size_t
275 old_scan_space(const struct ieee80211_scan_entry *se, int *ielen)
276 {
277         size_t len;
278
279         *ielen = 0;
280         if (se->se_ies.wpa_ie != NULL)
281                 *ielen += 2+se->se_ies.wpa_ie[1];
282         if (se->se_ies.wme_ie != NULL)
283                 *ielen += 2+se->se_ies.wme_ie[1];
284         /*
285          * NB: ie's can be no more than 255 bytes and the max 802.11
286          * packet is <3Kbytes so we are sure this doesn't overflow
287          * 16-bits; if this is a concern we can drop the ie's.
288          */
289         len = sizeof(struct scan_result_old) + se->se_ssid[1] + *ielen;
290         return roundup(len, sizeof(uint32_t));
291 }
292
293 static void
294 old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
295 {
296         struct oscanreq *req = arg;
297         int ielen;
298
299         req->space += old_scan_space(se, &ielen);
300 }
301
302 static void
303 old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
304 {
305         struct oscanreq *req = arg;
306         struct scan_result_old *sr;
307         int ielen, len, nr, nxr;
308         uint8_t *cp;
309
310         len = old_scan_space(se, &ielen);
311         if (len > req->space)
312                 return;
313
314         sr = req->sr;
315         memset(sr, 0, sizeof(*sr));
316         sr->isr_ssid_len = se->se_ssid[1];
317         /* NB: beware of overflow, isr_ie_len is 8 bits */
318         sr->isr_ie_len = (ielen > 255 ? 0 : ielen);
319         sr->isr_len = len;
320         sr->isr_freq = se->se_chan->ic_freq;
321         sr->isr_flags = se->se_chan->ic_flags;
322         sr->isr_rssi = se->se_rssi;
323         sr->isr_noise = se->se_noise;
324         sr->isr_intval = se->se_intval;
325         sr->isr_capinfo = se->se_capinfo;
326         sr->isr_erp = se->se_erp;
327         IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
328         nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
329         memcpy(sr->isr_rates, se->se_rates+2, nr);
330         nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
331         memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
332         sr->isr_nrates = nr + nxr;
333
334         cp = (uint8_t *)(sr+1);
335         memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
336         cp += sr->isr_ssid_len;
337         if (sr->isr_ie_len) {
338                 cp = copyie(cp, se->se_ies.wpa_ie);
339                 cp = copyie(cp, se->se_ies.wme_ie);
340         }
341
342         req->space -= len;
343         req->sr = (struct scan_result_old *)(((uint8_t *)sr) + len);
344 }
345
346 static int
347 old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
348 {
349         struct oscanreq req;
350         int error;
351
352         if (ireq->i_len < sizeof(struct scan_result_old))
353                 return EFAULT;
354
355         error = 0;
356         req.space = 0;
357         ieee80211_scan_iterate(ic, old_get_scan_space, &req);
358         if (req.space > ireq->i_len)
359                 req.space = ireq->i_len;
360         if (req.space > 0) {
361                 size_t space;
362                 void *p;
363
364                 space = req.space;
365                 /* XXX M_WAITOK after driver lock released */
366                 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
367                 if (p == NULL)
368                         return ENOMEM;
369                 req.sr = p;
370                 ieee80211_scan_iterate(ic, old_get_scan_result, &req);
371                 ireq->i_len = space - req.space;
372                 error = copyout(p, ireq->i_data, ireq->i_len);
373                 FREE(p, M_TEMP);
374         } else
375                 ireq->i_len = 0;
376
377         return error;
378 }
379 #endif /* COMPAT_FREEBSD6 */
380
381 struct scanreq {
382         struct ieee80211req_scan_result *sr;
383         size_t space;
384 };
385
386 static size_t
387 scan_space(const struct ieee80211_scan_entry *se, int *ielen)
388 {
389         size_t len;
390
391         *ielen = se->se_ies.len;
392         /*
393          * NB: ie's can be no more than 255 bytes and the max 802.11
394          * packet is <3Kbytes so we are sure this doesn't overflow
395          * 16-bits; if this is a concern we can drop the ie's.
396          */
397         len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen;
398         return roundup(len, sizeof(uint32_t));
399 }
400
401 static void
402 get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
403 {
404         struct scanreq *req = arg;
405         int ielen;
406
407         req->space += scan_space(se, &ielen);
408 }
409
410 static void
411 get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
412 {
413         struct scanreq *req = arg;
414         struct ieee80211req_scan_result *sr;
415         int ielen, len, nr, nxr;
416         uint8_t *cp;
417
418         len = scan_space(se, &ielen);
419         if (len > req->space)
420                 return;
421
422         sr = req->sr;
423         KASSERT(len <= 65535 && ielen <= 65535,
424             ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
425         sr->isr_ie_off = sizeof(struct ieee80211req_scan_result);
426         sr->isr_ie_len = ielen;
427         sr->isr_len = len;
428         sr->isr_freq = se->se_chan->ic_freq;
429         sr->isr_flags = se->se_chan->ic_flags;
430         sr->isr_rssi = se->se_rssi;
431         sr->isr_noise = se->se_noise;
432         sr->isr_intval = se->se_intval;
433         sr->isr_capinfo = se->se_capinfo;
434         sr->isr_erp = se->se_erp;
435         IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
436         nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
437         memcpy(sr->isr_rates, se->se_rates+2, nr);
438         nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
439         memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
440         sr->isr_nrates = nr + nxr;
441
442         sr->isr_ssid_len = se->se_ssid[1];
443         cp = ((uint8_t *)sr) + sr->isr_ie_off;
444         memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
445
446         if (ielen) {
447                 cp += sr->isr_ssid_len;
448                 memcpy(cp, se->se_ies.data, ielen);
449         }
450
451         req->space -= len;
452         req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
453 }
454
455 static int
456 ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
457 {
458         struct scanreq req;
459         int error;
460
461         if (ireq->i_len < sizeof(struct ieee80211req_scan_result))
462                 return EFAULT;
463
464         error = 0;
465         req.space = 0;
466         ieee80211_scan_iterate(ic, get_scan_space, &req);
467         if (req.space > ireq->i_len)
468                 req.space = ireq->i_len;
469         if (req.space > 0) {
470                 size_t space;
471                 void *p;
472
473                 space = req.space;
474                 /* XXX M_WAITOK after driver lock released */
475                 MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
476                 if (p == NULL)
477                         return ENOMEM;
478                 req.sr = p;
479                 ieee80211_scan_iterate(ic, get_scan_result, &req);
480                 ireq->i_len = space - req.space;
481                 error = copyout(p, ireq->i_data, ireq->i_len);
482                 FREE(p, M_TEMP);
483         } else
484                 ireq->i_len = 0;
485
486         return error;
487 }
488
489 struct stainforeq {
490         struct ieee80211com *ic;
491         struct ieee80211req_sta_info *si;
492         size_t  space;
493 };
494
495 static size_t
496 sta_space(const struct ieee80211_node *ni, size_t *ielen)
497 {
498         *ielen = ni->ni_ies.len;
499         return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
500                       sizeof(uint32_t));
501 }
502
503 static void
504 get_sta_space(void *arg, struct ieee80211_node *ni)
505 {
506         struct stainforeq *req = arg;
507         struct ieee80211com *ic = ni->ni_ic;
508         size_t ielen;
509
510         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
511             ni->ni_associd == 0)        /* only associated stations */
512                 return;
513         req->space += sta_space(ni, &ielen);
514 }
515
516 static void
517 get_sta_info(void *arg, struct ieee80211_node *ni)
518 {
519         struct stainforeq *req = arg;
520         struct ieee80211com *ic = ni->ni_ic;
521         struct ieee80211req_sta_info *si;
522         size_t ielen, len;
523         uint8_t *cp;
524
525         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
526             ni->ni_associd == 0)        /* only associated stations */
527                 return;
528         if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
529                 return;
530         len = sta_space(ni, &ielen);
531         if (len > req->space)
532                 return;
533         si = req->si;
534         si->isi_len = len;
535         si->isi_ie_off = sizeof(struct ieee80211req_sta_info);
536         si->isi_ie_len = ielen;
537         si->isi_freq = ni->ni_chan->ic_freq;
538         si->isi_flags = ni->ni_chan->ic_flags;
539         si->isi_state = ni->ni_flags;
540         si->isi_authmode = ni->ni_authmode;
541         ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise);
542         si->isi_noise = 0;              /* XXX */
543         si->isi_capinfo = ni->ni_capinfo;
544         si->isi_erp = ni->ni_erp;
545         IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
546         si->isi_nrates = ni->ni_rates.rs_nrates;
547         if (si->isi_nrates > 15)
548                 si->isi_nrates = 15;
549         memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
550         si->isi_txrate = ni->ni_txrate;
551         si->isi_ie_len = ielen;
552         si->isi_associd = ni->ni_associd;
553         si->isi_txpower = ni->ni_txpower;
554         si->isi_vlan = ni->ni_vlan;
555         if (ni->ni_flags & IEEE80211_NODE_QOS) {
556                 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
557                 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
558         } else {
559                 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
560                 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
561         }
562         /* NB: leave all cases in case we relax ni_associd == 0 check */
563         if (ieee80211_node_is_authorized(ni))
564                 si->isi_inact = ic->ic_inact_run;
565         else if (ni->ni_associd != 0)
566                 si->isi_inact = ic->ic_inact_auth;
567         else
568                 si->isi_inact = ic->ic_inact_init;
569         si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
570
571         if (ielen) {
572                 cp = ((uint8_t *)si) + si->isi_ie_off;
573                 memcpy(cp, ni->ni_ies.data, ielen);
574         }
575
576         req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len);
577         req->space -= len;
578 }
579
580 static int
581 getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq,
582         struct ieee80211_node *ni, int off)
583 {
584         struct stainforeq req;
585         size_t space;
586         void *p;
587         int error;
588
589         error = 0;
590         req.space = 0;
591         if (ni == NULL)
592                 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req);
593         else
594                 get_sta_space(&req, ni);
595         if (req.space > ireq->i_len)
596                 req.space = ireq->i_len;
597         if (req.space > 0) {
598                 space = req.space;
599                 /* XXX M_WAITOK after driver lock released */
600                 MALLOC(p, void *, space, M_TEMP, M_NOWAIT);
601                 if (p == NULL) {
602                         error = ENOMEM;
603                         goto bad;
604                 }
605                 req.si = p;
606                 if (ni == NULL)
607                         ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
608                 else
609                         get_sta_info(&req, ni);
610                 ireq->i_len = space - req.space;
611                 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
612                 FREE(p, M_TEMP);
613         } else
614                 ireq->i_len = 0;
615 bad:
616         if (ni != NULL)
617                 ieee80211_free_node(ni);
618         return error;
619 }
620
621 static int
622 ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
623 {
624         uint8_t macaddr[IEEE80211_ADDR_LEN];
625         const int off = __offsetof(struct ieee80211req_sta_req, info);
626         struct ieee80211_node *ni;
627         int error;
628
629         if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
630                 return EFAULT;
631         error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
632         if (error != 0)
633                 return error;
634         if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) {
635                 ni = NULL;
636         } else {
637                 ni = ieee80211_find_node(&ic->ic_sta, macaddr);
638                 if (ni == NULL)
639                         return EINVAL;
640         }
641         return getstainfo_common(ic, ireq, ni, off);
642 }
643
644 #ifdef COMPAT_FREEBSD6
645 #define IEEE80211_IOC_STA_INFO_OLD      45
646
647 static int
648 old_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
649 {
650         if (ireq->i_len < sizeof(struct ieee80211req_sta_info))
651                 return EFAULT;
652         return getstainfo_common(ic, ireq, NULL, 0);
653 }
654 #endif /* COMPAT_FREEBSD6 */
655
656 static int
657 ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
658 {
659         struct ieee80211_node *ni;
660         struct ieee80211req_sta_txpow txpow;
661         int error;
662
663         if (ireq->i_len != sizeof(txpow))
664                 return EINVAL;
665         error = copyin(ireq->i_data, &txpow, sizeof(txpow));
666         if (error != 0)
667                 return error;
668         ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
669         if (ni == NULL)
670                 return EINVAL;          /* XXX */
671         txpow.it_txpow = ni->ni_txpower;
672         error = copyout(&txpow, ireq->i_data, sizeof(txpow));
673         ieee80211_free_node(ni);
674         return error;
675 }
676
677 static int
678 ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
679 {
680         struct ieee80211_wme_state *wme = &ic->ic_wme;
681         struct wmeParams *wmep;
682         int ac;
683
684         if ((ic->ic_caps & IEEE80211_C_WME) == 0)
685                 return EINVAL;
686
687         ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
688         if (ac >= WME_NUM_AC)
689                 ac = WME_AC_BE;
690         if (ireq->i_len & IEEE80211_WMEPARAM_BSS)
691                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
692         else
693                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
694         switch (ireq->i_type) {
695         case IEEE80211_IOC_WME_CWMIN:           /* WME: CWmin */
696                 ireq->i_val = wmep->wmep_logcwmin;
697                 break;
698         case IEEE80211_IOC_WME_CWMAX:           /* WME: CWmax */
699                 ireq->i_val = wmep->wmep_logcwmax;
700                 break;
701         case IEEE80211_IOC_WME_AIFS:            /* WME: AIFS */
702                 ireq->i_val = wmep->wmep_aifsn;
703                 break;
704         case IEEE80211_IOC_WME_TXOPLIMIT:       /* WME: txops limit */
705                 ireq->i_val = wmep->wmep_txopLimit;
706                 break;
707         case IEEE80211_IOC_WME_ACM:             /* WME: ACM (bss only) */
708                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
709                 ireq->i_val = wmep->wmep_acm;
710                 break;
711         case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (!bss only)*/
712                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
713                 ireq->i_val = !wmep->wmep_noackPolicy;
714                 break;
715         }
716         return 0;
717 }
718
719 static int
720 ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
721 {
722         const struct ieee80211_aclator *acl = ic->ic_acl;
723
724         return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq));
725 }
726
727 /*
728  * Return the current ``state'' of an Atheros capbility.
729  * If associated in station mode report the negotiated
730  * setting. Otherwise report the current setting.
731  */
732 static int
733 getathcap(struct ieee80211com *ic, int cap)
734 {
735         if (ic->ic_opmode == IEEE80211_M_STA && ic->ic_state == IEEE80211_S_RUN)
736                 return IEEE80211_ATH_CAP(ic, ic->ic_bss, cap) != 0;
737         else
738                 return (ic->ic_flags & cap) != 0;
739 }
740
741 static int
742 ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq)
743 {
744         if (ireq->i_len != sizeof(struct ieee80211_channel))
745                 return EINVAL;
746         return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan));
747 }
748
749 /*
750  * When building the kernel with -O2 on the i386 architecture, gcc
751  * seems to want to inline this function into ieee80211_ioctl()
752  * (which is the only routine that calls it). When this happens,
753  * ieee80211_ioctl() ends up consuming an additional 2K of stack
754  * space. (Exactly why it needs so much is unclear.) The problem
755  * is that it's possible for ieee80211_ioctl() to invoke other
756  * routines (including driver init functions) which could then find
757  * themselves perilously close to exhausting the stack.
758  *
759  * To avoid this, we deliberately prevent gcc from inlining this
760  * routine. Another way to avoid this is to use less agressive
761  * optimization when compiling this file (i.e. -O instead of -O2)
762  * but special-casing the compilation of this one module in the
763  * build system would be awkward.
764  */
765 #ifdef __GNUC__
766 __attribute__ ((noinline))
767 #endif
768 static int
769 ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
770 {
771         const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
772         int error = 0;
773         u_int kid, len, m;
774         uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
775         char tmpssid[IEEE80211_NWID_LEN];
776
777         switch (ireq->i_type) {
778         case IEEE80211_IOC_SSID:
779                 switch (ic->ic_state) {
780                 case IEEE80211_S_INIT:
781                 case IEEE80211_S_SCAN:
782                         ireq->i_len = ic->ic_des_ssid[0].len;
783                         memcpy(tmpssid, ic->ic_des_ssid[0].ssid, ireq->i_len);
784                         break;
785                 default:
786                         ireq->i_len = ic->ic_bss->ni_esslen;
787                         memcpy(tmpssid, ic->ic_bss->ni_essid,
788                                 ireq->i_len);
789                         break;
790                 }
791                 error = copyout(tmpssid, ireq->i_data, ireq->i_len);
792                 break;
793         case IEEE80211_IOC_NUMSSIDS:
794                 ireq->i_val = 1;
795                 break;
796         case IEEE80211_IOC_WEP:
797                 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0)
798                         ireq->i_val = IEEE80211_WEP_OFF;
799                 else if (ic->ic_flags & IEEE80211_F_DROPUNENC)
800                         ireq->i_val = IEEE80211_WEP_ON;
801                 else
802                         ireq->i_val = IEEE80211_WEP_MIXED;
803                 break;
804         case IEEE80211_IOC_WEPKEY:
805                 kid = (u_int) ireq->i_val;
806                 if (kid >= IEEE80211_WEP_NKID)
807                         return EINVAL;
808                 len = (u_int) ic->ic_nw_keys[kid].wk_keylen;
809                 /* NB: only root can read WEP keys */
810                 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
811                         bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len);
812                 } else {
813                         bzero(tmpkey, len);
814                 }
815                 ireq->i_len = len;
816                 error = copyout(tmpkey, ireq->i_data, len);
817                 break;
818         case IEEE80211_IOC_NUMWEPKEYS:
819                 ireq->i_val = IEEE80211_WEP_NKID;
820                 break;
821         case IEEE80211_IOC_WEPTXKEY:
822                 ireq->i_val = ic->ic_def_txkey;
823                 break;
824         case IEEE80211_IOC_AUTHMODE:
825                 if (ic->ic_flags & IEEE80211_F_WPA)
826                         ireq->i_val = IEEE80211_AUTH_WPA;
827                 else
828                         ireq->i_val = ic->ic_bss->ni_authmode;
829                 break;
830         case IEEE80211_IOC_CHANNEL:
831                 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan);
832                 break;
833         case IEEE80211_IOC_POWERSAVE:
834                 if (ic->ic_flags & IEEE80211_F_PMGTON)
835                         ireq->i_val = IEEE80211_POWERSAVE_ON;
836                 else
837                         ireq->i_val = IEEE80211_POWERSAVE_OFF;
838                 break;
839         case IEEE80211_IOC_POWERSAVESLEEP:
840                 ireq->i_val = ic->ic_lintval;
841                 break;
842         case IEEE80211_IOC_RTSTHRESHOLD:
843                 ireq->i_val = ic->ic_rtsthreshold;
844                 break;
845         case IEEE80211_IOC_PROTMODE:
846                 ireq->i_val = ic->ic_protmode;
847                 break;
848         case IEEE80211_IOC_TXPOWER:
849                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
850                         return EINVAL;
851                 ireq->i_val = ic->ic_txpowlimit;
852                 break;
853         case IEEE80211_IOC_MCASTCIPHER:
854                 ireq->i_val = rsn->rsn_mcastcipher;
855                 break;
856         case IEEE80211_IOC_MCASTKEYLEN:
857                 ireq->i_val = rsn->rsn_mcastkeylen;
858                 break;
859         case IEEE80211_IOC_UCASTCIPHERS:
860                 ireq->i_val = 0;
861                 for (m = 0x1; m != 0; m <<= 1)
862                         if (rsn->rsn_ucastcipherset & m)
863                                 ireq->i_val |= 1<<cap2cipher(m);
864                 break;
865         case IEEE80211_IOC_UCASTCIPHER:
866                 ireq->i_val = rsn->rsn_ucastcipher;
867                 break;
868         case IEEE80211_IOC_UCASTKEYLEN:
869                 ireq->i_val = rsn->rsn_ucastkeylen;
870                 break;
871         case IEEE80211_IOC_KEYMGTALGS:
872                 ireq->i_val = rsn->rsn_keymgmtset;
873                 break;
874         case IEEE80211_IOC_RSNCAPS:
875                 ireq->i_val = rsn->rsn_caps;
876                 break;
877         case IEEE80211_IOC_WPA:
878                 switch (ic->ic_flags & IEEE80211_F_WPA) {
879                 case IEEE80211_F_WPA1:
880                         ireq->i_val = 1;
881                         break;
882                 case IEEE80211_F_WPA2:
883                         ireq->i_val = 2;
884                         break;
885                 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
886                         ireq->i_val = 3;
887                         break;
888                 default:
889                         ireq->i_val = 0;
890                         break;
891                 }
892                 break;
893         case IEEE80211_IOC_CHANLIST:
894                 error = ieee80211_ioctl_getchanlist(ic, ireq);
895                 break;
896         case IEEE80211_IOC_ROAMING:
897                 ireq->i_val = ic->ic_roaming;
898                 break;
899         case IEEE80211_IOC_PRIVACY:
900                 ireq->i_val = (ic->ic_flags & IEEE80211_F_PRIVACY) != 0;
901                 break;
902         case IEEE80211_IOC_DROPUNENCRYPTED:
903                 ireq->i_val = (ic->ic_flags & IEEE80211_F_DROPUNENC) != 0;
904                 break;
905         case IEEE80211_IOC_COUNTERMEASURES:
906                 ireq->i_val = (ic->ic_flags & IEEE80211_F_COUNTERM) != 0;
907                 break;
908         case IEEE80211_IOC_DRIVER_CAPS:
909                 ireq->i_val = ic->ic_caps>>16;
910                 ireq->i_len = ic->ic_caps&0xffff;
911                 break;
912         case IEEE80211_IOC_WME:
913                 ireq->i_val = (ic->ic_flags & IEEE80211_F_WME) != 0;
914                 break;
915         case IEEE80211_IOC_HIDESSID:
916                 ireq->i_val = (ic->ic_flags & IEEE80211_F_HIDESSID) != 0;
917                 break;
918         case IEEE80211_IOC_APBRIDGE:
919                 ireq->i_val = (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0;
920                 break;
921         case IEEE80211_IOC_OPTIE:
922                 if (ic->ic_opt_ie == NULL)
923                         return EINVAL;
924                 /* NB: truncate, caller can check length */
925                 if (ireq->i_len > ic->ic_opt_ie_len)
926                         ireq->i_len = ic->ic_opt_ie_len;
927                 error = copyout(ic->ic_opt_ie, ireq->i_data, ireq->i_len);
928                 break;
929         case IEEE80211_IOC_WPAKEY:
930                 error = ieee80211_ioctl_getkey(ic, ireq);
931                 break;
932         case IEEE80211_IOC_CHANINFO:
933                 error = ieee80211_ioctl_getchaninfo(ic, ireq);
934                 break;
935         case IEEE80211_IOC_BSSID:
936                 if (ireq->i_len != IEEE80211_ADDR_LEN)
937                         return EINVAL;
938                 error = copyout(ic->ic_state == IEEE80211_S_RUN ?
939                                         ic->ic_bss->ni_bssid :
940                                         ic->ic_des_bssid,
941                                 ireq->i_data, ireq->i_len);
942                 break;
943         case IEEE80211_IOC_WPAIE:
944                 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
945                 break;
946         case IEEE80211_IOC_WPAIE2:
947                 error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
948                 break;
949 #ifdef COMPAT_FREEBSD6
950         case IEEE80211_IOC_SCAN_RESULTS_OLD:
951                 error = old_getscanresults(ic, ireq);
952                 break;
953 #endif
954         case IEEE80211_IOC_SCAN_RESULTS:
955                 error = ieee80211_ioctl_getscanresults(ic, ireq);
956                 break;
957         case IEEE80211_IOC_STA_STATS:
958                 error = ieee80211_ioctl_getstastats(ic, ireq);
959                 break;
960         case IEEE80211_IOC_TXPOWMAX:
961                 ireq->i_val = ic->ic_bss->ni_txpower;
962                 break;
963         case IEEE80211_IOC_STA_TXPOW:
964                 error = ieee80211_ioctl_getstatxpow(ic, ireq);
965                 break;
966 #ifdef COMPAT_FREEBSD6
967         case IEEE80211_IOC_STA_INFO_OLD:
968                 error = old_getstainfo(ic, ireq);
969                 break;
970 #endif
971         case IEEE80211_IOC_STA_INFO:
972                 error = ieee80211_ioctl_getstainfo(ic, ireq);
973                 break;
974         case IEEE80211_IOC_WME_CWMIN:           /* WME: CWmin */
975         case IEEE80211_IOC_WME_CWMAX:           /* WME: CWmax */
976         case IEEE80211_IOC_WME_AIFS:            /* WME: AIFS */
977         case IEEE80211_IOC_WME_TXOPLIMIT:       /* WME: txops limit */
978         case IEEE80211_IOC_WME_ACM:             /* WME: ACM (bss only) */
979         case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (bss only) */
980                 error = ieee80211_ioctl_getwmeparam(ic, ireq);
981                 break;
982         case IEEE80211_IOC_DTIM_PERIOD:
983                 ireq->i_val = ic->ic_dtim_period;
984                 break;
985         case IEEE80211_IOC_BEACON_INTERVAL:
986                 /* NB: get from ic_bss for station mode */
987                 ireq->i_val = ic->ic_bss->ni_intval;
988                 break;
989         case IEEE80211_IOC_PUREG:
990                 ireq->i_val = (ic->ic_flags & IEEE80211_F_PUREG) != 0;
991                 break;
992         case IEEE80211_IOC_FF:
993                 ireq->i_val = getathcap(ic, IEEE80211_F_FF);
994                 break;
995         case IEEE80211_IOC_TURBOP:
996                 ireq->i_val = getathcap(ic, IEEE80211_F_TURBOP);
997                 break;
998         case IEEE80211_IOC_BGSCAN:
999                 ireq->i_val = (ic->ic_flags & IEEE80211_F_BGSCAN) != 0;
1000                 break;
1001         case IEEE80211_IOC_BGSCAN_IDLE:
1002                 ireq->i_val = ic->ic_bgscanidle*hz/1000;        /* ms */
1003                 break;
1004         case IEEE80211_IOC_BGSCAN_INTERVAL:
1005                 ireq->i_val = ic->ic_bgscanintvl/hz;            /* seconds */
1006                 break;
1007         case IEEE80211_IOC_SCANVALID:
1008                 ireq->i_val = ic->ic_scanvalid/hz;              /* seconds */
1009                 break;
1010         case IEEE80211_IOC_ROAM_RSSI_11A:
1011                 ireq->i_val = ic->ic_roam.rssi11a;
1012                 break;
1013         case IEEE80211_IOC_ROAM_RSSI_11B:
1014                 ireq->i_val = ic->ic_roam.rssi11bOnly;
1015                 break;
1016         case IEEE80211_IOC_ROAM_RSSI_11G:
1017                 ireq->i_val = ic->ic_roam.rssi11b;
1018                 break;
1019         case IEEE80211_IOC_ROAM_RATE_11A:
1020                 ireq->i_val = ic->ic_roam.rate11a;
1021                 break;
1022         case IEEE80211_IOC_ROAM_RATE_11B:
1023                 ireq->i_val = ic->ic_roam.rate11bOnly;
1024                 break;
1025         case IEEE80211_IOC_ROAM_RATE_11G:
1026                 ireq->i_val = ic->ic_roam.rate11b;
1027                 break;
1028         case IEEE80211_IOC_MCAST_RATE:
1029                 ireq->i_val = ic->ic_mcast_rate;
1030                 break;
1031         case IEEE80211_IOC_FRAGTHRESHOLD:
1032                 ireq->i_val = ic->ic_fragthreshold;
1033                 break;
1034         case IEEE80211_IOC_MACCMD:
1035                 error = ieee80211_ioctl_getmaccmd(ic, ireq);
1036                 break;
1037         case IEEE80211_IOC_BURST:
1038                 ireq->i_val = (ic->ic_flags & IEEE80211_F_BURST) != 0;
1039                 break;
1040         case IEEE80211_IOC_BMISSTHRESHOLD:
1041                 ireq->i_val = ic->ic_bmissthreshold;
1042                 break;
1043         case IEEE80211_IOC_CURCHAN:
1044                 error = ieee80211_ioctl_getcurchan(ic, ireq);
1045                 break;
1046         case IEEE80211_IOC_SHORTGI:
1047                 ireq->i_val = 0;
1048                 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI20)
1049                         ireq->i_val |= IEEE80211_HTCAP_SHORTGI20;
1050                 if (ic->ic_flags_ext & IEEE80211_FEXT_SHORTGI40)
1051                         ireq->i_val |= IEEE80211_HTCAP_SHORTGI40;
1052                 break;
1053         case IEEE80211_IOC_AMPDU:
1054                 ireq->i_val = 0;
1055                 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX)
1056                         ireq->i_val |= 1;
1057                 if (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_RX)
1058                         ireq->i_val |= 2;
1059                 break;
1060         case IEEE80211_IOC_AMPDU_LIMIT:
1061                 ireq->i_val = ic->ic_ampdu_limit;       /* XXX truncation? */
1062                 break;
1063         case IEEE80211_IOC_AMPDU_DENSITY:
1064                 ireq->i_val = ic->ic_ampdu_density;
1065                 break;
1066         case IEEE80211_IOC_AMSDU:
1067                 ireq->i_val = 0;
1068                 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_TX)
1069                         ireq->i_val |= 1;
1070                 if (ic->ic_flags_ext & IEEE80211_FEXT_AMSDU_RX)
1071                         ireq->i_val |= 2;
1072                 break;
1073         case IEEE80211_IOC_AMSDU_LIMIT:
1074                 ireq->i_val = ic->ic_amsdu_limit;       /* XXX truncation? */
1075                 break;
1076         case IEEE80211_IOC_PUREN:
1077                 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_PUREN) != 0;
1078                 break;
1079         case IEEE80211_IOC_DOTH:
1080                 ireq->i_val = (ic->ic_flags & IEEE80211_F_DOTH) != 0;
1081                 break;
1082         case IEEE80211_IOC_HTCOMPAT:
1083                 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0;
1084                 break;
1085         case IEEE80211_IOC_INACTIVITY:
1086                 ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_INACT) != 0;
1087                 break;
1088         case IEEE80211_IOC_HTPROTMODE:
1089                 ireq->i_val = ic->ic_htprotmode;
1090                 break;
1091         case IEEE80211_IOC_HTCONF:
1092                 if (ic->ic_flags_ext & IEEE80211_FEXT_HT) {
1093                         ireq->i_val = 1;
1094                         if (ic->ic_flags_ext & IEEE80211_FEXT_USEHT40)
1095                                 ireq->i_val |= 2;
1096                 } else
1097                         ireq->i_val = 0;
1098                 break;
1099         default:
1100                 error = EINVAL;
1101                 break;
1102         }
1103         return error;
1104 }
1105
1106 static int
1107 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq)
1108 {
1109         int error;
1110         void *ie, *oie;
1111
1112         /*
1113          * NB: Doing this for ap operation could be useful (e.g. for
1114          *     WPA and/or WME) except that it typically is worthless
1115          *     without being able to intervene when processing
1116          *     association response frames--so disallow it for now.
1117          */
1118         if (ic->ic_opmode != IEEE80211_M_STA)
1119                 return EINVAL;
1120         if (ireq->i_len > IEEE80211_MAX_OPT_IE)
1121                 return EINVAL;
1122         /* NB: data.length is validated by the wireless extensions code */
1123         /* XXX M_WAITOK after driver lock released */
1124         if (ireq->i_len > 0) {
1125                 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
1126                 if (ie == NULL)
1127                         return ENOMEM;
1128                 error = copyin(ireq->i_data, ie, ireq->i_len);
1129                 if (error) {
1130                         FREE(ie, M_DEVBUF);
1131                         return error;
1132                 }
1133         } else {
1134                 ie = NULL;
1135                 ireq->i_len = 0;
1136         }
1137         /* XXX sanity check data? */
1138         oie = ic->ic_opt_ie;
1139         ic->ic_opt_ie = ie;
1140         ic->ic_opt_ie_len = ireq->i_len;
1141         if (oie != NULL)
1142                 FREE(oie, M_DEVBUF);
1143         return 0;
1144 }
1145
1146 static int
1147 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1148 {
1149         struct ieee80211req_key ik;
1150         struct ieee80211_node *ni;
1151         struct ieee80211_key *wk;
1152         uint16_t kid;
1153         int error;
1154
1155         if (ireq->i_len != sizeof(ik))
1156                 return EINVAL;
1157         error = copyin(ireq->i_data, &ik, sizeof(ik));
1158         if (error)
1159                 return error;
1160         /* NB: cipher support is verified by ieee80211_crypt_newkey */
1161         /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1162         if (ik.ik_keylen > sizeof(ik.ik_keydata))
1163                 return E2BIG;
1164         kid = ik.ik_keyix;
1165         if (kid == IEEE80211_KEYIX_NONE) {
1166                 /* XXX unicast keys currently must be tx/rx */
1167                 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1168                         return EINVAL;
1169                 if (ic->ic_opmode == IEEE80211_M_STA) {
1170                         ni = ieee80211_ref_node(ic->ic_bss);
1171                         if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1172                                 ieee80211_free_node(ni);
1173                                 return EADDRNOTAVAIL;
1174                         }
1175                 } else {
1176                         ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
1177                         if (ni == NULL)
1178                                 return ENOENT;
1179                 }
1180                 wk = &ni->ni_ucastkey;
1181         } else {
1182                 if (kid >= IEEE80211_WEP_NKID)
1183                         return EINVAL;
1184                 wk = &ic->ic_nw_keys[kid];
1185                 /*
1186                  * Global slots start off w/o any assigned key index.
1187                  * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1188                  */
1189                 if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1190                         wk->wk_keyix = kid;
1191                 ni = NULL;
1192         }
1193         error = 0;
1194         ieee80211_key_update_begin(ic);
1195         if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) {
1196                 wk->wk_keylen = ik.ik_keylen;
1197                 /* NB: MIC presence is implied by cipher type */
1198                 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1199                         wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1200                 wk->wk_keyrsc = ik.ik_keyrsc;
1201                 wk->wk_keytsc = 0;                      /* new key, reset */
1202                 memset(wk->wk_key, 0, sizeof(wk->wk_key));
1203                 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1204                 if (!ieee80211_crypto_setkey(ic, wk,
1205                     ni != NULL ? ni->ni_macaddr : ik.ik_macaddr))
1206                         error = EIO;
1207                 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1208                         ic->ic_def_txkey = kid;
1209         } else
1210                 error = ENXIO;
1211         ieee80211_key_update_end(ic);
1212         if (ni != NULL)
1213                 ieee80211_free_node(ni);
1214         return error;
1215 }
1216
1217 static int
1218 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1219 {
1220         struct ieee80211req_del_key dk;
1221         int kid, error;
1222
1223         if (ireq->i_len != sizeof(dk))
1224                 return EINVAL;
1225         error = copyin(ireq->i_data, &dk, sizeof(dk));
1226         if (error)
1227                 return error;
1228         kid = dk.idk_keyix;
1229         /* XXX uint8_t -> uint16_t */
1230         if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1231                 struct ieee80211_node *ni;
1232
1233                 if (ic->ic_opmode == IEEE80211_M_STA) {
1234                         ni = ieee80211_ref_node(ic->ic_bss);
1235                         if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1236                                 ieee80211_free_node(ni);
1237                                 return EADDRNOTAVAIL;
1238                         }
1239                 } else {
1240                         ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr);
1241                         if (ni == NULL)
1242                                 return ENOENT;
1243                 }
1244                 /* XXX error return */
1245                 ieee80211_node_delucastkey(ni);
1246                 ieee80211_free_node(ni);
1247         } else {
1248                 if (kid >= IEEE80211_WEP_NKID)
1249                         return EINVAL;
1250                 /* XXX error return */
1251                 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]);
1252         }
1253         return 0;
1254 }
1255
1256 static void
1257 domlme(void *arg, struct ieee80211_node *ni)
1258 {
1259         struct ieee80211com *ic = ni->ni_ic;
1260         struct ieee80211req_mlme *mlme = arg;
1261
1262         if (ni->ni_associd != 0) {
1263                 IEEE80211_SEND_MGMT(ic, ni,
1264                         mlme->im_op == IEEE80211_MLME_DEAUTH ?
1265                                 IEEE80211_FC0_SUBTYPE_DEAUTH :
1266                                 IEEE80211_FC0_SUBTYPE_DISASSOC,
1267                         mlme->im_reason);
1268         }
1269         ieee80211_node_leave(ic, ni);
1270 }
1271
1272 struct scanlookup {
1273         const uint8_t *mac;
1274         int esslen;
1275         const uint8_t *essid;
1276         const struct ieee80211_scan_entry *se;
1277 };
1278
1279 /*
1280  * Match mac address and any ssid.
1281  */
1282 static void
1283 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1284 {
1285         struct scanlookup *look = arg;
1286
1287         if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1288                 return;
1289         if (look->esslen != 0) {
1290                 if (se->se_ssid[1] != look->esslen)
1291                         return;
1292                 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1293                         return;
1294         }
1295         look->se = se;
1296 }
1297
1298 static int
1299 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
1300 {
1301         struct ieee80211req_mlme mlme;
1302         struct ieee80211_node *ni;
1303         int error;
1304
1305         if (ireq->i_len != sizeof(mlme))
1306                 return EINVAL;
1307         error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1308         if (error)
1309                 return error;
1310         switch (mlme.im_op) {
1311         case IEEE80211_MLME_ASSOC:
1312                 /* XXX ibss/ahdemo */
1313                 if (ic->ic_opmode == IEEE80211_M_STA) {
1314                         struct scanlookup lookup;
1315
1316                         lookup.se = NULL;
1317                         lookup.mac = mlme.im_macaddr;
1318                         /* XXX use revised api w/ explicit ssid */
1319                         lookup.esslen = ic->ic_des_ssid[0].len;
1320                         lookup.essid = ic->ic_des_ssid[0].ssid;
1321                         ieee80211_scan_iterate(ic, mlmelookup, &lookup);
1322                         if (lookup.se != NULL &&
1323                             ieee80211_sta_join(ic, lookup.se))
1324                                 return 0;
1325                 }
1326                 return EINVAL;
1327         case IEEE80211_MLME_DISASSOC:
1328         case IEEE80211_MLME_DEAUTH:
1329                 switch (ic->ic_opmode) {
1330                 case IEEE80211_M_STA:
1331                         /* XXX not quite right */
1332                         ieee80211_new_state(ic, IEEE80211_S_INIT,
1333                                 mlme.im_reason);
1334                         break;
1335                 case IEEE80211_M_HOSTAP:
1336                         /* NB: the broadcast address means do 'em all */
1337                         if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) {
1338                                 if ((ni = ieee80211_find_node(&ic->ic_sta,
1339                                                 mlme.im_macaddr)) == NULL)
1340                                         return EINVAL;
1341                                 domlme(&mlme, ni);
1342                                 ieee80211_free_node(ni);
1343                         } else {
1344                                 ieee80211_iterate_nodes(&ic->ic_sta,
1345                                                 domlme, &mlme);
1346                         }
1347                         break;
1348                 default:
1349                         return EINVAL;
1350                 }
1351                 break;
1352         case IEEE80211_MLME_AUTHORIZE:
1353         case IEEE80211_MLME_UNAUTHORIZE:
1354                 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1355                         return EINVAL;
1356                 ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr);
1357                 if (ni == NULL)
1358                         return EINVAL;
1359                 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE)
1360                         ieee80211_node_authorize(ni);
1361                 else
1362                         ieee80211_node_unauthorize(ni);
1363                 ieee80211_free_node(ni);
1364                 break;
1365         default:
1366                 return EINVAL;
1367         }
1368         return 0;
1369 }
1370
1371 static int
1372 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
1373 {
1374         uint8_t mac[IEEE80211_ADDR_LEN];
1375         const struct ieee80211_aclator *acl = ic->ic_acl;
1376         int error;
1377
1378         if (ireq->i_len != sizeof(mac))
1379                 return EINVAL;
1380         error = copyin(ireq->i_data, mac, ireq->i_len);
1381         if (error)
1382                 return error;
1383         if (acl == NULL) {
1384                 acl = ieee80211_aclator_get("mac");
1385                 if (acl == NULL || !acl->iac_attach(ic))
1386                         return EINVAL;
1387                 ic->ic_acl = acl;
1388         }
1389         if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1390                 acl->iac_add(ic, mac);
1391         else
1392                 acl->iac_remove(ic, mac);
1393         return 0;
1394 }
1395
1396 static int
1397 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
1398 {
1399         const struct ieee80211_aclator *acl = ic->ic_acl;
1400
1401         switch (ireq->i_val) {
1402         case IEEE80211_MACCMD_POLICY_OPEN:
1403         case IEEE80211_MACCMD_POLICY_ALLOW:
1404         case IEEE80211_MACCMD_POLICY_DENY:
1405                 if (acl == NULL) {
1406                         acl = ieee80211_aclator_get("mac");
1407                         if (acl == NULL || !acl->iac_attach(ic))
1408                                 return EINVAL;
1409                         ic->ic_acl = acl;
1410                 }
1411                 acl->iac_setpolicy(ic, ireq->i_val);
1412                 break;
1413         case IEEE80211_MACCMD_FLUSH:
1414                 if (acl != NULL)
1415                         acl->iac_flush(ic);
1416                 /* NB: silently ignore when not in use */
1417                 break;
1418         case IEEE80211_MACCMD_DETACH:
1419                 if (acl != NULL) {
1420                         ic->ic_acl = NULL;
1421                         acl->iac_detach(ic);
1422                 }
1423                 break;
1424         default:
1425                 if (acl == NULL)
1426                         return EINVAL;
1427                 else
1428                         return acl->iac_setioctl(ic, ireq);
1429         }
1430         return 0;
1431 }
1432
1433 static int
1434 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
1435 {
1436         struct ieee80211req_chanlist list;
1437         u_char chanlist[IEEE80211_CHAN_BYTES];
1438         int i, j, nchan, error;
1439
1440         if (ireq->i_len != sizeof(list))
1441                 return EINVAL;
1442         error = copyin(ireq->i_data, &list, sizeof(list));
1443         if (error)
1444                 return error;
1445         memset(chanlist, 0, sizeof(chanlist));
1446         /*
1447          * Since channel 0 is not available for DS, channel 1
1448          * is assigned to LSB on WaveLAN.
1449          */
1450         if (ic->ic_phytype == IEEE80211_T_DS)
1451                 i = 1;
1452         else
1453                 i = 0;
1454         nchan = 0;
1455         for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
1456                 /*
1457                  * NB: silently discard unavailable channels so users
1458                  *     can specify 1-255 to get all available channels.
1459                  */
1460                 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
1461                         setbit(chanlist, i);
1462                         nchan++;
1463                 }
1464         }
1465         if (nchan == 0)
1466                 return EINVAL;
1467         if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&    /* XXX */
1468             isclr(chanlist, ic->ic_bsschan->ic_ieee))
1469                 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1470         memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
1471         return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0;
1472 }
1473
1474 static int
1475 ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
1476 {
1477         struct ieee80211_node *ni;
1478         uint8_t macaddr[IEEE80211_ADDR_LEN];
1479         int error;
1480
1481         /*
1482          * NB: we could copyin ieee80211req_sta_stats so apps
1483          *     could make selective changes but that's overkill;
1484          *     just clear all stats for now.
1485          */
1486         if (ireq->i_len < IEEE80211_ADDR_LEN)
1487                 return EINVAL;
1488         error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1489         if (error != 0)
1490                 return error;
1491         ni = ieee80211_find_node(&ic->ic_sta, macaddr);
1492         if (ni == NULL)
1493                 return EINVAL;          /* XXX */
1494         memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1495         ieee80211_free_node(ni);
1496         return 0;
1497 }
1498
1499 static int
1500 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
1501 {
1502         struct ieee80211_node *ni;
1503         struct ieee80211req_sta_txpow txpow;
1504         int error;
1505
1506         if (ireq->i_len != sizeof(txpow))
1507                 return EINVAL;
1508         error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1509         if (error != 0)
1510                 return error;
1511         ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
1512         if (ni == NULL)
1513                 return EINVAL;          /* XXX */
1514         ni->ni_txpower = txpow.it_txpow;
1515         ieee80211_free_node(ni);
1516         return error;
1517 }
1518
1519 static int
1520 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
1521 {
1522         struct ieee80211_wme_state *wme = &ic->ic_wme;
1523         struct wmeParams *wmep, *chanp;
1524         int isbss, ac;
1525
1526         if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1527                 return EINVAL;
1528
1529         isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1530         ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1531         if (ac >= WME_NUM_AC)
1532                 ac = WME_AC_BE;
1533         if (isbss) {
1534                 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1535                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1536         } else {
1537                 chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1538                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1539         }
1540         switch (ireq->i_type) {
1541         case IEEE80211_IOC_WME_CWMIN:           /* WME: CWmin */
1542                 if (isbss) {
1543                         wmep->wmep_logcwmin = ireq->i_val;
1544                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1545                                 chanp->wmep_logcwmin = ireq->i_val;
1546                 } else {
1547                         wmep->wmep_logcwmin = chanp->wmep_logcwmin =
1548                                 ireq->i_val;
1549                 }
1550                 break;
1551         case IEEE80211_IOC_WME_CWMAX:           /* WME: CWmax */
1552                 if (isbss) {
1553                         wmep->wmep_logcwmax = ireq->i_val;
1554                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1555                                 chanp->wmep_logcwmax = ireq->i_val;
1556                 } else {
1557                         wmep->wmep_logcwmax = chanp->wmep_logcwmax =
1558                                 ireq->i_val;
1559                 }
1560                 break;
1561         case IEEE80211_IOC_WME_AIFS:            /* WME: AIFS */
1562                 if (isbss) {
1563                         wmep->wmep_aifsn = ireq->i_val;
1564                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1565                                 chanp->wmep_aifsn = ireq->i_val;
1566                 } else {
1567                         wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
1568                 }
1569                 break;
1570         case IEEE80211_IOC_WME_TXOPLIMIT:       /* WME: txops limit */
1571                 if (isbss) {
1572                         wmep->wmep_txopLimit = ireq->i_val;
1573                         if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1574                                 chanp->wmep_txopLimit = ireq->i_val;
1575                 } else {
1576                         wmep->wmep_txopLimit = chanp->wmep_txopLimit =
1577                                 ireq->i_val;
1578                 }
1579                 break;
1580         case IEEE80211_IOC_WME_ACM:             /* WME: ACM (bss only) */
1581                 wmep->wmep_acm = ireq->i_val;
1582                 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1583                         chanp->wmep_acm = ireq->i_val;
1584                 break;
1585         case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (!bss only)*/
1586                 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
1587                         (ireq->i_val) == 0;
1588                 break;
1589         }
1590         ieee80211_wme_updateparams(ic);
1591         return 0;
1592 }
1593
1594 static int
1595 cipher2cap(int cipher)
1596 {
1597         switch (cipher) {
1598         case IEEE80211_CIPHER_WEP:      return IEEE80211_C_WEP;
1599         case IEEE80211_CIPHER_AES_OCB:  return IEEE80211_C_AES;
1600         case IEEE80211_CIPHER_AES_CCM:  return IEEE80211_C_AES_CCM;
1601         case IEEE80211_CIPHER_CKIP:     return IEEE80211_C_CKIP;
1602         case IEEE80211_CIPHER_TKIP:     return IEEE80211_C_TKIP;
1603         }
1604         return 0;
1605 }
1606
1607 static int
1608 find11gchannel(struct ieee80211com *ic, int start, int freq)
1609 {
1610         const struct ieee80211_channel *c;
1611         int i;
1612
1613         for (i = start+1; i < ic->ic_nchans; i++) {
1614                 c = &ic->ic_channels[i];
1615                 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1616                         return 1;
1617         }
1618         /* NB: should not be needed but in case things are mis-sorted */
1619         for (i = 0; i < start; i++) {
1620                 c = &ic->ic_channels[i];
1621                 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1622                         return 1;
1623         }
1624         return 0;
1625 }
1626
1627 static struct ieee80211_channel *
1628 findchannel(struct ieee80211com *ic, int ieee, int mode)
1629 {
1630         static const u_int chanflags[IEEE80211_MODE_MAX] = {
1631                 0,                      /* IEEE80211_MODE_AUTO */
1632                 IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
1633                 IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
1634                 IEEE80211_CHAN_G,       /* IEEE80211_MODE_11G */
1635                 IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */
1636                 IEEE80211_CHAN_108A,    /* IEEE80211_MODE_TURBO_A */
1637                 IEEE80211_CHAN_108G,    /* IEEE80211_MODE_TURBO_G */
1638                 IEEE80211_CHAN_STURBO,  /* IEEE80211_MODE_STURBO_A */
1639                 /* NB: handled specially below */
1640                 IEEE80211_CHAN_A,       /* IEEE80211_MODE_11NA */
1641                 IEEE80211_CHAN_G,       /* IEEE80211_MODE_11NG */
1642         };
1643         u_int modeflags;
1644         int i;
1645
1646         KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode));
1647         modeflags = chanflags[mode];
1648         KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO,
1649             ("no chanflags for mode %u", mode));
1650         for (i = 0; i < ic->ic_nchans; i++) {
1651                 struct ieee80211_channel *c = &ic->ic_channels[i];
1652
1653                 if (c->ic_ieee != ieee)
1654                         continue;
1655                 if (mode == IEEE80211_MODE_AUTO) {
1656                         /* ignore turbo channels for autoselect */
1657                         if (IEEE80211_IS_CHAN_TURBO(c))
1658                                 continue;
1659                         /*
1660                          * XXX special-case 11b/g channels so we
1661                          *     always select the g channel if both
1662                          *     are present.
1663                          * XXX prefer HT to non-HT?
1664                          */
1665                         if (!IEEE80211_IS_CHAN_B(c) ||
1666                             !find11gchannel(ic, i, c->ic_freq))
1667                                 return c;
1668                 } else {
1669                         /* must check HT specially */
1670                         if ((mode == IEEE80211_MODE_11NA ||
1671                             mode == IEEE80211_MODE_11NG) &&
1672                             !IEEE80211_IS_CHAN_HT(c))
1673                                 continue;
1674                         if ((c->ic_flags & modeflags) == modeflags)
1675                                 return c;
1676                 }
1677         }
1678         return NULL;
1679 }
1680
1681 /*
1682  * Check the specified against any desired mode (aka netband).
1683  * This is only used (presently) when operating in hostap mode
1684  * to enforce consistency.
1685  */
1686 static int
1687 check_mode_consistency(const struct ieee80211_channel *c, int mode)
1688 {
1689         KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1690
1691         switch (mode) {
1692         case IEEE80211_MODE_11B:
1693                 return (IEEE80211_IS_CHAN_B(c));
1694         case IEEE80211_MODE_11G:
1695                 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1696         case IEEE80211_MODE_11A:
1697                 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1698         case IEEE80211_MODE_STURBO_A:
1699                 return (IEEE80211_IS_CHAN_STURBO(c));
1700         case IEEE80211_MODE_11NA:
1701                 return (IEEE80211_IS_CHAN_HTA(c));
1702         case IEEE80211_MODE_11NG:
1703                 return (IEEE80211_IS_CHAN_HTG(c));
1704         }
1705         return 1;
1706
1707 }
1708
1709 /*
1710  * Common code to set the current channel.  If the device
1711  * is up and running this may result in an immediate channel
1712  * change or a kick of the state machine.
1713  */
1714 static int
1715 setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
1716 {
1717         int error;
1718
1719         if (c != IEEE80211_CHAN_ANYC) {
1720                 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1721                     !check_mode_consistency(c, ic->ic_des_mode))
1722                         return EINVAL;
1723                 if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan)
1724                         return 0;       /* NB: nothing to do */
1725         }
1726         ic->ic_des_chan = c;
1727
1728         error = 0;
1729         if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
1730             ic->ic_opmode == IEEE80211_M_WDS) &&
1731             ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1732                 /*
1733                  * Monitor and wds modes can switch directly.
1734                  */
1735                 ic->ic_curchan = ic->ic_des_chan;
1736                 if (ic->ic_state == IEEE80211_S_RUN)
1737                         ic->ic_set_channel(ic);
1738         } else {
1739                 /*
1740                  * Need to go through the state machine in case we
1741                  * need to reassociate or the like.  The state machine
1742                  * will pickup the desired channel and avoid scanning.
1743                  */
1744                 if (IS_UP_AUTO(ic))
1745                         error = ieee80211_init(ic, RESCAN);
1746                 else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1747                         /*
1748                          * When not up+running and a real channel has
1749                          * been specified fix the current channel so
1750                          * there is immediate feedback; e.g. via ifconfig.
1751                          */
1752                         ic->ic_curchan = ic->ic_des_chan;
1753                 }
1754         }
1755         return error;
1756 }
1757
1758 /*
1759  * Old api for setting the current channel; this is
1760  * deprecated because channel numbers are ambiguous.
1761  */
1762 static int
1763 ieee80211_ioctl_setchannel(struct ieee80211com *ic,
1764         const struct ieee80211req *ireq)
1765 {
1766         struct ieee80211_channel *c;
1767
1768         /* XXX 0xffff overflows 16-bit signed */
1769         if (ireq->i_val == 0 ||
1770             ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1771                 c = IEEE80211_CHAN_ANYC;
1772         } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
1773                 return EINVAL;
1774         } else {
1775                 struct ieee80211_channel *c2;
1776
1777                 c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
1778                 if (c == NULL) {
1779                         c = findchannel(ic, ireq->i_val,
1780                                 IEEE80211_MODE_AUTO);
1781                         if (c == NULL)
1782                                 return EINVAL;
1783                 }
1784                 /*
1785                  * Fine tune channel selection based on desired mode:
1786                  *   if 11b is requested, find the 11b version of any
1787                  *      11g channel returned,
1788                  *   if static turbo, find the turbo version of any
1789                  *      11a channel return,
1790                  *   if 11na is requested, find the ht version of any
1791                  *      11a channel returned,
1792                  *   if 11ng is requested, find the ht version of any
1793                  *      11g channel returned,
1794                  *   otherwise we should be ok with what we've got.
1795                  */
1796                 switch (ic->ic_des_mode) {
1797                 case IEEE80211_MODE_11B:
1798                         if (IEEE80211_IS_CHAN_ANYG(c)) {
1799                                 c2 = findchannel(ic, ireq->i_val,
1800                                         IEEE80211_MODE_11B);
1801                                 /* NB: should not happen, =>'s 11g w/o 11b */
1802                                 if (c2 != NULL)
1803                                         c = c2;
1804                         }
1805                         break;
1806                 case IEEE80211_MODE_TURBO_A:
1807                         if (IEEE80211_IS_CHAN_A(c)) {
1808                                 c2 = findchannel(ic, ireq->i_val,
1809                                         IEEE80211_MODE_TURBO_A);
1810                                 if (c2 != NULL)
1811                                         c = c2;
1812                         }
1813                         break;
1814                 case IEEE80211_MODE_11NA:
1815                         if (IEEE80211_IS_CHAN_A(c)) {
1816                                 c2 = findchannel(ic, ireq->i_val,
1817                                         IEEE80211_MODE_11NA);
1818                                 if (c2 != NULL)
1819                                         c = c2;
1820                         }
1821                         break;
1822                 case IEEE80211_MODE_11NG:
1823                         if (IEEE80211_IS_CHAN_ANYG(c)) {
1824                                 c2 = findchannel(ic, ireq->i_val,
1825                                         IEEE80211_MODE_11NG);
1826                                 if (c2 != NULL)
1827                                         c = c2;
1828                         }
1829                         break;
1830                 default:                /* NB: no static turboG */
1831                         break;
1832                 }
1833         }
1834         return setcurchan(ic, c);
1835 }
1836
1837 /*
1838  * New/current api for setting the current channel; a complete
1839  * channel description is provide so there is no ambiguity in
1840  * identifying the channel.
1841  */
1842 static int
1843 ieee80211_ioctl_setcurchan(struct ieee80211com *ic,
1844         const struct ieee80211req *ireq)
1845 {
1846         struct ieee80211_channel chan, *c;
1847         int error;
1848
1849         if (ireq->i_len != sizeof(chan))
1850                 return EINVAL;
1851         error = copyin(ireq->i_data, &chan, sizeof(chan));
1852         if (error != 0)
1853                 return error;
1854         /* XXX 0xffff overflows 16-bit signed */
1855         if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
1856                 c = IEEE80211_CHAN_ANYC;
1857         } else {
1858                 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
1859                 if (c == NULL)
1860                         return EINVAL;
1861         }
1862         return setcurchan(ic, c);
1863 }
1864
1865 static int
1866 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
1867 {
1868         static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
1869         struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
1870         int error;
1871         const struct ieee80211_authenticator *auth;
1872         uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
1873         char tmpssid[IEEE80211_NWID_LEN];
1874         uint8_t tmpbssid[IEEE80211_ADDR_LEN];
1875         struct ieee80211_key *k;
1876         int j, caps;
1877         u_int kid;
1878
1879         error = 0;
1880         switch (ireq->i_type) {
1881         case IEEE80211_IOC_SSID:
1882                 if (ireq->i_val != 0 ||
1883                     ireq->i_len > IEEE80211_NWID_LEN)
1884                         return EINVAL;
1885                 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
1886                 if (error)
1887                         break;
1888                 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
1889                 ic->ic_des_ssid[0].len = ireq->i_len;
1890                 memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len);
1891                 ic->ic_des_nssid = (ireq->i_len > 0);
1892                 if (IS_UP_AUTO(ic))
1893                         error = ieee80211_init(ic, RESCAN);
1894                 break;
1895         case IEEE80211_IOC_WEP:
1896                 switch (ireq->i_val) {
1897                 case IEEE80211_WEP_OFF:
1898                         ic->ic_flags &= ~IEEE80211_F_PRIVACY;
1899                         ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1900                         break;
1901                 case IEEE80211_WEP_ON:
1902                         ic->ic_flags |= IEEE80211_F_PRIVACY;
1903                         ic->ic_flags |= IEEE80211_F_DROPUNENC;
1904                         break;
1905                 case IEEE80211_WEP_MIXED:
1906                         ic->ic_flags |= IEEE80211_F_PRIVACY;
1907                         ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1908                         break;
1909                 }
1910                 if (IS_UP_AUTO(ic))
1911                         error = ieee80211_init(ic, RESCAN);
1912                 break;
1913         case IEEE80211_IOC_WEPKEY:
1914                 kid = (u_int) ireq->i_val;
1915                 if (kid >= IEEE80211_WEP_NKID)
1916                         return EINVAL;
1917                 k = &ic->ic_nw_keys[kid];
1918                 if (ireq->i_len == 0) {
1919                         /* zero-len =>'s delete any existing key */
1920                         (void) ieee80211_crypto_delkey(ic, k);
1921                         break;
1922                 }
1923                 if (ireq->i_len > sizeof(tmpkey))
1924                         return EINVAL;
1925                 memset(tmpkey, 0, sizeof(tmpkey));
1926                 error = copyin(ireq->i_data, tmpkey, ireq->i_len);
1927                 if (error)
1928                         break;
1929                 ieee80211_key_update_begin(ic);
1930                 k->wk_keyix = kid;      /* NB: force fixed key id */
1931                 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP,
1932                     IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
1933                         k->wk_keylen = ireq->i_len;
1934                         memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
1935                         if  (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
1936                                 error = EINVAL;
1937                 } else
1938                         error = EINVAL;
1939                 ieee80211_key_update_end(ic);
1940                 break;
1941         case IEEE80211_IOC_WEPTXKEY:
1942                 kid = (u_int) ireq->i_val;
1943                 if (kid >= IEEE80211_WEP_NKID &&
1944                     (uint16_t) kid != IEEE80211_KEYIX_NONE)
1945                         return EINVAL;
1946                 ic->ic_def_txkey = kid;
1947                 break;
1948         case IEEE80211_IOC_AUTHMODE:
1949                 switch (ireq->i_val) {
1950                 case IEEE80211_AUTH_WPA:
1951                 case IEEE80211_AUTH_8021X:      /* 802.1x */
1952                 case IEEE80211_AUTH_OPEN:       /* open */
1953                 case IEEE80211_AUTH_SHARED:     /* shared-key */
1954                 case IEEE80211_AUTH_AUTO:       /* auto */
1955                         auth = ieee80211_authenticator_get(ireq->i_val);
1956                         if (auth == NULL)
1957                                 return EINVAL;
1958                         break;
1959                 default:
1960                         return EINVAL;
1961                 }
1962                 switch (ireq->i_val) {
1963                 case IEEE80211_AUTH_WPA:        /* WPA w/ 802.1x */
1964                         ic->ic_flags |= IEEE80211_F_PRIVACY;
1965                         ireq->i_val = IEEE80211_AUTH_8021X;
1966                         break;
1967                 case IEEE80211_AUTH_OPEN:       /* open */
1968                         ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
1969                         break;
1970                 case IEEE80211_AUTH_SHARED:     /* shared-key */
1971                 case IEEE80211_AUTH_8021X:      /* 802.1x */
1972                         ic->ic_flags &= ~IEEE80211_F_WPA;
1973                         /* both require a key so mark the PRIVACY capability */
1974                         ic->ic_flags |= IEEE80211_F_PRIVACY;
1975                         break;
1976                 case IEEE80211_AUTH_AUTO:       /* auto */
1977                         ic->ic_flags &= ~IEEE80211_F_WPA;
1978                         /* XXX PRIVACY handling? */
1979                         /* XXX what's the right way to do this? */
1980                         break;
1981                 }
1982                 /* NB: authenticator attach/detach happens on state change */
1983                 ic->ic_bss->ni_authmode = ireq->i_val;
1984                 /* XXX mixed/mode/usage? */
1985                 ic->ic_auth = auth;
1986                 if (IS_UP_AUTO(ic))
1987                         error = ieee80211_init(ic, RESCAN);
1988                 break;
1989         case IEEE80211_IOC_CHANNEL:
1990                 error = ieee80211_ioctl_setchannel(ic, ireq);
1991                 break;
1992         case IEEE80211_IOC_POWERSAVE:
1993                 switch (ireq->i_val) {
1994                 case IEEE80211_POWERSAVE_OFF:
1995                         if (ic->ic_flags & IEEE80211_F_PMGTON) {
1996                                 ic->ic_flags &= ~IEEE80211_F_PMGTON;
1997                                 error = ENETRESET;
1998                         }
1999                         break;
2000                 case IEEE80211_POWERSAVE_ON:
2001                         if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
2002                                 error = EINVAL;
2003                         else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
2004                                 ic->ic_flags |= IEEE80211_F_PMGTON;
2005                                 error = ENETRESET;
2006                         }
2007                         break;
2008                 default:
2009                         error = EINVAL;
2010                         break;
2011                 }
2012                 if (error == ENETRESET) {
2013                         /*
2014                          * Switching in+out of power save mode
2015                          * should not require a state change.
2016                          */
2017                         error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2018                 }
2019                 break;
2020         case IEEE80211_IOC_POWERSAVESLEEP:
2021                 if (ireq->i_val < 0)
2022                         return EINVAL;
2023                 ic->ic_lintval = ireq->i_val;
2024                 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2025                 break;
2026         case IEEE80211_IOC_RTSTHRESHOLD:
2027                 if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
2028                       ireq->i_val <= IEEE80211_RTS_MAX))
2029                         return EINVAL;
2030                 ic->ic_rtsthreshold = ireq->i_val;
2031                 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2032                 break;
2033         case IEEE80211_IOC_PROTMODE:
2034                 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2035                         return EINVAL;
2036                 ic->ic_protmode = ireq->i_val;
2037                 /* NB: if not operating in 11g this can wait */
2038                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2039                     IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2040                         error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2041                 break;
2042         case IEEE80211_IOC_TXPOWER:
2043                 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2044                         return EINVAL;
2045                 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2046                       ireq->i_val <= IEEE80211_TXPOWER_MAX))
2047                         return EINVAL;
2048                 ic->ic_txpowlimit = ireq->i_val;
2049                 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2050                 break;
2051         case IEEE80211_IOC_ROAMING:
2052                 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2053                     ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2054                         return EINVAL;
2055                 ic->ic_roaming = ireq->i_val;
2056                 /* XXXX reset? */
2057                 break;
2058         case IEEE80211_IOC_PRIVACY:
2059                 if (ireq->i_val) {
2060                         /* XXX check for key state? */
2061                         ic->ic_flags |= IEEE80211_F_PRIVACY;
2062                 } else
2063                         ic->ic_flags &= ~IEEE80211_F_PRIVACY;
2064                 break;
2065         case IEEE80211_IOC_DROPUNENCRYPTED:
2066                 if (ireq->i_val)
2067                         ic->ic_flags |= IEEE80211_F_DROPUNENC;
2068                 else
2069                         ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2070                 break;
2071         case IEEE80211_IOC_WPAKEY:
2072                 error = ieee80211_ioctl_setkey(ic, ireq);
2073                 break;
2074         case IEEE80211_IOC_DELKEY:
2075                 error = ieee80211_ioctl_delkey(ic, ireq);
2076                 break;
2077         case IEEE80211_IOC_MLME:
2078                 error = ieee80211_ioctl_setmlme(ic, ireq);
2079                 break;
2080         case IEEE80211_IOC_OPTIE:
2081                 error = ieee80211_ioctl_setoptie(ic, ireq);
2082                 break;
2083         case IEEE80211_IOC_COUNTERMEASURES:
2084                 if (ireq->i_val) {
2085                         if ((ic->ic_flags & IEEE80211_F_WPA) == 0)
2086                                 return EINVAL;
2087                         ic->ic_flags |= IEEE80211_F_COUNTERM;
2088                 } else
2089                         ic->ic_flags &= ~IEEE80211_F_COUNTERM;
2090                 break;
2091         case IEEE80211_IOC_WPA:
2092                 if (ireq->i_val > 3)
2093                         return EINVAL;
2094                 /* XXX verify ciphers available */
2095                 ic->ic_flags &= ~IEEE80211_F_WPA;
2096                 switch (ireq->i_val) {
2097                 case 1:
2098                         ic->ic_flags |= IEEE80211_F_WPA1;
2099                         break;
2100                 case 2:
2101                         ic->ic_flags |= IEEE80211_F_WPA2;
2102                         break;
2103                 case 3:
2104                         ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2105                         break;
2106                 }
2107                 error = ENETRESET;
2108                 break;
2109         case IEEE80211_IOC_WME:
2110                 if (ireq->i_val) {
2111                         if ((ic->ic_caps & IEEE80211_C_WME) == 0)
2112                                 return EINVAL;
2113                         ic->ic_flags |= IEEE80211_F_WME;
2114                 } else
2115                         ic->ic_flags &= ~IEEE80211_F_WME;
2116                 if (IS_UP_AUTO(ic))
2117                         error = ieee80211_init(ic, 0);
2118                 break;
2119         case IEEE80211_IOC_HIDESSID:
2120                 if (ireq->i_val)
2121                         ic->ic_flags |= IEEE80211_F_HIDESSID;
2122                 else
2123                         ic->ic_flags &= ~IEEE80211_F_HIDESSID;
2124                 error = ENETRESET;
2125                 break;
2126         case IEEE80211_IOC_APBRIDGE:
2127                 if (ireq->i_val == 0)
2128                         ic->ic_flags |= IEEE80211_F_NOBRIDGE;
2129                 else
2130                         ic->ic_flags &= ~IEEE80211_F_NOBRIDGE;
2131                 break;
2132         case IEEE80211_IOC_MCASTCIPHER:
2133                 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 &&
2134                     !ieee80211_crypto_available(ireq->i_val))
2135                         return EINVAL;
2136                 rsn->rsn_mcastcipher = ireq->i_val;
2137                 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2138                 break;
2139         case IEEE80211_IOC_MCASTKEYLEN:
2140                 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2141                         return EINVAL;
2142                 /* XXX no way to verify driver capability */
2143                 rsn->rsn_mcastkeylen = ireq->i_val;
2144                 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2145                 break;
2146         case IEEE80211_IOC_UCASTCIPHERS:
2147                 /*
2148                  * Convert user-specified cipher set to the set
2149                  * we can support (via hardware or software).
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 = 0;
2155                 for (j = 1; j < 32; j++)        /* NB: skip WEP */
2156                         if ((ireq->i_val & (1<<j)) &&
2157                             ((ic->ic_caps & cipher2cap(j)) ||
2158                              ieee80211_crypto_available(j)))
2159                                 caps |= 1<<j;
2160                 if (caps == 0)                  /* nothing available */
2161                         return EINVAL;
2162                 /* XXX verify ciphers ok for unicast use? */
2163                 /* XXX disallow if running as it'll have no effect */
2164                 rsn->rsn_ucastcipherset = caps;
2165                 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2166                 break;
2167         case IEEE80211_IOC_UCASTCIPHER:
2168                 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0)
2169                         return EINVAL;
2170                 rsn->rsn_ucastcipher = ireq->i_val;
2171                 break;
2172         case IEEE80211_IOC_UCASTKEYLEN:
2173                 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2174                         return EINVAL;
2175                 /* XXX no way to verify driver capability */
2176                 rsn->rsn_ucastkeylen = ireq->i_val;
2177                 break;
2178         case IEEE80211_IOC_DRIVER_CAPS:
2179                 /* NB: for testing */
2180                 ic->ic_caps = (((uint16_t) ireq->i_val) << 16) |
2181                                ((uint16_t) ireq->i_len);
2182                 break;
2183         case IEEE80211_IOC_KEYMGTALGS:
2184                 /* XXX check */
2185                 rsn->rsn_keymgmtset = ireq->i_val;
2186                 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2187                 break;
2188         case IEEE80211_IOC_RSNCAPS:
2189                 /* XXX check */
2190                 rsn->rsn_caps = ireq->i_val;
2191                 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2192                 break;
2193         case IEEE80211_IOC_BSSID:
2194                 if (ireq->i_len != sizeof(tmpbssid))
2195                         return EINVAL;
2196                 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2197                 if (error)
2198                         break;
2199                 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid);
2200                 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid))
2201                         ic->ic_flags &= ~IEEE80211_F_DESBSSID;
2202                 else
2203                         ic->ic_flags |= IEEE80211_F_DESBSSID;
2204                 if (IS_UP_AUTO(ic))
2205                         error = ieee80211_init(ic, RESCAN);
2206                 break;
2207         case IEEE80211_IOC_CHANLIST:
2208                 error = ieee80211_ioctl_setchanlist(ic, ireq);
2209                 break;
2210         case IEEE80211_IOC_SCAN_REQ:
2211                 if (!IS_UP(ic))
2212                         return EINVAL;
2213                 (void) ieee80211_start_scan(ic,
2214                         IEEE80211_SCAN_ACTIVE |
2215                         IEEE80211_SCAN_NOPICK |
2216                         IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
2217                         /* XXX use ioctl params */
2218                         ic->ic_des_nssid, ic->ic_des_ssid);
2219                 break;
2220         case IEEE80211_IOC_ADDMAC:
2221         case IEEE80211_IOC_DELMAC:
2222                 error = ieee80211_ioctl_macmac(ic, ireq);
2223                 break;
2224         case IEEE80211_IOC_MACCMD:
2225                 error = ieee80211_ioctl_setmaccmd(ic, ireq);
2226                 break;
2227         case IEEE80211_IOC_STA_STATS:
2228                 error = ieee80211_ioctl_setstastats(ic, ireq);
2229                 break;
2230         case IEEE80211_IOC_STA_TXPOW:
2231                 error = ieee80211_ioctl_setstatxpow(ic, ireq);
2232                 break;
2233         case IEEE80211_IOC_WME_CWMIN:           /* WME: CWmin */
2234         case IEEE80211_IOC_WME_CWMAX:           /* WME: CWmax */
2235         case IEEE80211_IOC_WME_AIFS:            /* WME: AIFS */
2236         case IEEE80211_IOC_WME_TXOPLIMIT:       /* WME: txops limit */
2237         case IEEE80211_IOC_WME_ACM:             /* WME: ACM (bss only) */
2238         case IEEE80211_IOC_WME_ACKPOLICY:       /* WME: ACK policy (bss only) */
2239                 error = ieee80211_ioctl_setwmeparam(ic, ireq);
2240                 break;
2241         case IEEE80211_IOC_DTIM_PERIOD:
2242                 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2243                     ic->ic_opmode != IEEE80211_M_IBSS)
2244                         return EINVAL;
2245                 if (IEEE80211_DTIM_MIN <= ireq->i_val &&
2246                     ireq->i_val <= IEEE80211_DTIM_MAX) {
2247                         ic->ic_dtim_period = ireq->i_val;
2248                         error = ENETRESET;              /* requires restart */
2249                 } else
2250                         error = EINVAL;
2251                 break;
2252         case IEEE80211_IOC_BEACON_INTERVAL:
2253                 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2254                     ic->ic_opmode != IEEE80211_M_IBSS)
2255                         return EINVAL;
2256                 if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
2257                     ireq->i_val <= IEEE80211_BINTVAL_MAX) {
2258                         ic->ic_bintval = ireq->i_val;
2259                         error = ENETRESET;              /* requires restart */
2260                 } else
2261                         error = EINVAL;
2262                 break;
2263         case IEEE80211_IOC_PUREG:
2264                 if (ireq->i_val)
2265                         ic->ic_flags |= IEEE80211_F_PUREG;
2266                 else
2267                         ic->ic_flags &= ~IEEE80211_F_PUREG;
2268                 /* NB: reset only if we're operating on an 11g channel */
2269                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2270                     IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2271                         error = ENETRESET;
2272                 break;
2273         case IEEE80211_IOC_FF:
2274                 if (ireq->i_val) {
2275                         if ((ic->ic_caps & IEEE80211_C_FF) == 0)
2276                                 return EINVAL;
2277                         ic->ic_flags |= IEEE80211_F_FF;
2278                 } else
2279                         ic->ic_flags &= ~IEEE80211_F_FF;
2280                 error = ENETRESET;
2281                 break;
2282         case IEEE80211_IOC_TURBOP:
2283                 if (ireq->i_val) {
2284                         if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0)
2285                                 return EINVAL;
2286                         ic->ic_flags |= IEEE80211_F_TURBOP;
2287                 } else
2288                         ic->ic_flags &= ~IEEE80211_F_TURBOP;
2289                 error = ENETRESET;
2290                 break;
2291         case IEEE80211_IOC_BGSCAN:
2292                 if (ireq->i_val) {
2293                         if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0)
2294                                 return EINVAL;
2295                         ic->ic_flags |= IEEE80211_F_BGSCAN;
2296                 } else
2297                         ic->ic_flags &= ~IEEE80211_F_BGSCAN;
2298                 break;
2299         case IEEE80211_IOC_BGSCAN_IDLE:
2300                 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2301                         ic->ic_bgscanidle = ireq->i_val*hz/1000;
2302                 else
2303                         error = EINVAL;
2304                 break;
2305         case IEEE80211_IOC_BGSCAN_INTERVAL:
2306                 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2307                         ic->ic_bgscanintvl = ireq->i_val*hz;
2308                 else
2309                         error = EINVAL;
2310                 break;
2311         case IEEE80211_IOC_SCANVALID:
2312                 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2313                         ic->ic_scanvalid = ireq->i_val*hz;
2314                 else
2315                         error = EINVAL;
2316                 break;
2317         case IEEE80211_IOC_ROAM_RSSI_11A:
2318                 ic->ic_roam.rssi11a = ireq->i_val;
2319                 break;
2320         case IEEE80211_IOC_ROAM_RSSI_11B:
2321                 ic->ic_roam.rssi11bOnly = ireq->i_val;
2322                 break;
2323         case IEEE80211_IOC_ROAM_RSSI_11G:
2324                 ic->ic_roam.rssi11b = ireq->i_val;
2325                 break;
2326         case IEEE80211_IOC_ROAM_RATE_11A:
2327                 ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL;
2328                 break;
2329         case IEEE80211_IOC_ROAM_RATE_11B:
2330                 ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL;
2331                 break;
2332         case IEEE80211_IOC_ROAM_RATE_11G:
2333                 ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL;
2334                 break;
2335         case IEEE80211_IOC_MCAST_RATE:
2336                 ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL;
2337                 break;
2338         case IEEE80211_IOC_FRAGTHRESHOLD:
2339                 if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
2340                     ireq->i_val != IEEE80211_FRAG_MAX)
2341                         return EINVAL;
2342                 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
2343                       ireq->i_val <= IEEE80211_FRAG_MAX))
2344                         return EINVAL;
2345                 ic->ic_fragthreshold = ireq->i_val;
2346                 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2347                 break;
2348         case IEEE80211_IOC_BURST:
2349                 if (ireq->i_val) {
2350                         if ((ic->ic_caps & IEEE80211_C_BURST) == 0)
2351                                 return EINVAL;
2352                         ic->ic_flags |= IEEE80211_F_BURST;
2353                 } else
2354                         ic->ic_flags &= ~IEEE80211_F_BURST;
2355                 error = ENETRESET;              /* XXX maybe not for station? */
2356                 break;
2357         case IEEE80211_IOC_BMISSTHRESHOLD:
2358                 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2359                       ireq->i_val <= IEEE80211_HWBMISS_MAX))
2360                         return EINVAL;
2361                 ic->ic_bmissthreshold = ireq->i_val;
2362                 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2363                 break;
2364         case IEEE80211_IOC_CURCHAN:
2365                 error = ieee80211_ioctl_setcurchan(ic, ireq);
2366                 break;
2367         case IEEE80211_IOC_SHORTGI:
2368                 if (ireq->i_val) {
2369 #define IEEE80211_HTCAP_SHORTGI \
2370         (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2371                         if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2372                                 return EINVAL;
2373                         if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2374                                 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2375                         if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2376                                 ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2377 #undef IEEE80211_HTCAP_SHORTGI
2378                 } else
2379                         ic->ic_flags_ext &=
2380                             ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2381                 /* XXX kick state machine? */
2382                 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2383                 break;
2384         case IEEE80211_IOC_AMPDU:
2385                 if (ireq->i_val) {
2386                         if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0)
2387                                 return EINVAL;
2388                         if (ireq->i_val & 1)
2389                                 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2390                         if (ireq->i_val & 2)
2391                                 ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2392                 } else
2393                         ic->ic_flags_ext &=
2394                             ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX);
2395                 /* NB: reset only if we're operating on an 11n channel */
2396                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2397                     IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2398                         error = ENETRESET;
2399                 break;
2400         case IEEE80211_IOC_AMPDU_LIMIT:
2401                 /* XXX validate */
2402                 ic->ic_ampdu_limit = ireq->i_val;
2403                 break;
2404         case IEEE80211_IOC_AMPDU_DENSITY:
2405                 /* XXX validate */
2406                 ic->ic_ampdu_density = ireq->i_val;
2407                 break;
2408         case IEEE80211_IOC_AMSDU:
2409                 if (ireq->i_val) {
2410                         if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0)
2411                                 return EINVAL;
2412                         if (ireq->i_val & 1)
2413                                 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
2414                         if (ireq->i_val & 2)
2415                                 ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
2416                 } else
2417                         ic->ic_flags_ext &=
2418                             ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX);
2419                 /* NB: reset only if we're operating on an 11n channel */
2420                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2421                     IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2422                         error = ENETRESET;
2423                 break;
2424         case IEEE80211_IOC_AMSDU_LIMIT:
2425                 /* XXX validate */
2426                 ic->ic_amsdu_limit = ireq->i_val;       /* XXX truncation? */
2427                 break;
2428         case IEEE80211_IOC_PUREN:
2429                 if (ireq->i_val) {
2430                         if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2431                                 return EINVAL;
2432                         ic->ic_flags_ext |= IEEE80211_FEXT_PUREN;
2433                 } else
2434                         ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN;
2435                 /* NB: reset only if we're operating on an 11n channel */
2436                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2437                     IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2438                         error = ENETRESET;
2439                 break;
2440         case IEEE80211_IOC_DOTH:
2441                 if (ireq->i_val) {
2442 #if 0
2443                         /* XXX no capability */
2444                         if ((ic->ic_caps & IEEE80211_C_DOTH) == 0)
2445                                 return EINVAL;
2446 #endif
2447                         ic->ic_flags |= IEEE80211_F_DOTH;
2448                 } else
2449                         ic->ic_flags &= ~IEEE80211_F_DOTH;
2450                 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2451                 break;
2452         case IEEE80211_IOC_HTCOMPAT:
2453                 if (ireq->i_val) {
2454                         if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2455                                 return EINVAL;
2456                         ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
2457                 } else
2458                         ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
2459                 /* NB: reset only if we're operating on an 11n channel */
2460                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2461                     IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2462                         error = ENETRESET;
2463                 break;
2464         case IEEE80211_IOC_INACTIVITY:
2465                 if (ireq->i_val)
2466                         ic->ic_flags_ext |= IEEE80211_FEXT_INACT;
2467                 else
2468                         ic->ic_flags_ext &= ~IEEE80211_FEXT_INACT;
2469                 break;
2470         case IEEE80211_IOC_HTPROTMODE:
2471                 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2472                         return EINVAL;
2473                 ic->ic_htprotmode = ireq->i_val ?
2474                     IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE;
2475                 /* NB: if not operating in 11n this can wait */
2476                 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2477                     IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2478                         error = ERESTART;
2479                 break;
2480         case IEEE80211_IOC_HTCONF:
2481                 if (ireq->i_val & 1)
2482                         ic->ic_flags_ext |= IEEE80211_FEXT_HT;
2483                 else
2484                         ic->ic_flags_ext &= ~IEEE80211_FEXT_HT;
2485                 if (ireq->i_val & 2)
2486                         ic->ic_flags_ext |= IEEE80211_FEXT_USEHT40;
2487                 else
2488                         ic->ic_flags_ext &= ~IEEE80211_FEXT_USEHT40;
2489                 error = ENETRESET;
2490                 break;
2491         default:
2492                 error = EINVAL;
2493                 break;
2494         }
2495         if (error == ENETRESET)
2496                 error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0;
2497         return error;
2498 }
2499
2500 int
2501 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data)
2502 {
2503         struct ifnet *ifp = ic->ic_ifp;
2504         int error = 0;
2505         struct ifreq *ifr;
2506         struct ifaddr *ifa;                     /* XXX */
2507
2508         switch (cmd) {
2509         case SIOCSIFMEDIA:
2510         case SIOCGIFMEDIA:
2511                 error = ifmedia_ioctl(ifp, (struct ifreq *) data,
2512                                 &ic->ic_media, cmd);
2513                 break;
2514         case SIOCG80211:
2515                 error = ieee80211_ioctl_get80211(ic, cmd,
2516                                 (struct ieee80211req *) data);
2517                 break;
2518         case SIOCS80211:
2519                 error = priv_check(curthread, PRIV_NET80211_MANAGE);
2520                 if (error == 0)
2521                         error = ieee80211_ioctl_set80211(ic, cmd,
2522                                         (struct ieee80211req *) data);
2523                 break;
2524         case SIOCG80211STATS:
2525                 ifr = (struct ifreq *)data;
2526                 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
2527                 break;
2528         case SIOCSIFMTU:
2529                 ifr = (struct ifreq *)data;
2530                 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
2531                     ifr->ifr_mtu <= IEEE80211_MTU_MAX))
2532                         error = EINVAL;
2533                 else
2534                         ifp->if_mtu = ifr->ifr_mtu;
2535                 break;
2536         case SIOCSIFADDR:
2537                 /*
2538                  * XXX Handle this directly so we can supress if_init calls.
2539                  * XXX This should be done in ether_ioctl but for the moment
2540                  * XXX there are too many other parts of the system that
2541                  * XXX set IFF_UP and so supress if_init being called when
2542                  * XXX it should be.
2543                  */
2544                 ifa = (struct ifaddr *) data;
2545                 switch (ifa->ifa_addr->sa_family) {
2546 #ifdef INET
2547                 case AF_INET:
2548                         if ((ifp->if_flags & IFF_UP) == 0) {
2549                                 ifp->if_flags |= IFF_UP;
2550                                 ifp->if_init(ifp->if_softc);
2551                         }
2552                         arp_ifinit(ifp, ifa);
2553                         break;
2554 #endif
2555 #ifdef IPX
2556                 /*
2557                  * XXX - This code is probably wrong,
2558                  *       but has been copied many times.
2559                  */
2560                 case AF_IPX: {
2561                         struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
2562
2563                         if (ipx_nullhost(*ina))
2564                                 ina->x_host = *(union ipx_host *)
2565                                     IF_LLADDR(ifp);
2566                         else
2567                                 bcopy((caddr_t) ina->x_host.c_host,
2568                                       (caddr_t) IF_LLADDR(ifp),
2569                                       ETHER_ADDR_LEN);
2570                         /* fall thru... */
2571                 }
2572 #endif
2573                 default:
2574                         if ((ifp->if_flags & IFF_UP) == 0) {
2575                                 ifp->if_flags |= IFF_UP;
2576                                 ifp->if_init(ifp->if_softc);
2577                         }
2578                         break;
2579                 }
2580                 break;
2581         default:
2582                 error = ether_ioctl(ifp, cmd, data);
2583                 break;
2584         }
2585         return error;
2586 }