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