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