xref: /freebsd/sys/net80211/ieee80211_ioctl.c (revision b28624fde638caadd4a89f50c9b7e7da0f98c4d2)
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 	default:
1112 		error = EINVAL;
1113 		break;
1114 	}
1115 	return error;
1116 }
1117 
1118 static int
1119 ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq)
1120 {
1121 	int error;
1122 	void *ie, *oie;
1123 
1124 	/*
1125 	 * NB: Doing this for ap operation could be useful (e.g. for
1126 	 *     WPA and/or WME) except that it typically is worthless
1127 	 *     without being able to intervene when processing
1128 	 *     association response frames--so disallow it for now.
1129 	 */
1130 	if (ic->ic_opmode != IEEE80211_M_STA)
1131 		return EINVAL;
1132 	if (ireq->i_len > IEEE80211_MAX_OPT_IE)
1133 		return EINVAL;
1134 	/* NB: data.length is validated by the wireless extensions code */
1135 	/* XXX M_WAITOK after driver lock released */
1136 	if (ireq->i_len > 0) {
1137 		MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
1138 		if (ie == NULL)
1139 			return ENOMEM;
1140 		error = copyin(ireq->i_data, ie, ireq->i_len);
1141 		if (error) {
1142 			FREE(ie, M_DEVBUF);
1143 			return error;
1144 		}
1145 	} else {
1146 		ie = NULL;
1147 		ireq->i_len = 0;
1148 	}
1149 	/* XXX sanity check data? */
1150 	oie = ic->ic_opt_ie;
1151 	ic->ic_opt_ie = ie;
1152 	ic->ic_opt_ie_len = ireq->i_len;
1153 	if (oie != NULL)
1154 		FREE(oie, M_DEVBUF);
1155 	return 0;
1156 }
1157 
1158 static int
1159 ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1160 {
1161 	struct ieee80211req_key ik;
1162 	struct ieee80211_node *ni;
1163 	struct ieee80211_key *wk;
1164 	uint16_t kid;
1165 	int error;
1166 
1167 	if (ireq->i_len != sizeof(ik))
1168 		return EINVAL;
1169 	error = copyin(ireq->i_data, &ik, sizeof(ik));
1170 	if (error)
1171 		return error;
1172 	/* NB: cipher support is verified by ieee80211_crypt_newkey */
1173 	/* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */
1174 	if (ik.ik_keylen > sizeof(ik.ik_keydata))
1175 		return E2BIG;
1176 	kid = ik.ik_keyix;
1177 	if (kid == IEEE80211_KEYIX_NONE) {
1178 		/* XXX unicast keys currently must be tx/rx */
1179 		if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV))
1180 			return EINVAL;
1181 		if (ic->ic_opmode == IEEE80211_M_STA) {
1182 			ni = ieee80211_ref_node(ic->ic_bss);
1183 			if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) {
1184 				ieee80211_free_node(ni);
1185 				return EADDRNOTAVAIL;
1186 			}
1187 		} else {
1188 			ni = ieee80211_find_node(&ic->ic_sta, ik.ik_macaddr);
1189 			if (ni == NULL)
1190 				return ENOENT;
1191 		}
1192 		wk = &ni->ni_ucastkey;
1193 	} else {
1194 		if (kid >= IEEE80211_WEP_NKID)
1195 			return EINVAL;
1196 		wk = &ic->ic_nw_keys[kid];
1197 		/*
1198 		 * Global slots start off w/o any assigned key index.
1199 		 * Force one here for consistency with IEEE80211_IOC_WEPKEY.
1200 		 */
1201 		if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
1202 			wk->wk_keyix = kid;
1203 		ni = NULL;
1204 	}
1205 	error = 0;
1206 	ieee80211_key_update_begin(ic);
1207 	if (ieee80211_crypto_newkey(ic, ik.ik_type, ik.ik_flags, wk)) {
1208 		wk->wk_keylen = ik.ik_keylen;
1209 		/* NB: MIC presence is implied by cipher type */
1210 		if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE)
1211 			wk->wk_keylen = IEEE80211_KEYBUF_SIZE;
1212 		wk->wk_keyrsc = ik.ik_keyrsc;
1213 		wk->wk_keytsc = 0;			/* new key, reset */
1214 		memset(wk->wk_key, 0, sizeof(wk->wk_key));
1215 		memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen);
1216 		if (!ieee80211_crypto_setkey(ic, wk,
1217 		    ni != NULL ? ni->ni_macaddr : ik.ik_macaddr))
1218 			error = EIO;
1219 		else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
1220 			ic->ic_def_txkey = kid;
1221 	} else
1222 		error = ENXIO;
1223 	ieee80211_key_update_end(ic);
1224 	if (ni != NULL)
1225 		ieee80211_free_node(ni);
1226 	return error;
1227 }
1228 
1229 static int
1230 ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq)
1231 {
1232 	struct ieee80211req_del_key dk;
1233 	int kid, error;
1234 
1235 	if (ireq->i_len != sizeof(dk))
1236 		return EINVAL;
1237 	error = copyin(ireq->i_data, &dk, sizeof(dk));
1238 	if (error)
1239 		return error;
1240 	kid = dk.idk_keyix;
1241 	/* XXX uint8_t -> uint16_t */
1242 	if (dk.idk_keyix == (uint8_t) IEEE80211_KEYIX_NONE) {
1243 		struct ieee80211_node *ni;
1244 
1245 		if (ic->ic_opmode == IEEE80211_M_STA) {
1246 			ni = ieee80211_ref_node(ic->ic_bss);
1247 			if (!IEEE80211_ADDR_EQ(dk.idk_macaddr, ni->ni_bssid)) {
1248 				ieee80211_free_node(ni);
1249 				return EADDRNOTAVAIL;
1250 			}
1251 		} else {
1252 			ni = ieee80211_find_node(&ic->ic_sta, dk.idk_macaddr);
1253 			if (ni == NULL)
1254 				return ENOENT;
1255 		}
1256 		/* XXX error return */
1257 		ieee80211_node_delucastkey(ni);
1258 		ieee80211_free_node(ni);
1259 	} else {
1260 		if (kid >= IEEE80211_WEP_NKID)
1261 			return EINVAL;
1262 		/* XXX error return */
1263 		ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]);
1264 	}
1265 	return 0;
1266 }
1267 
1268 static void
1269 domlme(void *arg, struct ieee80211_node *ni)
1270 {
1271 	struct ieee80211com *ic = ni->ni_ic;
1272 	struct ieee80211req_mlme *mlme = arg;
1273 
1274 	if (ni->ni_associd != 0) {
1275 		IEEE80211_SEND_MGMT(ic, ni,
1276 			mlme->im_op == IEEE80211_MLME_DEAUTH ?
1277 				IEEE80211_FC0_SUBTYPE_DEAUTH :
1278 				IEEE80211_FC0_SUBTYPE_DISASSOC,
1279 			mlme->im_reason);
1280 	}
1281 	ieee80211_node_leave(ic, ni);
1282 }
1283 
1284 struct scanlookup {
1285 	const uint8_t *mac;
1286 	int esslen;
1287 	const uint8_t *essid;
1288 	const struct ieee80211_scan_entry *se;
1289 };
1290 
1291 /*
1292  * Match mac address and any ssid.
1293  */
1294 static void
1295 mlmelookup(void *arg, const struct ieee80211_scan_entry *se)
1296 {
1297 	struct scanlookup *look = arg;
1298 
1299 	if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr))
1300 		return;
1301 	if (look->esslen != 0) {
1302 		if (se->se_ssid[1] != look->esslen)
1303 			return;
1304 		if (memcmp(look->essid, se->se_ssid+2, look->esslen))
1305 			return;
1306 	}
1307 	look->se = se;
1308 }
1309 
1310 static int
1311 ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq)
1312 {
1313 	struct ieee80211req_mlme mlme;
1314 	struct ieee80211_node *ni;
1315 	int error;
1316 
1317 	if (ireq->i_len != sizeof(mlme))
1318 		return EINVAL;
1319 	error = copyin(ireq->i_data, &mlme, sizeof(mlme));
1320 	if (error)
1321 		return error;
1322 	switch (mlme.im_op) {
1323 	case IEEE80211_MLME_ASSOC:
1324 		/* XXX ibss/ahdemo */
1325 		if (ic->ic_opmode == IEEE80211_M_STA) {
1326 			struct scanlookup lookup;
1327 
1328 			lookup.se = NULL;
1329 			lookup.mac = mlme.im_macaddr;
1330 			/* XXX use revised api w/ explicit ssid */
1331 			lookup.esslen = ic->ic_des_ssid[0].len;
1332 			lookup.essid = ic->ic_des_ssid[0].ssid;
1333 			ieee80211_scan_iterate(ic, mlmelookup, &lookup);
1334 			if (lookup.se != NULL &&
1335 			    ieee80211_sta_join(ic, lookup.se))
1336 				return 0;
1337 		}
1338 		return EINVAL;
1339 	case IEEE80211_MLME_DISASSOC:
1340 	case IEEE80211_MLME_DEAUTH:
1341 		switch (ic->ic_opmode) {
1342 		case IEEE80211_M_STA:
1343 			/* XXX not quite right */
1344 			ieee80211_new_state(ic, IEEE80211_S_INIT,
1345 				mlme.im_reason);
1346 			break;
1347 		case IEEE80211_M_HOSTAP:
1348 			/* NB: the broadcast address means do 'em all */
1349 			if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) {
1350 				if ((ni = ieee80211_find_node(&ic->ic_sta,
1351 						mlme.im_macaddr)) == NULL)
1352 					return EINVAL;
1353 				domlme(&mlme, ni);
1354 				ieee80211_free_node(ni);
1355 			} else {
1356 				ieee80211_iterate_nodes(&ic->ic_sta,
1357 						domlme, &mlme);
1358 			}
1359 			break;
1360 		default:
1361 			return EINVAL;
1362 		}
1363 		break;
1364 	case IEEE80211_MLME_AUTHORIZE:
1365 	case IEEE80211_MLME_UNAUTHORIZE:
1366 		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1367 			return EINVAL;
1368 		ni = ieee80211_find_node(&ic->ic_sta, mlme.im_macaddr);
1369 		if (ni == NULL)
1370 			return EINVAL;
1371 		if (mlme.im_op == IEEE80211_MLME_AUTHORIZE)
1372 			ieee80211_node_authorize(ni);
1373 		else
1374 			ieee80211_node_unauthorize(ni);
1375 		ieee80211_free_node(ni);
1376 		break;
1377 	default:
1378 		return EINVAL;
1379 	}
1380 	return 0;
1381 }
1382 
1383 static int
1384 ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq)
1385 {
1386 	uint8_t mac[IEEE80211_ADDR_LEN];
1387 	const struct ieee80211_aclator *acl = ic->ic_acl;
1388 	int error;
1389 
1390 	if (ireq->i_len != sizeof(mac))
1391 		return EINVAL;
1392 	error = copyin(ireq->i_data, mac, ireq->i_len);
1393 	if (error)
1394 		return error;
1395 	if (acl == NULL) {
1396 		acl = ieee80211_aclator_get("mac");
1397 		if (acl == NULL || !acl->iac_attach(ic))
1398 			return EINVAL;
1399 		ic->ic_acl = acl;
1400 	}
1401 	if (ireq->i_type == IEEE80211_IOC_ADDMAC)
1402 		acl->iac_add(ic, mac);
1403 	else
1404 		acl->iac_remove(ic, mac);
1405 	return 0;
1406 }
1407 
1408 static int
1409 ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq)
1410 {
1411 	const struct ieee80211_aclator *acl = ic->ic_acl;
1412 
1413 	switch (ireq->i_val) {
1414 	case IEEE80211_MACCMD_POLICY_OPEN:
1415 	case IEEE80211_MACCMD_POLICY_ALLOW:
1416 	case IEEE80211_MACCMD_POLICY_DENY:
1417 		if (acl == NULL) {
1418 			acl = ieee80211_aclator_get("mac");
1419 			if (acl == NULL || !acl->iac_attach(ic))
1420 				return EINVAL;
1421 			ic->ic_acl = acl;
1422 		}
1423 		acl->iac_setpolicy(ic, ireq->i_val);
1424 		break;
1425 	case IEEE80211_MACCMD_FLUSH:
1426 		if (acl != NULL)
1427 			acl->iac_flush(ic);
1428 		/* NB: silently ignore when not in use */
1429 		break;
1430 	case IEEE80211_MACCMD_DETACH:
1431 		if (acl != NULL) {
1432 			ic->ic_acl = NULL;
1433 			acl->iac_detach(ic);
1434 		}
1435 		break;
1436 	default:
1437 		if (acl == NULL)
1438 			return EINVAL;
1439 		else
1440 			return acl->iac_setioctl(ic, ireq);
1441 	}
1442 	return 0;
1443 }
1444 
1445 static int
1446 ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq)
1447 {
1448 	struct ieee80211req_chanlist list;
1449 	u_char chanlist[IEEE80211_CHAN_BYTES];
1450 	int i, j, nchan, error;
1451 
1452 	if (ireq->i_len != sizeof(list))
1453 		return EINVAL;
1454 	error = copyin(ireq->i_data, &list, sizeof(list));
1455 	if (error)
1456 		return error;
1457 	memset(chanlist, 0, sizeof(chanlist));
1458 	/*
1459 	 * Since channel 0 is not available for DS, channel 1
1460 	 * is assigned to LSB on WaveLAN.
1461 	 */
1462 	if (ic->ic_phytype == IEEE80211_T_DS)
1463 		i = 1;
1464 	else
1465 		i = 0;
1466 	nchan = 0;
1467 	for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
1468 		/*
1469 		 * NB: silently discard unavailable channels so users
1470 		 *     can specify 1-255 to get all available channels.
1471 		 */
1472 		if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
1473 			setbit(chanlist, i);
1474 			nchan++;
1475 		}
1476 	}
1477 	if (nchan == 0)
1478 		return EINVAL;
1479 	if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&	/* XXX */
1480 	    isclr(chanlist, ic->ic_bsschan->ic_ieee))
1481 		ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1482 	memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
1483 	return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0;
1484 }
1485 
1486 static int
1487 ieee80211_ioctl_setstastats(struct ieee80211com *ic, struct ieee80211req *ireq)
1488 {
1489 	struct ieee80211_node *ni;
1490 	uint8_t macaddr[IEEE80211_ADDR_LEN];
1491 	int error;
1492 
1493 	/*
1494 	 * NB: we could copyin ieee80211req_sta_stats so apps
1495 	 *     could make selective changes but that's overkill;
1496 	 *     just clear all stats for now.
1497 	 */
1498 	if (ireq->i_len < IEEE80211_ADDR_LEN)
1499 		return EINVAL;
1500 	error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN);
1501 	if (error != 0)
1502 		return error;
1503 	ni = ieee80211_find_node(&ic->ic_sta, macaddr);
1504 	if (ni == NULL)
1505 		return EINVAL;		/* XXX */
1506 	memset(&ni->ni_stats, 0, sizeof(ni->ni_stats));
1507 	ieee80211_free_node(ni);
1508 	return 0;
1509 }
1510 
1511 static int
1512 ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq)
1513 {
1514 	struct ieee80211_node *ni;
1515 	struct ieee80211req_sta_txpow txpow;
1516 	int error;
1517 
1518 	if (ireq->i_len != sizeof(txpow))
1519 		return EINVAL;
1520 	error = copyin(ireq->i_data, &txpow, sizeof(txpow));
1521 	if (error != 0)
1522 		return error;
1523 	ni = ieee80211_find_node(&ic->ic_sta, txpow.it_macaddr);
1524 	if (ni == NULL)
1525 		return EINVAL;		/* XXX */
1526 	ni->ni_txpower = txpow.it_txpow;
1527 	ieee80211_free_node(ni);
1528 	return error;
1529 }
1530 
1531 static int
1532 ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
1533 {
1534 	struct ieee80211_wme_state *wme = &ic->ic_wme;
1535 	struct wmeParams *wmep, *chanp;
1536 	int isbss, ac;
1537 
1538 	if ((ic->ic_caps & IEEE80211_C_WME) == 0)
1539 		return EINVAL;
1540 
1541 	isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
1542 	ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
1543 	if (ac >= WME_NUM_AC)
1544 		ac = WME_AC_BE;
1545 	if (isbss) {
1546 		chanp = &wme->wme_bssChanParams.cap_wmeParams[ac];
1547 		wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac];
1548 	} else {
1549 		chanp = &wme->wme_chanParams.cap_wmeParams[ac];
1550 		wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac];
1551 	}
1552 	switch (ireq->i_type) {
1553 	case IEEE80211_IOC_WME_CWMIN:		/* WME: CWmin */
1554 		if (isbss) {
1555 			wmep->wmep_logcwmin = ireq->i_val;
1556 			if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1557 				chanp->wmep_logcwmin = ireq->i_val;
1558 		} else {
1559 			wmep->wmep_logcwmin = chanp->wmep_logcwmin =
1560 				ireq->i_val;
1561 		}
1562 		break;
1563 	case IEEE80211_IOC_WME_CWMAX:		/* WME: CWmax */
1564 		if (isbss) {
1565 			wmep->wmep_logcwmax = ireq->i_val;
1566 			if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1567 				chanp->wmep_logcwmax = ireq->i_val;
1568 		} else {
1569 			wmep->wmep_logcwmax = chanp->wmep_logcwmax =
1570 				ireq->i_val;
1571 		}
1572 		break;
1573 	case IEEE80211_IOC_WME_AIFS:		/* WME: AIFS */
1574 		if (isbss) {
1575 			wmep->wmep_aifsn = ireq->i_val;
1576 			if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1577 				chanp->wmep_aifsn = ireq->i_val;
1578 		} else {
1579 			wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
1580 		}
1581 		break;
1582 	case IEEE80211_IOC_WME_TXOPLIMIT:	/* WME: txops limit */
1583 		if (isbss) {
1584 			wmep->wmep_txopLimit = ireq->i_val;
1585 			if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1586 				chanp->wmep_txopLimit = ireq->i_val;
1587 		} else {
1588 			wmep->wmep_txopLimit = chanp->wmep_txopLimit =
1589 				ireq->i_val;
1590 		}
1591 		break;
1592 	case IEEE80211_IOC_WME_ACM:		/* WME: ACM (bss only) */
1593 		wmep->wmep_acm = ireq->i_val;
1594 		if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
1595 			chanp->wmep_acm = ireq->i_val;
1596 		break;
1597 	case IEEE80211_IOC_WME_ACKPOLICY:	/* WME: ACK policy (!bss only)*/
1598 		wmep->wmep_noackPolicy = chanp->wmep_noackPolicy =
1599 			(ireq->i_val) == 0;
1600 		break;
1601 	}
1602 	ieee80211_wme_updateparams(ic);
1603 	return 0;
1604 }
1605 
1606 static int
1607 cipher2cap(int cipher)
1608 {
1609 	switch (cipher) {
1610 	case IEEE80211_CIPHER_WEP:	return IEEE80211_C_WEP;
1611 	case IEEE80211_CIPHER_AES_OCB:	return IEEE80211_C_AES;
1612 	case IEEE80211_CIPHER_AES_CCM:	return IEEE80211_C_AES_CCM;
1613 	case IEEE80211_CIPHER_CKIP:	return IEEE80211_C_CKIP;
1614 	case IEEE80211_CIPHER_TKIP:	return IEEE80211_C_TKIP;
1615 	}
1616 	return 0;
1617 }
1618 
1619 static int
1620 find11gchannel(struct ieee80211com *ic, int start, int freq)
1621 {
1622 	const struct ieee80211_channel *c;
1623 	int i;
1624 
1625 	for (i = start+1; i < ic->ic_nchans; i++) {
1626 		c = &ic->ic_channels[i];
1627 		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1628 			return 1;
1629 	}
1630 	/* NB: should not be needed but in case things are mis-sorted */
1631 	for (i = 0; i < start; i++) {
1632 		c = &ic->ic_channels[i];
1633 		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
1634 			return 1;
1635 	}
1636 	return 0;
1637 }
1638 
1639 static struct ieee80211_channel *
1640 findchannel(struct ieee80211com *ic, int ieee, int mode)
1641 {
1642 	static const u_int chanflags[IEEE80211_MODE_MAX] = {
1643 		0,			/* IEEE80211_MODE_AUTO */
1644 		IEEE80211_CHAN_A,	/* IEEE80211_MODE_11A */
1645 		IEEE80211_CHAN_B,	/* IEEE80211_MODE_11B */
1646 		IEEE80211_CHAN_G,	/* IEEE80211_MODE_11G */
1647 		IEEE80211_CHAN_FHSS,	/* IEEE80211_MODE_FH */
1648 		IEEE80211_CHAN_108A,	/* IEEE80211_MODE_TURBO_A */
1649 		IEEE80211_CHAN_108G,	/* IEEE80211_MODE_TURBO_G */
1650 		IEEE80211_CHAN_STURBO,	/* IEEE80211_MODE_STURBO_A */
1651 		/* NB: handled specially below */
1652 		IEEE80211_CHAN_A,	/* IEEE80211_MODE_11NA */
1653 		IEEE80211_CHAN_G,	/* IEEE80211_MODE_11NG */
1654 	};
1655 	u_int modeflags;
1656 	int i;
1657 
1658 	KASSERT(mode < IEEE80211_MODE_MAX, ("bad mode %u", mode));
1659 	modeflags = chanflags[mode];
1660 	KASSERT(modeflags != 0 || mode == IEEE80211_MODE_AUTO,
1661 	    ("no chanflags for mode %u", mode));
1662 	for (i = 0; i < ic->ic_nchans; i++) {
1663 		struct ieee80211_channel *c = &ic->ic_channels[i];
1664 
1665 		if (c->ic_ieee != ieee)
1666 			continue;
1667 		if (mode == IEEE80211_MODE_AUTO) {
1668 			/* ignore turbo channels for autoselect */
1669 			if (IEEE80211_IS_CHAN_TURBO(c))
1670 				continue;
1671 			/*
1672 			 * XXX special-case 11b/g channels so we
1673 			 *     always select the g channel if both
1674 			 *     are present.
1675 			 * XXX prefer HT to non-HT?
1676 			 */
1677 			if (!IEEE80211_IS_CHAN_B(c) ||
1678 			    !find11gchannel(ic, i, c->ic_freq))
1679 				return c;
1680 		} else {
1681 			/* must check HT specially */
1682 			if ((mode == IEEE80211_MODE_11NA ||
1683 			    mode == IEEE80211_MODE_11NG) &&
1684 			    !IEEE80211_IS_CHAN_HT(c))
1685 				continue;
1686 			if ((c->ic_flags & modeflags) == modeflags)
1687 				return c;
1688 		}
1689 	}
1690 	return NULL;
1691 }
1692 
1693 /*
1694  * Check the specified against any desired mode (aka netband).
1695  * This is only used (presently) when operating in hostap mode
1696  * to enforce consistency.
1697  */
1698 static int
1699 check_mode_consistency(const struct ieee80211_channel *c, int mode)
1700 {
1701 	KASSERT(c != IEEE80211_CHAN_ANYC, ("oops, no channel"));
1702 
1703 	switch (mode) {
1704 	case IEEE80211_MODE_11B:
1705 		return (IEEE80211_IS_CHAN_B(c));
1706 	case IEEE80211_MODE_11G:
1707 		return (IEEE80211_IS_CHAN_ANYG(c) && !IEEE80211_IS_CHAN_HT(c));
1708 	case IEEE80211_MODE_11A:
1709 		return (IEEE80211_IS_CHAN_A(c) && !IEEE80211_IS_CHAN_HT(c));
1710 	case IEEE80211_MODE_STURBO_A:
1711 		return (IEEE80211_IS_CHAN_STURBO(c));
1712 	case IEEE80211_MODE_11NA:
1713 		return (IEEE80211_IS_CHAN_HTA(c));
1714 	case IEEE80211_MODE_11NG:
1715 		return (IEEE80211_IS_CHAN_HTG(c));
1716 	}
1717 	return 1;
1718 
1719 }
1720 
1721 /*
1722  * Common code to set the current channel.  If the device
1723  * is up and running this may result in an immediate channel
1724  * change or a kick of the state machine.
1725  */
1726 static int
1727 setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
1728 {
1729 	int error;
1730 
1731 	if (c != IEEE80211_CHAN_ANYC) {
1732 		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1733 		    !check_mode_consistency(c, ic->ic_des_mode))
1734 			return EINVAL;
1735 		if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_curchan)
1736 			return 0;	/* NB: nothing to do */
1737 	}
1738 	ic->ic_des_chan = c;
1739 
1740 	error = 0;
1741 	if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
1742 	    ic->ic_opmode == IEEE80211_M_WDS) &&
1743 	    ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1744 		/*
1745 		 * Monitor and wds modes can switch directly.
1746 		 */
1747 		ic->ic_curchan = ic->ic_des_chan;
1748 		if (ic->ic_state == IEEE80211_S_RUN)
1749 			ic->ic_set_channel(ic);
1750 	} else {
1751 		/*
1752 		 * Need to go through the state machine in case we
1753 		 * need to reassociate or the like.  The state machine
1754 		 * will pickup the desired channel and avoid scanning.
1755 		 */
1756 		if (IS_UP_AUTO(ic))
1757 			error = ieee80211_init(ic, RESCAN);
1758 		else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1759 			/*
1760 			 * When not up+running and a real channel has
1761 			 * been specified fix the current channel so
1762 			 * there is immediate feedback; e.g. via ifconfig.
1763 			 */
1764 			ic->ic_curchan = ic->ic_des_chan;
1765 		}
1766 	}
1767 	return error;
1768 }
1769 
1770 /*
1771  * Old api for setting the current channel; this is
1772  * deprecated because channel numbers are ambiguous.
1773  */
1774 static int
1775 ieee80211_ioctl_setchannel(struct ieee80211com *ic,
1776 	const struct ieee80211req *ireq)
1777 {
1778 	struct ieee80211_channel *c;
1779 
1780 	/* XXX 0xffff overflows 16-bit signed */
1781 	if (ireq->i_val == 0 ||
1782 	    ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
1783 		c = IEEE80211_CHAN_ANYC;
1784 	} else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
1785 		return EINVAL;
1786 	} else {
1787 		struct ieee80211_channel *c2;
1788 
1789 		c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
1790 		if (c == NULL) {
1791 			c = findchannel(ic, ireq->i_val,
1792 				IEEE80211_MODE_AUTO);
1793 			if (c == NULL)
1794 				return EINVAL;
1795 		}
1796 		/*
1797 		 * Fine tune channel selection based on desired mode:
1798 		 *   if 11b is requested, find the 11b version of any
1799 		 *      11g channel returned,
1800 		 *   if static turbo, find the turbo version of any
1801 		 *	11a channel return,
1802 		 *   if 11na is requested, find the ht version of any
1803 		 *      11a channel returned,
1804 		 *   if 11ng is requested, find the ht version of any
1805 		 *      11g channel returned,
1806 		 *   otherwise we should be ok with what we've got.
1807 		 */
1808 		switch (ic->ic_des_mode) {
1809 		case IEEE80211_MODE_11B:
1810 			if (IEEE80211_IS_CHAN_ANYG(c)) {
1811 				c2 = findchannel(ic, ireq->i_val,
1812 					IEEE80211_MODE_11B);
1813 				/* NB: should not happen, =>'s 11g w/o 11b */
1814 				if (c2 != NULL)
1815 					c = c2;
1816 			}
1817 			break;
1818 		case IEEE80211_MODE_TURBO_A:
1819 			if (IEEE80211_IS_CHAN_A(c)) {
1820 				c2 = findchannel(ic, ireq->i_val,
1821 					IEEE80211_MODE_TURBO_A);
1822 				if (c2 != NULL)
1823 					c = c2;
1824 			}
1825 			break;
1826 		case IEEE80211_MODE_11NA:
1827 			if (IEEE80211_IS_CHAN_A(c)) {
1828 				c2 = findchannel(ic, ireq->i_val,
1829 					IEEE80211_MODE_11NA);
1830 				if (c2 != NULL)
1831 					c = c2;
1832 			}
1833 			break;
1834 		case IEEE80211_MODE_11NG:
1835 			if (IEEE80211_IS_CHAN_ANYG(c)) {
1836 				c2 = findchannel(ic, ireq->i_val,
1837 					IEEE80211_MODE_11NG);
1838 				if (c2 != NULL)
1839 					c = c2;
1840 			}
1841 			break;
1842 		default:		/* NB: no static turboG */
1843 			break;
1844 		}
1845 	}
1846 	return setcurchan(ic, c);
1847 }
1848 
1849 /*
1850  * New/current api for setting the current channel; a complete
1851  * channel description is provide so there is no ambiguity in
1852  * identifying the channel.
1853  */
1854 static int
1855 ieee80211_ioctl_setcurchan(struct ieee80211com *ic,
1856 	const struct ieee80211req *ireq)
1857 {
1858 	struct ieee80211_channel chan, *c;
1859 	int error;
1860 
1861 	if (ireq->i_len != sizeof(chan))
1862 		return EINVAL;
1863 	error = copyin(ireq->i_data, &chan, sizeof(chan));
1864 	if (error != 0)
1865 		return error;
1866 	/* XXX 0xffff overflows 16-bit signed */
1867 	if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
1868 		c = IEEE80211_CHAN_ANYC;
1869 	} else {
1870 		c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
1871 		if (c == NULL)
1872 			return EINVAL;
1873 	}
1874 	return setcurchan(ic, c);
1875 }
1876 
1877 static int
1878 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
1879 {
1880 	static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
1881 	struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
1882 	int error;
1883 	const struct ieee80211_authenticator *auth;
1884 	uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
1885 	char tmpssid[IEEE80211_NWID_LEN];
1886 	uint8_t tmpbssid[IEEE80211_ADDR_LEN];
1887 	struct ieee80211_key *k;
1888 	int j, caps;
1889 	u_int kid;
1890 
1891 	error = 0;
1892 	switch (ireq->i_type) {
1893 	case IEEE80211_IOC_SSID:
1894 		if (ireq->i_val != 0 ||
1895 		    ireq->i_len > IEEE80211_NWID_LEN)
1896 			return EINVAL;
1897 		error = copyin(ireq->i_data, tmpssid, ireq->i_len);
1898 		if (error)
1899 			break;
1900 		memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
1901 		ic->ic_des_ssid[0].len = ireq->i_len;
1902 		memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len);
1903 		ic->ic_des_nssid = (ireq->i_len > 0);
1904 		if (IS_UP_AUTO(ic))
1905 			error = ieee80211_init(ic, RESCAN);
1906 		break;
1907 	case IEEE80211_IOC_WEP:
1908 		switch (ireq->i_val) {
1909 		case IEEE80211_WEP_OFF:
1910 			ic->ic_flags &= ~IEEE80211_F_PRIVACY;
1911 			ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1912 			break;
1913 		case IEEE80211_WEP_ON:
1914 			ic->ic_flags |= IEEE80211_F_PRIVACY;
1915 			ic->ic_flags |= IEEE80211_F_DROPUNENC;
1916 			break;
1917 		case IEEE80211_WEP_MIXED:
1918 			ic->ic_flags |= IEEE80211_F_PRIVACY;
1919 			ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
1920 			break;
1921 		}
1922 		if (IS_UP_AUTO(ic))
1923 			error = ieee80211_init(ic, RESCAN);
1924 		break;
1925 	case IEEE80211_IOC_WEPKEY:
1926 		kid = (u_int) ireq->i_val;
1927 		if (kid >= IEEE80211_WEP_NKID)
1928 			return EINVAL;
1929 		k = &ic->ic_nw_keys[kid];
1930 		if (ireq->i_len == 0) {
1931 			/* zero-len =>'s delete any existing key */
1932 			(void) ieee80211_crypto_delkey(ic, k);
1933 			break;
1934 		}
1935 		if (ireq->i_len > sizeof(tmpkey))
1936 			return EINVAL;
1937 		memset(tmpkey, 0, sizeof(tmpkey));
1938 		error = copyin(ireq->i_data, tmpkey, ireq->i_len);
1939 		if (error)
1940 			break;
1941 		ieee80211_key_update_begin(ic);
1942 		k->wk_keyix = kid;	/* NB: force fixed key id */
1943 		if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP,
1944 		    IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k)) {
1945 			k->wk_keylen = ireq->i_len;
1946 			memcpy(k->wk_key, tmpkey, sizeof(tmpkey));
1947 			if  (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
1948 				error = EINVAL;
1949 		} else
1950 			error = EINVAL;
1951 		ieee80211_key_update_end(ic);
1952 		break;
1953 	case IEEE80211_IOC_WEPTXKEY:
1954 		kid = (u_int) ireq->i_val;
1955 		if (kid >= IEEE80211_WEP_NKID &&
1956 		    (uint16_t) kid != IEEE80211_KEYIX_NONE)
1957 			return EINVAL;
1958 		ic->ic_def_txkey = kid;
1959 		break;
1960 	case IEEE80211_IOC_AUTHMODE:
1961 		switch (ireq->i_val) {
1962 		case IEEE80211_AUTH_WPA:
1963 		case IEEE80211_AUTH_8021X:	/* 802.1x */
1964 		case IEEE80211_AUTH_OPEN:	/* open */
1965 		case IEEE80211_AUTH_SHARED:	/* shared-key */
1966 		case IEEE80211_AUTH_AUTO:	/* auto */
1967 			auth = ieee80211_authenticator_get(ireq->i_val);
1968 			if (auth == NULL)
1969 				return EINVAL;
1970 			break;
1971 		default:
1972 			return EINVAL;
1973 		}
1974 		switch (ireq->i_val) {
1975 		case IEEE80211_AUTH_WPA:	/* WPA w/ 802.1x */
1976 			ic->ic_flags |= IEEE80211_F_PRIVACY;
1977 			ireq->i_val = IEEE80211_AUTH_8021X;
1978 			break;
1979 		case IEEE80211_AUTH_OPEN:	/* open */
1980 			ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
1981 			break;
1982 		case IEEE80211_AUTH_SHARED:	/* shared-key */
1983 		case IEEE80211_AUTH_8021X:	/* 802.1x */
1984 			ic->ic_flags &= ~IEEE80211_F_WPA;
1985 			/* both require a key so mark the PRIVACY capability */
1986 			ic->ic_flags |= IEEE80211_F_PRIVACY;
1987 			break;
1988 		case IEEE80211_AUTH_AUTO:	/* auto */
1989 			ic->ic_flags &= ~IEEE80211_F_WPA;
1990 			/* XXX PRIVACY handling? */
1991 			/* XXX what's the right way to do this? */
1992 			break;
1993 		}
1994 		/* NB: authenticator attach/detach happens on state change */
1995 		ic->ic_bss->ni_authmode = ireq->i_val;
1996 		/* XXX mixed/mode/usage? */
1997 		ic->ic_auth = auth;
1998 		if (IS_UP_AUTO(ic))
1999 			error = ieee80211_init(ic, RESCAN);
2000 		break;
2001 	case IEEE80211_IOC_CHANNEL:
2002 		error = ieee80211_ioctl_setchannel(ic, ireq);
2003 		break;
2004 	case IEEE80211_IOC_POWERSAVE:
2005 		switch (ireq->i_val) {
2006 		case IEEE80211_POWERSAVE_OFF:
2007 			if (ic->ic_flags & IEEE80211_F_PMGTON) {
2008 				ic->ic_flags &= ~IEEE80211_F_PMGTON;
2009 				error = ENETRESET;
2010 			}
2011 			break;
2012 		case IEEE80211_POWERSAVE_ON:
2013 			if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
2014 				error = EINVAL;
2015 			else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
2016 				ic->ic_flags |= IEEE80211_F_PMGTON;
2017 				error = ENETRESET;
2018 			}
2019 			break;
2020 		default:
2021 			error = EINVAL;
2022 			break;
2023 		}
2024 		if (error == ENETRESET) {
2025 			/*
2026 			 * Switching in+out of power save mode
2027 			 * should not require a state change.
2028 			 */
2029 			error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2030 		}
2031 		break;
2032 	case IEEE80211_IOC_POWERSAVESLEEP:
2033 		if (ireq->i_val < 0)
2034 			return EINVAL;
2035 		ic->ic_lintval = ireq->i_val;
2036 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2037 		break;
2038 	case IEEE80211_IOC_RTSTHRESHOLD:
2039 		if (!(IEEE80211_RTS_MIN <= ireq->i_val &&
2040 		      ireq->i_val <= IEEE80211_RTS_MAX))
2041 			return EINVAL;
2042 		ic->ic_rtsthreshold = ireq->i_val;
2043 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2044 		break;
2045 	case IEEE80211_IOC_PROTMODE:
2046 		if (ireq->i_val > IEEE80211_PROT_RTSCTS)
2047 			return EINVAL;
2048 		ic->ic_protmode = ireq->i_val;
2049 		/* NB: if not operating in 11g this can wait */
2050 		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2051 		    IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2052 			error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2053 		break;
2054 	case IEEE80211_IOC_TXPOWER:
2055 		if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
2056 			return EINVAL;
2057 		if (!(IEEE80211_TXPOWER_MIN <= ireq->i_val &&
2058 		      ireq->i_val <= IEEE80211_TXPOWER_MAX))
2059 			return EINVAL;
2060 		ic->ic_txpowlimit = ireq->i_val;
2061 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2062 		break;
2063 	case IEEE80211_IOC_ROAMING:
2064 		if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val &&
2065 		    ireq->i_val <= IEEE80211_ROAMING_MANUAL))
2066 			return EINVAL;
2067 		ic->ic_roaming = ireq->i_val;
2068 		/* XXXX reset? */
2069 		break;
2070 	case IEEE80211_IOC_PRIVACY:
2071 		if (ireq->i_val) {
2072 			/* XXX check for key state? */
2073 			ic->ic_flags |= IEEE80211_F_PRIVACY;
2074 		} else
2075 			ic->ic_flags &= ~IEEE80211_F_PRIVACY;
2076 		break;
2077 	case IEEE80211_IOC_DROPUNENCRYPTED:
2078 		if (ireq->i_val)
2079 			ic->ic_flags |= IEEE80211_F_DROPUNENC;
2080 		else
2081 			ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2082 		break;
2083 	case IEEE80211_IOC_WPAKEY:
2084 		error = ieee80211_ioctl_setkey(ic, ireq);
2085 		break;
2086 	case IEEE80211_IOC_DELKEY:
2087 		error = ieee80211_ioctl_delkey(ic, ireq);
2088 		break;
2089 	case IEEE80211_IOC_MLME:
2090 		error = ieee80211_ioctl_setmlme(ic, ireq);
2091 		break;
2092 	case IEEE80211_IOC_OPTIE:
2093 		error = ieee80211_ioctl_setoptie(ic, ireq);
2094 		break;
2095 	case IEEE80211_IOC_COUNTERMEASURES:
2096 		if (ireq->i_val) {
2097 			if ((ic->ic_flags & IEEE80211_F_WPA) == 0)
2098 				return EINVAL;
2099 			ic->ic_flags |= IEEE80211_F_COUNTERM;
2100 		} else
2101 			ic->ic_flags &= ~IEEE80211_F_COUNTERM;
2102 		break;
2103 	case IEEE80211_IOC_WPA:
2104 		if (ireq->i_val > 3)
2105 			return EINVAL;
2106 		/* XXX verify ciphers available */
2107 		ic->ic_flags &= ~IEEE80211_F_WPA;
2108 		switch (ireq->i_val) {
2109 		case 1:
2110 			ic->ic_flags |= IEEE80211_F_WPA1;
2111 			break;
2112 		case 2:
2113 			ic->ic_flags |= IEEE80211_F_WPA2;
2114 			break;
2115 		case 3:
2116 			ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
2117 			break;
2118 		}
2119 		error = ENETRESET;
2120 		break;
2121 	case IEEE80211_IOC_WME:
2122 		if (ireq->i_val) {
2123 			if ((ic->ic_caps & IEEE80211_C_WME) == 0)
2124 				return EINVAL;
2125 			ic->ic_flags |= IEEE80211_F_WME;
2126 		} else
2127 			ic->ic_flags &= ~IEEE80211_F_WME;
2128 		if (IS_UP_AUTO(ic))
2129 			error = ieee80211_init(ic, 0);
2130 		break;
2131 	case IEEE80211_IOC_HIDESSID:
2132 		if (ireq->i_val)
2133 			ic->ic_flags |= IEEE80211_F_HIDESSID;
2134 		else
2135 			ic->ic_flags &= ~IEEE80211_F_HIDESSID;
2136 		error = ENETRESET;
2137 		break;
2138 	case IEEE80211_IOC_APBRIDGE:
2139 		if (ireq->i_val == 0)
2140 			ic->ic_flags |= IEEE80211_F_NOBRIDGE;
2141 		else
2142 			ic->ic_flags &= ~IEEE80211_F_NOBRIDGE;
2143 		break;
2144 	case IEEE80211_IOC_MCASTCIPHER:
2145 		if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 &&
2146 		    !ieee80211_crypto_available(ireq->i_val))
2147 			return EINVAL;
2148 		rsn->rsn_mcastcipher = ireq->i_val;
2149 		error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2150 		break;
2151 	case IEEE80211_IOC_MCASTKEYLEN:
2152 		if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2153 			return EINVAL;
2154 		/* XXX no way to verify driver capability */
2155 		rsn->rsn_mcastkeylen = ireq->i_val;
2156 		error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2157 		break;
2158 	case IEEE80211_IOC_UCASTCIPHERS:
2159 		/*
2160 		 * Convert user-specified cipher set to the set
2161 		 * we can support (via hardware or software).
2162 		 * NB: this logic intentionally ignores unknown and
2163 		 * unsupported ciphers so folks can specify 0xff or
2164 		 * similar and get all available ciphers.
2165 		 */
2166 		caps = 0;
2167 		for (j = 1; j < 32; j++)	/* NB: skip WEP */
2168 			if ((ireq->i_val & (1<<j)) &&
2169 			    ((ic->ic_caps & cipher2cap(j)) ||
2170 			     ieee80211_crypto_available(j)))
2171 				caps |= 1<<j;
2172 		if (caps == 0)			/* nothing available */
2173 			return EINVAL;
2174 		/* XXX verify ciphers ok for unicast use? */
2175 		/* XXX disallow if running as it'll have no effect */
2176 		rsn->rsn_ucastcipherset = caps;
2177 		error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2178 		break;
2179 	case IEEE80211_IOC_UCASTCIPHER:
2180 		if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0)
2181 			return EINVAL;
2182 		rsn->rsn_ucastcipher = ireq->i_val;
2183 		break;
2184 	case IEEE80211_IOC_UCASTKEYLEN:
2185 		if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE))
2186 			return EINVAL;
2187 		/* XXX no way to verify driver capability */
2188 		rsn->rsn_ucastkeylen = ireq->i_val;
2189 		break;
2190 	case IEEE80211_IOC_DRIVER_CAPS:
2191 		/* NB: for testing */
2192 		ic->ic_caps = (((uint16_t) ireq->i_val) << 16) |
2193 			       ((uint16_t) ireq->i_len);
2194 		break;
2195 	case IEEE80211_IOC_KEYMGTALGS:
2196 		/* XXX check */
2197 		rsn->rsn_keymgmtset = ireq->i_val;
2198 		error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2199 		break;
2200 	case IEEE80211_IOC_RSNCAPS:
2201 		/* XXX check */
2202 		rsn->rsn_caps = ireq->i_val;
2203 		error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0;
2204 		break;
2205 	case IEEE80211_IOC_BSSID:
2206 		if (ireq->i_len != sizeof(tmpbssid))
2207 			return EINVAL;
2208 		error = copyin(ireq->i_data, tmpbssid, ireq->i_len);
2209 		if (error)
2210 			break;
2211 		IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid);
2212 		if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid))
2213 			ic->ic_flags &= ~IEEE80211_F_DESBSSID;
2214 		else
2215 			ic->ic_flags |= IEEE80211_F_DESBSSID;
2216 		if (IS_UP_AUTO(ic))
2217 			error = ieee80211_init(ic, RESCAN);
2218 		break;
2219 	case IEEE80211_IOC_CHANLIST:
2220 		error = ieee80211_ioctl_setchanlist(ic, ireq);
2221 		break;
2222 	case IEEE80211_IOC_SCAN_REQ:
2223 		if (!IS_UP(ic))
2224 			return EINVAL;
2225 		(void) ieee80211_start_scan(ic,
2226 			IEEE80211_SCAN_ACTIVE |
2227 			IEEE80211_SCAN_NOPICK |
2228 			IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER,
2229 			/* XXX use ioctl params */
2230 			ic->ic_des_nssid, ic->ic_des_ssid);
2231 		break;
2232 	case IEEE80211_IOC_ADDMAC:
2233 	case IEEE80211_IOC_DELMAC:
2234 		error = ieee80211_ioctl_macmac(ic, ireq);
2235 		break;
2236 	case IEEE80211_IOC_MACCMD:
2237 		error = ieee80211_ioctl_setmaccmd(ic, ireq);
2238 		break;
2239 	case IEEE80211_IOC_STA_STATS:
2240 		error = ieee80211_ioctl_setstastats(ic, ireq);
2241 		break;
2242 	case IEEE80211_IOC_STA_TXPOW:
2243 		error = ieee80211_ioctl_setstatxpow(ic, ireq);
2244 		break;
2245 	case IEEE80211_IOC_WME_CWMIN:		/* WME: CWmin */
2246 	case IEEE80211_IOC_WME_CWMAX:		/* WME: CWmax */
2247 	case IEEE80211_IOC_WME_AIFS:		/* WME: AIFS */
2248 	case IEEE80211_IOC_WME_TXOPLIMIT:	/* WME: txops limit */
2249 	case IEEE80211_IOC_WME_ACM:		/* WME: ACM (bss only) */
2250 	case IEEE80211_IOC_WME_ACKPOLICY:	/* WME: ACK policy (bss only) */
2251 		error = ieee80211_ioctl_setwmeparam(ic, ireq);
2252 		break;
2253 	case IEEE80211_IOC_DTIM_PERIOD:
2254 		if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2255 		    ic->ic_opmode != IEEE80211_M_IBSS)
2256 			return EINVAL;
2257 		if (IEEE80211_DTIM_MIN <= ireq->i_val &&
2258 		    ireq->i_val <= IEEE80211_DTIM_MAX) {
2259 			ic->ic_dtim_period = ireq->i_val;
2260 			error = ENETRESET;		/* requires restart */
2261 		} else
2262 			error = EINVAL;
2263 		break;
2264 	case IEEE80211_IOC_BEACON_INTERVAL:
2265 		if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2266 		    ic->ic_opmode != IEEE80211_M_IBSS)
2267 			return EINVAL;
2268 		if (IEEE80211_BINTVAL_MIN <= ireq->i_val &&
2269 		    ireq->i_val <= IEEE80211_BINTVAL_MAX) {
2270 			ic->ic_bintval = ireq->i_val;
2271 			error = ENETRESET;		/* requires restart */
2272 		} else
2273 			error = EINVAL;
2274 		break;
2275 	case IEEE80211_IOC_PUREG:
2276 		if (ireq->i_val)
2277 			ic->ic_flags |= IEEE80211_F_PUREG;
2278 		else
2279 			ic->ic_flags &= ~IEEE80211_F_PUREG;
2280 		/* NB: reset only if we're operating on an 11g channel */
2281 		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2282 		    IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
2283 			error = ENETRESET;
2284 		break;
2285 	case IEEE80211_IOC_FF:
2286 		if (ireq->i_val) {
2287 			if ((ic->ic_caps & IEEE80211_C_FF) == 0)
2288 				return EINVAL;
2289 			ic->ic_flags |= IEEE80211_F_FF;
2290 		} else
2291 			ic->ic_flags &= ~IEEE80211_F_FF;
2292 		error = ENETRESET;
2293 		break;
2294 	case IEEE80211_IOC_TURBOP:
2295 		if (ireq->i_val) {
2296 			if ((ic->ic_caps & IEEE80211_C_TURBOP) == 0)
2297 				return EINVAL;
2298 			ic->ic_flags |= IEEE80211_F_TURBOP;
2299 		} else
2300 			ic->ic_flags &= ~IEEE80211_F_TURBOP;
2301 		error = ENETRESET;
2302 		break;
2303 	case IEEE80211_IOC_BGSCAN:
2304 		if (ireq->i_val) {
2305 			if ((ic->ic_caps & IEEE80211_C_BGSCAN) == 0)
2306 				return EINVAL;
2307 			ic->ic_flags |= IEEE80211_F_BGSCAN;
2308 		} else
2309 			ic->ic_flags &= ~IEEE80211_F_BGSCAN;
2310 		break;
2311 	case IEEE80211_IOC_BGSCAN_IDLE:
2312 		if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN)
2313 			ic->ic_bgscanidle = ireq->i_val*hz/1000;
2314 		else
2315 			error = EINVAL;
2316 		break;
2317 	case IEEE80211_IOC_BGSCAN_INTERVAL:
2318 		if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN)
2319 			ic->ic_bgscanintvl = ireq->i_val*hz;
2320 		else
2321 			error = EINVAL;
2322 		break;
2323 	case IEEE80211_IOC_SCANVALID:
2324 		if (ireq->i_val >= IEEE80211_SCAN_VALID_MIN)
2325 			ic->ic_scanvalid = ireq->i_val*hz;
2326 		else
2327 			error = EINVAL;
2328 		break;
2329 	case IEEE80211_IOC_ROAM_RSSI_11A:
2330 		ic->ic_roam.rssi11a = ireq->i_val;
2331 		break;
2332 	case IEEE80211_IOC_ROAM_RSSI_11B:
2333 		ic->ic_roam.rssi11bOnly = ireq->i_val;
2334 		break;
2335 	case IEEE80211_IOC_ROAM_RSSI_11G:
2336 		ic->ic_roam.rssi11b = ireq->i_val;
2337 		break;
2338 	case IEEE80211_IOC_ROAM_RATE_11A:
2339 		ic->ic_roam.rate11a = ireq->i_val & IEEE80211_RATE_VAL;
2340 		break;
2341 	case IEEE80211_IOC_ROAM_RATE_11B:
2342 		ic->ic_roam.rate11bOnly = ireq->i_val & IEEE80211_RATE_VAL;
2343 		break;
2344 	case IEEE80211_IOC_ROAM_RATE_11G:
2345 		ic->ic_roam.rate11b = ireq->i_val & IEEE80211_RATE_VAL;
2346 		break;
2347 	case IEEE80211_IOC_MCAST_RATE:
2348 		ic->ic_mcast_rate = ireq->i_val & IEEE80211_RATE_VAL;
2349 		break;
2350 	case IEEE80211_IOC_FRAGTHRESHOLD:
2351 		if ((ic->ic_caps & IEEE80211_C_TXFRAG) == 0 &&
2352 		    ireq->i_val != IEEE80211_FRAG_MAX)
2353 			return EINVAL;
2354 		if (!(IEEE80211_FRAG_MIN <= ireq->i_val &&
2355 		      ireq->i_val <= IEEE80211_FRAG_MAX))
2356 			return EINVAL;
2357 		ic->ic_fragthreshold = ireq->i_val;
2358 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2359 		break;
2360 	case IEEE80211_IOC_BURST:
2361 		if (ireq->i_val) {
2362 			if ((ic->ic_caps & IEEE80211_C_BURST) == 0)
2363 				return EINVAL;
2364 			ic->ic_flags |= IEEE80211_F_BURST;
2365 		} else
2366 			ic->ic_flags &= ~IEEE80211_F_BURST;
2367 		error = ENETRESET;		/* XXX maybe not for station? */
2368 		break;
2369 	case IEEE80211_IOC_BMISSTHRESHOLD:
2370 		if (!(IEEE80211_HWBMISS_MIN <= ireq->i_val &&
2371 		      ireq->i_val <= IEEE80211_HWBMISS_MAX))
2372 			return EINVAL;
2373 		ic->ic_bmissthreshold = ireq->i_val;
2374 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2375 		break;
2376 	case IEEE80211_IOC_CURCHAN:
2377 		error = ieee80211_ioctl_setcurchan(ic, ireq);
2378 		break;
2379 	case IEEE80211_IOC_SHORTGI:
2380 		if (ireq->i_val) {
2381 #define	IEEE80211_HTCAP_SHORTGI \
2382 	(IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40)
2383 			if (((ireq->i_val ^ ic->ic_htcaps) & IEEE80211_HTCAP_SHORTGI) != 0)
2384 				return EINVAL;
2385 			if (ireq->i_val & IEEE80211_HTCAP_SHORTGI20)
2386 				ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI20;
2387 			if (ireq->i_val & IEEE80211_HTCAP_SHORTGI40)
2388 				ic->ic_flags_ext |= IEEE80211_FEXT_SHORTGI40;
2389 #undef IEEE80211_HTCAP_SHORTGI
2390 		} else
2391 			ic->ic_flags_ext &=
2392 			    ~(IEEE80211_FEXT_SHORTGI20 | IEEE80211_FEXT_SHORTGI40);
2393 		/* XXX kick state machine? */
2394 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2395 		break;
2396 	case IEEE80211_IOC_AMPDU:
2397 		if (ireq->i_val) {
2398 			if ((ic->ic_htcaps & IEEE80211_HTC_AMPDU) == 0)
2399 				return EINVAL;
2400 			if (ireq->i_val & 1)
2401 				ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_TX;
2402 			if (ireq->i_val & 2)
2403 				ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_RX;
2404 		} else
2405 			ic->ic_flags_ext &=
2406 			    ~(IEEE80211_FEXT_AMPDU_TX|IEEE80211_FEXT_AMPDU_RX);
2407 		/* NB: reset only if we're operating on an 11n channel */
2408 		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2409 		    IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2410 			error = ENETRESET;
2411 		break;
2412 	case IEEE80211_IOC_AMPDU_LIMIT:
2413 		/* XXX validate */
2414 		ic->ic_ampdu_limit = ireq->i_val;
2415 		break;
2416 	case IEEE80211_IOC_AMPDU_DENSITY:
2417 		/* XXX validate */
2418 		ic->ic_ampdu_density = ireq->i_val;
2419 		break;
2420 	case IEEE80211_IOC_AMSDU:
2421 		if (ireq->i_val) {
2422 			if ((ic->ic_htcaps & IEEE80211_HTC_AMSDU) == 0)
2423 				return EINVAL;
2424 			if (ireq->i_val & 1)
2425 				ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
2426 			if (ireq->i_val & 2)
2427 				ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
2428 		} else
2429 			ic->ic_flags_ext &=
2430 			    ~(IEEE80211_FEXT_AMSDU_TX|IEEE80211_FEXT_AMSDU_RX);
2431 		/* NB: reset only if we're operating on an 11n channel */
2432 		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2433 		    IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2434 			error = ENETRESET;
2435 		break;
2436 	case IEEE80211_IOC_AMSDU_LIMIT:
2437 		/* XXX validate */
2438 		ic->ic_amsdu_limit = ireq->i_val;	/* XXX truncation? */
2439 		break;
2440 	case IEEE80211_IOC_PUREN:
2441 		if (ireq->i_val) {
2442 			if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2443 				return EINVAL;
2444 			ic->ic_flags_ext |= IEEE80211_FEXT_PUREN;
2445 		} else
2446 			ic->ic_flags_ext &= ~IEEE80211_FEXT_PUREN;
2447 		/* NB: reset only if we're operating on an 11n channel */
2448 		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2449 		    IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2450 			error = ENETRESET;
2451 		break;
2452 	case IEEE80211_IOC_DOTH:
2453 		if (ireq->i_val) {
2454 #if 0
2455 			/* XXX no capability */
2456 			if ((ic->ic_caps & IEEE80211_C_DOTH) == 0)
2457 				return EINVAL;
2458 #endif
2459 			ic->ic_flags |= IEEE80211_F_DOTH;
2460 		} else
2461 			ic->ic_flags &= ~IEEE80211_F_DOTH;
2462 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
2463 		break;
2464 	case IEEE80211_IOC_HTCOMPAT:
2465 		if (ireq->i_val) {
2466 			if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) == 0)
2467 				return EINVAL;
2468 			ic->ic_flags_ext |= IEEE80211_FEXT_HTCOMPAT;
2469 		} else
2470 			ic->ic_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT;
2471 		/* NB: reset only if we're operating on an 11n channel */
2472 		if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
2473 		    IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2474 			error = ENETRESET;
2475 		break;
2476 	case IEEE80211_IOC_INACTIVITY:
2477 		if (ireq->i_val)
2478 			ic->ic_flags_ext |= IEEE80211_FEXT_INACT;
2479 		else
2480 			ic->ic_flags_ext &= ~IEEE80211_FEXT_INACT;
2481 		break;
2482 	default:
2483 		error = EINVAL;
2484 		break;
2485 	}
2486 	if (error == ENETRESET)
2487 		error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0;
2488 	return error;
2489 }
2490 
2491 int
2492 ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data)
2493 {
2494 	struct ifnet *ifp = ic->ic_ifp;
2495 	int error = 0;
2496 	struct ifreq *ifr;
2497 	struct ifaddr *ifa;			/* XXX */
2498 
2499 	switch (cmd) {
2500 	case SIOCSIFMEDIA:
2501 	case SIOCGIFMEDIA:
2502 		error = ifmedia_ioctl(ifp, (struct ifreq *) data,
2503 				&ic->ic_media, cmd);
2504 		break;
2505 	case SIOCG80211:
2506 		error = ieee80211_ioctl_get80211(ic, cmd,
2507 				(struct ieee80211req *) data);
2508 		break;
2509 	case SIOCS80211:
2510 		error = priv_check(curthread, PRIV_NET80211_MANAGE);
2511 		if (error == 0)
2512 			error = ieee80211_ioctl_set80211(ic, cmd,
2513 					(struct ieee80211req *) data);
2514 		break;
2515 	case SIOCG80211STATS:
2516 		ifr = (struct ifreq *)data;
2517 		copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
2518 		break;
2519 	case SIOCSIFMTU:
2520 		ifr = (struct ifreq *)data;
2521 		if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
2522 		    ifr->ifr_mtu <= IEEE80211_MTU_MAX))
2523 			error = EINVAL;
2524 		else
2525 			ifp->if_mtu = ifr->ifr_mtu;
2526 		break;
2527 	case SIOCSIFADDR:
2528 		/*
2529 		 * XXX Handle this directly so we can supress if_init calls.
2530 		 * XXX This should be done in ether_ioctl but for the moment
2531 		 * XXX there are too many other parts of the system that
2532 		 * XXX set IFF_UP and so supress if_init being called when
2533 		 * XXX it should be.
2534 		 */
2535 		ifa = (struct ifaddr *) data;
2536 		switch (ifa->ifa_addr->sa_family) {
2537 #ifdef INET
2538 		case AF_INET:
2539 			if ((ifp->if_flags & IFF_UP) == 0) {
2540 				ifp->if_flags |= IFF_UP;
2541 				ifp->if_init(ifp->if_softc);
2542 			}
2543 			arp_ifinit(ifp, ifa);
2544 			break;
2545 #endif
2546 #ifdef IPX
2547 		/*
2548 		 * XXX - This code is probably wrong,
2549 		 *	 but has been copied many times.
2550 		 */
2551 		case AF_IPX: {
2552 			struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
2553 
2554 			if (ipx_nullhost(*ina))
2555 				ina->x_host = *(union ipx_host *)
2556 				    IF_LLADDR(ifp);
2557 			else
2558 				bcopy((caddr_t) ina->x_host.c_host,
2559 				      (caddr_t) IF_LLADDR(ifp),
2560 				      ETHER_ADDR_LEN);
2561 			/* fall thru... */
2562 		}
2563 #endif
2564 		default:
2565 			if ((ifp->if_flags & IFF_UP) == 0) {
2566 				ifp->if_flags |= IFF_UP;
2567 				ifp->if_init(ifp->if_softc);
2568 			}
2569 			break;
2570 		}
2571 		break;
2572 	default:
2573 		error = ether_ioctl(ifp, cmd, data);
2574 		break;
2575 	}
2576 	return error;
2577 }
2578