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