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