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