1 /*
2  * Copyright (c) 2001 Atsushi Onoe
3  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * Alternatively, this software may be distributed under the terms of the
18  * GNU General Public License ("GPL") version 2 as published by the Free
19  * Software Foundation.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * $FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.13 2004/03/30 22:57:57 sam Exp $
33  * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_ioctl.c,v 1.1 2004/07/26 16:30:17 joerg Exp $
34  */
35 
36 /*
37  * IEEE 802.11 ioctl support (FreeBSD-specific)
38  */
39 
40 #include "opt_inet.h"
41 #include "opt_ipx.h"
42 
43 #include <sys/endian.h>
44 #include <sys/param.h>
45 #include <sys/kernel.h>
46 #include <sys/proc.h>
47 #include <sys/socket.h>
48 #include <sys/sockio.h>
49 #include <sys/systm.h>
50 #include <sys/thread.h>
51 
52 #include <net/if.h>
53 #include <net/if_arp.h>
54 #include <net/if_media.h>
55 #include <net/ethernet.h>
56 
57 #ifdef INET
58 #include <netinet/in.h>
59 #include <netinet/if_ether.h>
60 #endif
61 
62 #ifdef IPX
63 #include <netproto/ipx/ipx.h>
64 #include <netproto/ipx/ipx_if.h>
65 #endif
66 
67 #include <netproto/802_11/ieee80211_var.h>
68 #include <netproto/802_11/ieee80211_ioctl.h>
69 
70 #include <netproto/802_11/if_wavelan_ieee.h>
71 
72 /*
73  * XXX
74  * Wireless LAN specific configuration interface, which is compatible
75  * with wicontrol(8).
76  */
77 
78 int
79 ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
80 {
81 	struct ieee80211com *ic = (void *)ifp;
82 	int i, j, error;
83 	struct ifreq *ifr = (struct ifreq *)data;
84 	struct wi_req wreq;
85 	struct wi_ltv_keys *keys;
86 	struct wi_apinfo *ap;
87 	struct ieee80211_node *ni;
88 	struct ieee80211_rateset *rs;
89 	struct wi_sigcache wsc;
90 	struct wi_scan_p2_hdr *p2;
91 	struct wi_scan_res *res;
92 
93 	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
94 	if (error)
95 		return error;
96 	wreq.wi_len = 0;
97 	switch (wreq.wi_type) {
98 	case WI_RID_SERIALNO:
99 		/* nothing appropriate */
100 		break;
101 	case WI_RID_NODENAME:
102 		strcpy((char *)&wreq.wi_val[1], hostname);
103 		wreq.wi_val[0] = htole16(strlen(hostname));
104 		wreq.wi_len = (1 + strlen(hostname) + 1) / 2;
105 		break;
106 	case WI_RID_CURRENT_SSID:
107 		if (ic->ic_state != IEEE80211_S_RUN) {
108 			wreq.wi_val[0] = 0;
109 			wreq.wi_len = 1;
110 			break;
111 		}
112 		wreq.wi_val[0] = htole16(ic->ic_bss->ni_esslen);
113 		memcpy(&wreq.wi_val[1], ic->ic_bss->ni_essid,
114 		    ic->ic_bss->ni_esslen);
115 		wreq.wi_len = (1 + ic->ic_bss->ni_esslen + 1) / 2;
116 		break;
117 	case WI_RID_OWN_SSID:
118 	case WI_RID_DESIRED_SSID:
119 		wreq.wi_val[0] = htole16(ic->ic_des_esslen);
120 		memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen);
121 		wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2;
122 		break;
123 	case WI_RID_CURRENT_BSSID:
124 		if (ic->ic_state == IEEE80211_S_RUN)
125 			IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss->ni_bssid);
126 		else
127 			memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN);
128 		wreq.wi_len = IEEE80211_ADDR_LEN / 2;
129 		break;
130 	case WI_RID_CHANNEL_LIST:
131 		memset(wreq.wi_val, 0, sizeof(wreq.wi_val));
132 		/*
133 		 * Since channel 0 is not available for DS, channel 1
134 		 * is assigned to LSB on WaveLAN.
135 		 */
136 		if (ic->ic_phytype == IEEE80211_T_DS)
137 			i = 1;
138 		else
139 			i = 0;
140 		for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++)
141 			if (isset(ic->ic_chan_active, i)) {
142 				setbit((uint8_t *)wreq.wi_val, j);
143 				wreq.wi_len = j / 16 + 1;
144 			}
145 		break;
146 	case WI_RID_OWN_CHNL:
147 		wreq.wi_val[0] = htole16(
148 			ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
149 		wreq.wi_len = 1;
150 		break;
151 	case WI_RID_CURRENT_CHAN:
152 		wreq.wi_val[0] = htole16(
153 			ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
154 		wreq.wi_len = 1;
155 		break;
156 	case WI_RID_COMMS_QUALITY:
157 		wreq.wi_val[0] = 0;				/* quality */
158 		wreq.wi_val[1] =
159 			htole16((*ic->ic_node_getrssi)(ic, ic->ic_bss));
160 		wreq.wi_val[2] = 0;				/* noise */
161 		wreq.wi_len = 3;
162 		break;
163 	case WI_RID_PROMISC:
164 		wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0);
165 		wreq.wi_len = 1;
166 		break;
167 	case WI_RID_PORTTYPE:
168 		wreq.wi_val[0] = htole16(ic->ic_opmode);
169 		wreq.wi_len = 1;
170 		break;
171 	case WI_RID_MAC_NODE:
172 		IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr);
173 		wreq.wi_len = IEEE80211_ADDR_LEN / 2;
174 		break;
175 	case WI_RID_TX_RATE:
176 		if (ic->ic_fixed_rate == -1)
177 			wreq.wi_val[0] = 0;	/* auto */
178 		else
179 			wreq.wi_val[0] = htole16(
180 			    (ic->ic_sup_rates[ic->ic_curmode].rs_rates[ic->ic_fixed_rate] &
181 			    IEEE80211_RATE_VAL) / 2);
182 		wreq.wi_len = 1;
183 		break;
184 	case WI_RID_CUR_TX_RATE:
185 		wreq.wi_val[0] = htole16(
186 		    (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
187 		    IEEE80211_RATE_VAL) / 2);
188 		wreq.wi_len = 1;
189 		break;
190 	case WI_RID_RTS_THRESH:
191 		wreq.wi_val[0] = htole16(ic->ic_rtsthreshold);
192 		wreq.wi_len = 1;
193 		break;
194 	case WI_RID_CREATE_IBSS:
195 		wreq.wi_val[0] =
196 		    htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0);
197 		wreq.wi_len = 1;
198 		break;
199 	case WI_RID_MICROWAVE_OVEN:
200 		wreq.wi_val[0] = 0;	/* no ... not supported */
201 		wreq.wi_len = 1;
202 		break;
203 	case WI_RID_ROAMING_MODE:
204 		wreq.wi_val[0] = htole16(1);	/* enabled ... not supported */
205 		wreq.wi_len = 1;
206 		break;
207 	case WI_RID_SYSTEM_SCALE:
208 		wreq.wi_val[0] = htole16(1);	/* low density ... not supp */
209 		wreq.wi_len = 1;
210 		break;
211 	case WI_RID_PM_ENABLED:
212 		wreq.wi_val[0] =
213 		    htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
214 		wreq.wi_len = 1;
215 		break;
216 	case WI_RID_MAX_SLEEP:
217 		wreq.wi_val[0] = htole16(ic->ic_lintval);
218 		wreq.wi_len = 1;
219 		break;
220 	case WI_RID_CUR_BEACON_INT:
221 		wreq.wi_val[0] = htole16(ic->ic_bss->ni_intval);
222 		wreq.wi_len = 1;
223 		break;
224 	case WI_RID_WEP_AVAIL:
225 		wreq.wi_val[0] =
226 		    htole16((ic->ic_caps & IEEE80211_C_WEP) ? 1 : 0);
227 		wreq.wi_len = 1;
228 		break;
229 	case WI_RID_CNFAUTHMODE:
230 		wreq.wi_val[0] = htole16(1);	/* TODO: open system only */
231 		wreq.wi_len = 1;
232 		break;
233 	case WI_RID_ENCRYPTION:
234 		wreq.wi_val[0] =
235 		    htole16((ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0);
236 		wreq.wi_len = 1;
237 		break;
238 	case WI_RID_TX_CRYPT_KEY:
239 		wreq.wi_val[0] = htole16(ic->ic_wep_txkey);
240 		wreq.wi_len = 1;
241 		break;
242 	case WI_RID_DEFLT_CRYPT_KEYS:
243 		keys = (struct wi_ltv_keys *)&wreq;
244 		/* do not show keys to non-root user */
245 		error = suser_cred(cr, NULL_CRED_OKAY);
246 		if (error) {
247 			memset(keys, 0, sizeof(*keys));
248 			error = 0;
249 			break;
250 		}
251 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
252 			keys->wi_keys[i].wi_keylen =
253 			    htole16(ic->ic_nw_keys[i].wk_len);
254 			memcpy(keys->wi_keys[i].wi_keydat,
255 			    ic->ic_nw_keys[i].wk_key, ic->ic_nw_keys[i].wk_len);
256 		}
257 		wreq.wi_len = sizeof(*keys) / 2;
258 		break;
259 	case WI_RID_MAX_DATALEN:
260 		wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN);	/* TODO: frag */
261 		wreq.wi_len = 1;
262 		break;
263 	case WI_RID_IFACE_STATS:
264 		/* XXX: should be implemented in lower drivers */
265 		break;
266 	case WI_RID_READ_APS:
267 		if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
268 			/*
269 			 * Don't return results until active scan completes.
270 			 */
271 			if (ic->ic_state == IEEE80211_S_SCAN &&
272 			    (ic->ic_flags & IEEE80211_F_ASCAN)) {
273 				error = EINPROGRESS;
274 				break;
275 			}
276 		}
277 		i = 0;
278 		ap = (void *)((char *)wreq.wi_val + sizeof(i));
279 		TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
280 			if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1))
281 				break;
282 			memset(ap, 0, sizeof(*ap));
283 			if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
284 				IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr);
285 				ap->namelen = ic->ic_des_esslen;
286 				if (ic->ic_des_esslen)
287 					memcpy(ap->name, ic->ic_des_essid,
288 					    ic->ic_des_esslen);
289 			} else {
290 				IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid);
291 				ap->namelen = ni->ni_esslen;
292 				if (ni->ni_esslen)
293 					memcpy(ap->name, ni->ni_essid,
294 					    ni->ni_esslen);
295 			}
296 			ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan);
297 			ap->signal = (*ic->ic_node_getrssi)(ic, ni);
298 			ap->capinfo = ni->ni_capinfo;
299 			ap->interval = ni->ni_intval;
300 			rs = &ni->ni_rates;
301 			for (j = 0; j < rs->rs_nrates; j++) {
302 				if (rs->rs_rates[j] & IEEE80211_RATE_BASIC) {
303 					ap->rate = (rs->rs_rates[j] &
304 					    IEEE80211_RATE_VAL) * 5; /* XXX */
305 				}
306 			}
307 			i++;
308 			ap++;
309 		}
310 		memcpy(wreq.wi_val, &i, sizeof(i));
311 		wreq.wi_len = (sizeof(int) + sizeof(*ap) * i) / 2;
312 		break;
313 	case WI_RID_PRISM2:
314 		wreq.wi_val[0] = 1;	/* XXX lie so SCAN_RES can give rates */
315 		wreq.wi_len = sizeof(uint16_t) / 2;
316 		break;
317 	case WI_RID_SCAN_RES:			/* compatibility interface */
318 		if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
319 		    ic->ic_state == IEEE80211_S_SCAN &&
320 		    (ic->ic_flags & IEEE80211_F_ASCAN)) {
321 			error = EINPROGRESS;
322 			break;
323 		}
324 		/* NB: we use the Prism2 format so we can return rate info */
325 		p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
326 		res = (void *)&p2[1];
327 		i = 0;
328 		TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
329 			if ((caddr_t)(res + 1) > (caddr_t)(&wreq + 1))
330 				break;
331 			res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan);
332 			res->wi_noise = 0;
333 			res->wi_signal = (*ic->ic_node_getrssi)(ic, ni);
334 			IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid);
335 			res->wi_interval = ni->ni_intval;
336 			res->wi_capinfo = ni->ni_capinfo;
337 			res->wi_ssid_len = ni->ni_esslen;
338 			memcpy(res->wi_ssid, ni->ni_essid, IEEE80211_NWID_LEN);
339 			/* NB: assumes wi_srates holds <= ni->ni_rates */
340 			memcpy(res->wi_srates, ni->ni_rates.rs_rates,
341 				sizeof(res->wi_srates));
342 			if (ni->ni_rates.rs_nrates < 10)
343 				res->wi_srates[ni->ni_rates.rs_nrates] = 0;
344 			res->wi_rate = ni->ni_rates.rs_rates[ni->ni_txrate];
345 			res->wi_rsvd = 0;
346 			res++, i++;
347 		}
348 		p2->wi_rsvd = 0;
349 		p2->wi_reason = i;
350 		wreq.wi_len = (sizeof(*p2) + sizeof(*res) * i) / 2;
351 		break;
352 	case WI_RID_READ_CACHE:
353 		i = 0;
354 		TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
355 			if (i == (WI_MAX_DATALEN/sizeof(struct wi_sigcache))-1)
356 				break;
357 			IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr);
358 			memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc));
359 			wsc.signal = (*ic->ic_node_getrssi)(ic, ni);
360 			wsc.noise = 0;
361 			wsc.quality = 0;
362 			memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
363 			    &wsc, sizeof(wsc));
364 			i++;
365 		}
366 		wreq.wi_len = sizeof(wsc) * i / 2;
367 		break;
368 	case WI_RID_SCAN_APS:
369 		error = EINVAL;
370 		break;
371 	default:
372 		error = EINVAL;
373 		break;
374 	}
375 	if (error == 0) {
376 		wreq.wi_len++;
377 		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
378 	}
379 	return error;
380 }
381 
382 static int
383 findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate)
384 {
385 #define	IEEERATE(_ic,_m,_i) \
386 	((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
387 	int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
388 	for (i = 0; i < nrates; i++)
389 		if (IEEERATE(ic, mode, i) == rate)
390 			return i;
391 	return -1;
392 #undef IEEERATE
393 }
394 
395 /*
396  * Prepare to do a user-initiated scan for AP's.  If no
397  * current/default channel is setup or the current channel
398  * is invalid then pick the first available channel from
399  * the active list as the place to start the scan.
400  */
401 static int
402 ieee80211_setupscan(struct ieee80211com *ic)
403 {
404 	u_char *chanlist = ic->ic_chan_active;
405 	int i;
406 
407 	if (ic->ic_ibss_chan == NULL ||
408 	    isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
409 		for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
410 			if (isset(chanlist, i)) {
411 				ic->ic_ibss_chan = &ic->ic_channels[i];
412 				goto found;
413 			}
414 		return EINVAL;			/* no active channels */
415 found:
416 		;
417 	}
418 	if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC ||
419 	    isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)))
420 		ic->ic_bss->ni_chan = ic->ic_ibss_chan;
421 	/*
422 	 * XXX don't permit a scan to be started unless we
423 	 * know the device is ready.  For the moment this means
424 	 * the device is marked up as this is the required to
425 	 * initialize the hardware.  It would be better to permit
426 	 * scanning prior to being up but that'll require some
427 	 * changes to the infrastructure.
428 	 */
429 	return (ic->ic_if.if_flags & IFF_UP) ? 0 : ENETRESET;
430 }
431 
432 int
433 ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data)
434 {
435 	struct ieee80211com *ic = (void *)ifp;
436 	int i, j, len, error, rate;
437 	struct ifreq *ifr = (struct ifreq *)data;
438 	struct wi_ltv_keys *keys;
439 	struct wi_req wreq;
440 	u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)];
441 
442 	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
443 	if (error)
444 		return error;
445 	len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0;
446 	switch (wreq.wi_type) {
447 	case WI_RID_SERIALNO:
448 	case WI_RID_NODENAME:
449 		return EPERM;
450 	case WI_RID_CURRENT_SSID:
451 		return EPERM;
452 	case WI_RID_OWN_SSID:
453 	case WI_RID_DESIRED_SSID:
454 		if (le16toh(wreq.wi_val[0]) * 2 > len ||
455 		    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) {
456 			error = ENOSPC;
457 			break;
458 		}
459 		memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid));
460 		ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2;
461 		memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen);
462 		error = ENETRESET;
463 		break;
464 	case WI_RID_CURRENT_BSSID:
465 		return EPERM;
466 	case WI_RID_OWN_CHNL:
467 		if (len != 2)
468 			return EINVAL;
469 		i = le16toh(wreq.wi_val[0]);
470 		if (i < 0 ||
471 		    i > IEEE80211_CHAN_MAX ||
472 		    isclr(ic->ic_chan_active, i))
473 			return EINVAL;
474 		ic->ic_ibss_chan = &ic->ic_channels[i];
475 		if (ic->ic_flags & IEEE80211_F_SIBSS)
476 			error = ENETRESET;
477 		break;
478 	case WI_RID_CURRENT_CHAN:
479 		return EPERM;
480 	case WI_RID_COMMS_QUALITY:
481 		return EPERM;
482 	case WI_RID_PROMISC:
483 		if (len != 2)
484 			return EINVAL;
485 		if (ifp->if_flags & IFF_PROMISC) {
486 			if (wreq.wi_val[0] == 0) {
487 				ifp->if_flags &= ~IFF_PROMISC;
488 				error = ENETRESET;
489 			}
490 		} else {
491 			if (wreq.wi_val[0] != 0) {
492 				ifp->if_flags |= IFF_PROMISC;
493 				error = ENETRESET;
494 			}
495 		}
496 		break;
497 	case WI_RID_PORTTYPE:
498 		if (len != 2)
499 			return EINVAL;
500 		switch (le16toh(wreq.wi_val[0])) {
501 		case IEEE80211_M_STA:
502 			break;
503 		case IEEE80211_M_IBSS:
504 			if (!(ic->ic_caps & IEEE80211_C_IBSS))
505 				return EINVAL;
506 			break;
507 		case IEEE80211_M_AHDEMO:
508 			if (ic->ic_phytype != IEEE80211_T_DS ||
509 			    !(ic->ic_caps & IEEE80211_C_AHDEMO))
510 				return EINVAL;
511 			break;
512 		case IEEE80211_M_HOSTAP:
513 			if (!(ic->ic_caps & IEEE80211_C_HOSTAP))
514 				return EINVAL;
515 			break;
516 		default:
517 			return EINVAL;
518 		}
519 		if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) {
520 			ic->ic_opmode = le16toh(wreq.wi_val[0]);
521 			error = ENETRESET;
522 		}
523 		break;
524 #if 0
525 	case WI_RID_MAC_NODE:
526 		if (len != IEEE80211_ADDR_LEN)
527 			return EINVAL;
528 		IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val);
529 		/* if_init will copy lladdr into ic_myaddr */
530 		error = ENETRESET;
531 		break;
532 #endif
533 	case WI_RID_TX_RATE:
534 		if (len != 2)
535 			return EINVAL;
536 		if (wreq.wi_val[0] == 0) {
537 			/* auto */
538 			ic->ic_fixed_rate = -1;
539 			break;
540 		}
541 		rate = 2 * le16toh(wreq.wi_val[0]);
542 		if (ic->ic_curmode == IEEE80211_MODE_AUTO) {
543 			/*
544 			 * In autoselect mode search for the rate.  We take
545 			 * the first instance which may not be right, but we
546 			 * are limited by the interface.  Note that we also
547 			 * lock the mode to insure the rate is meaningful
548 			 * when it is used.
549 			 */
550 			for (j = IEEE80211_MODE_11A;
551 			     j < IEEE80211_MODE_MAX; j++) {
552 				if ((ic->ic_modecaps & (1<<j)) == 0)
553 					continue;
554 				i = findrate(ic, j, rate);
555 				if (i != -1) {
556 					/* lock mode too */
557 					ic->ic_curmode = j;
558 					goto setrate;
559 				}
560 			}
561 		} else {
562 			i = findrate(ic, ic->ic_curmode, rate);
563 			if (i != -1)
564 				goto setrate;
565 		}
566 		return EINVAL;
567 	setrate:
568 		ic->ic_fixed_rate = i;
569 		error = ENETRESET;
570 		break;
571 	case WI_RID_CUR_TX_RATE:
572 		return EPERM;
573 	case WI_RID_RTS_THRESH:
574 		if (len != 2)
575 			return EINVAL;
576 		if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN)
577 			return EINVAL;		/* TODO: RTS */
578 		break;
579 	case WI_RID_CREATE_IBSS:
580 		if (len != 2)
581 			return EINVAL;
582 		if (wreq.wi_val[0] != 0) {
583 			if ((ic->ic_caps & IEEE80211_C_IBSS) == 0)
584 				return EINVAL;
585 			if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) {
586 				ic->ic_flags |= IEEE80211_F_IBSSON;
587 				if (ic->ic_opmode == IEEE80211_M_IBSS &&
588 				    ic->ic_state == IEEE80211_S_SCAN)
589 					error = ENETRESET;
590 			}
591 		} else {
592 			if (ic->ic_flags & IEEE80211_F_IBSSON) {
593 				ic->ic_flags &= ~IEEE80211_F_IBSSON;
594 				if (ic->ic_flags & IEEE80211_F_SIBSS) {
595 					ic->ic_flags &= ~IEEE80211_F_SIBSS;
596 					error = ENETRESET;
597 				}
598 			}
599 		}
600 		break;
601 	case WI_RID_MICROWAVE_OVEN:
602 		if (len != 2)
603 			return EINVAL;
604 		if (wreq.wi_val[0] != 0)
605 			return EINVAL;		/* not supported */
606 		break;
607 	case WI_RID_ROAMING_MODE:
608 		if (len != 2)
609 			return EINVAL;
610 		if (le16toh(wreq.wi_val[0]) != 1)
611 			return EINVAL;		/* not supported */
612 		break;
613 	case WI_RID_SYSTEM_SCALE:
614 		if (len != 2)
615 			return EINVAL;
616 		if (le16toh(wreq.wi_val[0]) != 1)
617 			return EINVAL;		/* not supported */
618 		break;
619 	case WI_RID_PM_ENABLED:
620 		if (len != 2)
621 			return EINVAL;
622 		if (wreq.wi_val[0] != 0) {
623 			if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
624 				return EINVAL;
625 			if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
626 				ic->ic_flags |= IEEE80211_F_PMGTON;
627 				error = ENETRESET;
628 			}
629 		} else {
630 			if (ic->ic_flags & IEEE80211_F_PMGTON) {
631 				ic->ic_flags &= ~IEEE80211_F_PMGTON;
632 				error = ENETRESET;
633 			}
634 		}
635 		break;
636 	case WI_RID_MAX_SLEEP:
637 		if (len != 2)
638 			return EINVAL;
639 		ic->ic_lintval = le16toh(wreq.wi_val[0]);
640 		if (ic->ic_flags & IEEE80211_F_PMGTON)
641 			error = ENETRESET;
642 		break;
643 	case WI_RID_CUR_BEACON_INT:
644 		return EPERM;
645 	case WI_RID_WEP_AVAIL:
646 		return EPERM;
647 	case WI_RID_CNFAUTHMODE:
648 		if (len != 2)
649 			return EINVAL;
650 		if (le16toh(wreq.wi_val[0]) != 1)
651 			return EINVAL;		/* TODO: shared key auth */
652 		break;
653 	case WI_RID_ENCRYPTION:
654 		if (len != 2)
655 			return EINVAL;
656 		if (wreq.wi_val[0] != 0) {
657 			if ((ic->ic_caps & IEEE80211_C_WEP) == 0)
658 				return EINVAL;
659 			if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) {
660 				ic->ic_flags |= IEEE80211_F_WEPON;
661 				error = ENETRESET;
662 			}
663 		} else {
664 			if (ic->ic_flags & IEEE80211_F_WEPON) {
665 				ic->ic_flags &= ~IEEE80211_F_WEPON;
666 				error = ENETRESET;
667 			}
668 		}
669 		break;
670 	case WI_RID_TX_CRYPT_KEY:
671 		if (len != 2)
672 			return EINVAL;
673 		i = le16toh(wreq.wi_val[0]);
674 		if (i >= IEEE80211_WEP_NKID)
675 			return EINVAL;
676 		ic->ic_wep_txkey = i;
677 		break;
678 	case WI_RID_DEFLT_CRYPT_KEYS:
679 		if (len != sizeof(struct wi_ltv_keys))
680 			return EINVAL;
681 		keys = (struct wi_ltv_keys *)&wreq;
682 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
683 			len = le16toh(keys->wi_keys[i].wi_keylen);
684 			if (len != 0 && len < IEEE80211_WEP_KEYLEN)
685 				return EINVAL;
686 			if (len > sizeof(ic->ic_nw_keys[i].wk_key))
687 				return EINVAL;
688 		}
689 		memset(ic->ic_nw_keys, 0, sizeof(ic->ic_nw_keys));
690 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
691 			len = le16toh(keys->wi_keys[i].wi_keylen);
692 			ic->ic_nw_keys[i].wk_len = len;
693 			memcpy(ic->ic_nw_keys[i].wk_key,
694 			    keys->wi_keys[i].wi_keydat, len);
695 		}
696 		error = ENETRESET;
697 		break;
698 	case WI_RID_MAX_DATALEN:
699 		if (len != 2)
700 			return EINVAL;
701 		len = le16toh(wreq.wi_val[0]);
702 		if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN)
703 			return EINVAL;
704 		if (len != IEEE80211_MAX_LEN)
705 			return EINVAL;		/* TODO: fragment */
706 		ic->ic_fragthreshold = len;
707 		error = ENETRESET;
708 		break;
709 	case WI_RID_IFACE_STATS:
710 		error = EPERM;
711 		break;
712 	case WI_RID_SCAN_REQ:			/* XXX wicontrol */
713 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
714 			break;
715 		error = ieee80211_setupscan(ic);
716 		if (error == 0)
717 			error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
718 		break;
719 	case WI_RID_SCAN_APS:
720 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
721 			break;
722 		len--;			/* XXX: tx rate? */
723 		/* FALLTHRU */
724 	case WI_RID_CHANNEL_LIST:
725 		memset(chanlist, 0, sizeof(chanlist));
726 		/*
727 		 * Since channel 0 is not available for DS, channel 1
728 		 * is assigned to LSB on WaveLAN.
729 		 */
730 		if (ic->ic_phytype == IEEE80211_T_DS)
731 			i = 1;
732 		else
733 			i = 0;
734 		for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
735 			if ((j / 8) >= len)
736 				break;
737 			if (isclr((uint8_t *)wreq.wi_val, j))
738 				continue;
739 			if (isclr(ic->ic_chan_active, i)) {
740 				if (wreq.wi_type != WI_RID_CHANNEL_LIST)
741 					continue;
742 				if (isclr(ic->ic_chan_avail, i))
743 					return EPERM;
744 			}
745 			setbit(chanlist, i);
746 		}
747 		memcpy(ic->ic_chan_active, chanlist,
748 		    sizeof(ic->ic_chan_active));
749 		error = ieee80211_setupscan(ic);
750 		if (wreq.wi_type == WI_RID_CHANNEL_LIST) {
751 			/* NB: ignore error from ieee80211_setupscan */
752 			error = ENETRESET;
753 		} else if (error == 0)
754 			error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
755 		break;
756 	default:
757 		error = EINVAL;
758 		break;
759 	}
760 	return error;
761 }
762 
763 int
764 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
765 {
766 	struct ieee80211com *ic = (void *)ifp;
767 	int error = 0;
768 	u_int kid, len;
769 	struct ieee80211req *ireq;
770 	struct ifreq *ifr;
771 	uint8_t tmpkey[IEEE80211_KEYBUF_SIZE];
772 	char tmpssid[IEEE80211_NWID_LEN];
773 	struct ieee80211_channel *chan;
774 	struct ifaddr *ifa;			/* XXX */
775 
776 	switch (cmd) {
777 	case SIOCSIFMEDIA:
778 	case SIOCGIFMEDIA:
779 		error = ifmedia_ioctl(ifp, (struct ifreq *) data,
780 				&ic->ic_media, cmd);
781 		break;
782 	case SIOCG80211:
783 		ireq = (struct ieee80211req *) data;
784 		switch (ireq->i_type) {
785 		case IEEE80211_IOC_SSID:
786 			switch (ic->ic_state) {
787 			case IEEE80211_S_INIT:
788 			case IEEE80211_S_SCAN:
789 				ireq->i_len = ic->ic_des_esslen;
790 				memcpy(tmpssid, ic->ic_des_essid, ireq->i_len);
791 				break;
792 			default:
793 				ireq->i_len = ic->ic_bss->ni_esslen;
794 				memcpy(tmpssid, ic->ic_bss->ni_essid,
795 					ireq->i_len);
796 				break;
797 			}
798 			error = copyout(tmpssid, ireq->i_data, ireq->i_len);
799 			break;
800 		case IEEE80211_IOC_NUMSSIDS:
801 			ireq->i_val = 1;
802 			break;
803 		case IEEE80211_IOC_WEP:
804 			if ((ic->ic_caps & IEEE80211_C_WEP) == 0) {
805 				ireq->i_val = IEEE80211_WEP_NOSUP;
806 			} else {
807 				if (ic->ic_flags & IEEE80211_F_WEPON) {
808 					ireq->i_val =
809 					    IEEE80211_WEP_MIXED;
810 				} else {
811 					ireq->i_val =
812 					    IEEE80211_WEP_OFF;
813 				}
814 			}
815 			break;
816 		case IEEE80211_IOC_WEPKEY:
817 			if ((ic->ic_caps & IEEE80211_C_WEP) == 0) {
818 				error = EINVAL;
819 				break;
820 			}
821 			kid = (u_int) ireq->i_val;
822 			if (kid >= IEEE80211_WEP_NKID) {
823 				error = EINVAL;
824 				break;
825 			}
826 			len = (u_int) ic->ic_nw_keys[kid].wk_len;
827 			/* NB: only root can read WEP keys */
828 			if (suser_cred(cr, NULL_CRED_OKAY) == 0) {
829 				bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len);
830 			} else {
831 				bzero(tmpkey, len);
832 			}
833 			ireq->i_len = len;
834 			error = copyout(tmpkey, ireq->i_data, len);
835 			break;
836 		case IEEE80211_IOC_NUMWEPKEYS:
837 			if ((ic->ic_caps & IEEE80211_C_WEP) == 0)
838 				error = EINVAL;
839 			else
840 				ireq->i_val = IEEE80211_WEP_NKID;
841 			break;
842 		case IEEE80211_IOC_WEPTXKEY:
843 			if ((ic->ic_caps & IEEE80211_C_WEP) == 0)
844 				error = EINVAL;
845 			else
846 				ireq->i_val = ic->ic_wep_txkey;
847 			break;
848 		case IEEE80211_IOC_AUTHMODE:
849 			ireq->i_val = IEEE80211_AUTH_OPEN;
850 			break;
851 		case IEEE80211_IOC_CHANNEL:
852 			switch (ic->ic_state) {
853 			case IEEE80211_S_INIT:
854 			case IEEE80211_S_SCAN:
855 				if (ic->ic_opmode == IEEE80211_M_STA)
856 					chan = ic->ic_des_chan;
857 				else
858 					chan = ic->ic_ibss_chan;
859 				break;
860 			default:
861 				chan = ic->ic_bss->ni_chan;
862 				break;
863 			}
864 			ireq->i_val = ieee80211_chan2ieee(ic, chan);
865 			break;
866 		case IEEE80211_IOC_POWERSAVE:
867 			if (ic->ic_flags & IEEE80211_F_PMGTON)
868 				ireq->i_val = IEEE80211_POWERSAVE_ON;
869 			else
870 				ireq->i_val = IEEE80211_POWERSAVE_OFF;
871 			break;
872 		case IEEE80211_IOC_POWERSAVESLEEP:
873 			ireq->i_val = ic->ic_lintval;
874 			break;
875 		case IEEE80211_IOC_RTSTHRESHOLD:
876 			ireq->i_val = ic->ic_rtsthreshold;
877 			break;
878 		case IEEE80211_IOC_PROTMODE:
879 			ireq->i_val = ic->ic_protmode;
880 			break;
881 		case IEEE80211_IOC_TXPOWER:
882 			if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
883 				error = EINVAL;
884 			else
885 				ireq->i_val = ic->ic_txpower;
886 			break;
887 		default:
888 			error = EINVAL;
889 			break;
890 		}
891 		break;
892 	case SIOCS80211:
893 		error = suser_cred(cr, NULL_CRED_OKAY);
894 		if (error)
895 			break;
896 		ireq = (struct ieee80211req *) data;
897 		switch (ireq->i_type) {
898 		case IEEE80211_IOC_SSID:
899 			if (ireq->i_val != 0 ||
900 			    ireq->i_len > IEEE80211_NWID_LEN) {
901 				error = EINVAL;
902 				break;
903 			}
904 			error = copyin(ireq->i_data, tmpssid, ireq->i_len);
905 			if (error)
906 				break;
907 			memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
908 			ic->ic_des_esslen = ireq->i_len;
909 			memcpy(ic->ic_des_essid, tmpssid, ireq->i_len);
910 			error = ENETRESET;
911 			break;
912 		case IEEE80211_IOC_WEP:
913 			/*
914 			 * These cards only support one mode so
915 			 * we just turn wep on if what ever is
916 			 * passed in is not OFF.
917 			 */
918 			if (ireq->i_val == IEEE80211_WEP_OFF) {
919 				ic->ic_flags &= ~IEEE80211_F_WEPON;
920 			} else {
921 				ic->ic_flags |= IEEE80211_F_WEPON;
922 			}
923 			error = ENETRESET;
924 			break;
925 		case IEEE80211_IOC_WEPKEY:
926 			if ((ic->ic_caps & IEEE80211_C_WEP) == 0) {
927 				error = EINVAL;
928 				break;
929 			}
930 			kid = (u_int) ireq->i_val;
931 			if (kid >= IEEE80211_WEP_NKID) {
932 				error = EINVAL;
933 				break;
934 			}
935 			if (ireq->i_len > sizeof(tmpkey)) {
936 				error = EINVAL;
937 				break;
938 			}
939 			memset(tmpkey, 0, sizeof(tmpkey));
940 			error = copyin(ireq->i_data, tmpkey, ireq->i_len);
941 			if (error)
942 				break;
943 			memcpy(ic->ic_nw_keys[kid].wk_key, tmpkey,
944 				sizeof(tmpkey));
945 			ic->ic_nw_keys[kid].wk_len = ireq->i_len;
946 			error = ENETRESET;
947 			break;
948 		case IEEE80211_IOC_WEPTXKEY:
949 			kid = (u_int) ireq->i_val;
950 			if (kid >= IEEE80211_WEP_NKID) {
951 				error = EINVAL;
952 				break;
953 			}
954 			ic->ic_wep_txkey = kid;
955 			error = ENETRESET;
956 			break;
957 #if 0
958 		case IEEE80211_IOC_AUTHMODE:
959 			sc->wi_authmode = ireq->i_val;
960 			break;
961 #endif
962 		case IEEE80211_IOC_CHANNEL:
963 			/* XXX 0xffff overflows 16-bit signed */
964 			if (ireq->i_val == 0 ||
965 			    ireq->i_val == (int16_t) IEEE80211_CHAN_ANY)
966 				ic->ic_des_chan = IEEE80211_CHAN_ANYC;
967 			else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX ||
968 			    isclr(ic->ic_chan_active, ireq->i_val)) {
969 				error = EINVAL;
970 				break;
971 			} else
972 				ic->ic_ibss_chan = ic->ic_des_chan =
973 					&ic->ic_channels[ireq->i_val];
974 			switch (ic->ic_state) {
975 			case IEEE80211_S_INIT:
976 			case IEEE80211_S_SCAN:
977 				error = ENETRESET;
978 				break;
979 			default:
980 				if (ic->ic_opmode == IEEE80211_M_STA) {
981 					if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
982 					    ic->ic_bss->ni_chan != ic->ic_des_chan)
983 						error = ENETRESET;
984 				} else {
985 					if (ic->ic_bss->ni_chan != ic->ic_ibss_chan)
986 						error = ENETRESET;
987 				}
988 				break;
989 			}
990 			break;
991 		case IEEE80211_IOC_POWERSAVE:
992 			switch (ireq->i_val) {
993 			case IEEE80211_POWERSAVE_OFF:
994 				if (ic->ic_flags & IEEE80211_F_PMGTON) {
995 					ic->ic_flags &= ~IEEE80211_F_PMGTON;
996 					error = ENETRESET;
997 				}
998 				break;
999 			case IEEE80211_POWERSAVE_ON:
1000 				if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
1001 					error = EINVAL;
1002 				else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
1003 					ic->ic_flags |= IEEE80211_F_PMGTON;
1004 					error = ENETRESET;
1005 				}
1006 				break;
1007 			default:
1008 				error = EINVAL;
1009 				break;
1010 			}
1011 			break;
1012 		case IEEE80211_IOC_POWERSAVESLEEP:
1013 			if (ireq->i_val < 0) {
1014 				error = EINVAL;
1015 				break;
1016 			}
1017 			ic->ic_lintval = ireq->i_val;
1018 			error = ENETRESET;
1019 			break;
1020 		case IEEE80211_IOC_RTSTHRESHOLD:
1021 			if (!(IEEE80211_RTS_MIN < ireq->i_val &&
1022 			      ireq->i_val < IEEE80211_RTS_MAX)) {
1023 				error = EINVAL;
1024 				break;
1025 			}
1026 			ic->ic_rtsthreshold = ireq->i_val;
1027 			error = ENETRESET;
1028 			break;
1029 		case IEEE80211_IOC_PROTMODE:
1030 			if (ireq->i_val > IEEE80211_PROT_RTSCTS) {
1031 				error = EINVAL;
1032 				break;
1033 			}
1034 			ic->ic_protmode = ireq->i_val;
1035 			/* NB: if not operating in 11g this can wait */
1036 			if (ic->ic_curmode == IEEE80211_MODE_11G)
1037 				error = ENETRESET;
1038 			break;
1039 		case IEEE80211_IOC_TXPOWER:
1040 			if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) {
1041 				error = EINVAL;
1042 				break;
1043 			}
1044 			if (!(IEEE80211_TXPOWER_MIN < ireq->i_val &&
1045 			      ireq->i_val < IEEE80211_TXPOWER_MAX)) {
1046 				error = EINVAL;
1047 				break;
1048 			}
1049 			ic->ic_txpower = ireq->i_val;
1050 			error = ENETRESET;
1051 			break;
1052 		default:
1053 			error = EINVAL;
1054 			break;
1055 		}
1056 		break;
1057 	case SIOCGIFGENERIC:
1058 		error = ieee80211_cfgget(ifp, cmd, data, cr);
1059 		break;
1060 	case SIOCSIFGENERIC:
1061 		error = suser_cred(cr, NULL_CRED_OKAY);
1062 		if (error)
1063 			break;
1064 		error = ieee80211_cfgset(ifp, cmd, data);
1065 		break;
1066 	case SIOCG80211STATS:
1067 		ifr = (struct ifreq *)data;
1068 		copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
1069 		break;
1070 	case SIOCSIFMTU:
1071 		ifr = (struct ifreq *)data;
1072 		if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
1073 		    ifr->ifr_mtu <= IEEE80211_MTU_MAX))
1074 			error = EINVAL;
1075 		else
1076 			ifp->if_mtu = ifr->ifr_mtu;
1077 		break;
1078 	case SIOCSIFADDR:
1079 		/*
1080 		 * XXX Handle this directly so we can supress if_init calls.
1081 		 * XXX This should be done in ether_ioctl but for the moment
1082 		 * XXX there are too many other parts of the system that
1083 		 * XXX set IFF_UP and so supress if_init being called when
1084 		 * XXX it should be.
1085 		 */
1086 		ifa = (struct ifaddr *) data;
1087 		switch (ifa->ifa_addr->sa_family) {
1088 #ifdef INET
1089 		case AF_INET:
1090 			if ((ifp->if_flags & IFF_UP) == 0) {
1091 				ifp->if_flags |= IFF_UP;
1092 				ifp->if_init(ifp->if_softc);
1093 			}
1094 			arp_ifinit(ifp, ifa);
1095 			break;
1096 #endif
1097 #ifdef IPX
1098 		/*
1099 		 * XXX - This code is probably wrong,
1100 		 *	 but has been copied many times.
1101 		 */
1102 		case AF_IPX: {
1103 			struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
1104 			struct arpcom *ac = (struct arpcom *)ifp;
1105 
1106 			if (ipx_nullhost(*ina))
1107 				ina->x_host = *(union ipx_host *) ac->ac_enaddr;
1108 			else
1109 				bcopy((caddr_t) ina->x_host.c_host,
1110 				      (caddr_t) ac->ac_enaddr,
1111 				      sizeof(ac->ac_enaddr));
1112 			/* fall thru... */
1113 		}
1114 #endif
1115 		default:
1116 			if ((ifp->if_flags & IFF_UP) == 0) {
1117 				ifp->if_flags |= IFF_UP;
1118 				ifp->if_init(ifp->if_softc);
1119 			}
1120 			break;
1121 		}
1122 		break;
1123 	default:
1124 		error = ether_ioctl(ifp, cmd, data);
1125 		break;
1126 	}
1127 	return error;
1128 }
1129