ieee80211_input.c revision 119150
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: head/sys/net80211/ieee80211_input.c 119150 2003-08-19 22:17:04Z sam $");
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 */
79void
80ieee80211_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
334struct mbuf *
335ieee80211_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 */
437static int
438ieee80211_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
494void
495ieee80211_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