xref: /freebsd/sys/net80211/ieee80211_input.c (revision e0c27215058b5786c78fcfb3963eebe61a989511)
1 /*-
2  * Copyright (c) 2001 Atsushi Onoe
3  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * Alternatively, this software may be distributed under the terms of the
18  * GNU General Public License ("GPL") version 2 as published by the Free
19  * Software Foundation.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include "opt_inet.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/mbuf.h>
41 #include <sys/malloc.h>
42 #include <sys/kernel.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/endian.h>
46 #include <sys/errno.h>
47 #include <sys/bus.h>
48 #include <sys/proc.h>
49 #include <sys/sysctl.h>
50 
51 #include <machine/atomic.h>
52 
53 #include <net/if.h>
54 #include <net/if_dl.h>
55 #include <net/if_media.h>
56 #include <net/if_arp.h>
57 #include <net/ethernet.h>
58 #include <net/if_llc.h>
59 
60 #include <net80211/ieee80211_var.h>
61 
62 #include <net/bpf.h>
63 
64 #ifdef INET
65 #include <netinet/in.h>
66 #include <netinet/if_ether.h>
67 #endif
68 
69 void
70 ieee80211_input(struct ifnet *ifp, struct mbuf *m,
71 	int rssi, u_int32_t rstamp, u_int rantenna)
72 {
73 	struct ieee80211com *ic = (void *)ifp;
74 	struct ieee80211_node *ni = NULL;
75 	struct ieee80211_frame *wh;
76 	struct ether_header *eh;
77 	struct mbuf *m1;
78 	int len;
79 	u_int8_t dir, subtype;
80 	u_int8_t *bssid;
81 	u_int16_t rxseq;
82 
83 	/* trim CRC here for WEP can find its own CRC at the end of packet. */
84 	if (m->m_flags & M_HASFCS) {
85 		m_adj(m, -IEEE80211_CRC_LEN);
86 		m->m_flags &= ~M_HASFCS;
87 	}
88 
89 	wh = mtod(m, struct ieee80211_frame *);
90 	if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
91 	    IEEE80211_FC0_VERSION_0) {
92 		if (ifp->if_flags & IFF_DEBUG)
93 			if_printf(ifp, "receive packet with wrong version: %x\n",
94 			    wh->i_fc[0]);
95 		goto err;
96 	}
97 
98 	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
99 
100 	if (ic->ic_state != IEEE80211_S_SCAN) {
101 		switch (ic->ic_opmode) {
102 		case IEEE80211_M_STA:
103 			ni = ieee80211_ref_node(ic->ic_bss);
104 			if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
105 				IEEE80211_DPRINTF2(("%s: discard frame from "
106 					"bss %s\n", __func__,
107 					ether_sprintf(wh->i_addr2)));
108 				/* not interested in */
109 				ieee80211_unref_node(&ni);
110 				goto out;
111 			}
112 			break;
113 		case IEEE80211_M_IBSS:
114 		case IEEE80211_M_AHDEMO:
115 		case IEEE80211_M_HOSTAP:
116 			if (dir == IEEE80211_FC1_DIR_NODS)
117 				bssid = wh->i_addr3;
118 			else
119 				bssid = wh->i_addr1;
120 			if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) &&
121 			    !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
122 				/* not interested in */
123 				IEEE80211_DPRINTF2(("%s: other bss %s\n",
124 					__func__, ether_sprintf(wh->i_addr3)));
125 				goto out;
126 			}
127 			ni = ieee80211_find_node(ic, wh->i_addr2);
128 			if (ni == NULL) {
129 				IEEE80211_DPRINTF2(("%s: warning, unknown src "
130 					"%s\n", __func__,
131 					ether_sprintf(wh->i_addr2)));
132 				/*
133 				 * NB: Node allocation is handled in the
134 				 * management handling routines.  Just fake
135 				 * up a reference to the hosts's node to do
136 				 * the stuff below.
137 				 */
138 				ni = ieee80211_ref_node(ic->ic_bss);
139 			}
140 			break;
141 		case IEEE80211_M_MONITOR:
142 			/* NB: this should collect everything */
143 			goto out;
144 		default:
145 			/* XXX catch bad values */
146 			break;
147 		}
148 		ni->ni_rssi = rssi;
149 		ni->ni_rstamp = rstamp;
150 		ni->ni_rantenna = rantenna;
151 		rxseq = ni->ni_rxseq;
152 		ni->ni_rxseq =
153 		    le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
154 		/* TODO: fragment */
155 		if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
156 		    rxseq == ni->ni_rxseq) {
157 			/* duplicate, silently discarded */
158 			ieee80211_unref_node(&ni);
159 			goto out;
160 		}
161 		ni->ni_inact = 0;
162 		ieee80211_unref_node(&ni);
163 	}
164 
165 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
166 	case IEEE80211_FC0_TYPE_DATA:
167 		switch (ic->ic_opmode) {
168 		case IEEE80211_M_STA:
169 			if (dir != IEEE80211_FC1_DIR_FROMDS)
170 				goto out;
171 			if ((ifp->if_flags & IFF_SIMPLEX) &&
172 			    IEEE80211_IS_MULTICAST(wh->i_addr1) &&
173 			    IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
174 				/*
175 				 * In IEEE802.11 network, multicast packet
176 				 * sent from me is broadcasted from AP.
177 				 * It should be silently discarded for
178 				 * SIMPLEX interface.
179 				 */
180 				goto out;
181 			}
182 			break;
183 		case IEEE80211_M_IBSS:
184 		case IEEE80211_M_AHDEMO:
185 			if (dir != IEEE80211_FC1_DIR_NODS)
186 				goto out;
187 			break;
188 		case IEEE80211_M_HOSTAP:
189 			if (dir != IEEE80211_FC1_DIR_TODS)
190 				goto out;
191 			/* check if source STA is associated */
192 			ni = ieee80211_find_node(ic, wh->i_addr2);
193 			if (ni == NULL) {
194 				IEEE80211_DPRINTF(("%s: data from unknown src "
195 					"%s\n", __func__,
196 					ether_sprintf(wh->i_addr2)));
197 				ni = ieee80211_dup_bss(ic, wh->i_addr2);
198 				if (ni != NULL) {
199 					IEEE80211_SEND_MGMT(ic, ni,
200 					    IEEE80211_FC0_SUBTYPE_DEAUTH,
201 					    IEEE80211_REASON_NOT_AUTHED);
202 					ieee80211_free_node(ic, ni);
203 				}
204 				goto err;
205 			}
206 			if (ni->ni_associd == 0) {
207 				IEEE80211_DPRINTF(("ieee80211_input: "
208 				    "data from unassoc src %s\n",
209 				    ether_sprintf(wh->i_addr2)));
210 				IEEE80211_SEND_MGMT(ic, ni,
211 				    IEEE80211_FC0_SUBTYPE_DISASSOC,
212 				    IEEE80211_REASON_NOT_ASSOCED);
213 				ieee80211_unref_node(&ni);
214 				goto err;
215 			}
216 			ieee80211_unref_node(&ni);
217 			break;
218 		case IEEE80211_M_MONITOR:
219 			break;
220 		}
221 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
222 			if (ic->ic_flags & IEEE80211_F_WEPON) {
223 				m = ieee80211_wep_crypt(ifp, m, 0);
224 				if (m == NULL)
225 					goto err;
226 				wh = mtod(m, struct ieee80211_frame *);
227 			} else
228 				goto out;
229 		}
230 		/* copy to listener after decrypt */
231 		if (ic->ic_rawbpf)
232 			bpf_mtap(ic->ic_rawbpf, m);
233 		m = ieee80211_decap(ifp, m);
234 		if (m == NULL)
235 			goto err;
236 		ifp->if_ipackets++;
237 
238 		/* perform as a bridge within the AP */
239 		m1 = NULL;
240 		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
241 			eh = mtod(m, struct ether_header *);
242 			if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
243 				m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
244 				if (m1 == NULL)
245 					ifp->if_oerrors++;
246 				else
247 					m1->m_flags |= M_MCAST;
248 			} else {
249 				ni = ieee80211_find_node(ic, eh->ether_dhost);
250 				if (ni != NULL) {
251 					if (ni->ni_associd != 0) {
252 						m1 = m;
253 						m = NULL;
254 					}
255 					ieee80211_unref_node(&ni);
256 				}
257 			}
258 			if (m1 != NULL) {
259 #ifdef ALTQ
260 				if (ALTQ_IS_ENABLED(&ifp->if_snd))
261 					altq_etherclassify(&ifp->if_snd, m1,
262 					    &pktattr);
263 #endif
264 				len = m1->m_pkthdr.len;
265 				IF_ENQUEUE(&ifp->if_snd, m1);
266 				if (m != NULL)
267 					ifp->if_omcasts++;
268 				ifp->if_obytes += len;
269 			}
270 		}
271 		if (m != NULL)
272 			(*ifp->if_input)(ifp, m);
273 		return;
274 
275 	case IEEE80211_FC0_TYPE_MGT:
276 		if (dir != IEEE80211_FC1_DIR_NODS)
277 			goto err;
278 		if (ic->ic_opmode == IEEE80211_M_AHDEMO)
279 			goto out;
280 		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
281 
282 		/* drop frames without interest */
283 		if (ic->ic_state == IEEE80211_S_SCAN) {
284 			if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
285 			    subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
286 				goto out;
287 		} else {
288 			if (ic->ic_opmode != IEEE80211_M_IBSS &&
289 			    subtype == IEEE80211_FC0_SUBTYPE_BEACON)
290 				goto out;
291 		}
292 
293 		if (ifp->if_flags & IFF_DEBUG) {
294 			/* avoid to print too many frames */
295 			int doprint = 0;
296 
297 			switch (subtype) {
298 			case IEEE80211_FC0_SUBTYPE_BEACON:
299 				if (ic->ic_state == IEEE80211_S_SCAN)
300 					doprint = 1;
301 				break;
302 			case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
303 				if (ic->ic_opmode == IEEE80211_M_IBSS)
304 					doprint = 1;
305 				break;
306 			default:
307 				doprint = 1;
308 				break;
309 			}
310 #ifdef IEEE80211_DEBUG
311 			doprint += ieee80211_debug;
312 #endif
313 			if (doprint)
314 				if_printf(ifp, "received %s from %s rssi %d\n",
315 				    ieee80211_mgt_subtype_name[subtype
316 				    >> IEEE80211_FC0_SUBTYPE_SHIFT],
317 				    ether_sprintf(wh->i_addr2), rssi);
318 		}
319 		if (ic->ic_rawbpf)
320 			bpf_mtap(ic->ic_rawbpf, m);
321 		(*ic->ic_recv_mgmt)(ic, m, subtype, rssi, rstamp, rantenna);
322 		m_freem(m);
323 		return;
324 
325 	case IEEE80211_FC0_TYPE_CTL:
326 	default:
327 		IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, wh->i_fc[0]));
328 		/* should not come here */
329 		break;
330 	}
331   err:
332 	ifp->if_ierrors++;
333   out:
334 	if (m != NULL) {
335 		if (ic->ic_rawbpf)
336 			bpf_mtap(ic->ic_rawbpf, m);
337 		m_freem(m);
338 	}
339 }
340 
341 struct mbuf *
342 ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
343 {
344 	struct ether_header *eh;
345 	struct ieee80211_frame wh;
346 	struct llc *llc;
347 
348 	if (m->m_len < sizeof(wh) + sizeof(*llc)) {
349 		m = m_pullup(m, sizeof(wh) + sizeof(*llc));
350 		if (m == NULL)
351 			return NULL;
352 	}
353 	memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
354 	llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
355 	if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
356 	    llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
357 	    llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
358 		m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh));
359 		llc = NULL;
360 	} else {
361 		m_adj(m, sizeof(wh) - sizeof(*eh));
362 	}
363 	eh = mtod(m, struct ether_header *);
364 	switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
365 	case IEEE80211_FC1_DIR_NODS:
366 		IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
367 		IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
368 		break;
369 	case IEEE80211_FC1_DIR_TODS:
370 		IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
371 		IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
372 		break;
373 	case IEEE80211_FC1_DIR_FROMDS:
374 		IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
375 		IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
376 		break;
377 	case IEEE80211_FC1_DIR_DSTODS:
378 		/* not yet supported */
379 		IEEE80211_DPRINTF(("%s: DS to DS\n", __func__));
380 		m_freem(m);
381 		return NULL;
382 	}
383 #ifdef ALIGNED_POINTER
384 	if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
385 		struct mbuf *n, *n0, **np;
386 		caddr_t newdata;
387 		int off, pktlen;
388 
389 		n0 = NULL;
390 		np = &n0;
391 		off = 0;
392 		pktlen = m->m_pkthdr.len;
393 		while (pktlen > off) {
394 			if (n0 == NULL) {
395 				MGETHDR(n, M_DONTWAIT, MT_DATA);
396 				if (n == NULL) {
397 					m_freem(m);
398 					return NULL;
399 				}
400 				M_MOVE_PKTHDR(n, m);
401 				n->m_len = MHLEN;
402 			} else {
403 				MGET(n, M_DONTWAIT, MT_DATA);
404 				if (n == NULL) {
405 					m_freem(m);
406 					m_freem(n0);
407 					return NULL;
408 				}
409 				n->m_len = MLEN;
410 			}
411 			if (pktlen - off >= MINCLSIZE) {
412 				MCLGET(n, M_DONTWAIT);
413 				if (n->m_flags & M_EXT)
414 					n->m_len = n->m_ext.ext_size;
415 			}
416 			if (n0 == NULL) {
417 				newdata =
418 				    (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
419 				    sizeof(*eh);
420 				n->m_len -= newdata - n->m_data;
421 				n->m_data = newdata;
422 			}
423 			if (n->m_len > pktlen - off)
424 				n->m_len = pktlen - off;
425 			m_copydata(m, off, n->m_len, mtod(n, caddr_t));
426 			off += n->m_len;
427 			*np = n;
428 			np = &n->m_next;
429 		}
430 		m_freem(m);
431 		m = n0;
432 	}
433 #endif /* ALIGNED_POINTER */
434 	if (llc != NULL) {
435 		eh = mtod(m, struct ether_header *);
436 		eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
437 	}
438 	return m;
439 }
440 
441 /*
442  * Install received rate set information in the node's state block.
443  */
444 static int
445 ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
446 	u_int8_t *rates, u_int8_t *xrates, int flags)
447 {
448 	struct ieee80211_rateset *rs = &ni->ni_rates;
449 
450 	memset(rs, 0, sizeof(*rs));
451 	rs->rs_nrates = rates[1];
452 	memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);
453 	if (xrates != NULL) {
454 		u_int8_t nxrates;
455 		/*
456 		 * Tack on 11g extended supported rate element.
457 		 */
458 		nxrates = xrates[1];
459 		if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
460 			nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;
461 			IEEE80211_DPRINTF(("%s: extended rate set too large;"
462 				" only using %u of %u rates\n",
463 				__func__, nxrates, xrates[1]));
464 		}
465 		memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
466 		rs->rs_nrates += nxrates;
467 	}
468 	return ieee80211_fix_rate(ic, ni, flags);
469 }
470 
471 /* XXX statistics */
472 /* Verify the existence and length of __elem or get out. */
473 #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do {			\
474 	if ((__elem) == NULL) {						\
475 		IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n",	\
476 			__func__, ieee80211_mgt_subtype_name[subtype >>	\
477 				IEEE80211_FC0_SUBTYPE_SHIFT]));		\
478 		return;							\
479 	}								\
480 	if ((__elem)[1] > (__maxlen)) {					\
481 		IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s "	\
482 			"frame from %s\n", __func__, (__elem)[1],	\
483 			ieee80211_mgt_subtype_name[subtype >>		\
484 				IEEE80211_FC0_SUBTYPE_SHIFT],		\
485 			ether_sprintf(wh->i_addr2)));			\
486 		return;							\
487 	}								\
488 } while (0)
489 
490 #define	IEEE80211_VERIFY_LENGTH(_len, _minlen) do {			\
491 	if ((_len) < (_minlen)) {					\
492 		IEEE80211_DPRINTF(("%s: %s frame too short from %s\n",	\
493 			__func__,					\
494 			ieee80211_mgt_subtype_name[subtype >>		\
495 				IEEE80211_FC0_SUBTYPE_SHIFT],		\
496 			ether_sprintf(wh->i_addr2)));			\
497 		return;							\
498 	}								\
499 } while (0)
500 
501 void
502 ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, int subtype,
503 	int rssi, u_int32_t rstamp, u_int rantenna)
504 {
505 #define	ISPROBE(_st)	((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
506 	struct ifnet *ifp = &ic->ic_if;
507 	struct ieee80211_frame *wh;
508 	struct ieee80211_node *ni;
509 	u_int8_t *frm, *efrm;
510 	u_int8_t *ssid, *rates, *xrates;
511 	int reassoc, resp, newassoc, allocbs;
512 
513 	wh = mtod(m0, struct ieee80211_frame *);
514 	frm = (u_int8_t *)&wh[1];
515 	efrm = mtod(m0, u_int8_t *) + m0->m_len;
516 	switch (subtype) {
517 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
518 	case IEEE80211_FC0_SUBTYPE_BEACON: {
519 		u_int8_t *tstamp, *bintval, *capinfo, *country;
520 		u_int8_t chan, bchan, fhindex, erp;
521 		u_int16_t fhdwell;
522 
523 		if (ic->ic_opmode != IEEE80211_M_IBSS &&
524 		    ic->ic_state != IEEE80211_S_SCAN) {
525 			/* XXX: may be useful for background scan */
526 			return;
527 		}
528 
529 		/*
530 		 * beacon/probe response frame format
531 		 *	[8] time stamp
532 		 *	[2] beacon interval
533 		 *	[2] capability information
534 		 *	[tlv] ssid
535 		 *	[tlv] supported rates
536 		 *	[tlv] country information
537 		 *	[tlv] parameter set (FH/DS)
538 		 *	[tlv] erp information
539 		 *	[tlv] extended supported rates
540 		 */
541 		IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
542 		tstamp  = frm;	frm += 8;
543 		bintval = frm;	frm += 2;
544 		capinfo = frm;	frm += 2;
545 		ssid = rates = xrates = country = NULL;
546 		bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
547 		chan = bchan;
548 		fhdwell = 0;
549 		fhindex = 0;
550 		erp = 0;
551 		while (frm < efrm) {
552 			switch (*frm) {
553 			case IEEE80211_ELEMID_SSID:
554 				ssid = frm;
555 				break;
556 			case IEEE80211_ELEMID_RATES:
557 				rates = frm;
558 				break;
559 			case IEEE80211_ELEMID_COUNTRY:
560 				country = frm;
561 				break;
562 			case IEEE80211_ELEMID_FHPARMS:
563 				if (ic->ic_phytype == IEEE80211_T_FH) {
564 					fhdwell = (frm[3] << 8) | frm[2];
565 					chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
566 					fhindex = frm[6];
567 				}
568 				break;
569 			case IEEE80211_ELEMID_DSPARMS:
570 				/*
571 				 * XXX hack this since depending on phytype
572 				 * is problematic for multi-mode devices.
573 				 */
574 				if (ic->ic_phytype != IEEE80211_T_FH)
575 					chan = frm[2];
576 				break;
577 			case IEEE80211_ELEMID_TIM:
578 				break;
579 			case IEEE80211_ELEMID_XRATES:
580 				xrates = frm;
581 				break;
582 			case IEEE80211_ELEMID_ERP:
583 				if (frm[1] != 1) {
584 					IEEE80211_DPRINTF(("%s: invalid ERP "
585 						"element; length %u, expecting "
586 						"1\n", __func__, frm[1]));
587 					break;
588 				}
589 				erp = frm[2];
590 				break;
591 			default:
592 				IEEE80211_DPRINTF(("%s: element id %u/len %u "
593 					"ignored\n", __func__, *frm, frm[1]));
594 				break;
595 			}
596 			frm += frm[1] + 2;
597 		}
598 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
599 		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
600 		if (
601 #if IEEE80211_CHAN_MAX < 255
602 		    chan > IEEE80211_CHAN_MAX ||
603 #endif
604 		    isclr(ic->ic_chan_active, chan)) {
605 			IEEE80211_DPRINTF(("%s: ignore %s with invalid channel "
606 				"%u\n", __func__,
607 				ISPROBE(subtype) ? "probe response" : "beacon",
608 				chan));
609 			return;
610 		}
611 		if (chan != bchan) {
612 			/*
613 			 * Frame was received on a channel different from the
614 			 * one indicated in the DS/FH params element id;
615 			 * silently discard it.
616 			 *
617 			 * NB: this can happen due to signal leakage.
618 			 */
619 			IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked "
620 				"for channel %u\n", __func__,
621 				ISPROBE(subtype) ? "probe response" : "beacon",
622 				bchan, chan));
623 			/* XXX statistic */
624 			return;
625 		}
626 
627 		/*
628 		 * Use mac and channel for lookup so we collect all
629 		 * potential AP's when scanning.  Otherwise we may
630 		 * see the same AP on multiple channels and will only
631 		 * record the last one.  We could filter APs here based
632 		 * on rssi, etc. but leave that to the end of the scan
633 		 * so we can keep the selection criteria in one spot.
634 		 * This may result in a bloat of the scanned AP list but
635 		 * it shouldn't be too much.
636 		 */
637 		ni = ieee80211_lookup_node(ic, wh->i_addr2,
638 				&ic->ic_channels[chan]);
639 #ifdef IEEE80211_DEBUG
640 		if (ieee80211_debug &&
641 		    (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) {
642 			printf("%s: %s%s on chan %u (bss chan %u) ",
643 			    __func__, (ni == NULL ? "new " : ""),
644 			    ISPROBE(subtype) ? "probe response" : "beacon",
645 			    chan, bchan);
646 			ieee80211_print_essid(ssid + 2, ssid[1]);
647 			printf(" from %s\n", ether_sprintf(wh->i_addr2));
648 			printf("%s: caps 0x%x bintval %u erp 0x%x\n",
649 				__func__, le16toh(*(u_int16_t *)capinfo),
650 				le16toh(*(u_int16_t *)bintval), erp);
651 			if (country)
652 				printf("%s: country info %*D\n",
653 					__func__, country[1], country+2, " ");
654 		}
655 #endif
656 		if (ni == NULL) {
657 			ni = ieee80211_alloc_node(ic, wh->i_addr2);
658 			if (ni == NULL)
659 				return;
660 			ni->ni_esslen = ssid[1];
661 			memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
662 			memcpy(ni->ni_essid, ssid + 2, ssid[1]);
663 		} else if (ssid[1] != 0 && ISPROBE(subtype)) {
664 			/*
665 			 * Update ESSID at probe response to adopt hidden AP by
666 			 * Lucent/Cisco, which announces null ESSID in beacon.
667 			 */
668 			ni->ni_esslen = ssid[1];
669 			memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
670 			memcpy(ni->ni_essid, ssid + 2, ssid[1]);
671 		}
672 		IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
673 		ni->ni_rssi = rssi;
674 		ni->ni_rstamp = rstamp;
675 		ni->ni_rantenna = rantenna;
676 		memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
677 		ni->ni_intval = le16toh(*(u_int16_t *)bintval);
678 		ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo);
679 		/* XXX validate channel # */
680 		ni->ni_chan = &ic->ic_channels[chan];
681 		ni->ni_fhdwell = fhdwell;
682 		ni->ni_fhindex = fhindex;
683 		ni->ni_erp = erp;
684 		/* NB: must be after ni_chan is setup */
685 		ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
686 		ieee80211_unref_node(&ni);
687 		break;
688 	}
689 
690 	case IEEE80211_FC0_SUBTYPE_PROBE_REQ: {
691 		u_int8_t rate;
692 
693 		if (ic->ic_opmode == IEEE80211_M_STA)
694 			return;
695 		if (ic->ic_state != IEEE80211_S_RUN)
696 			return;
697 
698 		/*
699 		 * prreq frame format
700 		 *	[tlv] ssid
701 		 *	[tlv] supported rates
702 		 *	[tlv] extended supported rates
703 		 */
704 		ssid = rates = xrates = NULL;
705 		while (frm < efrm) {
706 			switch (*frm) {
707 			case IEEE80211_ELEMID_SSID:
708 				ssid = frm;
709 				break;
710 			case IEEE80211_ELEMID_RATES:
711 				rates = frm;
712 				break;
713 			case IEEE80211_ELEMID_XRATES:
714 				xrates = frm;
715 				break;
716 			}
717 			frm += frm[1] + 2;
718 		}
719 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
720 		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
721 		if (ssid[1] != 0 &&
722 		    (ssid[1] != ic->ic_bss->ni_esslen ||
723 		    memcmp(ssid + 2, ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen) != 0)) {
724 #ifdef IEEE80211_DEBUG
725 			if (ieee80211_debug) {
726 				printf("%s: ssid unmatch ", __func__);
727 				ieee80211_print_essid(ssid + 2, ssid[1]);
728 				printf(" from %s\n", ether_sprintf(wh->i_addr2));
729 			}
730 #endif
731 			return;
732 		}
733 
734 		ni = ieee80211_find_node(ic, wh->i_addr2);
735 		if (ni == NULL) {
736 			ni = ieee80211_dup_bss(ic, wh->i_addr2);
737 			if (ni == NULL)
738 				return;
739 			IEEE80211_DPRINTF(("%s: new req from %s\n",
740 				__func__, ether_sprintf(wh->i_addr2)));
741 			allocbs = 1;
742 		} else
743 			allocbs = 0;
744 		ni->ni_rssi = rssi;
745 		ni->ni_rstamp = rstamp;
746 		ni->ni_rantenna = rantenna;
747 		rate = ieee80211_setup_rates(ic, ni, rates, xrates,
748 				IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
749 				| IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
750 		if (rate & IEEE80211_RATE_BASIC) {
751 			IEEE80211_DPRINTF(("%s: rate negotiation failed: %s\n",
752 				__func__,ether_sprintf(wh->i_addr2)));
753 		} else {
754 			IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP,
755 			    0);
756 		}
757 		if (allocbs && ic->ic_opmode == IEEE80211_M_HOSTAP)
758 			ieee80211_free_node(ic, ni);
759 		else
760 			ieee80211_unref_node(&ni);
761 		break;
762 	}
763 
764 	case IEEE80211_FC0_SUBTYPE_AUTH: {
765 		u_int16_t algo, seq, status;
766 		/*
767 		 * auth frame format
768 		 *	[2] algorithm
769 		 *	[2] sequence
770 		 *	[2] status
771 		 *	[tlv*] challenge
772 		 */
773 		IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
774 		algo   = le16toh(*(u_int16_t *)frm);
775 		seq    = le16toh(*(u_int16_t *)(frm + 2));
776 		status = le16toh(*(u_int16_t *)(frm + 4));
777 		if (algo != IEEE80211_AUTH_ALG_OPEN) {
778 			/* TODO: shared key auth */
779 			IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n",
780 				__func__, algo, ether_sprintf(wh->i_addr2)));
781 			return;
782 		}
783 		switch (ic->ic_opmode) {
784 		case IEEE80211_M_IBSS:
785 			if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
786 				return;
787 			ieee80211_new_state(ic, IEEE80211_S_AUTH,
788 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
789 			break;
790 
791 		case IEEE80211_M_AHDEMO:
792 			/* should not come here */
793 			break;
794 
795 		case IEEE80211_M_HOSTAP:
796 			if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
797 				return;
798 			allocbs = 0;
799 			ni = ieee80211_find_node(ic, wh->i_addr2);
800 			if (ni == NULL) {
801 				ni = ieee80211_alloc_node(ic, wh->i_addr2);
802 				if (ni == NULL)
803 					return;
804 				IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
805 				ni->ni_rssi = rssi;
806 				ni->ni_rstamp = rstamp;
807 				ni->ni_rantenna = rantenna;
808 				ni->ni_chan = ic->ic_bss->ni_chan;
809 				allocbs = 1;
810 			}
811 			IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2);
812 			if (ifp->if_flags & IFF_DEBUG)
813 				if_printf(ifp, "station %s %s authenticated\n",
814 				    (allocbs ? "newly" : "already"),
815 				    ether_sprintf(ni->ni_macaddr));
816 			ieee80211_unref_node(&ni);
817 			break;
818 
819 		case IEEE80211_M_STA:
820 			if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
821 				return;
822 			if (status != 0) {
823 				if_printf(&ic->ic_if,
824 				    "authentication failed (reason %d) for %s\n",
825 				    status,
826 				    ether_sprintf(wh->i_addr3));
827 				ni = ieee80211_find_node(ic, wh->i_addr2);
828 				if (ni != NULL) {
829 					ni->ni_fails++;
830 					ieee80211_unref_node(&ni);
831 				}
832 				return;
833 			}
834 			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
835 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
836 			break;
837 		case IEEE80211_M_MONITOR:
838 			break;
839 		}
840 		break;
841 	}
842 
843 	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
844 	case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
845 		u_int16_t capinfo, bintval;
846 
847 		if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
848 		    (ic->ic_state != IEEE80211_S_RUN))
849 			return;
850 
851 		if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
852 			reassoc = 1;
853 			resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
854 		} else {
855 			reassoc = 0;
856 			resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
857 		}
858 		/*
859 		 * asreq frame format
860 		 *	[2] capability information
861 		 *	[2] listen interval
862 		 *	[6*] current AP address (reassoc only)
863 		 *	[tlv] ssid
864 		 *	[tlv] supported rates
865 		 *	[tlv] extended supported rates
866 		 */
867 		IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
868 		if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
869 			IEEE80211_DPRINTF(("%s: ignore other bss from %s\n",
870 				__func__, ether_sprintf(wh->i_addr2)));
871 			return;
872 		}
873 		capinfo = le16toh(*(u_int16_t *)frm);	frm += 2;
874 		bintval = le16toh(*(u_int16_t *)frm);	frm += 2;
875 		if (reassoc)
876 			frm += 6;	/* ignore current AP info */
877 		ssid = rates = xrates = NULL;
878 		while (frm < efrm) {
879 			switch (*frm) {
880 			case IEEE80211_ELEMID_SSID:
881 				ssid = frm;
882 				break;
883 			case IEEE80211_ELEMID_RATES:
884 				rates = frm;
885 				break;
886 			case IEEE80211_ELEMID_XRATES:
887 				xrates = frm;
888 				break;
889 			}
890 			frm += frm[1] + 2;
891 		}
892 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
893 		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
894 		if (ssid[1] != ic->ic_bss->ni_esslen ||
895 		    memcmp(ssid + 2, ic->ic_bss->ni_essid, ssid[1]) != 0) {
896 #ifdef IEEE80211_DEBUG
897 			if (ieee80211_debug) {
898 				printf("%s: ssid unmatch ", __func__);
899 				ieee80211_print_essid(ssid + 2, ssid[1]);
900 				printf(" from %s\n", ether_sprintf(wh->i_addr2));
901 			}
902 #endif
903 			return;
904 		}
905 		ni = ieee80211_find_node(ic, wh->i_addr2);
906 		if (ni == NULL) {
907 			IEEE80211_DPRINTF(("%s: not authenticated for %s\n",
908 				__func__, ether_sprintf(wh->i_addr2)));
909 			ni = ieee80211_dup_bss(ic, wh->i_addr2);
910 			if (ni == NULL)
911 				return;
912 			IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
913 			    IEEE80211_REASON_ASSOC_NOT_AUTHED);
914 			ieee80211_free_node(ic, ni);
915 			return;
916 		}
917 		/* XXX per-node cipher suite */
918 		/* XXX some stations use the privacy bit for handling APs
919 		       that suport both encrypted and unencrypted traffic */
920 		if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
921 		    (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
922 		    ((ic->ic_flags & IEEE80211_F_WEPON) ?
923 		     IEEE80211_CAPINFO_PRIVACY : 0)) {
924 			IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n",
925 				__func__, capinfo, ether_sprintf(wh->i_addr2)));
926 			ni->ni_associd = 0;
927 			IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO);
928 			ieee80211_unref_node(&ni);
929 			return;
930 		}
931 		ieee80211_setup_rates(ic, ni, rates, xrates,
932 				IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
933 				IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
934 		if (ni->ni_rates.rs_nrates == 0) {
935 			IEEE80211_DPRINTF(("%s: rate unmatch for %s\n",
936 				__func__, ether_sprintf(wh->i_addr2)));
937 			ni->ni_associd = 0;
938 			IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE);
939 			ieee80211_unref_node(&ni);
940 			return;
941 		}
942 		ni->ni_rssi = rssi;
943 		ni->ni_rstamp = rstamp;
944 		ni->ni_rantenna = rantenna;
945 		ni->ni_intval = bintval;
946 		ni->ni_capinfo = capinfo;
947 		ni->ni_chan = ic->ic_bss->ni_chan;
948 		ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
949 		ni->ni_fhindex = ic->ic_bss->ni_fhindex;
950 		if (ni->ni_associd == 0) {
951 			/* XXX handle rollover at 2007 */
952 			/* XXX guarantee uniqueness */
953 			ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++;
954 			newassoc = 1;
955 		} else
956 			newassoc = 0;
957 		/* XXX for 11g must turn off short slot time if long
958 	           slot time sta associates */
959 		IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
960 		if (ifp->if_flags & IFF_DEBUG)
961 			if_printf(ifp, "station %s %s associated\n",
962 			    (newassoc ? "newly" : "already"),
963 			    ether_sprintf(ni->ni_macaddr));
964 		/* give driver a chance to setup state like ni_txrate */
965 		if (ic->ic_newassoc)
966 			(*ic->ic_newassoc)(ic, ni, newassoc);
967 		ieee80211_unref_node(&ni);
968 		break;
969 	}
970 
971 	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
972 	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: {
973 		u_int16_t status;
974 
975 		if (ic->ic_opmode != IEEE80211_M_STA ||
976 		    ic->ic_state != IEEE80211_S_ASSOC)
977 			return;
978 
979 		/*
980 		 * asresp frame format
981 		 *	[2] capability information
982 		 *	[2] status
983 		 *	[2] association ID
984 		 *	[tlv] supported rates
985 		 *	[tlv] extended supported rates
986 		 */
987 		IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
988 		ni = ic->ic_bss;
989 		ni->ni_capinfo = le16toh(*(u_int16_t *)frm);
990 		frm += 2;
991 
992 		status = le16toh(*(u_int16_t *)frm);
993 		frm += 2;
994 		if (status != 0) {
995 			if_printf(ifp, "association failed (reason %d) for %s\n",
996 			    status, ether_sprintf(wh->i_addr3));
997 			ni = ieee80211_find_node(ic, wh->i_addr2);
998 			if (ni != NULL) {
999 				ni->ni_fails++;
1000 				ieee80211_unref_node(&ni);
1001 			}
1002 			return;
1003 		}
1004 		ni->ni_associd = le16toh(*(u_int16_t *)frm);
1005 		frm += 2;
1006 
1007 		rates = xrates = NULL;
1008 		while (frm < efrm) {
1009 			switch (*frm) {
1010 			case IEEE80211_ELEMID_RATES:
1011 				rates = frm;
1012 				break;
1013 			case IEEE80211_ELEMID_XRATES:
1014 				xrates = frm;
1015 				break;
1016 			}
1017 			frm += frm[1] + 2;
1018 		}
1019 
1020 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_SIZE);
1021 		ieee80211_setup_rates(ic, ni, rates, xrates,
1022 				IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1023 				IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1024 		if (ni->ni_rates.rs_nrates != 0)
1025 			ieee80211_new_state(ic, IEEE80211_S_RUN,
1026 				wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1027 		break;
1028 	}
1029 
1030 	case IEEE80211_FC0_SUBTYPE_DEAUTH: {
1031 		u_int16_t reason;
1032 		/*
1033 		 * deauth frame format
1034 		 *	[2] reason
1035 		 */
1036 		IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1037 		reason = le16toh(*(u_int16_t *)frm);
1038 		switch (ic->ic_opmode) {
1039 		case IEEE80211_M_STA:
1040 			ieee80211_new_state(ic, IEEE80211_S_AUTH,
1041 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1042 			break;
1043 		case IEEE80211_M_HOSTAP:
1044 			ni = ieee80211_find_node(ic, wh->i_addr2);
1045 			if (ni != NULL) {
1046 				if (ifp->if_flags & IFF_DEBUG)
1047 					if_printf(ifp, "station %s deauthenticated"
1048 					    " by peer (reason %d)\n",
1049 					    ether_sprintf(ni->ni_macaddr), reason);
1050 				ieee80211_free_node(ic, ni);
1051 			}
1052 			break;
1053 		default:
1054 			break;
1055 		}
1056 		break;
1057 	}
1058 
1059 	case IEEE80211_FC0_SUBTYPE_DISASSOC: {
1060 		u_int16_t reason;
1061 		/*
1062 		 * disassoc frame format
1063 		 *	[2] reason
1064 		 */
1065 		IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1066 		reason = le16toh(*(u_int16_t *)frm);
1067 		switch (ic->ic_opmode) {
1068 		case IEEE80211_M_STA:
1069 			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
1070 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1071 			break;
1072 		case IEEE80211_M_HOSTAP:
1073 			ni = ieee80211_find_node(ic, wh->i_addr2);
1074 			if (ni != NULL) {
1075 				if (ifp->if_flags & IFF_DEBUG)
1076 					if_printf(ifp, "station %s disassociated"
1077 					    " by peer (reason %d)\n",
1078 					    ether_sprintf(ni->ni_macaddr), reason);
1079 				ni->ni_associd = 0;
1080 				ieee80211_unref_node(&ni);
1081 			}
1082 			break;
1083 		default:
1084 			break;
1085 		}
1086 		break;
1087 	}
1088 	default:
1089 		IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
1090 			"handled\n", __func__, subtype));
1091 		break;
1092 	}
1093 #undef ISPROBE
1094 }
1095 #undef IEEE80211_VERIFY_LENGTH
1096 #undef IEEE80211_VERIFY_ELEMENT
1097