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