1 /*	$OpenBSD: if_ieee80211subr.c,v 1.2 2004/01/26 03:35:36 fgsch Exp $	*/
2 /*	$NetBSD: if_ieee80211subr.c,v 1.43 2003/07/06 20:54:25 dyoung Exp $	*/
3 /*	$FreeBSD: src/sys/net/if_ieee80211subr.c,v 1.4 2003/01/21 08:55:59 alfred Exp $	*/
4 
5 /*-
6  * Copyright (c) 2001 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Atsushi Onoe.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *        This product includes software developed by the NetBSD
23  *        Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 /*
42  * IEEE 802.11 generic handler
43  */
44 
45 #include "bpfilter.h"
46 
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/mbuf.h>
50 #include <sys/malloc.h>
51 #include <sys/kernel.h>
52 #include <sys/socket.h>
53 #include <sys/ioctl.h>
54 #include <sys/errno.h>
55 #include <sys/device.h>
56 #include <sys/proc.h>
57 
58 #include <machine/endian.h>
59 
60 #include <dev/rndvar.h>
61 #include <crypto/arc4.h>
62 
63 #include <net/if.h>
64 #include <net/if_dl.h>
65 #include <net/if_media.h>
66 #include <net/if_llc.h>
67 #include <netinet/in.h>
68 #include <netinet/if_ether.h>
69 #include <net/if_ieee80211.h>
70 
71 #include <dev/ic/if_wi_ieee.h>	/* XXX */
72 
73 #if NBPFILTER > 0
74 #include <net/bpf.h>
75 #endif
76 
77 #ifdef IEEE80211_DEBUG
78 int ieee80211_debug = 0;
79 #define	DPRINTF(X)	if (ieee80211_debug) printf X
80 #define	DPRINTF2(X)	if (ieee80211_debug>1) printf X
81 #else
82 #define	DPRINTF(X)
83 #define	DPRINTF2(X)
84 #endif
85 
86 static int ieee80211_send_prreq(struct ieee80211com *,
87     struct ieee80211_node *, int, int);
88 static int ieee80211_send_prresp(struct ieee80211com *,
89     struct ieee80211_node *, int, int);
90 static int ieee80211_send_auth(struct ieee80211com *,
91     struct ieee80211_node *, int, int);
92 static int ieee80211_send_deauth(struct ieee80211com *,
93     struct ieee80211_node *, int, int);
94 static int ieee80211_send_asreq(struct ieee80211com *,
95     struct ieee80211_node *, int, int);
96 static int ieee80211_send_asresp(struct ieee80211com *,
97     struct ieee80211_node *, int, int);
98 static int ieee80211_send_disassoc(struct ieee80211com *,
99     struct ieee80211_node *, int, int);
100 
101 static void ieee80211_recv_beacon(struct ieee80211com *,
102     struct mbuf *, int, u_int32_t);
103 static void ieee80211_recv_prreq(struct ieee80211com *,
104     struct mbuf *, int, u_int32_t);
105 static void ieee80211_recv_auth(struct ieee80211com *,
106     struct mbuf *, int, u_int32_t);
107 static void ieee80211_recv_asreq(struct ieee80211com *,
108     struct mbuf *, int, u_int32_t);
109 static void ieee80211_recv_asresp(struct ieee80211com *,
110     struct mbuf *, int, u_int32_t);
111 static void ieee80211_recv_disassoc(struct ieee80211com *,
112     struct mbuf *, int, u_int32_t);
113 static void ieee80211_recv_deauth(struct ieee80211com *,
114     struct mbuf *, int, u_int32_t);
115 
116 static void ieee80211_recv_pspoll(struct ieee80211com *,
117     struct mbuf *, int, u_int32_t);
118 
119 static void ieee80211_crc_init(void);
120 static u_int32_t ieee80211_crc_update(u_int32_t, u_int8_t *, int);
121 
122 static const char *ieee80211_mgt_subtype_name[] = {
123 	"assoc_req",	"assoc_resp",	"reassoc_req",	"reassoc_resp",
124 	"probe_req",	"probe_resp",	"reserved#6",	"reserved#7",
125 	"beacon",	"atim",		"disassoc",	"auth",
126 	"deauth",	"reserved#13",	"reserved#14",	"reserved#15"
127 };
128 
129 void
ieee80211_ifattach(struct ifnet * ifp)130 ieee80211_ifattach(struct ifnet *ifp)
131 {
132 	struct ieee80211com *ic = (void *)ifp;
133 	int i, rate, mword;
134 	struct ifmediareq imr;
135 
136 	bcopy(ic->ic_myaddr, ((struct arpcom *)ifp)->ac_enaddr,
137 	    ETHER_ADDR_LEN);
138 	ether_ifattach(ifp);
139 #if NBPFILTER > 0
140 	bpfattach(&ic->ic_rawbpf, ifp, DLT_IEEE802_11,
141 	    sizeof(struct ieee80211_frame_addr4));
142 #endif
143 	ieee80211_crc_init();
144 	memcpy(ic->ic_chan_active, ic->ic_chan_avail,
145 	    sizeof(ic->ic_chan_active));
146 	if (isclr(ic->ic_chan_active, ic->ic_ibss_chan)) {
147 		for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
148 			if (isset(ic->ic_chan_active, i)) {
149 				ic->ic_ibss_chan = i;
150 				break;
151 			}
152 		}
153 	}
154 	/* ic->ic_bss.ni_chan must always be a valid channel */
155 	if (isclr(ic->ic_chan_active, ic->ic_bss.ni_chan))
156 		ic->ic_bss.ni_chan = ic->ic_ibss_chan;
157 
158 	ic->ic_des_chan = IEEE80211_CHAN_ANY;
159 	ic->ic_fixed_rate = -1;
160 	if (ic->ic_lintval == 0)
161 		ic->ic_lintval = 100;	/* default sleep */
162 	TAILQ_INIT(&ic->ic_node);
163 	rate = 0;
164 	for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
165 		if (ic->ic_sup_rates[i] != 0)
166 			rate = (ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) / 2;
167 	}
168 	if (rate)
169 		ifp->if_baudrate = IF_Mbps(rate);
170 	ifp->if_hdrlen = sizeof(struct ieee80211_frame);
171 
172 	if (ic->ic_max_aid == 0)
173 		ic->ic_max_aid = IEEE80211_MAX_AID;
174 
175 	/* initialize management frame handlers */
176 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_RESP
177 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_beacon;
178 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_BEACON
179 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_beacon;
180 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_REQ
181 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_prreq;
182 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_AUTH
183 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_auth;
184 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_REQ
185 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asreq;
186 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_REQ
187 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asreq;
188 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_RESP
189 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asresp;
190 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_RESP
191 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_asresp;
192 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_DEAUTH
193 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_deauth;
194 	ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_DISASSOC
195 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_disassoc;
196 
197 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_REQ
198 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_prreq;
199 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_RESP
200 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_prresp;
201 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_AUTH
202 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_auth;
203 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_DEAUTH
204 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_deauth;
205 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_REQ
206 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asreq;
207 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_REQ
208 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asreq;
209 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_ASSOC_RESP
210 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asresp;
211 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_REASSOC_RESP
212 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_asresp;
213 	ic->ic_send_mgmt[IEEE80211_FC0_SUBTYPE_DISASSOC
214 	    >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_send_disassoc;
215 
216 #define	ADD(s, o)	ifmedia_add(&ic->ic_media, \
217 	IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL)
218 
219 	ifmedia_init(&ic->ic_media, 0, ieee80211_media_change,
220 	    ieee80211_media_status);
221 	ADD(IFM_AUTO, 0);			/* infrastructure */
222 	if (ic->ic_flags & IEEE80211_F_HASAHDEMO)
223 		ADD(IFM_AUTO, IFM_IEEE80211_ADHOC | IFM_FLAG0);
224 	if (ic->ic_flags & IEEE80211_F_HASHOSTAP)
225 		ADD(IFM_AUTO, IFM_IEEE80211_HOSTAP);
226 	if (ic->ic_flags & IEEE80211_F_HASIBSS)
227 		ADD(IFM_AUTO, IFM_IEEE80211_ADHOC);
228 	if (ic->ic_flags & IEEE80211_F_HASMONITOR)
229 		ADD(IFM_AUTO, IFM_IEEE80211_MONITOR);
230 
231 	for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
232 		rate = ic->ic_sup_rates[i];
233 		mword = ieee80211_rate2media(rate, ic->ic_phytype);
234 		if (mword == 0)
235 			continue;
236 		ADD(mword, 0);			/* infrastructure */
237 		if (ic->ic_flags & IEEE80211_F_HASAHDEMO)
238 			ADD(mword, IFM_IEEE80211_ADHOC | IFM_FLAG0);
239 		if (ic->ic_flags & IEEE80211_F_HASHOSTAP)
240 			ADD(mword, IFM_IEEE80211_HOSTAP);
241 		if (ic->ic_flags & IEEE80211_F_HASIBSS)
242 			ADD(mword, IFM_IEEE80211_ADHOC);
243 		if (ic->ic_flags & IEEE80211_F_HASMONITOR)
244 			ADD(mword, IFM_IEEE80211_MONITOR);
245 	}
246 	(*ic->ic_media.ifm_status)(ifp, &imr);
247 	ifmedia_set(&ic->ic_media, imr.ifm_active);
248 #undef	ADD
249 }
250 
251 void
ieee80211_ifdetach(struct ifnet * ifp)252 ieee80211_ifdetach(struct ifnet *ifp)
253 {
254 	struct ieee80211com *ic = (void *)ifp;
255 	int s;
256 
257 	s = splnet();
258 	IF_PURGE(&ic->ic_mgtq);
259 	IF_PURGE(&ic->ic_pwrsaveq);
260 	if (ic->ic_wep_ctx != NULL) {
261 		free(ic->ic_wep_ctx, M_DEVBUF);
262 		ic->ic_wep_ctx = NULL;
263 	}
264 	ieee80211_free_allnodes(ic);
265 	ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY);
266 #if NBPFILTER > 0
267 	bpfdetach(ifp);
268 #endif
269 	ether_ifdetach(ifp);
270 	splx(s);
271 }
272 
273 void
ieee80211_input(struct ifnet * ifp,struct mbuf * m,int rssi,u_int32_t rstamp)274 ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp)
275 {
276 	struct ieee80211com *ic = (void *)ifp;
277 	struct ieee80211_node *ni;
278 	struct ieee80211_frame *wh;
279 	struct ether_header *eh;
280 	void (*rh)(struct ieee80211com *, struct mbuf *, int, u_int);
281 	struct mbuf *m1;
282 	int error, len;
283 	u_int8_t dir, subtype;
284 	u_int8_t *bssid;
285 	u_int16_t rxseq;
286 
287 	wh = mtod(m, struct ieee80211_frame *);
288 	if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
289 	    IEEE80211_FC0_VERSION_0) {
290 		if (ifp->if_flags & IFF_DEBUG)
291 			printf("%s: receive packet with wrong version: %x\n",
292 			    ifp->if_xname, wh->i_fc[0]);
293 		goto err;
294 	}
295 
296 	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
297 
298 	if (ic->ic_state != IEEE80211_S_SCAN) {
299 		switch (ic->ic_opmode) {
300 		case IEEE80211_M_STA:
301 			ni = &ic->ic_bss;
302 			if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
303 				DPRINTF2(("ieee80211_input: other bss %s\n",
304 				    ether_sprintf(wh->i_addr2)));
305 				/* not interested in */
306 				goto out;
307 			}
308 			break;
309 		case IEEE80211_M_IBSS:
310 		case IEEE80211_M_AHDEMO:
311 		case IEEE80211_M_HOSTAP:
312 			if (dir == IEEE80211_FC1_DIR_NODS)
313 				bssid = wh->i_addr3;
314 			else
315 				bssid = wh->i_addr1;
316 			if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss.ni_bssid) &&
317 			    !IEEE80211_ADDR_EQ(bssid, etherbroadcastaddr) &&
318 			    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
319 			    IEEE80211_FC0_TYPE_CTL) {
320 				/* not interested in */
321 				DPRINTF2(("ieee80211_input: other bss %s\n",
322 				    ether_sprintf(wh->i_addr3)));
323 				goto out;
324 			}
325 			ni = ieee80211_find_node(ic, wh->i_addr2);
326 			if (ni == NULL) {
327 				DPRINTF2(("ieee80211_input: unknown src %s\n",
328 				    ether_sprintf(wh->i_addr2)));
329 				ni = &ic->ic_bss;	/* XXX allocate? */
330 			}
331 			break;
332 		case IEEE80211_M_MONITOR:
333 			goto out;
334 		}
335 		ni->ni_rssi = rssi;
336 		ni->ni_rstamp = rstamp;
337 		rxseq = ni->ni_rxseq;
338 		ni->ni_rxseq =
339 		    letoh16(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
340 		/* TODO: fragment */
341 		if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
342 		    rxseq == ni->ni_rxseq) {
343 			/* duplicate, silently discarded */
344 			goto out;
345 		}
346 		ni->ni_inact = 0;
347 	}
348 
349 	if (ic->ic_set_tim != NULL &&
350 	    (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT)
351 	    && ni->ni_pwrsave == 0) {
352 		/* turn on power save mode */
353 
354 		if (ifp->if_flags & IFF_DEBUG)
355 			printf("%s: power save mode on for %s\n",
356 			    ifp->if_xname, ether_sprintf(wh->i_addr2));
357 
358 		ni->ni_pwrsave = IEEE80211_PS_SLEEP;
359 	}
360 	if (ic->ic_set_tim != NULL &&
361 	    (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) == 0  &&
362 	    ni->ni_pwrsave != 0) {
363 		/* turn off power save mode, dequeue stored packets */
364 
365 		ni->ni_pwrsave = 0;
366 		if (ic->ic_set_tim)
367 			ic->ic_set_tim(ic, ni->ni_associd, 0);
368 
369 		if (ifp->if_flags & IFF_DEBUG)
370 			printf("%s: power save mode off for %s\n",
371 			    ifp->if_xname, ether_sprintf(wh->i_addr2));
372 
373 		while (!IF_IS_EMPTY(&ni->ni_savedq)) {
374 			struct mbuf *m;
375 			IF_DEQUEUE(&ni->ni_savedq, m);
376 			IF_ENQUEUE(&ic->ic_pwrsaveq, m);
377 			(*ifp->if_start)(ifp);
378 		}
379 	}
380 
381 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
382 	case IEEE80211_FC0_TYPE_DATA:
383 		switch (ic->ic_opmode) {
384 		case IEEE80211_M_STA:
385 			if (dir != IEEE80211_FC1_DIR_FROMDS)
386 				goto out;
387 			if ((ifp->if_flags & IFF_SIMPLEX) &&
388 			    IEEE80211_IS_MULTICAST(wh->i_addr1) &&
389 			    IEEE80211_ADDR_EQ(wh->i_addr3,
390 			    ic->ic_myaddr)) {
391 				/*
392 				 * In IEEE802.11 network, multicast packet
393 				 * sent from me is broadcasted from AP.
394 				 * It should be silently discarded for
395 				 * SIMPLEX interface.
396 				 */
397 				goto out;
398 			}
399 			break;
400 		case IEEE80211_M_IBSS:
401 		case IEEE80211_M_AHDEMO:
402 			if (dir != IEEE80211_FC1_DIR_NODS)
403 				goto out;
404 			break;
405 		case IEEE80211_M_HOSTAP:
406 			if (dir != IEEE80211_FC1_DIR_TODS)
407 				goto out;
408 			/* check if source STA is associated */
409 			ni = ieee80211_find_node(ic, wh->i_addr2);
410 			if (ni == NULL) {
411 				DPRINTF(("ieee80211_input: "
412 				    "data from unknown src %s\n",
413 				    ether_sprintf(wh->i_addr2)));
414 				if ((ni = ieee80211_alloc_node(ic, wh->i_addr2,
415 				    1)) != NULL) {
416 					IEEE80211_SEND_MGMT(ic, ni,
417 					    IEEE80211_FC0_SUBTYPE_DEAUTH,
418 					    IEEE80211_REASON_NOT_AUTHED);
419 					ieee80211_free_node(ic, ni);
420 				}
421 				goto err;
422 			}
423 			if (ni->ni_associd == 0) {
424 				DPRINTF(("ieee80211_input: "
425 				    "data from unassoc src %s\n",
426 				    ether_sprintf(wh->i_addr2)));
427 				IEEE80211_SEND_MGMT(ic, ni,
428 				    IEEE80211_FC0_SUBTYPE_DISASSOC,
429 				    IEEE80211_REASON_NOT_ASSOCED);
430 				goto err;
431 			}
432 			break;
433 		case IEEE80211_M_MONITOR:
434 			/* Should never get here */
435 			break;
436 		}
437 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
438 			if (ic->ic_flags & IEEE80211_F_WEPON) {
439 				m = ieee80211_wep_crypt(ifp, m, 0);
440 				if (m == NULL)
441 					goto err;
442 				wh = mtod(m, struct ieee80211_frame *);
443 			} else
444 				goto out;
445 		}
446 		/* copy to listener after decrypt */
447 #if NBPFILTER > 0
448 		if (ic->ic_rawbpf)
449 			bpf_mtap(ic->ic_rawbpf, m);
450 #endif
451 		m = ieee80211_decap(ifp, m);
452 		if (m == NULL)
453 			goto err;
454 		ifp->if_ipackets++;
455 
456 		/* perform as a bridge within the AP */
457 		m1 = NULL;
458 		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
459 			eh = mtod(m, struct ether_header *);
460 			if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
461 				m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
462 				if (m1 == NULL)
463 					ifp->if_oerrors++;
464 				else
465 					m1->m_flags |= M_MCAST;
466 			} else {
467 				ni = ieee80211_find_node(ic, eh->ether_dhost);
468 				if (ni != NULL && ni->ni_associd != 0) {
469 					m1 = m;
470 					m = NULL;
471 				}
472 			}
473 			if (m1 != NULL) {
474 				len = m1->m_pkthdr.len;
475 				IFQ_ENQUEUE(&ifp->if_snd, m1, NULL, error);
476 				if (error)
477 					ifp->if_oerrors++;
478 				else {
479 					if (m != NULL)
480 						ifp->if_omcasts++;
481 					ifp->if_obytes += len;
482 				}
483 			}
484 		}
485 		if (m != NULL) {
486 #if NBPFILTER > 0
487 			/*
488 			 * If we forward packet into transmitter of the AP,
489 			 * we don't need to duplicate for DLT_EN10MB.
490 			 */
491 			if (ifp->if_bpf && m1 == NULL)
492 				bpf_mtap(ifp->if_bpf, m);
493 #endif
494 			ether_input_mbuf(ifp, m);
495 		}
496 		return;
497 
498 	case IEEE80211_FC0_TYPE_MGT:
499 		if (dir != IEEE80211_FC1_DIR_NODS)
500 			goto err;
501 		if (ic->ic_opmode == IEEE80211_M_AHDEMO)
502 			goto out;
503 		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
504 
505 		/* drop frames without interest */
506 		if (ic->ic_state == IEEE80211_S_SCAN) {
507 			if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
508 			    subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
509 				goto out;
510 		} else {
511 			if (ic->ic_opmode != IEEE80211_M_IBSS &&
512 			    subtype == IEEE80211_FC0_SUBTYPE_BEACON)
513 				goto out;
514 		}
515 
516 		if (ifp->if_flags & IFF_DEBUG) {
517 			/* avoid to print too many frames */
518 			int doprint = 0;
519 
520 			switch (subtype) {
521 			case IEEE80211_FC0_SUBTYPE_BEACON:
522 				if (ic->ic_state == IEEE80211_S_SCAN)
523 					doprint = 1;
524 				break;
525 			case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
526 				if (ic->ic_opmode == IEEE80211_M_IBSS)
527 					doprint = 1;
528 				break;
529 			default:
530 				doprint = 1;
531 				break;
532 			}
533 #ifdef IEEE80211_DEBUG
534 			doprint += ieee80211_debug;
535 #endif
536 			if (doprint)
537 				printf("%s: received %s from %s rssi %d\n",
538 				    ifp->if_xname,
539 				    ieee80211_mgt_subtype_name[subtype
540 				    >> IEEE80211_FC0_SUBTYPE_SHIFT],
541 				    ether_sprintf(wh->i_addr2), rssi);
542 		}
543 #if NBPFILTER > 0
544 		if (ic->ic_rawbpf)
545 			bpf_mtap(ic->ic_rawbpf, m);
546 #endif
547 		rh = ic->ic_recv_mgmt[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT];
548 		if (rh != NULL)
549 			(*rh)(ic, m, rssi, rstamp);
550 		m_freem(m);
551 		return;
552 
553 	case IEEE80211_FC0_TYPE_CTL:
554 		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
555 			goto out;
556 		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
557 		if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL) {
558 			/* Dump out a single packet from the host */
559 			if (ifp->if_flags & IFF_DEBUG)
560 				printf("%s: got power save probe from %s\n",
561 				       ifp->if_xname,
562 				       ether_sprintf(wh->i_addr2));
563 			ieee80211_recv_pspoll(ic, m, rssi, rstamp);
564 		}
565 		goto out;
566 
567 	default:
568 		DPRINTF(("ieee80211_input: bad type %x\n", wh->i_fc[0]));
569 		/* should not come here */
570 		break;
571 	}
572   err:
573 	ifp->if_ierrors++;
574   out:
575 	if (m != NULL) {
576 #if NBPFILTER > 0
577 		if (ic->ic_rawbpf)
578 			bpf_mtap(ic->ic_rawbpf, m);
579 #endif
580 		m_freem(m);
581 	}
582 }
583 
584 int
ieee80211_mgmt_output(struct ifnet * ifp,struct ieee80211_node * ni,struct mbuf * m,int type)585 ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
586     struct mbuf *m, int type)
587 {
588 	struct ieee80211com *ic = (void *)ifp;
589 	struct ieee80211_frame *wh;
590 
591 	if (ni == NULL)
592 		ni = &ic->ic_bss;
593 	ni->ni_inact = 0;
594 	M_PREPEND(m, IEEE80211_HEADER_LEN(ic), M_DONTWAIT);
595 	if (m == NULL)
596 		return (ENOMEM);
597 	wh = mtod(m, struct ieee80211_frame *);
598 	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
599 	wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
600 	*(u_int16_t *)wh->i_dur = 0;
601 	*(u_int16_t *)wh->i_seq =
602 	    htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
603 	ni->ni_txseq++;
604 	IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
605 	IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
606 	IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
607 
608 	if (ifp->if_flags & IFF_DEBUG) {
609 		/* avoid to print too many frames */
610 		if (ic->ic_opmode == IEEE80211_M_IBSS ||
611 #ifdef IEEE80211_DEBUG
612 		    ieee80211_debug > 1 ||
613 #endif
614 		    (type & IEEE80211_FC0_SUBTYPE_MASK) !=
615 		    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
616 			printf("%s: sending %s to %s on channel %u\n",
617 			    ifp->if_xname,
618 			    ieee80211_mgt_subtype_name[
619 			    (type & IEEE80211_FC0_SUBTYPE_MASK)
620 			    >> IEEE80211_FC0_SUBTYPE_SHIFT],
621 			    ether_sprintf(ni->ni_macaddr),
622 			    ni->ni_chan);
623 	}
624 	IF_ENQUEUE(&ic->ic_mgtq, m);
625 	ifp->if_timer = 1;
626 	(*ifp->if_start)(ifp);
627 	return (0);
628 }
629 
630 struct mbuf *
ieee80211_encap(struct ifnet * ifp,struct mbuf * m)631 ieee80211_encap(struct ifnet *ifp, struct mbuf *m)
632 {
633 	struct ieee80211com *ic = (void *)ifp;
634 	struct ether_header eh;
635 	struct ieee80211_frame *wh;
636 	struct llc *llc;
637 	struct ieee80211_node *ni;
638 
639 	if (m->m_len < sizeof(struct ether_header)) {
640 		m = m_pullup(m, sizeof(struct ether_header));
641 		if (m == NULL)
642 			return (NULL);
643 	}
644 	memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
645 
646 	if (!IEEE80211_IS_MULTICAST(eh.ether_dhost) &&
647 	    (ic->ic_opmode == IEEE80211_M_IBSS ||
648 	     ic->ic_opmode == IEEE80211_M_HOSTAP)) {
649 		ni = ieee80211_find_node(ic, eh.ether_dhost);
650 		if (ni == NULL)
651 			ni = &ic->ic_bss;	/*XXX*/
652 	} else
653 		ni = &ic->ic_bss;
654 	ni->ni_inact = 0;
655 
656 	m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
657 	llc = mtod(m, struct llc *);
658 	llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
659 	llc->llc_control = LLC_UI;
660 	llc->llc_snap.org_code[0] = 0;
661 	llc->llc_snap.org_code[1] = 0;
662 	llc->llc_snap.org_code[2] = 0;
663 	llc->llc_snap.ether_type = eh.ether_type;
664 	M_PREPEND(m, IEEE80211_HEADER_LEN(ic), M_DONTWAIT);
665 	if (m == NULL)
666 		return (NULL);
667 	wh = mtod(m, struct ieee80211_frame *);
668 	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
669 	*(u_int16_t *)wh->i_dur = 0;
670 	*(u_int16_t *)wh->i_seq =
671 	    htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
672 	ni->ni_txseq++;
673 	switch (ic->ic_opmode) {
674 	case IEEE80211_M_STA:
675 		wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
676 		IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
677 		IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
678 		IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
679 		break;
680 	case IEEE80211_M_IBSS:
681 	case IEEE80211_M_AHDEMO:
682 		wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
683 		IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
684 		IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
685 		IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
686 		break;
687 	case IEEE80211_M_HOSTAP:
688 		wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
689 		IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
690 		IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
691 		IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
692 		break;
693 	case IEEE80211_M_MONITOR:
694 		/* Should never get here! */
695 		m_freem(m);
696 		return (NULL);
697 	}
698 	return (m);
699 }
700 
701 struct mbuf *
ieee80211_decap(struct ifnet * ifp,struct mbuf * m)702 ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
703 {
704 	struct ether_header *eh;
705 	struct ieee80211_frame wh;
706 	struct llc *llc;
707 
708 	if (m->m_len < sizeof(wh) + sizeof(*llc)) {
709 		m = m_pullup(m, sizeof(wh) + sizeof(*llc));
710 		if (m == NULL)
711 			return (NULL);
712 	}
713 	memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
714 	llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
715 	if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
716 	    llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
717 	    llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
718 		m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh));
719 		llc = NULL;
720 	} else {
721 		m_adj(m, sizeof(wh) - sizeof(*eh));
722 	}
723 	eh = mtod(m, struct ether_header *);
724 	switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
725 	case IEEE80211_FC1_DIR_NODS:
726 		IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
727 		IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
728 		break;
729 	case IEEE80211_FC1_DIR_TODS:
730 		IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
731 		IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
732 		break;
733 	case IEEE80211_FC1_DIR_FROMDS:
734 		IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
735 		IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
736 		break;
737 	case IEEE80211_FC1_DIR_DSTODS:
738 		/* not yet supported */
739 		DPRINTF(("ieee80211_decap: DS to DS\n"));
740 		m_freem(m);
741 		return (NULL);
742 	}
743 	if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
744 		struct mbuf *n, *n0, **np;
745 		caddr_t newdata;
746 		int off, pktlen;
747 
748 		n0 = NULL;
749 		np = &n0;
750 		off = 0;
751 		pktlen = m->m_pkthdr.len;
752 		while (pktlen > off) {
753 			if (n0 == NULL) {
754 				MGETHDR(n, M_DONTWAIT, MT_DATA);
755 				if (n == NULL) {
756 					m_freem(m);
757 					return (NULL);
758 				}
759 				M_MOVE_PKTHDR(n, m);
760 				n->m_len = MHLEN;
761 			} else {
762 				MGET(n, M_DONTWAIT, MT_DATA);
763 				if (n == NULL) {
764 					m_freem(m);
765 					m_freem(n0);
766 					return (NULL);
767 				}
768 				n->m_len = MLEN;
769 			}
770 			if (pktlen - off >= MINCLSIZE) {
771 				MCLGET(n, M_DONTWAIT);
772 				if (n->m_flags & M_EXT)
773 					n->m_len = n->m_ext.ext_size;
774 			}
775 			if (n0 == NULL) {
776 				newdata =
777 				    (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
778 				    sizeof(*eh);
779 				n->m_len -= newdata - n->m_data;
780 				n->m_data = newdata;
781 			}
782 			if (n->m_len > pktlen - off)
783 				n->m_len = pktlen - off;
784 			m_copydata(m, off, n->m_len, mtod(n, caddr_t));
785 			off += n->m_len;
786 			*np = n;
787 			np = &n->m_next;
788 		}
789 		m_freem(m);
790 		m = n0;
791 	}
792 	if (llc != NULL) {
793 		eh = mtod(m, struct ether_header *);
794 		eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
795 	}
796 	return (m);
797 }
798 
799 int
ieee80211_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)800 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
801 {
802 	struct ieee80211com *ic = (void *)ifp;
803 	struct ifreq *ifr = (struct ifreq *)data;
804 	int i, error = 0;
805 	struct ieee80211_nwid nwid;
806 	struct ieee80211_nwkey *nwkey;
807 	struct ieee80211_power *power;
808 	struct ieee80211_bssid *bssid;
809 	struct ieee80211_channel *chan;
810 	struct ieee80211_wepkey keys[IEEE80211_WEP_NKID];
811 	static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
812 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
813 	};
814 
815 	switch (cmd) {
816 	case SIOCSIFMEDIA:
817 	case SIOCGIFMEDIA:
818 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
819 		break;
820 	case SIOCS80211NWID:
821 		if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
822 			break;
823 		if (nwid.i_len > IEEE80211_NWID_LEN) {
824 			error = EINVAL;
825 			break;
826 		}
827 		memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
828 		ic->ic_des_esslen = nwid.i_len;
829 		memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
830 		error = ENETRESET;
831 		break;
832 	case SIOCG80211NWID:
833 		memset(&nwid, 0, sizeof(nwid));
834 		switch (ic->ic_state) {
835 		case IEEE80211_S_INIT:
836 		case IEEE80211_S_SCAN:
837 			nwid.i_len = ic->ic_des_esslen;
838 			memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);
839 			break;
840 		default:
841 			nwid.i_len = ic->ic_bss.ni_esslen;
842 			memcpy(nwid.i_nwid, ic->ic_bss.ni_essid, nwid.i_len);
843 			break;
844 		}
845 		error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
846 		break;
847 	case SIOCS80211NWKEY:
848 		nwkey = (struct ieee80211_nwkey *)data;
849 		if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0 &&
850 		    nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
851 			error = EINVAL;
852 			break;
853 		}
854 		/* check and copy keys */
855 		memset(keys, 0, sizeof(keys));
856 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
857 			keys[i].wk_len = nwkey->i_key[i].i_keylen;
858 			if ((keys[i].wk_len > 0 &&
859 			    keys[i].wk_len < IEEE80211_WEP_KEYLEN) ||
860 			    keys[i].wk_len > sizeof(keys[i].wk_key)) {
861 				error = EINVAL;
862 				break;
863 			}
864 			if (keys[i].wk_len <= 0)
865 				continue;
866 			if ((error = copyin(nwkey->i_key[i].i_keydat,
867 			    keys[i].wk_key, keys[i].wk_len)) != 0)
868 				break;
869 		}
870 		if (error)
871 			break;
872 		i = nwkey->i_defkid - 1;
873 		if (i < 0 || i >= IEEE80211_WEP_NKID ||
874 		    keys[i].wk_len == 0 ||
875 		    (keys[i].wk_len == -1 && ic->ic_nw_keys[i].wk_len == 0)) {
876 			if (nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
877 				error = EINVAL;
878 				break;
879 			}
880 		} else
881 			ic->ic_wep_txkey = i;
882 		/* save the key */
883 		if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN)
884 			ic->ic_flags &= ~IEEE80211_F_WEPON;
885 		else
886 			ic->ic_flags |= IEEE80211_F_WEPON;
887 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
888 			if (keys[i].wk_len < 0)
889 				continue;
890 			ic->ic_nw_keys[i].wk_len = keys[i].wk_len;
891 			memcpy(ic->ic_nw_keys[i].wk_key, keys[i].wk_key,
892 			    sizeof(keys[i].wk_key));
893 		}
894 		error = ENETRESET;
895 		break;
896 	case SIOCG80211NWKEY:
897 		nwkey = (struct ieee80211_nwkey *)data;
898 		if (ic->ic_flags & IEEE80211_F_WEPON)
899 			nwkey->i_wepon = IEEE80211_NWKEY_WEP;
900 		else
901 			nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
902 		nwkey->i_defkid = ic->ic_wep_txkey + 1;
903 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
904 			if (nwkey->i_key[i].i_keydat == NULL)
905 				continue;
906 			/* do not show any keys to non-root user */
907 			if ((error = suser(curproc, 0)) != 0)
908 				break;
909 			nwkey->i_key[i].i_keylen = ic->ic_nw_keys[i].wk_len;
910 			if ((error = copyout(ic->ic_nw_keys[i].wk_key,
911 			    nwkey->i_key[i].i_keydat,
912 			    ic->ic_nw_keys[i].wk_len)) != 0)
913 				break;
914 		}
915 		break;
916 	case SIOCS80211POWER:
917 		power = (struct ieee80211_power *)data;
918 		ic->ic_lintval = power->i_maxsleep;
919 		if (power->i_enabled != 0) {
920 			if ((ic->ic_flags & IEEE80211_F_HASPMGT) == 0)
921 				error = EINVAL;
922 			else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
923 				ic->ic_flags |= IEEE80211_F_PMGTON;
924 				error = ENETRESET;
925 			}
926 		} else {
927 			if (ic->ic_flags & IEEE80211_F_PMGTON) {
928 				ic->ic_flags &= ~IEEE80211_F_PMGTON;
929 				error = ENETRESET;
930 			}
931 		}
932 		break;
933 	case SIOCG80211POWER:
934 		power = (struct ieee80211_power *)data;
935 		power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
936 		power->i_maxsleep = ic->ic_lintval;
937 		break;
938 	case SIOCS80211BSSID:
939 		bssid = (struct ieee80211_bssid *)data;
940 		if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))
941 			ic->ic_flags &= ~IEEE80211_F_DESBSSID;
942 		else {
943 			ic->ic_flags |= IEEE80211_F_DESBSSID;
944 			IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);
945 		}
946 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
947 			break;
948 		switch (ic->ic_state) {
949 		case IEEE80211_S_INIT:
950 		case IEEE80211_S_SCAN:
951 			error = ENETRESET;
952 			break;
953 		default:
954 			if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
955 			    !IEEE80211_ADDR_EQ(ic->ic_des_bssid,
956 			    ic->ic_bss.ni_bssid))
957 				error = ENETRESET;
958 			break;
959 		}
960 		break;
961 	case SIOCG80211BSSID:
962 		bssid = (struct ieee80211_bssid *)data;
963 		switch (ic->ic_state) {
964 		case IEEE80211_S_INIT:
965 		case IEEE80211_S_SCAN:
966 			if (ic->ic_opmode == IEEE80211_M_HOSTAP)
967 				IEEE80211_ADDR_COPY(bssid->i_bssid,
968 				    ic->ic_myaddr);
969 			else if (ic->ic_flags & IEEE80211_F_DESBSSID)
970 				IEEE80211_ADDR_COPY(bssid->i_bssid,
971 				    ic->ic_des_bssid);
972 			else
973 				memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
974 			break;
975 		default:
976 			IEEE80211_ADDR_COPY(bssid->i_bssid,
977 			    ic->ic_bss.ni_bssid);
978 			break;
979 		}
980 		break;
981 	case SIOCS80211CHANNEL:
982 		chan = (struct ieee80211_channel *)data;
983 		if (chan->i_channel == IEEE80211_CHAN_ANY)
984 			ic->ic_des_chan = IEEE80211_CHAN_ANY;
985 		else if (chan->i_channel > IEEE80211_CHAN_MAX ||
986 		    isclr(ic->ic_chan_active, chan->i_channel)) {
987 			error = EINVAL;
988 			break;
989 		} else
990 			ic->ic_ibss_chan = ic->ic_des_chan = chan->i_channel;
991 		switch (ic->ic_state) {
992 		case IEEE80211_S_INIT:
993 		case IEEE80211_S_SCAN:
994 			error = ENETRESET;
995 			break;
996 		default:
997 			if (ic->ic_opmode == IEEE80211_M_STA) {
998 				if (ic->ic_des_chan != IEEE80211_CHAN_ANY &&
999 				    ic->ic_bss.ni_chan != ic->ic_des_chan)
1000 					error = ENETRESET;
1001 			} else {
1002 				if (ic->ic_bss.ni_chan != ic->ic_ibss_chan)
1003 					error = ENETRESET;
1004 			}
1005 			break;
1006 		}
1007 		break;
1008 	case SIOCG80211CHANNEL:
1009 		chan = (struct ieee80211_channel *)data;
1010 		chan->i_channel = ieee80211_get_channel(ic);
1011 		break;
1012 	case SIOCGWAVELAN:
1013 		error = ieee80211_cfgget(ifp, cmd, data);
1014 		break;
1015 	case SIOCSWAVELAN:
1016 		error = suser(curproc, 0);
1017 		if (error)
1018 			break;
1019 		error = ieee80211_cfgset(ifp, cmd, data);
1020 		break;
1021 	default:
1022 		error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
1023 		break;
1024 	}
1025 	return (error);
1026 }
1027 
1028 void
ieee80211_print_essid(u_int8_t * essid,int len)1029 ieee80211_print_essid(u_int8_t *essid, int len)
1030 {
1031 	int i;
1032 	u_int8_t *p;
1033 
1034 	if (len > IEEE80211_NWID_LEN)
1035 		len = IEEE80211_NWID_LEN;
1036 	/* determine printable or not */
1037 	for (i = 0, p = essid; i < len; i++, p++) {
1038 		if (*p < ' ' || *p > 0x7e)
1039 			break;
1040 	}
1041 	if (i == len) {
1042 		printf("\"");
1043 		for (i = 0, p = essid; i < len; i++, p++)
1044 			printf("%c", *p);
1045 		printf("\"");
1046 	} else {
1047 		printf("0x");
1048 		for (i = 0, p = essid; i < len; i++, p++)
1049 			printf("%02x", *p);
1050 	}
1051 }
1052 
1053 void
ieee80211_dump_pkt(u_int8_t * buf,int len,int rate,int rssi)1054 ieee80211_dump_pkt(u_int8_t *buf, int len, int rate, int rssi)
1055 {
1056 	struct ieee80211_frame *wh;
1057 	int i;
1058 
1059 	wh = (struct ieee80211_frame *)buf;
1060 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
1061 	case IEEE80211_FC1_DIR_NODS:
1062 		printf("NODS %s", ether_sprintf(wh->i_addr2));
1063 		printf("->%s", ether_sprintf(wh->i_addr1));
1064 		printf("(%s)", ether_sprintf(wh->i_addr3));
1065 		break;
1066 	case IEEE80211_FC1_DIR_TODS:
1067 		printf("TODS %s", ether_sprintf(wh->i_addr2));
1068 		printf("->%s", ether_sprintf(wh->i_addr3));
1069 		printf("(%s)", ether_sprintf(wh->i_addr1));
1070 		break;
1071 	case IEEE80211_FC1_DIR_FROMDS:
1072 		printf("FRDS %s", ether_sprintf(wh->i_addr3));
1073 		printf("->%s", ether_sprintf(wh->i_addr1));
1074 		printf("(%s)", ether_sprintf(wh->i_addr2));
1075 		break;
1076 	case IEEE80211_FC1_DIR_DSTODS:
1077 		printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
1078 		printf("->%s", ether_sprintf(wh->i_addr3));
1079 		printf("(%s", ether_sprintf(wh->i_addr2));
1080 		printf("->%s)", ether_sprintf(wh->i_addr1));
1081 		break;
1082 	}
1083 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1084 	case IEEE80211_FC0_TYPE_DATA:
1085 		printf(" data");
1086 		break;
1087 	case IEEE80211_FC0_TYPE_MGT:
1088 		printf(" %s", ieee80211_mgt_subtype_name[
1089 		    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
1090 		    >> IEEE80211_FC0_SUBTYPE_SHIFT]);
1091 		break;
1092 	default:
1093 		printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
1094 		break;
1095 	}
1096 	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
1097 		printf(" WEP");
1098 	if (rate >= 0)
1099 		printf(" %dM", rate / 2);
1100 	if (rssi >= 0)
1101 		printf(" +%d", rssi);
1102 	printf("\n");
1103 	if (len > 0) {
1104 		for (i = 0; i < len; i++) {
1105 			if ((i & 1) == 0)
1106 				printf(" ");
1107 			printf("%02x", buf[i]);
1108 		}
1109 		printf("\n");
1110 	}
1111 }
1112 
1113 void
ieee80211_watchdog(struct ifnet * ifp)1114 ieee80211_watchdog(struct ifnet *ifp)
1115 {
1116 	struct ieee80211com *ic = (void *)ifp;
1117 	if (ic->ic_mgt_timer) {
1118 		if (--ic->ic_mgt_timer == 0)
1119 			ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
1120 	}
1121 	if (ic->ic_inact_timer) {
1122 		if (--ic->ic_inact_timer == 0) {
1123 			struct ieee80211_node *ni, *nextbs;
1124 			for (ni = TAILQ_FIRST(&ic->ic_node); ni != NULL; ) {
1125 				if (++ni->ni_inact <= IEEE80211_INACT_MAX) {
1126 					ni = TAILQ_NEXT(ni, ni_list);
1127 					continue;
1128 				}
1129 				if (ifp->if_flags & IFF_DEBUG)
1130 					printf("%s: station %s deauthenticate"
1131 					    " (reason %d)\n",
1132 					    ifp->if_xname,
1133 					    ether_sprintf(ni->ni_macaddr),
1134 					    IEEE80211_REASON_AUTH_EXPIRE);
1135 				nextbs = TAILQ_NEXT(ni, ni_list);
1136 				IEEE80211_SEND_MGMT(ic, ni,
1137 				    IEEE80211_FC0_SUBTYPE_DEAUTH,
1138 				    IEEE80211_REASON_AUTH_EXPIRE);
1139 				ieee80211_free_node(ic, ni);
1140 				ni = nextbs;
1141 			}
1142 			if (!TAILQ_EMPTY(&ic->ic_node))
1143 				ic->ic_inact_timer = IEEE80211_INACT_WAIT;
1144 		}
1145 	}
1146 	if (ic->ic_mgt_timer != 0 || ic->ic_inact_timer != 0)
1147 		ifp->if_timer = 1;
1148 }
1149 
1150 static void
ieee80211_begin_scan(struct ifnet * ifp,struct ieee80211_node * ni)1151 ieee80211_begin_scan(struct ifnet *ifp, struct ieee80211_node *ni)
1152 {
1153 	struct ieee80211com *ic = (void *)ifp;
1154 	int i;
1155 
1156 	memcpy(ic->ic_chan_scan, ic->ic_chan_active,
1157 	    sizeof(ic->ic_chan_scan));
1158 
1159 	DPRINTF(("ieee80211_begin_scan: scanning"));
1160 	for (i = 0; i < sizeof(ic->ic_chan_scan) * NBBY; i++) {
1161 	        if (!isset(ic->ic_chan_scan, i))
1162 	                continue;
1163 	        DPRINTF((" %d", i));
1164 		ni->ni_chan = i;
1165 	}
1166 	DPRINTF(("\n"));
1167 	clrbit(ic->ic_chan_scan, ni->ni_chan);
1168 	ic->ic_flags |= IEEE80211_F_ASCAN;
1169 	IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
1170 }
1171 
1172 void
ieee80211_next_scan(struct ifnet * ifp)1173 ieee80211_next_scan(struct ifnet *ifp)
1174 {
1175 	struct ieee80211com *ic = (void *)ifp;
1176 	int chan, s;
1177 
1178 	s = splnet();
1179 
1180 	chan = ic->ic_bss.ni_chan;
1181 	for (;;) {
1182 		chan = (chan + 1) % (IEEE80211_CHAN_MAX + 1);
1183 		if (isset(ic->ic_chan_scan, chan))
1184 			break;
1185 		if (chan == ic->ic_bss.ni_chan) {
1186 			DPRINTF(("ieee80211_next_scan: no chan available\n"));
1187 			ieee80211_end_scan(ifp);
1188 			splx(s);
1189 			return;
1190 		}
1191 	}
1192 	clrbit(ic->ic_chan_scan, chan);
1193 	DPRINTF(("ieee80211_next_scan: chan %d->%d\n",
1194 	    ic->ic_bss.ni_chan, chan));
1195 	ic->ic_bss.ni_chan = chan;
1196 	ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
1197 	splx(s);
1198 }
1199 
1200 void
ieee80211_create_ibss(struct ieee80211com * ic)1201 ieee80211_create_ibss(struct ieee80211com *ic)
1202 {
1203 	struct ifnet *ifp = &ic->ic_if;
1204 	struct ieee80211_node *ni;
1205 	int i;
1206 
1207 	ni = &ic->ic_bss;
1208 	if (ifp->if_flags & IFF_DEBUG)
1209 		printf("%s: creating ibss\n", ifp->if_xname);
1210 	ic->ic_flags |= IEEE80211_F_SIBSS;
1211 	ni->ni_nrate = 0;
1212 	for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
1213 		if (ic->ic_sup_rates[i])
1214 			ni->ni_rates[ni->ni_nrate++] =
1215 			    ic->ic_sup_rates[i];
1216 	}
1217 	IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
1218 	IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
1219 	ni->ni_bssid[0] |= 0x02;	/* local bit for IBSS */
1220 	ni->ni_esslen = ic->ic_des_esslen;
1221 	memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
1222 	ni->ni_rssi = 0;
1223 	ni->ni_rstamp = 0;
1224 	memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
1225 	ni->ni_intval = ic->ic_lintval;
1226 	ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
1227 	if (ic->ic_flags & IEEE80211_F_WEPON)
1228 		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
1229 	ni->ni_chan = ic->ic_ibss_chan;
1230 	if (ic->ic_phytype == IEEE80211_T_FH) {
1231 		ni->ni_fhdwell = 200;	/* XXX */
1232 		ni->ni_fhindex = 1;
1233 	}
1234 	ieee80211_new_state(ifp, IEEE80211_S_RUN, -1);
1235 }
1236 
1237 int
ieee80211_match_bss(struct ieee80211com * ic,struct ieee80211_node * ni)1238 ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
1239 {
1240 	struct ifnet *ifp = &ic->ic_if;
1241 	u_int8_t rate;
1242 	int fail;
1243 
1244 	fail = 0;
1245 	if (isclr(ic->ic_chan_active, ni->ni_chan))
1246 		fail |= 0x01;
1247 	if (ic->ic_des_chan != IEEE80211_CHAN_ANY &&
1248 	    ni->ni_chan != ic->ic_des_chan)
1249 		fail |= 0x01;
1250 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
1251 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
1252 			fail |= 0x02;
1253 	} else {
1254 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
1255 			fail |= 0x02;
1256 	}
1257 	if (ic->ic_flags & IEEE80211_F_WEPON) {
1258 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
1259 			fail |= 0x04;
1260 	} else {
1261 		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
1262 			fail |= 0x04;
1263 	}
1264 	rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
1265 	if (rate & IEEE80211_RATE_BASIC)
1266 		fail |= 0x08;
1267 	if (ic->ic_des_esslen != 0 &&
1268 	    (ni->ni_esslen != ic->ic_des_esslen ||
1269 	     memcmp(ni->ni_essid, ic->ic_des_essid,
1270 	     ic->ic_des_esslen) != 0))
1271 		fail |= 0x10;
1272 	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
1273 	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
1274 		fail |= 0x20;
1275 	if (ifp->if_flags & IFF_DEBUG) {
1276 		printf(" %c %s", fail ? '-' : '+',
1277 		    ether_sprintf(ni->ni_macaddr));
1278 		printf(" %s%c", ether_sprintf(ni->ni_bssid),
1279 		    fail & 0x20 ? '!' : ' ');
1280 		printf(" %3d%c", ni->ni_chan,
1281 		    fail & 0x01 ? '!' : ' ');
1282 		printf(" %+4d", ni->ni_rssi);
1283 		printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
1284 		    fail & 0x08 ? '!' : ' ');
1285 		printf(" %4s%c",
1286 		    (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
1287 		    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
1288 		    "????",
1289 		    fail & 0x02 ? '!' : ' ');
1290 		printf(" %3s%c ",
1291 		    (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
1292 		    "wep" : "no",
1293 		    fail & 0x04 ? '!' : ' ');
1294 		ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
1295 		printf("%s\n", fail & 0x10 ? "!" : "");
1296 	}
1297 	return (fail);
1298 }
1299 
1300 void
ieee80211_end_scan(struct ifnet * ifp)1301 ieee80211_end_scan(struct ifnet *ifp)
1302 {
1303 	struct ieee80211com *ic = (void *)ifp;
1304 	struct ieee80211_node *ni, *nextbs, *selbs;
1305 	void *p;
1306 
1307 	ni = TAILQ_FIRST(&ic->ic_node);
1308 	if (ni == NULL) {
1309 		DPRINTF(("ieee80211_end_scan: no scan candidate\n"));
1310   notfound:
1311 		if (ic->ic_opmode == IEEE80211_M_IBSS &&
1312 		    (ic->ic_flags & IEEE80211_F_IBSSON) &&
1313 		    ic->ic_des_esslen != 0) {
1314 			ieee80211_create_ibss(ic);
1315 			return;
1316 		}
1317 		if (ic->ic_flags & IEEE80211_F_ASCAN) {
1318 			if (ifp->if_flags & IFF_DEBUG)
1319 				printf("%s: entering passive scan mode\n",
1320 				    ifp->if_xname);
1321 			ic->ic_flags &= ~IEEE80211_F_ASCAN;
1322 		}
1323 		memcpy(ic->ic_chan_scan, ic->ic_chan_active,
1324 		    sizeof(ic->ic_chan_active));
1325 		ieee80211_next_scan(ifp);
1326 		return;
1327 	}
1328 	selbs = NULL;
1329 	if (ifp->if_flags & IFF_DEBUG)
1330 		printf("%s:\tmacaddr          bssid         chan  rssi rate flag  wep  essid\n",
1331 		    ifp->if_xname);
1332 	for (; ni != NULL; ni = nextbs) {
1333 		nextbs = TAILQ_NEXT(ni, ni_list);
1334 		if (ni->ni_fails) {
1335 			/*
1336 			 * The configuration of the access points may change
1337 			 * during my scan.  So delete the entry for the AP
1338 			 * and retry to associate if there is another beacon.
1339 			 */
1340 			if (ni->ni_fails++ > 2)
1341 				ieee80211_free_node(ic, ni);
1342 			continue;
1343 		}
1344 		if (ieee80211_match_bss(ic, ni) == 0) {
1345 			if (selbs == NULL || ni->ni_rssi > selbs->ni_rssi)
1346 				selbs = ni;
1347 		}
1348 	}
1349 	if (selbs == NULL)
1350 		goto notfound;
1351 	p = ic->ic_bss.ni_private;
1352 	ic->ic_bss = *selbs;
1353 	ic->ic_bss.ni_private = p;
1354 	if (p != NULL && ic->ic_node_privlen)
1355 		memcpy(p, selbs->ni_private, ic->ic_node_privlen);
1356 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
1357 		ieee80211_fix_rate(ic, &ic->ic_bss, IEEE80211_F_DOFRATE |
1358 		    IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1359 		if (ic->ic_bss.ni_nrate == 0) {
1360 			selbs->ni_fails++;
1361 			goto notfound;
1362 		}
1363 		ieee80211_new_state(ifp, IEEE80211_S_RUN, -1);
1364 	} else
1365 		ieee80211_new_state(ifp, IEEE80211_S_AUTH, -1);
1366 }
1367 
1368 int
ieee80211_get_rate(struct ieee80211com * ic)1369 ieee80211_get_rate(struct ieee80211com *ic)
1370 {
1371 	int rate;
1372 	if (ic->ic_fixed_rate == -1) {
1373 		if (ic->ic_state == IEEE80211_S_RUN)
1374 			rate = ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate];
1375 		else
1376 			rate = 0;
1377 	} else
1378 		rate = ic->ic_sup_rates[ic->ic_fixed_rate];
1379 	return (rate & IEEE80211_RATE_VAL);
1380 }
1381 
1382 int
ieee80211_get_channel(struct ieee80211com * ic)1383 ieee80211_get_channel(struct ieee80211com *ic)
1384 {
1385 	switch (ic->ic_state) {
1386 	case IEEE80211_S_INIT:
1387 		if (ic->ic_opmode == IEEE80211_M_STA)
1388 			return (ic->ic_des_chan);
1389 		else
1390 			return (ic->ic_ibss_chan);
1391 	case IEEE80211_S_SCAN:	/* XXX could be confusing if ic_des_chan is
1392 				 * set
1393 				 */
1394 	default:
1395 		return (ic->ic_bss.ni_chan);
1396 	}
1397 }
1398 
1399 
1400 struct ieee80211_node *
ieee80211_alloc_node(struct ieee80211com * ic,u_int8_t * macaddr,int copy)1401 ieee80211_alloc_node(struct ieee80211com *ic, u_int8_t *macaddr, int copy)
1402 {
1403 	struct ieee80211_node *ni;
1404 	int hash;
1405 	int s;
1406 
1407 	ni = malloc(sizeof(struct ieee80211_node) + ic->ic_node_privlen,
1408 	    M_DEVBUF, M_NOWAIT);
1409 	if (ni == NULL)
1410 		return (NULL);
1411 	if (copy)
1412 		memcpy(ni, &ic->ic_bss, sizeof(struct ieee80211_node));
1413 	else
1414 		memset(ni, 0, sizeof(struct ieee80211_node));
1415 	IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
1416 	if (ic->ic_node_privlen) {
1417 		ni->ni_private = &ni[1];
1418 		memset(ni->ni_private, 0, ic->ic_node_privlen);
1419 	} else
1420 		ni->ni_private = NULL;
1421 
1422 	hash = IEEE80211_NODE_HASH(macaddr);
1423 	s = splnet();
1424 	TAILQ_INSERT_TAIL(&ic->ic_node, ni, ni_list);
1425 	LIST_INSERT_HEAD(&ic->ic_hash[hash], ni, ni_hash);
1426 	splx(s);
1427 	ic->ic_inact_timer = IEEE80211_INACT_WAIT;
1428 	return (ni);
1429 }
1430 
1431 struct ieee80211_node *
ieee80211_find_node(struct ieee80211com * ic,u_int8_t * macaddr)1432 ieee80211_find_node(struct ieee80211com *ic, u_int8_t *macaddr)
1433 {
1434 	struct ieee80211_node *ni;
1435 	int hash;
1436 	int s;
1437 
1438 	hash = IEEE80211_NODE_HASH(macaddr);
1439 	s = splnet();
1440 	LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) {
1441 		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr))
1442 			break;
1443 	}
1444 	splx(s);
1445 	return (ni);
1446 }
1447 
1448 void
ieee80211_free_node(struct ieee80211com * ic,struct ieee80211_node * ni)1449 ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni)
1450 {
1451 	int s;
1452 
1453 	s = splnet();
1454 	if (ic->ic_node_free != NULL)
1455 		(*ic->ic_node_free)(ic, ni);
1456 	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
1457 	TAILQ_REMOVE(&ic->ic_node, ni, ni_list);
1458 	LIST_REMOVE(ni, ni_hash);
1459 	if (!IF_IS_EMPTY(&ni->ni_savedq)) {
1460 		IF_PURGE(&ni->ni_savedq);
1461 		if (ic->ic_set_tim)
1462 			ic->ic_set_tim(ic, ni->ni_associd, 0);
1463 	}
1464 	splx(s);
1465 	free(ni, M_DEVBUF);
1466 	if (TAILQ_EMPTY(&ic->ic_node))
1467 		ic->ic_inact_timer = 0;
1468 }
1469 
1470 void
ieee80211_free_allnodes(struct ieee80211com * ic)1471 ieee80211_free_allnodes(struct ieee80211com *ic)
1472 {
1473 	struct ieee80211_node *ni;
1474 
1475 	while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL)
1476 		ieee80211_free_node(ic, ni);
1477 }
1478 
1479 int
ieee80211_fix_rate(struct ieee80211com * ic,struct ieee80211_node * ni,int flags)1480 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags)
1481 {
1482 	int i, j, ignore, error;
1483 	int okrate, badrate;
1484 	u_int8_t r;
1485 
1486 	error = 0;
1487 	okrate = badrate = 0;
1488 	for (i = 0; i < ni->ni_nrate; ) {
1489 		ignore = 0;
1490 		if (flags & IEEE80211_F_DOSORT) {
1491 			for (j = i + 1; j < ni->ni_nrate; j++) {
1492 				if ((ni->ni_rates[i] & IEEE80211_RATE_VAL) >
1493 				    (ni->ni_rates[j] & IEEE80211_RATE_VAL)) {
1494 					r = ni->ni_rates[i];
1495 					ni->ni_rates[i] = ni->ni_rates[j];
1496 					ni->ni_rates[j] = r;
1497 				}
1498 			}
1499 		}
1500 		r = ni->ni_rates[i] & IEEE80211_RATE_VAL;
1501 		badrate = r;
1502 		if (flags & IEEE80211_F_DOFRATE) {
1503 			if (ic->ic_fixed_rate >= 0 &&
1504 			    r != (ic->ic_sup_rates[ic->ic_fixed_rate] &
1505 			    IEEE80211_RATE_VAL))
1506 				ignore++;
1507 		}
1508 		if (flags & IEEE80211_F_DONEGO) {
1509 			for (j = 0; j < IEEE80211_RATE_SIZE; j++) {
1510 				if (r ==
1511 				    (ic->ic_sup_rates[j] & IEEE80211_RATE_VAL))
1512 					break;
1513 			}
1514 			if (j == IEEE80211_RATE_SIZE) {
1515 				if (ni->ni_rates[i] & IEEE80211_RATE_BASIC)
1516 					error++;
1517 				ignore++;
1518 			}
1519 		}
1520 		if (flags & IEEE80211_F_DODEL) {
1521 			if (ignore) {
1522 				ni->ni_nrate--;
1523 				for (j = i; j < ni->ni_nrate; j++)
1524 					ni->ni_rates[j] = ni->ni_rates[j + 1];
1525 				ni->ni_rates[j] = 0;
1526 				continue;
1527 			}
1528 		}
1529 		if (!ignore)
1530 			okrate = ni->ni_rates[i];
1531 		i++;
1532 	}
1533 	if (okrate == 0 || error != 0)
1534 		return (badrate | IEEE80211_RATE_BASIC);
1535 	return (okrate & IEEE80211_RATE_VAL);
1536 }
1537 
1538 static u_int8_t *
ieee80211_add_rates(u_int8_t * frm,const u_int8_t rates[IEEE80211_RATE_SIZE])1539 ieee80211_add_rates(u_int8_t *frm, const u_int8_t rates[IEEE80211_RATE_SIZE])
1540 {
1541 	int i, j;
1542 
1543 	*frm++ = IEEE80211_ELEMID_RATES;
1544 	j = 0;
1545 	for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
1546 		if (rates[i] != 0) {
1547 			frm[1 + j] = rates[i];
1548 			j++;
1549 		}
1550 	}
1551 	*frm++ = j;
1552 	return (frm + j);
1553 }
1554 
1555 static u_int8_t *
ieee80211_add_ssid(u_int8_t * frm,const u_int8_t * ssid,u_int len)1556 ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
1557 {
1558 	*frm++ = IEEE80211_ELEMID_SSID;
1559 	*frm++ = len;
1560 	memcpy(frm, ssid, len);
1561 	return (frm + len);
1562 }
1563 
1564 void
ieee80211_pwrsave(struct ieee80211com * ic,struct ieee80211_node * ni,struct mbuf * m)1565 ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni,
1566 		  struct mbuf *m)
1567 {
1568 	/* Store the new packet on our queue, changing the TIM if necessary */
1569 
1570 	if (IF_IS_EMPTY(&ni->ni_savedq)) {
1571 		ic->ic_set_tim(ic, ni->ni_associd, 1);
1572 	}
1573 	if (ni->ni_savedq.ifq_len >= IEEE80211_PS_MAX_QUEUE) {
1574 		IF_DROP(&ni->ni_savedq);
1575 		m_freem(m);
1576 		if (ic->ic_if.if_flags & IFF_DEBUG)
1577 			printf("%s: station %s power save queue overflow"
1578 			       " of size %d drops %d\n",
1579 			       ic->ic_if.if_xname,
1580 			       ether_sprintf(ni->ni_macaddr),
1581 			       IEEE80211_PS_MAX_QUEUE,
1582 			       ni->ni_savedq.ifq_drops);
1583 	} else {
1584 		IF_ENQUEUE(&ni->ni_savedq, m);
1585 	}
1586 }
1587 
1588 static int
ieee80211_send_prreq(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int dummy)1589 ieee80211_send_prreq(struct ieee80211com *ic, struct ieee80211_node *ni,
1590     int type, int dummy)
1591 {
1592 	int ret;
1593 	struct mbuf *m;
1594 	u_int8_t *frm;
1595 
1596 	/*
1597 	 * prreq frame format
1598 	 *	[tlv] ssid
1599 	 *	[tlv] supported rates
1600 	 */
1601 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1602 	if (m == NULL)
1603 		return (ENOMEM);
1604 	m->m_data += IEEE80211_HEADER_LEN(ic);
1605 	frm = mtod(m, u_int8_t *);
1606 	frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
1607 	frm = ieee80211_add_rates(frm, ic->ic_sup_rates);
1608 	m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1609 
1610 	ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
1611 	ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
1612 	return (ret);
1613 }
1614 
1615 static int
ieee80211_send_prresp(struct ieee80211com * ic,struct ieee80211_node * bs0,int type,int dummy)1616 ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_node *bs0,
1617     int type, int dummy)
1618 {
1619 	struct mbuf *m;
1620 	u_int8_t *frm;
1621 	struct ieee80211_node *ni = &ic->ic_bss;
1622 	u_int16_t capinfo;
1623 
1624 	/*
1625 	 * probe response frame format
1626 	 *	[8] time stamp
1627 	 *	[2] beacon interval
1628 	 *	[2] cabability information
1629 	 *	[tlv] ssid
1630 	 *	[tlv] supported rates
1631 	 *	[tlv] parameter set (IBSS)
1632 	 */
1633 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1634 	if (m == NULL)
1635 		return (ENOMEM);
1636 	m->m_data += IEEE80211_HEADER_LEN(ic);
1637 	frm = mtod(m, u_int8_t *);
1638 
1639 	memset(frm, 0, 8);	/* timestamp should be filled later */
1640 	frm += 8;
1641 	*(u_int16_t *)frm = htole16(ni->ni_intval);
1642 	frm += 2;
1643 	if (ic->ic_opmode == IEEE80211_M_IBSS)
1644 		capinfo = IEEE80211_CAPINFO_IBSS;
1645 	else
1646 		capinfo = IEEE80211_CAPINFO_ESS;
1647 	if (ic->ic_flags & IEEE80211_F_WEPON)
1648 		capinfo |= IEEE80211_CAPINFO_PRIVACY;
1649 	*(u_int16_t *)frm = htole16(capinfo);
1650 	frm += 2;
1651 
1652 	frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
1653 	frm = ieee80211_add_rates(frm, ni->ni_rates);
1654 
1655 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
1656 		*frm++ = IEEE80211_ELEMID_IBSSPARMS;
1657 		*frm++ = 2;
1658 		*frm++ = 0; *frm++ = 0;		/* TODO: ATIM window */
1659 	} else {	/* IEEE80211_M_HOSTAP */
1660 		/* TODO: TIM */
1661 		*frm++ = IEEE80211_ELEMID_TIM;
1662 		*frm++ = 4;	/* length */
1663 		*frm++ = 0;	/* DTIM count */
1664 		*frm++ = 1;	/* DTIM period */
1665 		*frm++ = 0;	/* bitmap control */
1666 		*frm++ = 0;	/* Partial Virtual Bitmap (variable length) */
1667 	}
1668 	/* TODO: check MHLEN limit */
1669 	m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1670 
1671 	return (ieee80211_mgmt_output(&ic->ic_if, bs0, m, type));
1672 }
1673 
1674 static int
ieee80211_send_auth(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int seq)1675 ieee80211_send_auth(struct ieee80211com *ic, struct ieee80211_node *ni,
1676     int type, int seq)
1677 {
1678 	struct mbuf *m;
1679 	u_int16_t *frm;
1680 	int ret;
1681 
1682 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1683 	if (m == NULL)
1684 		return (ENOMEM);
1685 	MH_ALIGN(m, 2 * 3);
1686 	m->m_pkthdr.len = m->m_len = 6;
1687 	frm = mtod(m, u_int16_t *);
1688 	/* TODO: shared key auth */
1689 	frm[0] = htole16(IEEE80211_AUTH_ALG_OPEN);
1690 	frm[1] = htole16(seq);
1691 	frm[2] = 0;			/* status */
1692 	ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
1693 	if (ic->ic_opmode == IEEE80211_M_STA)
1694 		ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
1695 	return (ret);
1696 }
1697 
1698 static int
ieee80211_send_deauth(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int reason)1699 ieee80211_send_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,
1700     int type, int reason)
1701 {
1702 	struct ifnet *ifp = &ic->ic_if;
1703 	struct mbuf *m;
1704 
1705 	if (ifp->if_flags & IFF_DEBUG)
1706 		printf("%s: station %s deauthenticate (reason %d)\n",
1707 		    ifp->if_xname, ether_sprintf(ni->ni_macaddr), reason);
1708 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1709 	if (m == NULL)
1710 		return (ENOMEM);
1711 	MH_ALIGN(m, 2);
1712 	m->m_pkthdr.len = m->m_len = 2;
1713 	*mtod(m, u_int16_t *) = htole16(reason);
1714 	return (ieee80211_mgmt_output(&ic->ic_if, ni, m, type));
1715 }
1716 
1717 static int
ieee80211_send_asreq(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int dummy)1718 ieee80211_send_asreq(struct ieee80211com *ic, struct ieee80211_node *ni,
1719     int type, int dummy)
1720 {
1721 	struct mbuf *m;
1722 	u_int8_t *frm;
1723 	u_int16_t capinfo;
1724 	int ret;
1725 
1726 	/*
1727 	 * asreq frame format
1728 	 *	[2] capability information
1729 	 *	[2] listen interval
1730 	 *	[6*] current AP address (reassoc only)
1731 	 *	[tlv] ssid
1732 	 *	[tlv] supported rates
1733 	 */
1734 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1735 	if (m == NULL)
1736 		return (ENOMEM);
1737 	m->m_data += IEEE80211_HEADER_LEN(ic);
1738 	frm = mtod(m, u_int8_t *);
1739 
1740 	capinfo = 0;
1741 	if (ic->ic_opmode == IEEE80211_M_IBSS)
1742 		capinfo |= IEEE80211_CAPINFO_IBSS;
1743 	else		/* IEEE80211_M_STA */
1744 		capinfo |= IEEE80211_CAPINFO_ESS;
1745 	if (ic->ic_flags & IEEE80211_F_WEPON)
1746 		capinfo |= IEEE80211_CAPINFO_PRIVACY;
1747 	*(u_int16_t *)frm = htole16(capinfo);
1748 	frm += 2;
1749 
1750 	*(u_int16_t *)frm = htole16(ic->ic_lintval);
1751 	frm += 2;
1752 
1753 	if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
1754 		IEEE80211_ADDR_COPY(frm, ic->ic_bss.ni_bssid);
1755 		frm += IEEE80211_ADDR_LEN;
1756 	}
1757 
1758 	frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
1759 	frm = ieee80211_add_rates(frm, ic->ic_sup_rates);
1760 	m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1761 
1762 	ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type);
1763 	ic->ic_mgt_timer = IEEE80211_TRANS_WAIT;
1764 	return (ret);
1765 }
1766 
1767 static int
ieee80211_send_asresp(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int status)1768 ieee80211_send_asresp(struct ieee80211com *ic, struct ieee80211_node *ni,
1769     int type, int status)
1770 {
1771 	struct mbuf *m;
1772 	u_int8_t *frm;
1773 	u_int16_t capinfo;
1774 
1775 	/*
1776 	 * asreq frame format
1777 	 *	[2] capability information
1778 	 *	[2] status
1779 	 *	[2] association ID
1780 	 *	[tlv] supported rates
1781 	 */
1782 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1783 	if (m == NULL)
1784 		return (ENOMEM);
1785 	m->m_data += IEEE80211_HEADER_LEN(ic);
1786 	frm = mtod(m, u_int8_t *);
1787 
1788 	capinfo = IEEE80211_CAPINFO_ESS;
1789 	if (ic->ic_flags & IEEE80211_F_WEPON)
1790 		capinfo |= IEEE80211_CAPINFO_PRIVACY;
1791 	*(u_int16_t *)frm = htole16(capinfo);
1792 	frm += 2;
1793 
1794 	*(u_int16_t *)frm = htole16(status);
1795 	frm += 2;
1796 
1797 	if (status == IEEE80211_STATUS_SUCCESS && ni != NULL)
1798 		*(u_int16_t *)frm = htole16(ni->ni_associd);
1799 	else
1800 		*(u_int16_t *)frm = htole16(0);
1801 	frm += 2;
1802 
1803 	if (ni != NULL)
1804 		frm = ieee80211_add_rates(frm, ni->ni_rates);
1805 	else
1806 		frm = ieee80211_add_rates(frm, ic->ic_bss.ni_rates);
1807 	m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
1808 
1809 	return (ieee80211_mgmt_output(&ic->ic_if, ni, m, type));
1810 }
1811 
1812 static int
ieee80211_send_disassoc(struct ieee80211com * ic,struct ieee80211_node * ni,int type,int reason)1813 ieee80211_send_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
1814     int type, int reason)
1815 {
1816 	struct ifnet *ifp = &ic->ic_if;
1817 	struct mbuf *m;
1818 
1819 	if (ifp->if_flags & IFF_DEBUG)
1820 		printf("%s: station %s disassociate (reason %d)\n",
1821 		    ifp->if_xname, ether_sprintf(ni->ni_macaddr), reason);
1822 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1823 	if (m == NULL)
1824 		return (ENOMEM);
1825 	MH_ALIGN(m, 2);
1826 	m->m_pkthdr.len = m->m_len = 2;
1827 	*mtod(m, u_int16_t *) = htole16(reason);
1828 	return (ieee80211_mgmt_output(&ic->ic_if, ni, m,
1829 	    IEEE80211_FC0_SUBTYPE_DISASSOC));
1830 }
1831 
1832 /* Verify the existence and length of __elem or get out. */
1833 #define IEEE80211_VERIFY_ELEMENT(__subr_name, __wh, __elem, __maxlen) \
1834 	do { \
1835 		if (__elem == NULL) { \
1836 			DPRINTF((#__subr_name ": no " #__elem "\n")); \
1837 			return; \
1838 		} \
1839 		if (__elem[1] > __maxlen) { \
1840 			DPRINTF((#__subr_name ": bad " #__elem \
1841 			    " len %d from %s\n", \
1842 			    __elem[1], ether_sprintf(__wh->i_addr2))); \
1843 			return; \
1844 		} \
1845 	} while (0)
1846 
1847 static void
ieee80211_recv_beacon(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)1848 ieee80211_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, int rssi,
1849     u_int32_t rstamp)
1850 {
1851 	struct ieee80211_frame *wh;
1852 	struct ieee80211_node *ni;
1853 	u_int8_t *frm, *efrm, *tstamp, *bintval, *capinfo, *ssid, *rates;
1854 	u_int8_t chan, fhindex;
1855 	u_int16_t fhdwell;
1856 
1857 	if (ic->ic_opmode != IEEE80211_M_IBSS &&
1858 	    ic->ic_state != IEEE80211_S_SCAN) {
1859 		/* XXX: may be useful for background scan */
1860 		return;
1861 	}
1862 
1863 	wh = mtod(m0, struct ieee80211_frame *);
1864 	frm = (u_int8_t *)&wh[1];
1865 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
1866 	/*
1867 	 * beacon frame format
1868 	 *	[8] time stamp
1869 	 *	[2] beacon interval
1870 	 *	[2] cabability information
1871 	 *	[tlv] ssid
1872 	 *	[tlv] supported rates
1873 	 *	[tlv] parameter set (FH/DS)
1874 	 */
1875 	tstamp  = frm;	frm += 8;
1876 	bintval = frm;	frm += 2;
1877 	capinfo = frm;	frm += 2;
1878 	ssid = rates = NULL;
1879 	chan = ic->ic_bss.ni_chan;
1880 	fhdwell = 0;
1881 	fhindex = 0;
1882 	while (frm < efrm) {
1883 		switch (*frm) {
1884 		case IEEE80211_ELEMID_SSID:
1885 			ssid = frm;
1886 			break;
1887 		case IEEE80211_ELEMID_RATES:
1888 			rates = frm;
1889 			break;
1890 		case IEEE80211_ELEMID_FHPARMS:
1891 			if (ic->ic_phytype == IEEE80211_T_FH) {
1892 				fhdwell = (frm[3] << 8) | frm[2];
1893 				chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
1894 				fhindex = frm[6];
1895 			}
1896 			break;
1897 		case IEEE80211_ELEMID_DSPARMS:
1898 			if (ic->ic_phytype == IEEE80211_T_DS)
1899 				chan = frm[2];
1900 			break;
1901 		}
1902 		frm += frm[1] + 2;
1903 	}
1904 	IEEE80211_VERIFY_ELEMENT(ieee80211_recv_beacon, wh, rates,
1905 	    IEEE80211_RATE_SIZE);
1906 	IEEE80211_VERIFY_ELEMENT(ieee80211_recv_beacon, wh, ssid,
1907 	    IEEE80211_NWID_LEN);
1908 	ni = ieee80211_find_node(ic, wh->i_addr2);
1909 #ifdef IEEE80211_DEBUG
1910 	if (ieee80211_debug &&
1911 	    (ieee80211_debug > 1 || ni == NULL ||
1912 	    ic->ic_state == IEEE80211_S_SCAN)) {
1913 		int is_prresp = ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
1914 		                 IEEE80211_FC0_SUBTYPE_PROBE_RESP);
1915 		printf("ieee80211_recv_beacon: %s%s on chan %u (bss chan %u) ",
1916 		    (ni == NULL ? "new " : ""),
1917 		    is_prresp ? "probe response" : "beacon",
1918 		    chan, ic->ic_bss.ni_chan);
1919 		ieee80211_print_essid(ssid + 2, ssid[1]);
1920 		printf(" from %s\n", ether_sprintf(wh->i_addr2));
1921 	}
1922 #endif
1923 	if (ni == NULL) {
1924 		if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 0)) == NULL)
1925 			return;
1926 		ni->ni_esslen = ssid[1];
1927 		memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
1928 		memcpy(ni->ni_essid, ssid + 2, ssid[1]);
1929 	} else if (ssid[1] != 0) {
1930 		ni->ni_esslen = ssid[1];
1931 		memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
1932 		memcpy(ni->ni_essid, ssid + 2, ssid[1]);
1933 	}
1934 	IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
1935 	memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
1936 	ni->ni_nrate = rates[1];
1937 	memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
1938 	ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT);
1939 	ni->ni_rssi = rssi;
1940 	ni->ni_rstamp = rstamp;
1941 	memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
1942 	ni->ni_intval = letoh16(*(u_int16_t *)bintval);
1943 	ni->ni_capinfo = letoh16(*(u_int16_t *)capinfo);
1944 	ni->ni_chan = chan;
1945 	ni->ni_fhdwell = fhdwell;
1946 	ni->ni_fhindex = fhindex;
1947 	if (ic->ic_state == IEEE80211_S_SCAN &&
1948 	    (ic->ic_flags & IEEE80211_F_ASCAN) == 0)
1949 		ieee80211_end_scan(&ic->ic_if);
1950 }
1951 
1952 static void
ieee80211_recv_prreq(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)1953 ieee80211_recv_prreq(struct ieee80211com *ic, struct mbuf *m0, int rssi,
1954     u_int32_t rstamp)
1955 {
1956 	struct ieee80211_frame *wh;
1957 	struct ieee80211_node *ni;
1958 	u_int8_t *frm, *efrm, *ssid, *rates;
1959 	u_int8_t rate;
1960 	int allocbs;
1961 
1962 	if (ic->ic_opmode == IEEE80211_M_STA)
1963 		return;
1964 	if (ic->ic_state != IEEE80211_S_RUN)
1965 		return;
1966 
1967 	wh = mtod(m0, struct ieee80211_frame *);
1968 	frm = (u_int8_t *)&wh[1];
1969 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
1970 	/*
1971 	 * prreq frame format
1972 	 *	[tlv] ssid
1973 	 *	[tlv] supported rates
1974 	 */
1975 	ssid = rates = NULL;
1976 	while (frm < efrm) {
1977 		switch (*frm) {
1978 		case IEEE80211_ELEMID_SSID:
1979 			ssid = frm;
1980 			break;
1981 		case IEEE80211_ELEMID_RATES:
1982 			rates = frm;
1983 			break;
1984 		}
1985 		frm += frm[1] + 2;
1986 	}
1987 	IEEE80211_VERIFY_ELEMENT(ieee80211_recv_prreq, wh, rates,
1988 	    IEEE80211_RATE_SIZE);
1989 	IEEE80211_VERIFY_ELEMENT(ieee80211_recv_prreq, wh, ssid,
1990 	    IEEE80211_NWID_LEN);
1991 	if (ssid[1] != 0 &&
1992 	    (ssid[1] != ic->ic_bss.ni_esslen ||
1993 	    memcmp(ssid + 2, ic->ic_bss.ni_essid, ic->ic_bss.ni_esslen) != 0)) {
1994 #ifdef IEEE80211_DEBUG
1995 		if (ieee80211_debug) {
1996 			printf("ieee80211_recv_prreq: ssid unmatch ");
1997 			ieee80211_print_essid(ssid + 2, ssid[1]);
1998 			printf(" from %s\n", ether_sprintf(wh->i_addr2));
1999 		}
2000 #endif
2001 		return;
2002 	}
2003 
2004 	ni = ieee80211_find_node(ic, wh->i_addr2);
2005 	if (ni == NULL) {
2006 		if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 1)) == NULL)
2007 			return;
2008 		DPRINTF(("ieee80211_recv_prreq: new req from %s\n",
2009 		    ether_sprintf(wh->i_addr2)));
2010 		allocbs = 1;
2011 	} else
2012 		allocbs = 0;
2013 	memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2014 	ni->ni_nrate = rates[1];
2015 	memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
2016 	ni->ni_rssi = rssi;
2017 	ni->ni_rstamp = rstamp;
2018 	rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT |
2019 	    IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
2020 	if (rate & IEEE80211_RATE_BASIC) {
2021 		DPRINTF(("ieee80211_recv_prreq: rate negotiation failed: %s\n",
2022 		    ether_sprintf(wh->i_addr2)));
2023 	} else {
2024 		IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP,
2025 		    0);
2026 	}
2027 	if (allocbs && (ic->ic_opmode == IEEE80211_M_HOSTAP))
2028 		ieee80211_free_node(ic, ni);
2029 }
2030 
2031 static void
ieee80211_recv_auth(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2032 ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2033     u_int32_t rstamp)
2034 {
2035 	struct ifnet *ifp = &ic->ic_if;
2036 	struct ieee80211_frame *wh;
2037 	struct ieee80211_node *ni;
2038 	u_int8_t *frm, *efrm;
2039 	u_int16_t algo, seq, status;
2040 	int allocbs;
2041 
2042 	wh = mtod(m0, struct ieee80211_frame *);
2043 	frm = (u_int8_t *)&wh[1];
2044 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
2045 	/*
2046 	 * auth frame format
2047 	 *	[2] algorithm
2048 	 *	[2] sequence
2049 	 *	[2] status
2050 	 *	[tlv*] challenge
2051 	 */
2052 	if (frm + 6 > efrm) {
2053 		DPRINTF(("ieee80211_recv_auth: too short from %s\n",
2054 		    ether_sprintf(wh->i_addr2)));
2055 		return;
2056 	}
2057 	algo   = letoh16(*(u_int16_t *)frm);
2058 	seq    = letoh16(*(u_int16_t *)(frm + 2));
2059 	status = letoh16(*(u_int16_t *)(frm + 4));
2060 	if (algo != IEEE80211_AUTH_ALG_OPEN) {
2061 		/* TODO: shared key auth */
2062 		DPRINTF(("ieee80211_recv_auth: unsupported auth %d from %s\n",
2063 		    algo, ether_sprintf(wh->i_addr2)));
2064 		return;
2065 	}
2066 	switch (ic->ic_opmode) {
2067 	case IEEE80211_M_IBSS:
2068 		if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
2069 			return;
2070 		ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH,
2071 		    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2072 		break;
2073 
2074 	case IEEE80211_M_AHDEMO:
2075 	case IEEE80211_M_MONITOR:
2076 		/* should not come here */
2077 		break;
2078 
2079 	case IEEE80211_M_HOSTAP:
2080 		if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
2081 			return;
2082 		allocbs = 0;
2083 		ni = ieee80211_find_node(ic, wh->i_addr2);
2084 		if (ni == NULL) {
2085 			ni = ieee80211_alloc_node(ic, wh->i_addr2, 0);
2086 			if (ni == NULL)
2087 				return;
2088 			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss.ni_bssid);
2089 			allocbs = 1;
2090 		}
2091 		IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2);
2092 		if (ifp->if_flags & IFF_DEBUG)
2093 			printf("%s: station %s %s authenticated\n",
2094 			    ifp->if_xname,
2095 			    (allocbs ? "newly" : "already"),
2096 			    ether_sprintf(ni->ni_macaddr));
2097 		break;
2098 
2099 	case IEEE80211_M_STA:
2100 		if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
2101 			return;
2102 		if (status != 0) {
2103 			printf("%s: authentication failed (reason %d) for %s\n",
2104 			    ic->ic_if.if_xname, status,
2105 			    ether_sprintf(wh->i_addr3));
2106 			ni = ieee80211_find_node(ic, wh->i_addr2);
2107 			if (ni != NULL)
2108 				ni->ni_fails++;
2109 			return;
2110 		}
2111 		ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC,
2112 		    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2113 		break;
2114 	}
2115 }
2116 
2117 static void
ieee80211_recv_asreq(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2118 ieee80211_recv_asreq(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2119     u_int32_t rstamp)
2120 {
2121 	struct ifnet *ifp = &ic->ic_if;
2122 	struct ieee80211_frame *wh;
2123 	struct ieee80211_node *ni = &ic->ic_bss;
2124 	u_int8_t *frm, *efrm, *ssid, *rates;
2125 	u_int16_t capinfo, bintval;
2126 	int reassoc, resp, newassoc;
2127 
2128 	if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
2129 	    (ic->ic_state != IEEE80211_S_RUN))
2130 		return;
2131 
2132 	wh = mtod(m0, struct ieee80211_frame *);
2133 	frm = (u_int8_t *)&wh[1];
2134 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
2135 	if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2136 	    IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
2137 		reassoc = 1;
2138 		resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
2139 	} else {
2140 		reassoc = 0;
2141 		resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
2142 	}
2143 	/*
2144 	 * asreq frame format
2145 	 *	[2] capability information
2146 	 *	[2] listen interval
2147 	 *	[6*] current AP address (reassoc only)
2148 	 *	[tlv] ssid
2149 	 *	[tlv] supported rates
2150 	 */
2151 	if (frm + (reassoc ? 10 : 4) > efrm) {
2152 		DPRINTF(("ieee80211_recv_asreq: too short from %s\n",
2153 		    ether_sprintf(wh->i_addr2)));
2154 		return;
2155 	}
2156 
2157 	if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss.ni_bssid)) {
2158 		DPRINTF(("ieee80211_recv_asreq: ignore other bss from %s\n",
2159 		    ether_sprintf(wh->i_addr2)));
2160 		return;
2161 	}
2162 	capinfo = letoh16(*(u_int16_t *)frm);	frm += 2;
2163 	bintval = letoh16(*(u_int16_t *)frm);	frm += 2;
2164 	if (reassoc)
2165 		frm += 6;	/* ignore current AP info */
2166 	ssid = rates = NULL;
2167 	while (frm < efrm) {
2168 		switch (*frm) {
2169 		case IEEE80211_ELEMID_SSID:
2170 			ssid = frm;
2171 			break;
2172 		case IEEE80211_ELEMID_RATES:
2173 			rates = frm;
2174 			break;
2175 		}
2176 		frm += frm[1] + 2;
2177 	}
2178 	IEEE80211_VERIFY_ELEMENT(ieee80211_recv_asreq, wh, rates,
2179 	    IEEE80211_RATE_SIZE);
2180 	IEEE80211_VERIFY_ELEMENT(ieee80211_recv_asreq, wh, ssid,
2181 	    IEEE80211_NWID_LEN);
2182 	if (ssid[1] != ic->ic_bss.ni_esslen ||
2183 	    memcmp(ssid + 2, ic->ic_bss.ni_essid, ssid[1]) != 0) {
2184 #ifdef IEEE80211_DEBUG
2185 		if (ieee80211_debug) {
2186 			printf("ieee80211_recv_asreq: ssid unmatch ");
2187 			ieee80211_print_essid(ssid + 2, ssid[1]);
2188 			printf(" from %s\n", ether_sprintf(wh->i_addr2));
2189 		}
2190 #endif
2191 		return;
2192 	}
2193 	ni = ieee80211_find_node(ic, wh->i_addr2);
2194 	if (ni == NULL) {
2195 		DPRINTF(("ieee80211_recv_asreq: not authenticated for %s\n",
2196 		    ether_sprintf(wh->i_addr2)));
2197 		if ((ni = ieee80211_alloc_node(ic, wh->i_addr2, 1)) == NULL)
2198 			return;
2199 		IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
2200 		    IEEE80211_REASON_ASSOC_NOT_AUTHED);
2201 		ieee80211_free_node(ic, ni);
2202 		return;
2203 	}
2204 	if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
2205 	    (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
2206 	    ((ic->ic_flags & IEEE80211_F_WEPON) ?
2207 	     IEEE80211_CAPINFO_PRIVACY : 0)) {
2208 		DPRINTF(("ieee80211_recv_asreq: capability unmatch %x for %s\n",
2209 		    capinfo, ether_sprintf(wh->i_addr2)));
2210 		IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
2211 		ni->ni_associd = 0;
2212 		IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO);
2213 		return;
2214 	}
2215 	memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2216 	ni->ni_nrate = rates[1];
2217 	memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
2218 	ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
2219 	    IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
2220 	if (ni->ni_nrate == 0) {
2221 		DPRINTF(("ieee80211_recv_asreq: rate unmatch for %s\n",
2222 		    ether_sprintf(wh->i_addr2)));
2223 		IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
2224 		ni->ni_associd = 0;
2225 		IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE);
2226 		return;
2227 	}
2228 	ni->ni_rssi = rssi;
2229 	ni->ni_rstamp = rstamp;
2230 	ni->ni_intval = bintval;
2231 	ni->ni_capinfo = capinfo;
2232 	ni->ni_chan = ic->ic_bss.ni_chan;
2233 	ni->ni_fhdwell = ic->ic_bss.ni_fhdwell;
2234 	ni->ni_fhindex = ic->ic_bss.ni_fhindex;
2235 	if (ni->ni_associd == 0) {
2236 		u_int16_t aid;
2237 
2238 		/*
2239 		 * It would be clever to search the bitmap more efficiently,
2240 		 * but this will do for now.
2241 		 */
2242 		for (aid = 1; aid < ic->ic_max_aid; aid++) {
2243 			if (!IEEE80211_AID_ISSET(aid, ic->ic_aid_bitmap))
2244 				break;
2245 		}
2246 
2247 		if (ic->ic_bss.ni_associd >= ic->ic_max_aid) {
2248 			IEEE80211_SEND_MGMT(ic, ni, resp,
2249 					    IEEE80211_REASON_ASSOC_TOOMANY);
2250 			return;
2251 		} else {
2252 			ni->ni_associd = aid | 0xc000;
2253 			IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
2254 			newassoc = 1;
2255 		}
2256 	} else
2257 		newassoc = 0;
2258 	IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
2259 	if (ifp->if_flags & IFF_DEBUG)
2260 		printf("%s: station %s %s associated at aid %d\n",
2261 		       ifp->if_xname, (newassoc ? "newly" : "already"),
2262 		       ether_sprintf(ni->ni_macaddr),
2263 		       (ni->ni_associd & ~0xc000));
2264 }
2265 
2266 static void
ieee80211_recv_asresp(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2267 ieee80211_recv_asresp(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2268     u_int32_t rstamp)
2269 {
2270 	struct ifnet *ifp = &ic->ic_if;
2271 	struct ieee80211_frame *wh;
2272 	struct ieee80211_node *ni = &ic->ic_bss;
2273 	u_int8_t *frm, *efrm, *rates;
2274 	int status;
2275 
2276 	if (ic->ic_opmode != IEEE80211_M_STA ||
2277 	    ic->ic_state != IEEE80211_S_ASSOC)
2278 		return;
2279 
2280 	wh = mtod(m0, struct ieee80211_frame *);
2281 	frm = (u_int8_t *)&wh[1];
2282 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
2283 	/*
2284 	 * asresp frame format
2285 	 *	[2] capability information
2286 	 *	[2] status
2287 	 *	[2] association ID
2288 	 *	[tlv] supported rates
2289 	 */
2290 	if (frm + 6 > efrm) {
2291 		DPRINTF(("ieee80211_recv_asresp: too short from %s\n",
2292 		    ether_sprintf(wh->i_addr2)));
2293 		return;
2294 	}
2295 
2296 	ni->ni_capinfo = letoh16(*(u_int16_t *)frm);
2297 	frm += 2;
2298 
2299 	status = letoh16(*(u_int16_t *)frm);
2300 	frm += 2;
2301 	if (status != 0) {
2302 		printf("%s: association failed (reason %d) for %s\n",
2303 		    ifp->if_xname, status, ether_sprintf(wh->i_addr3));
2304 		ni = ieee80211_find_node(ic, wh->i_addr2);
2305 		if (ni != NULL)
2306 			ni->ni_fails++;
2307 		return;
2308 	}
2309 	ni->ni_associd = letoh16(*(u_int16_t *)frm);
2310 	frm += 2;
2311 	rates = frm;
2312 
2313 	IEEE80211_VERIFY_ELEMENT(ieee80211_recv_asresp, wh, rates,
2314 	    IEEE80211_RATE_SIZE);
2315 	memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2316 	ni->ni_nrate = rates[1];
2317 	memcpy(ni->ni_rates, rates + 2, ni->ni_nrate);
2318 	ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
2319 	    IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
2320 	if (ni->ni_nrate == 0)
2321 		return;
2322 	ieee80211_new_state(ifp, IEEE80211_S_RUN,
2323 	    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2324 }
2325 
2326 static void
ieee80211_recv_disassoc(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2327 ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2328     u_int32_t rstamp)
2329 {
2330 	struct ifnet *ifp = &ic->ic_if;
2331 	struct ieee80211_frame *wh;
2332 	struct ieee80211_node *ni;
2333 	u_int8_t *frm, *efrm;
2334 	u_int16_t reason;
2335 
2336 	wh = mtod(m0, struct ieee80211_frame *);
2337 	frm = (u_int8_t *)&wh[1];
2338 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
2339 	/*
2340 	 * disassoc frame format
2341 	 *	[2] reason
2342 	 */
2343 	if (frm + 2 > efrm) {
2344 		DPRINTF(("ieee80211_recv_disassoc: too short from %s\n",
2345 		    ether_sprintf(wh->i_addr2)));
2346 		return;
2347 	}
2348 	reason = letoh16(*(u_int16_t *)frm);
2349 	switch (ic->ic_opmode) {
2350 	case IEEE80211_M_STA:
2351 		ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC,
2352 		    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2353 		break;
2354 	case IEEE80211_M_HOSTAP:
2355 		if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) {
2356 			if (ifp->if_flags & IFF_DEBUG)
2357 				printf("%s: station %s disassociated"
2358 				    " by peer (reason %d)\n", ifp->if_xname,
2359 				    ether_sprintf(ni->ni_macaddr), reason);
2360 			IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
2361 			ni->ni_associd = 0;
2362 		}
2363 		break;
2364 	default:
2365 		break;
2366 	}
2367 }
2368 
2369 static void
ieee80211_recv_deauth(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2370 ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2371     u_int32_t rstamp)
2372 {
2373 	struct ifnet *ifp = &ic->ic_if;
2374 	struct ieee80211_frame *wh;
2375 	struct ieee80211_node *ni;
2376 	u_int8_t *frm, *efrm;
2377 	u_int16_t reason;
2378 
2379 	wh = mtod(m0, struct ieee80211_frame *);
2380 	frm = (u_int8_t *)&wh[1];
2381 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
2382 	/*
2383 	 * dauth frame format
2384 	 *	[2] reason
2385 	 */
2386 	if (frm + 2 > efrm) {
2387 		DPRINTF(("ieee80211_recv_deauth: too short from %s\n",
2388 		    ether_sprintf(wh->i_addr2)));
2389 		return;
2390 	}
2391 	reason = letoh16(*(u_int16_t *)frm);
2392 	switch (ic->ic_opmode) {
2393 	case IEEE80211_M_STA:
2394 		ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH,
2395 		    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2396 		break;
2397 	case IEEE80211_M_HOSTAP:
2398 		if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) {
2399 			if (ifp->if_flags & IFF_DEBUG)
2400 				printf("%s: station %s deauthenticated"
2401 				    " by peer (reason %d)\n", ifp->if_xname,
2402 				    ether_sprintf(ni->ni_macaddr), reason);
2403 			ieee80211_free_node(ic, ni);
2404 		}
2405 		break;
2406 	default:
2407 		break;
2408 	}
2409 }
2410 
2411 
2412 static void
ieee80211_recv_pspoll(struct ieee80211com * ic,struct mbuf * m0,int rssi,u_int32_t rstamp)2413 ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi,
2414 		      u_int32_t rstamp)
2415 {
2416 	struct ifnet *ifp = &ic->ic_if;
2417 	struct ieee80211_frame *wh;
2418 	struct ieee80211_node *ni;
2419 	struct mbuf *m;
2420 	u_int16_t aid;
2421 
2422 	if (ic->ic_set_tim == NULL)  /* No powersaving functionality */
2423 		return;
2424 
2425 	wh = mtod(m0, struct ieee80211_frame *);
2426 
2427 	if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) {
2428 		if (ifp->if_flags & IFF_DEBUG)
2429 			printf("%s: station %s sent bogus power save poll\n",
2430 			       ifp->if_xname, ether_sprintf(wh->i_addr2));
2431 		return;
2432 	}
2433 
2434 	memcpy(&aid, wh->i_dur, sizeof(wh->i_dur));
2435 	if ((aid & 0xc000) != 0xc000) {
2436 		if (ifp->if_flags & IFF_DEBUG)
2437 			printf("%s: station %s sent bogus aid %x\n",
2438 			       ifp->if_xname, ether_sprintf(wh->i_addr2), aid);
2439 		return;
2440 	}
2441 
2442 	if (aid != ni->ni_associd) {
2443 		if (ifp->if_flags & IFF_DEBUG)
2444 			printf("%s: station %s aid %x doesn't match pspoll "
2445 			       "aid %x\n",
2446 			       ifp->if_xname, ether_sprintf(wh->i_addr2),
2447 			       ni->ni_associd, aid);
2448 		return;
2449 	}
2450 
2451 	/* Okay, take the first queued packet and put it out... */
2452 
2453 	IF_DEQUEUE(&ni->ni_savedq, m);
2454 	if (m == NULL) {
2455 		if (ifp->if_flags & IFF_DEBUG)
2456 			printf("%s: station %s sent pspoll, "
2457 			       "but no packets are saved\n",
2458 			       ifp->if_xname, ether_sprintf(wh->i_addr2));
2459 		return;
2460 	}
2461 	wh = mtod(m, struct ieee80211_frame *);
2462 
2463 	/*
2464 	 * If this is the last packet, turn off the TIM fields.
2465 	 * If there are more packets, set the more packets bit.
2466 	 */
2467 
2468 	if (IF_IS_EMPTY(&ni->ni_savedq)) {
2469 		if (ic->ic_set_tim)
2470 			ic->ic_set_tim(ic, ni->ni_associd, 0);
2471 	} else {
2472 		wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
2473 	}
2474 
2475 	if (ifp->if_flags & IFF_DEBUG)
2476 		printf("%s: enqueued power saving packet for station %s\n",
2477 		       ifp->if_xname, ether_sprintf(ni->ni_macaddr));
2478 
2479 	IF_ENQUEUE(&ic->ic_pwrsaveq, m);
2480 	(*ifp->if_start)(ifp);
2481 }
2482 
2483 
2484 int
ieee80211_new_state(struct ifnet * ifp,enum ieee80211_state nstate,int mgt)2485 ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt)
2486 {
2487 	struct ieee80211com *ic = (void *)ifp;
2488 	struct ieee80211_node *ni = &ic->ic_bss;
2489 	u_int8_t old_bssid[IEEE80211_ADDR_LEN];
2490 	int i, error, ostate;
2491 #ifdef IEEE80211_DEBUG
2492 	static const char *stname[] =
2493 	    { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
2494 #endif
2495 
2496 	ostate = ic->ic_state;
2497 	DPRINTF(("ieee80211_new_state: %s -> %s\n",
2498 	    stname[ostate], stname[nstate]));
2499 	if (ic->ic_newstate) {
2500 		error = (*ic->ic_newstate)(ic->ic_softc, nstate);
2501 		if (error == EINPROGRESS)
2502 			return (0);
2503 		if (error != 0)
2504 			return (error);
2505 	}
2506 
2507 	/* state transition */
2508 	ic->ic_state = nstate;
2509 	switch (nstate) {
2510 	case IEEE80211_S_INIT:
2511 		switch (ostate) {
2512 		case IEEE80211_S_INIT:
2513 			break;
2514 		case IEEE80211_S_RUN:
2515 			switch (ic->ic_opmode) {
2516 			case IEEE80211_M_STA:
2517 				IEEE80211_SEND_MGMT(ic, ni,
2518 				    IEEE80211_FC0_SUBTYPE_DISASSOC,
2519 				    IEEE80211_REASON_ASSOC_LEAVE);
2520 				break;
2521 			case IEEE80211_M_HOSTAP:
2522 				TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
2523 					if (ni->ni_associd == 0)
2524 						continue;
2525 					IEEE80211_SEND_MGMT(ic, ni,
2526 					    IEEE80211_FC0_SUBTYPE_DISASSOC,
2527 					    IEEE80211_REASON_ASSOC_LEAVE);
2528 				}
2529 				break;
2530 			default:
2531 				break;
2532 			}
2533 			/* FALLTHRU */
2534 		case IEEE80211_S_ASSOC:
2535 			switch (ic->ic_opmode) {
2536 			case IEEE80211_M_STA:
2537 				IEEE80211_SEND_MGMT(ic, ni,
2538 				    IEEE80211_FC0_SUBTYPE_DEAUTH,
2539 				    IEEE80211_REASON_AUTH_LEAVE);
2540 				break;
2541 			case IEEE80211_M_HOSTAP:
2542 				TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
2543 					IEEE80211_SEND_MGMT(ic, ni,
2544 					    IEEE80211_FC0_SUBTYPE_DEAUTH,
2545 					    IEEE80211_REASON_AUTH_LEAVE);
2546 				}
2547 				break;
2548 			default:
2549 				break;
2550 			}
2551 			/* FALLTHRU */
2552 		case IEEE80211_S_AUTH:
2553 		case IEEE80211_S_SCAN:
2554 			ic->ic_mgt_timer = 0;
2555 			IF_PURGE(&ic->ic_mgtq);
2556 			IF_PURGE(&ic->ic_pwrsaveq);
2557 			if (ic->ic_wep_ctx != NULL) {
2558 				free(ic->ic_wep_ctx, M_DEVBUF);
2559 				ic->ic_wep_ctx = NULL;
2560 			}
2561 			ieee80211_free_allnodes(ic);
2562 			break;
2563 		}
2564 		break;
2565 	case IEEE80211_S_SCAN:
2566 		ic->ic_flags &= ~IEEE80211_F_SIBSS;
2567 		ni = &ic->ic_bss;
2568 		/* initialize bss for probe request */
2569 		IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
2570 		IEEE80211_ADDR_COPY(old_bssid, ic->ic_bss.ni_bssid);
2571 		IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
2572 		ni->ni_nrate = 0;
2573 		memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE);
2574 		for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
2575 			if (ic->ic_sup_rates[i] != 0)
2576 				ni->ni_rates[ni->ni_nrate++] =
2577 				    ic->ic_sup_rates[i];
2578 		}
2579 		ni->ni_associd = 0;
2580 		ni->ni_rstamp = 0;
2581 		switch (ostate) {
2582 		case IEEE80211_S_INIT:
2583 			/* use lowest rate */
2584 			ni->ni_txrate = 0;
2585 			ieee80211_begin_scan(ifp, ni);
2586 			break;
2587 		case IEEE80211_S_SCAN:
2588 			/* scan next */
2589 			if (ic->ic_flags & IEEE80211_F_ASCAN) {
2590 				IEEE80211_SEND_MGMT(ic, ni,
2591 				    IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
2592 			}
2593 			break;
2594 		case IEEE80211_S_RUN:
2595 			/* beacon miss */
2596 			if (ifp->if_flags & IFF_DEBUG)
2597 				printf("%s: no recent beacons from %s;"
2598 				    " rescanning\n",
2599 				    ifp->if_xname, ether_sprintf(old_bssid));
2600 			ieee80211_free_allnodes(ic);
2601 			/* FALLTHRU */
2602 		case IEEE80211_S_AUTH:
2603 		case IEEE80211_S_ASSOC:
2604 			/* timeout restart scan */
2605 			ni = ieee80211_find_node(ic, ic->ic_bss.ni_macaddr);
2606 			if (ni != NULL)
2607 				ni->ni_fails++;
2608 			ieee80211_begin_scan(ifp, &ic->ic_bss);
2609 			break;
2610 		}
2611 		break;
2612 	case IEEE80211_S_AUTH:
2613 		switch (ostate) {
2614 		case IEEE80211_S_INIT:
2615 			DPRINTF(("ieee80211_new_state: invalid transition\n"));
2616 			break;
2617 		case IEEE80211_S_SCAN:
2618 			IEEE80211_SEND_MGMT(ic, ni,
2619 			    IEEE80211_FC0_SUBTYPE_AUTH, 1);
2620 			break;
2621 		case IEEE80211_S_AUTH:
2622 		case IEEE80211_S_ASSOC:
2623 			switch (mgt) {
2624 			case IEEE80211_FC0_SUBTYPE_AUTH:
2625 				/* ??? */
2626 				IEEE80211_SEND_MGMT(ic, ni,
2627 				    IEEE80211_FC0_SUBTYPE_AUTH, 2);
2628 				break;
2629 			case IEEE80211_FC0_SUBTYPE_DEAUTH:
2630 				/* ignore and retry scan on timeout */
2631 				break;
2632 			}
2633 			break;
2634 		case IEEE80211_S_RUN:
2635 			switch (mgt) {
2636 			case IEEE80211_FC0_SUBTYPE_AUTH:
2637 				IEEE80211_SEND_MGMT(ic, ni,
2638 				    IEEE80211_FC0_SUBTYPE_AUTH, 2);
2639 				ic->ic_state = ostate;	/* stay RUN */
2640 				break;
2641 			case IEEE80211_FC0_SUBTYPE_DEAUTH:
2642 				/* try to reauth */
2643 				IEEE80211_SEND_MGMT(ic, ni,
2644 				    IEEE80211_FC0_SUBTYPE_AUTH, 1);
2645 				break;
2646 			}
2647 			break;
2648 		}
2649 		break;
2650 	case IEEE80211_S_ASSOC:
2651 		switch (ostate) {
2652 		case IEEE80211_S_INIT:
2653 		case IEEE80211_S_SCAN:
2654 		case IEEE80211_S_ASSOC:
2655 			DPRINTF(("ieee80211_new_state: invalid transition\n"));
2656 			break;
2657 		case IEEE80211_S_AUTH:
2658 			IEEE80211_SEND_MGMT(ic, ni,
2659 			    IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
2660 			break;
2661 		case IEEE80211_S_RUN:
2662 			IEEE80211_SEND_MGMT(ic, ni,
2663 			    IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
2664 			break;
2665 		}
2666 		break;
2667 	case IEEE80211_S_RUN:
2668 		switch (ostate) {
2669 		case IEEE80211_S_INIT:
2670 		case IEEE80211_S_AUTH:
2671 		case IEEE80211_S_RUN:
2672 			DPRINTF(("ieee80211_new_state: invalid transition\n"));
2673 			break;
2674 		case IEEE80211_S_SCAN:		/* adhoc mode */
2675 		case IEEE80211_S_ASSOC:		/* infra mode */
2676 			if (ifp->if_flags & IFF_DEBUG) {
2677 				printf("%s: ", ifp->if_xname);
2678 				if (ic->ic_opmode == IEEE80211_M_STA)
2679 					printf("associated ");
2680 				else
2681 					printf("synchronized ");
2682 				printf("with %s ssid ",
2683 				    ether_sprintf(ic->ic_bss.ni_bssid));
2684 				ieee80211_print_essid(ic->ic_bss.ni_essid,
2685 				    ic->ic_bss.ni_esslen);
2686 				printf(" channel %d\n", ic->ic_bss.ni_chan);
2687 			}
2688 			/* start with highest negotiated rate */
2689 			ic->ic_bss.ni_txrate = ic->ic_bss.ni_nrate - 1;
2690 			ic->ic_mgt_timer = 0;
2691 			(*ifp->if_start)(ifp);
2692 			break;
2693 		}
2694 		break;
2695 	}
2696 	return (0);
2697 }
2698 
2699 struct mbuf *
ieee80211_wep_crypt(struct ifnet * ifp,struct mbuf * m0,int txflag)2700 ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
2701 {
2702 	struct ieee80211com *ic = (void *)ifp;
2703 	struct mbuf *m, *n, *n0;
2704 	struct ieee80211_frame *wh;
2705 	int i, left, len, moff, noff, kid;
2706 	u_int32_t iv, crc;
2707 	u_int8_t *ivp;
2708 	void *ctx;
2709 	u_int8_t keybuf[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
2710 	u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
2711 
2712 	n0 = NULL;
2713 	if ((ctx = ic->ic_wep_ctx) == NULL) {
2714 		ctx = malloc(RC4STATE, M_DEVBUF, M_NOWAIT);
2715 		if (ctx == NULL)
2716 			goto fail;
2717 		ic->ic_wep_ctx = ctx;
2718 	}
2719 	m = m0;
2720 	left = m->m_pkthdr.len;
2721 	MGET(n, M_DONTWAIT, m->m_type);
2722 	n0 = n;
2723 	if (n == NULL)
2724 		goto fail;
2725 	M_MOVE_PKTHDR(n, m);
2726 	len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2727 	if (txflag) {
2728 		n->m_pkthdr.len += len;
2729 	} else {
2730 		n->m_pkthdr.len -= len;
2731 		left -= len;
2732 	}
2733 	n->m_len = MHLEN;
2734 	if (n->m_pkthdr.len >= MINCLSIZE) {
2735 		MCLGET(n, M_DONTWAIT);
2736 		if (n->m_flags & M_EXT)
2737 			n->m_len = n->m_ext.ext_size;
2738 	}
2739 	len = sizeof(struct ieee80211_frame);
2740 	memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
2741 	wh = mtod(n, struct ieee80211_frame *);
2742 	left -= len;
2743 	moff = len;
2744 	noff = len;
2745 	if (txflag) {
2746 		kid = ic->ic_wep_txkey;
2747 		wh->i_fc[1] |= IEEE80211_FC1_WEP;
2748 		if (!ic->ic_iv_flag) {
2749 			ic->ic_iv = arc4random();
2750 			ic->ic_iv_flag++;
2751 		} else
2752 	                iv = ic->ic_iv + 1;
2753 		/*
2754 		 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2755 		 * (B, 255, N) with 3 <= B < 8
2756 		 */
2757 		if (iv >= 0x03ff00 &&
2758 		    (iv & 0xf8ff00) == 0x00ff00)
2759 			iv += 0x000100;
2760 		ic->ic_iv = iv + 1;
2761 		/* put iv in little endian to prepare 802.11i */
2762 		ivp = mtod(n, u_int8_t *) + noff;
2763 		for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
2764 			ivp[i] = iv & 0xff;
2765 			iv >>= 8;
2766 		}
2767 		ivp[IEEE80211_WEP_IVLEN] = kid << 6;	/* pad and keyid */
2768 		noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
2769 	} else {
2770 		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
2771 		ivp = mtod(m, u_int8_t *) + moff;
2772 		kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
2773 		moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
2774 	}
2775 	memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
2776 	memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].wk_key,
2777 	    ic->ic_nw_keys[kid].wk_len);
2778 	rc4_keysetup(ctx, keybuf,
2779 	    IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].wk_len);
2780 
2781 	/* encrypt with calculating CRC */
2782 	crc = ~0;
2783 	while (left > 0) {
2784 		len = m->m_len - moff;
2785 		if (len == 0) {
2786 			m = m->m_next;
2787 			moff = 0;
2788 			continue;
2789 		}
2790 		if (len > n->m_len - noff) {
2791 			len = n->m_len - noff;
2792 			if (len == 0) {
2793 				MGET(n->m_next, M_DONTWAIT, n->m_type);
2794 				if (n->m_next == NULL)
2795 					goto fail;
2796 				n = n->m_next;
2797 				n->m_len = MLEN;
2798 				if (left >= MINCLSIZE) {
2799 					MCLGET(n, M_DONTWAIT);
2800 					if (n->m_flags & M_EXT)
2801 						n->m_len = n->m_ext.ext_size;
2802 				}
2803 				noff = 0;
2804 				continue;
2805 			}
2806 		}
2807 		if (len > left)
2808 			len = left;
2809 		rc4_crypt(ctx, mtod(n, caddr_t) + noff,
2810 		    mtod(m, caddr_t) + moff, len);
2811 		if (txflag)
2812 			crc = ieee80211_crc_update(crc,
2813 			    mtod(m, u_int8_t *) + moff, len);
2814 		else
2815 			crc = ieee80211_crc_update(crc,
2816 			    mtod(n, u_int8_t *) + noff, len);
2817 		left -= len;
2818 		moff += len;
2819 		noff += len;
2820 	}
2821 	crc = ~crc;
2822 	if (txflag) {
2823 		*(u_int32_t *)crcbuf = htole32(crc);
2824 		if (n->m_len >= noff + sizeof(crcbuf))
2825 			n->m_len = noff + sizeof(crcbuf);
2826 		else {
2827 			n->m_len = noff;
2828 			MGET(n->m_next, M_DONTWAIT, n->m_type);
2829 			if (n->m_next == NULL)
2830 				goto fail;
2831 			n = n->m_next;
2832 			n->m_len = sizeof(crcbuf);
2833 			noff = 0;
2834 		}
2835 		rc4_crypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
2836 		    sizeof(crcbuf));
2837 	} else {
2838 		n->m_len = noff;
2839 		for (noff = 0; noff < sizeof(crcbuf); noff += len) {
2840 			len = sizeof(crcbuf) - noff;
2841 			if (len > m->m_len - moff)
2842 				len = m->m_len - moff;
2843 			if (len > 0)
2844 				rc4_crypt(ctx, crcbuf + noff,
2845 				    mtod(m, caddr_t) + moff, len);
2846 			m = m->m_next;
2847 			moff = 0;
2848 		}
2849 		if (crc != letoh32(*(u_int32_t *)crcbuf)) {
2850 #ifdef IEEE80211_DEBUG
2851 			if (ieee80211_debug) {
2852 				printf("%s: decrypt CRC error\n",
2853 				    ifp->if_xname);
2854 				if (ieee80211_debug > 1)
2855 					ieee80211_dump_pkt(n0->m_data,
2856 					    n0->m_len, -1, -1);
2857 			}
2858 #endif
2859 			goto fail;
2860 		}
2861 	}
2862 	m_freem(m0);
2863 	return (n0);
2864 
2865   fail:
2866 	m_freem(m0);
2867 	m_freem(n0);
2868 	return (NULL);
2869 }
2870 
2871 /*
2872  * CRC 32 -- routine from RFC 2083
2873  */
2874 
2875 /* Table of CRCs of all 8-bit messages */
2876 static u_int32_t ieee80211_crc_table[256];
2877 
2878 /* Make the table for a fast CRC. */
2879 static void
ieee80211_crc_init(void)2880 ieee80211_crc_init(void)
2881 {
2882 	u_int32_t c;
2883 	int n, k;
2884 
2885 	for (n = 0; n < 256; n++) {
2886 		c = (u_int32_t)n;
2887 		for (k = 0; k < 8; k++) {
2888 			if (c & 1)
2889 				c = 0xedb88320UL ^ (c >> 1);
2890 			else
2891 				c = c >> 1;
2892 		}
2893 		ieee80211_crc_table[n] = c;
2894 	}
2895 }
2896 
2897 /*
2898  * Update a running CRC with the bytes buf[0..len-1]--the CRC
2899  * should be initialized to all 1's, and the transmitted value
2900  * is the 1's complement of the final running CRC
2901  */
2902 
2903 static u_int32_t
ieee80211_crc_update(u_int32_t crc,u_int8_t * buf,int len)2904 ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len)
2905 {
2906 	u_int8_t *endbuf;
2907 
2908 	for (endbuf = buf + len; buf < endbuf; buf++)
2909 		crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
2910 	return (crc);
2911 }
2912 
2913 int
ieee80211_media_change(struct ifnet * ifp)2914 ieee80211_media_change(struct ifnet *ifp)
2915 {
2916 	struct ieee80211com *ic = (void *)ifp;
2917 	struct ifmedia_entry *ime;
2918 	enum ieee80211_opmode newmode;
2919 	int i, rate, error = 0;
2920 
2921 	ime = ic->ic_media.ifm_cur;
2922 	if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
2923 		i = -1;
2924 	} else {
2925 		rate = ieee80211_media2rate(ime->ifm_media, ic->ic_phytype);
2926 		if (rate == 0)
2927 			return (EINVAL);
2928 		for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
2929 			if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate)
2930 				break;
2931 		}
2932 		if (i == IEEE80211_RATE_SIZE)
2933 			return (EINVAL);
2934 	}
2935 	if (ic->ic_fixed_rate != i) {
2936 		ic->ic_fixed_rate = i;
2937 		error = ENETRESET;
2938 	}
2939 
2940 	if ((ime->ifm_media & IFM_IEEE80211_ADHOC) &&
2941 	    (ime->ifm_media & IFM_FLAG0))
2942 		newmode = IEEE80211_M_AHDEMO;
2943 	else if (ime->ifm_media & IFM_IEEE80211_ADHOC)
2944 		newmode = IEEE80211_M_IBSS;
2945 	else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
2946 		newmode = IEEE80211_M_HOSTAP;
2947 	else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
2948 		newmode = IEEE80211_M_MONITOR;
2949 	else
2950 		newmode = IEEE80211_M_STA;
2951 	if (ic->ic_opmode != newmode) {
2952 		ic->ic_opmode = newmode;
2953 		error = ENETRESET;
2954 	}
2955 	if (error == ENETRESET) {
2956 		if ((ifp->if_flags & IFF_UP) != 0)
2957 			error = (*ifp->if_init)(ifp);
2958 		else
2959 			error = 0;
2960 	}
2961 	if (error == 0)
2962 		ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);
2963 
2964 	return (error);
2965 }
2966 
2967 void
ieee80211_media_status(struct ifnet * ifp,struct ifmediareq * imr)2968 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2969 {
2970 	struct ieee80211com *ic = (void *)ifp;
2971 	int rate;
2972 
2973 	imr->ifm_status = IFM_AVALID;
2974 	if (ic->ic_state == IEEE80211_S_RUN)
2975 		imr->ifm_status |= IFM_ACTIVE;
2976 	imr->ifm_active = IFM_IEEE80211;
2977 	if (ic->ic_state == IEEE80211_S_RUN)
2978 		rate = ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] &
2979 		    IEEE80211_RATE_VAL;
2980 	else {
2981 		if (ic->ic_fixed_rate == -1)
2982 			rate = 0;
2983 		else
2984 			rate = ic->ic_sup_rates[ic->ic_fixed_rate] &
2985 			    IEEE80211_RATE_VAL;
2986 	}
2987 	imr->ifm_active |= ieee80211_rate2media(rate, ic->ic_phytype);
2988 	switch (ic->ic_opmode) {
2989 	case IEEE80211_M_AHDEMO:
2990 		imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
2991 		break;
2992 	case IEEE80211_M_HOSTAP:
2993 		imr->ifm_active |= IFM_IEEE80211_HOSTAP;
2994 		break;
2995 	case IEEE80211_M_IBSS:
2996 		imr->ifm_active |= IFM_IEEE80211_ADHOC;
2997 		break;
2998 	case IEEE80211_M_MONITOR:
2999 		imr->ifm_active |= IFM_IEEE80211_MONITOR;
3000 		break;
3001 	case IEEE80211_M_STA:
3002 		break;
3003 	}
3004 }
3005 
3006 /*
3007  * convert IEEE80211 rate value to ifmedia subtype.
3008  * ieee80211 rate is in unit of 0.5Mbps.
3009  */
3010 
3011 int
ieee80211_rate2media(int rate,enum ieee80211_phytype phytype)3012 ieee80211_rate2media(int rate, enum ieee80211_phytype phytype)
3013 {
3014 	int mword;
3015 
3016 	mword = 0;
3017 	switch (phytype) {
3018 	case IEEE80211_T_FH:
3019 		switch (rate & IEEE80211_RATE_VAL) {
3020 		case 0:
3021 			mword = IFM_AUTO;
3022 			break;
3023 		case 2:
3024 			mword = IFM_IEEE80211_FH1;
3025 			break;
3026 		case 4:
3027 			mword = IFM_IEEE80211_FH2;
3028 			break;
3029 		default:
3030 			mword = IFM_NONE;
3031 			break;
3032 		}
3033 		break;
3034 
3035 	case IEEE80211_T_DS:
3036 		switch (rate & IEEE80211_RATE_VAL) {
3037 		case 0:
3038 			mword = IFM_AUTO;
3039 			break;
3040 		case 2:
3041 			mword = IFM_IEEE80211_DS1;
3042 			break;
3043 		case 4:
3044 			mword = IFM_IEEE80211_DS2;
3045 			break;
3046 		case 11:
3047 			mword = IFM_IEEE80211_DS5;
3048 			break;
3049 		case 22:
3050 			mword = IFM_IEEE80211_DS11;
3051 			break;
3052 		default:
3053 			mword = IFM_NONE;
3054 			break;
3055 		}
3056 		break;
3057 
3058 	default:
3059 		mword = IFM_MANUAL;
3060 		break;
3061 	}
3062 	return (mword);
3063 }
3064 
3065 int
ieee80211_media2rate(int mword,enum ieee80211_phytype phytype)3066 ieee80211_media2rate(int mword, enum ieee80211_phytype phytype)
3067 {
3068 	int rate;
3069 
3070 	rate = 0;
3071 	switch (phytype) {
3072 	case IEEE80211_T_FH:
3073 		switch (IFM_SUBTYPE(mword)) {
3074 		case IFM_IEEE80211_FH1:
3075 			rate = 2;
3076 			break;
3077 		case IFM_IEEE80211_FH2:
3078 			rate = 4;
3079 			break;
3080 		}
3081 		break;
3082 
3083 	case IEEE80211_T_DS:
3084 		switch (IFM_SUBTYPE(mword)) {
3085 		case IFM_IEEE80211_DS1:
3086 			rate = 2;
3087 			break;
3088 		case IFM_IEEE80211_DS2:
3089 			rate = 4;
3090 			break;
3091 		case IFM_IEEE80211_DS5:
3092 			rate = 11;
3093 			break;
3094 		case IFM_IEEE80211_DS11:
3095 			rate = 22;
3096 			break;
3097 		}
3098 		break;
3099 
3100 	default:
3101 		break;
3102 	}
3103 	return (rate);
3104 }
3105 
3106 /*
3107  * XXX
3108  * Wireless LAN specific configuration interface, which is compatible
3109  * with wiconfig(8).
3110  */
3111 
3112 int
ieee80211_cfgget(struct ifnet * ifp,u_long cmd,caddr_t data)3113 ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data)
3114 {
3115 	struct ieee80211com *ic = (void *)ifp;
3116 	int i, j, error;
3117 	struct ifreq *ifr = (struct ifreq *)data;
3118 	struct wi_req wreq;
3119 	struct wi_ltv_keys *keys;
3120 	struct wi_apinfo *ap;
3121 	struct ieee80211_node *ni;
3122 #ifdef WICACHE
3123 	struct wi_sigcache wsc;
3124 #endif /* WICACHE */
3125 
3126 	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
3127 	if (error)
3128 		return (error);
3129 	wreq.wi_len = 0;
3130 	switch (wreq.wi_type) {
3131 	case WI_RID_SERIALNO:
3132 		/* nothing appropriate */
3133 		break;
3134 	case WI_RID_NODENAME:
3135 		strlcpy((char *)&wreq.wi_val[1], hostname,
3136 		    sizeof(wreq.wi_val) - 1);
3137 		wreq.wi_val[0] = htole16(strlen(hostname));
3138 		wreq.wi_len = (1 + strlen(hostname) + 1) / 2;
3139 		break;
3140 	case WI_RID_CURRENT_SSID:
3141 		if (ic->ic_state != IEEE80211_S_RUN) {
3142 			wreq.wi_val[0] = 0;
3143 			wreq.wi_len = 1;
3144 			break;
3145 		}
3146 		wreq.wi_val[0] = htole16(ic->ic_bss.ni_esslen);
3147 		memcpy(&wreq.wi_val[1], ic->ic_bss.ni_essid,
3148 		    ic->ic_bss.ni_esslen);
3149 		wreq.wi_len = (1 + ic->ic_bss.ni_esslen + 1) / 2;
3150 		break;
3151 	case WI_RID_OWN_SSID:
3152 	case WI_RID_DESIRED_SSID:
3153 		wreq.wi_val[0] = htole16(ic->ic_des_esslen);
3154 		memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen);
3155 		wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2;
3156 		break;
3157 	case WI_RID_CURRENT_BSSID:
3158 		if (ic->ic_state == IEEE80211_S_RUN)
3159 			IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss.ni_bssid);
3160 		else
3161 			memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN);
3162 		wreq.wi_len = IEEE80211_ADDR_LEN / 2;
3163 		break;
3164 	case WI_RID_CHANNEL_LIST:
3165 		memset(wreq.wi_val, 0, sizeof(wreq.wi_val));
3166 		/*
3167 		 * Since channel 0 is not available for DS, channel 1
3168 		 * is assigned to LSB on WaveLAN.
3169 		 */
3170 		if (ic->ic_phytype == IEEE80211_T_DS)
3171 			i = 1;
3172 		else
3173 			i = 0;
3174 		for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
3175 			if (isset(ic->ic_chan_active, i)) {
3176 				setbit((u_int8_t *)wreq.wi_val, j);
3177 				wreq.wi_len = j / 16 + 1;
3178 			}
3179 		}
3180 		break;
3181 	case WI_RID_OWN_CHNL:
3182 		wreq.wi_val[0] = htole16(ic->ic_ibss_chan);
3183 		wreq.wi_len = 1;
3184 		break;
3185 	case WI_RID_CURRENT_CHAN:
3186 		wreq.wi_val[0] = htole16(ic->ic_bss.ni_chan);
3187 		wreq.wi_len = 1;
3188 		break;
3189 	case WI_RID_COMMS_QUALITY:
3190 		wreq.wi_val[0] = 0;				/* quality */
3191 		wreq.wi_val[1] = htole16(ic->ic_bss.ni_rssi);	/* signal */
3192 		wreq.wi_val[2] = 0;				/* noise */
3193 		wreq.wi_len = 3;
3194 		break;
3195 	case WI_RID_PROMISC:
3196 		wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0);
3197 		wreq.wi_len = 1;
3198 		break;
3199 	case WI_RID_PORTTYPE:
3200 		wreq.wi_val[0] = htole16(ic->ic_opmode);
3201 		wreq.wi_len = 1;
3202 		break;
3203 	case WI_RID_MAC_NODE:
3204 		IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr);
3205 		wreq.wi_len = IEEE80211_ADDR_LEN / 2;
3206 		break;
3207 	case WI_RID_TX_RATE:
3208 		if (ic->ic_fixed_rate == -1)
3209 			wreq.wi_val[0] = 0;	/* auto */
3210 		else
3211 			wreq.wi_val[0] = htole16(
3212 			    (ic->ic_sup_rates[ic->ic_fixed_rate] &
3213 			    IEEE80211_RATE_VAL) / 2);
3214 		wreq.wi_len = 1;
3215 		break;
3216 	case WI_RID_CUR_TX_RATE:
3217 		wreq.wi_val[0] = htole16(
3218 		    (ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] &
3219 		    IEEE80211_RATE_VAL) / 2);
3220 		wreq.wi_len = 1;
3221 		break;
3222 	case WI_RID_RTS_THRESH:
3223 		wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN);	/* TODO: RTS */
3224 		wreq.wi_len = 1;
3225 		break;
3226 	case WI_RID_CREATE_IBSS:
3227 		wreq.wi_val[0] =
3228 		    htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0);
3229 		wreq.wi_len = 1;
3230 		break;
3231 	case WI_RID_MICROWAVE_OVEN:
3232 		wreq.wi_val[0] = 0;	/* no ... not supported */
3233 		wreq.wi_len = 1;
3234 		break;
3235 	case WI_RID_ROAMING_MODE:
3236 		wreq.wi_val[0] = htole16(1);	/* enabled ... not supported */
3237 		wreq.wi_len = 1;
3238 		break;
3239 	case WI_RID_SYSTEM_SCALE:
3240 		wreq.wi_val[0] = htole16(1);	/* low density ... not supp */
3241 		wreq.wi_len = 1;
3242 		break;
3243 	case WI_RID_PM_ENABLED:
3244 		wreq.wi_val[0] =
3245 		    htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
3246 		wreq.wi_len = 1;
3247 		break;
3248 	case WI_RID_MAX_SLEEP:
3249 		wreq.wi_val[0] = htole16(ic->ic_lintval);
3250 		wreq.wi_len = 1;
3251 		break;
3252 	case WI_RID_CUR_BEACON_INT:
3253 		wreq.wi_val[0] = htole16(ic->ic_bss.ni_intval);
3254 		wreq.wi_len = 1;
3255 		break;
3256 	case WI_RID_WEP_AVAIL:
3257 		wreq.wi_val[0] =
3258 		    htole16((ic->ic_flags & IEEE80211_F_HASWEP) ? 1 : 0);
3259 		wreq.wi_len = 1;
3260 		break;
3261 	case WI_RID_CNFAUTHMODE:
3262 		wreq.wi_val[0] = htole16(1);	/* TODO: open system only */
3263 		wreq.wi_len = 1;
3264 		break;
3265 	case WI_RID_ENCRYPTION:
3266 		wreq.wi_val[0] =
3267 		    htole16((ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0);
3268 		wreq.wi_len = 1;
3269 		break;
3270 	case WI_RID_TX_CRYPT_KEY:
3271 		wreq.wi_val[0] = htole16(ic->ic_wep_txkey);
3272 		wreq.wi_len = 1;
3273 		break;
3274 	case WI_RID_DEFLT_CRYPT_KEYS:
3275 		keys = (struct wi_ltv_keys *)&wreq;
3276 		/* do not show keys to non-root user */
3277 		error = suser(curproc, 0);
3278 		if (error) {
3279 			memset(keys, 0, sizeof(*keys));
3280 			error = 0;
3281 			break;
3282 		}
3283 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3284 			keys->wi_keys[i].wi_keylen =
3285 			    htole16(ic->ic_nw_keys[i].wk_len);
3286 			memcpy(keys->wi_keys[i].wi_keydat,
3287 			    ic->ic_nw_keys[i].wk_key, ic->ic_nw_keys[i].wk_len);
3288 		}
3289 		wreq.wi_len = sizeof(*keys) / 2;
3290 		break;
3291 	case WI_RID_MAX_DATALEN:
3292 		wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN);	/* TODO: frag */
3293 		wreq.wi_len = 1;
3294 		break;
3295 	case WI_RID_IFACE_STATS:
3296 		/* XXX: should be implemented in lower drivers */
3297 		break;
3298 	case WI_RID_READ_APS:
3299 		if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
3300 			for (i = 0; i < IEEE80211_PSCAN_WAIT; i++) {
3301 				tsleep((caddr_t)ic, PWAIT | PCATCH, "i80211",
3302 				    hz);
3303 				if (ic->ic_state != IEEE80211_S_SCAN ||
3304 				    (ic->ic_flags & IEEE80211_F_SCANAP) == 0 ||
3305 				    (ic->ic_flags & IEEE80211_F_ASCAN) == 0)
3306 					break;
3307 			}
3308 			ic->ic_flags &= ~IEEE80211_F_SCANAP;
3309 			memcpy(ic->ic_chan_active, ic->ic_chan_avail,
3310 			    sizeof(ic->ic_chan_active));
3311 		}
3312 		i = 0;
3313 		ap = (void *)((char *)wreq.wi_val + sizeof(i));
3314 		TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
3315 			if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1))
3316 				break;
3317 			memset(ap, 0, sizeof(*ap));
3318 			if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
3319 				IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr);
3320 				ap->namelen = ic->ic_des_esslen;
3321 				if (ic->ic_des_esslen)
3322 					memcpy(ap->name, ic->ic_des_essid,
3323 					    ic->ic_des_esslen);
3324 			} else {
3325 				IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid);
3326 				ap->namelen = ni->ni_esslen;
3327 				if (ni->ni_esslen)
3328 					memcpy(ap->name, ni->ni_essid,
3329 					    ni->ni_esslen);
3330 			}
3331 			ap->channel = ni->ni_chan;
3332 			ap->signal = ni->ni_rssi;
3333 			ap->capinfo = ni->ni_capinfo;
3334 			ap->interval = ni->ni_intval;
3335 			for (j = 0; j < ni->ni_nrate; j++) {
3336 				if (ni->ni_rates[j] & IEEE80211_RATE_BASIC) {
3337 					ap->rate = (ni->ni_rates[j] &
3338 					    IEEE80211_RATE_VAL) * 5; /* XXX */
3339 				}
3340 			}
3341 			i++;
3342 			ap++;
3343 		}
3344 		memcpy(wreq.wi_val, &i, sizeof(i));
3345 		wreq.wi_len = (sizeof(int) + sizeof(*ap) * i) / 2;
3346 		break;
3347 #ifdef WICACHE
3348 	case WI_RID_READ_CACHE:
3349 		i = 0;
3350 		TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
3351 			if (i == MAXWICACHE)
3352 				break;
3353 			IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr);
3354 			memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc));
3355 			wsc.signal = ni->ni_rssi;
3356 			wsc.noise = 0;
3357 			wsc.quality = 0;
3358 			memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
3359 			    &wsc, sizeof(wsc));
3360 			i++;
3361 		}
3362 		wreq.wi_len = sizeof(wsc) * i / 2;
3363 		break;
3364 #endif /* WICACHE */
3365 	case WI_RID_SCAN_APS:
3366 		error = EINVAL;
3367 		break;
3368 	default:
3369 		error = EINVAL;
3370 		break;
3371 	}
3372 	if (error == 0) {
3373 		wreq.wi_len++;
3374 		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
3375 	}
3376 	return (error);
3377 }
3378 
3379 int
ieee80211_cfgset(struct ifnet * ifp,u_long cmd,caddr_t data)3380 ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data)
3381 {
3382 	struct ieee80211com *ic = (void *)ifp;
3383 	int i, j, len, error;
3384 	struct ifreq *ifr = (struct ifreq *)data;
3385 	struct wi_ltv_keys *keys;
3386 	struct wi_req wreq;
3387 	u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)];
3388 
3389 	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
3390 	if (error)
3391 		return (error);
3392 	if (wreq.wi_len-- < 1)
3393 		return (EINVAL);
3394 	switch (wreq.wi_type) {
3395 	case WI_RID_SERIALNO:
3396 	case WI_RID_NODENAME:
3397 		return (EPERM);
3398 	case WI_RID_CURRENT_SSID:
3399 		return (EPERM);
3400 	case WI_RID_OWN_SSID:
3401 	case WI_RID_DESIRED_SSID:
3402 		len = letoh16(wreq.wi_val[0]);
3403 		if (wreq.wi_len < (1 + len + 1) / 2)
3404 			return (EINVAL);
3405 		if (len > IEEE80211_NWID_LEN)
3406 			return (EINVAL);
3407 		ic->ic_des_esslen = len;
3408 		memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid));
3409 		memcpy(ic->ic_des_essid, &wreq.wi_val[1], len);
3410 		error = ENETRESET;
3411 		break;
3412 	case WI_RID_CURRENT_BSSID:
3413 		return (EPERM);
3414 	case WI_RID_OWN_CHNL:
3415 		if (wreq.wi_len != 1)
3416 			return (EINVAL);
3417 		i = letoh16(wreq.wi_val[0]);
3418 		if (i < 0 ||
3419 		    i > IEEE80211_CHAN_MAX ||
3420 		    isclr(ic->ic_chan_active, i))
3421 			return (EINVAL);
3422 		ic->ic_ibss_chan = i;
3423 		if (ic->ic_flags & IEEE80211_F_SIBSS)
3424 			error = ENETRESET;
3425 		break;
3426 	case WI_RID_CURRENT_CHAN:
3427 		return (EPERM);
3428 	case WI_RID_COMMS_QUALITY:
3429 		return (EPERM);
3430 	case WI_RID_PROMISC:
3431 		if (wreq.wi_len != 1)
3432 			return (EINVAL);
3433 		if (ifp->if_flags & IFF_PROMISC) {
3434 			if (wreq.wi_val[0] == 0) {
3435 				ifp->if_flags &= ~IFF_PROMISC;
3436 				error = ENETRESET;
3437 			}
3438 		} else {
3439 			if (wreq.wi_val[0] != 0) {
3440 				ifp->if_flags |= IFF_PROMISC;
3441 				error = ENETRESET;
3442 			}
3443 		}
3444 		break;
3445 	case WI_RID_PORTTYPE:
3446 		if (wreq.wi_len != 1)
3447 			return (EINVAL);
3448 		switch (letoh16(wreq.wi_val[0])) {
3449 		case IEEE80211_M_STA:
3450 			break;
3451 		case IEEE80211_M_IBSS:
3452 			if (!(ic->ic_flags & IEEE80211_F_HASIBSS))
3453 				return (EINVAL);
3454 			break;
3455 		case IEEE80211_M_AHDEMO:
3456 			if (ic->ic_phytype != IEEE80211_T_DS ||
3457 			    !(ic->ic_flags & IEEE80211_F_HASAHDEMO))
3458 				return (EINVAL);
3459 			break;
3460 		case IEEE80211_M_HOSTAP:
3461 			if (!(ic->ic_flags & IEEE80211_F_HASHOSTAP))
3462 				return (EINVAL);
3463 			break;
3464 		default:
3465 			return (EINVAL);
3466 		}
3467 		if (letoh16(wreq.wi_val[0]) != ic->ic_opmode) {
3468 			ic->ic_opmode = letoh16(wreq.wi_val[0]);
3469 			error = ENETRESET;
3470 		}
3471 		break;
3472 	case WI_RID_MAC_NODE:
3473 		if (wreq.wi_len != IEEE80211_ADDR_LEN / 2)
3474 			return (EINVAL);
3475 		IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val);
3476 		/* if_init will copy lladdr into ic_myaddr */
3477 		error = ENETRESET;
3478 		break;
3479 	case WI_RID_TX_RATE:
3480 		if (wreq.wi_len != 1)
3481 			return (EINVAL);
3482 		if (wreq.wi_val[0] == 0) {
3483 			/* auto */
3484 			ic->ic_fixed_rate = -1;
3485 			break;
3486 		}
3487 		for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
3488 			if (letoh16(wreq.wi_val[0]) ==
3489 			    (ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) / 2)
3490 				break;
3491 		}
3492 		if (i == IEEE80211_RATE_SIZE)
3493 			return (EINVAL);
3494 		ic->ic_fixed_rate = i;
3495 		error = ENETRESET;
3496 		break;
3497 	case WI_RID_CUR_TX_RATE:
3498 		return (EPERM);
3499 	case WI_RID_RTS_THRESH:
3500 		if (wreq.wi_len != 1)
3501 			return (EINVAL);
3502 		if (letoh16(wreq.wi_val[0]) != IEEE80211_MAX_LEN)
3503 			return (EINVAL);	/* TODO: RTS */
3504 		break;
3505 	case WI_RID_CREATE_IBSS:
3506 		if (wreq.wi_len != 1)
3507 			return (EINVAL);
3508 		if (wreq.wi_val[0] != 0) {
3509 			if ((ic->ic_flags & IEEE80211_F_HASIBSS) == 0)
3510 				return (EINVAL);
3511 			if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) {
3512 				ic->ic_flags |= IEEE80211_F_IBSSON;
3513 				if (ic->ic_opmode == IEEE80211_M_IBSS &&
3514 				    ic->ic_state == IEEE80211_S_SCAN)
3515 					error = ENETRESET;
3516 			}
3517 		} else {
3518 			if (ic->ic_flags & IEEE80211_F_IBSSON) {
3519 				ic->ic_flags &= ~IEEE80211_F_IBSSON;
3520 				if (ic->ic_flags & IEEE80211_F_SIBSS) {
3521 					ic->ic_flags &= ~IEEE80211_F_SIBSS;
3522 					error = ENETRESET;
3523 				}
3524 			}
3525 		}
3526 		break;
3527 	case WI_RID_MICROWAVE_OVEN:
3528 		if (wreq.wi_len != 1)
3529 			return (EINVAL);
3530 		if (wreq.wi_val[0] != 0)
3531 			return (EINVAL);	/* not supported */
3532 		break;
3533 	case WI_RID_ROAMING_MODE:
3534 		if (wreq.wi_len != 1)
3535 			return EINVAL;
3536 		if (letoh16(wreq.wi_val[0]) != 1)
3537 			return (EINVAL);	/* not supported */
3538 		break;
3539 	case WI_RID_SYSTEM_SCALE:
3540 		if (wreq.wi_len != 1)
3541 			return (EINVAL);
3542 		if (letoh16(wreq.wi_val[0]) != 1)
3543 			return (EINVAL);	/* not supported */
3544 		break;
3545 	case WI_RID_PM_ENABLED:
3546 		if (wreq.wi_len != 1)
3547 			return (EINVAL);
3548 		if (wreq.wi_val[0] != 0) {
3549 			if ((ic->ic_flags & IEEE80211_F_HASPMGT) == 0)
3550 				return (EINVAL);
3551 			if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
3552 				ic->ic_flags |= IEEE80211_F_PMGTON;
3553 				error = ENETRESET;
3554 			}
3555 		} else {
3556 			if (ic->ic_flags & IEEE80211_F_PMGTON) {
3557 				ic->ic_flags &= ~IEEE80211_F_PMGTON;
3558 				error = ENETRESET;
3559 			}
3560 		}
3561 		break;
3562 	case WI_RID_MAX_SLEEP:
3563 		if (wreq.wi_len != 1)
3564 			return (EINVAL);
3565 		ic->ic_lintval = letoh16(wreq.wi_val[0]);
3566 		if (ic->ic_flags & IEEE80211_F_PMGTON)
3567 			error = ENETRESET;
3568 		break;
3569 	case WI_RID_CUR_BEACON_INT:
3570 		return (EPERM);
3571 	case WI_RID_WEP_AVAIL:
3572 		return (EPERM);
3573 	case WI_RID_CNFAUTHMODE:
3574 		if (wreq.wi_len != 1)
3575 			return (EINVAL);
3576 		if (letoh16(wreq.wi_val[0]) != 1)
3577 			return (EINVAL);	/* TODO: shared key auth */
3578 		break;
3579 	case WI_RID_ENCRYPTION:
3580 		if (wreq.wi_len != 1)
3581 			return (EINVAL);
3582 		if (wreq.wi_val[0] != 0) {
3583 			if ((ic->ic_flags & IEEE80211_F_HASWEP) == 0)
3584 				return (EINVAL);
3585 			if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) {
3586 				ic->ic_flags |= IEEE80211_F_WEPON;
3587 				error = ENETRESET;
3588 			}
3589 		} else {
3590 			if (ic->ic_flags & IEEE80211_F_WEPON) {
3591 				ic->ic_flags &= ~IEEE80211_F_WEPON;
3592 				error = ENETRESET;
3593 			}
3594 		}
3595 		break;
3596 	case WI_RID_TX_CRYPT_KEY:
3597 		if (wreq.wi_len != 1)
3598 			return (EINVAL);
3599 		i = letoh16(wreq.wi_val[0]);
3600 		if (i >= IEEE80211_WEP_NKID)
3601 			return (EINVAL);
3602 		ic->ic_wep_txkey = i;
3603 		break;
3604 	case WI_RID_DEFLT_CRYPT_KEYS:
3605 		if (wreq.wi_len != sizeof(struct wi_ltv_keys) / 2)
3606 			return (EINVAL);
3607 		keys = (struct wi_ltv_keys *)&wreq;
3608 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3609 			len = letoh16(keys->wi_keys[i].wi_keylen);
3610 			if (len != 0 && len < IEEE80211_WEP_KEYLEN)
3611 				return (EINVAL);
3612 			if (len > sizeof(ic->ic_nw_keys[i].wk_key))
3613 				return (EINVAL);
3614 		}
3615 		memset(ic->ic_nw_keys, 0, sizeof(ic->ic_nw_keys));
3616 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3617 			len = letoh16(keys->wi_keys[i].wi_keylen);
3618 			ic->ic_nw_keys[i].wk_len = len;
3619 			memcpy(ic->ic_nw_keys[i].wk_key,
3620 			    keys->wi_keys[i].wi_keydat, len);
3621 		}
3622 		error = ENETRESET;
3623 		break;
3624 	case WI_RID_MAX_DATALEN:
3625 		if (wreq.wi_len != 1)
3626 			return (EINVAL);
3627 		len = letoh16(wreq.wi_val[0]);
3628 		if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN)
3629 			return (EINVAL);
3630 		if (len != IEEE80211_MAX_LEN)
3631 			return (EINVAL);	/* TODO: fragment */
3632 		break;
3633 	case WI_RID_IFACE_STATS:
3634 		error = EPERM;
3635 		break;
3636 	case WI_RID_SCAN_APS:
3637 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
3638 			break;
3639 		wreq.wi_len -= 2;	/* XXX: tx rate? */
3640 		/* FALLTHRU */
3641 	case WI_RID_CHANNEL_LIST:
3642 		memset(chanlist, 0, sizeof(chanlist));
3643 		/*
3644 		 * Since channel 0 is not available for DS, channel 1
3645 		 * is assigned to LSB on WaveLAN.
3646 		 */
3647 		if (ic->ic_phytype == IEEE80211_T_DS)
3648 			i = 1;
3649 		else
3650 			i = 0;
3651 		for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
3652 			if (j / 16 >= wreq.wi_len)
3653 				break;
3654 			if (isclr((u_int8_t *)wreq.wi_val, j))
3655 				continue;
3656 			if (isclr(ic->ic_chan_avail, i)) {
3657 				if (wreq.wi_type == WI_RID_CHANNEL_LIST)
3658 					error = EPERM;
3659 				else
3660 					continue;
3661 			}
3662 			setbit(chanlist, i);
3663 		}
3664 		if (error == EPERM && ic->ic_chancheck != NULL)
3665 			error = (*ic->ic_chancheck)(ic->ic_softc, chanlist);
3666 		if (error)
3667 			return (error);
3668 		memcpy(ic->ic_chan_active, chanlist,
3669 		    sizeof(ic->ic_chan_active));
3670 		if (isclr(chanlist, ic->ic_ibss_chan)) {
3671 			for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
3672 				if (isset(chanlist, i)) {
3673 					ic->ic_ibss_chan = i;
3674 					break;
3675 				}
3676 		}
3677 		if (isclr(chanlist, ic->ic_bss.ni_chan))
3678 			ic->ic_bss.ni_chan = ic->ic_ibss_chan;
3679 		if (wreq.wi_type == WI_RID_CHANNEL_LIST)
3680 			error = ENETRESET;
3681 		else {
3682 			ic->ic_flags |= IEEE80211_F_SCANAP;
3683 			error = ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1);
3684 		}
3685 		break;
3686 	default:
3687 		error = EINVAL;
3688 		break;
3689 	}
3690 	return (error);
3691 }
3692