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