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