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