ieee80211_sta.c revision 193966
155714Skris/*- 255714Skris * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting 355714Skris * All rights reserved. 455714Skris * 555714Skris * Redistribution and use in source and binary forms, with or without 655714Skris * modification, are permitted provided that the following conditions 755714Skris * are met: 8280304Sjkim * 1. Redistributions of source code must retain the above copyright 955714Skris * notice, this list of conditions and the following disclaimer. 1055714Skris * 2. Redistributions in binary form must reproduce the above copyright 1155714Skris * notice, this list of conditions and the following disclaimer in the 1255714Skris * documentation and/or other materials provided with the distribution. 1355714Skris * 1455714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15280304Sjkim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1655714Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1755714Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1855714Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1955714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2055714Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2155714Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22280304Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2355714Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2455714Skris */ 2555714Skris 2655714Skris#include <sys/cdefs.h> 2755714Skris#ifdef __FreeBSD__ 2855714Skris__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_sta.c 193966 2009-06-11 04:43:42Z sam $"); 2955714Skris#endif 3055714Skris 3155714Skris/* 3255714Skris * IEEE 802.11 Station mode support. 3355714Skris */ 3455714Skris#include "opt_inet.h" 3555714Skris#include "opt_wlan.h" 3655714Skris 37280304Sjkim#include <sys/param.h> 3855714Skris#include <sys/systm.h> 3955714Skris#include <sys/mbuf.h> 40280304Sjkim#include <sys/malloc.h> 4155714Skris#include <sys/kernel.h> 4255714Skris 4355714Skris#include <sys/socket.h> 4455714Skris#include <sys/sockio.h> 4555714Skris#include <sys/endian.h> 4655714Skris#include <sys/errno.h> 4755714Skris#include <sys/proc.h> 4855714Skris#include <sys/sysctl.h> 4955714Skris 5055714Skris#include <net/if.h> 5155714Skris#include <net/if_media.h> 52280304Sjkim#include <net/if_llc.h> 5355714Skris#include <net/ethernet.h> 5455714Skris 5555714Skris#include <net/bpf.h> 5655714Skris 5755714Skris#include <net80211/ieee80211_var.h> 5855714Skris#include <net80211/ieee80211_sta.h> 5955714Skris#include <net80211/ieee80211_input.h> 60280304Sjkim#ifdef IEEE80211_SUPPORT_SUPERG 6155714Skris#include <net80211/ieee80211_superg.h> 62280304Sjkim#endif 63280304Sjkim 64280304Sjkim#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) 65280304Sjkim 66280304Sjkimstatic void sta_vattach(struct ieee80211vap *); 67280304Sjkimstatic void sta_beacon_miss(struct ieee80211vap *); 68280304Sjkimstatic int sta_newstate(struct ieee80211vap *, enum ieee80211_state, int); 6955714Skrisstatic int sta_input(struct ieee80211_node *, struct mbuf *, int, int); 70280304Sjkimstatic void sta_recv_mgmt(struct ieee80211_node *, struct mbuf *, 71110007Smarkm int subtype, int rssi, int nf); 72280304Sjkimstatic void sta_recv_ctl(struct ieee80211_node *, struct mbuf *, int subtype); 73110007Smarkm 74280304Sjkimvoid 75280304Sjkimieee80211_sta_attach(struct ieee80211com *ic) 76280304Sjkim{ 7755714Skris ic->ic_vattach[IEEE80211_M_STA] = sta_vattach; 78280304Sjkim} 79280304Sjkim 80280304Sjkimvoid 81280304Sjkimieee80211_sta_detach(struct ieee80211com *ic) 82280304Sjkim{ 83280304Sjkim} 84110007Smarkm 85280304Sjkimstatic void 86280304Sjkimsta_vdetach(struct ieee80211vap *vap) 87280304Sjkim{ 88280304Sjkim} 8955714Skris 90280304Sjkimstatic void 9155714Skrissta_vattach(struct ieee80211vap *vap) 92280304Sjkim{ 9355714Skris vap->iv_newstate = sta_newstate; 94280304Sjkim vap->iv_input = sta_input; 9555714Skris vap->iv_recv_mgmt = sta_recv_mgmt; 96280304Sjkim vap->iv_recv_ctl = sta_recv_ctl; 97280304Sjkim vap->iv_opdetach = sta_vdetach; 98280304Sjkim vap->iv_bmiss = sta_beacon_miss; 99280304Sjkim} 100280304Sjkim 101280304Sjkim/* 102280304Sjkim * Handle a beacon miss event. The common code filters out 103280304Sjkim * spurious events that can happen when scanning and/or before 104280304Sjkim * reaching RUN state. 105280304Sjkim */ 10655714Skrisstatic void 107280304Sjkimsta_beacon_miss(struct ieee80211vap *vap) 108280304Sjkim{ 109280304Sjkim struct ieee80211com *ic = vap->iv_ic; 110280304Sjkim 111280304Sjkim KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0, ("scanning")); 112280304Sjkim KASSERT(vap->iv_state >= IEEE80211_S_RUN, 113280304Sjkim ("wrong state %s", ieee80211_state_name[vap->iv_state])); 114280304Sjkim 115280304Sjkim IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, 116280304Sjkim "beacon miss, mode %s state %s\n", 117280304Sjkim ieee80211_opmode_name[vap->iv_opmode], 118280304Sjkim ieee80211_state_name[vap->iv_state]); 11955714Skris 120280304Sjkim if (vap->iv_state == IEEE80211_S_CSA) { 12168654Skris /* 12268654Skris * A Channel Switch is pending; assume we missed the 12368654Skris * beacon that would've completed the process and just 124280304Sjkim * force the switch. If we made a mistake we'll not 125280304Sjkim * find the AP on the new channel and fall back to a 126280304Sjkim * normal scan. 127280304Sjkim */ 128280304Sjkim ieee80211_csa_completeswitch(ic); 129280304Sjkim return; 130280304Sjkim } 131280304Sjkim if (++vap->iv_bmiss_count < vap->iv_bmiss_max) { 132280304Sjkim /* 133280304Sjkim * Send a directed probe req before falling back to a 134280304Sjkim * scan; if we receive a response ic_bmiss_count will 135280304Sjkim * be reset. Some cards mistakenly report beacon miss 136280304Sjkim * so this avoids the expensive scan if the ap is 137280304Sjkim * still there. 138280304Sjkim */ 139280304Sjkim ieee80211_send_probereq(vap->iv_bss, vap->iv_myaddr, 140280304Sjkim vap->iv_bss->ni_bssid, vap->iv_bss->ni_bssid, 141280304Sjkim vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen); 142280304Sjkim return; 143280304Sjkim } 144280304Sjkim vap->iv_bmiss_count = 0; 145280304Sjkim vap->iv_stats.is_beacon_miss++; 146280304Sjkim if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) { 147280304Sjkim#ifdef IEEE80211_SUPPORT_SUPERG 148280304Sjkim struct ieee80211com *ic = vap->iv_ic; 149280304Sjkim 150280304Sjkim /* 151280304Sjkim * If we receive a beacon miss interrupt when using 15255714Skris * dynamic turbo, attempt to switch modes before 153280304Sjkim * reassociating. 154280304Sjkim */ 155280304Sjkim if (IEEE80211_ATH_CAP(vap, vap->iv_bss, IEEE80211_NODE_TURBOP)) 156280304Sjkim ieee80211_dturbo_switch(vap, 15755714Skris ic->ic_bsschan->ic_flags ^ IEEE80211_CHAN_TURBO); 158280304Sjkim#endif 159280304Sjkim /* 160280304Sjkim * Try to reassociate before scanning for a new ap. 161280304Sjkim */ 162280304Sjkim ieee80211_new_state(vap, IEEE80211_S_ASSOC, 1); 163280304Sjkim } else { 164280304Sjkim /* 165280304Sjkim * Somebody else is controlling state changes (e.g. 166280304Sjkim * a user-mode app) don't do anything that would 167280304Sjkim * confuse them; just drop into scan mode so they'll 168280304Sjkim * notified of the state change and given control. 169280304Sjkim */ 170280304Sjkim ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 171280304Sjkim } 172280304Sjkim} 173280304Sjkim 174280304Sjkim/* 175280304Sjkim * Handle deauth with reason. We retry only for 176280304Sjkim * the cases where we might succeed. Otherwise 177280304Sjkim * we downgrade the ap and scan. 178280304Sjkim */ 179280304Sjkimstatic void 180280304Sjkimsta_authretry(struct ieee80211vap *vap, struct ieee80211_node *ni, int reason) 18155714Skris{ 182280304Sjkim switch (reason) { 183280304Sjkim case IEEE80211_STATUS_SUCCESS: /* NB: MLME assoc */ 184280304Sjkim case IEEE80211_STATUS_TIMEOUT: 185280304Sjkim case IEEE80211_REASON_ASSOC_EXPIRE: 186280304Sjkim case IEEE80211_REASON_NOT_AUTHED: 187280304Sjkim case IEEE80211_REASON_NOT_ASSOCED: 188280304Sjkim case IEEE80211_REASON_ASSOC_LEAVE: 18955714Skris case IEEE80211_REASON_ASSOC_NOT_AUTHED: 190280304Sjkim IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, 1); 191280304Sjkim break; 192160817Ssimon default: 193280304Sjkim ieee80211_scan_assoc_fail(vap, vap->iv_bss->ni_macaddr, reason); 194280304Sjkim if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) 195280304Sjkim ieee80211_check_scan_current(vap); 196280304Sjkim break; 197280304Sjkim } 198280304Sjkim} 199280304Sjkim 20055714Skris/* 201238405Sjkim * IEEE80211_M_STA vap state machine handler. 202238405Sjkim * This routine handles the main states in the 802.11 protocol. 203280304Sjkim */ 204238405Sjkimstatic int 205238405Sjkimsta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 206238405Sjkim{ 207280304Sjkim struct ieee80211com *ic = vap->iv_ic; 208238405Sjkim struct ieee80211_node *ni; 209238405Sjkim enum ieee80211_state ostate; 210238405Sjkim 211280304Sjkim IEEE80211_LOCK_ASSERT(ic); 212238405Sjkim 213238405Sjkim ostate = vap->iv_state; 214238405Sjkim IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n", 215280304Sjkim __func__, ieee80211_state_name[ostate], 216238405Sjkim ieee80211_state_name[nstate], arg); 217238405Sjkim vap->iv_state = nstate; /* state transition */ 218238405Sjkim callout_stop(&vap->iv_mgtsend); /* XXX callout_drain */ 219280304Sjkim if (ostate != IEEE80211_S_SCAN) 220238405Sjkim ieee80211_cancel_scan(vap); /* background scan */ 221280304Sjkim ni = vap->iv_bss; /* NB: no reference held */ 222280304Sjkim if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) 223194206Ssimon callout_stop(&vap->iv_swbmiss); 224238405Sjkim switch (nstate) { 225194206Ssimon case IEEE80211_S_INIT: 226280304Sjkim switch (ostate) { 227280304Sjkim case IEEE80211_S_SLEEP: 228238405Sjkim /* XXX wakeup */ 229238405Sjkim case IEEE80211_S_RUN: 230238405Sjkim IEEE80211_SEND_MGMT(ni, 231280304Sjkim IEEE80211_FC0_SUBTYPE_DISASSOC, 232238405Sjkim IEEE80211_REASON_ASSOC_LEAVE); 233280304Sjkim ieee80211_sta_leave(ni); 23455714Skris break; 235280304Sjkim case IEEE80211_S_ASSOC: 236280304Sjkim IEEE80211_SEND_MGMT(ni, 237280304Sjkim IEEE80211_FC0_SUBTYPE_DEAUTH, 238280304Sjkim IEEE80211_REASON_AUTH_LEAVE); 239280304Sjkim break; 240280304Sjkim case IEEE80211_S_SCAN: 241280304Sjkim ieee80211_cancel_scan(vap); 242280304Sjkim break; 24355714Skris default: 244280304Sjkim goto invalid; 245280304Sjkim } 246280304Sjkim if (ostate != IEEE80211_S_INIT) { 247160817Ssimon /* NB: optimize INIT -> INIT case */ 248280304Sjkim ieee80211_reset_bss(vap); 249280304Sjkim } 250280304Sjkim if (vap->iv_auth->ia_detach != NULL) 251160817Ssimon vap->iv_auth->ia_detach(vap); 252280304Sjkim break; 253280304Sjkim case IEEE80211_S_SCAN: 254280304Sjkim switch (ostate) { 255280304Sjkim case IEEE80211_S_INIT: 256280304Sjkim /* 257280304Sjkim * Initiate a scan. We can come here as a result 258280304Sjkim * of an IEEE80211_IOC_SCAN_REQ too in which case 259280304Sjkim * the vap will be marked with IEEE80211_FEXT_SCANREQ 260280304Sjkim * and the scan request parameters will be present 261280304Sjkim * in iv_scanreq. Otherwise we do the default. 262280304Sjkim */ 263280304Sjkim if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) { 26455714Skris ieee80211_check_scan(vap, 265280304Sjkim vap->iv_scanreq_flags, 26655714Skris vap->iv_scanreq_duration, 267280304Sjkim vap->iv_scanreq_mindwell, 268280304Sjkim vap->iv_scanreq_maxdwell, 269280304Sjkim vap->iv_scanreq_nssid, vap->iv_scanreq_ssid); 270280304Sjkim vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ; 271280304Sjkim } else 272280304Sjkim ieee80211_check_scan_current(vap); 273280304Sjkim break; 274280304Sjkim case IEEE80211_S_SCAN: 275280304Sjkim case IEEE80211_S_AUTH: 276280304Sjkim case IEEE80211_S_ASSOC: 277280304Sjkim /* 27855714Skris * These can happen either because of a timeout 279110007Smarkm * on an assoc/auth response or because of a 28068654Skris * change in state that requires a reset. For 281280304Sjkim * the former we're called with a non-zero arg 282280304Sjkim * that is the cause for the failure; pass this 283280304Sjkim * to the scan code so it can update state. 284280304Sjkim * Otherwise trigger a new scan unless we're in 285280304Sjkim * manual roaming mode in which case an application 286280304Sjkim * must issue an explicit scan request. 287280304Sjkim */ 288280304Sjkim if (arg != 0) 289280304Sjkim ieee80211_scan_assoc_fail(vap, 290238405Sjkim vap->iv_bss->ni_macaddr, arg); 291238405Sjkim if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) 292280304Sjkim ieee80211_check_scan_current(vap); 293280304Sjkim break; 294110007Smarkm case IEEE80211_S_RUN: /* beacon miss */ 295280304Sjkim /* 296280304Sjkim * Beacon miss. Notify user space and if not 297238405Sjkim * under control of a user application (roaming 298238405Sjkim * manual) kick off a scan to re-connect. 299238405Sjkim */ 300280304Sjkim ieee80211_sta_leave(ni); 301280304Sjkim if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) 302280304Sjkim ieee80211_check_scan_current(vap); 303280304Sjkim break; 304194206Ssimon default: 305280304Sjkim goto invalid; 306238405Sjkim } 307280304Sjkim break; 308280304Sjkim case IEEE80211_S_AUTH: 309280304Sjkim switch (ostate) { 310280304Sjkim case IEEE80211_S_INIT: 311280304Sjkim case IEEE80211_S_SCAN: 312280304Sjkim IEEE80211_SEND_MGMT(ni, 313280304Sjkim IEEE80211_FC0_SUBTYPE_AUTH, 1); 314280304Sjkim break; 315280304Sjkim case IEEE80211_S_AUTH: 316280304Sjkim case IEEE80211_S_ASSOC: 317280304Sjkim switch (arg & 0xff) { 318280304Sjkim case IEEE80211_FC0_SUBTYPE_AUTH: 319280304Sjkim /* ??? */ 320280304Sjkim IEEE80211_SEND_MGMT(ni, 321280304Sjkim IEEE80211_FC0_SUBTYPE_AUTH, 2); 322280304Sjkim break; 323280304Sjkim case IEEE80211_FC0_SUBTYPE_DEAUTH: 324280304Sjkim sta_authretry(vap, ni, arg>>8); 325280304Sjkim break; 326280304Sjkim } 327280304Sjkim break; 328280304Sjkim case IEEE80211_S_RUN: 329280304Sjkim switch (arg & 0xff) { 330280304Sjkim case IEEE80211_FC0_SUBTYPE_AUTH: 331280304Sjkim IEEE80211_SEND_MGMT(ni, 332280304Sjkim IEEE80211_FC0_SUBTYPE_AUTH, 2); 333280304Sjkim vap->iv_state = ostate; /* stay RUN */ 33455714Skris break; 33568654Skris case IEEE80211_FC0_SUBTYPE_DEAUTH: 33668654Skris ieee80211_sta_leave(ni); 33768654Skris if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) { 33868654Skris /* try to reauth */ 339280304Sjkim IEEE80211_SEND_MGMT(ni, 340280304Sjkim IEEE80211_FC0_SUBTYPE_AUTH, 1); 341280304Sjkim } 342280304Sjkim break; 343280304Sjkim } 344280304Sjkim break; 345280304Sjkim default: 346280304Sjkim goto invalid; 347280304Sjkim } 348280304Sjkim break; 34968654Skris case IEEE80211_S_ASSOC: 350280304Sjkim switch (ostate) { 35168654Skris case IEEE80211_S_AUTH: 352280304Sjkim case IEEE80211_S_ASSOC: 35368654Skris IEEE80211_SEND_MGMT(ni, 354280304Sjkim IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 35568654Skris break; 356280304Sjkim case IEEE80211_S_SLEEP: /* cannot happen */ 35768654Skris case IEEE80211_S_RUN: 358280304Sjkim ieee80211_sta_leave(ni); 359110007Smarkm if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) { 360280304Sjkim IEEE80211_SEND_MGMT(ni, arg ? 361160817Ssimon IEEE80211_FC0_SUBTYPE_REASSOC_REQ : 362280304Sjkim IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 363238405Sjkim } 364280304Sjkim break; 365194206Ssimon default: 366280304Sjkim goto invalid; 367194206Ssimon } 368280304Sjkim break; 369238405Sjkim case IEEE80211_S_RUN: 370280304Sjkim if (vap->iv_flags & IEEE80211_F_WPA) { 371238405Sjkim /* XXX validate prerequisites */ 372280304Sjkim } 373280304Sjkim switch (ostate) { 374280304Sjkim case IEEE80211_S_RUN: 375238405Sjkim case IEEE80211_S_CSA: 376280304Sjkim break; 377280304Sjkim case IEEE80211_S_AUTH: /* when join is done in fw */ 37868654Skris case IEEE80211_S_ASSOC: 37968654Skris#ifdef IEEE80211_DEBUG 38068654Skris if (ieee80211_msg_debug(vap)) { 381280304Sjkim ieee80211_note(vap, "%s with %s ssid ", 382280304Sjkim (vap->iv_opmode == IEEE80211_M_STA ? 383280304Sjkim "associated" : "synchronized"), 384280304Sjkim ether_sprintf(ni->ni_bssid)); 385280304Sjkim ieee80211_print_essid(vap->iv_bss->ni_essid, 386280304Sjkim ni->ni_esslen); 387280304Sjkim /* XXX MCS/HT */ 388280304Sjkim printf(" channel %d start %uMb\n", 389280304Sjkim ieee80211_chan2ieee(ic, ic->ic_curchan), 390280304Sjkim IEEE80211_RATE2MBS(ni->ni_txrate)); 391280304Sjkim } 392280304Sjkim#endif 393280304Sjkim ieee80211_scan_assoc_success(vap, ni->ni_macaddr); 394280304Sjkim ieee80211_notify_node_join(ni, 395280304Sjkim arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP); 396280304Sjkim break; 397280304Sjkim case IEEE80211_S_SLEEP: 398280304Sjkim ieee80211_sta_pwrsave(vap, 0); 399280304Sjkim break; 400280304Sjkim default: 401280304Sjkim goto invalid; 402280304Sjkim } 403280304Sjkim ieee80211_sync_curchan(ic); 404238405Sjkim if (ostate != IEEE80211_S_RUN && 405280304Sjkim (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) { 406238405Sjkim /* 407280304Sjkim * Start s/w beacon miss timer for devices w/o 408238405Sjkim * hardware support. We fudge a bit here since 409280304Sjkim * we're doing this in software. 41068654Skris */ 411284285Sjkim vap->iv_swbmiss_period = IEEE80211_TU_TO_TICKS( 412284285Sjkim 2 * vap->iv_bmissthreshold * ni->ni_intval); 413284285Sjkim vap->iv_swbmiss_count = 0; 414238405Sjkim callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period, 415238405Sjkim ieee80211_swbmiss, vap); 416280304Sjkim } 417238405Sjkim /* 418280304Sjkim * When 802.1x is not in use mark the port authorized 419238405Sjkim * at this point so traffic can flow. 420280304Sjkim */ 421238405Sjkim if (ni->ni_authmode != IEEE80211_AUTH_8021X) 422280304Sjkim ieee80211_node_authorize(ni); 423280304Sjkim /* 424280304Sjkim * Fake association when joining an existing bss. 425280304Sjkim */ 42655714Skris if (ic->ic_newassoc != NULL) 427280304Sjkim ic->ic_newassoc(vap->iv_bss, ostate != IEEE80211_S_RUN); 428280304Sjkim break; 429280304Sjkim case IEEE80211_S_CSA: 430280304Sjkim if (ostate != IEEE80211_S_RUN) 431280304Sjkim goto invalid; 432280304Sjkim break; 433280304Sjkim case IEEE80211_S_SLEEP: 434280304Sjkim ieee80211_sta_pwrsave(vap, 0); 435280304Sjkim break; 436280304Sjkim default: 437280304Sjkim invalid: 438280304Sjkim IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, 439280304Sjkim "%s: unexpected state transition %s -> %s\n", __func__, 440280304Sjkim ieee80211_state_name[ostate], ieee80211_state_name[nstate]); 441280304Sjkim break; 442280304Sjkim } 443280304Sjkim return 0; 444280304Sjkim} 44555714Skris 446280304Sjkim/* 447280304Sjkim * Return non-zero if the frame is an echo of a multicast 448280304Sjkim * frame sent by ourself. The dir is known to be DSTODS. 449280304Sjkim */ 450280304Sjkimstatic __inline int 451280304Sjkimisdstods_mcastecho(struct ieee80211vap *vap, const struct ieee80211_frame *wh) 452280304Sjkim{ 453280304Sjkim#define QWH4(wh) ((const struct ieee80211_qosframe_addr4 *)wh) 454280304Sjkim#define WH4(wh) ((const struct ieee80211_frame_addr4 *)wh) 455280304Sjkim const uint8_t *sa; 456280304Sjkim 457280304Sjkim KASSERT(vap->iv_opmode == IEEE80211_M_STA, ("wrong mode")); 458280304Sjkim 459280304Sjkim if (!IEEE80211_IS_MULTICAST(wh->i_addr3)) 460280304Sjkim return 0; 46155714Skris sa = IEEE80211_QOS_HAS_SEQ(wh) ? QWH4(wh)->i_addr4 : WH4(wh)->i_addr4; 46255714Skris return IEEE80211_ADDR_EQ(sa, vap->iv_myaddr); 463280304Sjkim#undef WH4 464280304Sjkim#undef QWH4 465280304Sjkim} 466280304Sjkim 46755714Skris/* 468280304Sjkim * Return non-zero if the frame is an echo of a multicast 469280304Sjkim * frame sent by ourself. The dir is known to be FROMDS. 470280304Sjkim */ 471280304Sjkimstatic __inline int 47272616Skrisisfromds_mcastecho(struct ieee80211vap *vap, const struct ieee80211_frame *wh) 473280304Sjkim{ 474280304Sjkim KASSERT(vap->iv_opmode == IEEE80211_M_STA, ("wrong mode")); 475280304Sjkim 476280304Sjkim if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) 47772616Skris return 0; 478280304Sjkim return IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_myaddr); 479280304Sjkim} 480280304Sjkim 481280304Sjkim/* 48255714Skris * Decide if a received management frame should be 483280304Sjkim * printed when debugging is enabled. This filters some 484280304Sjkim * of the less interesting frames that come frequently 485160817Ssimon * (e.g. beacons). 486280304Sjkim */ 487160817Ssimonstatic __inline int 48855714Skrisdoprint(struct ieee80211vap *vap, int subtype) 489280304Sjkim{ 490280304Sjkim switch (subtype) { 491280304Sjkim case IEEE80211_FC0_SUBTYPE_BEACON: 492280304Sjkim return (vap->iv_ic->ic_flags & IEEE80211_F_SCAN); 49355714Skris case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 494167615Ssimon return 0; 495280304Sjkim } 496280304Sjkim return 1; 497280304Sjkim} 498167615Ssimon 499167615Ssimon/* 500238405Sjkim * Process a received frame. The node associated with the sender 50155714Skris * should be supplied. If nothing was found in the node table then 502238405Sjkim * the caller is assumed to supply a reference to iv_bss instead. 503280304Sjkim * The RSSI and a timestamp are also supplied. The RSSI data is used 504280304Sjkim * during AP scanning to select a AP to associate with; it can have 505280304Sjkim * any units so long as values have consistent units and higher values 50655714Skris * mean ``better signal''. The receive timestamp is currently not used 507167615Ssimon * by the 802.11 layer. 508280304Sjkim */ 509167615Ssimonstatic int 510167615Ssimonsta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) 511167615Ssimon{ 512167615Ssimon#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) 513280304Sjkim#define HAS_SEQ(type) ((type & 0x4) == 0) 51455714Skris struct ieee80211vap *vap = ni->ni_vap; 515280304Sjkim struct ieee80211com *ic = ni->ni_ic; 516167615Ssimon struct ifnet *ifp = vap->iv_ifp; 517167615Ssimon struct ieee80211_frame *wh; 518167615Ssimon struct ieee80211_key *key; 519167615Ssimon struct ether_header *eh; 520238405Sjkim int hdrspace, need_tap; 521280304Sjkim uint8_t dir, type, subtype, qos; 522167615Ssimon uint8_t *bssid; 523280304Sjkim uint16_t rxseq; 524167615Ssimon 525280304Sjkim if (m->m_flags & M_AMPDU_MPDU) { 52655714Skris /* 527280304Sjkim * Fastpath for A-MPDU reorder q resubmission. Frames 528280304Sjkim * w/ M_AMPDU_MPDU marked have already passed through 52955714Skris * here but were received out of order and been held on 530280304Sjkim * the reorder queue. When resubmitted they are marked 531280304Sjkim * with the M_AMPDU_MPDU flag and we can bypass most of 532280304Sjkim * the normal processing. 533280304Sjkim */ 534280304Sjkim wh = mtod(m, struct ieee80211_frame *); 535280304Sjkim type = IEEE80211_FC0_TYPE_DATA; 536280304Sjkim dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; 537280304Sjkim subtype = IEEE80211_FC0_SUBTYPE_QOS; 538280304Sjkim hdrspace = ieee80211_hdrspace(ic, wh); /* XXX optimize? */ 539280304Sjkim goto resubmit_ampdu; 54055714Skris } 541280304Sjkim 542280304Sjkim KASSERT(ni != NULL, ("null node")); 543280304Sjkim ni->ni_inact = ni->ni_inact_reload; 544280304Sjkim 545280304Sjkim need_tap = 1; /* mbuf need to be tapped. */ 546280304Sjkim type = -1; /* undefined */ 547280304Sjkim 548280304Sjkim if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { 549280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, 550280304Sjkim ni->ni_macaddr, NULL, 55155714Skris "too short (1): len %u", m->m_pkthdr.len); 552167615Ssimon vap->iv_stats.is_rx_tooshort++; 553280304Sjkim goto out; 55455714Skris } 555280304Sjkim /* 556280304Sjkim * Bit of a cheat here, we use a pointer for a 3-address 557280304Sjkim * frame format but don't reference fields past outside 558280304Sjkim * ieee80211_frame_min w/o first validating the data is 559280304Sjkim * present. 560280304Sjkim */ 561280304Sjkim wh = mtod(m, struct ieee80211_frame *); 562280304Sjkim 56355714Skris if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != 564280304Sjkim IEEE80211_FC0_VERSION_0) { 565280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, 566110007Smarkm ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", 567280304Sjkim wh->i_fc[0], wh->i_fc[1]); 568280304Sjkim vap->iv_stats.is_rx_badversion++; 569280304Sjkim goto err; 570280304Sjkim } 571280304Sjkim 572280304Sjkim dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; 573280304Sjkim type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 574280304Sjkim subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 575280304Sjkim if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { 576280304Sjkim bssid = wh->i_addr2; 577280304Sjkim if (!IEEE80211_ADDR_EQ(bssid, ni->ni_bssid)) { 57855714Skris /* not interested in */ 579280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, 580280304Sjkim bssid, NULL, "%s", "not to bss"); 581280304Sjkim vap->iv_stats.is_rx_wrongbss++; 582110007Smarkm goto out; 583280304Sjkim } 584280304Sjkim IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); 585280304Sjkim ni->ni_noise = nf; 586280304Sjkim if (HAS_SEQ(type)) { 587280304Sjkim uint8_t tid = ieee80211_gettid(wh); 58855714Skris if (IEEE80211_QOS_HAS_SEQ(wh) && 589280304Sjkim TID_TO_WME_AC(tid) >= WME_AC_VI) 590280304Sjkim ic->ic_wme.wme_hipri_traffic++; 591280304Sjkim rxseq = le16toh(*(uint16_t *)wh->i_seq); 592280304Sjkim if ((ni->ni_flags & IEEE80211_NODE_HT) == 0 && 59355714Skris (wh->i_fc[1] & IEEE80211_FC1_RETRY) && 594280304Sjkim SEQ_LEQ(rxseq, ni->ni_rxseqs[tid])) { 595280304Sjkim /* duplicate, discard */ 596280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, 597194206Ssimon bssid, "duplicate", 598280304Sjkim "seqno <%u,%u> fragno <%u,%u> tid %u", 599280304Sjkim rxseq >> IEEE80211_SEQ_SEQ_SHIFT, 600280304Sjkim ni->ni_rxseqs[tid] >> 601280304Sjkim IEEE80211_SEQ_SEQ_SHIFT, 602280304Sjkim rxseq & IEEE80211_SEQ_FRAG_MASK, 603280304Sjkim ni->ni_rxseqs[tid] & 604280304Sjkim IEEE80211_SEQ_FRAG_MASK, 605280304Sjkim tid); 606280304Sjkim vap->iv_stats.is_rx_dup++; 60755714Skris IEEE80211_NODE_STAT(ni, rx_dup); 608280304Sjkim goto out; 609280304Sjkim } 610280304Sjkim ni->ni_rxseqs[tid] = rxseq; 611280304Sjkim } 612280304Sjkim } 613280304Sjkim 614280304Sjkim switch (type) { 615280304Sjkim case IEEE80211_FC0_TYPE_DATA: 616280304Sjkim hdrspace = ieee80211_hdrspace(ic, wh); 61755714Skris if (m->m_len < hdrspace && 618280304Sjkim (m = m_pullup(m, hdrspace)) == NULL) { 619280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, 620280304Sjkim ni->ni_macaddr, NULL, 621280304Sjkim "data too short: expecting %u", hdrspace); 622280304Sjkim vap->iv_stats.is_rx_tooshort++; 623280304Sjkim goto out; /* XXX */ 624280304Sjkim } 625280304Sjkim /* 626280304Sjkim * Handle A-MPDU re-ordering. If the frame is to be 627280304Sjkim * processed directly then ieee80211_ampdu_reorder 62855714Skris * will return 0; otherwise it has consumed the mbuf 629280304Sjkim * and we should do nothing more with it. 630280304Sjkim */ 63155714Skris if ((m->m_flags & M_AMPDU) && 632280304Sjkim (dir == IEEE80211_FC1_DIR_FROMDS || 633280304Sjkim dir == IEEE80211_FC1_DIR_DSTODS) && 63455714Skris ieee80211_ampdu_reorder(ni, m) != 0) { 635280304Sjkim m = NULL; 636280304Sjkim goto out; 637280304Sjkim } 638280304Sjkim resubmit_ampdu: 639238405Sjkim if (dir == IEEE80211_FC1_DIR_FROMDS) { 640280304Sjkim if ((ifp->if_flags & IFF_SIMPLEX) && 641280304Sjkim isfromds_mcastecho(vap, wh)) { 642280304Sjkim /* 643238405Sjkim * In IEEE802.11 network, multicast 644280304Sjkim * packets sent from "me" are broadcast 645280304Sjkim * from the AP; silently discard for 646280304Sjkim * SIMPLEX interface. 647280304Sjkim */ 64855714Skris IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, 649280304Sjkim wh, "data", "%s", "multicast echo"); 650280304Sjkim vap->iv_stats.is_rx_mcastecho++; 651280304Sjkim goto out; 652280304Sjkim } 65355714Skris if ((vap->iv_flags & IEEE80211_F_DWDS) && 654280304Sjkim IEEE80211_IS_MULTICAST(wh->i_addr1)) { 655280304Sjkim /* 656280304Sjkim * DWDS sta's must drop 3-address mcast frames 657280304Sjkim * as they will be sent separately as a 4-addr 658280304Sjkim * frame. Accepting the 3-addr frame will 65955714Skris * confuse the bridge into thinking the sending 660280304Sjkim * sta is located at the end of WDS link. 661280304Sjkim */ 662280304Sjkim IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, wh, 663280304Sjkim "3-address data", "%s", "DWDS enabled"); 664280304Sjkim vap->iv_stats.is_rx_mcastecho++; 665280304Sjkim goto out; 66655714Skris } 66755714Skris } else if (dir == IEEE80211_FC1_DIR_DSTODS) { 66868654Skris if ((vap->iv_flags & IEEE80211_F_DWDS) == 0) { 669160817Ssimon IEEE80211_DISCARD(vap, 670160817Ssimon IEEE80211_MSG_INPUT, wh, "4-address data", 67168654Skris "%s", "DWDS not enabled"); 672110007Smarkm vap->iv_stats.is_rx_wrongdir++; 67368654Skris goto out; 674160817Ssimon } 67555714Skris if ((ifp->if_flags & IFF_SIMPLEX) && 676280304Sjkim isdstods_mcastecho(vap, wh)) { 67755714Skris /* 67855714Skris * In IEEE802.11 network, multicast 67955714Skris * packets sent from "me" are broadcast 68055714Skris * from the AP; silently discard for 681280304Sjkim * SIMPLEX interface. 682280304Sjkim */ 683280304Sjkim IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, wh, 68455714Skris "4-address data", "%s", "multicast echo"); 685110007Smarkm vap->iv_stats.is_rx_mcastecho++; 686280304Sjkim goto out; 687110007Smarkm } 688280304Sjkim } else { 689280304Sjkim IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, wh, 690110007Smarkm "data", "incorrect dir 0x%x", dir); 691280304Sjkim vap->iv_stats.is_rx_wrongdir++; 692280304Sjkim goto out; 693110007Smarkm } 694280304Sjkim 695280304Sjkim /* 696110007Smarkm * Handle privacy requirements. Note that we 697110007Smarkm * must not be preempted from here until after 698110007Smarkm * we (potentially) call ieee80211_crypto_demic; 699110007Smarkm * otherwise we may violate assumptions in the 700160817Ssimon * crypto cipher modules used to do delayed update 701280304Sjkim * of replay sequence numbers. 702280304Sjkim */ 703160817Ssimon if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 704160817Ssimon if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { 705280304Sjkim /* 706280304Sjkim * Discard encrypted frames when privacy is off. 707160817Ssimon */ 708160817Ssimon IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, 709280304Sjkim wh, "WEP", "%s", "PRIVACY off"); 710280304Sjkim vap->iv_stats.is_rx_noprivacy++; 711110007Smarkm IEEE80211_NODE_STAT(ni, rx_noprivacy); 712280304Sjkim goto out; 713280304Sjkim } 714110007Smarkm key = ieee80211_crypto_decap(ni, m, hdrspace); 715280304Sjkim if (key == NULL) { 716280304Sjkim /* NB: stats+msgs handled in crypto_decap */ 717238405Sjkim IEEE80211_NODE_STAT(ni, rx_wepfail); 718280304Sjkim goto out; 719280304Sjkim } 720280304Sjkim wh = mtod(m, struct ieee80211_frame *); 721110007Smarkm wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 722110007Smarkm } else { 723110007Smarkm /* XXX M_WEP and IEEE80211_F_PRIVACY */ 724110007Smarkm key = NULL; 725110007Smarkm } 726142428Snectar 727280304Sjkim /* 728142428Snectar * Save QoS bits for use below--before we strip the header. 729142428Snectar */ 730142428Snectar if (subtype == IEEE80211_FC0_SUBTYPE_QOS) { 731280304Sjkim qos = (dir == IEEE80211_FC1_DIR_DSTODS) ? 732280304Sjkim ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] : 733142428Snectar ((struct ieee80211_qosframe *)wh)->i_qos[0]; 734142428Snectar } else 735280304Sjkim qos = 0; 736142428Snectar 737280304Sjkim /* 738142428Snectar * Next up, any fragmentation. 739142428Snectar */ 740110007Smarkm if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 741110007Smarkm m = ieee80211_defrag(ni, m, hdrspace); 742110007Smarkm if (m == NULL) { 743110007Smarkm /* Fragment dropped or frame not complete yet */ 744110007Smarkm goto out; 745110007Smarkm } 746110007Smarkm } 747280304Sjkim wh = NULL; /* no longer valid, catch any uses */ 748280304Sjkim 749280304Sjkim /* 750280304Sjkim * Next strip any MSDU crypto bits. 751280304Sjkim */ 752280304Sjkim if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) { 753280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, 754110007Smarkm ni->ni_macaddr, "data", "%s", "demic error"); 755110007Smarkm vap->iv_stats.is_rx_demicfail++; 756110007Smarkm IEEE80211_NODE_STAT(ni, rx_demicfail); 757280304Sjkim goto out; 758280304Sjkim } 759110007Smarkm 760280304Sjkim /* copy to listener after decrypt */ 761110007Smarkm if (ieee80211_radiotap_active_vap(vap)) 762110007Smarkm ieee80211_radiotap_tx(vap, m); 763280304Sjkim need_tap = 0; 764238405Sjkim 765280304Sjkim /* 766280304Sjkim * Finally, strip the 802.11 header. 767280304Sjkim */ 768110007Smarkm m = ieee80211_decap(vap, m, hdrspace); 769142428Snectar if (m == NULL) { 770280304Sjkim /* XXX mask bit to check for both */ 771110007Smarkm /* don't count Null data frames as errors */ 772110007Smarkm if (subtype == IEEE80211_FC0_SUBTYPE_NODATA || 773280304Sjkim subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL) 774280304Sjkim goto out; 775110007Smarkm IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, 776110007Smarkm ni->ni_macaddr, "data", "%s", "decap error"); 777110007Smarkm vap->iv_stats.is_rx_decap++; 778110007Smarkm IEEE80211_NODE_STAT(ni, rx_decap); 779142428Snectar goto err; 780280304Sjkim } 781110007Smarkm eh = mtod(m, struct ether_header *); 782280304Sjkim if (!ieee80211_node_is_authorized(ni)) { 783280304Sjkim /* 784110007Smarkm * Deny any non-PAE frames received prior to 785110007Smarkm * authorization. For open/shared-key 786142428Snectar * authentication the port is mark authorized 787280304Sjkim * after authentication completes. For 802.1x 788110007Smarkm * the port is not marked authorized by the 789280304Sjkim * authenticator until the handshake has completed. 790280304Sjkim */ 791110007Smarkm if (eh->ether_type != htons(ETHERTYPE_PAE)) { 792110007Smarkm IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, 793142428Snectar eh->ether_shost, "data", 794280304Sjkim "unauthorized port: ether type 0x%x len %u", 795110007Smarkm eh->ether_type, m->m_pkthdr.len); 796280304Sjkim vap->iv_stats.is_rx_unauth++; 797280304Sjkim IEEE80211_NODE_STAT(ni, rx_unauth); 798110007Smarkm goto err; 799110007Smarkm } 800142428Snectar } else { 801280304Sjkim /* 802110007Smarkm * When denying unencrypted frames, discard 803280304Sjkim * any non-PAE frames received without encryption. 804280304Sjkim */ 805110007Smarkm if ((vap->iv_flags & IEEE80211_F_DROPUNENC) && 806110007Smarkm (key == NULL && (m->m_flags & M_WEP) == 0) && 807142428Snectar eh->ether_type != htons(ETHERTYPE_PAE)) { 808142428Snectar /* 809142428Snectar * Drop unencrypted frames. 810280304Sjkim */ 811110007Smarkm vap->iv_stats.is_rx_unencrypted++; 812110007Smarkm IEEE80211_NODE_STAT(ni, rx_unencrypted); 813246772Sjkim goto out; 814238405Sjkim } 815238405Sjkim } 816110007Smarkm /* XXX require HT? */ 817110007Smarkm if (qos & IEEE80211_QOS_AMSDU) { 818142428Snectar m = ieee80211_decap_amsdu(ni, m); 819142428Snectar if (m == NULL) 820142428Snectar return IEEE80211_FC0_TYPE_DATA; 821280304Sjkim } else { 822110007Smarkm#ifdef IEEE80211_SUPPORT_SUPERG 823110007Smarkm m = ieee80211_decap_fastframe(vap, ni, m); 824246772Sjkim if (m == NULL) 825238405Sjkim return IEEE80211_FC0_TYPE_DATA; 826110007Smarkm#endif 827110007Smarkm } 828142428Snectar ieee80211_deliver_data(vap, ni, m); 829142428Snectar return IEEE80211_FC0_TYPE_DATA; 830142428Snectar 831280304Sjkim case IEEE80211_FC0_TYPE_MGT: 832110007Smarkm vap->iv_stats.is_rx_mgmt++; 833110007Smarkm IEEE80211_NODE_STAT(ni, rx_mgmt); 834246772Sjkim if (dir != IEEE80211_FC1_DIR_NODS) { 835238405Sjkim IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, 836238405Sjkim wh, "data", "incorrect dir 0x%x", dir); 837280304Sjkim vap->iv_stats.is_rx_wrongdir++; 838238405Sjkim goto err; 839238405Sjkim } 840280304Sjkim if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) { 841280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, 842280304Sjkim ni->ni_macaddr, "mgt", "too short: len %u", 843162914Ssimon m->m_pkthdr.len); 844162914Ssimon vap->iv_stats.is_rx_tooshort++; 845162914Ssimon goto out; 846162914Ssimon } 847162914Ssimon#ifdef IEEE80211_DEBUG 848280304Sjkim if ((ieee80211_msg_debug(vap) && doprint(vap, subtype)) || 849162914Ssimon ieee80211_msg_dumppkts(vap)) { 850162914Ssimon if_printf(ifp, "received %s from %s rssi %d\n", 851162914Ssimon ieee80211_mgt_subtype_name[subtype >> 852162914Ssimon IEEE80211_FC0_SUBTYPE_SHIFT], 853162914Ssimon ether_sprintf(wh->i_addr2), rssi); 854162914Ssimon } 855280304Sjkim#endif 856162914Ssimon if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 857162914Ssimon if (subtype != IEEE80211_FC0_SUBTYPE_AUTH) { 858162914Ssimon /* 859162914Ssimon * Only shared key auth frames with a challenge 860162914Ssimon * should be encrypted, discard all others. 861162914Ssimon */ 862280304Sjkim IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, 863162914Ssimon wh, ieee80211_mgt_subtype_name[subtype >> 864280304Sjkim IEEE80211_FC0_SUBTYPE_SHIFT], 865110007Smarkm "%s", "WEP set but not permitted"); 866280304Sjkim vap->iv_stats.is_rx_mgtdiscard++; /* XXX */ 867194206Ssimon goto out; 868194206Ssimon } 869194206Ssimon if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { 870280304Sjkim /* 871194206Ssimon * Discard encrypted frames when privacy is off. 872280304Sjkim */ 873194206Ssimon IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, 874110007Smarkm wh, "mgt", "%s", "WEP set but PRIVACY off"); 875110007Smarkm vap->iv_stats.is_rx_noprivacy++; 876110007Smarkm goto out; 877280304Sjkim } 878280304Sjkim hdrspace = ieee80211_hdrspace(ic, wh); 879280304Sjkim key = ieee80211_crypto_decap(ni, m, hdrspace); 880280304Sjkim if (key == NULL) { 881280304Sjkim /* NB: stats+msgs handled in crypto_decap */ 882280304Sjkim goto out; 883280304Sjkim } 884110007Smarkm wh = mtod(m, struct ieee80211_frame *); 88559194Skris wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 88659194Skris } 887280304Sjkim vap->iv_recv_mgmt(ni, m, subtype, rssi, nf); 888280304Sjkim goto out; 889280304Sjkim 89055714Skris case IEEE80211_FC0_TYPE_CTL: 891110007Smarkm vap->iv_stats.is_rx_ctl++; 892110007Smarkm IEEE80211_NODE_STAT(ni, rx_ctrl); 89355714Skris vap->iv_recv_ctl(ni, m, subtype); 89455714Skris goto out; 89555714Skris 89655714Skris default: 89755714Skris IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, 898280304Sjkim wh, NULL, "bad frame type 0x%x", type); 899280304Sjkim /* should not come here */ 900280304Sjkim break; 901280304Sjkim } 902280304Sjkimerr: 903280304Sjkim ifp->if_ierrors++; 904238405Sjkimout: 905280304Sjkim if (m != NULL) { 906280304Sjkim if (need_tap && ieee80211_radiotap_active_vap(vap)) 907280304Sjkim ieee80211_radiotap_rx(vap, m); 908280304Sjkim m_freem(m); 909280304Sjkim } 910280304Sjkim return type; 911238405Sjkim#undef SEQ_LEQ 912280304Sjkim} 913280304Sjkim 914280304Sjkimstatic void 915280304Sjkimsta_auth_open(struct ieee80211_node *ni, struct ieee80211_frame *wh, 916280304Sjkim int rssi, int nf, uint16_t seq, uint16_t status) 917280304Sjkim{ 918280304Sjkim struct ieee80211vap *vap = ni->ni_vap; 919280304Sjkim 920280304Sjkim if (ni->ni_authmode == IEEE80211_AUTH_SHARED) { 921280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, 922280304Sjkim ni->ni_macaddr, "open auth", 923280304Sjkim "bad sta auth mode %u", ni->ni_authmode); 924280304Sjkim vap->iv_stats.is_rx_bad_auth++; /* XXX */ 925280304Sjkim return; 926280304Sjkim } 927110007Smarkm if (vap->iv_state != IEEE80211_S_AUTH || 928280304Sjkim seq != IEEE80211_AUTH_OPEN_RESPONSE) { 929110007Smarkm vap->iv_stats.is_rx_bad_auth++; 930280304Sjkim return; 931110007Smarkm } 932280304Sjkim if (status != 0) { 933280304Sjkim IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, 934110007Smarkm ni, "open auth failed (reason %d)", status); 935280304Sjkim vap->iv_stats.is_rx_auth_fail++; 936110007Smarkm vap->iv_stats.is_rx_authfail_code = status; 937280304Sjkim ieee80211_new_state(vap, IEEE80211_S_SCAN, 938280304Sjkim IEEE80211_SCAN_FAIL_STATUS); 939110007Smarkm } else 940280304Sjkim ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0); 941110007Smarkm} 942280304Sjkim 943280304Sjkimstatic void 944160817Ssimonsta_auth_shared(struct ieee80211_node *ni, struct ieee80211_frame *wh, 945280304Sjkim uint8_t *frm, uint8_t *efrm, int rssi, int nf, 946160817Ssimon uint16_t seq, uint16_t status) 947280304Sjkim{ 948110007Smarkm struct ieee80211vap *vap = ni->ni_vap; 949280304Sjkim uint8_t *challenge; 950280304Sjkim int estatus; 951160817Ssimon 952280304Sjkim /* 953280304Sjkim * NB: this can happen as we allow pre-shared key 954280304Sjkim * authentication to be enabled w/o wep being turned 95555714Skris * on so that configuration of these can be done 956280304Sjkim * in any order. It may be better to enforce the 957280304Sjkim * ordering in which case this check would just be 958280304Sjkim * for sanity/consistency. 959280304Sjkim */ 960280304Sjkim if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { 96155714Skris IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, 962160817Ssimon ni->ni_macaddr, "shared key auth", 963160817Ssimon "%s", " PRIVACY is disabled"); 964280304Sjkim estatus = IEEE80211_STATUS_ALG; 965160817Ssimon goto bad; 96655714Skris } 967160817Ssimon /* 968160817Ssimon * Pre-shared key authentication is evil; accept 969238405Sjkim * it only if explicitly configured (it is supported 970280304Sjkim * mainly for compatibility with clients like OS X). 971238405Sjkim */ 972280304Sjkim if (ni->ni_authmode != IEEE80211_AUTH_AUTO && 973238405Sjkim ni->ni_authmode != IEEE80211_AUTH_SHARED) { 974280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, 975238405Sjkim ni->ni_macaddr, "shared key auth", 976238405Sjkim "bad sta auth mode %u", ni->ni_authmode); 977238405Sjkim vap->iv_stats.is_rx_bad_auth++; /* XXX maybe a unique error? */ 97855714Skris estatus = IEEE80211_STATUS_ALG; 97955714Skris goto bad; 98055714Skris } 98155714Skris 98255714Skris challenge = NULL; 98355714Skris if (frm + 1 < efrm) { 98455714Skris if ((frm[1] + 2) > (efrm - frm)) { 985280304Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, 986280304Sjkim ni->ni_macaddr, "shared key auth", 98755714Skris "ie %d/%d too long", 98855714Skris frm[0], (frm[1] + 2) - (efrm - frm)); 98955714Skris vap->iv_stats.is_rx_bad_auth++; 990280304Sjkim estatus = IEEE80211_STATUS_CHALLENGE; 991280304Sjkim goto bad; 99255714Skris } 993280304Sjkim if (*frm == IEEE80211_ELEMID_CHALLENGE) 994280304Sjkim challenge = frm; 995238405Sjkim frm += frm[1] + 2; 996280304Sjkim } 997280304Sjkim switch (seq) { 99855714Skris case IEEE80211_AUTH_SHARED_CHALLENGE: 999280304Sjkim case IEEE80211_AUTH_SHARED_RESPONSE: 1000280304Sjkim if (challenge == NULL) { 100155714Skris IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, 100255714Skris ni->ni_macaddr, "shared key auth", 100355714Skris "%s", "no challenge"); 1004280304Sjkim vap->iv_stats.is_rx_bad_auth++; 1005280304Sjkim estatus = IEEE80211_STATUS_CHALLENGE; 1006238405Sjkim goto bad; 1007238405Sjkim } 1008238405Sjkim if (challenge[1] != IEEE80211_CHALLENGE_LEN) { 1009238405Sjkim IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH, 1010280304Sjkim ni->ni_macaddr, "shared key auth", 1011238405Sjkim "bad challenge len %d", challenge[1]); 1012280304Sjkim vap->iv_stats.is_rx_bad_auth++; 1013238405Sjkim estatus = IEEE80211_STATUS_CHALLENGE; 1014280304Sjkim goto bad; 1015280304Sjkim } 1016110007Smarkm default: 1017280304Sjkim break; 1018280304Sjkim } 1019280304Sjkim if (vap->iv_state != IEEE80211_S_AUTH) 102055714Skris return; 102155714Skris switch (seq) { 1022280304Sjkim case IEEE80211_AUTH_SHARED_PASS: 1023280304Sjkim if (ni->ni_challenge != NULL) { 1024280304Sjkim free(ni->ni_challenge, M_80211_NODE); 1025194206Ssimon ni->ni_challenge = NULL; 1026280304Sjkim } 1027280304Sjkim if (status != 0) { 1028280304Sjkim IEEE80211_NOTE_FRAME(vap, 1029280304Sjkim IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, wh, 1030280304Sjkim "shared key auth failed (reason %d)", status); 1031194206Ssimon vap->iv_stats.is_rx_auth_fail++; 1032238405Sjkim vap->iv_stats.is_rx_authfail_code = status; 1033238405Sjkim return; 1034238405Sjkim } 1035238405Sjkim ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0); 1036280304Sjkim break; 1037238405Sjkim case IEEE80211_AUTH_SHARED_CHALLENGE: 1038238405Sjkim if (!ieee80211_alloc_challenge(ni)) 1039280304Sjkim return; 1040280304Sjkim /* XXX could optimize by passing recvd challenge */ 1041280304Sjkim memcpy(ni->ni_challenge, &challenge[2], challenge[1]); 1042280304Sjkim IEEE80211_SEND_MGMT(ni, 1043238405Sjkim IEEE80211_FC0_SUBTYPE_AUTH, seq + 1); 1044280304Sjkim break; 1045280304Sjkim default: 1046280304Sjkim IEEE80211_DISCARD(vap, IEEE80211_MSG_AUTH, 1047280304Sjkim wh, "shared key auth", "bad seq %d", seq); 1048280304Sjkim vap->iv_stats.is_rx_bad_auth++; 1049280304Sjkim return; 1050238405Sjkim } 1051238405Sjkim return; 1052280304Sjkimbad: 1053280304Sjkim /* 1054280304Sjkim * Kick the state machine. This short-circuits 1055280304Sjkim * using the mgt frame timeout to trigger the 1056280304Sjkim * state transition. 1057280304Sjkim */ 1058280304Sjkim if (vap->iv_state == IEEE80211_S_AUTH) 1059280304Sjkim ieee80211_new_state(vap, IEEE80211_S_SCAN, 1060280304Sjkim IEEE80211_SCAN_FAIL_STATUS); 1061280304Sjkim} 1062280304Sjkim 1063238405Sjkimstatic int 1064280304Sjkimieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm, 1065280304Sjkim const struct ieee80211_frame *wh) 1066280304Sjkim{ 1067280304Sjkim#define MS(_v, _f) (((_v) & _f) >> _f##_S) 1068280304Sjkim struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme; 1069280304Sjkim u_int len = frm[1], qosinfo; 1070280304Sjkim int i; 1071280304Sjkim 1072280304Sjkim if (len < sizeof(struct ieee80211_wme_param)-2) { 1073238405Sjkim IEEE80211_DISCARD_IE(vap, 1074280304Sjkim IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME, 1075280304Sjkim wh, "WME", "too short, len %u", len); 1076280304Sjkim return -1; 1077280304Sjkim } 1078280304Sjkim qosinfo = frm[__offsetof(struct ieee80211_wme_param, param_qosInfo)]; 1079280304Sjkim qosinfo &= WME_QOSINFO_COUNT; 1080280304Sjkim /* XXX do proper check for wraparound */ 1081280304Sjkim if (qosinfo == wme->wme_wmeChanParams.cap_info) 1082280304Sjkim return 0; 1083280304Sjkim frm += __offsetof(struct ieee80211_wme_param, params_acParams); 1084280304Sjkim for (i = 0; i < WME_NUM_AC; i++) { 1085280304Sjkim struct wmeParams *wmep = 1086280304Sjkim &wme->wme_wmeChanParams.cap_wmeParams[i]; 1087280304Sjkim /* NB: ACI not used */ 1088238405Sjkim wmep->wmep_acm = MS(frm[0], WME_PARAM_ACM); 1089238405Sjkim wmep->wmep_aifsn = MS(frm[0], WME_PARAM_AIFSN); 1090280304Sjkim wmep->wmep_logcwmin = MS(frm[1], WME_PARAM_LOGCWMIN); 1091238405Sjkim wmep->wmep_logcwmax = MS(frm[1], WME_PARAM_LOGCWMAX); 1092280304Sjkim wmep->wmep_txopLimit = LE_READ_2(frm+2); 1093280304Sjkim frm += 4; 1094238405Sjkim } 1095280304Sjkim wme->wme_wmeChanParams.cap_info = qosinfo; 1096280304Sjkim return 1; 1097280304Sjkim#undef MS 1098280304Sjkim} 1099280304Sjkim 1100280304Sjkim/* 1101280304Sjkim * Process 11h Channel Switch Announcement (CSA) ie. If this 1102280304Sjkim * is the first CSA then initiate the switch. Otherwise we 1103280304Sjkim * track state and trigger completion and/or cancel of the switch. 1104280304Sjkim * XXX should be public for IBSS use 1105280304Sjkim */ 1106238405Sjkimstatic void 1107280304Sjkimieee80211_parse_csaparams(struct ieee80211vap *vap, uint8_t *frm, 1108280304Sjkim const struct ieee80211_frame *wh) 1109280304Sjkim{ 1110238405Sjkim struct ieee80211com *ic = vap->iv_ic; 1111280304Sjkim const struct ieee80211_csa_ie *csa = 1112280304Sjkim (const struct ieee80211_csa_ie *) frm; 1113238405Sjkim 1114280304Sjkim KASSERT(vap->iv_state >= IEEE80211_S_RUN, 1115280304Sjkim ("state %s", ieee80211_state_name[vap->iv_state])); 1116238405Sjkim 1117280304Sjkim if (csa->csa_mode > 1) { 1118280304Sjkim IEEE80211_DISCARD_IE(vap, 1119238405Sjkim IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH, 1120280304Sjkim wh, "CSA", "invalid mode %u", csa->csa_mode); 1121280304Sjkim return; 1122280304Sjkim } 1123238405Sjkim IEEE80211_LOCK(ic); 1124280304Sjkim if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) { 1125280304Sjkim /* 1126238405Sjkim * Convert the channel number to a channel reference. We 1127280304Sjkim * try first to preserve turbo attribute of the current 1128280304Sjkim * channel then fallback. Note this will not work if the 1129238405Sjkim * CSA specifies a channel that requires a band switch (e.g. 1130280304Sjkim * 11a => 11g). This is intentional as 11h is defined only 1131238405Sjkim * for 5GHz/11a and because the switch does not involve a 1132280304Sjkim * reassociation, protocol state (capabilities, negotated 1133238405Sjkim * rates, etc) may/will be wrong. 1134280304Sjkim */ 1135238405Sjkim struct ieee80211_channel *c = 1136238405Sjkim ieee80211_find_channel_byieee(ic, csa->csa_newchan, 1137280304Sjkim (ic->ic_bsschan->ic_flags & IEEE80211_CHAN_ALLTURBO)); 1138238405Sjkim if (c == NULL) { 1139280304Sjkim c = ieee80211_find_channel_byieee(ic, 1140280304Sjkim csa->csa_newchan, 1141280304Sjkim (ic->ic_bsschan->ic_flags & IEEE80211_CHAN_ALL)); 1142238405Sjkim if (c == NULL) { 1143280304Sjkim IEEE80211_DISCARD_IE(vap, 1144238405Sjkim IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH, 1145280304Sjkim wh, "CSA", "invalid channel %u", 1146238405Sjkim csa->csa_newchan); 1147280304Sjkim goto done; 1148280304Sjkim } 1149280304Sjkim } 1150238405Sjkim#if IEEE80211_CSA_COUNT_MIN > 0 1151280304Sjkim if (csa->csa_count < IEEE80211_CSA_COUNT_MIN) { 1152238405Sjkim /* 1153238405Sjkim * Require at least IEEE80211_CSA_COUNT_MIN count to 1154280304Sjkim * reduce the risk of being redirected by a fabricated 1155238405Sjkim * CSA. If a valid CSA is dropped we'll still get a 1156280304Sjkim * beacon miss when the AP leaves the channel so we'll 1157238405Sjkim * eventually follow to the new channel. 1158238405Sjkim * 1159238405Sjkim * NOTE: this violates the 11h spec that states that 1160238405Sjkim * count may be any value and if 0 then a switch 1161238405Sjkim * should happen asap. 1162238405Sjkim */ 1163238405Sjkim IEEE80211_DISCARD_IE(vap, 1164238405Sjkim IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH, 1165238405Sjkim wh, "CSA", "count %u too small, must be >= %u", 1166238405Sjkim csa->csa_count, IEEE80211_CSA_COUNT_MIN); 1167280304Sjkim goto done; 1168238405Sjkim } 1169280304Sjkim#endif 1170238405Sjkim ieee80211_csa_startswitch(ic, c, csa->csa_mode, csa->csa_count); 1171238405Sjkim } else { 1172238405Sjkim /* 1173238405Sjkim * Validate this ie against the initial CSA. We require 1174238405Sjkim * mode and channel not change and the count must be 1175280304Sjkim * monotonically decreasing. This may be pointless and 1176238405Sjkim * canceling the switch as a result may be too paranoid but 1177238405Sjkim * in the worst case if we drop out of CSA because of this 1178238405Sjkim * and the AP does move then we'll just end up taking a 1179238405Sjkim * beacon miss and scan to find the AP. 1180238405Sjkim * 1181238405Sjkim * XXX may want <= on count as we also process ProbeResp 1182238405Sjkim * frames and those may come in w/ the same count as the 1183238405Sjkim * previous beacon; but doing so leaves us open to a stuck 1184238405Sjkim * count until we add a dead-man timer 1185238405Sjkim */ 1186238405Sjkim if (!(csa->csa_count < ic->ic_csa_count && 1187238405Sjkim csa->csa_mode == ic->ic_csa_mode && 1188280304Sjkim csa->csa_newchan == ieee80211_chan2ieee(ic, ic->ic_csa_newchan))) { 1189280304Sjkim IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_DOTH, wh, 1190238405Sjkim "CSA ie mismatch, initial ie <%d,%d,%d>, " 1191238405Sjkim "this ie <%d,%d,%d>", ic->ic_csa_mode, 1192280304Sjkim ic->ic_csa_newchan, ic->ic_csa_count, 1193280304Sjkim csa->csa_mode, csa->csa_newchan, csa->csa_count); 1194238405Sjkim ieee80211_csa_cancelswitch(ic); 1195238405Sjkim } else { 1196280304Sjkim if (csa->csa_count <= 1) 1197280304Sjkim ieee80211_csa_completeswitch(ic); 1198238405Sjkim else 1199238405Sjkim ic->ic_csa_count = csa->csa_count; 1200280304Sjkim } 1201280304Sjkim } 1202238405Sjkimdone: 1203238405Sjkim IEEE80211_UNLOCK(ic); 1204280304Sjkim} 1205280304Sjkim 1206238405Sjkim/* 1207238405Sjkim * Return non-zero if a background scan may be continued: 1208238405Sjkim * o bg scan is active 1209238405Sjkim * o no channel switch is pending 1210238405Sjkim * o there has not been any traffic recently 1211280304Sjkim * 1212238405Sjkim * Note we do not check if there is an administrative enable; 1213238405Sjkim * this is only done to start the scan. We assume that any 1214238405Sjkim * change in state will be accompanied by a request to cancel 1215238405Sjkim * active scans which will otherwise cause this test to fail. 1216238405Sjkim */ 1217238405Sjkimstatic __inline int 1218238405Sjkimcontbgscan(struct ieee80211vap *vap) 1219238405Sjkim{ 1220238405Sjkim struct ieee80211com *ic = vap->iv_ic; 1221238405Sjkim 1222238405Sjkim return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) && 1223238405Sjkim (ic->ic_flags & IEEE80211_F_CSAPENDING) == 0 && 1224280304Sjkim vap->iv_state == IEEE80211_S_RUN && /* XXX? */ 1225238405Sjkim time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)); 1226238405Sjkim} 1227280304Sjkim 1228280304Sjkim/* 1229238405Sjkim * Return non-zero if a backgrond scan may be started: 1230238405Sjkim * o bg scanning is administratively enabled 1231280304Sjkim * o no channel switch is pending 1232238405Sjkim * o we are not boosted on a dynamic turbo channel 1233238405Sjkim * o there has not been a scan recently 1234280304Sjkim * o there has not been any traffic recently 1235280304Sjkim */ 1236280304Sjkimstatic __inline int 1237238405Sjkimstartbgscan(struct ieee80211vap *vap) 1238238405Sjkim{ 1239280304Sjkim struct ieee80211com *ic = vap->iv_ic; 1240280304Sjkim 1241280304Sjkim return ((vap->iv_flags & IEEE80211_F_BGSCAN) && 1242238405Sjkim (ic->ic_flags & IEEE80211_F_CSAPENDING) == 0 && 1243238405Sjkim#ifdef IEEE80211_SUPPORT_SUPERG 1244280304Sjkim !IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) && 1245280304Sjkim#endif 1246280304Sjkim time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) && 1247280304Sjkim time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)); 1248280304Sjkim} 1249238405Sjkim 1250238405Sjkimstatic void 1251280304Sjkimsta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, 1252280304Sjkim int subtype, int rssi, int nf) 1253280304Sjkim{ 1254280304Sjkim#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP) 1255280304Sjkim#define ISREASSOC(_st) ((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP) 1256280304Sjkim struct ieee80211vap *vap = ni->ni_vap; 1257238405Sjkim struct ieee80211com *ic = ni->ni_ic; 1258238405Sjkim struct ieee80211_frame *wh; 1259280304Sjkim uint8_t *frm, *efrm; 1260280304Sjkim uint8_t *rates, *xrates, *wme, *htcap, *htinfo; 1261280304Sjkim uint8_t rate; 1262280304Sjkim 1263280304Sjkim wh = mtod(m0, struct ieee80211_frame *); 1264280304Sjkim frm = (uint8_t *)&wh[1]; 1265280304Sjkim efrm = mtod(m0, uint8_t *) + m0->m_len; 1266280304Sjkim switch (subtype) { 1267280304Sjkim case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 1268280304Sjkim case IEEE80211_FC0_SUBTYPE_BEACON: { 1269238405Sjkim struct ieee80211_scanparams scan; 1270238405Sjkim /* 1271280304Sjkim * We process beacon/probe response frames: 1272280304Sjkim * o when scanning, or 1273280304Sjkim * o station mode when associated (to collect state 1274280304Sjkim * updates such as 802.11g slot time) 1275280304Sjkim * Frames otherwise received are discarded. 1276280304Sjkim */ 1277238405Sjkim if (!((ic->ic_flags & IEEE80211_F_SCAN) || ni->ni_associd)) { 1278238405Sjkim vap->iv_stats.is_rx_mgtdiscard++; 1279280304Sjkim return; 1280280304Sjkim } 1281280304Sjkim /* XXX probe response in sta mode when !scanning? */ 1282280304Sjkim if (ieee80211_parse_beacon(ni, m0, &scan) != 0) 1283280304Sjkim return; 1284280304Sjkim /* 1285238405Sjkim * Count frame now that we know it's to be processed. 1286238405Sjkim */ 1287280304Sjkim if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) { 1288280304Sjkim vap->iv_stats.is_rx_beacon++; /* XXX remove */ 1289280304Sjkim IEEE80211_NODE_STAT(ni, rx_beacons); 1290280304Sjkim } else 1291280304Sjkim IEEE80211_NODE_STAT(ni, rx_proberesp); 1292280304Sjkim /* 1293238405Sjkim * When operating in station mode, check for state updates. 1294238405Sjkim * Be careful to ignore beacons received while doing a 1295280304Sjkim * background scan. We consider only 11g/WMM stuff right now. 1296280304Sjkim */ 1297280304Sjkim if (ni->ni_associd != 0 && 1298280304Sjkim ((ic->ic_flags & IEEE80211_F_SCAN) == 0 || 1299280304Sjkim IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))) { 1300280304Sjkim /* record tsf of last beacon */ 1301238405Sjkim memcpy(ni->ni_tstamp.data, scan.tstamp, 1302238405Sjkim sizeof(ni->ni_tstamp)); 1303280304Sjkim /* count beacon frame for s/w bmiss handling */ 1304280304Sjkim vap->iv_swbmiss_count++; 1305280304Sjkim vap->iv_bmiss_count = 0; 1306280304Sjkim if (ni->ni_erp != scan.erp) { 1307238405Sjkim IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ASSOC, 1308238405Sjkim wh->i_addr2, 1309280304Sjkim "erp change: was 0x%x, now 0x%x", 1310280304Sjkim ni->ni_erp, scan.erp); 1311280304Sjkim if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && 1312280304Sjkim (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION)) 1313280304Sjkim ic->ic_flags |= IEEE80211_F_USEPROT; 1314238405Sjkim else 1315246772Sjkim ic->ic_flags &= ~IEEE80211_F_USEPROT; 1316246772Sjkim ni->ni_erp = scan.erp; 131755714Skris /* XXX statistic */ 1318280304Sjkim /* XXX driver notification */ 1319280304Sjkim } 132055714Skris if ((ni->ni_capinfo ^ scan.capinfo) & IEEE80211_CAPINFO_SHORT_SLOTTIME) { 132155714Skris IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ASSOC, 132289840Skris wh->i_addr2, 132355714Skris "capabilities change: was 0x%x, now 0x%x", 132455714Skris ni->ni_capinfo, scan.capinfo); 132555714Skris /* 132655714Skris * NB: we assume short preamble doesn't 1327280304Sjkim * change dynamically 1328280304Sjkim */ 1329280304Sjkim ieee80211_set_shortslottime(ic, 1330280304Sjkim IEEE80211_IS_CHAN_A(ic->ic_bsschan) || 1331280304Sjkim (scan.capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)); 1332280304Sjkim ni->ni_capinfo = (ni->ni_capinfo &~ IEEE80211_CAPINFO_SHORT_SLOTTIME) 1333280304Sjkim | (scan.capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME); 1334280304Sjkim /* XXX statistic */ 1335280304Sjkim } 1336280304Sjkim if (scan.wme != NULL && 1337280304Sjkim (ni->ni_flags & IEEE80211_NODE_QOS) && 1338280304Sjkim ieee80211_parse_wmeparams(vap, scan.wme, wh) > 0) 1339280304Sjkim ieee80211_wme_updateparams(vap); 1340280304Sjkim#ifdef IEEE80211_SUPPORT_SUPERG 1341280304Sjkim if (scan.ath != NULL) 1342280304Sjkim ieee80211_parse_athparams(ni, scan.ath, wh); 1343280304Sjkim#endif 1344280304Sjkim if (scan.htcap != NULL && scan.htinfo != NULL && 1345280304Sjkim (vap->iv_flags_ht & IEEE80211_FHT_HT)) { 1346280304Sjkim ieee80211_ht_updateparams(ni, 1347280304Sjkim scan.htcap, scan.htinfo); 1348280304Sjkim /* XXX state changes? */ 1349280304Sjkim } 1350280304Sjkim if (scan.tim != NULL) { 1351280304Sjkim struct ieee80211_tim_ie *tim = 1352280304Sjkim (struct ieee80211_tim_ie *) scan.tim; 1353280304Sjkim#if 0 1354280304Sjkim int aid = IEEE80211_AID(ni->ni_associd); 1355280304Sjkim int ix = aid / NBBY; 1356280304Sjkim int min = tim->tim_bitctl &~ 1; 1357280304Sjkim int max = tim->tim_len + min - 4; 1358280304Sjkim if ((tim->tim_bitctl&1) || 1359280304Sjkim (min <= ix && ix <= max && 1360280304Sjkim isset(tim->tim_bitmap - min, aid))) { 1361280304Sjkim /* 1362280304Sjkim * XXX Do not let bg scan kick off 1363280304Sjkim * we are expecting data. 1364280304Sjkim */ 1365280304Sjkim ic->ic_lastdata = ticks; 1366280304Sjkim ieee80211_sta_pwrsave(vap, 0); 1367280304Sjkim } 1368280304Sjkim#endif 1369280304Sjkim ni->ni_dtim_count = tim->tim_count; 1370280304Sjkim ni->ni_dtim_period = tim->tim_period; 1371280304Sjkim } 1372280304Sjkim if (scan.csa != NULL && 1373280304Sjkim (vap->iv_flags & IEEE80211_F_DOTH)) 1374280304Sjkim ieee80211_parse_csaparams(vap, scan.csa, wh); 1375280304Sjkim else if (ic->ic_flags & IEEE80211_F_CSAPENDING) { 1376280304Sjkim /* 1377280304Sjkim * No CSA ie or 11h disabled, but a channel 1378280304Sjkim * switch is pending; drop out so we aren't 1379280304Sjkim * stuck in CSA state. If the AP really is 1380280304Sjkim * moving we'll get a beacon miss and scan. 1381280304Sjkim */ 1382280304Sjkim IEEE80211_LOCK(ic); 1383280304Sjkim ieee80211_csa_cancelswitch(ic); 1384280304Sjkim IEEE80211_UNLOCK(ic); 1385280304Sjkim } 1386280304Sjkim /* 1387280304Sjkim * If scanning, pass the info to the scan module. 1388280304Sjkim * Otherwise, check if it's the right time to do 1389280304Sjkim * a background scan. Background scanning must 1390280304Sjkim * be enabled and we must not be operating in the 1391280304Sjkim * turbo phase of dynamic turbo mode. Then, 1392280304Sjkim * it's been a while since the last background 1393280304Sjkim * scan and if no data frames have come through 1394280304Sjkim * recently, kick off a scan. Note that this 1395280304Sjkim * is the mechanism by which a background scan 1396280304Sjkim * is started _and_ continued each time we 1397280304Sjkim * return on-channel to receive a beacon from 1398280304Sjkim * our ap. 1399280304Sjkim */ 1400280304Sjkim if (ic->ic_flags & IEEE80211_F_SCAN) { 1401280304Sjkim ieee80211_add_scan(vap, &scan, wh, 1402280304Sjkim subtype, rssi, nf); 1403280304Sjkim } else if (contbgscan(vap)) { 140455714Skris ieee80211_bg_scan(vap, 0); 140555714Skris } else if (startbgscan(vap)) { 1406280304Sjkim vap->iv_stats.is_scan_bg++; 1407280304Sjkim#if 0 1408280304Sjkim /* wakeup if we are sleeing */ 1409280304Sjkim ieee80211_set_pwrsave(vap, 0); 1410280304Sjkim#endif 1411280304Sjkim ieee80211_bg_scan(vap, 0); 1412280304Sjkim } 1413280304Sjkim return; 1414280304Sjkim } 1415280304Sjkim /* 1416280304Sjkim * If scanning, just pass information to the scan module. 1417280304Sjkim */ 1418280304Sjkim if (ic->ic_flags & IEEE80211_F_SCAN) { 1419280304Sjkim if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) { 1420280304Sjkim /* 1421280304Sjkim * Actively scanning a channel marked passive; 1422280304Sjkim * send a probe request now that we know there 1423280304Sjkim * is 802.11 traffic present. 1424280304Sjkim * 1425280304Sjkim * XXX check if the beacon we recv'd gives 1426280304Sjkim * us what we need and suppress the probe req 1427280304Sjkim */ 1428280304Sjkim ieee80211_probe_curchan(vap, 1); 1429280304Sjkim ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN; 1430280304Sjkim } 1431280304Sjkim ieee80211_add_scan(vap, &scan, wh, subtype, rssi, nf); 1432280304Sjkim return; 1433280304Sjkim } 1434280304Sjkim break; 1435280304Sjkim } 1436280304Sjkim 1437280304Sjkim case IEEE80211_FC0_SUBTYPE_AUTH: { 1438280304Sjkim uint16_t algo, seq, status; 1439280304Sjkim /* 1440280304Sjkim * auth frame format 1441280304Sjkim * [2] algorithm 1442280304Sjkim * [2] sequence 1443280304Sjkim * [2] status 1444280304Sjkim * [tlv*] challenge 1445280304Sjkim */ 1446280304Sjkim IEEE80211_VERIFY_LENGTH(efrm - frm, 6, return); 1447280304Sjkim algo = le16toh(*(uint16_t *)frm); 1448280304Sjkim seq = le16toh(*(uint16_t *)(frm + 2)); 1449280304Sjkim status = le16toh(*(uint16_t *)(frm + 4)); 1450280304Sjkim IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_AUTH, wh->i_addr2, 1451280304Sjkim "recv auth frame with algorithm %d seq %d", algo, seq); 1452280304Sjkim 1453280304Sjkim if (vap->iv_flags & IEEE80211_F_COUNTERM) { 1454280304Sjkim IEEE80211_DISCARD(vap, 1455280304Sjkim IEEE80211_MSG_AUTH | IEEE80211_MSG_CRYPTO, 1456280304Sjkim wh, "auth", "%s", "TKIP countermeasures enabled"); 1457280304Sjkim vap->iv_stats.is_rx_auth_countermeasures++; 1458280304Sjkim if (vap->iv_opmode == IEEE80211_M_HOSTAP) { 1459280304Sjkim ieee80211_send_error(ni, wh->i_addr2, 1460280304Sjkim IEEE80211_FC0_SUBTYPE_AUTH, 1461280304Sjkim IEEE80211_REASON_MIC_FAILURE); 1462280304Sjkim } 1463280304Sjkim return; 1464280304Sjkim } 1465280304Sjkim if (algo == IEEE80211_AUTH_ALG_SHARED) 1466280304Sjkim sta_auth_shared(ni, wh, frm + 6, efrm, rssi, nf, 1467280304Sjkim seq, status); 1468280304Sjkim else if (algo == IEEE80211_AUTH_ALG_OPEN) 1469280304Sjkim sta_auth_open(ni, wh, rssi, nf, seq, status); 1470280304Sjkim else { 1471280304Sjkim IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, 1472280304Sjkim wh, "auth", "unsupported alg %d", algo); 1473280304Sjkim vap->iv_stats.is_rx_auth_unsupported++; 1474280304Sjkim return; 1475280304Sjkim } 147655714Skris break; 147755714Skris } 147855714Skris 147955714Skris case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 148055714Skris case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: { 1481 uint16_t capinfo, associd; 1482 uint16_t status; 1483 1484 if (vap->iv_state != IEEE80211_S_ASSOC) { 1485 vap->iv_stats.is_rx_mgtdiscard++; 1486 return; 1487 } 1488 1489 /* 1490 * asresp frame format 1491 * [2] capability information 1492 * [2] status 1493 * [2] association ID 1494 * [tlv] supported rates 1495 * [tlv] extended supported rates 1496 * [tlv] WME 1497 * [tlv] HT capabilities 1498 * [tlv] HT info 1499 */ 1500 IEEE80211_VERIFY_LENGTH(efrm - frm, 6, return); 1501 ni = vap->iv_bss; 1502 capinfo = le16toh(*(uint16_t *)frm); 1503 frm += 2; 1504 status = le16toh(*(uint16_t *)frm); 1505 frm += 2; 1506 if (status != 0) { 1507 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ASSOC, 1508 wh->i_addr2, "%sassoc failed (reason %d)", 1509 ISREASSOC(subtype) ? "re" : "", status); 1510 vap->iv_stats.is_rx_auth_fail++; /* XXX */ 1511 return; 1512 } 1513 associd = le16toh(*(uint16_t *)frm); 1514 frm += 2; 1515 1516 rates = xrates = wme = htcap = htinfo = NULL; 1517 while (efrm - frm > 1) { 1518 IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return); 1519 switch (*frm) { 1520 case IEEE80211_ELEMID_RATES: 1521 rates = frm; 1522 break; 1523 case IEEE80211_ELEMID_XRATES: 1524 xrates = frm; 1525 break; 1526 case IEEE80211_ELEMID_HTCAP: 1527 htcap = frm; 1528 break; 1529 case IEEE80211_ELEMID_HTINFO: 1530 htinfo = frm; 1531 break; 1532 case IEEE80211_ELEMID_VENDOR: 1533 if (iswmeoui(frm)) 1534 wme = frm; 1535 else if (vap->iv_flags_ht & IEEE80211_FHT_HTCOMPAT) { 1536 /* 1537 * Accept pre-draft HT ie's if the 1538 * standard ones have not been seen. 1539 */ 1540 if (ishtcapoui(frm)) { 1541 if (htcap == NULL) 1542 htcap = frm; 1543 } else if (ishtinfooui(frm)) { 1544 if (htinfo == NULL) 1545 htcap = frm; 1546 } 1547 } 1548 /* XXX Atheros OUI support */ 1549 break; 1550 } 1551 frm += frm[1] + 2; 1552 } 1553 1554 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, return); 1555 if (xrates != NULL) 1556 IEEE80211_VERIFY_ELEMENT(xrates, 1557 IEEE80211_RATE_MAXSIZE - rates[1], return); 1558 rate = ieee80211_setup_rates(ni, rates, xrates, 1559 IEEE80211_F_JOIN | 1560 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | 1561 IEEE80211_F_DONEGO | IEEE80211_F_DODEL); 1562 if (rate & IEEE80211_RATE_BASIC) { 1563 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ASSOC, 1564 wh->i_addr2, 1565 "%sassoc failed (rate set mismatch)", 1566 ISREASSOC(subtype) ? "re" : ""); 1567 vap->iv_stats.is_rx_assoc_norate++; 1568 ieee80211_new_state(vap, IEEE80211_S_SCAN, 1569 IEEE80211_SCAN_FAIL_STATUS); 1570 return; 1571 } 1572 1573 ni->ni_capinfo = capinfo; 1574 ni->ni_associd = associd; 1575 if (ni->ni_jointime == 0) 1576 ni->ni_jointime = time_uptime; 1577 if (wme != NULL && 1578 ieee80211_parse_wmeparams(vap, wme, wh) >= 0) { 1579 ni->ni_flags |= IEEE80211_NODE_QOS; 1580 ieee80211_wme_updateparams(vap); 1581 } else 1582 ni->ni_flags &= ~IEEE80211_NODE_QOS; 1583 /* 1584 * Setup HT state according to the negotiation. 1585 * 1586 * NB: shouldn't need to check if HT use is enabled but some 1587 * ap's send back HT ie's even when we don't indicate we 1588 * are HT capable in our AssocReq. 1589 */ 1590 if (htcap != NULL && htinfo != NULL && 1591 (vap->iv_flags_ht & IEEE80211_FHT_HT)) { 1592 ieee80211_ht_node_init(ni); 1593 ieee80211_ht_updateparams(ni, htcap, htinfo); 1594 ieee80211_setup_htrates(ni, htcap, 1595 IEEE80211_F_JOIN | IEEE80211_F_DOBRS); 1596 ieee80211_setup_basic_htrates(ni, htinfo); 1597 ieee80211_node_setuptxparms(ni); 1598 } else { 1599#ifdef IEEE80211_SUPPORT_SUPERG 1600 if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_ATH)) 1601 ieee80211_ff_node_init(ni); 1602#endif 1603 } 1604 /* 1605 * Configure state now that we are associated. 1606 * 1607 * XXX may need different/additional driver callbacks? 1608 */ 1609 if (IEEE80211_IS_CHAN_A(ic->ic_curchan) || 1610 (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { 1611 ic->ic_flags |= IEEE80211_F_SHPREAMBLE; 1612 ic->ic_flags &= ~IEEE80211_F_USEBARKER; 1613 } else { 1614 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; 1615 ic->ic_flags |= IEEE80211_F_USEBARKER; 1616 } 1617 ieee80211_set_shortslottime(ic, 1618 IEEE80211_IS_CHAN_A(ic->ic_curchan) || 1619 (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)); 1620 /* 1621 * Honor ERP protection. 1622 * 1623 * NB: ni_erp should zero for non-11g operation. 1624 */ 1625 if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && 1626 (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION)) 1627 ic->ic_flags |= IEEE80211_F_USEPROT; 1628 else 1629 ic->ic_flags &= ~IEEE80211_F_USEPROT; 1630 IEEE80211_NOTE_MAC(vap, 1631 IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, wh->i_addr2, 1632 "%sassoc success at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s%s", 1633 ISREASSOC(subtype) ? "re" : "", 1634 IEEE80211_NODE_AID(ni), 1635 ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long", 1636 ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long", 1637 ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "", 1638 ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", 1639 ni->ni_flags & IEEE80211_NODE_HT ? 1640 (ni->ni_chw == 40 ? ", HT40" : ", HT20") : "", 1641 ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", 1642 ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" : 1643 ni->ni_flags & IEEE80211_NODE_MIMO_PS ? " (+SMPS)" : "", 1644 ni->ni_flags & IEEE80211_NODE_RIFS ? " (+RIFS)" : "", 1645 IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) ? 1646 ", fast-frames" : "", 1647 IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_TURBOP) ? 1648 ", turbo" : "" 1649 ); 1650 ieee80211_new_state(vap, IEEE80211_S_RUN, subtype); 1651 break; 1652 } 1653 1654 case IEEE80211_FC0_SUBTYPE_DEAUTH: { 1655 uint16_t reason; 1656 1657 if (vap->iv_state == IEEE80211_S_SCAN) { 1658 vap->iv_stats.is_rx_mgtdiscard++; 1659 return; 1660 } 1661 if (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr)) { 1662 /* NB: can happen when in promiscuous mode */ 1663 vap->iv_stats.is_rx_mgtdiscard++; 1664 break; 1665 } 1666 1667 /* 1668 * deauth frame format 1669 * [2] reason 1670 */ 1671 IEEE80211_VERIFY_LENGTH(efrm - frm, 2, return); 1672 reason = le16toh(*(uint16_t *)frm); 1673 1674 vap->iv_stats.is_rx_deauth++; 1675 vap->iv_stats.is_rx_deauth_code = reason; 1676 IEEE80211_NODE_STAT(ni, rx_deauth); 1677 1678 IEEE80211_NOTE(vap, IEEE80211_MSG_AUTH, ni, 1679 "recv deauthenticate (reason %d)", reason); 1680 ieee80211_new_state(vap, IEEE80211_S_AUTH, 1681 (reason << 8) | IEEE80211_FC0_SUBTYPE_DEAUTH); 1682 break; 1683 } 1684 1685 case IEEE80211_FC0_SUBTYPE_DISASSOC: { 1686 uint16_t reason; 1687 1688 if (vap->iv_state != IEEE80211_S_RUN && 1689 vap->iv_state != IEEE80211_S_ASSOC && 1690 vap->iv_state != IEEE80211_S_AUTH) { 1691 vap->iv_stats.is_rx_mgtdiscard++; 1692 return; 1693 } 1694 if (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr)) { 1695 /* NB: can happen when in promiscuous mode */ 1696 vap->iv_stats.is_rx_mgtdiscard++; 1697 break; 1698 } 1699 1700 /* 1701 * disassoc frame format 1702 * [2] reason 1703 */ 1704 IEEE80211_VERIFY_LENGTH(efrm - frm, 2, return); 1705 reason = le16toh(*(uint16_t *)frm); 1706 1707 vap->iv_stats.is_rx_disassoc++; 1708 vap->iv_stats.is_rx_disassoc_code = reason; 1709 IEEE80211_NODE_STAT(ni, rx_disassoc); 1710 1711 IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, 1712 "recv disassociate (reason %d)", reason); 1713 ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0); 1714 break; 1715 } 1716 1717 case IEEE80211_FC0_SUBTYPE_ACTION: 1718 if (vap->iv_state == IEEE80211_S_RUN) { 1719 if (ieee80211_parse_action(ni, m0) == 0) 1720 ic->ic_recv_action(ni, frm, efrm); 1721 } else 1722 vap->iv_stats.is_rx_mgtdiscard++; 1723 break; 1724 1725 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 1726 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 1727 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: 1728 vap->iv_stats.is_rx_mgtdiscard++; 1729 return; 1730 default: 1731 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, 1732 wh, "mgt", "subtype 0x%x not handled", subtype); 1733 vap->iv_stats.is_rx_badsubtype++; 1734 break; 1735 } 1736#undef ISREASSOC 1737#undef ISPROBE 1738} 1739 1740static void 1741sta_recv_ctl(struct ieee80211_node *ni, struct mbuf *m0, int subtype) 1742{ 1743} 1744