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