xref: /openbsd-src/sys/net80211/ieee80211_ioctl.c (revision aa997e528a848ca5596493c2a801bdd6fb26ae61)
1 /*	$OpenBSD: ieee80211_ioctl.c,v 1.59 2018/02/19 08:59:52 mpi Exp $	*/
2 /*	$NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $	*/
3 
4 /*-
5  * Copyright (c) 2001 Atsushi Onoe
6  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * IEEE 802.11 ioctl support
34  */
35 
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/systm.h>
41 #include <sys/endian.h>
42 #include <sys/tree.h>
43 
44 #include <net/if.h>
45 #include <net/if_media.h>
46 
47 #include <netinet/in.h>
48 #include <netinet/if_ether.h>
49 
50 #include <net80211/ieee80211_var.h>
51 #include <net80211/ieee80211_crypto.h>
52 #include <net80211/ieee80211_ioctl.h>
53 
54 void	 ieee80211_node2req(struct ieee80211com *,
55 	    const struct ieee80211_node *, struct ieee80211_nodereq *);
56 void	 ieee80211_req2node(struct ieee80211com *,
57 	    const struct ieee80211_nodereq *, struct ieee80211_node *);
58 
59 void
60 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni,
61     struct ieee80211_nodereq *nr)
62 {
63 	uint8_t rssi;
64 
65 	memset(nr, 0, sizeof(*nr));
66 
67 	strlcpy(nr->nr_ifname, ic->ic_if.if_xname, sizeof(nr->nr_ifname));
68 
69 	/* Node address and name information */
70 	IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr);
71 	IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid);
72 	nr->nr_nwid_len = ni->ni_esslen;
73 	bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN);
74 
75 	/* Channel and rates */
76 	nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan);
77 	nr->nr_chan_flags = ni->ni_chan->ic_flags;
78 	if (ic->ic_curmode != IEEE80211_MODE_11N)
79 		nr->nr_chan_flags &= ~IEEE80211_CHAN_HT;
80 	nr->nr_nrates = ni->ni_rates.rs_nrates;
81 	bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE);
82 
83 	/* Node status information */
84 	rssi = (*ic->ic_node_getrssi)(ic, ni);
85 	if (ic->ic_max_rssi) {
86 		/* Driver reports RSSI relative to ic_max_rssi. */
87 		nr->nr_rssi = rssi;
88 	} else {
89 		/*
90 		 * Driver reports RSSI value in dBm.
91 		 * Convert from unsigned to signed.
92 		 * Some drivers report a negative value, some don't.
93 		 * Reasonable range is -20dBm to -80dBm.
94 		 */
95 		nr->nr_rssi = (rssi < 128) ? -rssi : rssi;
96 	}
97 	nr->nr_max_rssi = ic->ic_max_rssi;
98 	bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp));
99 	nr->nr_intval = ni->ni_intval;
100 	nr->nr_capinfo = ni->ni_capinfo;
101 	nr->nr_erp = ni->ni_erp;
102 	nr->nr_pwrsave = ni->ni_pwrsave;
103 	nr->nr_associd = ni->ni_associd;
104 	nr->nr_txseq = ni->ni_txseq;
105 	nr->nr_rxseq = ni->ni_rxseq;
106 	nr->nr_fails = ni->ni_fails;
107 	nr->nr_inact = ni->ni_inact;
108 	nr->nr_txrate = ni->ni_txrate;
109 	nr->nr_state = ni->ni_state;
110 
111 	/* RSN */
112 	nr->nr_rsnciphers = ni->ni_rsnciphers;
113 	nr->nr_rsnakms = 0;
114 	nr->nr_rsnprotos = 0;
115 	if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_RSN)
116 		nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA2;
117 	if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_WPA)
118 		nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA1;
119 	if (ni->ni_supported_rsnakms & IEEE80211_AKM_8021X)
120 		nr->nr_rsnakms |= IEEE80211_WPA_AKM_8021X;
121 	if (ni->ni_supported_rsnakms & IEEE80211_AKM_PSK)
122 		nr->nr_rsnakms |= IEEE80211_WPA_AKM_PSK;
123 	if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_8021X)
124 		nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_8021X;
125 	if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_PSK)
126 		nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_PSK;
127 
128 	/* Node flags */
129 	nr->nr_flags = 0;
130 	if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0)
131 		nr->nr_flags |= IEEE80211_NODEREQ_AP;
132 	if (ni == ic->ic_bss)
133 		nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS;
134 
135 	/* HT */
136 	nr->nr_htcaps = ni->ni_htcaps;
137 	memcpy(nr->nr_rxmcs, ni->ni_rxmcs, sizeof(nr->nr_rxmcs));
138 	nr->nr_max_rxrate = ni->ni_max_rxrate;
139 	nr->nr_tx_mcs_set = ni->ni_tx_mcs_set;
140 	nr->nr_txmcs = ni->ni_txmcs;
141 	if (ni->ni_flags & IEEE80211_NODE_HT)
142 		nr->nr_flags |= IEEE80211_NODEREQ_HT;
143 }
144 
145 void
146 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr,
147     struct ieee80211_node *ni)
148 {
149 	/* Node address and name information */
150 	IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr);
151 	IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid);
152 	ni->ni_esslen = nr->nr_nwid_len;
153 	bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN);
154 
155 	/* Rates */
156 	ni->ni_rates.rs_nrates = nr->nr_nrates;
157 	bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE);
158 
159 	/* Node information */
160 	ni->ni_intval = nr->nr_intval;
161 	ni->ni_capinfo = nr->nr_capinfo;
162 	ni->ni_erp = nr->nr_erp;
163 	ni->ni_pwrsave = nr->nr_pwrsave;
164 	ni->ni_associd = nr->nr_associd;
165 	ni->ni_txseq = nr->nr_txseq;
166 	ni->ni_rxseq = nr->nr_rxseq;
167 	ni->ni_fails = nr->nr_fails;
168 	ni->ni_inact = nr->nr_inact;
169 	ni->ni_txrate = nr->nr_txrate;
170 	ni->ni_state = nr->nr_state;
171 }
172 
173 void
174 ieee80211_disable_wep(struct ieee80211com *ic)
175 {
176 	struct ieee80211_key *k;
177 	int i;
178 
179 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
180 		k = &ic->ic_nw_keys[i];
181 		if (k->k_cipher != IEEE80211_CIPHER_NONE)
182 			(*ic->ic_delete_key)(ic, NULL, k);
183 		explicit_bzero(k, sizeof(*k));
184 	}
185 	ic->ic_flags &= ~IEEE80211_F_WEPON;
186 }
187 
188 void
189 ieee80211_disable_rsn(struct ieee80211com *ic)
190 {
191 	ic->ic_flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON);
192 	explicit_bzero(ic->ic_psk, sizeof(ic->ic_psk));
193 	ic->ic_rsnprotos = 0;
194 	ic->ic_rsnakms = 0;
195 	ic->ic_rsngroupcipher = 0;
196 	ic->ic_rsnciphers = 0;
197 }
198 
199 static int
200 ieee80211_ioctl_setnwkeys(struct ieee80211com *ic,
201     const struct ieee80211_nwkey *nwkey)
202 {
203 	struct ieee80211_key *k;
204 	int error, i;
205 
206 	if (!(ic->ic_caps & IEEE80211_C_WEP))
207 		return ENODEV;
208 
209 	if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) {
210 		if (!(ic->ic_flags & IEEE80211_F_WEPON))
211 			return 0;
212 		ic->ic_flags &= ~IEEE80211_F_WEPON;
213 		return ENETRESET;
214 	}
215 	if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID)
216 		return EINVAL;
217 
218 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
219 		if (nwkey->i_key[i].i_keylen == 0 ||
220 		    nwkey->i_key[i].i_keydat == NULL)
221 			continue;	/* entry not set */
222 		if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE)
223 			return EINVAL;
224 
225 		/* map wep key to ieee80211_key */
226 		k = &ic->ic_nw_keys[i];
227 		if (k->k_cipher != IEEE80211_CIPHER_NONE)
228 			(*ic->ic_delete_key)(ic, NULL, k);
229 		memset(k, 0, sizeof(*k));
230 		if (nwkey->i_key[i].i_keylen <= 5)
231 			k->k_cipher = IEEE80211_CIPHER_WEP40;
232 		else
233 			k->k_cipher = IEEE80211_CIPHER_WEP104;
234 		k->k_len = ieee80211_cipher_keylen(k->k_cipher);
235 		k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;
236 		error = copyin(nwkey->i_key[i].i_keydat, k->k_key, k->k_len);
237 		if (error != 0)
238 			return error;
239 		if ((error = (*ic->ic_set_key)(ic, NULL, k)) != 0)
240 			return error;
241 	}
242 
243 	ic->ic_def_txkey = nwkey->i_defkid - 1;
244 	ic->ic_flags |= IEEE80211_F_WEPON;
245 	if (ic->ic_flags & IEEE80211_F_RSNON)
246 		ieee80211_disable_rsn(ic);
247 
248 	return ENETRESET;
249 }
250 
251 static int
252 ieee80211_ioctl_getnwkeys(struct ieee80211com *ic,
253     struct ieee80211_nwkey *nwkey)
254 {
255 	int i;
256 
257 	if (ic->ic_flags & IEEE80211_F_WEPON)
258 		nwkey->i_wepon = IEEE80211_NWKEY_WEP;
259 	else
260 		nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
261 
262 	nwkey->i_defkid = ic->ic_wep_txkey + 1;
263 
264 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
265 		if (nwkey->i_key[i].i_keydat == NULL)
266 			continue;
267 		/* do not show any keys to userland */
268 		return EPERM;
269 	}
270 	return 0;
271 }
272 
273 static int
274 ieee80211_ioctl_setwpaparms(struct ieee80211com *ic,
275     const struct ieee80211_wpaparams *wpa)
276 {
277 	if (!(ic->ic_caps & IEEE80211_C_RSN))
278 		return ENODEV;
279 
280 	if (!wpa->i_enabled) {
281 		if (!(ic->ic_flags & IEEE80211_F_RSNON))
282 			return 0;
283 		ic->ic_flags &= ~IEEE80211_F_RSNON;
284 		ic->ic_rsnprotos = 0;
285 		ic->ic_rsnakms = 0;
286 		ic->ic_rsngroupcipher = 0;
287 		ic->ic_rsnciphers = 0;
288 		return ENETRESET;
289 	}
290 
291 	ic->ic_rsnprotos = 0;
292 	if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1)
293 		ic->ic_rsnprotos |= IEEE80211_PROTO_WPA;
294 	if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2)
295 		ic->ic_rsnprotos |= IEEE80211_PROTO_RSN;
296 	if (ic->ic_rsnprotos == 0)	/* set to default (RSN) */
297 		ic->ic_rsnprotos = IEEE80211_PROTO_RSN;
298 
299 	ic->ic_rsnakms = 0;
300 	if (wpa->i_akms & IEEE80211_WPA_AKM_PSK)
301 		ic->ic_rsnakms |= IEEE80211_AKM_PSK;
302 	if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK)
303 		ic->ic_rsnakms |= IEEE80211_AKM_SHA256_PSK;
304 	if (wpa->i_akms & IEEE80211_WPA_AKM_8021X)
305 		ic->ic_rsnakms |= IEEE80211_AKM_8021X;
306 	if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X)
307 		ic->ic_rsnakms |= IEEE80211_AKM_SHA256_8021X;
308 	if (ic->ic_rsnakms == 0)	/* set to default (PSK) */
309 		ic->ic_rsnakms = IEEE80211_AKM_PSK;
310 
311 	if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40)
312 		ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40;
313 	else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP)
314 		ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;
315 	else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP)
316 		ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;
317 	else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104)
318 		ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104;
319 	else  {	/* set to default */
320 		if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
321 			ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;
322 		else
323 			ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;
324 	}
325 
326 	ic->ic_rsnciphers = 0;
327 	if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP)
328 		ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;
329 	if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP)
330 		ic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP;
331 	if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP)
332 		ic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP;
333 	if (ic->ic_rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */
334 		ic->ic_rsnciphers = IEEE80211_CIPHER_CCMP;
335 		if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
336 			ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;
337 	}
338 
339 	ic->ic_flags |= IEEE80211_F_RSNON;
340 
341 	return ENETRESET;
342 }
343 
344 static int
345 ieee80211_ioctl_getwpaparms(struct ieee80211com *ic,
346     struct ieee80211_wpaparams *wpa)
347 {
348 	wpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0;
349 
350 	wpa->i_protos = 0;
351 	if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
352 		wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1;
353 	if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN)
354 		wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2;
355 
356 	wpa->i_akms = 0;
357 	if (ic->ic_rsnakms & IEEE80211_AKM_PSK)
358 		wpa->i_akms |= IEEE80211_WPA_AKM_PSK;
359 	if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK)
360 		wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK;
361 	if (ic->ic_rsnakms & IEEE80211_AKM_8021X)
362 		wpa->i_akms |= IEEE80211_WPA_AKM_8021X;
363 	if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X)
364 		wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X;
365 
366 	if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40)
367 		wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40;
368 	else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP)
369 		wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP;
370 	else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP)
371 		wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP;
372 	else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104)
373 		wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104;
374 	else
375 		wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE;
376 
377 	wpa->i_ciphers = 0;
378 	if (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP)
379 		wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP;
380 	if (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP)
381 		wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP;
382 	if (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP)
383 		wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP;
384 
385 	return 0;
386 }
387 
388 int
389 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
390 {
391 	struct ieee80211com *ic = (void *)ifp;
392 	struct ifreq *ifr = (struct ifreq *)data;
393 	int i, error = 0;
394 	struct ieee80211_nwid nwid;
395 	struct ieee80211_wpapsk *psk;
396 	struct ieee80211_keyavail *ka;
397 	struct ieee80211_keyrun *kr;
398 	struct ieee80211_power *power;
399 	struct ieee80211_bssid *bssid;
400 	struct ieee80211chanreq *chanreq;
401 	struct ieee80211_channel *chan;
402 	struct ieee80211_txpower *txpower;
403 	static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
404 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
405 	};
406 	struct ieee80211_nodereq *nr, nrbuf;
407 	struct ieee80211_nodereq_all *na;
408 	struct ieee80211_node *ni;
409 	u_int32_t flags;
410 
411 	switch (cmd) {
412 	case SIOCSIFMEDIA:
413 	case SIOCGIFMEDIA:
414 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
415 		break;
416 	case SIOCS80211NWID:
417 		if ((error = suser(curproc)) != 0)
418 			break;
419 		if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
420 			break;
421 		if (nwid.i_len > IEEE80211_NWID_LEN) {
422 			error = EINVAL;
423 			break;
424 		}
425 		memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
426 		ic->ic_des_esslen = nwid.i_len;
427 		memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
428 		/* disable WPA/WEP */
429 		ieee80211_disable_rsn(ic);
430 		ieee80211_disable_wep(ic);
431 		error = ENETRESET;
432 		break;
433 	case SIOCG80211NWID:
434 		memset(&nwid, 0, sizeof(nwid));
435 		switch (ic->ic_state) {
436 		case IEEE80211_S_INIT:
437 		case IEEE80211_S_SCAN:
438 			nwid.i_len = ic->ic_des_esslen;
439 			memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);
440 			break;
441 		default:
442 			nwid.i_len = ic->ic_bss->ni_esslen;
443 			memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len);
444 			break;
445 		}
446 		error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
447 		break;
448 	case SIOCS80211NWKEY:
449 		if ((error = suser(curproc)) != 0)
450 			break;
451 		error = ieee80211_ioctl_setnwkeys(ic, (void *)data);
452 		break;
453 	case SIOCG80211NWKEY:
454 		error = ieee80211_ioctl_getnwkeys(ic, (void *)data);
455 		break;
456 	case SIOCS80211WPAPARMS:
457 		if ((error = suser(curproc)) != 0)
458 			break;
459 		error = ieee80211_ioctl_setwpaparms(ic, (void *)data);
460 		break;
461 	case SIOCG80211WPAPARMS:
462 		error = ieee80211_ioctl_getwpaparms(ic, (void *)data);
463 		break;
464 	case SIOCS80211WPAPSK:
465 		if ((error = suser(curproc)) != 0)
466 			break;
467 		psk = (struct ieee80211_wpapsk *)data;
468 		if (psk->i_enabled) {
469 			ic->ic_flags |= IEEE80211_F_PSK;
470 			memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk));
471 			if (ic->ic_flags & IEEE80211_F_WEPON)
472 				ieee80211_disable_wep(ic);
473 		} else {
474 			ic->ic_flags &= ~IEEE80211_F_PSK;
475 			memset(ic->ic_psk, 0, sizeof(ic->ic_psk));
476 		}
477 		error = ENETRESET;
478 		break;
479 	case SIOCG80211WPAPSK:
480 		psk = (struct ieee80211_wpapsk *)data;
481 		if (ic->ic_flags & IEEE80211_F_PSK) {
482 			/* do not show any keys to userland */
483 			psk->i_enabled = 2;
484 			memset(psk->i_psk, 0, sizeof(psk->i_psk));
485 			break;	/* return ok but w/o key */
486 		} else
487 			psk->i_enabled = 0;
488 		break;
489 	case SIOCS80211KEYAVAIL:
490 		if ((error = suser(curproc)) != 0)
491 			break;
492 		ka = (struct ieee80211_keyavail *)data;
493 		(void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X,
494 		    ka->i_macaddr, ka->i_key, ka->i_lifetime);
495 		break;
496 	case SIOCS80211KEYRUN:
497 		if ((error = suser(curproc)) != 0)
498 			break;
499 		kr = (struct ieee80211_keyrun *)data;
500 		error = ieee80211_keyrun(ic, kr->i_macaddr);
501 		if (error == 0 && (ic->ic_flags & IEEE80211_F_WEPON))
502 			ieee80211_disable_wep(ic);
503 		break;
504 	case SIOCS80211POWER:
505 		if ((error = suser(curproc)) != 0)
506 			break;
507 		power = (struct ieee80211_power *)data;
508 		ic->ic_lintval = power->i_maxsleep;
509 		if (power->i_enabled != 0) {
510 			if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
511 				error = EINVAL;
512 			else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
513 				ic->ic_flags |= IEEE80211_F_PMGTON;
514 				error = ENETRESET;
515 			}
516 		} else {
517 			if (ic->ic_flags & IEEE80211_F_PMGTON) {
518 				ic->ic_flags &= ~IEEE80211_F_PMGTON;
519 				error = ENETRESET;
520 			}
521 		}
522 		break;
523 	case SIOCG80211POWER:
524 		power = (struct ieee80211_power *)data;
525 		power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
526 		power->i_maxsleep = ic->ic_lintval;
527 		break;
528 	case SIOCS80211BSSID:
529 		if ((error = suser(curproc)) != 0)
530 			break;
531 		bssid = (struct ieee80211_bssid *)data;
532 		if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))
533 			ic->ic_flags &= ~IEEE80211_F_DESBSSID;
534 		else {
535 			ic->ic_flags |= IEEE80211_F_DESBSSID;
536 			IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);
537 		}
538 #ifndef IEEE80211_STA_ONLY
539 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
540 			break;
541 #endif
542 		switch (ic->ic_state) {
543 		case IEEE80211_S_INIT:
544 		case IEEE80211_S_SCAN:
545 			error = ENETRESET;
546 			break;
547 		default:
548 			if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
549 			    !IEEE80211_ADDR_EQ(ic->ic_des_bssid,
550 			    ic->ic_bss->ni_bssid))
551 				error = ENETRESET;
552 			break;
553 		}
554 		break;
555 	case SIOCG80211BSSID:
556 		bssid = (struct ieee80211_bssid *)data;
557 		switch (ic->ic_state) {
558 		case IEEE80211_S_INIT:
559 		case IEEE80211_S_SCAN:
560 #ifndef IEEE80211_STA_ONLY
561 			if (ic->ic_opmode == IEEE80211_M_HOSTAP)
562 				IEEE80211_ADDR_COPY(bssid->i_bssid,
563 				    ic->ic_myaddr);
564 			else
565 #endif
566 			if (ic->ic_flags & IEEE80211_F_DESBSSID)
567 				IEEE80211_ADDR_COPY(bssid->i_bssid,
568 				    ic->ic_des_bssid);
569 			else
570 				memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
571 			break;
572 		default:
573 			IEEE80211_ADDR_COPY(bssid->i_bssid,
574 			    ic->ic_bss->ni_bssid);
575 			break;
576 		}
577 		break;
578 	case SIOCS80211CHANNEL:
579 		if ((error = suser(curproc)) != 0)
580 			break;
581 		chanreq = (struct ieee80211chanreq *)data;
582 		if (chanreq->i_channel == IEEE80211_CHAN_ANY)
583 			ic->ic_des_chan = IEEE80211_CHAN_ANYC;
584 		else if (chanreq->i_channel > IEEE80211_CHAN_MAX ||
585 		    isclr(ic->ic_chan_active, chanreq->i_channel)) {
586 			error = EINVAL;
587 			break;
588 		} else
589 			ic->ic_ibss_chan = ic->ic_des_chan =
590 			    &ic->ic_channels[chanreq->i_channel];
591 		switch (ic->ic_state) {
592 		case IEEE80211_S_INIT:
593 		case IEEE80211_S_SCAN:
594 			error = ENETRESET;
595 			break;
596 		default:
597 			if (ic->ic_opmode == IEEE80211_M_STA) {
598 				if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
599 				    ic->ic_bss->ni_chan != ic->ic_des_chan)
600 					error = ENETRESET;
601 			} else {
602 				if (ic->ic_bss->ni_chan != ic->ic_ibss_chan)
603 					error = ENETRESET;
604 			}
605 			break;
606 		}
607 		break;
608 	case SIOCG80211CHANNEL:
609 		chanreq = (struct ieee80211chanreq *)data;
610 		switch (ic->ic_state) {
611 		case IEEE80211_S_INIT:
612 		case IEEE80211_S_SCAN:
613 			if (ic->ic_opmode == IEEE80211_M_STA)
614 				chan = ic->ic_des_chan;
615 			else
616 				chan = ic->ic_ibss_chan;
617 			break;
618 		default:
619 			chan = ic->ic_bss->ni_chan;
620 			break;
621 		}
622 		chanreq->i_channel = ieee80211_chan2ieee(ic, chan);
623 		break;
624 	case SIOCG80211ALLCHANS:
625 		error = copyout(ic->ic_channels,
626 		    ((struct ieee80211_chanreq_all *)data)->i_chans,
627 		    sizeof(ic->ic_channels));
628 		break;
629 #if 0
630 	case SIOCG80211ZSTATS:
631 #endif
632 	case SIOCG80211STATS:
633 		ifr = (struct ifreq *)data;
634 		error = copyout(&ic->ic_stats, ifr->ifr_data,
635 		    sizeof(ic->ic_stats));
636 #if 0
637 		if (cmd == SIOCG80211ZSTATS)
638 			memset(&ic->ic_stats, 0, sizeof(ic->ic_stats));
639 #endif
640 		break;
641 	case SIOCS80211TXPOWER:
642 		if ((error = suser(curproc)) != 0)
643 			break;
644 		txpower = (struct ieee80211_txpower *)data;
645 		if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) {
646 			error = EINVAL;
647 			break;
648 		}
649 		if (!(IEEE80211_TXPOWER_MIN <= txpower->i_val &&
650 			txpower->i_val <= IEEE80211_TXPOWER_MAX)) {
651 			error = EINVAL;
652 			break;
653 		}
654 		ic->ic_txpower = txpower->i_val;
655 		error = ENETRESET;
656 		break;
657 	case SIOCG80211TXPOWER:
658 		txpower = (struct ieee80211_txpower *)data;
659 		if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
660 			error = EINVAL;
661 		else
662 			txpower->i_val = ic->ic_txpower;
663 		break;
664 	case SIOCSIFMTU:
665 		ifr = (struct ifreq *)data;
666 		if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
667 		    ifr->ifr_mtu <= IEEE80211_MTU_MAX))
668 			error = EINVAL;
669 		else
670 			ifp->if_mtu = ifr->ifr_mtu;
671 		break;
672 	case SIOCS80211SCAN:
673 		if ((error = suser(curproc)) != 0)
674 			break;
675 #ifndef IEEE80211_STA_ONLY
676 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
677 			break;
678 #endif
679 		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
680 		    (IFF_UP | IFF_RUNNING)) {
681 			error = ENETDOWN;
682 			break;
683 		}
684 		if ((ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) == 0) {
685 			if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED)
686 				ic->ic_scan_lock |= IEEE80211_SCAN_RESUME;
687 			ic->ic_scan_lock |= IEEE80211_SCAN_REQUEST;
688 			if (ic->ic_state != IEEE80211_S_SCAN) {
689 				ieee80211_clean_cached(ic);
690 				if (ic->ic_opmode == IEEE80211_M_STA &&
691 				    ic->ic_state == IEEE80211_S_RUN &&
692 				    IFM_MODE(ic->ic_media.ifm_cur->ifm_media)
693 				    == IFM_AUTO) {
694 					/*
695 					 * We're already associated to an AP.
696 					 * Make the scanning loop start off in
697 					 * auto mode so all supported bands
698 					 * get scanned.
699 					 */
700 					ieee80211_setmode(ic,
701 					    IEEE80211_MODE_AUTO);
702 				}
703 				ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
704 			}
705 		}
706 		/* Let the userspace process wait for completion */
707 		error = tsleep(&ic->ic_scan_lock, PCATCH, "80211scan",
708 		    hz * IEEE80211_SCAN_TIMEOUT);
709 		break;
710 	case SIOCG80211NODE:
711 		nr = (struct ieee80211_nodereq *)data;
712 		ni = ieee80211_find_node(ic, nr->nr_macaddr);
713 		if (ni == NULL) {
714 			error = ENOENT;
715 			break;
716 		}
717 		ieee80211_node2req(ic, ni, nr);
718 		break;
719 	case SIOCS80211NODE:
720 		if ((error = suser(curproc)) != 0)
721 			break;
722 #ifndef IEEE80211_STA_ONLY
723 		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
724 			error = EINVAL;
725 			break;
726 		}
727 #endif
728 		nr = (struct ieee80211_nodereq *)data;
729 
730 		ni = ieee80211_find_node(ic, nr->nr_macaddr);
731 		if (ni == NULL)
732 			ni = ieee80211_alloc_node(ic, nr->nr_macaddr);
733 		if (ni == NULL) {
734 			error = ENOENT;
735 			break;
736 		}
737 
738 		if (nr->nr_flags & IEEE80211_NODEREQ_COPY)
739 			ieee80211_req2node(ic, nr, ni);
740 		break;
741 #ifndef IEEE80211_STA_ONLY
742 	case SIOCS80211DELNODE:
743 		if ((error = suser(curproc)) != 0)
744 			break;
745 		nr = (struct ieee80211_nodereq *)data;
746 		ni = ieee80211_find_node(ic, nr->nr_macaddr);
747 		if (ni == NULL)
748 			error = ENOENT;
749 		else if (ni == ic->ic_bss)
750 			error = EPERM;
751 		else {
752 			if (ni->ni_state == IEEE80211_STA_COLLECT)
753 				break;
754 
755 			/* Disassociate station. */
756 			if (ni->ni_state == IEEE80211_STA_ASSOC)
757 				IEEE80211_SEND_MGMT(ic, ni,
758 				    IEEE80211_FC0_SUBTYPE_DISASSOC,
759 				    IEEE80211_REASON_ASSOC_LEAVE);
760 
761 			/* Deauth station. */
762 			if (ni->ni_state >= IEEE80211_STA_AUTH)
763 				IEEE80211_SEND_MGMT(ic, ni,
764 				    IEEE80211_FC0_SUBTYPE_DEAUTH,
765 				    IEEE80211_REASON_AUTH_LEAVE);
766 
767 			ieee80211_node_leave(ic, ni);
768 		}
769 		break;
770 #endif
771 	case SIOCG80211ALLNODES:
772 		na = (struct ieee80211_nodereq_all *)data;
773 		na->na_nodes = i = 0;
774 		ni = RBT_MIN(ieee80211_tree, &ic->ic_tree);
775 		while (ni && na->na_size >=
776 		    i + sizeof(struct ieee80211_nodereq)) {
777 			ieee80211_node2req(ic, ni, &nrbuf);
778 			error = copyout(&nrbuf, (caddr_t)na->na_node + i,
779 			    sizeof(struct ieee80211_nodereq));
780 			if (error)
781 				break;
782 			i += sizeof(struct ieee80211_nodereq);
783 			na->na_nodes++;
784 			ni = RBT_NEXT(ieee80211_tree, ni);
785 		}
786 		break;
787 	case SIOCG80211FLAGS:
788 		flags = ic->ic_flags;
789 #ifndef IEEE80211_STA_ONLY
790 		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
791 #endif
792 			flags &= ~IEEE80211_F_HOSTAPMASK;
793 		ifr->ifr_flags = flags >> IEEE80211_F_USERSHIFT;
794 		break;
795 	case SIOCS80211FLAGS:
796 		if ((error = suser(curproc)) != 0)
797 			break;
798 		flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
799 		if (
800 #ifndef IEEE80211_STA_ONLY
801 		    ic->ic_opmode != IEEE80211_M_HOSTAP &&
802 #endif
803 		    (flags & IEEE80211_F_HOSTAPMASK)) {
804 			error = EINVAL;
805 			break;
806 		}
807 		ic->ic_flags = (ic->ic_flags & ~IEEE80211_F_USERMASK) | flags;
808 		error = ENETRESET;
809 		break;
810 	case SIOCADDMULTI:
811 	case SIOCDELMULTI:
812 		error = (cmd == SIOCADDMULTI) ?
813 		    ether_addmulti(ifr, &ic->ic_ac) :
814 		    ether_delmulti(ifr, &ic->ic_ac);
815 		if (error == ENETRESET)
816 			error = 0;
817 		break;
818 	default:
819 		error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
820 	}
821 
822 	return error;
823 }
824