Deleted Added
full compact
ieee80211_ioctl.c (190384) ieee80211_ioctl.c (190391)
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2009 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>
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2009 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: head/sys/net80211/ieee80211_ioctl.c 190384 2009-03-24 17:57:48Z sam $");
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 190391 2009-03-24 20:39:08Z sam $");
29
30/*
31 * IEEE 802.11 ioctl support (FreeBSD-specific)
32 */
33
34#include "opt_inet.h"
35#include "opt_ipx.h"
36#include "opt_wlan.h"
37
38#include <sys/endian.h>
39#include <sys/param.h>
40#include <sys/kernel.h>
41#include <sys/priv.h>
42#include <sys/socket.h>
43#include <sys/sockio.h>
44#include <sys/systm.h>
45#include <sys/taskqueue.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#include <net80211/ieee80211_regdomain.h>
65#include <net80211/ieee80211_input.h>
66
67#define IS_UP_AUTO(_vap) \
68 (IFNET_IS_UP_RUNNING(vap->iv_ifp) && \
69 (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO)
70
71static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
72static struct ieee80211_channel *findchannel(struct ieee80211com *,
73 int ieee, int mode);
74
75static __noinline int
76ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
77{
78 struct ieee80211com *ic = vap->iv_ic;
79 struct ieee80211_node *ni;
80 struct ieee80211req_key ik;
81 struct ieee80211_key *wk;
82 const struct ieee80211_cipher *cip;
83 u_int kid;
84 int error;
85
86 if (ireq->i_len != sizeof(ik))
87 return EINVAL;
88 error = copyin(ireq->i_data, &ik, sizeof(ik));
89 if (error)
90 return error;
91 kid = ik.ik_keyix;
92 if (kid == IEEE80211_KEYIX_NONE) {
93 ni = ieee80211_find_vap_node(&ic->ic_sta, vap, ik.ik_macaddr);
94 if (ni == NULL)
95 return ENOENT;
96 wk = &ni->ni_ucastkey;
97 } else {
98 if (kid >= IEEE80211_WEP_NKID)
99 return EINVAL;
100 wk = &vap->iv_nw_keys[kid];
101 IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr);
102 ni = NULL;
103 }
104 cip = wk->wk_cipher;
105 ik.ik_type = cip->ic_cipher;
106 ik.ik_keylen = wk->wk_keylen;
107 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
108 if (wk->wk_keyix == vap->iv_def_txkey)
109 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
110 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
111 /* NB: only root can read key data */
112 ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID];
113 ik.ik_keytsc = wk->wk_keytsc;
114 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
115 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
116 memcpy(ik.ik_keydata+wk->wk_keylen,
117 wk->wk_key + IEEE80211_KEYBUF_SIZE,
118 IEEE80211_MICBUF_SIZE);
119 ik.ik_keylen += IEEE80211_MICBUF_SIZE;
120 }
121 } else {
122 ik.ik_keyrsc = 0;
123 ik.ik_keytsc = 0;
124 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
125 }
126 if (ni != NULL)
127 ieee80211_free_node(ni);
128 return copyout(&ik, ireq->i_data, sizeof(ik));
129}
130
131static __noinline int
132ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
133{
134 struct ieee80211com *ic = vap->iv_ic;
135
136 if (sizeof(ic->ic_chan_active) < ireq->i_len)
137 ireq->i_len = sizeof(ic->ic_chan_active);
138 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
139}
140
141static __noinline int
142ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
143{
144 struct ieee80211com *ic = vap->iv_ic;
145 int space;
146
147 space = __offsetof(struct ieee80211req_chaninfo,
148 ic_chans[ic->ic_nchans]);
149 if (space > ireq->i_len)
150 space = ireq->i_len;
151 /* XXX assumes compatible layout */
152 return copyout(&ic->ic_nchans, ireq->i_data, space);
153}
154
155static __noinline int
156ieee80211_ioctl_getwpaie(struct ieee80211vap *vap,
157 struct ieee80211req *ireq, int req)
158{
159 struct ieee80211_node *ni;
160 struct ieee80211req_wpaie2 wpaie;
161 int error;
162
163 if (ireq->i_len < IEEE80211_ADDR_LEN)
164 return EINVAL;
165 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
166 if (error != 0)
167 return error;
168 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie.wpa_macaddr);
169 if (ni == NULL)
170 return ENOENT;
171 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
172 if (ni->ni_ies.wpa_ie != NULL) {
173 int ielen = ni->ni_ies.wpa_ie[1] + 2;
174 if (ielen > sizeof(wpaie.wpa_ie))
175 ielen = sizeof(wpaie.wpa_ie);
176 memcpy(wpaie.wpa_ie, ni->ni_ies.wpa_ie, ielen);
177 }
178 if (req == IEEE80211_IOC_WPAIE2) {
179 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie));
180 if (ni->ni_ies.rsn_ie != NULL) {
181 int ielen = ni->ni_ies.rsn_ie[1] + 2;
182 if (ielen > sizeof(wpaie.rsn_ie))
183 ielen = sizeof(wpaie.rsn_ie);
184 memcpy(wpaie.rsn_ie, ni->ni_ies.rsn_ie, ielen);
185 }
186 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
187 ireq->i_len = sizeof(struct ieee80211req_wpaie2);
188 } else {
189 /* compatibility op, may overwrite wpa ie */
190 /* XXX check ic_flags? */
191 if (ni->ni_ies.rsn_ie != NULL) {
192 int ielen = ni->ni_ies.rsn_ie[1] + 2;
193 if (ielen > sizeof(wpaie.wpa_ie))
194 ielen = sizeof(wpaie.wpa_ie);
195 memcpy(wpaie.wpa_ie, ni->ni_ies.rsn_ie, ielen);
196 }
197 if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
198 ireq->i_len = sizeof(struct ieee80211req_wpaie);
199 }
200 ieee80211_free_node(ni);
201 return copyout(&wpaie, ireq->i_data, ireq->i_len);
202}
203
204static __noinline int
205ieee80211_ioctl_getstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
206{
207 struct ieee80211_node *ni;
208 uint8_t macaddr[IEEE80211_ADDR_LEN];
209 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats);
210 int error;
211
212 if (ireq->i_len < off)
213 return EINVAL;
214 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
215 if (error != 0)
216 return error;
217 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
218 if (ni == NULL)
219 return ENOENT;
220 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
221 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
222 /* NB: copy out only the statistics */
223 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off,
224 ireq->i_len - off);
225 ieee80211_free_node(ni);
226 return error;
227}
228
229struct scanreq {
230 struct ieee80211req_scan_result *sr;
231 size_t space;
232};
233
234static size_t
235scan_space(const struct ieee80211_scan_entry *se, int *ielen)
236{
237 size_t len;
238
239 *ielen = se->se_ies.len;
240 /*
241 * NB: ie's can be no more than 255 bytes and the max 802.11
242 * packet is <3Kbytes so we are sure this doesn't overflow
243 * 16-bits; if this is a concern we can drop the ie's.
244 */
245 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen;
246 return roundup(len, sizeof(uint32_t));
247}
248
249static void
250get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
251{
252 struct scanreq *req = arg;
253 int ielen;
254
255 req->space += scan_space(se, &ielen);
256}
257
258static __noinline void
259get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
260{
261 struct scanreq *req = arg;
262 struct ieee80211req_scan_result *sr;
263 int ielen, len, nr, nxr;
264 uint8_t *cp;
265
266 len = scan_space(se, &ielen);
267 if (len > req->space)
268 return;
269
270 sr = req->sr;
271 KASSERT(len <= 65535 && ielen <= 65535,
272 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
273 sr->isr_len = len;
274 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result);
275 sr->isr_ie_len = ielen;
276 sr->isr_freq = se->se_chan->ic_freq;
277 sr->isr_flags = se->se_chan->ic_flags;
278 sr->isr_rssi = se->se_rssi;
279 sr->isr_noise = se->se_noise;
280 sr->isr_intval = se->se_intval;
281 sr->isr_capinfo = se->se_capinfo;
282 sr->isr_erp = se->se_erp;
283 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
284 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
285 memcpy(sr->isr_rates, se->se_rates+2, nr);
286 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
287 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
288 sr->isr_nrates = nr + nxr;
289
290 sr->isr_ssid_len = se->se_ssid[1];
291 cp = ((uint8_t *)sr) + sr->isr_ie_off;
292 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
293
294 if (ielen) {
295 cp += sr->isr_ssid_len;
296 memcpy(cp, se->se_ies.data, ielen);
297 }
298
299 req->space -= len;
300 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
301}
302
303static __noinline int
304ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
305 struct ieee80211req *ireq)
306{
307 struct scanreq req;
308 int error;
309
310 if (ireq->i_len < sizeof(struct scanreq))
311 return EFAULT;
312
313 error = 0;
314 req.space = 0;
315 ieee80211_scan_iterate(vap, get_scan_space, &req);
316 if (req.space > ireq->i_len)
317 req.space = ireq->i_len;
318 if (req.space > 0) {
319 size_t space;
320 void *p;
321
322 space = req.space;
323 /* XXX M_WAITOK after driver lock released */
324 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
325 if (p == NULL)
326 return ENOMEM;
327 req.sr = p;
328 ieee80211_scan_iterate(vap, get_scan_result, &req);
329 ireq->i_len = space - req.space;
330 error = copyout(p, ireq->i_data, ireq->i_len);
331 free(p, M_TEMP);
332 } else
333 ireq->i_len = 0;
334
335 return error;
336}
337
338struct stainforeq {
339 struct ieee80211vap *vap;
340 struct ieee80211req_sta_info *si;
341 size_t space;
342};
343
344static size_t
345sta_space(const struct ieee80211_node *ni, size_t *ielen)
346{
347 *ielen = ni->ni_ies.len;
348 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
349 sizeof(uint32_t));
350}
351
352static void
353get_sta_space(void *arg, struct ieee80211_node *ni)
354{
355 struct stainforeq *req = arg;
356 size_t ielen;
357
358 if (req->vap != ni->ni_vap)
359 return;
360 if (ni->ni_vap->iv_opmode == IEEE80211_M_HOSTAP &&
361 ni->ni_associd == 0) /* only associated stations */
362 return;
363 req->space += sta_space(ni, &ielen);
364}
365
366static __noinline void
367get_sta_info(void *arg, struct ieee80211_node *ni)
368{
369 struct stainforeq *req = arg;
370 struct ieee80211vap *vap = ni->ni_vap;
371 struct ieee80211req_sta_info *si;
372 size_t ielen, len;
373 uint8_t *cp;
374
375 if (req->vap != ni->ni_vap)
376 return;
377 if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
378 ni->ni_associd == 0) /* only associated stations */
379 return;
380 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
381 return;
382 len = sta_space(ni, &ielen);
383 if (len > req->space)
384 return;
385 si = req->si;
386 si->isi_len = len;
387 si->isi_ie_off = sizeof(struct ieee80211req_sta_info);
388 si->isi_ie_len = ielen;
389 si->isi_freq = ni->ni_chan->ic_freq;
390 si->isi_flags = ni->ni_chan->ic_flags;
391 si->isi_state = ni->ni_flags;
392 si->isi_authmode = ni->ni_authmode;
393 vap->iv_ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise);
394 vap->iv_ic->ic_node_getmimoinfo(ni, &si->isi_mimo);
395 si->isi_capinfo = ni->ni_capinfo;
396 si->isi_erp = ni->ni_erp;
397 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
398 si->isi_nrates = ni->ni_rates.rs_nrates;
399 if (si->isi_nrates > 15)
400 si->isi_nrates = 15;
401 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
402 si->isi_txrate = ni->ni_txrate;
403 if (si->isi_txrate & IEEE80211_RATE_MCS) {
404 const struct ieee80211_mcs_rates *mcs =
405 &ieee80211_htrates[ni->ni_txrate &~ IEEE80211_RATE_MCS];
406 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
407 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
408 si->isi_txmbps = mcs->ht40_rate_800ns;
409 else
410 si->isi_txmbps = mcs->ht40_rate_400ns;
411 } else {
412 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
413 si->isi_txmbps = mcs->ht20_rate_800ns;
414 else
415 si->isi_txmbps = mcs->ht20_rate_400ns;
416 }
417 } else
418 si->isi_txmbps = si->isi_txrate;
419 si->isi_associd = ni->ni_associd;
420 si->isi_txpower = ni->ni_txpower;
421 si->isi_vlan = ni->ni_vlan;
422 if (ni->ni_flags & IEEE80211_NODE_QOS) {
423 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
424 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
425 } else {
426 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
427 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
428 }
429 /* NB: leave all cases in case we relax ni_associd == 0 check */
430 if (ieee80211_node_is_authorized(ni))
431 si->isi_inact = vap->iv_inact_run;
432 else if (ni->ni_associd != 0 ||
433 (vap->iv_opmode == IEEE80211_M_WDS &&
434 (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY)))
435 si->isi_inact = vap->iv_inact_auth;
436 else
437 si->isi_inact = vap->iv_inact_init;
438 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
439
440 if (ielen) {
441 cp = ((uint8_t *)si) + si->isi_ie_off;
442 memcpy(cp, ni->ni_ies.data, ielen);
443 }
444
445 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len);
446 req->space -= len;
447}
448
449static __noinline int
450getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
451 struct ieee80211_node *ni, int off)
452{
453 struct ieee80211com *ic = vap->iv_ic;
454 struct stainforeq req;
455 size_t space;
456 void *p;
457 int error;
458
459 error = 0;
460 req.space = 0;
461 req.vap = vap;
462 if (ni == NULL)
463 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req);
464 else
465 get_sta_space(&req, ni);
466 if (req.space > ireq->i_len)
467 req.space = ireq->i_len;
468 if (req.space > 0) {
469 space = req.space;
470 /* XXX M_WAITOK after driver lock released */
471 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
472 if (p == NULL) {
473 error = ENOMEM;
474 goto bad;
475 }
476 req.si = p;
477 if (ni == NULL)
478 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
479 else
480 get_sta_info(&req, ni);
481 ireq->i_len = space - req.space;
482 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
483 free(p, M_TEMP);
484 } else
485 ireq->i_len = 0;
486bad:
487 if (ni != NULL)
488 ieee80211_free_node(ni);
489 return error;
490}
491
492static __noinline int
493ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
494{
495 uint8_t macaddr[IEEE80211_ADDR_LEN];
496 const int off = __offsetof(struct ieee80211req_sta_req, info);
497 struct ieee80211_node *ni;
498 int error;
499
500 if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
501 return EFAULT;
502 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
503 if (error != 0)
504 return error;
505 if (IEEE80211_ADDR_EQ(macaddr, vap->iv_ifp->if_broadcastaddr)) {
506 ni = NULL;
507 } else {
508 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
509 if (ni == NULL)
510 return ENOENT;
511 }
512 return getstainfo_common(vap, ireq, ni, off);
513}
514
515static __noinline int
516ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
517{
518 struct ieee80211_node *ni;
519 struct ieee80211req_sta_txpow txpow;
520 int error;
521
522 if (ireq->i_len != sizeof(txpow))
523 return EINVAL;
524 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
525 if (error != 0)
526 return error;
527 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr);
528 if (ni == NULL)
529 return ENOENT;
530 txpow.it_txpow = ni->ni_txpower;
531 error = copyout(&txpow, ireq->i_data, sizeof(txpow));
532 ieee80211_free_node(ni);
533 return error;
534}
535
536static __noinline int
537ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
538{
539 struct ieee80211com *ic = vap->iv_ic;
540 struct ieee80211_wme_state *wme = &ic->ic_wme;
541 struct wmeParams *wmep;
542 int ac;
543
544 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
545 return EINVAL;
546
547 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
548 if (ac >= WME_NUM_AC)
549 ac = WME_AC_BE;
550 if (ireq->i_len & IEEE80211_WMEPARAM_BSS)
551 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
552 else
553 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
554 switch (ireq->i_type) {
555 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
556 ireq->i_val = wmep->wmep_logcwmin;
557 break;
558 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
559 ireq->i_val = wmep->wmep_logcwmax;
560 break;
561 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
562 ireq->i_val = wmep->wmep_aifsn;
563 break;
564 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
565 ireq->i_val = wmep->wmep_txopLimit;
566 break;
567 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
568 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
569 ireq->i_val = wmep->wmep_acm;
570 break;
571 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
572 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
573 ireq->i_val = !wmep->wmep_noackPolicy;
574 break;
575 }
576 return 0;
577}
578
579static __noinline int
580ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
581{
582 const struct ieee80211_aclator *acl = vap->iv_acl;
583
584 return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq));
585}
586
29
30/*
31 * IEEE 802.11 ioctl support (FreeBSD-specific)
32 */
33
34#include "opt_inet.h"
35#include "opt_ipx.h"
36#include "opt_wlan.h"
37
38#include <sys/endian.h>
39#include <sys/param.h>
40#include <sys/kernel.h>
41#include <sys/priv.h>
42#include <sys/socket.h>
43#include <sys/sockio.h>
44#include <sys/systm.h>
45#include <sys/taskqueue.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#include <net80211/ieee80211_regdomain.h>
65#include <net80211/ieee80211_input.h>
66
67#define IS_UP_AUTO(_vap) \
68 (IFNET_IS_UP_RUNNING(vap->iv_ifp) && \
69 (_vap)->iv_roaming == IEEE80211_ROAMING_AUTO)
70
71static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
72static struct ieee80211_channel *findchannel(struct ieee80211com *,
73 int ieee, int mode);
74
75static __noinline int
76ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
77{
78 struct ieee80211com *ic = vap->iv_ic;
79 struct ieee80211_node *ni;
80 struct ieee80211req_key ik;
81 struct ieee80211_key *wk;
82 const struct ieee80211_cipher *cip;
83 u_int kid;
84 int error;
85
86 if (ireq->i_len != sizeof(ik))
87 return EINVAL;
88 error = copyin(ireq->i_data, &ik, sizeof(ik));
89 if (error)
90 return error;
91 kid = ik.ik_keyix;
92 if (kid == IEEE80211_KEYIX_NONE) {
93 ni = ieee80211_find_vap_node(&ic->ic_sta, vap, ik.ik_macaddr);
94 if (ni == NULL)
95 return ENOENT;
96 wk = &ni->ni_ucastkey;
97 } else {
98 if (kid >= IEEE80211_WEP_NKID)
99 return EINVAL;
100 wk = &vap->iv_nw_keys[kid];
101 IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr);
102 ni = NULL;
103 }
104 cip = wk->wk_cipher;
105 ik.ik_type = cip->ic_cipher;
106 ik.ik_keylen = wk->wk_keylen;
107 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
108 if (wk->wk_keyix == vap->iv_def_txkey)
109 ik.ik_flags |= IEEE80211_KEY_DEFAULT;
110 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
111 /* NB: only root can read key data */
112 ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID];
113 ik.ik_keytsc = wk->wk_keytsc;
114 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen);
115 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) {
116 memcpy(ik.ik_keydata+wk->wk_keylen,
117 wk->wk_key + IEEE80211_KEYBUF_SIZE,
118 IEEE80211_MICBUF_SIZE);
119 ik.ik_keylen += IEEE80211_MICBUF_SIZE;
120 }
121 } else {
122 ik.ik_keyrsc = 0;
123 ik.ik_keytsc = 0;
124 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
125 }
126 if (ni != NULL)
127 ieee80211_free_node(ni);
128 return copyout(&ik, ireq->i_data, sizeof(ik));
129}
130
131static __noinline int
132ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
133{
134 struct ieee80211com *ic = vap->iv_ic;
135
136 if (sizeof(ic->ic_chan_active) < ireq->i_len)
137 ireq->i_len = sizeof(ic->ic_chan_active);
138 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len);
139}
140
141static __noinline int
142ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
143{
144 struct ieee80211com *ic = vap->iv_ic;
145 int space;
146
147 space = __offsetof(struct ieee80211req_chaninfo,
148 ic_chans[ic->ic_nchans]);
149 if (space > ireq->i_len)
150 space = ireq->i_len;
151 /* XXX assumes compatible layout */
152 return copyout(&ic->ic_nchans, ireq->i_data, space);
153}
154
155static __noinline int
156ieee80211_ioctl_getwpaie(struct ieee80211vap *vap,
157 struct ieee80211req *ireq, int req)
158{
159 struct ieee80211_node *ni;
160 struct ieee80211req_wpaie2 wpaie;
161 int error;
162
163 if (ireq->i_len < IEEE80211_ADDR_LEN)
164 return EINVAL;
165 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN);
166 if (error != 0)
167 return error;
168 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie.wpa_macaddr);
169 if (ni == NULL)
170 return ENOENT;
171 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie));
172 if (ni->ni_ies.wpa_ie != NULL) {
173 int ielen = ni->ni_ies.wpa_ie[1] + 2;
174 if (ielen > sizeof(wpaie.wpa_ie))
175 ielen = sizeof(wpaie.wpa_ie);
176 memcpy(wpaie.wpa_ie, ni->ni_ies.wpa_ie, ielen);
177 }
178 if (req == IEEE80211_IOC_WPAIE2) {
179 memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie));
180 if (ni->ni_ies.rsn_ie != NULL) {
181 int ielen = ni->ni_ies.rsn_ie[1] + 2;
182 if (ielen > sizeof(wpaie.rsn_ie))
183 ielen = sizeof(wpaie.rsn_ie);
184 memcpy(wpaie.rsn_ie, ni->ni_ies.rsn_ie, ielen);
185 }
186 if (ireq->i_len > sizeof(struct ieee80211req_wpaie2))
187 ireq->i_len = sizeof(struct ieee80211req_wpaie2);
188 } else {
189 /* compatibility op, may overwrite wpa ie */
190 /* XXX check ic_flags? */
191 if (ni->ni_ies.rsn_ie != NULL) {
192 int ielen = ni->ni_ies.rsn_ie[1] + 2;
193 if (ielen > sizeof(wpaie.wpa_ie))
194 ielen = sizeof(wpaie.wpa_ie);
195 memcpy(wpaie.wpa_ie, ni->ni_ies.rsn_ie, ielen);
196 }
197 if (ireq->i_len > sizeof(struct ieee80211req_wpaie))
198 ireq->i_len = sizeof(struct ieee80211req_wpaie);
199 }
200 ieee80211_free_node(ni);
201 return copyout(&wpaie, ireq->i_data, ireq->i_len);
202}
203
204static __noinline int
205ieee80211_ioctl_getstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
206{
207 struct ieee80211_node *ni;
208 uint8_t macaddr[IEEE80211_ADDR_LEN];
209 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats);
210 int error;
211
212 if (ireq->i_len < off)
213 return EINVAL;
214 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
215 if (error != 0)
216 return error;
217 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
218 if (ni == NULL)
219 return ENOENT;
220 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats))
221 ireq->i_len = sizeof(struct ieee80211req_sta_stats);
222 /* NB: copy out only the statistics */
223 error = copyout(&ni->ni_stats, (uint8_t *) ireq->i_data + off,
224 ireq->i_len - off);
225 ieee80211_free_node(ni);
226 return error;
227}
228
229struct scanreq {
230 struct ieee80211req_scan_result *sr;
231 size_t space;
232};
233
234static size_t
235scan_space(const struct ieee80211_scan_entry *se, int *ielen)
236{
237 size_t len;
238
239 *ielen = se->se_ies.len;
240 /*
241 * NB: ie's can be no more than 255 bytes and the max 802.11
242 * packet is <3Kbytes so we are sure this doesn't overflow
243 * 16-bits; if this is a concern we can drop the ie's.
244 */
245 len = sizeof(struct ieee80211req_scan_result) + se->se_ssid[1] + *ielen;
246 return roundup(len, sizeof(uint32_t));
247}
248
249static void
250get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
251{
252 struct scanreq *req = arg;
253 int ielen;
254
255 req->space += scan_space(se, &ielen);
256}
257
258static __noinline void
259get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
260{
261 struct scanreq *req = arg;
262 struct ieee80211req_scan_result *sr;
263 int ielen, len, nr, nxr;
264 uint8_t *cp;
265
266 len = scan_space(se, &ielen);
267 if (len > req->space)
268 return;
269
270 sr = req->sr;
271 KASSERT(len <= 65535 && ielen <= 65535,
272 ("len %u ssid %u ie %u", len, se->se_ssid[1], ielen));
273 sr->isr_len = len;
274 sr->isr_ie_off = sizeof(struct ieee80211req_scan_result);
275 sr->isr_ie_len = ielen;
276 sr->isr_freq = se->se_chan->ic_freq;
277 sr->isr_flags = se->se_chan->ic_flags;
278 sr->isr_rssi = se->se_rssi;
279 sr->isr_noise = se->se_noise;
280 sr->isr_intval = se->se_intval;
281 sr->isr_capinfo = se->se_capinfo;
282 sr->isr_erp = se->se_erp;
283 IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
284 nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
285 memcpy(sr->isr_rates, se->se_rates+2, nr);
286 nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
287 memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
288 sr->isr_nrates = nr + nxr;
289
290 sr->isr_ssid_len = se->se_ssid[1];
291 cp = ((uint8_t *)sr) + sr->isr_ie_off;
292 memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
293
294 if (ielen) {
295 cp += sr->isr_ssid_len;
296 memcpy(cp, se->se_ies.data, ielen);
297 }
298
299 req->space -= len;
300 req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len);
301}
302
303static __noinline int
304ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
305 struct ieee80211req *ireq)
306{
307 struct scanreq req;
308 int error;
309
310 if (ireq->i_len < sizeof(struct scanreq))
311 return EFAULT;
312
313 error = 0;
314 req.space = 0;
315 ieee80211_scan_iterate(vap, get_scan_space, &req);
316 if (req.space > ireq->i_len)
317 req.space = ireq->i_len;
318 if (req.space > 0) {
319 size_t space;
320 void *p;
321
322 space = req.space;
323 /* XXX M_WAITOK after driver lock released */
324 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
325 if (p == NULL)
326 return ENOMEM;
327 req.sr = p;
328 ieee80211_scan_iterate(vap, get_scan_result, &req);
329 ireq->i_len = space - req.space;
330 error = copyout(p, ireq->i_data, ireq->i_len);
331 free(p, M_TEMP);
332 } else
333 ireq->i_len = 0;
334
335 return error;
336}
337
338struct stainforeq {
339 struct ieee80211vap *vap;
340 struct ieee80211req_sta_info *si;
341 size_t space;
342};
343
344static size_t
345sta_space(const struct ieee80211_node *ni, size_t *ielen)
346{
347 *ielen = ni->ni_ies.len;
348 return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
349 sizeof(uint32_t));
350}
351
352static void
353get_sta_space(void *arg, struct ieee80211_node *ni)
354{
355 struct stainforeq *req = arg;
356 size_t ielen;
357
358 if (req->vap != ni->ni_vap)
359 return;
360 if (ni->ni_vap->iv_opmode == IEEE80211_M_HOSTAP &&
361 ni->ni_associd == 0) /* only associated stations */
362 return;
363 req->space += sta_space(ni, &ielen);
364}
365
366static __noinline void
367get_sta_info(void *arg, struct ieee80211_node *ni)
368{
369 struct stainforeq *req = arg;
370 struct ieee80211vap *vap = ni->ni_vap;
371 struct ieee80211req_sta_info *si;
372 size_t ielen, len;
373 uint8_t *cp;
374
375 if (req->vap != ni->ni_vap)
376 return;
377 if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
378 ni->ni_associd == 0) /* only associated stations */
379 return;
380 if (ni->ni_chan == IEEE80211_CHAN_ANYC) /* XXX bogus entry */
381 return;
382 len = sta_space(ni, &ielen);
383 if (len > req->space)
384 return;
385 si = req->si;
386 si->isi_len = len;
387 si->isi_ie_off = sizeof(struct ieee80211req_sta_info);
388 si->isi_ie_len = ielen;
389 si->isi_freq = ni->ni_chan->ic_freq;
390 si->isi_flags = ni->ni_chan->ic_flags;
391 si->isi_state = ni->ni_flags;
392 si->isi_authmode = ni->ni_authmode;
393 vap->iv_ic->ic_node_getsignal(ni, &si->isi_rssi, &si->isi_noise);
394 vap->iv_ic->ic_node_getmimoinfo(ni, &si->isi_mimo);
395 si->isi_capinfo = ni->ni_capinfo;
396 si->isi_erp = ni->ni_erp;
397 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr);
398 si->isi_nrates = ni->ni_rates.rs_nrates;
399 if (si->isi_nrates > 15)
400 si->isi_nrates = 15;
401 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
402 si->isi_txrate = ni->ni_txrate;
403 if (si->isi_txrate & IEEE80211_RATE_MCS) {
404 const struct ieee80211_mcs_rates *mcs =
405 &ieee80211_htrates[ni->ni_txrate &~ IEEE80211_RATE_MCS];
406 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
407 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
408 si->isi_txmbps = mcs->ht40_rate_800ns;
409 else
410 si->isi_txmbps = mcs->ht40_rate_400ns;
411 } else {
412 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
413 si->isi_txmbps = mcs->ht20_rate_800ns;
414 else
415 si->isi_txmbps = mcs->ht20_rate_400ns;
416 }
417 } else
418 si->isi_txmbps = si->isi_txrate;
419 si->isi_associd = ni->ni_associd;
420 si->isi_txpower = ni->ni_txpower;
421 si->isi_vlan = ni->ni_vlan;
422 if (ni->ni_flags & IEEE80211_NODE_QOS) {
423 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs));
424 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs));
425 } else {
426 si->isi_txseqs[0] = ni->ni_txseqs[IEEE80211_NONQOS_TID];
427 si->isi_rxseqs[0] = ni->ni_rxseqs[IEEE80211_NONQOS_TID];
428 }
429 /* NB: leave all cases in case we relax ni_associd == 0 check */
430 if (ieee80211_node_is_authorized(ni))
431 si->isi_inact = vap->iv_inact_run;
432 else if (ni->ni_associd != 0 ||
433 (vap->iv_opmode == IEEE80211_M_WDS &&
434 (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY)))
435 si->isi_inact = vap->iv_inact_auth;
436 else
437 si->isi_inact = vap->iv_inact_init;
438 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
439
440 if (ielen) {
441 cp = ((uint8_t *)si) + si->isi_ie_off;
442 memcpy(cp, ni->ni_ies.data, ielen);
443 }
444
445 req->si = (struct ieee80211req_sta_info *)(((uint8_t *)si) + len);
446 req->space -= len;
447}
448
449static __noinline int
450getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
451 struct ieee80211_node *ni, int off)
452{
453 struct ieee80211com *ic = vap->iv_ic;
454 struct stainforeq req;
455 size_t space;
456 void *p;
457 int error;
458
459 error = 0;
460 req.space = 0;
461 req.vap = vap;
462 if (ni == NULL)
463 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req);
464 else
465 get_sta_space(&req, ni);
466 if (req.space > ireq->i_len)
467 req.space = ireq->i_len;
468 if (req.space > 0) {
469 space = req.space;
470 /* XXX M_WAITOK after driver lock released */
471 p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
472 if (p == NULL) {
473 error = ENOMEM;
474 goto bad;
475 }
476 req.si = p;
477 if (ni == NULL)
478 ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req);
479 else
480 get_sta_info(&req, ni);
481 ireq->i_len = space - req.space;
482 error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
483 free(p, M_TEMP);
484 } else
485 ireq->i_len = 0;
486bad:
487 if (ni != NULL)
488 ieee80211_free_node(ni);
489 return error;
490}
491
492static __noinline int
493ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq)
494{
495 uint8_t macaddr[IEEE80211_ADDR_LEN];
496 const int off = __offsetof(struct ieee80211req_sta_req, info);
497 struct ieee80211_node *ni;
498 int error;
499
500 if (ireq->i_len < sizeof(struct ieee80211req_sta_req))
501 return EFAULT;
502 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
503 if (error != 0)
504 return error;
505 if (IEEE80211_ADDR_EQ(macaddr, vap->iv_ifp->if_broadcastaddr)) {
506 ni = NULL;
507 } else {
508 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
509 if (ni == NULL)
510 return ENOENT;
511 }
512 return getstainfo_common(vap, ireq, ni, off);
513}
514
515static __noinline int
516ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
517{
518 struct ieee80211_node *ni;
519 struct ieee80211req_sta_txpow txpow;
520 int error;
521
522 if (ireq->i_len != sizeof(txpow))
523 return EINVAL;
524 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
525 if (error != 0)
526 return error;
527 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr);
528 if (ni == NULL)
529 return ENOENT;
530 txpow.it_txpow = ni->ni_txpower;
531 error = copyout(&txpow, ireq->i_data, sizeof(txpow));
532 ieee80211_free_node(ni);
533 return error;
534}
535
536static __noinline int
537ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
538{
539 struct ieee80211com *ic = vap->iv_ic;
540 struct ieee80211_wme_state *wme = &ic->ic_wme;
541 struct wmeParams *wmep;
542 int ac;
543
544 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
545 return EINVAL;
546
547 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
548 if (ac >= WME_NUM_AC)
549 ac = WME_AC_BE;
550 if (ireq->i_len & IEEE80211_WMEPARAM_BSS)
551 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
552 else
553 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
554 switch (ireq->i_type) {
555 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
556 ireq->i_val = wmep->wmep_logcwmin;
557 break;
558 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
559 ireq->i_val = wmep->wmep_logcwmax;
560 break;
561 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
562 ireq->i_val = wmep->wmep_aifsn;
563 break;
564 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
565 ireq->i_val = wmep->wmep_txopLimit;
566 break;
567 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
568 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
569 ireq->i_val = wmep->wmep_acm;
570 break;
571 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
572 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
573 ireq->i_val = !wmep->wmep_noackPolicy;
574 break;
575 }
576 return 0;
577}
578
579static __noinline int
580ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
581{
582 const struct ieee80211_aclator *acl = vap->iv_acl;
583
584 return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq));
585}
586
587/*
588 * Return the current ``state'' of an Atheros capbility.
589 * If associated in station mode report the negotiated
590 * setting. Otherwise report the current setting.
591 */
592static int
593getathcap(struct ieee80211vap *vap, int cap)
594{
595 if (vap->iv_opmode == IEEE80211_M_STA &&
596 vap->iv_state == IEEE80211_S_RUN)
597 return IEEE80211_ATH_CAP(vap, vap->iv_bss, cap) != 0;
598 else
599 return (vap->iv_flags & cap) != 0;
600}
601
602static __noinline int
603ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq)
604{
605 struct ieee80211com *ic = vap->iv_ic;
606 struct ieee80211_channel *c;
607
608 if (ireq->i_len != sizeof(struct ieee80211_channel))
609 return EINVAL;
610 /*
611 * vap's may have different operating channels when HT is
612 * in use. When in RUN state report the vap-specific channel.
613 * Otherwise return curchan.
614 */
615 if (vap->iv_state == IEEE80211_S_RUN)
616 c = vap->iv_bss->ni_chan;
617 else
618 c = ic->ic_curchan;
619 return copyout(c, ireq->i_data, sizeof(*c));
620}
621
622static int
623getappie(const struct ieee80211_appie *aie, struct ieee80211req *ireq)
624{
625 if (aie == NULL)
626 return EINVAL;
627 /* NB: truncate, caller can check length */
628 if (ireq->i_len > aie->ie_len)
629 ireq->i_len = aie->ie_len;
630 return copyout(aie->ie_data, ireq->i_data, ireq->i_len);
631}
632
633static int
634ieee80211_ioctl_getappie(struct ieee80211vap *vap, struct ieee80211req *ireq)
635{
636 uint8_t fc0;
637
638 fc0 = ireq->i_val & 0xff;
639 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
640 return EINVAL;
641 /* NB: could check iv_opmode and reject but hardly worth the effort */
642 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) {
643 case IEEE80211_FC0_SUBTYPE_BEACON:
644 return getappie(vap->iv_appie_beacon, ireq);
645 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
646 return getappie(vap->iv_appie_proberesp, ireq);
647 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
648 return getappie(vap->iv_appie_assocresp, ireq);
649 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
650 return getappie(vap->iv_appie_probereq, ireq);
651 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
652 return getappie(vap->iv_appie_assocreq, ireq);
653 case IEEE80211_FC0_SUBTYPE_BEACON|IEEE80211_FC0_SUBTYPE_PROBE_RESP:
654 return getappie(vap->iv_appie_wpa, ireq);
655 }
656 return EINVAL;
657}
658
659static __noinline int
660ieee80211_ioctl_getregdomain(struct ieee80211vap *vap,
661 const struct ieee80211req *ireq)
662{
663 struct ieee80211com *ic = vap->iv_ic;
664
665 if (ireq->i_len != sizeof(ic->ic_regdomain))
666 return EINVAL;
667 return copyout(&ic->ic_regdomain, ireq->i_data,
668 sizeof(ic->ic_regdomain));
669}
670
671static __noinline int
672ieee80211_ioctl_getroam(struct ieee80211vap *vap,
673 const struct ieee80211req *ireq)
674{
675 size_t len = ireq->i_len;
676 /* NB: accept short requests for backwards compat */
677 if (len > sizeof(vap->iv_roamparms))
678 len = sizeof(vap->iv_roamparms);
679 return copyout(vap->iv_roamparms, ireq->i_data, len);
680}
681
682static __noinline int
683ieee80211_ioctl_gettxparams(struct ieee80211vap *vap,
684 const struct ieee80211req *ireq)
685{
686 size_t len = ireq->i_len;
687 /* NB: accept short requests for backwards compat */
688 if (len > sizeof(vap->iv_txparms))
689 len = sizeof(vap->iv_txparms);
690 return copyout(vap->iv_txparms, ireq->i_data, len);
691}
692
693static __noinline int
694ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
695 const struct ieee80211req *ireq)
696{
697 struct ieee80211_devcaps_req *dc;
698 struct ieee80211req_chaninfo *ci;
699 int maxchans, error;
700
701 maxchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_devcaps_req)) /
702 sizeof(struct ieee80211_channel));
703 /* NB: require 1 so we know ic_nchans is accessible */
704 if (maxchans < 1)
705 return EINVAL;
706 /* constrain max request size, 2K channels is ~24Kbytes */
707 if (maxchans > 2048)
708 maxchans = 2048;
709 dc = (struct ieee80211_devcaps_req *)
710 malloc(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP, M_NOWAIT | M_ZERO);
711 if (dc == NULL)
712 return ENOMEM;
713 dc->dc_drivercaps = ic->ic_caps;
714 dc->dc_cryptocaps = ic->ic_cryptocaps;
715 dc->dc_htcaps = ic->ic_htcaps;
716 ci = &dc->dc_chaninfo;
717 ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans);
718 KASSERT(ci->ic_nchans <= maxchans,
719 ("nchans %d maxchans %d", ci->ic_nchans, maxchans));
720 ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
721 error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc));
722 free(dc, M_TEMP);
723 return error;
724}
725
726static __noinline int
727ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
728{
729 struct ieee80211_node *ni;
730 struct ieee80211req_sta_vlan vlan;
731 int error;
732
733 if (ireq->i_len != sizeof(vlan))
734 return EINVAL;
735 error = copyin(ireq->i_data, &vlan, sizeof(vlan));
736 if (error != 0)
737 return error;
738 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) {
739 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
740 vlan.sv_macaddr);
741 if (ni == NULL)
742 return ENOENT;
743 } else
744 ni = ieee80211_ref_node(vap->iv_bss);
745 vlan.sv_vlan = ni->ni_vlan;
746 error = copyout(&vlan, ireq->i_data, sizeof(vlan));
747 ieee80211_free_node(ni);
748 return error;
749}
750
751/*
752 * Dummy ioctl get handler so the linker set is defined.
753 */
754static int
755dummy_ioctl_get(struct ieee80211vap *vap, struct ieee80211req *ireq)
756{
757 return ENOSYS;
758}
759IEEE80211_IOCTL_GET(dummy, dummy_ioctl_get);
760
761static int
762ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
763{
764 ieee80211_ioctl_getfunc * const *get;
765 int error;
766
767 SET_FOREACH(get, ieee80211_ioctl_getset) {
768 error = (*get)(vap, ireq);
769 if (error != ENOSYS)
770 return error;
771 }
772 return EINVAL;
773}
774
775/*
776 * When building the kernel with -O2 on the i386 architecture, gcc
777 * seems to want to inline this function into ieee80211_ioctl()
778 * (which is the only routine that calls it). When this happens,
779 * ieee80211_ioctl() ends up consuming an additional 2K of stack
780 * space. (Exactly why it needs so much is unclear.) The problem
781 * is that it's possible for ieee80211_ioctl() to invoke other
782 * routines (including driver init functions) which could then find
783 * themselves perilously close to exhausting the stack.
784 *
785 * To avoid this, we deliberately prevent gcc from inlining this
786 * routine. Another way to avoid this is to use less agressive
787 * optimization when compiling this file (i.e. -O instead of -O2)
788 * but special-casing the compilation of this one module in the
789 * build system would be awkward.
790 */
791static __noinline int
792ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
793 struct ieee80211req *ireq)
794{
795#define MS(_v, _f) (((_v) & _f) >> _f##_S)
796 struct ieee80211com *ic = vap->iv_ic;
797 u_int kid, len;
798 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
799 char tmpssid[IEEE80211_NWID_LEN];
800 int error = 0;
801
802 switch (ireq->i_type) {
803 case IEEE80211_IOC_SSID:
804 switch (vap->iv_state) {
805 case IEEE80211_S_INIT:
806 case IEEE80211_S_SCAN:
807 ireq->i_len = vap->iv_des_ssid[0].len;
808 memcpy(tmpssid, vap->iv_des_ssid[0].ssid, ireq->i_len);
809 break;
810 default:
811 ireq->i_len = vap->iv_bss->ni_esslen;
812 memcpy(tmpssid, vap->iv_bss->ni_essid, ireq->i_len);
813 break;
814 }
815 error = copyout(tmpssid, ireq->i_data, ireq->i_len);
816 break;
817 case IEEE80211_IOC_NUMSSIDS:
818 ireq->i_val = 1;
819 break;
820 case IEEE80211_IOC_WEP:
821 if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0)
822 ireq->i_val = IEEE80211_WEP_OFF;
823 else if (vap->iv_flags & IEEE80211_F_DROPUNENC)
824 ireq->i_val = IEEE80211_WEP_ON;
825 else
826 ireq->i_val = IEEE80211_WEP_MIXED;
827 break;
828 case IEEE80211_IOC_WEPKEY:
829 kid = (u_int) ireq->i_val;
830 if (kid >= IEEE80211_WEP_NKID)
831 return EINVAL;
832 len = (u_int) vap->iv_nw_keys[kid].wk_keylen;
833 /* NB: only root can read WEP keys */
834 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
835 bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len);
836 } else {
837 bzero(tmpkey, len);
838 }
839 ireq->i_len = len;
840 error = copyout(tmpkey, ireq->i_data, len);
841 break;
842 case IEEE80211_IOC_NUMWEPKEYS:
843 ireq->i_val = IEEE80211_WEP_NKID;
844 break;
845 case IEEE80211_IOC_WEPTXKEY:
846 ireq->i_val = vap->iv_def_txkey;
847 break;
848 case IEEE80211_IOC_AUTHMODE:
849 if (vap->iv_flags & IEEE80211_F_WPA)
850 ireq->i_val = IEEE80211_AUTH_WPA;
851 else
852 ireq->i_val = vap->iv_bss->ni_authmode;
853 break;
854 case IEEE80211_IOC_CHANNEL:
855 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan);
856 break;
857 case IEEE80211_IOC_POWERSAVE:
858 if (vap->iv_flags & IEEE80211_F_PMGTON)
859 ireq->i_val = IEEE80211_POWERSAVE_ON;
860 else
861 ireq->i_val = IEEE80211_POWERSAVE_OFF;
862 break;
863 case IEEE80211_IOC_POWERSAVESLEEP:
864 ireq->i_val = ic->ic_lintval;
865 break;
866 case IEEE80211_IOC_RTSTHRESHOLD:
867 ireq->i_val = vap->iv_rtsthreshold;
868 break;
869 case IEEE80211_IOC_PROTMODE:
870 ireq->i_val = ic->ic_protmode;
871 break;
872 case IEEE80211_IOC_TXPOWER:
873 /*
874 * Tx power limit is the min of max regulatory
875 * power, any user-set limit, and the max the
876 * radio can do.
877 */
878 ireq->i_val = 2*ic->ic_curchan->ic_maxregpower;
879 if (ireq->i_val > ic->ic_txpowlimit)
880 ireq->i_val = ic->ic_txpowlimit;
881 if (ireq->i_val > ic->ic_curchan->ic_maxpower)
882 ireq->i_val = ic->ic_curchan->ic_maxpower;
883 break;
884 case IEEE80211_IOC_WPA:
885 switch (vap->iv_flags & IEEE80211_F_WPA) {
886 case IEEE80211_F_WPA1:
887 ireq->i_val = 1;
888 break;
889 case IEEE80211_F_WPA2:
890 ireq->i_val = 2;
891 break;
892 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
893 ireq->i_val = 3;
894 break;
895 default:
896 ireq->i_val = 0;
897 break;
898 }
899 break;
900 case IEEE80211_IOC_CHANLIST:
901 error = ieee80211_ioctl_getchanlist(vap, ireq);
902 break;
903 case IEEE80211_IOC_ROAMING:
904 ireq->i_val = vap->iv_roaming;
905 break;
906 case IEEE80211_IOC_PRIVACY:
907 ireq->i_val = (vap->iv_flags & IEEE80211_F_PRIVACY) != 0;
908 break;
909 case IEEE80211_IOC_DROPUNENCRYPTED:
910 ireq->i_val = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0;
911 break;
912 case IEEE80211_IOC_COUNTERMEASURES:
913 ireq->i_val = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0;
914 break;
915 case IEEE80211_IOC_WME:
916 ireq->i_val = (vap->iv_flags & IEEE80211_F_WME) != 0;
917 break;
918 case IEEE80211_IOC_HIDESSID:
919 ireq->i_val = (vap->iv_flags & IEEE80211_F_HIDESSID) != 0;
920 break;
921 case IEEE80211_IOC_APBRIDGE:
922 ireq->i_val = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0;
923 break;
924 case IEEE80211_IOC_WPAKEY:
925 error = ieee80211_ioctl_getkey(vap, ireq);
926 break;
927 case IEEE80211_IOC_CHANINFO:
928 error = ieee80211_ioctl_getchaninfo(vap, ireq);
929 break;
930 case IEEE80211_IOC_BSSID:
931 if (ireq->i_len != IEEE80211_ADDR_LEN)
932 return EINVAL;
933 error = copyout(vap->iv_state == IEEE80211_S_RUN ?
934 vap->iv_bss->ni_bssid :
935 vap->iv_des_bssid,
936 ireq->i_data, ireq->i_len);
937 break;
938 case IEEE80211_IOC_WPAIE:
939 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type);
940 break;
941 case IEEE80211_IOC_WPAIE2:
942 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type);
943 break;
944 case IEEE80211_IOC_SCAN_RESULTS:
945 error = ieee80211_ioctl_getscanresults(vap, ireq);
946 break;
947 case IEEE80211_IOC_STA_STATS:
948 error = ieee80211_ioctl_getstastats(vap, ireq);
949 break;
950 case IEEE80211_IOC_TXPOWMAX:
951 ireq->i_val = vap->iv_bss->ni_txpower;
952 break;
953 case IEEE80211_IOC_STA_TXPOW:
954 error = ieee80211_ioctl_getstatxpow(vap, ireq);
955 break;
956 case IEEE80211_IOC_STA_INFO:
957 error = ieee80211_ioctl_getstainfo(vap, ireq);
958 break;
959 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
960 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
961 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
962 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
963 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
964 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
965 error = ieee80211_ioctl_getwmeparam(vap, ireq);
966 break;
967 case IEEE80211_IOC_DTIM_PERIOD:
968 ireq->i_val = vap->iv_dtim_period;
969 break;
970 case IEEE80211_IOC_BEACON_INTERVAL:
971 /* NB: get from ic_bss for station mode */
972 ireq->i_val = vap->iv_bss->ni_intval;
973 break;
974 case IEEE80211_IOC_PUREG:
975 ireq->i_val = (vap->iv_flags & IEEE80211_F_PUREG) != 0;
976 break;
587static __noinline int
588ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq)
589{
590 struct ieee80211com *ic = vap->iv_ic;
591 struct ieee80211_channel *c;
592
593 if (ireq->i_len != sizeof(struct ieee80211_channel))
594 return EINVAL;
595 /*
596 * vap's may have different operating channels when HT is
597 * in use. When in RUN state report the vap-specific channel.
598 * Otherwise return curchan.
599 */
600 if (vap->iv_state == IEEE80211_S_RUN)
601 c = vap->iv_bss->ni_chan;
602 else
603 c = ic->ic_curchan;
604 return copyout(c, ireq->i_data, sizeof(*c));
605}
606
607static int
608getappie(const struct ieee80211_appie *aie, struct ieee80211req *ireq)
609{
610 if (aie == NULL)
611 return EINVAL;
612 /* NB: truncate, caller can check length */
613 if (ireq->i_len > aie->ie_len)
614 ireq->i_len = aie->ie_len;
615 return copyout(aie->ie_data, ireq->i_data, ireq->i_len);
616}
617
618static int
619ieee80211_ioctl_getappie(struct ieee80211vap *vap, struct ieee80211req *ireq)
620{
621 uint8_t fc0;
622
623 fc0 = ireq->i_val & 0xff;
624 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
625 return EINVAL;
626 /* NB: could check iv_opmode and reject but hardly worth the effort */
627 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) {
628 case IEEE80211_FC0_SUBTYPE_BEACON:
629 return getappie(vap->iv_appie_beacon, ireq);
630 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
631 return getappie(vap->iv_appie_proberesp, ireq);
632 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
633 return getappie(vap->iv_appie_assocresp, ireq);
634 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
635 return getappie(vap->iv_appie_probereq, ireq);
636 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
637 return getappie(vap->iv_appie_assocreq, ireq);
638 case IEEE80211_FC0_SUBTYPE_BEACON|IEEE80211_FC0_SUBTYPE_PROBE_RESP:
639 return getappie(vap->iv_appie_wpa, ireq);
640 }
641 return EINVAL;
642}
643
644static __noinline int
645ieee80211_ioctl_getregdomain(struct ieee80211vap *vap,
646 const struct ieee80211req *ireq)
647{
648 struct ieee80211com *ic = vap->iv_ic;
649
650 if (ireq->i_len != sizeof(ic->ic_regdomain))
651 return EINVAL;
652 return copyout(&ic->ic_regdomain, ireq->i_data,
653 sizeof(ic->ic_regdomain));
654}
655
656static __noinline int
657ieee80211_ioctl_getroam(struct ieee80211vap *vap,
658 const struct ieee80211req *ireq)
659{
660 size_t len = ireq->i_len;
661 /* NB: accept short requests for backwards compat */
662 if (len > sizeof(vap->iv_roamparms))
663 len = sizeof(vap->iv_roamparms);
664 return copyout(vap->iv_roamparms, ireq->i_data, len);
665}
666
667static __noinline int
668ieee80211_ioctl_gettxparams(struct ieee80211vap *vap,
669 const struct ieee80211req *ireq)
670{
671 size_t len = ireq->i_len;
672 /* NB: accept short requests for backwards compat */
673 if (len > sizeof(vap->iv_txparms))
674 len = sizeof(vap->iv_txparms);
675 return copyout(vap->iv_txparms, ireq->i_data, len);
676}
677
678static __noinline int
679ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
680 const struct ieee80211req *ireq)
681{
682 struct ieee80211_devcaps_req *dc;
683 struct ieee80211req_chaninfo *ci;
684 int maxchans, error;
685
686 maxchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_devcaps_req)) /
687 sizeof(struct ieee80211_channel));
688 /* NB: require 1 so we know ic_nchans is accessible */
689 if (maxchans < 1)
690 return EINVAL;
691 /* constrain max request size, 2K channels is ~24Kbytes */
692 if (maxchans > 2048)
693 maxchans = 2048;
694 dc = (struct ieee80211_devcaps_req *)
695 malloc(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP, M_NOWAIT | M_ZERO);
696 if (dc == NULL)
697 return ENOMEM;
698 dc->dc_drivercaps = ic->ic_caps;
699 dc->dc_cryptocaps = ic->ic_cryptocaps;
700 dc->dc_htcaps = ic->ic_htcaps;
701 ci = &dc->dc_chaninfo;
702 ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans);
703 KASSERT(ci->ic_nchans <= maxchans,
704 ("nchans %d maxchans %d", ci->ic_nchans, maxchans));
705 ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
706 error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc));
707 free(dc, M_TEMP);
708 return error;
709}
710
711static __noinline int
712ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
713{
714 struct ieee80211_node *ni;
715 struct ieee80211req_sta_vlan vlan;
716 int error;
717
718 if (ireq->i_len != sizeof(vlan))
719 return EINVAL;
720 error = copyin(ireq->i_data, &vlan, sizeof(vlan));
721 if (error != 0)
722 return error;
723 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) {
724 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
725 vlan.sv_macaddr);
726 if (ni == NULL)
727 return ENOENT;
728 } else
729 ni = ieee80211_ref_node(vap->iv_bss);
730 vlan.sv_vlan = ni->ni_vlan;
731 error = copyout(&vlan, ireq->i_data, sizeof(vlan));
732 ieee80211_free_node(ni);
733 return error;
734}
735
736/*
737 * Dummy ioctl get handler so the linker set is defined.
738 */
739static int
740dummy_ioctl_get(struct ieee80211vap *vap, struct ieee80211req *ireq)
741{
742 return ENOSYS;
743}
744IEEE80211_IOCTL_GET(dummy, dummy_ioctl_get);
745
746static int
747ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
748{
749 ieee80211_ioctl_getfunc * const *get;
750 int error;
751
752 SET_FOREACH(get, ieee80211_ioctl_getset) {
753 error = (*get)(vap, ireq);
754 if (error != ENOSYS)
755 return error;
756 }
757 return EINVAL;
758}
759
760/*
761 * When building the kernel with -O2 on the i386 architecture, gcc
762 * seems to want to inline this function into ieee80211_ioctl()
763 * (which is the only routine that calls it). When this happens,
764 * ieee80211_ioctl() ends up consuming an additional 2K of stack
765 * space. (Exactly why it needs so much is unclear.) The problem
766 * is that it's possible for ieee80211_ioctl() to invoke other
767 * routines (including driver init functions) which could then find
768 * themselves perilously close to exhausting the stack.
769 *
770 * To avoid this, we deliberately prevent gcc from inlining this
771 * routine. Another way to avoid this is to use less agressive
772 * optimization when compiling this file (i.e. -O instead of -O2)
773 * but special-casing the compilation of this one module in the
774 * build system would be awkward.
775 */
776static __noinline int
777ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
778 struct ieee80211req *ireq)
779{
780#define MS(_v, _f) (((_v) & _f) >> _f##_S)
781 struct ieee80211com *ic = vap->iv_ic;
782 u_int kid, len;
783 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
784 char tmpssid[IEEE80211_NWID_LEN];
785 int error = 0;
786
787 switch (ireq->i_type) {
788 case IEEE80211_IOC_SSID:
789 switch (vap->iv_state) {
790 case IEEE80211_S_INIT:
791 case IEEE80211_S_SCAN:
792 ireq->i_len = vap->iv_des_ssid[0].len;
793 memcpy(tmpssid, vap->iv_des_ssid[0].ssid, ireq->i_len);
794 break;
795 default:
796 ireq->i_len = vap->iv_bss->ni_esslen;
797 memcpy(tmpssid, vap->iv_bss->ni_essid, ireq->i_len);
798 break;
799 }
800 error = copyout(tmpssid, ireq->i_data, ireq->i_len);
801 break;
802 case IEEE80211_IOC_NUMSSIDS:
803 ireq->i_val = 1;
804 break;
805 case IEEE80211_IOC_WEP:
806 if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0)
807 ireq->i_val = IEEE80211_WEP_OFF;
808 else if (vap->iv_flags & IEEE80211_F_DROPUNENC)
809 ireq->i_val = IEEE80211_WEP_ON;
810 else
811 ireq->i_val = IEEE80211_WEP_MIXED;
812 break;
813 case IEEE80211_IOC_WEPKEY:
814 kid = (u_int) ireq->i_val;
815 if (kid >= IEEE80211_WEP_NKID)
816 return EINVAL;
817 len = (u_int) vap->iv_nw_keys[kid].wk_keylen;
818 /* NB: only root can read WEP keys */
819 if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) {
820 bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len);
821 } else {
822 bzero(tmpkey, len);
823 }
824 ireq->i_len = len;
825 error = copyout(tmpkey, ireq->i_data, len);
826 break;
827 case IEEE80211_IOC_NUMWEPKEYS:
828 ireq->i_val = IEEE80211_WEP_NKID;
829 break;
830 case IEEE80211_IOC_WEPTXKEY:
831 ireq->i_val = vap->iv_def_txkey;
832 break;
833 case IEEE80211_IOC_AUTHMODE:
834 if (vap->iv_flags & IEEE80211_F_WPA)
835 ireq->i_val = IEEE80211_AUTH_WPA;
836 else
837 ireq->i_val = vap->iv_bss->ni_authmode;
838 break;
839 case IEEE80211_IOC_CHANNEL:
840 ireq->i_val = ieee80211_chan2ieee(ic, ic->ic_curchan);
841 break;
842 case IEEE80211_IOC_POWERSAVE:
843 if (vap->iv_flags & IEEE80211_F_PMGTON)
844 ireq->i_val = IEEE80211_POWERSAVE_ON;
845 else
846 ireq->i_val = IEEE80211_POWERSAVE_OFF;
847 break;
848 case IEEE80211_IOC_POWERSAVESLEEP:
849 ireq->i_val = ic->ic_lintval;
850 break;
851 case IEEE80211_IOC_RTSTHRESHOLD:
852 ireq->i_val = vap->iv_rtsthreshold;
853 break;
854 case IEEE80211_IOC_PROTMODE:
855 ireq->i_val = ic->ic_protmode;
856 break;
857 case IEEE80211_IOC_TXPOWER:
858 /*
859 * Tx power limit is the min of max regulatory
860 * power, any user-set limit, and the max the
861 * radio can do.
862 */
863 ireq->i_val = 2*ic->ic_curchan->ic_maxregpower;
864 if (ireq->i_val > ic->ic_txpowlimit)
865 ireq->i_val = ic->ic_txpowlimit;
866 if (ireq->i_val > ic->ic_curchan->ic_maxpower)
867 ireq->i_val = ic->ic_curchan->ic_maxpower;
868 break;
869 case IEEE80211_IOC_WPA:
870 switch (vap->iv_flags & IEEE80211_F_WPA) {
871 case IEEE80211_F_WPA1:
872 ireq->i_val = 1;
873 break;
874 case IEEE80211_F_WPA2:
875 ireq->i_val = 2;
876 break;
877 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2:
878 ireq->i_val = 3;
879 break;
880 default:
881 ireq->i_val = 0;
882 break;
883 }
884 break;
885 case IEEE80211_IOC_CHANLIST:
886 error = ieee80211_ioctl_getchanlist(vap, ireq);
887 break;
888 case IEEE80211_IOC_ROAMING:
889 ireq->i_val = vap->iv_roaming;
890 break;
891 case IEEE80211_IOC_PRIVACY:
892 ireq->i_val = (vap->iv_flags & IEEE80211_F_PRIVACY) != 0;
893 break;
894 case IEEE80211_IOC_DROPUNENCRYPTED:
895 ireq->i_val = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0;
896 break;
897 case IEEE80211_IOC_COUNTERMEASURES:
898 ireq->i_val = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0;
899 break;
900 case IEEE80211_IOC_WME:
901 ireq->i_val = (vap->iv_flags & IEEE80211_F_WME) != 0;
902 break;
903 case IEEE80211_IOC_HIDESSID:
904 ireq->i_val = (vap->iv_flags & IEEE80211_F_HIDESSID) != 0;
905 break;
906 case IEEE80211_IOC_APBRIDGE:
907 ireq->i_val = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0;
908 break;
909 case IEEE80211_IOC_WPAKEY:
910 error = ieee80211_ioctl_getkey(vap, ireq);
911 break;
912 case IEEE80211_IOC_CHANINFO:
913 error = ieee80211_ioctl_getchaninfo(vap, ireq);
914 break;
915 case IEEE80211_IOC_BSSID:
916 if (ireq->i_len != IEEE80211_ADDR_LEN)
917 return EINVAL;
918 error = copyout(vap->iv_state == IEEE80211_S_RUN ?
919 vap->iv_bss->ni_bssid :
920 vap->iv_des_bssid,
921 ireq->i_data, ireq->i_len);
922 break;
923 case IEEE80211_IOC_WPAIE:
924 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type);
925 break;
926 case IEEE80211_IOC_WPAIE2:
927 error = ieee80211_ioctl_getwpaie(vap, ireq, ireq->i_type);
928 break;
929 case IEEE80211_IOC_SCAN_RESULTS:
930 error = ieee80211_ioctl_getscanresults(vap, ireq);
931 break;
932 case IEEE80211_IOC_STA_STATS:
933 error = ieee80211_ioctl_getstastats(vap, ireq);
934 break;
935 case IEEE80211_IOC_TXPOWMAX:
936 ireq->i_val = vap->iv_bss->ni_txpower;
937 break;
938 case IEEE80211_IOC_STA_TXPOW:
939 error = ieee80211_ioctl_getstatxpow(vap, ireq);
940 break;
941 case IEEE80211_IOC_STA_INFO:
942 error = ieee80211_ioctl_getstainfo(vap, ireq);
943 break;
944 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
945 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
946 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
947 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
948 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
949 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
950 error = ieee80211_ioctl_getwmeparam(vap, ireq);
951 break;
952 case IEEE80211_IOC_DTIM_PERIOD:
953 ireq->i_val = vap->iv_dtim_period;
954 break;
955 case IEEE80211_IOC_BEACON_INTERVAL:
956 /* NB: get from ic_bss for station mode */
957 ireq->i_val = vap->iv_bss->ni_intval;
958 break;
959 case IEEE80211_IOC_PUREG:
960 ireq->i_val = (vap->iv_flags & IEEE80211_F_PUREG) != 0;
961 break;
977 case IEEE80211_IOC_FF:
978 ireq->i_val = getathcap(vap, IEEE80211_F_FF);
979 break;
980 case IEEE80211_IOC_TURBOP:
981 ireq->i_val = getathcap(vap, IEEE80211_F_TURBOP);
982 break;
983 case IEEE80211_IOC_BGSCAN:
984 ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0;
985 break;
986 case IEEE80211_IOC_BGSCAN_IDLE:
987 ireq->i_val = vap->iv_bgscanidle*hz/1000; /* ms */
988 break;
989 case IEEE80211_IOC_BGSCAN_INTERVAL:
990 ireq->i_val = vap->iv_bgscanintvl/hz; /* seconds */
991 break;
992 case IEEE80211_IOC_SCANVALID:
993 ireq->i_val = vap->iv_scanvalid/hz; /* seconds */
994 break;
995 case IEEE80211_IOC_FRAGTHRESHOLD:
996 ireq->i_val = vap->iv_fragthreshold;
997 break;
998 case IEEE80211_IOC_MACCMD:
999 error = ieee80211_ioctl_getmaccmd(vap, ireq);
1000 break;
1001 case IEEE80211_IOC_BURST:
1002 ireq->i_val = (vap->iv_flags & IEEE80211_F_BURST) != 0;
1003 break;
1004 case IEEE80211_IOC_BMISSTHRESHOLD:
1005 ireq->i_val = vap->iv_bmissthreshold;
1006 break;
1007 case IEEE80211_IOC_CURCHAN:
1008 error = ieee80211_ioctl_getcurchan(vap, ireq);
1009 break;
1010 case IEEE80211_IOC_SHORTGI:
1011 ireq->i_val = 0;
1012 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI20)
1013 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20;
1014 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI40)
1015 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40;
1016 break;
1017 case IEEE80211_IOC_AMPDU:
1018 ireq->i_val = 0;
1019 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_TX)
1020 ireq->i_val |= 1;
1021 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_RX)
1022 ireq->i_val |= 2;
1023 break;
1024 case IEEE80211_IOC_AMPDU_LIMIT:
1025 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
1026 ireq->i_val = vap->iv_ampdu_rxmax;
1027 else if (vap->iv_state == IEEE80211_S_RUN)
1028 ireq->i_val = MS(vap->iv_bss->ni_htparam,
1029 IEEE80211_HTCAP_MAXRXAMPDU);
1030 else
1031 ireq->i_val = vap->iv_ampdu_limit;
1032 break;
1033 case IEEE80211_IOC_AMPDU_DENSITY:
1034 if (vap->iv_opmode == IEEE80211_M_STA &&
1035 vap->iv_state == IEEE80211_S_RUN)
1036 ireq->i_val = MS(vap->iv_bss->ni_htparam,
1037 IEEE80211_HTCAP_MPDUDENSITY);
1038 else
1039 ireq->i_val = vap->iv_ampdu_density;
1040 break;
1041 case IEEE80211_IOC_AMSDU:
1042 ireq->i_val = 0;
1043 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_TX)
1044 ireq->i_val |= 1;
1045 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_RX)
1046 ireq->i_val |= 2;
1047 break;
1048 case IEEE80211_IOC_AMSDU_LIMIT:
1049 ireq->i_val = vap->iv_amsdu_limit; /* XXX truncation? */
1050 break;
1051 case IEEE80211_IOC_PUREN:
1052 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_PUREN) != 0;
1053 break;
1054 case IEEE80211_IOC_DOTH:
1055 ireq->i_val = (vap->iv_flags & IEEE80211_F_DOTH) != 0;
1056 break;
1057 case IEEE80211_IOC_REGDOMAIN:
1058 error = ieee80211_ioctl_getregdomain(vap, ireq);
1059 break;
1060 case IEEE80211_IOC_ROAM:
1061 error = ieee80211_ioctl_getroam(vap, ireq);
1062 break;
1063 case IEEE80211_IOC_TXPARAMS:
1064 error = ieee80211_ioctl_gettxparams(vap, ireq);
1065 break;
1066 case IEEE80211_IOC_HTCOMPAT:
1067 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0;
1068 break;
1069 case IEEE80211_IOC_DWDS:
1070 ireq->i_val = (vap->iv_flags & IEEE80211_F_DWDS) != 0;
1071 break;
1072 case IEEE80211_IOC_INACTIVITY:
1073 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_INACT) != 0;
1074 break;
1075 case IEEE80211_IOC_APPIE:
1076 error = ieee80211_ioctl_getappie(vap, ireq);
1077 break;
1078 case IEEE80211_IOC_WPS:
1079 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_WPS) != 0;
1080 break;
1081 case IEEE80211_IOC_TSN:
1082 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_TSN) != 0;
1083 break;
1084 case IEEE80211_IOC_DFS:
1085 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DFS) != 0;
1086 break;
1087 case IEEE80211_IOC_DOTD:
1088 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DOTD) != 0;
1089 break;
1090 case IEEE80211_IOC_DEVCAPS:
1091 error = ieee80211_ioctl_getdevcaps(ic, ireq);
1092 break;
1093 case IEEE80211_IOC_HTPROTMODE:
1094 ireq->i_val = ic->ic_htprotmode;
1095 break;
1096 case IEEE80211_IOC_HTCONF:
1097 if (vap->iv_flags_ext & IEEE80211_FEXT_HT) {
1098 ireq->i_val = 1;
1099 if (vap->iv_flags_ext & IEEE80211_FEXT_USEHT40)
1100 ireq->i_val |= 2;
1101 } else
1102 ireq->i_val = 0;
1103 break;
1104 case IEEE80211_IOC_STA_VLAN:
1105 error = ieee80211_ioctl_getstavlan(vap, ireq);
1106 break;
1107 case IEEE80211_IOC_SMPS:
1108 if (vap->iv_opmode == IEEE80211_M_STA &&
1109 vap->iv_state == IEEE80211_S_RUN) {
1110 if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS)
1111 ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC;
1112 else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS)
1113 ireq->i_val = IEEE80211_HTCAP_SMPS_ENA;
1114 else
1115 ireq->i_val = IEEE80211_HTCAP_SMPS_OFF;
1116 } else
1117 ireq->i_val = vap->iv_htcaps & IEEE80211_HTCAP_SMPS;
1118 break;
1119 case IEEE80211_IOC_RIFS:
1120 if (vap->iv_opmode == IEEE80211_M_STA &&
1121 vap->iv_state == IEEE80211_S_RUN)
1122 ireq->i_val =
1123 (vap->iv_bss->ni_flags & IEEE80211_NODE_RIFS) != 0;
1124 else
1125 ireq->i_val =
1126 (vap->iv_flags_ext & IEEE80211_FEXT_RIFS) != 0;
1127 break;
1128 default:
1129 error = ieee80211_ioctl_getdefault(vap, ireq);
1130 break;
1131 }
1132 return error;
1133#undef MS
1134}
1135
1136static __noinline int
1137ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
1138{
1139 struct ieee80211req_key ik;
1140 struct ieee80211_node *ni;
1141 struct ieee80211_key *wk;
1142 uint16_t kid;
1143 int error, i;
1144
1145 if (ireq->i_len != sizeof(ik))
1146 return EINVAL;
1147 error = copyin(ireq->i_data, &ik, sizeof(ik));
1148 if (error)
1149 return error;
1150 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1151 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1152 if (ik.ik_keylen > sizeof(ik.ik_keydata))
1153 return E2BIG;
1154 kid = ik.ik_keyix;
1155 if (kid == IEEE80211_KEYIX_NONE) {
1156 /* XXX unicast keys currently must be tx/rx */
1157 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1158 return EINVAL;
1159 if (vap->iv_opmode == IEEE80211_M_STA) {
1160 ni = ieee80211_ref_node(vap->iv_bss);
1161 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1162 ieee80211_free_node(ni);
1163 return EADDRNOTAVAIL;
1164 }
1165 } else {
1166 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
1167 ik.ik_macaddr);
1168 if (ni == NULL)
1169 return ENOENT;
1170 }
1171 wk = &ni->ni_ucastkey;
1172 } else {
1173 if (kid >= IEEE80211_WEP_NKID)
1174 return EINVAL;
1175 wk = &vap->iv_nw_keys[kid];
1176 /*
1177 * Global slots start off w/o any assigned key index.
1178 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1179 */
1180 if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1181 wk->wk_keyix = kid;
1182 ni = NULL;
1183 }
1184 error = 0;
1185 ieee80211_key_update_begin(vap);
1186 if (ieee80211_crypto_newkey(vap, ik.ik_type, ik.ik_flags, wk)) {
1187 wk->wk_keylen = ik.ik_keylen;
1188 /* NB: MIC presence is implied by cipher type */
1189 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1190 wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1191 for (i = 0; i < IEEE80211_TID_SIZE; i++)
1192 wk->wk_keyrsc[i] = ik.ik_keyrsc;
1193 wk->wk_keytsc = 0; /* new key, reset */
1194 memset(wk->wk_key, 0, sizeof(wk->wk_key));
1195 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1196 IEEE80211_ADDR_COPY(wk->wk_macaddr,
1197 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr);
1198 if (!ieee80211_crypto_setkey(vap, wk))
1199 error = EIO;
1200 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1201 vap->iv_def_txkey = kid;
1202 } else
1203 error = ENXIO;
1204 ieee80211_key_update_end(vap);
1205 if (ni != NULL)
1206 ieee80211_free_node(ni);
1207 return error;
1208}
1209
1210static __noinline int
1211ieee80211_ioctl_delkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
1212{
1213 struct ieee80211req_del_key dk;
1214 int kid, error;
1215
1216 if (ireq->i_len != sizeof(dk))
1217 return EINVAL;
1218 error = copyin(ireq->i_data, &dk, sizeof(dk));
1219 if (error)
1220 return error;
1221 kid = dk.idk_keyix;
1222 /* XXX uint8_t -> uint16_t */
1223 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1224 struct ieee80211_node *ni;
1225
1226 if (vap->iv_opmode == IEEE80211_M_STA) {
1227 ni = ieee80211_ref_node(vap->iv_bss);
1228 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1229 ieee80211_free_node(ni);
1230 return EADDRNOTAVAIL;
1231 }
1232 } else {
1233 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
1234 dk.idk_macaddr);
1235 if (ni == NULL)
1236 return ENOENT;
1237 }
1238 /* XXX error return */
1239 ieee80211_node_delucastkey(ni);
1240 ieee80211_free_node(ni);
1241 } else {
1242 if (kid >= IEEE80211_WEP_NKID)
1243 return EINVAL;
1244 /* XXX error return */
1245 ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid]);
1246 }
1247 return 0;
1248}
1249
1250struct mlmeop {
1251 struct ieee80211vap *vap;
1252 int op;
1253 int reason;
1254};
1255
1256static void
1257mlmedebug(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
1258 int op, int reason)
1259{
1260#ifdef IEEE80211_DEBUG
1261 static const struct {
1262 int mask;
1263 const char *opstr;
1264 } ops[] = {
1265 { 0, "op#0" },
1266 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1267 IEEE80211_MSG_ASSOC, "assoc" },
1268 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1269 IEEE80211_MSG_ASSOC, "disassoc" },
1270 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1271 IEEE80211_MSG_AUTH, "deauth" },
1272 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1273 IEEE80211_MSG_AUTH, "authorize" },
1274 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1275 IEEE80211_MSG_AUTH, "unauthorize" },
1276 };
1277
1278 if (op == IEEE80211_MLME_AUTH) {
1279 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_IOCTL |
1280 IEEE80211_MSG_STATE | IEEE80211_MSG_AUTH, mac,
1281 "station authenticate %s via MLME (reason %d)",
1282 reason == IEEE80211_STATUS_SUCCESS ? "ACCEPT" : "REJECT",
1283 reason);
1284 } else if (!(IEEE80211_MLME_ASSOC <= op && op <= IEEE80211_MLME_AUTH)) {
1285 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, mac,
1286 "unknown MLME request %d (reason %d)", op, reason);
1287 } else if (reason == IEEE80211_STATUS_SUCCESS) {
1288 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
1289 "station %s via MLME", ops[op].opstr);
1290 } else {
1291 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
1292 "station %s via MLME (reason %d)", ops[op].opstr, reason);
1293 }
1294#endif /* IEEE80211_DEBUG */
1295}
1296
1297static void
1298domlme(void *arg, struct ieee80211_node *ni)
1299{
1300 struct mlmeop *mop = arg;
1301 struct ieee80211vap *vap = ni->ni_vap;
1302
1303 if (vap != mop->vap)
1304 return;
1305 /*
1306 * NB: if ni_associd is zero then the node is already cleaned
1307 * up and we don't need to do this (we're safely holding a
1308 * reference but should otherwise not modify it's state).
1309 */
1310 if (ni->ni_associd == 0)
1311 return;
1312 mlmedebug(vap, ni->ni_macaddr, mop->op, mop->reason);
1313 if (mop->op == IEEE80211_MLME_DEAUTH) {
1314 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
1315 mop->reason);
1316 } else {
1317 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
1318 mop->reason);
1319 }
1320 ieee80211_node_leave(ni);
1321}
1322
1323static int
1324setmlme_dropsta(struct ieee80211vap *vap,
1325 const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
1326{
1327 struct ieee80211com *ic = vap->iv_ic;
1328 struct ieee80211_node_table *nt = &ic->ic_sta;
1329 struct ieee80211_node *ni;
1330 int error = 0;
1331
1332 /* NB: the broadcast address means do 'em all */
1333 if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
1334 IEEE80211_NODE_LOCK(nt);
1335 ni = ieee80211_find_node_locked(nt, mac);
1336 if (ni != NULL) {
1337 domlme(mlmeop, ni);
1338 ieee80211_free_node(ni);
1339 } else
1340 error = ENOENT;
1341 IEEE80211_NODE_UNLOCK(nt);
1342 } else {
1343 ieee80211_iterate_nodes(nt, domlme, mlmeop);
1344 }
1345 return error;
1346}
1347
1348static __noinline int
1349setmlme_common(struct ieee80211vap *vap, int op,
1350 const uint8_t mac[IEEE80211_ADDR_LEN], int reason)
1351{
1352 struct ieee80211com *ic = vap->iv_ic;
1353 struct ieee80211_node_table *nt = &ic->ic_sta;
1354 struct ieee80211_node *ni;
1355 struct mlmeop mlmeop;
1356 int error;
1357
1358 error = 0;
1359 switch (op) {
1360 case IEEE80211_MLME_DISASSOC:
1361 case IEEE80211_MLME_DEAUTH:
1362 switch (vap->iv_opmode) {
1363 case IEEE80211_M_STA:
1364 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason);
1365 /* XXX not quite right */
1366 ieee80211_new_state(vap, IEEE80211_S_INIT, reason);
1367 break;
1368 case IEEE80211_M_HOSTAP:
1369 mlmeop.vap = vap;
1370 mlmeop.op = op;
1371 mlmeop.reason = reason;
1372 error = setmlme_dropsta(vap, mac, &mlmeop);
1373 break;
1374 case IEEE80211_M_WDS:
1375 /* XXX user app should send raw frame? */
1376 if (op != IEEE80211_MLME_DEAUTH) {
1377 error = EINVAL;
1378 break;
1379 }
1380#if 0
1381 /* XXX accept any address, simplifies user code */
1382 if (!IEEE80211_ADDR_EQ(mac, vap->iv_bss->ni_macaddr)) {
1383 error = EINVAL;
1384 break;
1385 }
1386#endif
1387 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason);
1388 ni = ieee80211_ref_node(vap->iv_bss);
1389 IEEE80211_SEND_MGMT(ni,
1390 IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
1391 ieee80211_free_node(ni);
1392 break;
1393 default:
1394 error = EINVAL;
1395 break;
1396 }
1397 break;
1398 case IEEE80211_MLME_AUTHORIZE:
1399 case IEEE80211_MLME_UNAUTHORIZE:
1400 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
1401 vap->iv_opmode != IEEE80211_M_WDS) {
1402 error = EINVAL;
1403 break;
1404 }
1405 IEEE80211_NODE_LOCK(nt);
1406 ni = ieee80211_find_vap_node_locked(nt, vap, mac);
1407 if (ni != NULL) {
1408 mlmedebug(vap, mac, op, reason);
1409 if (op == IEEE80211_MLME_AUTHORIZE)
1410 ieee80211_node_authorize(ni);
1411 else
1412 ieee80211_node_unauthorize(ni);
1413 ieee80211_free_node(ni);
1414 } else
1415 error = ENOENT;
1416 IEEE80211_NODE_UNLOCK(nt);
1417 break;
1418 case IEEE80211_MLME_AUTH:
1419 if (vap->iv_opmode != IEEE80211_M_HOSTAP) {
1420 error = EINVAL;
1421 break;
1422 }
1423 IEEE80211_NODE_LOCK(nt);
1424 ni = ieee80211_find_vap_node_locked(nt, vap, mac);
1425 if (ni != NULL) {
1426 mlmedebug(vap, mac, op, reason);
1427 if (reason == IEEE80211_STATUS_SUCCESS) {
1428 IEEE80211_SEND_MGMT(ni,
1429 IEEE80211_FC0_SUBTYPE_AUTH, 2);
1430 /*
1431 * For shared key auth, just continue the
1432 * exchange. Otherwise when 802.1x is not in
1433 * use mark the port authorized at this point
1434 * so traffic can flow.
1435 */
1436 if (ni->ni_authmode != IEEE80211_AUTH_8021X &&
1437 ni->ni_challenge == NULL)
1438 ieee80211_node_authorize(ni);
1439 } else {
1440 vap->iv_stats.is_rx_acl++;
1441 ieee80211_send_error(ni, ni->ni_macaddr,
1442 IEEE80211_FC0_SUBTYPE_AUTH, 2|(reason<<16));
1443 ieee80211_node_leave(ni);
1444 }
1445 ieee80211_free_node(ni);
1446 } else
1447 error = ENOENT;
1448 IEEE80211_NODE_UNLOCK(nt);
1449 break;
1450 default:
1451 error = EINVAL;
1452 break;
1453 }
1454 return error;
1455}
1456
1457struct scanlookup {
1458 const uint8_t *mac;
1459 int esslen;
1460 const uint8_t *essid;
1461 const struct ieee80211_scan_entry *se;
1462};
1463
1464/*
1465 * Match mac address and any ssid.
1466 */
1467static void
1468mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1469{
1470 struct scanlookup *look = arg;
1471
1472 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1473 return;
1474 if (look->esslen != 0) {
1475 if (se->se_ssid[1] != look->esslen)
1476 return;
1477 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1478 return;
1479 }
1480 look->se = se;
1481}
1482
1483static __noinline int
1484setmlme_assoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
1485 int ssid_len, const uint8_t ssid[IEEE80211_NWID_LEN])
1486{
1487 struct scanlookup lookup;
1488
1489 /* XXX ibss/ahdemo */
1490 if (vap->iv_opmode != IEEE80211_M_STA)
1491 return EINVAL;
1492
1493 /* NB: this is racey if roaming is !manual */
1494 lookup.se = NULL;
1495 lookup.mac = mac;
1496 lookup.esslen = ssid_len;
1497 lookup.essid = ssid;
1498 ieee80211_scan_iterate(vap, mlmelookup, &lookup);
1499 if (lookup.se == NULL)
1500 return ENOENT;
1501 mlmedebug(vap, mac, IEEE80211_MLME_ASSOC, 0);
1502 if (!ieee80211_sta_join(vap, lookup.se->se_chan, lookup.se))
1503 return EIO; /* XXX unique but could be better */
1504 return 0;
1505}
1506
1507static __noinline int
1508ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq)
1509{
1510 struct ieee80211req_mlme mlme;
1511 int error;
1512
1513 if (ireq->i_len != sizeof(mlme))
1514 return EINVAL;
1515 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1516 if (error)
1517 return error;
1518 if (mlme.im_op == IEEE80211_MLME_ASSOC)
1519 return setmlme_assoc(vap, mlme.im_macaddr,
1520 vap->iv_des_ssid[0].len, vap->iv_des_ssid[0].ssid);
1521 else
1522 return setmlme_common(vap, mlme.im_op,
1523 mlme.im_macaddr, mlme.im_reason);
1524}
1525
1526static __noinline int
1527ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq)
1528{
1529 uint8_t mac[IEEE80211_ADDR_LEN];
1530 const struct ieee80211_aclator *acl = vap->iv_acl;
1531 int error;
1532
1533 if (ireq->i_len != sizeof(mac))
1534 return EINVAL;
1535 error = copyin(ireq->i_data, mac, ireq->i_len);
1536 if (error)
1537 return error;
1538 if (acl == NULL) {
1539 acl = ieee80211_aclator_get("mac");
1540 if (acl == NULL || !acl->iac_attach(vap))
1541 return EINVAL;
1542 vap->iv_acl = acl;
1543 }
1544 if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1545 acl->iac_add(vap, mac);
1546 else
1547 acl->iac_remove(vap, mac);
1548 return 0;
1549}
1550
1551static __noinline int
1552ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
1553{
1554 const struct ieee80211_aclator *acl = vap->iv_acl;
1555
1556 switch (ireq->i_val) {
1557 case IEEE80211_MACCMD_POLICY_OPEN:
1558 case IEEE80211_MACCMD_POLICY_ALLOW:
1559 case IEEE80211_MACCMD_POLICY_DENY:
1560 case IEEE80211_MACCMD_POLICY_RADIUS:
1561 if (acl == NULL) {
1562 acl = ieee80211_aclator_get("mac");
1563 if (acl == NULL || !acl->iac_attach(vap))
1564 return EINVAL;
1565 vap->iv_acl = acl;
1566 }
1567 acl->iac_setpolicy(vap, ireq->i_val);
1568 break;
1569 case IEEE80211_MACCMD_FLUSH:
1570 if (acl != NULL)
1571 acl->iac_flush(vap);
1572 /* NB: silently ignore when not in use */
1573 break;
1574 case IEEE80211_MACCMD_DETACH:
1575 if (acl != NULL) {
1576 vap->iv_acl = NULL;
1577 acl->iac_detach(vap);
1578 }
1579 break;
1580 default:
1581 if (acl == NULL)
1582 return EINVAL;
1583 else
1584 return acl->iac_setioctl(vap, ireq);
1585 }
1586 return 0;
1587}
1588
1589static __noinline int
1590ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
1591{
1592 struct ieee80211com *ic = vap->iv_ic;
1593 uint8_t *chanlist, *list;
1594 int i, nchan, maxchan, error;
1595
1596 if (ireq->i_len > sizeof(ic->ic_chan_active))
1597 ireq->i_len = sizeof(ic->ic_chan_active);
1598 list = malloc(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP,
1599 M_NOWAIT | M_ZERO);
1600 if (list == NULL)
1601 return ENOMEM;
1602 error = copyin(ireq->i_data, list, ireq->i_len);
1603 if (error)
1604 return error;
1605 nchan = 0;
1606 chanlist = list + ireq->i_len; /* NB: zero'd already */
1607 maxchan = ireq->i_len * NBBY;
1608 for (i = 0; i < ic->ic_nchans; i++) {
1609 const struct ieee80211_channel *c = &ic->ic_channels[i];
1610 /*
1611 * Calculate the intersection of the user list and the
1612 * available channels so users can do things like specify
1613 * 1-255 to get all available channels.
1614 */
1615 if (c->ic_ieee < maxchan && isset(list, c->ic_ieee)) {
1616 setbit(chanlist, c->ic_ieee);
1617 nchan++;
1618 }
1619 }
1620 if (nchan == 0)
1621 return EINVAL;
1622 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1623 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1624 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1625 memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES);
1626 ieee80211_scan_flush(vap);
1627 free(list, M_TEMP);
1628 return ENETRESET;
1629}
1630
1631static __noinline int
1632ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
1633{
1634 struct ieee80211_node *ni;
1635 uint8_t macaddr[IEEE80211_ADDR_LEN];
1636 int error;
1637
1638 /*
1639 * NB: we could copyin ieee80211req_sta_stats so apps
1640 * could make selective changes but that's overkill;
1641 * just clear all stats for now.
1642 */
1643 if (ireq->i_len < IEEE80211_ADDR_LEN)
1644 return EINVAL;
1645 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1646 if (error != 0)
1647 return error;
1648 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
1649 if (ni == NULL)
1650 return ENOENT;
1651 /* XXX require ni_vap == vap? */
1652 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1653 ieee80211_free_node(ni);
1654 return 0;
1655}
1656
1657static __noinline int
1658ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
1659{
1660 struct ieee80211_node *ni;
1661 struct ieee80211req_sta_txpow txpow;
1662 int error;
1663
1664 if (ireq->i_len != sizeof(txpow))
1665 return EINVAL;
1666 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1667 if (error != 0)
1668 return error;
1669 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr);
1670 if (ni == NULL)
1671 return ENOENT;
1672 ni->ni_txpower = txpow.it_txpow;
1673 ieee80211_free_node(ni);
1674 return error;
1675}
1676
1677static __noinline int
1678ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
1679{
1680 struct ieee80211com *ic = vap->iv_ic;
1681 struct ieee80211_wme_state *wme = &ic->ic_wme;
1682 struct wmeParams *wmep, *chanp;
1683 int isbss, ac;
1684
1685 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1686 return EOPNOTSUPP;
1687
1688 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1689 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1690 if (ac >= WME_NUM_AC)
1691 ac = WME_AC_BE;
1692 if (isbss) {
1693 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1694 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1695 } else {
1696 chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1697 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1698 }
1699 switch (ireq->i_type) {
1700 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
1701 if (isbss) {
1702 wmep->wmep_logcwmin = ireq->i_val;
1703 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1704 chanp->wmep_logcwmin = ireq->i_val;
1705 } else {
1706 wmep->wmep_logcwmin = chanp->wmep_logcwmin =
1707 ireq->i_val;
1708 }
1709 break;
1710 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
1711 if (isbss) {
1712 wmep->wmep_logcwmax = ireq->i_val;
1713 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1714 chanp->wmep_logcwmax = ireq->i_val;
1715 } else {
1716 wmep->wmep_logcwmax = chanp->wmep_logcwmax =
1717 ireq->i_val;
1718 }
1719 break;
1720 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1721 if (isbss) {
1722 wmep->wmep_aifsn = ireq->i_val;
1723 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1724 chanp->wmep_aifsn = ireq->i_val;
1725 } else {
1726 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
1727 }
1728 break;
1729 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1730 if (isbss) {
1731 wmep->wmep_txopLimit = ireq->i_val;
1732 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1733 chanp->wmep_txopLimit = ireq->i_val;
1734 } else {
1735 wmep->wmep_txopLimit = chanp->wmep_txopLimit =
1736 ireq->i_val;
1737 }
1738 break;
1739 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1740 wmep->wmep_acm = ireq->i_val;
1741 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1742 chanp->wmep_acm = ireq->i_val;
1743 break;
1744 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
1745 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
1746 (ireq->i_val) == 0;
1747 break;
1748 }
1749 ieee80211_wme_updateparams(vap);
1750 return 0;
1751}
1752
1753static int
1754find11gchannel(struct ieee80211com *ic, int start, int freq)
1755{
1756 const struct ieee80211_channel *c;
1757 int i;
1758
1759 for (i = start+1; i < ic->ic_nchans; i++) {
1760 c = &ic->ic_channels[i];
1761 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1762 return 1;
1763 }
1764 /* NB: should not be needed but in case things are mis-sorted */
1765 for (i = 0; i < start; i++) {
1766 c = &ic->ic_channels[i];
1767 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1768 return 1;
1769 }
1770 return 0;
1771}
1772
1773static struct ieee80211_channel *
1774findchannel(struct ieee80211com *ic, int ieee, int mode)
1775{
1776 static const u_int chanflags[IEEE80211_MODE_MAX] = {
1777 [IEEE80211_MODE_AUTO] = 0,
1778 [IEEE80211_MODE_11A] = IEEE80211_CHAN_A,
1779 [IEEE80211_MODE_11B] = IEEE80211_CHAN_B,
1780 [IEEE80211_MODE_11G] = IEEE80211_CHAN_G,
1781 [IEEE80211_MODE_FH] = IEEE80211_CHAN_FHSS,
1782 [IEEE80211_MODE_TURBO_A] = IEEE80211_CHAN_108A,
1783 [IEEE80211_MODE_TURBO_G] = IEEE80211_CHAN_108G,
1784 [IEEE80211_MODE_STURBO_A] = IEEE80211_CHAN_STURBO,
1785 [IEEE80211_MODE_HALF] = IEEE80211_CHAN_HALF,
1786 [IEEE80211_MODE_QUARTER] = IEEE80211_CHAN_QUARTER,
1787 /* NB: handled specially below */
1788 [IEEE80211_MODE_11NA] = IEEE80211_CHAN_A,
1789 [IEEE80211_MODE_11NG] = IEEE80211_CHAN_G,
1790 };
1791 u_int modeflags;
1792 int i;
1793
1794 modeflags = chanflags[mode];
1795 for (i = 0; i < ic->ic_nchans; i++) {
1796 struct ieee80211_channel *c = &ic->ic_channels[i];
1797
1798 if (c->ic_ieee != ieee)
1799 continue;
1800 if (mode == IEEE80211_MODE_AUTO) {
1801 /* ignore turbo channels for autoselect */
1802 if (IEEE80211_IS_CHAN_TURBO(c))
1803 continue;
1804 /*
1805 * XXX special-case 11b/g channels so we
1806 * always select the g channel if both
1807 * are present.
1808 * XXX prefer HT to non-HT?
1809 */
1810 if (!IEEE80211_IS_CHAN_B(c) ||
1811 !find11gchannel(ic, i, c->ic_freq))
1812 return c;
1813 } else {
1814 /* must check HT specially */
1815 if ((mode == IEEE80211_MODE_11NA ||
1816 mode == IEEE80211_MODE_11NG) &&
1817 !IEEE80211_IS_CHAN_HT(c))
1818 continue;
1819 if ((c->ic_flags & modeflags) == modeflags)
1820 return c;
1821 }
1822 }
1823 return NULL;
1824}
1825
1826/*
1827 * Check the specified against any desired mode (aka netband).
1828 * This is only used (presently) when operating in hostap mode
1829 * to enforce consistency.
1830 */
1831static int
1832check_mode_consistency(const struct ieee80211_channel *c, int mode)
1833{
1834 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1835
1836 switch (mode) {
1837 case IEEE80211_MODE_11B:
1838 return (IEEE80211_IS_CHAN_B(c));
1839 case IEEE80211_MODE_11G:
1840 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1841 case IEEE80211_MODE_11A:
1842 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1843 case IEEE80211_MODE_STURBO_A:
1844 return (IEEE80211_IS_CHAN_STURBO(c));
1845 case IEEE80211_MODE_11NA:
1846 return (IEEE80211_IS_CHAN_HTA(c));
1847 case IEEE80211_MODE_11NG:
1848 return (IEEE80211_IS_CHAN_HTG(c));
1849 }
1850 return 1;
1851
1852}
1853
1854/*
1855 * Common code to set the current channel. If the device
1856 * is up and running this may result in an immediate channel
1857 * change or a kick of the state machine.
1858 */
1859static int
1860setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
1861{
1862 struct ieee80211com *ic = vap->iv_ic;
1863 int error;
1864
1865 if (c != IEEE80211_CHAN_ANYC) {
1866 if (IEEE80211_IS_CHAN_RADAR(c))
1867 return EBUSY; /* XXX better code? */
1868 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
1869 if (IEEE80211_IS_CHAN_NOHOSTAP(c))
1870 return EINVAL;
1871 if (!check_mode_consistency(c, vap->iv_des_mode))
1872 return EINVAL;
1873 } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
1874 if (IEEE80211_IS_CHAN_NOADHOC(c))
1875 return EINVAL;
1876 }
1877 if (vap->iv_state == IEEE80211_S_RUN &&
1878 vap->iv_bss->ni_chan == c)
1879 return 0; /* NB: nothing to do */
1880 }
1881 vap->iv_des_chan = c;
1882
1883 error = 0;
1884 if (vap->iv_opmode == IEEE80211_M_MONITOR &&
1885 vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
1886 /*
1887 * Monitor mode can switch directly.
1888 */
1889 if (IFNET_IS_UP_RUNNING(vap->iv_ifp)) {
1890 /* XXX need state machine for other vap's to follow */
1891 ieee80211_setcurchan(ic, vap->iv_des_chan);
1892 vap->iv_bss->ni_chan = ic->ic_curchan;
1893 } else
1894 ic->ic_curchan = vap->iv_des_chan;
1895 } else {
1896 /*
1897 * Need to go through the state machine in case we
1898 * need to reassociate or the like. The state machine
1899 * will pickup the desired channel and avoid scanning.
1900 */
1901 if (IS_UP_AUTO(vap))
1902 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1903 else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
1904 /*
1905 * When not up+running and a real channel has
1906 * been specified fix the current channel so
1907 * there is immediate feedback; e.g. via ifconfig.
1908 */
1909 ic->ic_curchan = vap->iv_des_chan;
1910 }
1911 }
1912 return error;
1913}
1914
1915/*
1916 * Old api for setting the current channel; this is
1917 * deprecated because channel numbers are ambiguous.
1918 */
1919static __noinline int
1920ieee80211_ioctl_setchannel(struct ieee80211vap *vap,
1921 const struct ieee80211req *ireq)
1922{
1923 struct ieee80211com *ic = vap->iv_ic;
1924 struct ieee80211_channel *c;
1925
1926 /* XXX 0xffff overflows 16-bit signed */
1927 if (ireq->i_val == 0 ||
1928 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1929 c = IEEE80211_CHAN_ANYC;
1930 } else {
1931 struct ieee80211_channel *c2;
1932
1933 c = findchannel(ic, ireq->i_val, vap->iv_des_mode);
1934 if (c == NULL) {
1935 c = findchannel(ic, ireq->i_val,
1936 IEEE80211_MODE_AUTO);
1937 if (c == NULL)
1938 return EINVAL;
1939 }
1940 /*
1941 * Fine tune channel selection based on desired mode:
1942 * if 11b is requested, find the 11b version of any
1943 * 11g channel returned,
1944 * if static turbo, find the turbo version of any
1945 * 11a channel return,
1946 * if 11na is requested, find the ht version of any
1947 * 11a channel returned,
1948 * if 11ng is requested, find the ht version of any
1949 * 11g channel returned,
1950 * otherwise we should be ok with what we've got.
1951 */
1952 switch (vap->iv_des_mode) {
1953 case IEEE80211_MODE_11B:
1954 if (IEEE80211_IS_CHAN_ANYG(c)) {
1955 c2 = findchannel(ic, ireq->i_val,
1956 IEEE80211_MODE_11B);
1957 /* NB: should not happen, =>'s 11g w/o 11b */
1958 if (c2 != NULL)
1959 c = c2;
1960 }
1961 break;
1962 case IEEE80211_MODE_TURBO_A:
1963 if (IEEE80211_IS_CHAN_A(c)) {
1964 c2 = findchannel(ic, ireq->i_val,
1965 IEEE80211_MODE_TURBO_A);
1966 if (c2 != NULL)
1967 c = c2;
1968 }
1969 break;
1970 case IEEE80211_MODE_11NA:
1971 if (IEEE80211_IS_CHAN_A(c)) {
1972 c2 = findchannel(ic, ireq->i_val,
1973 IEEE80211_MODE_11NA);
1974 if (c2 != NULL)
1975 c = c2;
1976 }
1977 break;
1978 case IEEE80211_MODE_11NG:
1979 if (IEEE80211_IS_CHAN_ANYG(c)) {
1980 c2 = findchannel(ic, ireq->i_val,
1981 IEEE80211_MODE_11NG);
1982 if (c2 != NULL)
1983 c = c2;
1984 }
1985 break;
1986 default: /* NB: no static turboG */
1987 break;
1988 }
1989 }
1990 return setcurchan(vap, c);
1991}
1992
1993/*
1994 * New/current api for setting the current channel; a complete
1995 * channel description is provide so there is no ambiguity in
1996 * identifying the channel.
1997 */
1998static __noinline int
1999ieee80211_ioctl_setcurchan(struct ieee80211vap *vap,
2000 const struct ieee80211req *ireq)
2001{
2002 struct ieee80211com *ic = vap->iv_ic;
2003 struct ieee80211_channel chan, *c;
2004 int error;
2005
2006 if (ireq->i_len != sizeof(chan))
2007 return EINVAL;
2008 error = copyin(ireq->i_data, &chan, sizeof(chan));
2009 if (error != 0)
2010 return error;
2011 /* XXX 0xffff overflows 16-bit signed */
2012 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
2013 c = IEEE80211_CHAN_ANYC;
2014 } else {
2015 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
2016 if (c == NULL)
2017 return EINVAL;
2018 }
2019 return setcurchan(vap, c);
2020}
2021
2022static __noinline int
2023ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
2024 const struct ieee80211req *ireq)
2025{
2026 struct ieee80211_regdomain_req *reg;
2027 int nchans, error;
2028
2029 nchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_regdomain_req)) /
2030 sizeof(struct ieee80211_channel));
2031 if (!(1 <= nchans && nchans <= IEEE80211_CHAN_MAX)) {
2032 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2033 "%s: bad # chans, i_len %d nchans %d\n", __func__,
2034 ireq->i_len, nchans);
2035 return EINVAL;
2036 }
2037 reg = (struct ieee80211_regdomain_req *)
2038 malloc(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP, M_NOWAIT);
2039 if (reg == NULL) {
2040 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2041 "%s: no memory, nchans %d\n", __func__, nchans);
2042 return ENOMEM;
2043 }
2044 error = copyin(ireq->i_data, reg, IEEE80211_REGDOMAIN_SIZE(nchans));
2045 if (error == 0) {
2046 /* NB: validate inline channel count against storage size */
2047 if (reg->chaninfo.ic_nchans != nchans) {
2048 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2049 "%s: chan cnt mismatch, %d != %d\n", __func__,
2050 reg->chaninfo.ic_nchans, nchans);
2051 error = EINVAL;
2052 } else
2053 error = ieee80211_setregdomain(vap, reg);
2054 }
2055 free(reg, M_TEMP);
2056
2057 return (error == 0 ? ENETRESET : error);
2058}
2059
2060static int
2061ieee80211_ioctl_setroam(struct ieee80211vap *vap,
2062 const struct ieee80211req *ireq)
2063{
2064 if (ireq->i_len != sizeof(vap->iv_roamparms))
2065 return EINVAL;
2066 /* XXX validate params */
2067 /* XXX? ENETRESET to push to device? */
2068 return copyin(ireq->i_data, vap->iv_roamparms,
2069 sizeof(vap->iv_roamparms));
2070}
2071
2072static int
2073checkrate(const struct ieee80211_rateset *rs, int rate)
2074{
2075 int i;
2076
2077 if (rate == IEEE80211_FIXED_RATE_NONE)
2078 return 1;
2079 for (i = 0; i < rs->rs_nrates; i++)
2080 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
2081 return 1;
2082 return 0;
2083}
2084
2085static int
2086checkmcs(int mcs)
2087{
2088 if (mcs == IEEE80211_FIXED_RATE_NONE)
2089 return 1;
2090 if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */
2091 return 0;
2092 return (mcs & 0x7f) <= 15; /* XXX could search ht rate set */
2093}
2094
2095static __noinline int
2096ieee80211_ioctl_settxparams(struct ieee80211vap *vap,
2097 const struct ieee80211req *ireq)
2098{
2099 struct ieee80211com *ic = vap->iv_ic;
2100 struct ieee80211_txparams_req parms; /* XXX stack use? */
2101 struct ieee80211_txparam *src, *dst;
2102 const struct ieee80211_rateset *rs;
2103 int error, mode, changed, is11n, nmodes;
2104
2105 /* NB: accept short requests for backwards compat */
2106 if (ireq->i_len > sizeof(parms))
2107 return EINVAL;
2108 error = copyin(ireq->i_data, &parms, ireq->i_len);
2109 if (error != 0)
2110 return error;
2111 nmodes = ireq->i_len / sizeof(struct ieee80211_txparam);
2112 changed = 0;
2113 /* validate parameters and check if anything changed */
2114 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
2115 if (isclr(ic->ic_modecaps, mode))
2116 continue;
2117 src = &parms.params[mode];
2118 dst = &vap->iv_txparms[mode];
2119 rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */
2120 is11n = (mode == IEEE80211_MODE_11NA ||
2121 mode == IEEE80211_MODE_11NG);
2122 if (src->ucastrate != dst->ucastrate) {
2123 if (!checkrate(rs, src->ucastrate) &&
2124 (!is11n || !checkmcs(src->ucastrate)))
2125 return EINVAL;
2126 changed++;
2127 }
2128 if (src->mcastrate != dst->mcastrate) {
2129 if (!checkrate(rs, src->mcastrate) &&
2130 (!is11n || !checkmcs(src->mcastrate)))
2131 return EINVAL;
2132 changed++;
2133 }
2134 if (src->mgmtrate != dst->mgmtrate) {
2135 if (!checkrate(rs, src->mgmtrate) &&
2136 (!is11n || !checkmcs(src->mgmtrate)))
2137 return EINVAL;
2138 changed++;
2139 }
2140 if (src->maxretry != dst->maxretry) /* NB: no bounds */
2141 changed++;
2142 }
2143 if (changed) {
2144 /*
2145 * Copy new parameters in place and notify the
2146 * driver so it can push state to the device.
2147 */
2148 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
2149 if (isset(ic->ic_modecaps, mode))
2150 vap->iv_txparms[mode] = parms.params[mode];
2151 }
2152 /* XXX could be more intelligent,
2153 e.g. don't reset if setting not being used */
2154 return ENETRESET;
2155 }
2156 return 0;
2157}
2158
2159/*
2160 * Application Information Element support.
2161 */
2162static int
2163setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
2164{
2165 struct ieee80211_appie *app = *aie;
2166 struct ieee80211_appie *napp;
2167 int error;
2168
2169 if (ireq->i_len == 0) { /* delete any existing ie */
2170 if (app != NULL) {
2171 *aie = NULL; /* XXX racey */
2172 free(app, M_80211_NODE_IE);
2173 }
2174 return 0;
2175 }
2176 if (!(2 <= ireq->i_len && ireq->i_len <= IEEE80211_MAX_APPIE))
2177 return EINVAL;
2178 /*
2179 * Allocate a new appie structure and copy in the user data.
2180 * When done swap in the new structure. Note that we do not
2181 * guard against users holding a ref to the old structure;
2182 * this must be handled outside this code.
2183 *
2184 * XXX bad bad bad
2185 */
2186 napp = (struct ieee80211_appie *) malloc(
2187 sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE, M_NOWAIT);
2188 if (napp == NULL)
2189 return ENOMEM;
2190 /* XXX holding ic lock */
2191 error = copyin(ireq->i_data, napp->ie_data, ireq->i_len);
2192 if (error) {
2193 free(napp, M_80211_NODE_IE);
2194 return error;
2195 }
2196 napp->ie_len = ireq->i_len;
2197 *aie = napp;
2198 if (app != NULL)
2199 free(app, M_80211_NODE_IE);
2200 return 0;
2201}
2202
2203static void
2204setwparsnie(struct ieee80211vap *vap, uint8_t *ie, int space)
2205{
2206 /* validate data is present as best we can */
2207 if (space == 0 || 2+ie[1] > space)
2208 return;
2209 if (ie[0] == IEEE80211_ELEMID_VENDOR)
2210 vap->iv_wpa_ie = ie;
2211 else if (ie[0] == IEEE80211_ELEMID_RSN)
2212 vap->iv_rsn_ie = ie;
2213}
2214
2215static __noinline int
2216ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap,
2217 const struct ieee80211req *ireq, int fc0)
2218{
2219 int error;
2220
2221 IEEE80211_LOCK_ASSERT(vap->iv_ic);
2222
2223 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) {
2224 case IEEE80211_FC0_SUBTYPE_BEACON:
2225 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2226 vap->iv_opmode != IEEE80211_M_IBSS) {
2227 error = EINVAL;
2228 break;
2229 }
2230 error = setappie(&vap->iv_appie_beacon, ireq);
2231 if (error == 0)
2232 ieee80211_beacon_notify(vap, IEEE80211_BEACON_APPIE);
2233 break;
2234 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
2235 error = setappie(&vap->iv_appie_proberesp, ireq);
2236 break;
2237 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
2238 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
2239 error = setappie(&vap->iv_appie_assocresp, ireq);
2240 else
2241 error = EINVAL;
2242 break;
2243 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
2244 error = setappie(&vap->iv_appie_probereq, ireq);
2245 break;
2246 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
2247 if (vap->iv_opmode == IEEE80211_M_STA)
2248 error = setappie(&vap->iv_appie_assocreq, ireq);
2249 else
2250 error = EINVAL;
2251 break;
2252 case (IEEE80211_APPIE_WPA & IEEE80211_FC0_SUBTYPE_MASK):
2253 error = setappie(&vap->iv_appie_wpa, ireq);
2254 if (error == 0) {
2255 /*
2256 * Must split single blob of data into separate
2257 * WPA and RSN ie's because they go in different
2258 * locations in the mgt frames.
2259 * XXX use IEEE80211_IOC_WPA2 so user code does split
2260 */
2261 vap->iv_wpa_ie = NULL;
2262 vap->iv_rsn_ie = NULL;
2263 if (vap->iv_appie_wpa != NULL) {
2264 struct ieee80211_appie *appie =
2265 vap->iv_appie_wpa;
2266 uint8_t *data = appie->ie_data;
2267
2268 /* XXX ie length validate is painful, cheat */
2269 setwparsnie(vap, data, appie->ie_len);
2270 setwparsnie(vap, data + 2 + data[1],
2271 appie->ie_len - (2 + data[1]));
2272 }
2273 if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
2274 vap->iv_opmode == IEEE80211_M_IBSS) {
2275 /*
2276 * Must rebuild beacon frame as the update
2277 * mechanism doesn't handle WPA/RSN ie's.
2278 * Could extend it but it doesn't normally
2279 * change; this is just to deal with hostapd
2280 * plumbing the ie after the interface is up.
2281 */
2282 error = ENETRESET;
2283 }
2284 }
2285 break;
2286 default:
2287 error = EINVAL;
2288 break;
2289 }
2290 return error;
2291}
2292
2293static __noinline int
2294ieee80211_ioctl_setappie(struct ieee80211vap *vap,
2295 const struct ieee80211req *ireq)
2296{
2297 struct ieee80211com *ic = vap->iv_ic;
2298 int error;
2299 uint8_t fc0;
2300
2301 fc0 = ireq->i_val & 0xff;
2302 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
2303 return EINVAL;
2304 /* NB: could check iv_opmode and reject but hardly worth the effort */
2305 IEEE80211_LOCK(ic);
2306 error = ieee80211_ioctl_setappie_locked(vap, ireq, fc0);
2307 IEEE80211_UNLOCK(ic);
2308 return error;
2309}
2310
2311static __noinline int
2312ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq)
2313{
2314 struct ieee80211com *ic = vap->iv_ic;
2315 struct ieee80211_chanswitch_req csr;
2316 struct ieee80211_channel *c;
2317 int error;
2318
2319 if (ireq->i_len != sizeof(csr))
2320 return EINVAL;
2321 error = copyin(ireq->i_data, &csr, sizeof(csr));
2322 if (error != 0)
2323 return error;
2324 if ((vap->iv_flags & IEEE80211_F_DOTH) == 0)
2325 return EINVAL;
2326 c = ieee80211_find_channel(ic,
2327 csr.csa_chan.ic_freq, csr.csa_chan.ic_flags);
2328 if (c == NULL)
2329 return ENOENT;
2330 IEEE80211_LOCK(ic);
2331 if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0)
2332 ieee80211_csa_startswitch(ic, c, csr.csa_mode, csr.csa_count);
2333 else
2334 error = EBUSY;
2335 IEEE80211_UNLOCK(ic);
2336 return error;
2337}
2338
2339static __noinline int
2340ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
2341{
2342#define IEEE80211_IOC_SCAN_FLAGS \
2343 (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \
2344 IEEE80211_IOC_SCAN_PICK1ST | IEEE80211_IOC_SCAN_BGSCAN | \
2345 IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOBCAST | \
2346 IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \
2347 IEEE80211_IOC_SCAN_CHECK)
2348 struct ieee80211com *ic = vap->iv_ic;
2349 struct ieee80211_scan_req sr; /* XXX off stack? */
2350 int error, i;
2351
2352 /* NB: parent must be running */
2353 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
2354 return ENXIO;
2355
2356 if (ireq->i_len != sizeof(sr))
2357 return EINVAL;
2358 error = copyin(ireq->i_data, &sr, sizeof(sr));
2359 if (error != 0)
2360 return error;
2361 /* convert duration */
2362 if (sr.sr_duration == IEEE80211_IOC_SCAN_FOREVER)
2363 sr.sr_duration = IEEE80211_SCAN_FOREVER;
2364 else {
2365 if (sr.sr_duration < IEEE80211_IOC_SCAN_DURATION_MIN ||
2366 sr.sr_duration > IEEE80211_IOC_SCAN_DURATION_MAX)
2367 return EINVAL;
2368 sr.sr_duration = msecs_to_ticks(sr.sr_duration);
2369 if (sr.sr_duration < 1)
2370 sr.sr_duration = 1;
2371 }
2372 /* convert min/max channel dwell */
2373 if (sr.sr_mindwell != 0) {
2374 sr.sr_mindwell = msecs_to_ticks(sr.sr_mindwell);
2375 if (sr.sr_mindwell < 1)
2376 sr.sr_mindwell = 1;
2377 }
2378 if (sr.sr_maxdwell != 0) {
2379 sr.sr_maxdwell = msecs_to_ticks(sr.sr_maxdwell);
2380 if (sr.sr_maxdwell < 1)
2381 sr.sr_maxdwell = 1;
2382 }
2383 /* NB: silently reduce ssid count to what is supported */
2384 if (sr.sr_nssid > IEEE80211_SCAN_MAX_SSID)
2385 sr.sr_nssid = IEEE80211_SCAN_MAX_SSID;
2386 for (i = 0; i < sr.sr_nssid; i++)
2387 if (sr.sr_ssid[i].len > IEEE80211_NWID_LEN)
2388 return EINVAL;
2389 /* cleanse flags just in case, could reject if invalid flags */
2390 sr.sr_flags &= IEEE80211_IOC_SCAN_FLAGS;
2391 /*
2392 * Add an implicit NOPICK if the vap is not marked UP. This
2393 * allows applications to scan without joining a bss (or picking
2394 * a channel and setting up a bss) and without forcing manual
2395 * roaming mode--you just need to mark the parent device UP.
2396 */
2397 if ((vap->iv_ifp->if_flags & IFF_UP) == 0)
2398 sr.sr_flags |= IEEE80211_IOC_SCAN_NOPICK;
2399
2400 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
2401 "%s: flags 0x%x%s duration 0x%x mindwell %u maxdwell %u nssid %d\n",
2402 __func__, sr.sr_flags,
2403 (vap->iv_ifp->if_flags & IFF_UP) == 0 ? " (!IFF_UP)" : "",
2404 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, sr.sr_nssid);
2405 /*
2406 * If we are in INIT state then the driver has never had a chance
2407 * to setup hardware state to do a scan; we must use the state
2408 * machine to get us up to the SCAN state but once we reach SCAN
2409 * state we then want to use the supplied params. Stash the
2410 * parameters in the vap and mark IEEE80211_FEXT_SCANREQ; the
2411 * state machines will recognize this and use the stashed params
2412 * to issue the scan request.
2413 *
2414 * Otherwise just invoke the scan machinery directly.
2415 */
2416 IEEE80211_LOCK(ic);
2417 if (vap->iv_state == IEEE80211_S_INIT) {
2418 /* NB: clobbers previous settings */
2419 vap->iv_scanreq_flags = sr.sr_flags;
2420 vap->iv_scanreq_duration = sr.sr_duration;
2421 vap->iv_scanreq_nssid = sr.sr_nssid;
2422 for (i = 0; i < sr.sr_nssid; i++) {
2423 vap->iv_scanreq_ssid[i].len = sr.sr_ssid[i].len;
2424 memcpy(vap->iv_scanreq_ssid[i].ssid, sr.sr_ssid[i].ssid,
2425 sr.sr_ssid[i].len);
2426 }
2427 vap->iv_flags_ext |= IEEE80211_FEXT_SCANREQ;
2428 IEEE80211_UNLOCK(ic);
2429 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2430 } else {
2431 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
2432 IEEE80211_UNLOCK(ic);
2433 /* XXX neeed error return codes */
2434 if (sr.sr_flags & IEEE80211_IOC_SCAN_CHECK) {
2435 (void) ieee80211_check_scan(vap, sr.sr_flags,
2436 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell,
2437 sr.sr_nssid,
2438 /* NB: cheat, we assume structures are compatible */
2439 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]);
2440 } else {
2441 (void) ieee80211_start_scan(vap, sr.sr_flags,
2442 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell,
2443 sr.sr_nssid,
2444 /* NB: cheat, we assume structures are compatible */
2445 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]);
2446 }
2447 }
2448 return error;
2449#undef IEEE80211_IOC_SCAN_FLAGS
2450}
2451
2452static __noinline int
2453ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
2454{
2455 struct ieee80211_node *ni;
2456 struct ieee80211req_sta_vlan vlan;
2457 int error;
2458
2459 if (ireq->i_len != sizeof(vlan))
2460 return EINVAL;
2461 error = copyin(ireq->i_data, &vlan, sizeof(vlan));
2462 if (error != 0)
2463 return error;
2464 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) {
2465 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
2466 vlan.sv_macaddr);
2467 if (ni == NULL)
2468 return ENOENT;
2469 } else
2470 ni = ieee80211_ref_node(vap->iv_bss);
2471 ni->ni_vlan = vlan.sv_vlan;
2472 ieee80211_free_node(ni);
2473 return error;
2474}
2475
2476static int
2477isvap11g(const struct ieee80211vap *vap)
2478{
2479 const struct ieee80211_node *bss = vap->iv_bss;
2480 return bss->ni_chan != IEEE80211_CHAN_ANYC &&
2481 IEEE80211_IS_CHAN_ANYG(bss->ni_chan);
2482}
2483
2484static int
2485isvapht(const struct ieee80211vap *vap)
2486{
2487 const struct ieee80211_node *bss = vap->iv_bss;
2488 return bss->ni_chan != IEEE80211_CHAN_ANYC &&
2489 IEEE80211_IS_CHAN_HT(bss->ni_chan);
2490}
2491
2492/*
2493 * Dummy ioctl set handler so the linker set is defined.
2494 */
2495static int
2496dummy_ioctl_set(struct ieee80211vap *vap, struct ieee80211req *ireq)
2497{
2498 return ENOSYS;
2499}
2500IEEE80211_IOCTL_SET(dummy, dummy_ioctl_set);
2501
2502static int
2503ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
2504{
2505 ieee80211_ioctl_setfunc * const *set;
2506 int error;
2507
2508 SET_FOREACH(set, ieee80211_ioctl_setset) {
2509 error = (*set)(vap, ireq);
2510 if (error != ENOSYS)
2511 return error;
2512 }
2513 return EINVAL;
2514}
2515
2516static __noinline int
2517ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq)
2518{
2519 struct ieee80211com *ic = vap->iv_ic;
2520 int error;
2521 const struct ieee80211_authenticator *auth;
2522 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
2523 char tmpssid[IEEE80211_NWID_LEN];
2524 uint8_t tmpbssid[IEEE80211_ADDR_LEN];
2525 struct ieee80211_key *k;
2526 u_int kid;
2527 uint32_t flags;
2528
2529 error = 0;
2530 switch (ireq->i_type) {
2531 case IEEE80211_IOC_SSID:
2532 if (ireq->i_val != 0 ||
2533 ireq->i_len > IEEE80211_NWID_LEN)
2534 return EINVAL;
2535 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
2536 if (error)
2537 break;
2538 memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
2539 vap->iv_des_ssid[0].len = ireq->i_len;
2540 memcpy(vap->iv_des_ssid[0].ssid, tmpssid, ireq->i_len);
2541 vap->iv_des_nssid = (ireq->i_len > 0);
2542 error = ENETRESET;
2543 break;
2544 case IEEE80211_IOC_WEP:
2545 switch (ireq->i_val) {
2546 case IEEE80211_WEP_OFF:
2547 vap->iv_flags &= ~IEEE80211_F_PRIVACY;
2548 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2549 break;
2550 case IEEE80211_WEP_ON:
2551 vap->iv_flags |= IEEE80211_F_PRIVACY;
2552 vap->iv_flags |= IEEE80211_F_DROPUNENC;
2553 break;
2554 case IEEE80211_WEP_MIXED:
2555 vap->iv_flags |= IEEE80211_F_PRIVACY;
2556 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2557 break;
2558 }
2559 error = ENETRESET;
2560 break;
2561 case IEEE80211_IOC_WEPKEY:
2562 kid = (u_int) ireq->i_val;
2563 if (kid >= IEEE80211_WEP_NKID)
2564 return EINVAL;
2565 k = &vap->iv_nw_keys[kid];
2566 if (ireq->i_len == 0) {
2567 /* zero-len =>'s delete any existing key */
2568 (void) ieee80211_crypto_delkey(vap, k);
2569 break;
2570 }
2571 if (ireq->i_len > sizeof(tmpkey))
2572 return EINVAL;
2573 memset(tmpkey, 0, sizeof(tmpkey));
2574 error = copyin(ireq->i_data, tmpkey, ireq->i_len);
2575 if (error)
2576 break;
2577 ieee80211_key_update_begin(vap);
2578 k->wk_keyix = kid; /* NB: force fixed key id */
2579 if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP,
2580 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
2581 k->wk_keylen = ireq->i_len;
2582 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
2583 IEEE80211_ADDR_COPY(k->wk_macaddr, vap->iv_myaddr);
2584 if (!ieee80211_crypto_setkey(vap, k))
2585 error = EINVAL;
2586 } else
2587 error = EINVAL;
2588 ieee80211_key_update_end(vap);
2589 break;
2590 case IEEE80211_IOC_WEPTXKEY:
2591 kid = (u_int) ireq->i_val;
2592 if (kid >= IEEE80211_WEP_NKID &&
2593 (uint16_t) kid != IEEE80211_KEYIX_NONE)
2594 return EINVAL;
2595 vap->iv_def_txkey = kid;
2596 break;
2597 case IEEE80211_IOC_AUTHMODE:
2598 switch (ireq->i_val) {
2599 case IEEE80211_AUTH_WPA:
2600 case IEEE80211_AUTH_8021X: /* 802.1x */
2601 case IEEE80211_AUTH_OPEN: /* open */
2602 case IEEE80211_AUTH_SHARED: /* shared-key */
2603 case IEEE80211_AUTH_AUTO: /* auto */
2604 auth = ieee80211_authenticator_get(ireq->i_val);
2605 if (auth == NULL)
2606 return EINVAL;
2607 break;
2608 default:
2609 return EINVAL;
2610 }
2611 switch (ireq->i_val) {
2612 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */
2613 vap->iv_flags |= IEEE80211_F_PRIVACY;
2614 ireq->i_val = IEEE80211_AUTH_8021X;
2615 break;
2616 case IEEE80211_AUTH_OPEN: /* open */
2617 vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
2618 break;
2619 case IEEE80211_AUTH_SHARED: /* shared-key */
2620 case IEEE80211_AUTH_8021X: /* 802.1x */
2621 vap->iv_flags &= ~IEEE80211_F_WPA;
2622 /* both require a key so mark the PRIVACY capability */
2623 vap->iv_flags |= IEEE80211_F_PRIVACY;
2624 break;
2625 case IEEE80211_AUTH_AUTO: /* auto */
2626 vap->iv_flags &= ~IEEE80211_F_WPA;
2627 /* XXX PRIVACY handling? */
2628 /* XXX what's the right way to do this? */
2629 break;
2630 }
2631 /* NB: authenticator attach/detach happens on state change */
2632 vap->iv_bss->ni_authmode = ireq->i_val;
2633 /* XXX mixed/mode/usage? */
2634 vap->iv_auth = auth;
2635 error = ENETRESET;
2636 break;
2637 case IEEE80211_IOC_CHANNEL:
2638 error = ieee80211_ioctl_setchannel(vap, ireq);
2639 break;
2640 case IEEE80211_IOC_POWERSAVE:
2641 switch (ireq->i_val) {
2642 case IEEE80211_POWERSAVE_OFF:
2643 if (vap->iv_flags & IEEE80211_F_PMGTON) {
2644 ieee80211_syncflag(vap, -IEEE80211_F_PMGTON);
2645 error = ERESTART;
2646 }
2647 break;
2648 case IEEE80211_POWERSAVE_ON:
2649 if ((vap->iv_caps & IEEE80211_C_PMGT) == 0)
2650 error = EOPNOTSUPP;
2651 else if ((vap->iv_flags & IEEE80211_F_PMGTON) == 0) {
2652 ieee80211_syncflag(vap, IEEE80211_F_PMGTON);
2653 error = ERESTART;
2654 }
2655 break;
2656 default:
2657 error = EINVAL;
2658 break;
2659 }
2660 break;
2661 case IEEE80211_IOC_POWERSAVESLEEP:
2662 if (ireq->i_val < 0)
2663 return EINVAL;
2664 ic->ic_lintval = ireq->i_val;
2665 error = ERESTART;
2666 break;
2667 case IEEE80211_IOC_RTSTHRESHOLD:
2668 if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
2669 ireq->i_val <= IEEE80211_RTS_MAX))
2670 return EINVAL;
2671 vap->iv_rtsthreshold = ireq->i_val;
2672 error = ERESTART;
2673 break;
2674 case IEEE80211_IOC_PROTMODE:
2675 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2676 return EINVAL;
2677 ic->ic_protmode = ireq->i_val;
2678 /* NB: if not operating in 11g this can wait */
2679 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2680 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2681 error = ERESTART;
2682 break;
2683 case IEEE80211_IOC_TXPOWER:
2684 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2685 return EOPNOTSUPP;
2686 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2687 ireq->i_val <= IEEE80211_TXPOWER_MAX))
2688 return EINVAL;
2689 ic->ic_txpowlimit = ireq->i_val;
2690 error = ERESTART;
2691 break;
2692 case IEEE80211_IOC_ROAMING:
2693 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2694 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2695 return EINVAL;
2696 vap->iv_roaming = ireq->i_val;
2697 /* XXXX reset? */
2698 break;
2699 case IEEE80211_IOC_PRIVACY:
2700 if (ireq->i_val) {
2701 /* XXX check for key state? */
2702 vap->iv_flags |= IEEE80211_F_PRIVACY;
2703 } else
2704 vap->iv_flags &= ~IEEE80211_F_PRIVACY;
2705 /* XXX ERESTART? */
2706 break;
2707 case IEEE80211_IOC_DROPUNENCRYPTED:
2708 if (ireq->i_val)
2709 vap->iv_flags |= IEEE80211_F_DROPUNENC;
2710 else
2711 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2712 /* XXX ERESTART? */
2713 break;
2714 case IEEE80211_IOC_WPAKEY:
2715 error = ieee80211_ioctl_setkey(vap, ireq);
2716 break;
2717 case IEEE80211_IOC_DELKEY:
2718 error = ieee80211_ioctl_delkey(vap, ireq);
2719 break;
2720 case IEEE80211_IOC_MLME:
2721 error = ieee80211_ioctl_setmlme(vap, ireq);
2722 break;
2723 case IEEE80211_IOC_COUNTERMEASURES:
2724 if (ireq->i_val) {
2725 if ((vap->iv_flags & IEEE80211_F_WPA) == 0)
2726 return EOPNOTSUPP;
2727 vap->iv_flags |= IEEE80211_F_COUNTERM;
2728 } else
2729 vap->iv_flags &= ~IEEE80211_F_COUNTERM;
2730 /* XXX ERESTART? */
2731 break;
2732 case IEEE80211_IOC_WPA:
2733 if (ireq->i_val > 3)
2734 return EINVAL;
2735 /* XXX verify ciphers available */
2736 flags = vap->iv_flags & ~IEEE80211_F_WPA;
2737 switch (ireq->i_val) {
2738 case 1:
2739 if (!(vap->iv_caps & IEEE80211_C_WPA1))
2740 return EOPNOTSUPP;
2741 flags |= IEEE80211_F_WPA1;
2742 break;
2743 case 2:
2744 if (!(vap->iv_caps & IEEE80211_C_WPA2))
2745 return EOPNOTSUPP;
2746 flags |= IEEE80211_F_WPA2;
2747 break;
2748 case 3:
2749 if ((vap->iv_caps & IEEE80211_C_WPA) != IEEE80211_C_WPA)
2750 return EOPNOTSUPP;
2751 flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2752 break;
2753 default: /* Can't set any -> error */
2754 return EOPNOTSUPP;
2755 }
2756 vap->iv_flags = flags;
2757 error = ERESTART; /* NB: can change beacon frame */
2758 break;
2759 case IEEE80211_IOC_WME:
2760 if (ireq->i_val) {
2761 if ((vap->iv_caps & IEEE80211_C_WME) == 0)
2762 return EOPNOTSUPP;
2763 ieee80211_syncflag(vap, IEEE80211_F_WME);
2764 } else
2765 ieee80211_syncflag(vap, -IEEE80211_F_WME);
2766 error = ERESTART; /* NB: can change beacon frame */
2767 break;
2768 case IEEE80211_IOC_HIDESSID:
2769 if (ireq->i_val)
2770 vap->iv_flags |= IEEE80211_F_HIDESSID;
2771 else
2772 vap->iv_flags &= ~IEEE80211_F_HIDESSID;
2773 error = ERESTART; /* XXX ENETRESET? */
2774 break;
2775 case IEEE80211_IOC_APBRIDGE:
2776 if (ireq->i_val == 0)
2777 vap->iv_flags |= IEEE80211_F_NOBRIDGE;
2778 else
2779 vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
2780 break;
2781 case IEEE80211_IOC_BSSID:
2782 if (ireq->i_len != sizeof(tmpbssid))
2783 return EINVAL;
2784 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2785 if (error)
2786 break;
2787 IEEE80211_ADDR_COPY(vap->iv_des_bssid, tmpbssid);
2788 if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zerobssid))
2789 vap->iv_flags &= ~IEEE80211_F_DESBSSID;
2790 else
2791 vap->iv_flags |= IEEE80211_F_DESBSSID;
2792 error = ENETRESET;
2793 break;
2794 case IEEE80211_IOC_CHANLIST:
2795 error = ieee80211_ioctl_setchanlist(vap, ireq);
2796 break;
2797#define OLD_IEEE80211_IOC_SCAN_REQ 23
2798#ifdef OLD_IEEE80211_IOC_SCAN_REQ
2799 case OLD_IEEE80211_IOC_SCAN_REQ:
2800 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
2801 "%s: active scan request\n", __func__);
2802 /*
2803 * If we are in INIT state then the driver has never
2804 * had a chance to setup hardware state to do a scan;
2805 * use the state machine to get us up the SCAN state.
2806 * Otherwise just invoke the scan machinery to start
2807 * a one-time scan.
2808 */
2809 if (vap->iv_state == IEEE80211_S_INIT)
2810 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2811 else
2812 (void) ieee80211_start_scan(vap,
2813 IEEE80211_SCAN_ACTIVE |
2814 IEEE80211_SCAN_NOPICK |
2815 IEEE80211_SCAN_ONCE,
2816 IEEE80211_SCAN_FOREVER, 0, 0,
2817 /* XXX use ioctl params */
2818 vap->iv_des_nssid, vap->iv_des_ssid);
2819 break;
2820#endif /* OLD_IEEE80211_IOC_SCAN_REQ */
2821 case IEEE80211_IOC_SCAN_REQ:
2822 error = ieee80211_ioctl_scanreq(vap, ireq);
2823 break;
2824 case IEEE80211_IOC_SCAN_CANCEL:
2825 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
2826 "%s: cancel scan\n", __func__);
2827 ieee80211_cancel_scan(vap);
2828 break;
2829 case IEEE80211_IOC_HTCONF:
2830 if (ireq->i_val & 1)
2831 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_HT);
2832 else
2833 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_HT);
2834 if (ireq->i_val & 2)
2835 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_USEHT40);
2836 else
2837 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_USEHT40);
2838 error = ENETRESET;
2839 break;
2840 case IEEE80211_IOC_ADDMAC:
2841 case IEEE80211_IOC_DELMAC:
2842 error = ieee80211_ioctl_macmac(vap, ireq);
2843 break;
2844 case IEEE80211_IOC_MACCMD:
2845 error = ieee80211_ioctl_setmaccmd(vap, ireq);
2846 break;
2847 case IEEE80211_IOC_STA_STATS:
2848 error = ieee80211_ioctl_setstastats(vap, ireq);
2849 break;
2850 case IEEE80211_IOC_STA_TXPOW:
2851 error = ieee80211_ioctl_setstatxpow(vap, ireq);
2852 break;
2853 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
2854 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
2855 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
2856 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
2857 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
2858 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
2859 error = ieee80211_ioctl_setwmeparam(vap, ireq);
2860 break;
2861 case IEEE80211_IOC_DTIM_PERIOD:
2862 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2863 vap->iv_opmode != IEEE80211_M_IBSS)
2864 return EINVAL;
2865 if (IEEE80211_DTIM_MIN <= ireq->i_val &&
2866 ireq->i_val <= IEEE80211_DTIM_MAX) {
2867 vap->iv_dtim_period = ireq->i_val;
2868 error = ENETRESET; /* requires restart */
2869 } else
2870 error = EINVAL;
2871 break;
2872 case IEEE80211_IOC_BEACON_INTERVAL:
2873 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2874 vap->iv_opmode != IEEE80211_M_IBSS)
2875 return EINVAL;
2876 if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
2877 ireq->i_val <= IEEE80211_BINTVAL_MAX) {
2878 ic->ic_bintval = ireq->i_val;
2879 error = ENETRESET; /* requires restart */
2880 } else
2881 error = EINVAL;
2882 break;
2883 case IEEE80211_IOC_PUREG:
2884 if (ireq->i_val)
2885 vap->iv_flags |= IEEE80211_F_PUREG;
2886 else
2887 vap->iv_flags &= ~IEEE80211_F_PUREG;
2888 /* NB: reset only if we're operating on an 11g channel */
2889 if (isvap11g(vap))
2890 error = ENETRESET;
2891 break;
962 case IEEE80211_IOC_BGSCAN:
963 ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0;
964 break;
965 case IEEE80211_IOC_BGSCAN_IDLE:
966 ireq->i_val = vap->iv_bgscanidle*hz/1000; /* ms */
967 break;
968 case IEEE80211_IOC_BGSCAN_INTERVAL:
969 ireq->i_val = vap->iv_bgscanintvl/hz; /* seconds */
970 break;
971 case IEEE80211_IOC_SCANVALID:
972 ireq->i_val = vap->iv_scanvalid/hz; /* seconds */
973 break;
974 case IEEE80211_IOC_FRAGTHRESHOLD:
975 ireq->i_val = vap->iv_fragthreshold;
976 break;
977 case IEEE80211_IOC_MACCMD:
978 error = ieee80211_ioctl_getmaccmd(vap, ireq);
979 break;
980 case IEEE80211_IOC_BURST:
981 ireq->i_val = (vap->iv_flags & IEEE80211_F_BURST) != 0;
982 break;
983 case IEEE80211_IOC_BMISSTHRESHOLD:
984 ireq->i_val = vap->iv_bmissthreshold;
985 break;
986 case IEEE80211_IOC_CURCHAN:
987 error = ieee80211_ioctl_getcurchan(vap, ireq);
988 break;
989 case IEEE80211_IOC_SHORTGI:
990 ireq->i_val = 0;
991 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI20)
992 ireq->i_val |= IEEE80211_HTCAP_SHORTGI20;
993 if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI40)
994 ireq->i_val |= IEEE80211_HTCAP_SHORTGI40;
995 break;
996 case IEEE80211_IOC_AMPDU:
997 ireq->i_val = 0;
998 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_TX)
999 ireq->i_val |= 1;
1000 if (vap->iv_flags_ext & IEEE80211_FEXT_AMPDU_RX)
1001 ireq->i_val |= 2;
1002 break;
1003 case IEEE80211_IOC_AMPDU_LIMIT:
1004 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
1005 ireq->i_val = vap->iv_ampdu_rxmax;
1006 else if (vap->iv_state == IEEE80211_S_RUN)
1007 ireq->i_val = MS(vap->iv_bss->ni_htparam,
1008 IEEE80211_HTCAP_MAXRXAMPDU);
1009 else
1010 ireq->i_val = vap->iv_ampdu_limit;
1011 break;
1012 case IEEE80211_IOC_AMPDU_DENSITY:
1013 if (vap->iv_opmode == IEEE80211_M_STA &&
1014 vap->iv_state == IEEE80211_S_RUN)
1015 ireq->i_val = MS(vap->iv_bss->ni_htparam,
1016 IEEE80211_HTCAP_MPDUDENSITY);
1017 else
1018 ireq->i_val = vap->iv_ampdu_density;
1019 break;
1020 case IEEE80211_IOC_AMSDU:
1021 ireq->i_val = 0;
1022 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_TX)
1023 ireq->i_val |= 1;
1024 if (vap->iv_flags_ext & IEEE80211_FEXT_AMSDU_RX)
1025 ireq->i_val |= 2;
1026 break;
1027 case IEEE80211_IOC_AMSDU_LIMIT:
1028 ireq->i_val = vap->iv_amsdu_limit; /* XXX truncation? */
1029 break;
1030 case IEEE80211_IOC_PUREN:
1031 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_PUREN) != 0;
1032 break;
1033 case IEEE80211_IOC_DOTH:
1034 ireq->i_val = (vap->iv_flags & IEEE80211_F_DOTH) != 0;
1035 break;
1036 case IEEE80211_IOC_REGDOMAIN:
1037 error = ieee80211_ioctl_getregdomain(vap, ireq);
1038 break;
1039 case IEEE80211_IOC_ROAM:
1040 error = ieee80211_ioctl_getroam(vap, ireq);
1041 break;
1042 case IEEE80211_IOC_TXPARAMS:
1043 error = ieee80211_ioctl_gettxparams(vap, ireq);
1044 break;
1045 case IEEE80211_IOC_HTCOMPAT:
1046 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) != 0;
1047 break;
1048 case IEEE80211_IOC_DWDS:
1049 ireq->i_val = (vap->iv_flags & IEEE80211_F_DWDS) != 0;
1050 break;
1051 case IEEE80211_IOC_INACTIVITY:
1052 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_INACT) != 0;
1053 break;
1054 case IEEE80211_IOC_APPIE:
1055 error = ieee80211_ioctl_getappie(vap, ireq);
1056 break;
1057 case IEEE80211_IOC_WPS:
1058 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_WPS) != 0;
1059 break;
1060 case IEEE80211_IOC_TSN:
1061 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_TSN) != 0;
1062 break;
1063 case IEEE80211_IOC_DFS:
1064 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DFS) != 0;
1065 break;
1066 case IEEE80211_IOC_DOTD:
1067 ireq->i_val = (vap->iv_flags_ext & IEEE80211_FEXT_DOTD) != 0;
1068 break;
1069 case IEEE80211_IOC_DEVCAPS:
1070 error = ieee80211_ioctl_getdevcaps(ic, ireq);
1071 break;
1072 case IEEE80211_IOC_HTPROTMODE:
1073 ireq->i_val = ic->ic_htprotmode;
1074 break;
1075 case IEEE80211_IOC_HTCONF:
1076 if (vap->iv_flags_ext & IEEE80211_FEXT_HT) {
1077 ireq->i_val = 1;
1078 if (vap->iv_flags_ext & IEEE80211_FEXT_USEHT40)
1079 ireq->i_val |= 2;
1080 } else
1081 ireq->i_val = 0;
1082 break;
1083 case IEEE80211_IOC_STA_VLAN:
1084 error = ieee80211_ioctl_getstavlan(vap, ireq);
1085 break;
1086 case IEEE80211_IOC_SMPS:
1087 if (vap->iv_opmode == IEEE80211_M_STA &&
1088 vap->iv_state == IEEE80211_S_RUN) {
1089 if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS)
1090 ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC;
1091 else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS)
1092 ireq->i_val = IEEE80211_HTCAP_SMPS_ENA;
1093 else
1094 ireq->i_val = IEEE80211_HTCAP_SMPS_OFF;
1095 } else
1096 ireq->i_val = vap->iv_htcaps & IEEE80211_HTCAP_SMPS;
1097 break;
1098 case IEEE80211_IOC_RIFS:
1099 if (vap->iv_opmode == IEEE80211_M_STA &&
1100 vap->iv_state == IEEE80211_S_RUN)
1101 ireq->i_val =
1102 (vap->iv_bss->ni_flags & IEEE80211_NODE_RIFS) != 0;
1103 else
1104 ireq->i_val =
1105 (vap->iv_flags_ext & IEEE80211_FEXT_RIFS) != 0;
1106 break;
1107 default:
1108 error = ieee80211_ioctl_getdefault(vap, ireq);
1109 break;
1110 }
1111 return error;
1112#undef MS
1113}
1114
1115static __noinline int
1116ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
1117{
1118 struct ieee80211req_key ik;
1119 struct ieee80211_node *ni;
1120 struct ieee80211_key *wk;
1121 uint16_t kid;
1122 int error, i;
1123
1124 if (ireq->i_len != sizeof(ik))
1125 return EINVAL;
1126 error = copyin(ireq->i_data, &ik, sizeof(ik));
1127 if (error)
1128 return error;
1129 /* NB: cipher support is verified by ieee80211_crypt_newkey */
1130 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1131 if (ik.ik_keylen > sizeof(ik.ik_keydata))
1132 return E2BIG;
1133 kid = ik.ik_keyix;
1134 if (kid == IEEE80211_KEYIX_NONE) {
1135 /* XXX unicast keys currently must be tx/rx */
1136 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1137 return EINVAL;
1138 if (vap->iv_opmode == IEEE80211_M_STA) {
1139 ni = ieee80211_ref_node(vap->iv_bss);
1140 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1141 ieee80211_free_node(ni);
1142 return EADDRNOTAVAIL;
1143 }
1144 } else {
1145 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
1146 ik.ik_macaddr);
1147 if (ni == NULL)
1148 return ENOENT;
1149 }
1150 wk = &ni->ni_ucastkey;
1151 } else {
1152 if (kid >= IEEE80211_WEP_NKID)
1153 return EINVAL;
1154 wk = &vap->iv_nw_keys[kid];
1155 /*
1156 * Global slots start off w/o any assigned key index.
1157 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1158 */
1159 if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1160 wk->wk_keyix = kid;
1161 ni = NULL;
1162 }
1163 error = 0;
1164 ieee80211_key_update_begin(vap);
1165 if (ieee80211_crypto_newkey(vap, ik.ik_type, ik.ik_flags, wk)) {
1166 wk->wk_keylen = ik.ik_keylen;
1167 /* NB: MIC presence is implied by cipher type */
1168 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1169 wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1170 for (i = 0; i < IEEE80211_TID_SIZE; i++)
1171 wk->wk_keyrsc[i] = ik.ik_keyrsc;
1172 wk->wk_keytsc = 0; /* new key, reset */
1173 memset(wk->wk_key, 0, sizeof(wk->wk_key));
1174 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1175 IEEE80211_ADDR_COPY(wk->wk_macaddr,
1176 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr);
1177 if (!ieee80211_crypto_setkey(vap, wk))
1178 error = EIO;
1179 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1180 vap->iv_def_txkey = kid;
1181 } else
1182 error = ENXIO;
1183 ieee80211_key_update_end(vap);
1184 if (ni != NULL)
1185 ieee80211_free_node(ni);
1186 return error;
1187}
1188
1189static __noinline int
1190ieee80211_ioctl_delkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
1191{
1192 struct ieee80211req_del_key dk;
1193 int kid, error;
1194
1195 if (ireq->i_len != sizeof(dk))
1196 return EINVAL;
1197 error = copyin(ireq->i_data, &dk, sizeof(dk));
1198 if (error)
1199 return error;
1200 kid = dk.idk_keyix;
1201 /* XXX uint8_t -> uint16_t */
1202 if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1203 struct ieee80211_node *ni;
1204
1205 if (vap->iv_opmode == IEEE80211_M_STA) {
1206 ni = ieee80211_ref_node(vap->iv_bss);
1207 if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1208 ieee80211_free_node(ni);
1209 return EADDRNOTAVAIL;
1210 }
1211 } else {
1212 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
1213 dk.idk_macaddr);
1214 if (ni == NULL)
1215 return ENOENT;
1216 }
1217 /* XXX error return */
1218 ieee80211_node_delucastkey(ni);
1219 ieee80211_free_node(ni);
1220 } else {
1221 if (kid >= IEEE80211_WEP_NKID)
1222 return EINVAL;
1223 /* XXX error return */
1224 ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[kid]);
1225 }
1226 return 0;
1227}
1228
1229struct mlmeop {
1230 struct ieee80211vap *vap;
1231 int op;
1232 int reason;
1233};
1234
1235static void
1236mlmedebug(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
1237 int op, int reason)
1238{
1239#ifdef IEEE80211_DEBUG
1240 static const struct {
1241 int mask;
1242 const char *opstr;
1243 } ops[] = {
1244 { 0, "op#0" },
1245 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1246 IEEE80211_MSG_ASSOC, "assoc" },
1247 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1248 IEEE80211_MSG_ASSOC, "disassoc" },
1249 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1250 IEEE80211_MSG_AUTH, "deauth" },
1251 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1252 IEEE80211_MSG_AUTH, "authorize" },
1253 { IEEE80211_MSG_IOCTL | IEEE80211_MSG_STATE |
1254 IEEE80211_MSG_AUTH, "unauthorize" },
1255 };
1256
1257 if (op == IEEE80211_MLME_AUTH) {
1258 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_IOCTL |
1259 IEEE80211_MSG_STATE | IEEE80211_MSG_AUTH, mac,
1260 "station authenticate %s via MLME (reason %d)",
1261 reason == IEEE80211_STATUS_SUCCESS ? "ACCEPT" : "REJECT",
1262 reason);
1263 } else if (!(IEEE80211_MLME_ASSOC <= op && op <= IEEE80211_MLME_AUTH)) {
1264 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, mac,
1265 "unknown MLME request %d (reason %d)", op, reason);
1266 } else if (reason == IEEE80211_STATUS_SUCCESS) {
1267 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
1268 "station %s via MLME", ops[op].opstr);
1269 } else {
1270 IEEE80211_NOTE_MAC(vap, ops[op].mask, mac,
1271 "station %s via MLME (reason %d)", ops[op].opstr, reason);
1272 }
1273#endif /* IEEE80211_DEBUG */
1274}
1275
1276static void
1277domlme(void *arg, struct ieee80211_node *ni)
1278{
1279 struct mlmeop *mop = arg;
1280 struct ieee80211vap *vap = ni->ni_vap;
1281
1282 if (vap != mop->vap)
1283 return;
1284 /*
1285 * NB: if ni_associd is zero then the node is already cleaned
1286 * up and we don't need to do this (we're safely holding a
1287 * reference but should otherwise not modify it's state).
1288 */
1289 if (ni->ni_associd == 0)
1290 return;
1291 mlmedebug(vap, ni->ni_macaddr, mop->op, mop->reason);
1292 if (mop->op == IEEE80211_MLME_DEAUTH) {
1293 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
1294 mop->reason);
1295 } else {
1296 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
1297 mop->reason);
1298 }
1299 ieee80211_node_leave(ni);
1300}
1301
1302static int
1303setmlme_dropsta(struct ieee80211vap *vap,
1304 const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
1305{
1306 struct ieee80211com *ic = vap->iv_ic;
1307 struct ieee80211_node_table *nt = &ic->ic_sta;
1308 struct ieee80211_node *ni;
1309 int error = 0;
1310
1311 /* NB: the broadcast address means do 'em all */
1312 if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
1313 IEEE80211_NODE_LOCK(nt);
1314 ni = ieee80211_find_node_locked(nt, mac);
1315 if (ni != NULL) {
1316 domlme(mlmeop, ni);
1317 ieee80211_free_node(ni);
1318 } else
1319 error = ENOENT;
1320 IEEE80211_NODE_UNLOCK(nt);
1321 } else {
1322 ieee80211_iterate_nodes(nt, domlme, mlmeop);
1323 }
1324 return error;
1325}
1326
1327static __noinline int
1328setmlme_common(struct ieee80211vap *vap, int op,
1329 const uint8_t mac[IEEE80211_ADDR_LEN], int reason)
1330{
1331 struct ieee80211com *ic = vap->iv_ic;
1332 struct ieee80211_node_table *nt = &ic->ic_sta;
1333 struct ieee80211_node *ni;
1334 struct mlmeop mlmeop;
1335 int error;
1336
1337 error = 0;
1338 switch (op) {
1339 case IEEE80211_MLME_DISASSOC:
1340 case IEEE80211_MLME_DEAUTH:
1341 switch (vap->iv_opmode) {
1342 case IEEE80211_M_STA:
1343 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason);
1344 /* XXX not quite right */
1345 ieee80211_new_state(vap, IEEE80211_S_INIT, reason);
1346 break;
1347 case IEEE80211_M_HOSTAP:
1348 mlmeop.vap = vap;
1349 mlmeop.op = op;
1350 mlmeop.reason = reason;
1351 error = setmlme_dropsta(vap, mac, &mlmeop);
1352 break;
1353 case IEEE80211_M_WDS:
1354 /* XXX user app should send raw frame? */
1355 if (op != IEEE80211_MLME_DEAUTH) {
1356 error = EINVAL;
1357 break;
1358 }
1359#if 0
1360 /* XXX accept any address, simplifies user code */
1361 if (!IEEE80211_ADDR_EQ(mac, vap->iv_bss->ni_macaddr)) {
1362 error = EINVAL;
1363 break;
1364 }
1365#endif
1366 mlmedebug(vap, vap->iv_bss->ni_macaddr, op, reason);
1367 ni = ieee80211_ref_node(vap->iv_bss);
1368 IEEE80211_SEND_MGMT(ni,
1369 IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
1370 ieee80211_free_node(ni);
1371 break;
1372 default:
1373 error = EINVAL;
1374 break;
1375 }
1376 break;
1377 case IEEE80211_MLME_AUTHORIZE:
1378 case IEEE80211_MLME_UNAUTHORIZE:
1379 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
1380 vap->iv_opmode != IEEE80211_M_WDS) {
1381 error = EINVAL;
1382 break;
1383 }
1384 IEEE80211_NODE_LOCK(nt);
1385 ni = ieee80211_find_vap_node_locked(nt, vap, mac);
1386 if (ni != NULL) {
1387 mlmedebug(vap, mac, op, reason);
1388 if (op == IEEE80211_MLME_AUTHORIZE)
1389 ieee80211_node_authorize(ni);
1390 else
1391 ieee80211_node_unauthorize(ni);
1392 ieee80211_free_node(ni);
1393 } else
1394 error = ENOENT;
1395 IEEE80211_NODE_UNLOCK(nt);
1396 break;
1397 case IEEE80211_MLME_AUTH:
1398 if (vap->iv_opmode != IEEE80211_M_HOSTAP) {
1399 error = EINVAL;
1400 break;
1401 }
1402 IEEE80211_NODE_LOCK(nt);
1403 ni = ieee80211_find_vap_node_locked(nt, vap, mac);
1404 if (ni != NULL) {
1405 mlmedebug(vap, mac, op, reason);
1406 if (reason == IEEE80211_STATUS_SUCCESS) {
1407 IEEE80211_SEND_MGMT(ni,
1408 IEEE80211_FC0_SUBTYPE_AUTH, 2);
1409 /*
1410 * For shared key auth, just continue the
1411 * exchange. Otherwise when 802.1x is not in
1412 * use mark the port authorized at this point
1413 * so traffic can flow.
1414 */
1415 if (ni->ni_authmode != IEEE80211_AUTH_8021X &&
1416 ni->ni_challenge == NULL)
1417 ieee80211_node_authorize(ni);
1418 } else {
1419 vap->iv_stats.is_rx_acl++;
1420 ieee80211_send_error(ni, ni->ni_macaddr,
1421 IEEE80211_FC0_SUBTYPE_AUTH, 2|(reason<<16));
1422 ieee80211_node_leave(ni);
1423 }
1424 ieee80211_free_node(ni);
1425 } else
1426 error = ENOENT;
1427 IEEE80211_NODE_UNLOCK(nt);
1428 break;
1429 default:
1430 error = EINVAL;
1431 break;
1432 }
1433 return error;
1434}
1435
1436struct scanlookup {
1437 const uint8_t *mac;
1438 int esslen;
1439 const uint8_t *essid;
1440 const struct ieee80211_scan_entry *se;
1441};
1442
1443/*
1444 * Match mac address and any ssid.
1445 */
1446static void
1447mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1448{
1449 struct scanlookup *look = arg;
1450
1451 if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1452 return;
1453 if (look->esslen != 0) {
1454 if (se->se_ssid[1] != look->esslen)
1455 return;
1456 if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1457 return;
1458 }
1459 look->se = se;
1460}
1461
1462static __noinline int
1463setmlme_assoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
1464 int ssid_len, const uint8_t ssid[IEEE80211_NWID_LEN])
1465{
1466 struct scanlookup lookup;
1467
1468 /* XXX ibss/ahdemo */
1469 if (vap->iv_opmode != IEEE80211_M_STA)
1470 return EINVAL;
1471
1472 /* NB: this is racey if roaming is !manual */
1473 lookup.se = NULL;
1474 lookup.mac = mac;
1475 lookup.esslen = ssid_len;
1476 lookup.essid = ssid;
1477 ieee80211_scan_iterate(vap, mlmelookup, &lookup);
1478 if (lookup.se == NULL)
1479 return ENOENT;
1480 mlmedebug(vap, mac, IEEE80211_MLME_ASSOC, 0);
1481 if (!ieee80211_sta_join(vap, lookup.se->se_chan, lookup.se))
1482 return EIO; /* XXX unique but could be better */
1483 return 0;
1484}
1485
1486static __noinline int
1487ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq)
1488{
1489 struct ieee80211req_mlme mlme;
1490 int error;
1491
1492 if (ireq->i_len != sizeof(mlme))
1493 return EINVAL;
1494 error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1495 if (error)
1496 return error;
1497 if (mlme.im_op == IEEE80211_MLME_ASSOC)
1498 return setmlme_assoc(vap, mlme.im_macaddr,
1499 vap->iv_des_ssid[0].len, vap->iv_des_ssid[0].ssid);
1500 else
1501 return setmlme_common(vap, mlme.im_op,
1502 mlme.im_macaddr, mlme.im_reason);
1503}
1504
1505static __noinline int
1506ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq)
1507{
1508 uint8_t mac[IEEE80211_ADDR_LEN];
1509 const struct ieee80211_aclator *acl = vap->iv_acl;
1510 int error;
1511
1512 if (ireq->i_len != sizeof(mac))
1513 return EINVAL;
1514 error = copyin(ireq->i_data, mac, ireq->i_len);
1515 if (error)
1516 return error;
1517 if (acl == NULL) {
1518 acl = ieee80211_aclator_get("mac");
1519 if (acl == NULL || !acl->iac_attach(vap))
1520 return EINVAL;
1521 vap->iv_acl = acl;
1522 }
1523 if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1524 acl->iac_add(vap, mac);
1525 else
1526 acl->iac_remove(vap, mac);
1527 return 0;
1528}
1529
1530static __noinline int
1531ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
1532{
1533 const struct ieee80211_aclator *acl = vap->iv_acl;
1534
1535 switch (ireq->i_val) {
1536 case IEEE80211_MACCMD_POLICY_OPEN:
1537 case IEEE80211_MACCMD_POLICY_ALLOW:
1538 case IEEE80211_MACCMD_POLICY_DENY:
1539 case IEEE80211_MACCMD_POLICY_RADIUS:
1540 if (acl == NULL) {
1541 acl = ieee80211_aclator_get("mac");
1542 if (acl == NULL || !acl->iac_attach(vap))
1543 return EINVAL;
1544 vap->iv_acl = acl;
1545 }
1546 acl->iac_setpolicy(vap, ireq->i_val);
1547 break;
1548 case IEEE80211_MACCMD_FLUSH:
1549 if (acl != NULL)
1550 acl->iac_flush(vap);
1551 /* NB: silently ignore when not in use */
1552 break;
1553 case IEEE80211_MACCMD_DETACH:
1554 if (acl != NULL) {
1555 vap->iv_acl = NULL;
1556 acl->iac_detach(vap);
1557 }
1558 break;
1559 default:
1560 if (acl == NULL)
1561 return EINVAL;
1562 else
1563 return acl->iac_setioctl(vap, ireq);
1564 }
1565 return 0;
1566}
1567
1568static __noinline int
1569ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
1570{
1571 struct ieee80211com *ic = vap->iv_ic;
1572 uint8_t *chanlist, *list;
1573 int i, nchan, maxchan, error;
1574
1575 if (ireq->i_len > sizeof(ic->ic_chan_active))
1576 ireq->i_len = sizeof(ic->ic_chan_active);
1577 list = malloc(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP,
1578 M_NOWAIT | M_ZERO);
1579 if (list == NULL)
1580 return ENOMEM;
1581 error = copyin(ireq->i_data, list, ireq->i_len);
1582 if (error)
1583 return error;
1584 nchan = 0;
1585 chanlist = list + ireq->i_len; /* NB: zero'd already */
1586 maxchan = ireq->i_len * NBBY;
1587 for (i = 0; i < ic->ic_nchans; i++) {
1588 const struct ieee80211_channel *c = &ic->ic_channels[i];
1589 /*
1590 * Calculate the intersection of the user list and the
1591 * available channels so users can do things like specify
1592 * 1-255 to get all available channels.
1593 */
1594 if (c->ic_ieee < maxchan && isset(list, c->ic_ieee)) {
1595 setbit(chanlist, c->ic_ieee);
1596 nchan++;
1597 }
1598 }
1599 if (nchan == 0)
1600 return EINVAL;
1601 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1602 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1603 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1604 memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES);
1605 ieee80211_scan_flush(vap);
1606 free(list, M_TEMP);
1607 return ENETRESET;
1608}
1609
1610static __noinline int
1611ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
1612{
1613 struct ieee80211_node *ni;
1614 uint8_t macaddr[IEEE80211_ADDR_LEN];
1615 int error;
1616
1617 /*
1618 * NB: we could copyin ieee80211req_sta_stats so apps
1619 * could make selective changes but that's overkill;
1620 * just clear all stats for now.
1621 */
1622 if (ireq->i_len < IEEE80211_ADDR_LEN)
1623 return EINVAL;
1624 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1625 if (error != 0)
1626 return error;
1627 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, macaddr);
1628 if (ni == NULL)
1629 return ENOENT;
1630 /* XXX require ni_vap == vap? */
1631 memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1632 ieee80211_free_node(ni);
1633 return 0;
1634}
1635
1636static __noinline int
1637ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq)
1638{
1639 struct ieee80211_node *ni;
1640 struct ieee80211req_sta_txpow txpow;
1641 int error;
1642
1643 if (ireq->i_len != sizeof(txpow))
1644 return EINVAL;
1645 error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1646 if (error != 0)
1647 return error;
1648 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, txpow.it_macaddr);
1649 if (ni == NULL)
1650 return ENOENT;
1651 ni->ni_txpower = txpow.it_txpow;
1652 ieee80211_free_node(ni);
1653 return error;
1654}
1655
1656static __noinline int
1657ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
1658{
1659 struct ieee80211com *ic = vap->iv_ic;
1660 struct ieee80211_wme_state *wme = &ic->ic_wme;
1661 struct wmeParams *wmep, *chanp;
1662 int isbss, ac;
1663
1664 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1665 return EOPNOTSUPP;
1666
1667 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1668 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1669 if (ac >= WME_NUM_AC)
1670 ac = WME_AC_BE;
1671 if (isbss) {
1672 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1673 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1674 } else {
1675 chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1676 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1677 }
1678 switch (ireq->i_type) {
1679 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
1680 if (isbss) {
1681 wmep->wmep_logcwmin = ireq->i_val;
1682 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1683 chanp->wmep_logcwmin = ireq->i_val;
1684 } else {
1685 wmep->wmep_logcwmin = chanp->wmep_logcwmin =
1686 ireq->i_val;
1687 }
1688 break;
1689 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
1690 if (isbss) {
1691 wmep->wmep_logcwmax = ireq->i_val;
1692 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1693 chanp->wmep_logcwmax = ireq->i_val;
1694 } else {
1695 wmep->wmep_logcwmax = chanp->wmep_logcwmax =
1696 ireq->i_val;
1697 }
1698 break;
1699 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
1700 if (isbss) {
1701 wmep->wmep_aifsn = ireq->i_val;
1702 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1703 chanp->wmep_aifsn = ireq->i_val;
1704 } else {
1705 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
1706 }
1707 break;
1708 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
1709 if (isbss) {
1710 wmep->wmep_txopLimit = ireq->i_val;
1711 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1712 chanp->wmep_txopLimit = ireq->i_val;
1713 } else {
1714 wmep->wmep_txopLimit = chanp->wmep_txopLimit =
1715 ireq->i_val;
1716 }
1717 break;
1718 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
1719 wmep->wmep_acm = ireq->i_val;
1720 if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1721 chanp->wmep_acm = ireq->i_val;
1722 break;
1723 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
1724 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
1725 (ireq->i_val) == 0;
1726 break;
1727 }
1728 ieee80211_wme_updateparams(vap);
1729 return 0;
1730}
1731
1732static int
1733find11gchannel(struct ieee80211com *ic, int start, int freq)
1734{
1735 const struct ieee80211_channel *c;
1736 int i;
1737
1738 for (i = start+1; i < ic->ic_nchans; i++) {
1739 c = &ic->ic_channels[i];
1740 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1741 return 1;
1742 }
1743 /* NB: should not be needed but in case things are mis-sorted */
1744 for (i = 0; i < start; i++) {
1745 c = &ic->ic_channels[i];
1746 if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1747 return 1;
1748 }
1749 return 0;
1750}
1751
1752static struct ieee80211_channel *
1753findchannel(struct ieee80211com *ic, int ieee, int mode)
1754{
1755 static const u_int chanflags[IEEE80211_MODE_MAX] = {
1756 [IEEE80211_MODE_AUTO] = 0,
1757 [IEEE80211_MODE_11A] = IEEE80211_CHAN_A,
1758 [IEEE80211_MODE_11B] = IEEE80211_CHAN_B,
1759 [IEEE80211_MODE_11G] = IEEE80211_CHAN_G,
1760 [IEEE80211_MODE_FH] = IEEE80211_CHAN_FHSS,
1761 [IEEE80211_MODE_TURBO_A] = IEEE80211_CHAN_108A,
1762 [IEEE80211_MODE_TURBO_G] = IEEE80211_CHAN_108G,
1763 [IEEE80211_MODE_STURBO_A] = IEEE80211_CHAN_STURBO,
1764 [IEEE80211_MODE_HALF] = IEEE80211_CHAN_HALF,
1765 [IEEE80211_MODE_QUARTER] = IEEE80211_CHAN_QUARTER,
1766 /* NB: handled specially below */
1767 [IEEE80211_MODE_11NA] = IEEE80211_CHAN_A,
1768 [IEEE80211_MODE_11NG] = IEEE80211_CHAN_G,
1769 };
1770 u_int modeflags;
1771 int i;
1772
1773 modeflags = chanflags[mode];
1774 for (i = 0; i < ic->ic_nchans; i++) {
1775 struct ieee80211_channel *c = &ic->ic_channels[i];
1776
1777 if (c->ic_ieee != ieee)
1778 continue;
1779 if (mode == IEEE80211_MODE_AUTO) {
1780 /* ignore turbo channels for autoselect */
1781 if (IEEE80211_IS_CHAN_TURBO(c))
1782 continue;
1783 /*
1784 * XXX special-case 11b/g channels so we
1785 * always select the g channel if both
1786 * are present.
1787 * XXX prefer HT to non-HT?
1788 */
1789 if (!IEEE80211_IS_CHAN_B(c) ||
1790 !find11gchannel(ic, i, c->ic_freq))
1791 return c;
1792 } else {
1793 /* must check HT specially */
1794 if ((mode == IEEE80211_MODE_11NA ||
1795 mode == IEEE80211_MODE_11NG) &&
1796 !IEEE80211_IS_CHAN_HT(c))
1797 continue;
1798 if ((c->ic_flags & modeflags) == modeflags)
1799 return c;
1800 }
1801 }
1802 return NULL;
1803}
1804
1805/*
1806 * Check the specified against any desired mode (aka netband).
1807 * This is only used (presently) when operating in hostap mode
1808 * to enforce consistency.
1809 */
1810static int
1811check_mode_consistency(const struct ieee80211_channel *c, int mode)
1812{
1813 KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1814
1815 switch (mode) {
1816 case IEEE80211_MODE_11B:
1817 return (IEEE80211_IS_CHAN_B(c));
1818 case IEEE80211_MODE_11G:
1819 return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1820 case IEEE80211_MODE_11A:
1821 return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1822 case IEEE80211_MODE_STURBO_A:
1823 return (IEEE80211_IS_CHAN_STURBO(c));
1824 case IEEE80211_MODE_11NA:
1825 return (IEEE80211_IS_CHAN_HTA(c));
1826 case IEEE80211_MODE_11NG:
1827 return (IEEE80211_IS_CHAN_HTG(c));
1828 }
1829 return 1;
1830
1831}
1832
1833/*
1834 * Common code to set the current channel. If the device
1835 * is up and running this may result in an immediate channel
1836 * change or a kick of the state machine.
1837 */
1838static int
1839setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
1840{
1841 struct ieee80211com *ic = vap->iv_ic;
1842 int error;
1843
1844 if (c != IEEE80211_CHAN_ANYC) {
1845 if (IEEE80211_IS_CHAN_RADAR(c))
1846 return EBUSY; /* XXX better code? */
1847 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
1848 if (IEEE80211_IS_CHAN_NOHOSTAP(c))
1849 return EINVAL;
1850 if (!check_mode_consistency(c, vap->iv_des_mode))
1851 return EINVAL;
1852 } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
1853 if (IEEE80211_IS_CHAN_NOADHOC(c))
1854 return EINVAL;
1855 }
1856 if (vap->iv_state == IEEE80211_S_RUN &&
1857 vap->iv_bss->ni_chan == c)
1858 return 0; /* NB: nothing to do */
1859 }
1860 vap->iv_des_chan = c;
1861
1862 error = 0;
1863 if (vap->iv_opmode == IEEE80211_M_MONITOR &&
1864 vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
1865 /*
1866 * Monitor mode can switch directly.
1867 */
1868 if (IFNET_IS_UP_RUNNING(vap->iv_ifp)) {
1869 /* XXX need state machine for other vap's to follow */
1870 ieee80211_setcurchan(ic, vap->iv_des_chan);
1871 vap->iv_bss->ni_chan = ic->ic_curchan;
1872 } else
1873 ic->ic_curchan = vap->iv_des_chan;
1874 } else {
1875 /*
1876 * Need to go through the state machine in case we
1877 * need to reassociate or the like. The state machine
1878 * will pickup the desired channel and avoid scanning.
1879 */
1880 if (IS_UP_AUTO(vap))
1881 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
1882 else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) {
1883 /*
1884 * When not up+running and a real channel has
1885 * been specified fix the current channel so
1886 * there is immediate feedback; e.g. via ifconfig.
1887 */
1888 ic->ic_curchan = vap->iv_des_chan;
1889 }
1890 }
1891 return error;
1892}
1893
1894/*
1895 * Old api for setting the current channel; this is
1896 * deprecated because channel numbers are ambiguous.
1897 */
1898static __noinline int
1899ieee80211_ioctl_setchannel(struct ieee80211vap *vap,
1900 const struct ieee80211req *ireq)
1901{
1902 struct ieee80211com *ic = vap->iv_ic;
1903 struct ieee80211_channel *c;
1904
1905 /* XXX 0xffff overflows 16-bit signed */
1906 if (ireq->i_val == 0 ||
1907 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1908 c = IEEE80211_CHAN_ANYC;
1909 } else {
1910 struct ieee80211_channel *c2;
1911
1912 c = findchannel(ic, ireq->i_val, vap->iv_des_mode);
1913 if (c == NULL) {
1914 c = findchannel(ic, ireq->i_val,
1915 IEEE80211_MODE_AUTO);
1916 if (c == NULL)
1917 return EINVAL;
1918 }
1919 /*
1920 * Fine tune channel selection based on desired mode:
1921 * if 11b is requested, find the 11b version of any
1922 * 11g channel returned,
1923 * if static turbo, find the turbo version of any
1924 * 11a channel return,
1925 * if 11na is requested, find the ht version of any
1926 * 11a channel returned,
1927 * if 11ng is requested, find the ht version of any
1928 * 11g channel returned,
1929 * otherwise we should be ok with what we've got.
1930 */
1931 switch (vap->iv_des_mode) {
1932 case IEEE80211_MODE_11B:
1933 if (IEEE80211_IS_CHAN_ANYG(c)) {
1934 c2 = findchannel(ic, ireq->i_val,
1935 IEEE80211_MODE_11B);
1936 /* NB: should not happen, =>'s 11g w/o 11b */
1937 if (c2 != NULL)
1938 c = c2;
1939 }
1940 break;
1941 case IEEE80211_MODE_TURBO_A:
1942 if (IEEE80211_IS_CHAN_A(c)) {
1943 c2 = findchannel(ic, ireq->i_val,
1944 IEEE80211_MODE_TURBO_A);
1945 if (c2 != NULL)
1946 c = c2;
1947 }
1948 break;
1949 case IEEE80211_MODE_11NA:
1950 if (IEEE80211_IS_CHAN_A(c)) {
1951 c2 = findchannel(ic, ireq->i_val,
1952 IEEE80211_MODE_11NA);
1953 if (c2 != NULL)
1954 c = c2;
1955 }
1956 break;
1957 case IEEE80211_MODE_11NG:
1958 if (IEEE80211_IS_CHAN_ANYG(c)) {
1959 c2 = findchannel(ic, ireq->i_val,
1960 IEEE80211_MODE_11NG);
1961 if (c2 != NULL)
1962 c = c2;
1963 }
1964 break;
1965 default: /* NB: no static turboG */
1966 break;
1967 }
1968 }
1969 return setcurchan(vap, c);
1970}
1971
1972/*
1973 * New/current api for setting the current channel; a complete
1974 * channel description is provide so there is no ambiguity in
1975 * identifying the channel.
1976 */
1977static __noinline int
1978ieee80211_ioctl_setcurchan(struct ieee80211vap *vap,
1979 const struct ieee80211req *ireq)
1980{
1981 struct ieee80211com *ic = vap->iv_ic;
1982 struct ieee80211_channel chan, *c;
1983 int error;
1984
1985 if (ireq->i_len != sizeof(chan))
1986 return EINVAL;
1987 error = copyin(ireq->i_data, &chan, sizeof(chan));
1988 if (error != 0)
1989 return error;
1990 /* XXX 0xffff overflows 16-bit signed */
1991 if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
1992 c = IEEE80211_CHAN_ANYC;
1993 } else {
1994 c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
1995 if (c == NULL)
1996 return EINVAL;
1997 }
1998 return setcurchan(vap, c);
1999}
2000
2001static __noinline int
2002ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
2003 const struct ieee80211req *ireq)
2004{
2005 struct ieee80211_regdomain_req *reg;
2006 int nchans, error;
2007
2008 nchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_regdomain_req)) /
2009 sizeof(struct ieee80211_channel));
2010 if (!(1 <= nchans && nchans <= IEEE80211_CHAN_MAX)) {
2011 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2012 "%s: bad # chans, i_len %d nchans %d\n", __func__,
2013 ireq->i_len, nchans);
2014 return EINVAL;
2015 }
2016 reg = (struct ieee80211_regdomain_req *)
2017 malloc(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP, M_NOWAIT);
2018 if (reg == NULL) {
2019 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2020 "%s: no memory, nchans %d\n", __func__, nchans);
2021 return ENOMEM;
2022 }
2023 error = copyin(ireq->i_data, reg, IEEE80211_REGDOMAIN_SIZE(nchans));
2024 if (error == 0) {
2025 /* NB: validate inline channel count against storage size */
2026 if (reg->chaninfo.ic_nchans != nchans) {
2027 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2028 "%s: chan cnt mismatch, %d != %d\n", __func__,
2029 reg->chaninfo.ic_nchans, nchans);
2030 error = EINVAL;
2031 } else
2032 error = ieee80211_setregdomain(vap, reg);
2033 }
2034 free(reg, M_TEMP);
2035
2036 return (error == 0 ? ENETRESET : error);
2037}
2038
2039static int
2040ieee80211_ioctl_setroam(struct ieee80211vap *vap,
2041 const struct ieee80211req *ireq)
2042{
2043 if (ireq->i_len != sizeof(vap->iv_roamparms))
2044 return EINVAL;
2045 /* XXX validate params */
2046 /* XXX? ENETRESET to push to device? */
2047 return copyin(ireq->i_data, vap->iv_roamparms,
2048 sizeof(vap->iv_roamparms));
2049}
2050
2051static int
2052checkrate(const struct ieee80211_rateset *rs, int rate)
2053{
2054 int i;
2055
2056 if (rate == IEEE80211_FIXED_RATE_NONE)
2057 return 1;
2058 for (i = 0; i < rs->rs_nrates; i++)
2059 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
2060 return 1;
2061 return 0;
2062}
2063
2064static int
2065checkmcs(int mcs)
2066{
2067 if (mcs == IEEE80211_FIXED_RATE_NONE)
2068 return 1;
2069 if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */
2070 return 0;
2071 return (mcs & 0x7f) <= 15; /* XXX could search ht rate set */
2072}
2073
2074static __noinline int
2075ieee80211_ioctl_settxparams(struct ieee80211vap *vap,
2076 const struct ieee80211req *ireq)
2077{
2078 struct ieee80211com *ic = vap->iv_ic;
2079 struct ieee80211_txparams_req parms; /* XXX stack use? */
2080 struct ieee80211_txparam *src, *dst;
2081 const struct ieee80211_rateset *rs;
2082 int error, mode, changed, is11n, nmodes;
2083
2084 /* NB: accept short requests for backwards compat */
2085 if (ireq->i_len > sizeof(parms))
2086 return EINVAL;
2087 error = copyin(ireq->i_data, &parms, ireq->i_len);
2088 if (error != 0)
2089 return error;
2090 nmodes = ireq->i_len / sizeof(struct ieee80211_txparam);
2091 changed = 0;
2092 /* validate parameters and check if anything changed */
2093 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
2094 if (isclr(ic->ic_modecaps, mode))
2095 continue;
2096 src = &parms.params[mode];
2097 dst = &vap->iv_txparms[mode];
2098 rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */
2099 is11n = (mode == IEEE80211_MODE_11NA ||
2100 mode == IEEE80211_MODE_11NG);
2101 if (src->ucastrate != dst->ucastrate) {
2102 if (!checkrate(rs, src->ucastrate) &&
2103 (!is11n || !checkmcs(src->ucastrate)))
2104 return EINVAL;
2105 changed++;
2106 }
2107 if (src->mcastrate != dst->mcastrate) {
2108 if (!checkrate(rs, src->mcastrate) &&
2109 (!is11n || !checkmcs(src->mcastrate)))
2110 return EINVAL;
2111 changed++;
2112 }
2113 if (src->mgmtrate != dst->mgmtrate) {
2114 if (!checkrate(rs, src->mgmtrate) &&
2115 (!is11n || !checkmcs(src->mgmtrate)))
2116 return EINVAL;
2117 changed++;
2118 }
2119 if (src->maxretry != dst->maxretry) /* NB: no bounds */
2120 changed++;
2121 }
2122 if (changed) {
2123 /*
2124 * Copy new parameters in place and notify the
2125 * driver so it can push state to the device.
2126 */
2127 for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
2128 if (isset(ic->ic_modecaps, mode))
2129 vap->iv_txparms[mode] = parms.params[mode];
2130 }
2131 /* XXX could be more intelligent,
2132 e.g. don't reset if setting not being used */
2133 return ENETRESET;
2134 }
2135 return 0;
2136}
2137
2138/*
2139 * Application Information Element support.
2140 */
2141static int
2142setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
2143{
2144 struct ieee80211_appie *app = *aie;
2145 struct ieee80211_appie *napp;
2146 int error;
2147
2148 if (ireq->i_len == 0) { /* delete any existing ie */
2149 if (app != NULL) {
2150 *aie = NULL; /* XXX racey */
2151 free(app, M_80211_NODE_IE);
2152 }
2153 return 0;
2154 }
2155 if (!(2 <= ireq->i_len && ireq->i_len <= IEEE80211_MAX_APPIE))
2156 return EINVAL;
2157 /*
2158 * Allocate a new appie structure and copy in the user data.
2159 * When done swap in the new structure. Note that we do not
2160 * guard against users holding a ref to the old structure;
2161 * this must be handled outside this code.
2162 *
2163 * XXX bad bad bad
2164 */
2165 napp = (struct ieee80211_appie *) malloc(
2166 sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE, M_NOWAIT);
2167 if (napp == NULL)
2168 return ENOMEM;
2169 /* XXX holding ic lock */
2170 error = copyin(ireq->i_data, napp->ie_data, ireq->i_len);
2171 if (error) {
2172 free(napp, M_80211_NODE_IE);
2173 return error;
2174 }
2175 napp->ie_len = ireq->i_len;
2176 *aie = napp;
2177 if (app != NULL)
2178 free(app, M_80211_NODE_IE);
2179 return 0;
2180}
2181
2182static void
2183setwparsnie(struct ieee80211vap *vap, uint8_t *ie, int space)
2184{
2185 /* validate data is present as best we can */
2186 if (space == 0 || 2+ie[1] > space)
2187 return;
2188 if (ie[0] == IEEE80211_ELEMID_VENDOR)
2189 vap->iv_wpa_ie = ie;
2190 else if (ie[0] == IEEE80211_ELEMID_RSN)
2191 vap->iv_rsn_ie = ie;
2192}
2193
2194static __noinline int
2195ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap,
2196 const struct ieee80211req *ireq, int fc0)
2197{
2198 int error;
2199
2200 IEEE80211_LOCK_ASSERT(vap->iv_ic);
2201
2202 switch (fc0 & IEEE80211_FC0_SUBTYPE_MASK) {
2203 case IEEE80211_FC0_SUBTYPE_BEACON:
2204 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2205 vap->iv_opmode != IEEE80211_M_IBSS) {
2206 error = EINVAL;
2207 break;
2208 }
2209 error = setappie(&vap->iv_appie_beacon, ireq);
2210 if (error == 0)
2211 ieee80211_beacon_notify(vap, IEEE80211_BEACON_APPIE);
2212 break;
2213 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
2214 error = setappie(&vap->iv_appie_proberesp, ireq);
2215 break;
2216 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
2217 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
2218 error = setappie(&vap->iv_appie_assocresp, ireq);
2219 else
2220 error = EINVAL;
2221 break;
2222 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
2223 error = setappie(&vap->iv_appie_probereq, ireq);
2224 break;
2225 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
2226 if (vap->iv_opmode == IEEE80211_M_STA)
2227 error = setappie(&vap->iv_appie_assocreq, ireq);
2228 else
2229 error = EINVAL;
2230 break;
2231 case (IEEE80211_APPIE_WPA & IEEE80211_FC0_SUBTYPE_MASK):
2232 error = setappie(&vap->iv_appie_wpa, ireq);
2233 if (error == 0) {
2234 /*
2235 * Must split single blob of data into separate
2236 * WPA and RSN ie's because they go in different
2237 * locations in the mgt frames.
2238 * XXX use IEEE80211_IOC_WPA2 so user code does split
2239 */
2240 vap->iv_wpa_ie = NULL;
2241 vap->iv_rsn_ie = NULL;
2242 if (vap->iv_appie_wpa != NULL) {
2243 struct ieee80211_appie *appie =
2244 vap->iv_appie_wpa;
2245 uint8_t *data = appie->ie_data;
2246
2247 /* XXX ie length validate is painful, cheat */
2248 setwparsnie(vap, data, appie->ie_len);
2249 setwparsnie(vap, data + 2 + data[1],
2250 appie->ie_len - (2 + data[1]));
2251 }
2252 if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
2253 vap->iv_opmode == IEEE80211_M_IBSS) {
2254 /*
2255 * Must rebuild beacon frame as the update
2256 * mechanism doesn't handle WPA/RSN ie's.
2257 * Could extend it but it doesn't normally
2258 * change; this is just to deal with hostapd
2259 * plumbing the ie after the interface is up.
2260 */
2261 error = ENETRESET;
2262 }
2263 }
2264 break;
2265 default:
2266 error = EINVAL;
2267 break;
2268 }
2269 return error;
2270}
2271
2272static __noinline int
2273ieee80211_ioctl_setappie(struct ieee80211vap *vap,
2274 const struct ieee80211req *ireq)
2275{
2276 struct ieee80211com *ic = vap->iv_ic;
2277 int error;
2278 uint8_t fc0;
2279
2280 fc0 = ireq->i_val & 0xff;
2281 if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
2282 return EINVAL;
2283 /* NB: could check iv_opmode and reject but hardly worth the effort */
2284 IEEE80211_LOCK(ic);
2285 error = ieee80211_ioctl_setappie_locked(vap, ireq, fc0);
2286 IEEE80211_UNLOCK(ic);
2287 return error;
2288}
2289
2290static __noinline int
2291ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq)
2292{
2293 struct ieee80211com *ic = vap->iv_ic;
2294 struct ieee80211_chanswitch_req csr;
2295 struct ieee80211_channel *c;
2296 int error;
2297
2298 if (ireq->i_len != sizeof(csr))
2299 return EINVAL;
2300 error = copyin(ireq->i_data, &csr, sizeof(csr));
2301 if (error != 0)
2302 return error;
2303 if ((vap->iv_flags & IEEE80211_F_DOTH) == 0)
2304 return EINVAL;
2305 c = ieee80211_find_channel(ic,
2306 csr.csa_chan.ic_freq, csr.csa_chan.ic_flags);
2307 if (c == NULL)
2308 return ENOENT;
2309 IEEE80211_LOCK(ic);
2310 if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0)
2311 ieee80211_csa_startswitch(ic, c, csr.csa_mode, csr.csa_count);
2312 else
2313 error = EBUSY;
2314 IEEE80211_UNLOCK(ic);
2315 return error;
2316}
2317
2318static __noinline int
2319ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
2320{
2321#define IEEE80211_IOC_SCAN_FLAGS \
2322 (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \
2323 IEEE80211_IOC_SCAN_PICK1ST | IEEE80211_IOC_SCAN_BGSCAN | \
2324 IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOBCAST | \
2325 IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \
2326 IEEE80211_IOC_SCAN_CHECK)
2327 struct ieee80211com *ic = vap->iv_ic;
2328 struct ieee80211_scan_req sr; /* XXX off stack? */
2329 int error, i;
2330
2331 /* NB: parent must be running */
2332 if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
2333 return ENXIO;
2334
2335 if (ireq->i_len != sizeof(sr))
2336 return EINVAL;
2337 error = copyin(ireq->i_data, &sr, sizeof(sr));
2338 if (error != 0)
2339 return error;
2340 /* convert duration */
2341 if (sr.sr_duration == IEEE80211_IOC_SCAN_FOREVER)
2342 sr.sr_duration = IEEE80211_SCAN_FOREVER;
2343 else {
2344 if (sr.sr_duration < IEEE80211_IOC_SCAN_DURATION_MIN ||
2345 sr.sr_duration > IEEE80211_IOC_SCAN_DURATION_MAX)
2346 return EINVAL;
2347 sr.sr_duration = msecs_to_ticks(sr.sr_duration);
2348 if (sr.sr_duration < 1)
2349 sr.sr_duration = 1;
2350 }
2351 /* convert min/max channel dwell */
2352 if (sr.sr_mindwell != 0) {
2353 sr.sr_mindwell = msecs_to_ticks(sr.sr_mindwell);
2354 if (sr.sr_mindwell < 1)
2355 sr.sr_mindwell = 1;
2356 }
2357 if (sr.sr_maxdwell != 0) {
2358 sr.sr_maxdwell = msecs_to_ticks(sr.sr_maxdwell);
2359 if (sr.sr_maxdwell < 1)
2360 sr.sr_maxdwell = 1;
2361 }
2362 /* NB: silently reduce ssid count to what is supported */
2363 if (sr.sr_nssid > IEEE80211_SCAN_MAX_SSID)
2364 sr.sr_nssid = IEEE80211_SCAN_MAX_SSID;
2365 for (i = 0; i < sr.sr_nssid; i++)
2366 if (sr.sr_ssid[i].len > IEEE80211_NWID_LEN)
2367 return EINVAL;
2368 /* cleanse flags just in case, could reject if invalid flags */
2369 sr.sr_flags &= IEEE80211_IOC_SCAN_FLAGS;
2370 /*
2371 * Add an implicit NOPICK if the vap is not marked UP. This
2372 * allows applications to scan without joining a bss (or picking
2373 * a channel and setting up a bss) and without forcing manual
2374 * roaming mode--you just need to mark the parent device UP.
2375 */
2376 if ((vap->iv_ifp->if_flags & IFF_UP) == 0)
2377 sr.sr_flags |= IEEE80211_IOC_SCAN_NOPICK;
2378
2379 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
2380 "%s: flags 0x%x%s duration 0x%x mindwell %u maxdwell %u nssid %d\n",
2381 __func__, sr.sr_flags,
2382 (vap->iv_ifp->if_flags & IFF_UP) == 0 ? " (!IFF_UP)" : "",
2383 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, sr.sr_nssid);
2384 /*
2385 * If we are in INIT state then the driver has never had a chance
2386 * to setup hardware state to do a scan; we must use the state
2387 * machine to get us up to the SCAN state but once we reach SCAN
2388 * state we then want to use the supplied params. Stash the
2389 * parameters in the vap and mark IEEE80211_FEXT_SCANREQ; the
2390 * state machines will recognize this and use the stashed params
2391 * to issue the scan request.
2392 *
2393 * Otherwise just invoke the scan machinery directly.
2394 */
2395 IEEE80211_LOCK(ic);
2396 if (vap->iv_state == IEEE80211_S_INIT) {
2397 /* NB: clobbers previous settings */
2398 vap->iv_scanreq_flags = sr.sr_flags;
2399 vap->iv_scanreq_duration = sr.sr_duration;
2400 vap->iv_scanreq_nssid = sr.sr_nssid;
2401 for (i = 0; i < sr.sr_nssid; i++) {
2402 vap->iv_scanreq_ssid[i].len = sr.sr_ssid[i].len;
2403 memcpy(vap->iv_scanreq_ssid[i].ssid, sr.sr_ssid[i].ssid,
2404 sr.sr_ssid[i].len);
2405 }
2406 vap->iv_flags_ext |= IEEE80211_FEXT_SCANREQ;
2407 IEEE80211_UNLOCK(ic);
2408 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2409 } else {
2410 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
2411 IEEE80211_UNLOCK(ic);
2412 /* XXX neeed error return codes */
2413 if (sr.sr_flags & IEEE80211_IOC_SCAN_CHECK) {
2414 (void) ieee80211_check_scan(vap, sr.sr_flags,
2415 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell,
2416 sr.sr_nssid,
2417 /* NB: cheat, we assume structures are compatible */
2418 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]);
2419 } else {
2420 (void) ieee80211_start_scan(vap, sr.sr_flags,
2421 sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell,
2422 sr.sr_nssid,
2423 /* NB: cheat, we assume structures are compatible */
2424 (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]);
2425 }
2426 }
2427 return error;
2428#undef IEEE80211_IOC_SCAN_FLAGS
2429}
2430
2431static __noinline int
2432ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
2433{
2434 struct ieee80211_node *ni;
2435 struct ieee80211req_sta_vlan vlan;
2436 int error;
2437
2438 if (ireq->i_len != sizeof(vlan))
2439 return EINVAL;
2440 error = copyin(ireq->i_data, &vlan, sizeof(vlan));
2441 if (error != 0)
2442 return error;
2443 if (!IEEE80211_ADDR_EQ(vlan.sv_macaddr, zerobssid)) {
2444 ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap,
2445 vlan.sv_macaddr);
2446 if (ni == NULL)
2447 return ENOENT;
2448 } else
2449 ni = ieee80211_ref_node(vap->iv_bss);
2450 ni->ni_vlan = vlan.sv_vlan;
2451 ieee80211_free_node(ni);
2452 return error;
2453}
2454
2455static int
2456isvap11g(const struct ieee80211vap *vap)
2457{
2458 const struct ieee80211_node *bss = vap->iv_bss;
2459 return bss->ni_chan != IEEE80211_CHAN_ANYC &&
2460 IEEE80211_IS_CHAN_ANYG(bss->ni_chan);
2461}
2462
2463static int
2464isvapht(const struct ieee80211vap *vap)
2465{
2466 const struct ieee80211_node *bss = vap->iv_bss;
2467 return bss->ni_chan != IEEE80211_CHAN_ANYC &&
2468 IEEE80211_IS_CHAN_HT(bss->ni_chan);
2469}
2470
2471/*
2472 * Dummy ioctl set handler so the linker set is defined.
2473 */
2474static int
2475dummy_ioctl_set(struct ieee80211vap *vap, struct ieee80211req *ireq)
2476{
2477 return ENOSYS;
2478}
2479IEEE80211_IOCTL_SET(dummy, dummy_ioctl_set);
2480
2481static int
2482ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
2483{
2484 ieee80211_ioctl_setfunc * const *set;
2485 int error;
2486
2487 SET_FOREACH(set, ieee80211_ioctl_setset) {
2488 error = (*set)(vap, ireq);
2489 if (error != ENOSYS)
2490 return error;
2491 }
2492 return EINVAL;
2493}
2494
2495static __noinline int
2496ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq)
2497{
2498 struct ieee80211com *ic = vap->iv_ic;
2499 int error;
2500 const struct ieee80211_authenticator *auth;
2501 uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
2502 char tmpssid[IEEE80211_NWID_LEN];
2503 uint8_t tmpbssid[IEEE80211_ADDR_LEN];
2504 struct ieee80211_key *k;
2505 u_int kid;
2506 uint32_t flags;
2507
2508 error = 0;
2509 switch (ireq->i_type) {
2510 case IEEE80211_IOC_SSID:
2511 if (ireq->i_val != 0 ||
2512 ireq->i_len > IEEE80211_NWID_LEN)
2513 return EINVAL;
2514 error = copyin(ireq->i_data, tmpssid, ireq->i_len);
2515 if (error)
2516 break;
2517 memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
2518 vap->iv_des_ssid[0].len = ireq->i_len;
2519 memcpy(vap->iv_des_ssid[0].ssid, tmpssid, ireq->i_len);
2520 vap->iv_des_nssid = (ireq->i_len > 0);
2521 error = ENETRESET;
2522 break;
2523 case IEEE80211_IOC_WEP:
2524 switch (ireq->i_val) {
2525 case IEEE80211_WEP_OFF:
2526 vap->iv_flags &= ~IEEE80211_F_PRIVACY;
2527 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2528 break;
2529 case IEEE80211_WEP_ON:
2530 vap->iv_flags |= IEEE80211_F_PRIVACY;
2531 vap->iv_flags |= IEEE80211_F_DROPUNENC;
2532 break;
2533 case IEEE80211_WEP_MIXED:
2534 vap->iv_flags |= IEEE80211_F_PRIVACY;
2535 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2536 break;
2537 }
2538 error = ENETRESET;
2539 break;
2540 case IEEE80211_IOC_WEPKEY:
2541 kid = (u_int) ireq->i_val;
2542 if (kid >= IEEE80211_WEP_NKID)
2543 return EINVAL;
2544 k = &vap->iv_nw_keys[kid];
2545 if (ireq->i_len == 0) {
2546 /* zero-len =>'s delete any existing key */
2547 (void) ieee80211_crypto_delkey(vap, k);
2548 break;
2549 }
2550 if (ireq->i_len > sizeof(tmpkey))
2551 return EINVAL;
2552 memset(tmpkey, 0, sizeof(tmpkey));
2553 error = copyin(ireq->i_data, tmpkey, ireq->i_len);
2554 if (error)
2555 break;
2556 ieee80211_key_update_begin(vap);
2557 k->wk_keyix = kid; /* NB: force fixed key id */
2558 if (ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP,
2559 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
2560 k->wk_keylen = ireq->i_len;
2561 memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
2562 IEEE80211_ADDR_COPY(k->wk_macaddr, vap->iv_myaddr);
2563 if (!ieee80211_crypto_setkey(vap, k))
2564 error = EINVAL;
2565 } else
2566 error = EINVAL;
2567 ieee80211_key_update_end(vap);
2568 break;
2569 case IEEE80211_IOC_WEPTXKEY:
2570 kid = (u_int) ireq->i_val;
2571 if (kid >= IEEE80211_WEP_NKID &&
2572 (uint16_t) kid != IEEE80211_KEYIX_NONE)
2573 return EINVAL;
2574 vap->iv_def_txkey = kid;
2575 break;
2576 case IEEE80211_IOC_AUTHMODE:
2577 switch (ireq->i_val) {
2578 case IEEE80211_AUTH_WPA:
2579 case IEEE80211_AUTH_8021X: /* 802.1x */
2580 case IEEE80211_AUTH_OPEN: /* open */
2581 case IEEE80211_AUTH_SHARED: /* shared-key */
2582 case IEEE80211_AUTH_AUTO: /* auto */
2583 auth = ieee80211_authenticator_get(ireq->i_val);
2584 if (auth == NULL)
2585 return EINVAL;
2586 break;
2587 default:
2588 return EINVAL;
2589 }
2590 switch (ireq->i_val) {
2591 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */
2592 vap->iv_flags |= IEEE80211_F_PRIVACY;
2593 ireq->i_val = IEEE80211_AUTH_8021X;
2594 break;
2595 case IEEE80211_AUTH_OPEN: /* open */
2596 vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
2597 break;
2598 case IEEE80211_AUTH_SHARED: /* shared-key */
2599 case IEEE80211_AUTH_8021X: /* 802.1x */
2600 vap->iv_flags &= ~IEEE80211_F_WPA;
2601 /* both require a key so mark the PRIVACY capability */
2602 vap->iv_flags |= IEEE80211_F_PRIVACY;
2603 break;
2604 case IEEE80211_AUTH_AUTO: /* auto */
2605 vap->iv_flags &= ~IEEE80211_F_WPA;
2606 /* XXX PRIVACY handling? */
2607 /* XXX what's the right way to do this? */
2608 break;
2609 }
2610 /* NB: authenticator attach/detach happens on state change */
2611 vap->iv_bss->ni_authmode = ireq->i_val;
2612 /* XXX mixed/mode/usage? */
2613 vap->iv_auth = auth;
2614 error = ENETRESET;
2615 break;
2616 case IEEE80211_IOC_CHANNEL:
2617 error = ieee80211_ioctl_setchannel(vap, ireq);
2618 break;
2619 case IEEE80211_IOC_POWERSAVE:
2620 switch (ireq->i_val) {
2621 case IEEE80211_POWERSAVE_OFF:
2622 if (vap->iv_flags & IEEE80211_F_PMGTON) {
2623 ieee80211_syncflag(vap, -IEEE80211_F_PMGTON);
2624 error = ERESTART;
2625 }
2626 break;
2627 case IEEE80211_POWERSAVE_ON:
2628 if ((vap->iv_caps & IEEE80211_C_PMGT) == 0)
2629 error = EOPNOTSUPP;
2630 else if ((vap->iv_flags & IEEE80211_F_PMGTON) == 0) {
2631 ieee80211_syncflag(vap, IEEE80211_F_PMGTON);
2632 error = ERESTART;
2633 }
2634 break;
2635 default:
2636 error = EINVAL;
2637 break;
2638 }
2639 break;
2640 case IEEE80211_IOC_POWERSAVESLEEP:
2641 if (ireq->i_val < 0)
2642 return EINVAL;
2643 ic->ic_lintval = ireq->i_val;
2644 error = ERESTART;
2645 break;
2646 case IEEE80211_IOC_RTSTHRESHOLD:
2647 if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
2648 ireq->i_val <= IEEE80211_RTS_MAX))
2649 return EINVAL;
2650 vap->iv_rtsthreshold = ireq->i_val;
2651 error = ERESTART;
2652 break;
2653 case IEEE80211_IOC_PROTMODE:
2654 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2655 return EINVAL;
2656 ic->ic_protmode = ireq->i_val;
2657 /* NB: if not operating in 11g this can wait */
2658 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2659 IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2660 error = ERESTART;
2661 break;
2662 case IEEE80211_IOC_TXPOWER:
2663 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2664 return EOPNOTSUPP;
2665 if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2666 ireq->i_val <= IEEE80211_TXPOWER_MAX))
2667 return EINVAL;
2668 ic->ic_txpowlimit = ireq->i_val;
2669 error = ERESTART;
2670 break;
2671 case IEEE80211_IOC_ROAMING:
2672 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2673 ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2674 return EINVAL;
2675 vap->iv_roaming = ireq->i_val;
2676 /* XXXX reset? */
2677 break;
2678 case IEEE80211_IOC_PRIVACY:
2679 if (ireq->i_val) {
2680 /* XXX check for key state? */
2681 vap->iv_flags |= IEEE80211_F_PRIVACY;
2682 } else
2683 vap->iv_flags &= ~IEEE80211_F_PRIVACY;
2684 /* XXX ERESTART? */
2685 break;
2686 case IEEE80211_IOC_DROPUNENCRYPTED:
2687 if (ireq->i_val)
2688 vap->iv_flags |= IEEE80211_F_DROPUNENC;
2689 else
2690 vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
2691 /* XXX ERESTART? */
2692 break;
2693 case IEEE80211_IOC_WPAKEY:
2694 error = ieee80211_ioctl_setkey(vap, ireq);
2695 break;
2696 case IEEE80211_IOC_DELKEY:
2697 error = ieee80211_ioctl_delkey(vap, ireq);
2698 break;
2699 case IEEE80211_IOC_MLME:
2700 error = ieee80211_ioctl_setmlme(vap, ireq);
2701 break;
2702 case IEEE80211_IOC_COUNTERMEASURES:
2703 if (ireq->i_val) {
2704 if ((vap->iv_flags & IEEE80211_F_WPA) == 0)
2705 return EOPNOTSUPP;
2706 vap->iv_flags |= IEEE80211_F_COUNTERM;
2707 } else
2708 vap->iv_flags &= ~IEEE80211_F_COUNTERM;
2709 /* XXX ERESTART? */
2710 break;
2711 case IEEE80211_IOC_WPA:
2712 if (ireq->i_val > 3)
2713 return EINVAL;
2714 /* XXX verify ciphers available */
2715 flags = vap->iv_flags & ~IEEE80211_F_WPA;
2716 switch (ireq->i_val) {
2717 case 1:
2718 if (!(vap->iv_caps & IEEE80211_C_WPA1))
2719 return EOPNOTSUPP;
2720 flags |= IEEE80211_F_WPA1;
2721 break;
2722 case 2:
2723 if (!(vap->iv_caps & IEEE80211_C_WPA2))
2724 return EOPNOTSUPP;
2725 flags |= IEEE80211_F_WPA2;
2726 break;
2727 case 3:
2728 if ((vap->iv_caps & IEEE80211_C_WPA) != IEEE80211_C_WPA)
2729 return EOPNOTSUPP;
2730 flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2731 break;
2732 default: /* Can't set any -> error */
2733 return EOPNOTSUPP;
2734 }
2735 vap->iv_flags = flags;
2736 error = ERESTART; /* NB: can change beacon frame */
2737 break;
2738 case IEEE80211_IOC_WME:
2739 if (ireq->i_val) {
2740 if ((vap->iv_caps & IEEE80211_C_WME) == 0)
2741 return EOPNOTSUPP;
2742 ieee80211_syncflag(vap, IEEE80211_F_WME);
2743 } else
2744 ieee80211_syncflag(vap, -IEEE80211_F_WME);
2745 error = ERESTART; /* NB: can change beacon frame */
2746 break;
2747 case IEEE80211_IOC_HIDESSID:
2748 if (ireq->i_val)
2749 vap->iv_flags |= IEEE80211_F_HIDESSID;
2750 else
2751 vap->iv_flags &= ~IEEE80211_F_HIDESSID;
2752 error = ERESTART; /* XXX ENETRESET? */
2753 break;
2754 case IEEE80211_IOC_APBRIDGE:
2755 if (ireq->i_val == 0)
2756 vap->iv_flags |= IEEE80211_F_NOBRIDGE;
2757 else
2758 vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
2759 break;
2760 case IEEE80211_IOC_BSSID:
2761 if (ireq->i_len != sizeof(tmpbssid))
2762 return EINVAL;
2763 error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2764 if (error)
2765 break;
2766 IEEE80211_ADDR_COPY(vap->iv_des_bssid, tmpbssid);
2767 if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zerobssid))
2768 vap->iv_flags &= ~IEEE80211_F_DESBSSID;
2769 else
2770 vap->iv_flags |= IEEE80211_F_DESBSSID;
2771 error = ENETRESET;
2772 break;
2773 case IEEE80211_IOC_CHANLIST:
2774 error = ieee80211_ioctl_setchanlist(vap, ireq);
2775 break;
2776#define OLD_IEEE80211_IOC_SCAN_REQ 23
2777#ifdef OLD_IEEE80211_IOC_SCAN_REQ
2778 case OLD_IEEE80211_IOC_SCAN_REQ:
2779 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
2780 "%s: active scan request\n", __func__);
2781 /*
2782 * If we are in INIT state then the driver has never
2783 * had a chance to setup hardware state to do a scan;
2784 * use the state machine to get us up the SCAN state.
2785 * Otherwise just invoke the scan machinery to start
2786 * a one-time scan.
2787 */
2788 if (vap->iv_state == IEEE80211_S_INIT)
2789 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
2790 else
2791 (void) ieee80211_start_scan(vap,
2792 IEEE80211_SCAN_ACTIVE |
2793 IEEE80211_SCAN_NOPICK |
2794 IEEE80211_SCAN_ONCE,
2795 IEEE80211_SCAN_FOREVER, 0, 0,
2796 /* XXX use ioctl params */
2797 vap->iv_des_nssid, vap->iv_des_ssid);
2798 break;
2799#endif /* OLD_IEEE80211_IOC_SCAN_REQ */
2800 case IEEE80211_IOC_SCAN_REQ:
2801 error = ieee80211_ioctl_scanreq(vap, ireq);
2802 break;
2803 case IEEE80211_IOC_SCAN_CANCEL:
2804 IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
2805 "%s: cancel scan\n", __func__);
2806 ieee80211_cancel_scan(vap);
2807 break;
2808 case IEEE80211_IOC_HTCONF:
2809 if (ireq->i_val & 1)
2810 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_HT);
2811 else
2812 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_HT);
2813 if (ireq->i_val & 2)
2814 ieee80211_syncflag_ext(vap, IEEE80211_FEXT_USEHT40);
2815 else
2816 ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_USEHT40);
2817 error = ENETRESET;
2818 break;
2819 case IEEE80211_IOC_ADDMAC:
2820 case IEEE80211_IOC_DELMAC:
2821 error = ieee80211_ioctl_macmac(vap, ireq);
2822 break;
2823 case IEEE80211_IOC_MACCMD:
2824 error = ieee80211_ioctl_setmaccmd(vap, ireq);
2825 break;
2826 case IEEE80211_IOC_STA_STATS:
2827 error = ieee80211_ioctl_setstastats(vap, ireq);
2828 break;
2829 case IEEE80211_IOC_STA_TXPOW:
2830 error = ieee80211_ioctl_setstatxpow(vap, ireq);
2831 break;
2832 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
2833 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
2834 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
2835 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
2836 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
2837 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
2838 error = ieee80211_ioctl_setwmeparam(vap, ireq);
2839 break;
2840 case IEEE80211_IOC_DTIM_PERIOD:
2841 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2842 vap->iv_opmode != IEEE80211_M_IBSS)
2843 return EINVAL;
2844 if (IEEE80211_DTIM_MIN <= ireq->i_val &&
2845 ireq->i_val <= IEEE80211_DTIM_MAX) {
2846 vap->iv_dtim_period = ireq->i_val;
2847 error = ENETRESET; /* requires restart */
2848 } else
2849 error = EINVAL;
2850 break;
2851 case IEEE80211_IOC_BEACON_INTERVAL:
2852 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
2853 vap->iv_opmode != IEEE80211_M_IBSS)
2854 return EINVAL;
2855 if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
2856 ireq->i_val <= IEEE80211_BINTVAL_MAX) {
2857 ic->ic_bintval = ireq->i_val;
2858 error = ENETRESET; /* requires restart */
2859 } else
2860 error = EINVAL;
2861 break;
2862 case IEEE80211_IOC_PUREG:
2863 if (ireq->i_val)
2864 vap->iv_flags |= IEEE80211_F_PUREG;
2865 else
2866 vap->iv_flags &= ~IEEE80211_F_PUREG;
2867 /* NB: reset only if we're operating on an 11g channel */
2868 if (isvap11g(vap))
2869 error = ENETRESET;
2870 break;
2892 case IEEE80211_IOC_FF:
2893 if (ireq->i_val) {
2894 if ((vap->iv_caps & IEEE80211_C_FF) == 0)
2895 return EOPNOTSUPP;
2896 vap->iv_flags |= IEEE80211_F_FF;
2897 } else
2898 vap->iv_flags &= ~IEEE80211_F_FF;
2899 error = ERESTART;
2900 break;
2901 case IEEE80211_IOC_TURBOP:
2902 if (ireq->i_val) {
2903 if ((vap->iv_caps & IEEE80211_C_TURBOP) == 0)
2904 return EOPNOTSUPP;
2905 vap->iv_flags |= IEEE80211_F_TURBOP;
2906 } else
2907 vap->iv_flags &= ~IEEE80211_F_TURBOP;
2908 error = ENETRESET;
2909 break;
2910 case IEEE80211_IOC_BGSCAN:
2911 if (ireq->i_val) {
2912 if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
2913 return EOPNOTSUPP;
2914 vap->iv_flags |= IEEE80211_F_BGSCAN;
2915 } else
2916 vap->iv_flags &= ~IEEE80211_F_BGSCAN;
2917 break;
2918 case IEEE80211_IOC_BGSCAN_IDLE:
2919 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2920 vap->iv_bgscanidle = ireq->i_val*hz/1000;
2921 else
2922 error = EINVAL;
2923 break;
2924 case IEEE80211_IOC_BGSCAN_INTERVAL:
2925 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2926 vap->iv_bgscanintvl = ireq->i_val*hz;
2927 else
2928 error = EINVAL;
2929 break;
2930 case IEEE80211_IOC_SCANVALID:
2931 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2932 vap->iv_scanvalid = ireq->i_val*hz;
2933 else
2934 error = EINVAL;
2935 break;
2936 case IEEE80211_IOC_FRAGTHRESHOLD:
2937 if ((vap->iv_caps & IEEE80211_C_TXFRAG) == 0 &&
2938 ireq->i_val != IEEE80211_FRAG_MAX)
2939 return EOPNOTSUPP;
2940 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
2941 ireq->i_val <= IEEE80211_FRAG_MAX))
2942 return EINVAL;
2943 vap->iv_fragthreshold = ireq->i_val;
2944 error = ERESTART;
2945 break;
2946 case IEEE80211_IOC_BURST:
2947 if (ireq->i_val) {
2948 if ((vap->iv_caps & IEEE80211_C_BURST) == 0)
2949 return EOPNOTSUPP;
2950 ieee80211_syncflag(vap, IEEE80211_F_BURST);
2951 } else
2952 ieee80211_syncflag(vap, -IEEE80211_F_BURST);
2953 error = ERESTART;
2954 break;
2955 case IEEE80211_IOC_BMISSTHRESHOLD:
2956 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2957 ireq->i_val <= IEEE80211_HWBMISS_MAX))
2958 return EINVAL;
2959 vap->iv_bmissthreshold = ireq->i_val;
2960 error = ERESTART;
2961 break;
2962 case IEEE80211_IOC_CURCHAN:
2963 error = ieee80211_ioctl_setcurchan(vap, ireq);
2964 break;
2965 case IEEE80211_IOC_SHORTGI:
2966 if (ireq->i_val) {
2967#define IEEE80211_HTCAP_SHORTGI \
2968 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2969 if (((ireq->i_val ^ vap->iv_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2970 return EINVAL;
2971 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2972 vap->iv_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2973 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2974 vap->iv_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2975#undef IEEE80211_HTCAP_SHORTGI
2976 } else
2977 vap->iv_flags_ext &=
2978 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2979 error = ERESTART;
2980 break;
2981 case IEEE80211_IOC_AMPDU:
2982 if (ireq->i_val && (vap->iv_htcaps & IEEE80211_HTC_AMPDU) == 0)
2983 return EINVAL;
2984 if (ireq->i_val & 1)
2985 vap->iv_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2986 else
2987 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMPDU_TX;
2988 if (ireq->i_val & 2)
2989 vap->iv_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2990 else
2991 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMPDU_RX;
2992 /* NB: reset only if we're operating on an 11n channel */
2993 if (isvapht(vap))
2994 error = ERESTART;
2995 break;
2996 case IEEE80211_IOC_AMPDU_LIMIT:
2997 if (!(IEEE80211_HTCAP_MAXRXAMPDU_8K <= ireq->i_val &&
2998 ireq->i_val <= IEEE80211_HTCAP_MAXRXAMPDU_64K))
2999 return EINVAL;
3000 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
3001 vap->iv_ampdu_rxmax = ireq->i_val;
3002 else
3003 vap->iv_ampdu_limit = ireq->i_val;
3004 error = ERESTART;
3005 break;
3006 case IEEE80211_IOC_AMPDU_DENSITY:
3007 if (!(IEEE80211_HTCAP_MPDUDENSITY_NA <= ireq->i_val &&
3008 ireq->i_val <= IEEE80211_HTCAP_MPDUDENSITY_16))
3009 return EINVAL;
3010 vap->iv_ampdu_density = ireq->i_val;
3011 error = ERESTART;
3012 break;
3013 case IEEE80211_IOC_AMSDU:
3014 if (ireq->i_val && (vap->iv_htcaps & IEEE80211_HTC_AMSDU) == 0)
3015 return EINVAL;
3016 if (ireq->i_val & 1)
3017 vap->iv_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
3018 else
3019 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMSDU_TX;
3020 if (ireq->i_val & 2)
3021 vap->iv_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
3022 else
3023 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMSDU_RX;
3024 /* NB: reset only if we're operating on an 11n channel */
3025 if (isvapht(vap))
3026 error = ERESTART;
3027 break;
3028 case IEEE80211_IOC_AMSDU_LIMIT:
3029 /* XXX validate */
3030 vap->iv_amsdu_limit = ireq->i_val; /* XXX truncation? */
3031 break;
3032 case IEEE80211_IOC_PUREN:
3033 if (ireq->i_val) {
3034 if ((vap->iv_flags_ext & IEEE80211_FEXT_HT) == 0)
3035 return EINVAL;
3036 vap->iv_flags_ext |= IEEE80211_FEXT_PUREN;
3037 } else
3038 vap->iv_flags_ext &= ~IEEE80211_FEXT_PUREN;
3039 /* NB: reset only if we're operating on an 11n channel */
3040 if (isvapht(vap))
3041 error = ERESTART;
3042 break;
3043 case IEEE80211_IOC_DOTH:
3044 if (ireq->i_val) {
3045#if 0
3046 /* XXX no capability */
3047 if ((vap->iv_caps & IEEE80211_C_DOTH) == 0)
3048 return EOPNOTSUPP;
3049#endif
3050 vap->iv_flags |= IEEE80211_F_DOTH;
3051 } else
3052 vap->iv_flags &= ~IEEE80211_F_DOTH;
3053 error = ENETRESET;
3054 break;
3055 case IEEE80211_IOC_REGDOMAIN:
3056 error = ieee80211_ioctl_setregdomain(vap, ireq);
3057 break;
3058 case IEEE80211_IOC_ROAM:
3059 error = ieee80211_ioctl_setroam(vap, ireq);
3060 break;
3061 case IEEE80211_IOC_TXPARAMS:
3062 error = ieee80211_ioctl_settxparams(vap, ireq);
3063 break;
3064 case IEEE80211_IOC_HTCOMPAT:
3065 if (ireq->i_val) {
3066 if ((vap->iv_flags_ext & IEEE80211_FEXT_HT) == 0)
3067 return EOPNOTSUPP;
3068 vap->iv_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
3069 } else
3070 vap->iv_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
3071 /* NB: reset only if we're operating on an 11n channel */
3072 if (isvapht(vap))
3073 error = ERESTART;
3074 break;
3075 case IEEE80211_IOC_DWDS:
3076 if (ireq->i_val) {
3077 /* NB: DWDS only makes sense for WDS-capable devices */
3078 if ((ic->ic_caps & IEEE80211_C_WDS) == 0)
3079 return EOPNOTSUPP;
3080 /* NB: DWDS is used only with ap+sta vaps */
3081 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
3082 vap->iv_opmode != IEEE80211_M_STA)
3083 return EINVAL;
3084 vap->iv_flags |= IEEE80211_F_DWDS;
3085 } else
3086 vap->iv_flags &= ~IEEE80211_F_DWDS;
3087 break;
3088 case IEEE80211_IOC_INACTIVITY:
3089 if (ireq->i_val)
3090 vap->iv_flags_ext |= IEEE80211_FEXT_INACT;
3091 else
3092 vap->iv_flags_ext &= ~IEEE80211_FEXT_INACT;
3093 break;
3094 case IEEE80211_IOC_APPIE:
3095 error = ieee80211_ioctl_setappie(vap, ireq);
3096 break;
3097 case IEEE80211_IOC_WPS:
3098 if (ireq->i_val) {
3099 if ((vap->iv_caps & IEEE80211_C_WPA) == 0)
3100 return EOPNOTSUPP;
3101 vap->iv_flags_ext |= IEEE80211_FEXT_WPS;
3102 } else
3103 vap->iv_flags_ext &= ~IEEE80211_FEXT_WPS;
3104 break;
3105 case IEEE80211_IOC_TSN:
3106 if (ireq->i_val) {
3107 if ((vap->iv_caps & IEEE80211_C_WPA) == 0)
3108 return EOPNOTSUPP;
3109 vap->iv_flags_ext |= IEEE80211_FEXT_TSN;
3110 } else
3111 vap->iv_flags_ext &= ~IEEE80211_FEXT_TSN;
3112 break;
3113 case IEEE80211_IOC_CHANSWITCH:
3114 error = ieee80211_ioctl_chanswitch(vap, ireq);
3115 break;
3116 case IEEE80211_IOC_DFS:
3117 if (ireq->i_val) {
3118 if ((vap->iv_caps & IEEE80211_C_DFS) == 0)
3119 return EOPNOTSUPP;
3120 /* NB: DFS requires 11h support */
3121 if ((vap->iv_flags & IEEE80211_F_DOTH) == 0)
3122 return EINVAL;
3123 vap->iv_flags_ext |= IEEE80211_FEXT_DFS;
3124 } else
3125 vap->iv_flags_ext &= ~IEEE80211_FEXT_DFS;
3126 break;
3127 case IEEE80211_IOC_DOTD:
3128 if (ireq->i_val)
3129 vap->iv_flags_ext |= IEEE80211_FEXT_DOTD;
3130 else
3131 vap->iv_flags_ext &= ~IEEE80211_FEXT_DOTD;
3132 if (vap->iv_opmode == IEEE80211_M_STA)
3133 error = ENETRESET;
3134 break;
3135 case IEEE80211_IOC_HTPROTMODE:
3136 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
3137 return EINVAL;
3138 ic->ic_htprotmode = ireq->i_val ?
3139 IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE;
3140 /* NB: if not operating in 11n this can wait */
3141 if (isvapht(vap))
3142 error = ERESTART;
3143 break;
3144 case IEEE80211_IOC_STA_VLAN:
3145 error = ieee80211_ioctl_setstavlan(vap, ireq);
3146 break;
3147 case IEEE80211_IOC_SMPS:
3148 if ((ireq->i_val &~ IEEE80211_HTCAP_SMPS) != 0 ||
3149 ireq->i_val == 0x0008) /* value of 2 is reserved */
3150 return EINVAL;
3151 if (ireq->i_val != IEEE80211_HTCAP_SMPS_OFF &&
3152 (vap->iv_htcaps & IEEE80211_HTC_SMPS) == 0)
3153 return EOPNOTSUPP;
3154 vap->iv_htcaps = (vap->iv_htcaps &~ IEEE80211_HTCAP_SMPS) |
3155 ireq->i_val;
3156 /* NB: if not operating in 11n this can wait */
3157 if (isvapht(vap))
3158 error = ERESTART;
3159 break;
3160 case IEEE80211_IOC_RIFS:
3161 if (ireq->i_val != 0) {
3162 if ((vap->iv_htcaps & IEEE80211_HTC_RIFS) == 0)
3163 return EOPNOTSUPP;
3164 vap->iv_flags_ext |= IEEE80211_FEXT_RIFS;
3165 } else
3166 vap->iv_flags_ext &= ~IEEE80211_FEXT_RIFS;
3167 /* NB: if not operating in 11n this can wait */
3168 if (isvapht(vap))
3169 error = ERESTART;
3170 break;
3171 default:
3172 error = ieee80211_ioctl_setdefault(vap, ireq);
3173 break;
3174 }
3175 /*
3176 * The convention is that ENETRESET means an operation
3177 * requires a complete re-initialization of the device (e.g.
3178 * changing something that affects the association state).
3179 * ERESTART means the request may be handled with only a
3180 * reload of the hardware state. We hand ERESTART requests
3181 * to the iv_reset callback so the driver can decide. If
3182 * a device does not fillin iv_reset then it defaults to one
3183 * that returns ENETRESET. Otherwise a driver may return
3184 * ENETRESET (in which case a full reset will be done) or
3185 * 0 to mean there's no need to do anything (e.g. when the
3186 * change has no effect on the driver/device).
3187 */
3188 if (error == ERESTART)
3189 error = IFNET_IS_UP_RUNNING(vap->iv_ifp) ?
3190 vap->iv_reset(vap, ireq->i_type) : 0;
3191 if (error == ENETRESET) {
3192 /* XXX need to re-think AUTO handling */
3193 if (IS_UP_AUTO(vap))
3194 ieee80211_init(vap);
3195 error = 0;
3196 }
3197 return error;
3198}
3199
3200/*
3201 * Rebuild the parent's multicast address list after an add/del
3202 * of a multicast address for a vap. We have no way to tell
3203 * what happened above to optimize the work so we purge the entire
3204 * list and rebuild from scratch. This is way expensive.
3205 * Note also the half-baked workaround for if_addmulti calling
3206 * back to the parent device; there's no way to insert mcast
3207 * entries quietly and/or cheaply.
3208 */
3209static void
3210ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
3211{
3212 struct ifnet *parent = ic->ic_ifp;
3213 struct ieee80211vap *vap;
3214 void *ioctl;
3215
3216 IEEE80211_LOCK(ic);
3217 if_purgemaddrs(parent);
3218 ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
3219 parent->if_ioctl = NULL;
3220 TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
3221 struct ifnet *ifp = vap->iv_ifp;
3222 struct ifmultiaddr *ifma;
3223
3224 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
3225 (void) if_addmulti(parent, ifma->ifma_addr, NULL);
3226 }
3227 parent->if_ioctl = ioctl;
3228
3229 ic->ic_update_mcast(ic->ic_ifp);
3230 IEEE80211_UNLOCK(ic);
3231}
3232
3233int
3234ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
3235{
3236 struct ieee80211vap *vap;
3237 struct ieee80211com *ic;
3238 int error = 0;
3239 struct ifreq *ifr;
3240 struct ifaddr *ifa; /* XXX */
3241
3242 vap = ifp->if_softc;
3243 if (vap == NULL) {
3244 /*
3245 * During detach we clear the backpointer in the softc
3246 * so any ioctl request through the ifnet that arrives
3247 * before teardown is ignored/rejected. In particular
3248 * this hack handles destroying a vap used by an app
3249 * like wpa_supplicant that will respond to the vap
3250 * being forced into INIT state by immediately trying
3251 * to force it back up. We can yank this hack if/when
3252 * we can destroy the ifnet before cleaning up vap state.
3253 */
3254 return ENXIO;
3255 }
3256 switch (cmd) {
3257 case SIOCSIFFLAGS:
3258 ic = vap->iv_ic;
3259 IEEE80211_LOCK(ic);
3260 ieee80211_syncifflag_locked(ic, IFF_PROMISC);
3261 ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
3262 if (ifp->if_flags & IFF_UP) {
3263 /*
3264 * Bring ourself up unless we're already operational.
3265 * If we're the first vap and the parent is not up
3266 * then it will automatically be brought up as a
3267 * side-effect of bringing ourself up.
3268 */
3269 if (vap->iv_state == IEEE80211_S_INIT)
3270 ieee80211_start_locked(vap);
3271 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3272 /*
3273 * Stop ourself. If we are the last vap to be
3274 * marked down the parent will also be taken down.
3275 */
3276 ieee80211_stop_locked(vap);
3277 }
3278 IEEE80211_UNLOCK(ic);
3279 /* Wait for parent ioctl handler if it was queued */
3280 ieee80211_waitfor_parent(ic);
3281 break;
3282 case SIOCADDMULTI:
3283 case SIOCDELMULTI:
3284 ieee80211_ioctl_updatemulti(vap->iv_ic);
3285 break;
3286 case SIOCSIFMEDIA:
3287 case SIOCGIFMEDIA:
3288 ifr = (struct ifreq *)data;
3289 error = ifmedia_ioctl(ifp, ifr, &vap->iv_media, cmd);
3290 break;
3291 case SIOCG80211:
3292 error = ieee80211_ioctl_get80211(vap, cmd,
3293 (struct ieee80211req *) data);
3294 break;
3295 case SIOCS80211:
3296 error = priv_check(curthread, PRIV_NET80211_MANAGE);
3297 if (error == 0)
3298 error = ieee80211_ioctl_set80211(vap, cmd,
3299 (struct ieee80211req *) data);
3300 break;
3301 case SIOCG80211STATS:
3302 ifr = (struct ifreq *)data;
3303 copyout(&vap->iv_stats, ifr->ifr_data, sizeof (vap->iv_stats));
3304 break;
3305 case SIOCSIFMTU:
3306 ifr = (struct ifreq *)data;
3307 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
3308 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
3309 error = EINVAL;
3310 else
3311 ifp->if_mtu = ifr->ifr_mtu;
3312 break;
3313 case SIOCSIFADDR:
3314 /*
3315 * XXX Handle this directly so we can supress if_init calls.
3316 * XXX This should be done in ether_ioctl but for the moment
3317 * XXX there are too many other parts of the system that
3318 * XXX set IFF_UP and so supress if_init being called when
3319 * XXX it should be.
3320 */
3321 ifa = (struct ifaddr *) data;
3322 switch (ifa->ifa_addr->sa_family) {
3323#ifdef INET
3324 case AF_INET:
3325 if ((ifp->if_flags & IFF_UP) == 0) {
3326 ifp->if_flags |= IFF_UP;
3327 ifp->if_init(ifp->if_softc);
3328 }
3329 arp_ifinit(ifp, ifa);
3330 break;
3331#endif
3332#ifdef IPX
3333 /*
3334 * XXX - This code is probably wrong,
3335 * but has been copied many times.
3336 */
3337 case AF_IPX: {
3338 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
3339
3340 if (ipx_nullhost(*ina))
3341 ina->x_host = *(union ipx_host *)
3342 IF_LLADDR(ifp);
3343 else
3344 bcopy((caddr_t) ina->x_host.c_host,
3345 (caddr_t) IF_LLADDR(ifp),
3346 ETHER_ADDR_LEN);
3347 /* fall thru... */
3348 }
3349#endif
3350 default:
3351 if ((ifp->if_flags & IFF_UP) == 0) {
3352 ifp->if_flags |= IFF_UP;
3353 ifp->if_init(ifp->if_softc);
3354 }
3355 break;
3356 }
3357 break;
3358 /* Pass NDIS ioctls up to the driver */
3359 case SIOCGDRVSPEC:
3360 case SIOCSDRVSPEC:
3361 case SIOCGPRIVATE_0: {
3362 struct ifnet *parent = vap->iv_ic->ic_ifp;
3363 error = parent->if_ioctl(parent, cmd, data);
3364 break;
3365 }
3366 default:
3367 error = ether_ioctl(ifp, cmd, data);
3368 break;
3369 }
3370 return error;
3371}
2871 case IEEE80211_IOC_BGSCAN:
2872 if (ireq->i_val) {
2873 if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
2874 return EOPNOTSUPP;
2875 vap->iv_flags |= IEEE80211_F_BGSCAN;
2876 } else
2877 vap->iv_flags &= ~IEEE80211_F_BGSCAN;
2878 break;
2879 case IEEE80211_IOC_BGSCAN_IDLE:
2880 if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2881 vap->iv_bgscanidle = ireq->i_val*hz/1000;
2882 else
2883 error = EINVAL;
2884 break;
2885 case IEEE80211_IOC_BGSCAN_INTERVAL:
2886 if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2887 vap->iv_bgscanintvl = ireq->i_val*hz;
2888 else
2889 error = EINVAL;
2890 break;
2891 case IEEE80211_IOC_SCANVALID:
2892 if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2893 vap->iv_scanvalid = ireq->i_val*hz;
2894 else
2895 error = EINVAL;
2896 break;
2897 case IEEE80211_IOC_FRAGTHRESHOLD:
2898 if ((vap->iv_caps & IEEE80211_C_TXFRAG) == 0 &&
2899 ireq->i_val != IEEE80211_FRAG_MAX)
2900 return EOPNOTSUPP;
2901 if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
2902 ireq->i_val <= IEEE80211_FRAG_MAX))
2903 return EINVAL;
2904 vap->iv_fragthreshold = ireq->i_val;
2905 error = ERESTART;
2906 break;
2907 case IEEE80211_IOC_BURST:
2908 if (ireq->i_val) {
2909 if ((vap->iv_caps & IEEE80211_C_BURST) == 0)
2910 return EOPNOTSUPP;
2911 ieee80211_syncflag(vap, IEEE80211_F_BURST);
2912 } else
2913 ieee80211_syncflag(vap, -IEEE80211_F_BURST);
2914 error = ERESTART;
2915 break;
2916 case IEEE80211_IOC_BMISSTHRESHOLD:
2917 if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2918 ireq->i_val <= IEEE80211_HWBMISS_MAX))
2919 return EINVAL;
2920 vap->iv_bmissthreshold = ireq->i_val;
2921 error = ERESTART;
2922 break;
2923 case IEEE80211_IOC_CURCHAN:
2924 error = ieee80211_ioctl_setcurchan(vap, ireq);
2925 break;
2926 case IEEE80211_IOC_SHORTGI:
2927 if (ireq->i_val) {
2928#define IEEE80211_HTCAP_SHORTGI \
2929 (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2930 if (((ireq->i_val ^ vap->iv_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2931 return EINVAL;
2932 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2933 vap->iv_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2934 if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2935 vap->iv_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2936#undef IEEE80211_HTCAP_SHORTGI
2937 } else
2938 vap->iv_flags_ext &=
2939 ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2940 error = ERESTART;
2941 break;
2942 case IEEE80211_IOC_AMPDU:
2943 if (ireq->i_val && (vap->iv_htcaps & IEEE80211_HTC_AMPDU) == 0)
2944 return EINVAL;
2945 if (ireq->i_val & 1)
2946 vap->iv_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2947 else
2948 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMPDU_TX;
2949 if (ireq->i_val & 2)
2950 vap->iv_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2951 else
2952 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMPDU_RX;
2953 /* NB: reset only if we're operating on an 11n channel */
2954 if (isvapht(vap))
2955 error = ERESTART;
2956 break;
2957 case IEEE80211_IOC_AMPDU_LIMIT:
2958 if (!(IEEE80211_HTCAP_MAXRXAMPDU_8K <= ireq->i_val &&
2959 ireq->i_val <= IEEE80211_HTCAP_MAXRXAMPDU_64K))
2960 return EINVAL;
2961 if (vap->iv_opmode == IEEE80211_M_HOSTAP)
2962 vap->iv_ampdu_rxmax = ireq->i_val;
2963 else
2964 vap->iv_ampdu_limit = ireq->i_val;
2965 error = ERESTART;
2966 break;
2967 case IEEE80211_IOC_AMPDU_DENSITY:
2968 if (!(IEEE80211_HTCAP_MPDUDENSITY_NA <= ireq->i_val &&
2969 ireq->i_val <= IEEE80211_HTCAP_MPDUDENSITY_16))
2970 return EINVAL;
2971 vap->iv_ampdu_density = ireq->i_val;
2972 error = ERESTART;
2973 break;
2974 case IEEE80211_IOC_AMSDU:
2975 if (ireq->i_val && (vap->iv_htcaps & IEEE80211_HTC_AMSDU) == 0)
2976 return EINVAL;
2977 if (ireq->i_val & 1)
2978 vap->iv_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
2979 else
2980 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMSDU_TX;
2981 if (ireq->i_val & 2)
2982 vap->iv_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
2983 else
2984 vap->iv_flags_ext &= ~IEEE80211_FEXT_AMSDU_RX;
2985 /* NB: reset only if we're operating on an 11n channel */
2986 if (isvapht(vap))
2987 error = ERESTART;
2988 break;
2989 case IEEE80211_IOC_AMSDU_LIMIT:
2990 /* XXX validate */
2991 vap->iv_amsdu_limit = ireq->i_val; /* XXX truncation? */
2992 break;
2993 case IEEE80211_IOC_PUREN:
2994 if (ireq->i_val) {
2995 if ((vap->iv_flags_ext & IEEE80211_FEXT_HT) == 0)
2996 return EINVAL;
2997 vap->iv_flags_ext |= IEEE80211_FEXT_PUREN;
2998 } else
2999 vap->iv_flags_ext &= ~IEEE80211_FEXT_PUREN;
3000 /* NB: reset only if we're operating on an 11n channel */
3001 if (isvapht(vap))
3002 error = ERESTART;
3003 break;
3004 case IEEE80211_IOC_DOTH:
3005 if (ireq->i_val) {
3006#if 0
3007 /* XXX no capability */
3008 if ((vap->iv_caps & IEEE80211_C_DOTH) == 0)
3009 return EOPNOTSUPP;
3010#endif
3011 vap->iv_flags |= IEEE80211_F_DOTH;
3012 } else
3013 vap->iv_flags &= ~IEEE80211_F_DOTH;
3014 error = ENETRESET;
3015 break;
3016 case IEEE80211_IOC_REGDOMAIN:
3017 error = ieee80211_ioctl_setregdomain(vap, ireq);
3018 break;
3019 case IEEE80211_IOC_ROAM:
3020 error = ieee80211_ioctl_setroam(vap, ireq);
3021 break;
3022 case IEEE80211_IOC_TXPARAMS:
3023 error = ieee80211_ioctl_settxparams(vap, ireq);
3024 break;
3025 case IEEE80211_IOC_HTCOMPAT:
3026 if (ireq->i_val) {
3027 if ((vap->iv_flags_ext & IEEE80211_FEXT_HT) == 0)
3028 return EOPNOTSUPP;
3029 vap->iv_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
3030 } else
3031 vap->iv_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
3032 /* NB: reset only if we're operating on an 11n channel */
3033 if (isvapht(vap))
3034 error = ERESTART;
3035 break;
3036 case IEEE80211_IOC_DWDS:
3037 if (ireq->i_val) {
3038 /* NB: DWDS only makes sense for WDS-capable devices */
3039 if ((ic->ic_caps & IEEE80211_C_WDS) == 0)
3040 return EOPNOTSUPP;
3041 /* NB: DWDS is used only with ap+sta vaps */
3042 if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
3043 vap->iv_opmode != IEEE80211_M_STA)
3044 return EINVAL;
3045 vap->iv_flags |= IEEE80211_F_DWDS;
3046 } else
3047 vap->iv_flags &= ~IEEE80211_F_DWDS;
3048 break;
3049 case IEEE80211_IOC_INACTIVITY:
3050 if (ireq->i_val)
3051 vap->iv_flags_ext |= IEEE80211_FEXT_INACT;
3052 else
3053 vap->iv_flags_ext &= ~IEEE80211_FEXT_INACT;
3054 break;
3055 case IEEE80211_IOC_APPIE:
3056 error = ieee80211_ioctl_setappie(vap, ireq);
3057 break;
3058 case IEEE80211_IOC_WPS:
3059 if (ireq->i_val) {
3060 if ((vap->iv_caps & IEEE80211_C_WPA) == 0)
3061 return EOPNOTSUPP;
3062 vap->iv_flags_ext |= IEEE80211_FEXT_WPS;
3063 } else
3064 vap->iv_flags_ext &= ~IEEE80211_FEXT_WPS;
3065 break;
3066 case IEEE80211_IOC_TSN:
3067 if (ireq->i_val) {
3068 if ((vap->iv_caps & IEEE80211_C_WPA) == 0)
3069 return EOPNOTSUPP;
3070 vap->iv_flags_ext |= IEEE80211_FEXT_TSN;
3071 } else
3072 vap->iv_flags_ext &= ~IEEE80211_FEXT_TSN;
3073 break;
3074 case IEEE80211_IOC_CHANSWITCH:
3075 error = ieee80211_ioctl_chanswitch(vap, ireq);
3076 break;
3077 case IEEE80211_IOC_DFS:
3078 if (ireq->i_val) {
3079 if ((vap->iv_caps & IEEE80211_C_DFS) == 0)
3080 return EOPNOTSUPP;
3081 /* NB: DFS requires 11h support */
3082 if ((vap->iv_flags & IEEE80211_F_DOTH) == 0)
3083 return EINVAL;
3084 vap->iv_flags_ext |= IEEE80211_FEXT_DFS;
3085 } else
3086 vap->iv_flags_ext &= ~IEEE80211_FEXT_DFS;
3087 break;
3088 case IEEE80211_IOC_DOTD:
3089 if (ireq->i_val)
3090 vap->iv_flags_ext |= IEEE80211_FEXT_DOTD;
3091 else
3092 vap->iv_flags_ext &= ~IEEE80211_FEXT_DOTD;
3093 if (vap->iv_opmode == IEEE80211_M_STA)
3094 error = ENETRESET;
3095 break;
3096 case IEEE80211_IOC_HTPROTMODE:
3097 if (ireq->i_val > IEEE80211_PROT_RTSCTS)
3098 return EINVAL;
3099 ic->ic_htprotmode = ireq->i_val ?
3100 IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE;
3101 /* NB: if not operating in 11n this can wait */
3102 if (isvapht(vap))
3103 error = ERESTART;
3104 break;
3105 case IEEE80211_IOC_STA_VLAN:
3106 error = ieee80211_ioctl_setstavlan(vap, ireq);
3107 break;
3108 case IEEE80211_IOC_SMPS:
3109 if ((ireq->i_val &~ IEEE80211_HTCAP_SMPS) != 0 ||
3110 ireq->i_val == 0x0008) /* value of 2 is reserved */
3111 return EINVAL;
3112 if (ireq->i_val != IEEE80211_HTCAP_SMPS_OFF &&
3113 (vap->iv_htcaps & IEEE80211_HTC_SMPS) == 0)
3114 return EOPNOTSUPP;
3115 vap->iv_htcaps = (vap->iv_htcaps &~ IEEE80211_HTCAP_SMPS) |
3116 ireq->i_val;
3117 /* NB: if not operating in 11n this can wait */
3118 if (isvapht(vap))
3119 error = ERESTART;
3120 break;
3121 case IEEE80211_IOC_RIFS:
3122 if (ireq->i_val != 0) {
3123 if ((vap->iv_htcaps & IEEE80211_HTC_RIFS) == 0)
3124 return EOPNOTSUPP;
3125 vap->iv_flags_ext |= IEEE80211_FEXT_RIFS;
3126 } else
3127 vap->iv_flags_ext &= ~IEEE80211_FEXT_RIFS;
3128 /* NB: if not operating in 11n this can wait */
3129 if (isvapht(vap))
3130 error = ERESTART;
3131 break;
3132 default:
3133 error = ieee80211_ioctl_setdefault(vap, ireq);
3134 break;
3135 }
3136 /*
3137 * The convention is that ENETRESET means an operation
3138 * requires a complete re-initialization of the device (e.g.
3139 * changing something that affects the association state).
3140 * ERESTART means the request may be handled with only a
3141 * reload of the hardware state. We hand ERESTART requests
3142 * to the iv_reset callback so the driver can decide. If
3143 * a device does not fillin iv_reset then it defaults to one
3144 * that returns ENETRESET. Otherwise a driver may return
3145 * ENETRESET (in which case a full reset will be done) or
3146 * 0 to mean there's no need to do anything (e.g. when the
3147 * change has no effect on the driver/device).
3148 */
3149 if (error == ERESTART)
3150 error = IFNET_IS_UP_RUNNING(vap->iv_ifp) ?
3151 vap->iv_reset(vap, ireq->i_type) : 0;
3152 if (error == ENETRESET) {
3153 /* XXX need to re-think AUTO handling */
3154 if (IS_UP_AUTO(vap))
3155 ieee80211_init(vap);
3156 error = 0;
3157 }
3158 return error;
3159}
3160
3161/*
3162 * Rebuild the parent's multicast address list after an add/del
3163 * of a multicast address for a vap. We have no way to tell
3164 * what happened above to optimize the work so we purge the entire
3165 * list and rebuild from scratch. This is way expensive.
3166 * Note also the half-baked workaround for if_addmulti calling
3167 * back to the parent device; there's no way to insert mcast
3168 * entries quietly and/or cheaply.
3169 */
3170static void
3171ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
3172{
3173 struct ifnet *parent = ic->ic_ifp;
3174 struct ieee80211vap *vap;
3175 void *ioctl;
3176
3177 IEEE80211_LOCK(ic);
3178 if_purgemaddrs(parent);
3179 ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
3180 parent->if_ioctl = NULL;
3181 TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
3182 struct ifnet *ifp = vap->iv_ifp;
3183 struct ifmultiaddr *ifma;
3184
3185 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
3186 (void) if_addmulti(parent, ifma->ifma_addr, NULL);
3187 }
3188 parent->if_ioctl = ioctl;
3189
3190 ic->ic_update_mcast(ic->ic_ifp);
3191 IEEE80211_UNLOCK(ic);
3192}
3193
3194int
3195ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
3196{
3197 struct ieee80211vap *vap;
3198 struct ieee80211com *ic;
3199 int error = 0;
3200 struct ifreq *ifr;
3201 struct ifaddr *ifa; /* XXX */
3202
3203 vap = ifp->if_softc;
3204 if (vap == NULL) {
3205 /*
3206 * During detach we clear the backpointer in the softc
3207 * so any ioctl request through the ifnet that arrives
3208 * before teardown is ignored/rejected. In particular
3209 * this hack handles destroying a vap used by an app
3210 * like wpa_supplicant that will respond to the vap
3211 * being forced into INIT state by immediately trying
3212 * to force it back up. We can yank this hack if/when
3213 * we can destroy the ifnet before cleaning up vap state.
3214 */
3215 return ENXIO;
3216 }
3217 switch (cmd) {
3218 case SIOCSIFFLAGS:
3219 ic = vap->iv_ic;
3220 IEEE80211_LOCK(ic);
3221 ieee80211_syncifflag_locked(ic, IFF_PROMISC);
3222 ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
3223 if (ifp->if_flags & IFF_UP) {
3224 /*
3225 * Bring ourself up unless we're already operational.
3226 * If we're the first vap and the parent is not up
3227 * then it will automatically be brought up as a
3228 * side-effect of bringing ourself up.
3229 */
3230 if (vap->iv_state == IEEE80211_S_INIT)
3231 ieee80211_start_locked(vap);
3232 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3233 /*
3234 * Stop ourself. If we are the last vap to be
3235 * marked down the parent will also be taken down.
3236 */
3237 ieee80211_stop_locked(vap);
3238 }
3239 IEEE80211_UNLOCK(ic);
3240 /* Wait for parent ioctl handler if it was queued */
3241 ieee80211_waitfor_parent(ic);
3242 break;
3243 case SIOCADDMULTI:
3244 case SIOCDELMULTI:
3245 ieee80211_ioctl_updatemulti(vap->iv_ic);
3246 break;
3247 case SIOCSIFMEDIA:
3248 case SIOCGIFMEDIA:
3249 ifr = (struct ifreq *)data;
3250 error = ifmedia_ioctl(ifp, ifr, &vap->iv_media, cmd);
3251 break;
3252 case SIOCG80211:
3253 error = ieee80211_ioctl_get80211(vap, cmd,
3254 (struct ieee80211req *) data);
3255 break;
3256 case SIOCS80211:
3257 error = priv_check(curthread, PRIV_NET80211_MANAGE);
3258 if (error == 0)
3259 error = ieee80211_ioctl_set80211(vap, cmd,
3260 (struct ieee80211req *) data);
3261 break;
3262 case SIOCG80211STATS:
3263 ifr = (struct ifreq *)data;
3264 copyout(&vap->iv_stats, ifr->ifr_data, sizeof (vap->iv_stats));
3265 break;
3266 case SIOCSIFMTU:
3267 ifr = (struct ifreq *)data;
3268 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
3269 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
3270 error = EINVAL;
3271 else
3272 ifp->if_mtu = ifr->ifr_mtu;
3273 break;
3274 case SIOCSIFADDR:
3275 /*
3276 * XXX Handle this directly so we can supress if_init calls.
3277 * XXX This should be done in ether_ioctl but for the moment
3278 * XXX there are too many other parts of the system that
3279 * XXX set IFF_UP and so supress if_init being called when
3280 * XXX it should be.
3281 */
3282 ifa = (struct ifaddr *) data;
3283 switch (ifa->ifa_addr->sa_family) {
3284#ifdef INET
3285 case AF_INET:
3286 if ((ifp->if_flags & IFF_UP) == 0) {
3287 ifp->if_flags |= IFF_UP;
3288 ifp->if_init(ifp->if_softc);
3289 }
3290 arp_ifinit(ifp, ifa);
3291 break;
3292#endif
3293#ifdef IPX
3294 /*
3295 * XXX - This code is probably wrong,
3296 * but has been copied many times.
3297 */
3298 case AF_IPX: {
3299 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
3300
3301 if (ipx_nullhost(*ina))
3302 ina->x_host = *(union ipx_host *)
3303 IF_LLADDR(ifp);
3304 else
3305 bcopy((caddr_t) ina->x_host.c_host,
3306 (caddr_t) IF_LLADDR(ifp),
3307 ETHER_ADDR_LEN);
3308 /* fall thru... */
3309 }
3310#endif
3311 default:
3312 if ((ifp->if_flags & IFF_UP) == 0) {
3313 ifp->if_flags |= IFF_UP;
3314 ifp->if_init(ifp->if_softc);
3315 }
3316 break;
3317 }
3318 break;
3319 /* Pass NDIS ioctls up to the driver */
3320 case SIOCGDRVSPEC:
3321 case SIOCSDRVSPEC:
3322 case SIOCGPRIVATE_0: {
3323 struct ifnet *parent = vap->iv_ic->ic_ifp;
3324 error = parent->if_ioctl(parent, cmd, data);
3325 break;
3326 }
3327 default:
3328 error = ether_ioctl(ifp, cmd, data);
3329 break;
3330 }
3331 return error;
3332}