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