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