ieee80211_input.c revision 127762
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 127762 2004-04-02 22:47:11Z 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, 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_unref_node(&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
383struct mbuf *
384ieee80211_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 */
486static int
487ieee80211_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
546void
547ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
548	struct ieee80211_node *ni,
549	int subtype, int rssi, u_int32_t rstamp)
550{
551#define	ISPROBE(_st)	((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
552	struct ifnet *ifp = &ic->ic_if;
553	struct ieee80211_frame *wh;
554	u_int8_t *frm, *efrm;
555	u_int8_t *ssid, *rates, *xrates;
556	int reassoc, resp, newassoc, allocbs;
557
558	wh = mtod(m0, struct ieee80211_frame *);
559	frm = (u_int8_t *)&wh[1];
560	efrm = mtod(m0, u_int8_t *) + m0->m_len;
561	switch (subtype) {
562	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
563	case IEEE80211_FC0_SUBTYPE_BEACON: {
564		u_int8_t *tstamp, *bintval, *capinfo, *country;
565		u_int8_t chan, bchan, fhindex, erp;
566		u_int16_t fhdwell;
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
574		/*
575		 * beacon/probe response frame format
576		 *	[8] time stamp
577		 *	[2] beacon interval
578		 *	[2] capability information
579		 *	[tlv] ssid
580		 *	[tlv] supported rates
581		 *	[tlv] country information
582		 *	[tlv] parameter set (FH/DS)
583		 *	[tlv] erp information
584		 *	[tlv] extended supported rates
585		 */
586		IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
587		tstamp  = frm;	frm += 8;
588		bintval = frm;	frm += 2;
589		capinfo = frm;	frm += 2;
590		ssid = rates = xrates = country = NULL;
591		bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
592		chan = bchan;
593		fhdwell = 0;
594		fhindex = 0;
595		erp = 0;
596		while (frm < efrm) {
597			switch (*frm) {
598			case IEEE80211_ELEMID_SSID:
599				ssid = frm;
600				break;
601			case IEEE80211_ELEMID_RATES:
602				rates = frm;
603				break;
604			case IEEE80211_ELEMID_COUNTRY:
605				country = frm;
606				break;
607			case IEEE80211_ELEMID_FHPARMS:
608				if (ic->ic_phytype == IEEE80211_T_FH) {
609					fhdwell = (frm[3] << 8) | frm[2];
610					chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
611					fhindex = frm[6];
612				}
613				break;
614			case IEEE80211_ELEMID_DSPARMS:
615				/*
616				 * XXX hack this since depending on phytype
617				 * is problematic for multi-mode devices.
618				 */
619				if (ic->ic_phytype != IEEE80211_T_FH)
620					chan = frm[2];
621				break;
622			case IEEE80211_ELEMID_TIM:
623				break;
624			case IEEE80211_ELEMID_XRATES:
625				xrates = frm;
626				break;
627			case IEEE80211_ELEMID_ERP:
628				if (frm[1] != 1) {
629					IEEE80211_DPRINTF(("%s: invalid ERP "
630						"element; length %u, expecting "
631						"1\n", __func__, frm[1]));
632					ic->ic_stats.is_rx_elem_toobig++;
633					break;
634				}
635				erp = frm[2];
636				break;
637			default:
638				IEEE80211_DPRINTF2(("%s: element id %u/len %u "
639					"ignored\n", __func__, *frm, frm[1]));
640				ic->ic_stats.is_rx_elem_unknown++;
641				break;
642			}
643			frm += frm[1] + 2;
644		}
645		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
646		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
647		if (
648#if IEEE80211_CHAN_MAX < 255
649		    chan > IEEE80211_CHAN_MAX ||
650#endif
651		    isclr(ic->ic_chan_active, chan)) {
652			IEEE80211_DPRINTF(("%s: ignore %s with invalid channel "
653				"%u\n", __func__,
654				ISPROBE(subtype) ? "probe response" : "beacon",
655				chan));
656			ic->ic_stats.is_rx_badchan++;
657			return;
658		}
659		if (chan != bchan && ic->ic_phytype != IEEE80211_T_FH) {
660			/*
661			 * Frame was received on a channel different from the
662			 * one indicated in the DS params element id;
663			 * silently discard it.
664			 *
665			 * NB: this can happen due to signal leakage.
666			 *     But we should take it for FH phy because
667			 *     the rssi value should be correct even for
668			 *     different hop pattern in FH.
669			 */
670			IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked "
671				"for channel %u\n", __func__,
672				ISPROBE(subtype) ? "probe response" : "beacon",
673				bchan, chan));
674			ic->ic_stats.is_rx_chanmismatch++;
675			return;
676		}
677
678		/*
679		 * Use mac and channel for lookup so we collect all
680		 * potential AP's when scanning.  Otherwise we may
681		 * see the same AP on multiple channels and will only
682		 * record the last one.  We could filter APs here based
683		 * on rssi, etc. but leave that to the end of the scan
684		 * so we can keep the selection criteria in one spot.
685		 * This may result in a bloat of the scanned AP list but
686		 * it shouldn't be too much.
687		 */
688		ni = ieee80211_lookup_node(ic, wh->i_addr2,
689				&ic->ic_channels[chan]);
690#ifdef IEEE80211_DEBUG
691		if (ieee80211_debug &&
692		    (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) {
693			printf("%s: %s%s on chan %u (bss chan %u) ",
694			    __func__, (ni == NULL ? "new " : ""),
695			    ISPROBE(subtype) ? "probe response" : "beacon",
696			    chan, bchan);
697			ieee80211_print_essid(ssid + 2, ssid[1]);
698			printf(" from %s\n", ether_sprintf(wh->i_addr2));
699			printf("%s: caps 0x%x bintval %u erp 0x%x\n",
700				__func__, le16toh(*(u_int16_t *)capinfo),
701				le16toh(*(u_int16_t *)bintval), erp);
702			if (country)
703				printf("%s: country info %*D\n",
704					__func__, country[1], country+2, " ");
705		}
706#endif
707		if (ni == NULL) {
708			ni = ieee80211_alloc_node(ic, wh->i_addr2);
709			if (ni == NULL) {
710				ic->ic_stats.is_rx_nodealloc++;
711				return;
712			}
713			ni->ni_esslen = ssid[1];
714			memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
715			memcpy(ni->ni_essid, ssid + 2, ssid[1]);
716		} else if (ssid[1] != 0 && ISPROBE(subtype)) {
717			/*
718			 * Update ESSID at probe response to adopt hidden AP by
719			 * Lucent/Cisco, which announces null ESSID in beacon.
720			 */
721			ni->ni_esslen = ssid[1];
722			memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
723			memcpy(ni->ni_essid, ssid + 2, ssid[1]);
724		}
725		IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
726		ni->ni_rssi = rssi;
727		ni->ni_rstamp = rstamp;
728		memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
729		ni->ni_intval = le16toh(*(u_int16_t *)bintval);
730		ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo);
731		/* XXX validate channel # */
732		ni->ni_chan = &ic->ic_channels[chan];
733		ni->ni_fhdwell = fhdwell;
734		ni->ni_fhindex = fhindex;
735		ni->ni_erp = erp;
736		/* NB: must be after ni_chan is setup */
737		ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
738		ieee80211_unref_node(&ni);
739		break;
740	}
741
742	case IEEE80211_FC0_SUBTYPE_PROBE_REQ: {
743		u_int8_t rate;
744
745		if (ic->ic_opmode == IEEE80211_M_STA)
746			return;
747		if (ic->ic_state != IEEE80211_S_RUN)
748			return;
749
750		/*
751		 * prreq frame format
752		 *	[tlv] ssid
753		 *	[tlv] supported rates
754		 *	[tlv] extended supported rates
755		 */
756		ssid = rates = xrates = NULL;
757		while (frm < efrm) {
758			switch (*frm) {
759			case IEEE80211_ELEMID_SSID:
760				ssid = frm;
761				break;
762			case IEEE80211_ELEMID_RATES:
763				rates = frm;
764				break;
765			case IEEE80211_ELEMID_XRATES:
766				xrates = frm;
767				break;
768			}
769			frm += frm[1] + 2;
770		}
771		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
772		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
773		if (ssid[1] != 0 &&
774		    (ssid[1] != ic->ic_bss->ni_esslen ||
775		    memcmp(ssid + 2, ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen) != 0)) {
776#ifdef IEEE80211_DEBUG
777			if (ieee80211_debug) {
778				printf("%s: ssid unmatch ", __func__);
779				ieee80211_print_essid(ssid + 2, ssid[1]);
780				printf(" from %s\n", ether_sprintf(wh->i_addr2));
781			}
782#endif
783			ic->ic_stats.is_rx_ssidmismatch++;
784			return;
785		}
786
787		if (ni == ic->ic_bss) {
788			ni = ieee80211_dup_bss(ic, wh->i_addr2);
789			if (ni == NULL) {
790				ic->ic_stats.is_rx_nodealloc++;
791				return;
792			}
793			IEEE80211_DPRINTF(("%s: new req from %s\n",
794				__func__, ether_sprintf(wh->i_addr2)));
795			allocbs = 1;
796		} else
797			allocbs = 0;
798		ni->ni_rssi = rssi;
799		ni->ni_rstamp = rstamp;
800		rate = ieee80211_setup_rates(ic, ni, rates, xrates,
801				IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
802				| IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
803		if (rate & IEEE80211_RATE_BASIC) {
804			IEEE80211_DPRINTF(("%s: rate negotiation failed: %s\n",
805				__func__,ether_sprintf(wh->i_addr2)));
806		} else {
807			IEEE80211_SEND_MGMT(ic, ni,
808				IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
809		}
810		if (allocbs) {
811			/* XXX just use free? */
812			if (ic->ic_opmode == IEEE80211_M_HOSTAP)
813				ieee80211_free_node(ic, ni);
814			else
815				ieee80211_unref_node(&ni);
816		}
817		break;
818	}
819
820	case IEEE80211_FC0_SUBTYPE_AUTH: {
821		u_int16_t algo, seq, status;
822		/*
823		 * auth frame format
824		 *	[2] algorithm
825		 *	[2] sequence
826		 *	[2] status
827		 *	[tlv*] challenge
828		 */
829		IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
830		algo   = le16toh(*(u_int16_t *)frm);
831		seq    = le16toh(*(u_int16_t *)(frm + 2));
832		status = le16toh(*(u_int16_t *)(frm + 4));
833		if (algo != IEEE80211_AUTH_ALG_OPEN) {
834			/* TODO: shared key auth */
835			IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n",
836				__func__, algo, ether_sprintf(wh->i_addr2)));
837			ic->ic_stats.is_rx_auth_unsupported++;
838			return;
839		}
840		switch (ic->ic_opmode) {
841		case IEEE80211_M_IBSS:
842			if (ic->ic_state != IEEE80211_S_RUN || seq != 1) {
843				IEEE80211_DPRINTF(("%s: discard auth from %s; "
844					"state %u, seq %u\n", __func__,
845					ether_sprintf(wh->i_addr2),
846					ic->ic_state, seq));
847				ic->ic_stats.is_rx_bad_auth++;
848				break;
849			}
850			ieee80211_new_state(ic, IEEE80211_S_AUTH,
851			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
852			break;
853
854		case IEEE80211_M_AHDEMO:
855			/* should not come here */
856			break;
857
858		case IEEE80211_M_HOSTAP:
859			if (ic->ic_state != IEEE80211_S_RUN || seq != 1) {
860				IEEE80211_DPRINTF(("%s: discard auth from %s; "
861					"state %u, seq %u\n", __func__,
862					ether_sprintf(wh->i_addr2),
863					ic->ic_state, seq));
864				ic->ic_stats.is_rx_bad_auth++;
865				break;
866			}
867			if (ni == ic->ic_bss) {
868				ni = ieee80211_alloc_node(ic, wh->i_addr2);
869				if (ni == NULL) {
870					ic->ic_stats.is_rx_nodealloc++;
871					return;
872				}
873				IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
874				ni->ni_rssi = rssi;
875				ni->ni_rstamp = rstamp;
876				ni->ni_chan = ic->ic_bss->ni_chan;
877				allocbs = 1;
878			} else
879				allocbs = 0;
880			IEEE80211_SEND_MGMT(ic, ni,
881				IEEE80211_FC0_SUBTYPE_AUTH, 2);
882			if (ifp->if_flags & IFF_DEBUG)
883				if_printf(ifp, "station %s %s authenticated\n",
884				    (allocbs ? "newly" : "already"),
885				    ether_sprintf(ni->ni_macaddr));
886			break;
887
888		case IEEE80211_M_STA:
889			if (ic->ic_state != IEEE80211_S_AUTH || seq != 2) {
890				IEEE80211_DPRINTF(("%s: discard auth from %s; "
891					"state %u, seq %u\n", __func__,
892					ether_sprintf(wh->i_addr2),
893					ic->ic_state, seq));
894				ic->ic_stats.is_rx_bad_auth++;
895				break;
896			}
897			if (status != 0) {
898				if_printf(&ic->ic_if,
899				    "authentication failed (reason %d) for %s\n",
900				    status,
901				    ether_sprintf(wh->i_addr3));
902				if (ni != ic->ic_bss)
903					ni->ni_fails++;
904				ic->ic_stats.is_rx_auth_fail++;
905				return;
906			}
907			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
908			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
909			break;
910		case IEEE80211_M_MONITOR:
911			break;
912		}
913		break;
914	}
915
916	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
917	case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
918		u_int16_t capinfo, bintval;
919
920		if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
921		    (ic->ic_state != IEEE80211_S_RUN))
922			return;
923
924		if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
925			reassoc = 1;
926			resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
927		} else {
928			reassoc = 0;
929			resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
930		}
931		/*
932		 * asreq frame format
933		 *	[2] capability information
934		 *	[2] listen interval
935		 *	[6*] current AP address (reassoc only)
936		 *	[tlv] ssid
937		 *	[tlv] supported rates
938		 *	[tlv] extended supported rates
939		 */
940		IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
941		if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
942			IEEE80211_DPRINTF(("%s: ignore other bss from %s\n",
943				__func__, ether_sprintf(wh->i_addr2)));
944			ic->ic_stats.is_rx_assoc_bss++;
945			return;
946		}
947		capinfo = le16toh(*(u_int16_t *)frm);	frm += 2;
948		bintval = le16toh(*(u_int16_t *)frm);	frm += 2;
949		if (reassoc)
950			frm += 6;	/* ignore current AP info */
951		ssid = rates = xrates = NULL;
952		while (frm < efrm) {
953			switch (*frm) {
954			case IEEE80211_ELEMID_SSID:
955				ssid = frm;
956				break;
957			case IEEE80211_ELEMID_RATES:
958				rates = frm;
959				break;
960			case IEEE80211_ELEMID_XRATES:
961				xrates = frm;
962				break;
963			}
964			frm += frm[1] + 2;
965		}
966		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
967		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
968		if (ssid[1] != ic->ic_bss->ni_esslen ||
969		    memcmp(ssid + 2, ic->ic_bss->ni_essid, ssid[1]) != 0) {
970#ifdef IEEE80211_DEBUG
971			if (ieee80211_debug) {
972				printf("%s: ssid unmatch ", __func__);
973				ieee80211_print_essid(ssid + 2, ssid[1]);
974				printf(" from %s\n", ether_sprintf(wh->i_addr2));
975			}
976#endif
977			ic->ic_stats.is_rx_ssidmismatch++;
978			return;
979		}
980		if (ni == ic->ic_bss) {
981			IEEE80211_DPRINTF(("%s: not authenticated for %s\n",
982				__func__, ether_sprintf(wh->i_addr2)));
983			ni = ieee80211_dup_bss(ic, wh->i_addr2);
984			if (ni != NULL) {
985				IEEE80211_SEND_MGMT(ic, ni,
986				    IEEE80211_FC0_SUBTYPE_DEAUTH,
987				    IEEE80211_REASON_ASSOC_NOT_AUTHED);
988				ieee80211_free_node(ic, ni);
989			}
990			ic->ic_stats.is_rx_assoc_notauth++;
991			return;
992		}
993		/* XXX per-node cipher suite */
994		/* XXX some stations use the privacy bit for handling APs
995		       that suport both encrypted and unencrypted traffic */
996		if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
997		    (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
998		    ((ic->ic_flags & IEEE80211_F_WEPON) ?
999		     IEEE80211_CAPINFO_PRIVACY : 0)) {
1000			IEEE80211_DPRINTF(("%s: capability mismatch %x for %s\n",
1001				__func__, capinfo, ether_sprintf(wh->i_addr2)));
1002			ni->ni_associd = 0;
1003			IEEE80211_SEND_MGMT(ic, ni, resp,
1004				IEEE80211_STATUS_CAPINFO);
1005			ic->ic_stats.is_rx_assoc_capmismatch++;
1006			return;
1007		}
1008		ieee80211_setup_rates(ic, ni, rates, xrates,
1009				IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1010				IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1011		if (ni->ni_rates.rs_nrates == 0) {
1012			IEEE80211_DPRINTF(("%s: rate unmatch for %s\n",
1013				__func__, ether_sprintf(wh->i_addr2)));
1014			ni->ni_associd = 0;
1015			IEEE80211_SEND_MGMT(ic, ni, resp,
1016				IEEE80211_STATUS_BASIC_RATE);
1017			ic->ic_stats.is_rx_assoc_norate++;
1018			return;
1019		}
1020		ni->ni_rssi = rssi;
1021		ni->ni_rstamp = rstamp;
1022		ni->ni_intval = bintval;
1023		ni->ni_capinfo = capinfo;
1024		ni->ni_chan = ic->ic_bss->ni_chan;
1025		ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
1026		ni->ni_fhindex = ic->ic_bss->ni_fhindex;
1027		if (ni->ni_associd == 0) {
1028			/* XXX handle rollover at 2007 */
1029			/* XXX guarantee uniqueness */
1030			ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++;
1031			newassoc = 1;
1032		} else
1033			newassoc = 0;
1034		/* XXX for 11g must turn off short slot time if long
1035	           slot time sta associates */
1036		IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
1037		if (ifp->if_flags & IFF_DEBUG)
1038			if_printf(ifp, "station %s %s associated\n",
1039			    (newassoc ? "newly" : "already"),
1040			    ether_sprintf(ni->ni_macaddr));
1041		/* give driver a chance to setup state like ni_txrate */
1042		if (ic->ic_newassoc)
1043			(*ic->ic_newassoc)(ic, ni, newassoc);
1044		break;
1045	}
1046
1047	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
1048	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: {
1049		u_int16_t status;
1050
1051		if (ic->ic_opmode != IEEE80211_M_STA ||
1052		    ic->ic_state != IEEE80211_S_ASSOC)
1053			return;
1054
1055		/*
1056		 * asresp frame format
1057		 *	[2] capability information
1058		 *	[2] status
1059		 *	[2] association ID
1060		 *	[tlv] supported rates
1061		 *	[tlv] extended supported rates
1062		 */
1063		IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
1064		ni = ic->ic_bss;
1065		ni->ni_capinfo = le16toh(*(u_int16_t *)frm);
1066		frm += 2;
1067
1068		status = le16toh(*(u_int16_t *)frm);
1069		frm += 2;
1070		if (status != 0) {
1071			if_printf(ifp, "association failed (reason %d) for %s\n",
1072			    status, ether_sprintf(wh->i_addr3));
1073			if (ni != ic->ic_bss)
1074				ni->ni_fails++;
1075			ic->ic_stats.is_rx_auth_fail++;
1076			return;
1077		}
1078		ni->ni_associd = le16toh(*(u_int16_t *)frm);
1079		frm += 2;
1080
1081		rates = xrates = NULL;
1082		while (frm < efrm) {
1083			switch (*frm) {
1084			case IEEE80211_ELEMID_RATES:
1085				rates = frm;
1086				break;
1087			case IEEE80211_ELEMID_XRATES:
1088				xrates = frm;
1089				break;
1090			}
1091			frm += frm[1] + 2;
1092		}
1093
1094		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
1095		ieee80211_setup_rates(ic, ni, rates, xrates,
1096				IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1097				IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1098		if (ni->ni_rates.rs_nrates != 0)
1099			ieee80211_new_state(ic, IEEE80211_S_RUN,
1100				wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1101		break;
1102	}
1103
1104	case IEEE80211_FC0_SUBTYPE_DEAUTH: {
1105		u_int16_t reason;
1106		/*
1107		 * deauth frame format
1108		 *	[2] reason
1109		 */
1110		IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1111		reason = le16toh(*(u_int16_t *)frm);
1112		ic->ic_stats.is_rx_deauth++;
1113		switch (ic->ic_opmode) {
1114		case IEEE80211_M_STA:
1115			ieee80211_new_state(ic, IEEE80211_S_AUTH,
1116			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1117			break;
1118		case IEEE80211_M_HOSTAP:
1119			if (ni != ic->ic_bss) {
1120				if (ifp->if_flags & IFF_DEBUG)
1121					if_printf(ifp, "station %s deauthenticated"
1122					    " by peer (reason %d)\n",
1123					    ether_sprintf(ni->ni_macaddr), reason);
1124				/* node will be free'd on return */
1125				ieee80211_unref_node(&ni);
1126			}
1127			break;
1128		default:
1129			break;
1130		}
1131		break;
1132	}
1133
1134	case IEEE80211_FC0_SUBTYPE_DISASSOC: {
1135		u_int16_t reason;
1136		/*
1137		 * disassoc frame format
1138		 *	[2] reason
1139		 */
1140		IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
1141		reason = le16toh(*(u_int16_t *)frm);
1142		ic->ic_stats.is_rx_disassoc++;
1143		switch (ic->ic_opmode) {
1144		case IEEE80211_M_STA:
1145			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
1146			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1147			break;
1148		case IEEE80211_M_HOSTAP:
1149			if (ni != ic->ic_bss) {
1150				if (ifp->if_flags & IFF_DEBUG)
1151					if_printf(ifp, "station %s disassociated"
1152					    " by peer (reason %d)\n",
1153					    ether_sprintf(ni->ni_macaddr), reason);
1154				ni->ni_associd = 0;
1155				/* XXX node reclaimed how? */
1156			}
1157			break;
1158		default:
1159			break;
1160		}
1161		break;
1162	}
1163	default:
1164		IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
1165			"handled\n", __func__, subtype));
1166		ic->ic_stats.is_rx_badsubtype++;
1167		break;
1168	}
1169#undef ISPROBE
1170}
1171#undef IEEE80211_VERIFY_LENGTH
1172#undef IEEE80211_VERIFY_ELEMENT
1173