ieee80211_proto.c revision 170530
199651Sbenno/*- 299651Sbenno * Copyright (c) 2001 Atsushi Onoe 399651Sbenno * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting 499651Sbenno * All rights reserved. 599651Sbenno * 699651Sbenno * Redistribution and use in source and binary forms, with or without 799651Sbenno * modification, are permitted provided that the following conditions 899651Sbenno * are met: 999651Sbenno * 1. Redistributions of source code must retain the above copyright 1099651Sbenno * notice, this list of conditions and the following disclaimer. 1199651Sbenno * 2. Redistributions in binary form must reproduce the above copyright 1299651Sbenno * notice, this list of conditions and the following disclaimer in the 1399651Sbenno * documentation and/or other materials provided with the distribution. 1499651Sbenno * 1599651Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1699651Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1799651Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1899651Sbenno * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1999651Sbenno * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2099651Sbenno * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2199651Sbenno * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2299651Sbenno * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2399651Sbenno * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2499651Sbenno * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2599651Sbenno */ 2699651Sbenno 2799651Sbenno#include <sys/cdefs.h> 2899651Sbenno__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_proto.c 170530 2007-06-11 03:36:55Z sam $"); 2999651Sbenno 3099651Sbenno/* 3199651Sbenno * IEEE 802.11 protocol support. 3299651Sbenno */ 3399651Sbenno 3499651Sbenno#include "opt_inet.h" 3599651Sbenno 3699651Sbenno#include <sys/param.h> 3799651Sbenno#include <sys/kernel.h> 3899651Sbenno#include <sys/systm.h> 3999651Sbenno 4099651Sbenno#include <sys/socket.h> 4199651Sbenno 4299651Sbenno#include <net/if.h> 4399651Sbenno#include <net/if_media.h> 4499651Sbenno#include <net/ethernet.h> /* XXX for ether_sprintf */ 4599651Sbenno 4699651Sbenno#include <net80211/ieee80211_var.h> 4799651Sbenno 4899651Sbenno/* XXX tunables */ 4999651Sbenno#define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */ 5099651Sbenno#define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */ 5199651Sbenno 5299651Sbenno#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) 5399651Sbenno 5499651Sbennoconst char *ieee80211_mgt_subtype_name[] = { 5599651Sbenno "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp", 5699651Sbenno "probe_req", "probe_resp", "reserved#6", "reserved#7", 5799651Sbenno "beacon", "atim", "disassoc", "auth", 5899651Sbenno "deauth", "reserved#13", "reserved#14", "reserved#15" 5999651Sbenno}; 6099651Sbennoconst char *ieee80211_ctl_subtype_name[] = { 6199651Sbenno "reserved#0", "reserved#1", "reserved#2", "reserved#3", 6299651Sbenno "reserved#3", "reserved#5", "reserved#6", "reserved#7", 6399651Sbenno "reserved#8", "reserved#9", "ps_poll", "rts", 6499651Sbenno "cts", "ack", "cf_end", "cf_end_ack" 65}; 66const char *ieee80211_opmode_name[IEEE80211_OPMODE_MAX] = { 67 "IBSS", /* IEEE80211_M_IBSS */ 68 "STA", /* IEEE80211_M_STA */ 69 "#2", 70 "AHDEMO", /* IEEE80211_M_AHDEMO */ 71 "#4", "#5", 72 "HOSTAP", /* IEEE80211_M_HOSTAP */ 73 "#7", 74 "MONITOR" /* IEEE80211_M_MONITOR */ 75}; 76const char *ieee80211_state_name[IEEE80211_S_MAX] = { 77 "INIT", /* IEEE80211_S_INIT */ 78 "SCAN", /* IEEE80211_S_SCAN */ 79 "AUTH", /* IEEE80211_S_AUTH */ 80 "ASSOC", /* IEEE80211_S_ASSOC */ 81 "RUN" /* IEEE80211_S_RUN */ 82}; 83const char *ieee80211_wme_acnames[] = { 84 "WME_AC_BE", 85 "WME_AC_BK", 86 "WME_AC_VI", 87 "WME_AC_VO", 88 "WME_UPSD", 89}; 90 91static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int); 92 93void 94ieee80211_proto_attach(struct ieee80211com *ic) 95{ 96 struct ifnet *ifp = ic->ic_ifp; 97 98 /* XXX room for crypto */ 99 ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4); 100 101 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT; 102 ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT; 103 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 104 ic->ic_bmiss_max = IEEE80211_BMISS_MAX; 105 callout_init(&ic->ic_swbmiss, CALLOUT_MPSAFE); 106 callout_init(&ic->ic_mgtsend, CALLOUT_MPSAFE); 107 ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT; 108 ic->ic_protmode = IEEE80211_PROT_CTSONLY; 109 ic->ic_roaming = IEEE80211_ROAMING_AUTO; 110 111 ic->ic_wme.wme_hipri_switch_hysteresis = 112 AGGRESSIVE_MODE_SWITCH_HYSTERESIS; 113 114 mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_xname, "mgmt send q", MTX_DEF); 115 116 /* protocol state change handler */ 117 ic->ic_newstate = ieee80211_newstate; 118 119 /* initialize management frame handlers */ 120 ic->ic_recv_mgmt = ieee80211_recv_mgmt; 121 ic->ic_send_mgmt = ieee80211_send_mgmt; 122 ic->ic_raw_xmit = ieee80211_raw_xmit; 123} 124 125void 126ieee80211_proto_detach(struct ieee80211com *ic) 127{ 128 129 /* 130 * This should not be needed as we detach when reseting 131 * the state but be conservative here since the 132 * authenticator may do things like spawn kernel threads. 133 */ 134 if (ic->ic_auth->ia_detach) 135 ic->ic_auth->ia_detach(ic); 136 137 ieee80211_drain_ifq(&ic->ic_mgtq); 138 mtx_destroy(&ic->ic_mgtq.ifq_mtx); 139 140 /* 141 * Detach any ACL'ator. 142 */ 143 if (ic->ic_acl != NULL) 144 ic->ic_acl->iac_detach(ic); 145} 146 147/* 148 * Simple-minded authenticator module support. 149 */ 150 151#define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1) 152/* XXX well-known names */ 153static const char *auth_modnames[IEEE80211_AUTH_MAX] = { 154 "wlan_internal", /* IEEE80211_AUTH_NONE */ 155 "wlan_internal", /* IEEE80211_AUTH_OPEN */ 156 "wlan_internal", /* IEEE80211_AUTH_SHARED */ 157 "wlan_xauth", /* IEEE80211_AUTH_8021X */ 158 "wlan_internal", /* IEEE80211_AUTH_AUTO */ 159 "wlan_xauth", /* IEEE80211_AUTH_WPA */ 160}; 161static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX]; 162 163static const struct ieee80211_authenticator auth_internal = { 164 .ia_name = "wlan_internal", 165 .ia_attach = NULL, 166 .ia_detach = NULL, 167 .ia_node_join = NULL, 168 .ia_node_leave = NULL, 169}; 170 171/* 172 * Setup internal authenticators once; they are never unregistered. 173 */ 174static void 175ieee80211_auth_setup(void) 176{ 177 ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal); 178 ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal); 179 ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal); 180} 181SYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL); 182 183const struct ieee80211_authenticator * 184ieee80211_authenticator_get(int auth) 185{ 186 if (auth >= IEEE80211_AUTH_MAX) 187 return NULL; 188 if (authenticators[auth] == NULL) 189 ieee80211_load_module(auth_modnames[auth]); 190 return authenticators[auth]; 191} 192 193void 194ieee80211_authenticator_register(int type, 195 const struct ieee80211_authenticator *auth) 196{ 197 if (type >= IEEE80211_AUTH_MAX) 198 return; 199 authenticators[type] = auth; 200} 201 202void 203ieee80211_authenticator_unregister(int type) 204{ 205 206 if (type >= IEEE80211_AUTH_MAX) 207 return; 208 authenticators[type] = NULL; 209} 210 211/* 212 * Very simple-minded ACL module support. 213 */ 214/* XXX just one for now */ 215static const struct ieee80211_aclator *acl = NULL; 216 217void 218ieee80211_aclator_register(const struct ieee80211_aclator *iac) 219{ 220 printf("wlan: %s acl policy registered\n", iac->iac_name); 221 acl = iac; 222} 223 224void 225ieee80211_aclator_unregister(const struct ieee80211_aclator *iac) 226{ 227 if (acl == iac) 228 acl = NULL; 229 printf("wlan: %s acl policy unregistered\n", iac->iac_name); 230} 231 232const struct ieee80211_aclator * 233ieee80211_aclator_get(const char *name) 234{ 235 if (acl == NULL) 236 ieee80211_load_module("wlan_acl"); 237 return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL; 238} 239 240void 241ieee80211_print_essid(const uint8_t *essid, int len) 242{ 243 const uint8_t *p; 244 int i; 245 246 if (len > IEEE80211_NWID_LEN) 247 len = IEEE80211_NWID_LEN; 248 /* determine printable or not */ 249 for (i = 0, p = essid; i < len; i++, p++) { 250 if (*p < ' ' || *p > 0x7e) 251 break; 252 } 253 if (i == len) { 254 printf("\""); 255 for (i = 0, p = essid; i < len; i++, p++) 256 printf("%c", *p); 257 printf("\""); 258 } else { 259 printf("0x"); 260 for (i = 0, p = essid; i < len; i++, p++) 261 printf("%02x", *p); 262 } 263} 264 265void 266ieee80211_dump_pkt(struct ieee80211com *ic, 267 const uint8_t *buf, int len, int rate, int rssi) 268{ 269 const struct ieee80211_frame *wh; 270 int i; 271 272 wh = (const struct ieee80211_frame *)buf; 273 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 274 case IEEE80211_FC1_DIR_NODS: 275 printf("NODS %s", ether_sprintf(wh->i_addr2)); 276 printf("->%s", ether_sprintf(wh->i_addr1)); 277 printf("(%s)", ether_sprintf(wh->i_addr3)); 278 break; 279 case IEEE80211_FC1_DIR_TODS: 280 printf("TODS %s", ether_sprintf(wh->i_addr2)); 281 printf("->%s", ether_sprintf(wh->i_addr3)); 282 printf("(%s)", ether_sprintf(wh->i_addr1)); 283 break; 284 case IEEE80211_FC1_DIR_FROMDS: 285 printf("FRDS %s", ether_sprintf(wh->i_addr3)); 286 printf("->%s", ether_sprintf(wh->i_addr1)); 287 printf("(%s)", ether_sprintf(wh->i_addr2)); 288 break; 289 case IEEE80211_FC1_DIR_DSTODS: 290 printf("DSDS %s", ether_sprintf((const uint8_t *)&wh[1])); 291 printf("->%s", ether_sprintf(wh->i_addr3)); 292 printf("(%s", ether_sprintf(wh->i_addr2)); 293 printf("->%s)", ether_sprintf(wh->i_addr1)); 294 break; 295 } 296 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 297 case IEEE80211_FC0_TYPE_DATA: 298 printf(" data"); 299 break; 300 case IEEE80211_FC0_TYPE_MGT: 301 printf(" %s", ieee80211_mgt_subtype_name[ 302 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) 303 >> IEEE80211_FC0_SUBTYPE_SHIFT]); 304 break; 305 default: 306 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 307 break; 308 } 309 if (IEEE80211_QOS_HAS_SEQ(wh)) { 310 const struct ieee80211_qosframe *qwh = 311 (const struct ieee80211_qosframe *)buf; 312 printf(" QoS [TID %u%s]", qwh->i_qos[0] & IEEE80211_QOS_TID, 313 qwh->i_qos[0] & IEEE80211_QOS_ACKPOLICY ? " ACM" : ""); 314 } 315 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 316 int off; 317 318 off = ieee80211_anyhdrspace(ic, wh); 319 printf(" WEP [IV %.02x %.02x %.02x", 320 buf[off+0], buf[off+1], buf[off+2]); 321 if (buf[off+IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) 322 printf(" %.02x %.02x %.02x", 323 buf[off+4], buf[off+5], buf[off+6]); 324 printf(" KID %u]", buf[off+IEEE80211_WEP_IVLEN] >> 6); 325 } 326 if (rate >= 0) 327 printf(" %dM", rate / 2); 328 if (rssi >= 0) 329 printf(" +%d", rssi); 330 printf("\n"); 331 if (len > 0) { 332 for (i = 0; i < len; i++) { 333 if ((i & 1) == 0) 334 printf(" "); 335 printf("%02x", buf[i]); 336 } 337 printf("\n"); 338 } 339} 340 341static __inline int 342findrix(const struct ieee80211_rateset *rs, int r) 343{ 344 int i; 345 346 for (i = 0; i < rs->rs_nrates; i++) 347 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == r) 348 return i; 349 return -1; 350} 351 352int 353ieee80211_fix_rate(struct ieee80211_node *ni, 354 struct ieee80211_rateset *nrs, int flags) 355{ 356#define RV(v) ((v) & IEEE80211_RATE_VAL) 357 struct ieee80211com *ic = ni->ni_ic; 358 int i, j, rix, error; 359 int okrate, badrate, fixedrate; 360 const struct ieee80211_rateset *srs; 361 uint8_t r; 362 363 error = 0; 364 okrate = badrate = 0; 365 fixedrate = IEEE80211_FIXED_RATE_NONE; 366 srs = ieee80211_get_suprates(ic, ni->ni_chan); 367 for (i = 0; i < nrs->rs_nrates; ) { 368 if (flags & IEEE80211_F_DOSORT) { 369 /* 370 * Sort rates. 371 */ 372 for (j = i + 1; j < nrs->rs_nrates; j++) { 373 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) { 374 r = nrs->rs_rates[i]; 375 nrs->rs_rates[i] = nrs->rs_rates[j]; 376 nrs->rs_rates[j] = r; 377 } 378 } 379 } 380 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL; 381 badrate = r; 382 /* 383 * Check for fixed rate. 384 */ 385 if (r == ic->ic_fixed_rate) 386 fixedrate = r; 387 /* 388 * Check against supported rates. 389 */ 390 rix = findrix(srs, r); 391 if (flags & IEEE80211_F_DONEGO) { 392 if (rix < 0) { 393 /* 394 * A rate in the node's rate set is not 395 * supported. If this is a basic rate and we 396 * are operating as a STA then this is an error. 397 * Otherwise we just discard/ignore the rate. 398 */ 399 if ((flags & IEEE80211_F_JOIN) && 400 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) 401 error++; 402 } else if ((flags & IEEE80211_F_JOIN) == 0) { 403 /* 404 * Overwrite with the supported rate 405 * value so any basic rate bit is set. 406 */ 407 nrs->rs_rates[i] = srs->rs_rates[rix]; 408 } 409 } 410 if ((flags & IEEE80211_F_DODEL) && rix < 0) { 411 /* 412 * Delete unacceptable rates. 413 */ 414 nrs->rs_nrates--; 415 for (j = i; j < nrs->rs_nrates; j++) 416 nrs->rs_rates[j] = nrs->rs_rates[j + 1]; 417 nrs->rs_rates[j] = 0; 418 continue; 419 } 420 if (rix >= 0) 421 okrate = nrs->rs_rates[i]; 422 i++; 423 } 424 if (okrate == 0 || error != 0 || 425 ((flags & IEEE80211_F_DOFRATE) && fixedrate != ic->ic_fixed_rate)) 426 return badrate | IEEE80211_RATE_BASIC; 427 else 428 return RV(okrate); 429#undef RV 430} 431 432/* 433 * Reset 11g-related state. 434 */ 435void 436ieee80211_reset_erp(struct ieee80211com *ic) 437{ 438 ic->ic_flags &= ~IEEE80211_F_USEPROT; 439 ic->ic_nonerpsta = 0; 440 ic->ic_longslotsta = 0; 441 /* 442 * Short slot time is enabled only when operating in 11g 443 * and not in an IBSS. We must also honor whether or not 444 * the driver is capable of doing it. 445 */ 446 ieee80211_set_shortslottime(ic, 447 IEEE80211_IS_CHAN_A(ic->ic_curchan) || 448 IEEE80211_IS_CHAN_HT(ic->ic_curchan) || 449 (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && 450 ic->ic_opmode == IEEE80211_M_HOSTAP && 451 (ic->ic_caps & IEEE80211_C_SHSLOT))); 452 /* 453 * Set short preamble and ERP barker-preamble flags. 454 */ 455 if (IEEE80211_IS_CHAN_A(ic->ic_curchan) || 456 (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) { 457 ic->ic_flags |= IEEE80211_F_SHPREAMBLE; 458 ic->ic_flags &= ~IEEE80211_F_USEBARKER; 459 } else { 460 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; 461 ic->ic_flags |= IEEE80211_F_USEBARKER; 462 } 463} 464 465/* 466 * Set the short slot time state and notify the driver. 467 */ 468void 469ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff) 470{ 471 if (onoff) 472 ic->ic_flags |= IEEE80211_F_SHSLOT; 473 else 474 ic->ic_flags &= ~IEEE80211_F_SHSLOT; 475 /* notify driver */ 476 if (ic->ic_updateslot != NULL) 477 ic->ic_updateslot(ic->ic_ifp); 478} 479 480/* 481 * Check if the specified rate set supports ERP. 482 * NB: the rate set is assumed to be sorted. 483 */ 484int 485ieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs) 486{ 487#define N(a) (sizeof(a) / sizeof(a[0])) 488 static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 }; 489 int i, j; 490 491 if (rs->rs_nrates < N(rates)) 492 return 0; 493 for (i = 0; i < N(rates); i++) { 494 for (j = 0; j < rs->rs_nrates; j++) { 495 int r = rs->rs_rates[j] & IEEE80211_RATE_VAL; 496 if (rates[i] == r) 497 goto next; 498 if (r > rates[i]) 499 return 0; 500 } 501 return 0; 502 next: 503 ; 504 } 505 return 1; 506#undef N 507} 508 509/* 510 * Mark the basic rates for the 11g rate table based on the 511 * operating mode. For real 11g we mark all the 11b rates 512 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only 513 * 11b rates. There's also a pseudo 11a-mode used to mark only 514 * the basic OFDM rates. 515 */ 516void 517ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode) 518{ 519 static const struct ieee80211_rateset basic[IEEE80211_MODE_MAX] = { 520 { .rs_nrates = 0 }, /* IEEE80211_MODE_AUTO */ 521 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */ 522 { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */ 523 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */ 524 { .rs_nrates = 0 }, /* IEEE80211_MODE_FH */ 525 /* IEEE80211_MODE_PUREG (not yet) */ 526 { 7, { 2, 4, 11, 22, 12, 24, 48 } }, 527 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11NA */ 528 /* IEEE80211_MODE_11NG (mixed b/g) */ 529 { 7, { 2, 4, 11, 22, 12, 24, 48 } }, 530 }; 531 int i, j; 532 533 for (i = 0; i < rs->rs_nrates; i++) { 534 rs->rs_rates[i] &= IEEE80211_RATE_VAL; 535 for (j = 0; j < basic[mode].rs_nrates; j++) 536 if (basic[mode].rs_rates[j] == rs->rs_rates[i]) { 537 rs->rs_rates[i] |= IEEE80211_RATE_BASIC; 538 break; 539 } 540 } 541} 542 543/* 544 * WME protocol support. The following parameters come from the spec. 545 */ 546typedef struct phyParamType { 547 uint8_t aifsn; 548 uint8_t logcwmin; 549 uint8_t logcwmax; 550 uint16_t txopLimit; 551 uint8_t acm; 552} paramType; 553 554static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = { 555 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_AUTO */ 556 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11A */ 557 { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_11B */ 558 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11G */ 559 { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_FH */ 560 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_A */ 561 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_G */ 562 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_STURBO_A */ 563 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11NA */ /* XXXcheck*/ 564 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11NG */ /* XXXcheck*/ 565}; 566static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = { 567 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */ 568 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */ 569 { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_11B */ 570 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */ 571 { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_FH */ 572 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */ 573 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */ 574 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */ 575 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */ 576 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */ 577}; 578static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = { 579 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */ 580 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */ 581 { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_11B */ 582 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */ 583 { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_FH */ 584 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */ 585 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */ 586 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */ 587 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */ 588 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */ 589}; 590static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = { 591 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */ 592 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */ 593 { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_11B */ 594 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */ 595 { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_FH */ 596 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */ 597 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */ 598 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */ 599 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */ 600 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */ 601}; 602 603static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = { 604 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */ 605 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */ 606 { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_11B */ 607 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */ 608 { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_FH */ 609 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */ 610 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */ 611 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */ 612 { 1, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */ 613 { 1, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */ 614}; 615static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = { 616 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */ 617 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */ 618 { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_11B */ 619 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */ 620 { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_FH */ 621 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */ 622 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */ 623 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */ 624 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */ 625 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */ 626}; 627static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = { 628 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */ 629 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */ 630 { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_11B */ 631 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */ 632 { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_FH */ 633 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */ 634 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */ 635 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */ 636 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */ 637 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */ 638}; 639 640void 641ieee80211_wme_initparams(struct ieee80211com *ic) 642{ 643 struct ieee80211_wme_state *wme = &ic->ic_wme; 644 const paramType *pPhyParam, *pBssPhyParam; 645 struct wmeParams *wmep; 646 enum ieee80211_phymode mode; 647 int i; 648 649 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 650 return; 651 652 /* 653 * Select mode; we can be called early in which case we 654 * always use auto mode. We know we'll be called when 655 * entering the RUN state with bsschan setup properly 656 * so state will eventually get set correctly 657 */ 658 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) 659 mode = ieee80211_chan2mode(ic->ic_bsschan); 660 else 661 mode = IEEE80211_MODE_AUTO; 662 for (i = 0; i < WME_NUM_AC; i++) { 663 switch (i) { 664 case WME_AC_BK: 665 pPhyParam = &phyParamForAC_BK[mode]; 666 pBssPhyParam = &phyParamForAC_BK[mode]; 667 break; 668 case WME_AC_VI: 669 pPhyParam = &phyParamForAC_VI[mode]; 670 pBssPhyParam = &bssPhyParamForAC_VI[mode]; 671 break; 672 case WME_AC_VO: 673 pPhyParam = &phyParamForAC_VO[mode]; 674 pBssPhyParam = &bssPhyParamForAC_VO[mode]; 675 break; 676 case WME_AC_BE: 677 default: 678 pPhyParam = &phyParamForAC_BE[mode]; 679 pBssPhyParam = &bssPhyParamForAC_BE[mode]; 680 break; 681 } 682 683 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 684 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 685 wmep->wmep_acm = pPhyParam->acm; 686 wmep->wmep_aifsn = pPhyParam->aifsn; 687 wmep->wmep_logcwmin = pPhyParam->logcwmin; 688 wmep->wmep_logcwmax = pPhyParam->logcwmax; 689 wmep->wmep_txopLimit = pPhyParam->txopLimit; 690 } else { 691 wmep->wmep_acm = pBssPhyParam->acm; 692 wmep->wmep_aifsn = pBssPhyParam->aifsn; 693 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 694 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 695 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 696 697 } 698 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 699 "%s: %s chan [acm %u aifsn %u log2(cwmin) %u " 700 "log2(cwmax) %u txpoLimit %u]\n", __func__ 701 , ieee80211_wme_acnames[i] 702 , wmep->wmep_acm 703 , wmep->wmep_aifsn 704 , wmep->wmep_logcwmin 705 , wmep->wmep_logcwmax 706 , wmep->wmep_txopLimit 707 ); 708 709 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 710 wmep->wmep_acm = pBssPhyParam->acm; 711 wmep->wmep_aifsn = pBssPhyParam->aifsn; 712 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 713 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 714 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 715 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 716 "%s: %s bss [acm %u aifsn %u log2(cwmin) %u " 717 "log2(cwmax) %u txpoLimit %u]\n", __func__ 718 , ieee80211_wme_acnames[i] 719 , wmep->wmep_acm 720 , wmep->wmep_aifsn 721 , wmep->wmep_logcwmin 722 , wmep->wmep_logcwmax 723 , wmep->wmep_txopLimit 724 ); 725 } 726 /* NB: check ic_bss to avoid NULL deref on initial attach */ 727 if (ic->ic_bss != NULL) { 728 /* 729 * Calculate agressive mode switching threshold based 730 * on beacon interval. This doesn't need locking since 731 * we're only called before entering the RUN state at 732 * which point we start sending beacon frames. 733 */ 734 wme->wme_hipri_switch_thresh = 735 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100; 736 ieee80211_wme_updateparams(ic); 737 } 738} 739 740/* 741 * Update WME parameters for ourself and the BSS. 742 */ 743void 744ieee80211_wme_updateparams_locked(struct ieee80211com *ic) 745{ 746 static const paramType phyParam[IEEE80211_MODE_MAX] = { 747 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_AUTO */ 748 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11A */ 749 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_11B */ 750 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11G */ 751 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_FH */ 752 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_A */ 753 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_G */ 754 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_STURBO_A */ 755 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NA */ /*XXXcheck*/ 756 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NG */ /*XXXcheck*/ 757 }; 758 struct ieee80211_wme_state *wme = &ic->ic_wme; 759 const struct wmeParams *wmep; 760 struct wmeParams *chanp, *bssp; 761 enum ieee80211_phymode mode; 762 int i; 763 764 /* set up the channel access parameters for the physical device */ 765 for (i = 0; i < WME_NUM_AC; i++) { 766 chanp = &wme->wme_chanParams.cap_wmeParams[i]; 767 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 768 chanp->wmep_aifsn = wmep->wmep_aifsn; 769 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 770 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 771 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 772 773 chanp = &wme->wme_bssChanParams.cap_wmeParams[i]; 774 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 775 chanp->wmep_aifsn = wmep->wmep_aifsn; 776 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 777 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 778 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 779 } 780 781 /* 782 * Select mode; we can be called early in which case we 783 * always use auto mode. We know we'll be called when 784 * entering the RUN state with bsschan setup properly 785 * so state will eventually get set correctly 786 */ 787 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) 788 mode = ieee80211_chan2mode(ic->ic_bsschan); 789 else 790 mode = IEEE80211_MODE_AUTO; 791 792 /* 793 * This implements agressive mode as found in certain 794 * vendors' AP's. When there is significant high 795 * priority (VI/VO) traffic in the BSS throttle back BE 796 * traffic by using conservative parameters. Otherwise 797 * BE uses agressive params to optimize performance of 798 * legacy/non-QoS traffic. 799 */ 800 if ((ic->ic_opmode == IEEE80211_M_HOSTAP && 801 (wme->wme_flags & WME_F_AGGRMODE) != 0) || 802 (ic->ic_opmode == IEEE80211_M_STA && 803 (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) || 804 (ic->ic_flags & IEEE80211_F_WME) == 0) { 805 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE]; 806 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE]; 807 808 chanp->wmep_aifsn = bssp->wmep_aifsn = phyParam[mode].aifsn; 809 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 810 phyParam[mode].logcwmin; 811 chanp->wmep_logcwmax = bssp->wmep_logcwmax = 812 phyParam[mode].logcwmax; 813 chanp->wmep_txopLimit = bssp->wmep_txopLimit = 814 (ic->ic_flags & IEEE80211_F_BURST) ? 815 phyParam[mode].txopLimit : 0; 816 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 817 "%s: %s [acm %u aifsn %u log2(cwmin) %u " 818 "log2(cwmax) %u txpoLimit %u]\n", __func__ 819 , ieee80211_wme_acnames[WME_AC_BE] 820 , chanp->wmep_acm 821 , chanp->wmep_aifsn 822 , chanp->wmep_logcwmin 823 , chanp->wmep_logcwmax 824 , chanp->wmep_txopLimit 825 ); 826 } 827 828 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 829 ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) { 830 static const uint8_t logCwMin[IEEE80211_MODE_MAX] = { 831 3, /* IEEE80211_MODE_AUTO */ 832 3, /* IEEE80211_MODE_11A */ 833 4, /* IEEE80211_MODE_11B */ 834 3, /* IEEE80211_MODE_11G */ 835 4, /* IEEE80211_MODE_FH */ 836 3, /* IEEE80211_MODE_TURBO_A */ 837 3, /* IEEE80211_MODE_TURBO_G */ 838 3, /* IEEE80211_MODE_STURBO_A */ 839 3, /* IEEE80211_MODE_11NA */ 840 3, /* IEEE80211_MODE_11NG */ 841 }; 842 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE]; 843 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE]; 844 845 chanp->wmep_logcwmin = bssp->wmep_logcwmin = logCwMin[mode]; 846 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 847 "%s: %s log2(cwmin) %u\n", __func__ 848 , ieee80211_wme_acnames[WME_AC_BE] 849 , chanp->wmep_logcwmin 850 ); 851 } 852 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */ 853 /* 854 * Arrange for a beacon update and bump the parameter 855 * set number so associated stations load the new values. 856 */ 857 wme->wme_bssChanParams.cap_info = 858 (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT; 859 ic->ic_flags |= IEEE80211_F_WMEUPDATE; 860 } 861 862 wme->wme_update(ic); 863 864 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 865 "%s: WME params updated, cap_info 0x%x\n", __func__, 866 ic->ic_opmode == IEEE80211_M_STA ? 867 wme->wme_wmeChanParams.cap_info : 868 wme->wme_bssChanParams.cap_info); 869} 870 871void 872ieee80211_wme_updateparams(struct ieee80211com *ic) 873{ 874 875 if (ic->ic_caps & IEEE80211_C_WME) { 876 IEEE80211_BEACON_LOCK(ic); 877 ieee80211_wme_updateparams_locked(ic); 878 IEEE80211_BEACON_UNLOCK(ic); 879 } 880} 881 882/* 883 * Start a device. If this is the first vap running on the 884 * underlying device then we first bring it up. 885 */ 886int 887ieee80211_init(struct ieee80211com *ic, int forcescan) 888{ 889 890 IEEE80211_DPRINTF(ic, 891 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, 892 "%s\n", "start running"); 893 894 /* 895 * Kick the 802.11 state machine as appropriate. 896 */ 897 if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) { 898 if (ic->ic_opmode == IEEE80211_M_STA) { 899 /* 900 * Try to be intelligent about clocking the state 901 * machine. If we're currently in RUN state then 902 * we should be able to apply any new state/parameters 903 * simply by re-associating. Otherwise we need to 904 * re-scan to select an appropriate ap. 905 */ 906 if (ic->ic_state != IEEE80211_S_RUN || forcescan) 907 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 908 else 909 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1); 910 } else { 911 /* 912 * For monitor+wds modes there's nothing to do but 913 * start running. Otherwise, if this is the first 914 * vap to be brought up, start a scan which may be 915 * preempted if the station is locked to a particular 916 * channel. 917 */ 918 if (ic->ic_opmode == IEEE80211_M_MONITOR || 919 ic->ic_opmode == IEEE80211_M_WDS) { 920 ic->ic_state = IEEE80211_S_INIT; /* XXX*/ 921 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 922 } else 923 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 924 } 925 } 926 return 0; 927} 928 929/* 930 * Switch between turbo and non-turbo operating modes. 931 * Use the specified channel flags to locate the new 932 * channel, update 802.11 state, and then call back into 933 * the driver to effect the change. 934 */ 935void 936ieee80211_dturbo_switch(struct ieee80211com *ic, int newflags) 937{ 938 struct ieee80211_channel *chan; 939 940 chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags); 941 if (chan == NULL) { /* XXX should not happen */ 942 IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG, 943 "%s: no channel with freq %u flags 0x%x\n", 944 __func__, ic->ic_bsschan->ic_freq, newflags); 945 return; 946 } 947 948 IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG, 949 "%s: %s -> %s (freq %u flags 0x%x)\n", __func__, 950 ieee80211_phymode_name[ieee80211_chan2mode(ic->ic_bsschan)], 951 ieee80211_phymode_name[ieee80211_chan2mode(chan)], 952 chan->ic_freq, chan->ic_flags); 953 954 ic->ic_bsschan = chan; 955 ic->ic_prevchan = ic->ic_curchan; 956 ic->ic_curchan = chan; 957 ic->ic_set_channel(ic); 958 /* NB: do not need to reset ERP state 'cuz we're in sta mode */ 959} 960 961void 962ieee80211_beacon_miss(struct ieee80211com *ic) 963{ 964 965 if (ic->ic_flags & IEEE80211_F_SCAN) { 966 /* XXX check ic_curchan != ic_bsschan? */ 967 return; 968 } 969 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, 970 "%s\n", "beacon miss"); 971 972 /* 973 * Our handling is only meaningful for stations that are 974 * associated; any other conditions else will be handled 975 * through different means (e.g. the tx timeout on mgt frames). 976 */ 977 if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN) 978 return; 979 980 if (++ic->ic_bmiss_count < ic->ic_bmiss_max) { 981 /* 982 * Send a directed probe req before falling back to a scan; 983 * if we receive a response ic_bmiss_count will be reset. 984 * Some cards mistakenly report beacon miss so this avoids 985 * the expensive scan if the ap is still there. 986 */ 987 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr, 988 ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid, 989 ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen, 990 ic->ic_opt_ie, ic->ic_opt_ie_len); 991 return; 992 } 993 ic->ic_bmiss_count = 0; 994 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { 995 /* 996 * If we receive a beacon miss interrupt when using 997 * dynamic turbo, attempt to switch modes before 998 * reassociating. 999 */ 1000 if (IEEE80211_ATH_CAP(ic, ic->ic_bss, IEEE80211_NODE_TURBOP)) 1001 ieee80211_dturbo_switch(ic, 1002 ic->ic_bsschan->ic_flags ^ IEEE80211_CHAN_TURBO); 1003 /* 1004 * Try to reassociate before scanning for a new ap. 1005 */ 1006 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1); 1007 } else { 1008 /* 1009 * Somebody else is controlling state changes (e.g. 1010 * a user-mode app) don't do anything that would 1011 * confuse them; just drop into scan mode so they'll 1012 * notified of the state change and given control. 1013 */ 1014 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 1015 } 1016} 1017 1018/* 1019 * Software beacon miss handling. Check if any beacons 1020 * were received in the last period. If not post a 1021 * beacon miss; otherwise reset the counter. 1022 */ 1023static void 1024ieee80211_swbmiss(void *arg) 1025{ 1026 struct ieee80211com *ic = arg; 1027 1028 if (ic->ic_swbmiss_count == 0) { 1029 ieee80211_beacon_miss(ic); 1030 if (ic->ic_bmiss_count == 0) /* don't re-arm timer */ 1031 return; 1032 } else 1033 ic->ic_swbmiss_count = 0; 1034 callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period, 1035 ieee80211_swbmiss, ic); 1036} 1037 1038static void 1039sta_disassoc(void *arg, struct ieee80211_node *ni) 1040{ 1041 struct ieee80211com *ic = arg; 1042 1043 if (ni->ni_associd != 0) { 1044 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC, 1045 IEEE80211_REASON_ASSOC_LEAVE); 1046 ieee80211_node_leave(ic, ni); 1047 } 1048} 1049 1050static void 1051sta_deauth(void *arg, struct ieee80211_node *ni) 1052{ 1053 struct ieee80211com *ic = arg; 1054 1055 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, 1056 IEEE80211_REASON_ASSOC_LEAVE); 1057} 1058 1059/* 1060 * Handle deauth with reason. We retry only for 1061 * the cases where we might succeed. Otherwise 1062 * we downgrade the ap and scan. 1063 */ 1064static void 1065sta_authretry(struct ieee80211com *ic, struct ieee80211_node *ni, int reason) 1066{ 1067 switch (reason) { 1068 case IEEE80211_STATUS_TIMEOUT: 1069 case IEEE80211_REASON_ASSOC_EXPIRE: 1070 case IEEE80211_REASON_NOT_AUTHED: 1071 case IEEE80211_REASON_NOT_ASSOCED: 1072 case IEEE80211_REASON_ASSOC_LEAVE: 1073 case IEEE80211_REASON_ASSOC_NOT_AUTHED: 1074 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 1); 1075 break; 1076 default: 1077 ieee80211_scan_assoc_fail(ic, ic->ic_bss->ni_macaddr, reason); 1078 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) 1079 ieee80211_check_scan(ic, 1080 IEEE80211_SCAN_ACTIVE, 1081 IEEE80211_SCAN_FOREVER, 1082 ic->ic_des_nssid, ic->ic_des_ssid); 1083 break; 1084 } 1085} 1086 1087static int 1088ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 1089{ 1090 struct ifnet *ifp = ic->ic_ifp; 1091 struct ieee80211_node *ni; 1092 enum ieee80211_state ostate; 1093 1094 ostate = ic->ic_state; 1095 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__, 1096 ieee80211_state_name[ostate], ieee80211_state_name[nstate]); 1097 ic->ic_state = nstate; /* state transition */ 1098 callout_stop(&ic->ic_mgtsend); /* XXX callout_drain */ 1099 if (ostate != IEEE80211_S_SCAN) 1100 ieee80211_cancel_scan(ic); /* background scan */ 1101 ni = ic->ic_bss; /* NB: no reference held */ 1102 if (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS) 1103 callout_stop(&ic->ic_swbmiss); 1104 switch (nstate) { 1105 case IEEE80211_S_INIT: 1106 switch (ostate) { 1107 case IEEE80211_S_INIT: 1108 break; 1109 case IEEE80211_S_RUN: 1110 switch (ic->ic_opmode) { 1111 case IEEE80211_M_STA: 1112 IEEE80211_SEND_MGMT(ic, ni, 1113 IEEE80211_FC0_SUBTYPE_DISASSOC, 1114 IEEE80211_REASON_ASSOC_LEAVE); 1115 ieee80211_sta_leave(ic, ni); 1116 break; 1117 case IEEE80211_M_HOSTAP: 1118 ieee80211_iterate_nodes(&ic->ic_sta, 1119 sta_disassoc, ic); 1120 break; 1121 default: 1122 break; 1123 } 1124 break; 1125 case IEEE80211_S_ASSOC: 1126 switch (ic->ic_opmode) { 1127 case IEEE80211_M_STA: 1128 IEEE80211_SEND_MGMT(ic, ni, 1129 IEEE80211_FC0_SUBTYPE_DEAUTH, 1130 IEEE80211_REASON_AUTH_LEAVE); 1131 break; 1132 case IEEE80211_M_HOSTAP: 1133 ieee80211_iterate_nodes(&ic->ic_sta, 1134 sta_deauth, ic); 1135 break; 1136 default: 1137 break; 1138 } 1139 break; 1140 case IEEE80211_S_SCAN: 1141 ieee80211_cancel_scan(ic); 1142 break; 1143 case IEEE80211_S_AUTH: 1144 break; 1145 } 1146 if (ostate != IEEE80211_S_INIT) { 1147 /* NB: optimize INIT -> INIT case */ 1148 ieee80211_drain_ifq(&ic->ic_mgtq); 1149 ieee80211_reset_bss(ic); 1150 ieee80211_scan_flush(ic); 1151 } 1152 if (ic->ic_auth->ia_detach != NULL) 1153 ic->ic_auth->ia_detach(ic); 1154 break; 1155 case IEEE80211_S_SCAN: 1156 switch (ostate) { 1157 case IEEE80211_S_INIT: 1158 createibss: 1159 if ((ic->ic_opmode == IEEE80211_M_HOSTAP || 1160 ic->ic_opmode == IEEE80211_M_IBSS || 1161 ic->ic_opmode == IEEE80211_M_AHDEMO) && 1162 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 1163 /* 1164 * Already have a channel; bypass the 1165 * scan and startup immediately. Because 1166 * of this explicitly sync the scanner state. 1167 */ 1168 ieee80211_scan_update(ic); 1169 ieee80211_create_ibss(ic, ic->ic_des_chan); 1170 } else { 1171 ieee80211_check_scan(ic, 1172 IEEE80211_SCAN_ACTIVE | 1173 IEEE80211_SCAN_FLUSH, 1174 IEEE80211_SCAN_FOREVER, 1175 ic->ic_des_nssid, ic->ic_des_ssid); 1176 } 1177 break; 1178 case IEEE80211_S_SCAN: 1179 case IEEE80211_S_AUTH: 1180 case IEEE80211_S_ASSOC: 1181 /* 1182 * These can happen either because of a timeout 1183 * on an assoc/auth response or because of a 1184 * change in state that requires a reset. For 1185 * the former we're called with a non-zero arg 1186 * that is the cause for the failure; pass this 1187 * to the scan code so it can update state. 1188 * Otherwise trigger a new scan unless we're in 1189 * manual roaming mode in which case an application 1190 * must issue an explicit scan request. 1191 */ 1192 if (arg != 0) 1193 ieee80211_scan_assoc_fail(ic, 1194 ic->ic_bss->ni_macaddr, arg); 1195 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) 1196 ieee80211_check_scan(ic, 1197 IEEE80211_SCAN_ACTIVE, 1198 IEEE80211_SCAN_FOREVER, 1199 ic->ic_des_nssid, ic->ic_des_ssid); 1200 break; 1201 case IEEE80211_S_RUN: /* beacon miss */ 1202 if (ic->ic_opmode == IEEE80211_M_STA) { 1203 ieee80211_sta_leave(ic, ni); 1204 ic->ic_flags &= ~IEEE80211_F_SIBSS; /* XXX */ 1205 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) 1206 ieee80211_check_scan(ic, 1207 IEEE80211_SCAN_ACTIVE, 1208 IEEE80211_SCAN_FOREVER, 1209 ic->ic_des_nssid, 1210 ic->ic_des_ssid); 1211 } else { 1212 ieee80211_iterate_nodes(&ic->ic_sta, 1213 sta_disassoc, ic); 1214 goto createibss; 1215 } 1216 break; 1217 } 1218 break; 1219 case IEEE80211_S_AUTH: 1220 KASSERT(ic->ic_opmode == IEEE80211_M_STA, 1221 ("switch to %s state when operating in mode %u", 1222 ieee80211_state_name[nstate], ic->ic_opmode)); 1223 switch (ostate) { 1224 case IEEE80211_S_INIT: 1225 case IEEE80211_S_SCAN: 1226 IEEE80211_SEND_MGMT(ic, ni, 1227 IEEE80211_FC0_SUBTYPE_AUTH, 1); 1228 break; 1229 case IEEE80211_S_AUTH: 1230 case IEEE80211_S_ASSOC: 1231 switch (arg & 0xff) { 1232 case IEEE80211_FC0_SUBTYPE_AUTH: 1233 /* ??? */ 1234 IEEE80211_SEND_MGMT(ic, ni, 1235 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1236 break; 1237 case IEEE80211_FC0_SUBTYPE_DEAUTH: 1238 sta_authretry(ic, ni, arg>>8); 1239 break; 1240 } 1241 break; 1242 case IEEE80211_S_RUN: 1243 switch (arg & 0xff) { 1244 case IEEE80211_FC0_SUBTYPE_AUTH: 1245 IEEE80211_SEND_MGMT(ic, ni, 1246 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1247 ic->ic_state = ostate; /* stay RUN */ 1248 break; 1249 case IEEE80211_FC0_SUBTYPE_DEAUTH: 1250 ieee80211_sta_leave(ic, ni); 1251 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { 1252 /* try to reauth */ 1253 IEEE80211_SEND_MGMT(ic, ni, 1254 IEEE80211_FC0_SUBTYPE_AUTH, 1); 1255 } 1256 break; 1257 } 1258 break; 1259 } 1260 break; 1261 case IEEE80211_S_ASSOC: 1262 KASSERT(ic->ic_opmode == IEEE80211_M_STA, 1263 ("switch to %s state when operating in mode %u", 1264 ieee80211_state_name[nstate], ic->ic_opmode)); 1265 switch (ostate) { 1266 case IEEE80211_S_INIT: 1267 case IEEE80211_S_SCAN: 1268 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, 1269 "%s: invalid transition\n", __func__); 1270 break; 1271 case IEEE80211_S_AUTH: 1272 case IEEE80211_S_ASSOC: 1273 IEEE80211_SEND_MGMT(ic, ni, 1274 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 1275 break; 1276 case IEEE80211_S_RUN: 1277 ieee80211_sta_leave(ic, ni); 1278 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { 1279 IEEE80211_SEND_MGMT(ic, ni, arg ? 1280 IEEE80211_FC0_SUBTYPE_REASSOC_REQ : 1281 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 1282 } 1283 break; 1284 } 1285 break; 1286 case IEEE80211_S_RUN: 1287 if (ic->ic_flags & IEEE80211_F_WPA) { 1288 /* XXX validate prerequisites */ 1289 } 1290 switch (ostate) { 1291 case IEEE80211_S_INIT: 1292 if (ic->ic_opmode == IEEE80211_M_MONITOR || 1293 ic->ic_opmode == IEEE80211_M_WDS || 1294 ic->ic_opmode == IEEE80211_M_HOSTAP) { 1295 /* 1296 * Already have a channel; bypass the 1297 * scan and startup immediately. Because 1298 * of this explicitly sync the scanner state. 1299 */ 1300 ieee80211_scan_update(ic); 1301 ieee80211_create_ibss(ic, ic->ic_curchan); 1302 break; 1303 } 1304 /* fall thru... */ 1305 case IEEE80211_S_AUTH: 1306 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, 1307 "%s: invalid transition\n", __func__); 1308 /* fall thru... */ 1309 case IEEE80211_S_RUN: 1310 break; 1311 case IEEE80211_S_SCAN: /* adhoc/hostap mode */ 1312 case IEEE80211_S_ASSOC: /* infra mode */ 1313 KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates, 1314 ("%s: bogus xmit rate %u setup\n", __func__, 1315 ni->ni_txrate)); 1316#ifdef IEEE80211_DEBUG 1317 if (ieee80211_msg_debug(ic)) { 1318 if (ic->ic_opmode == IEEE80211_M_STA) 1319 if_printf(ifp, "associated "); 1320 else 1321 if_printf(ifp, "synchronized "); 1322 printf("with %s ssid ", 1323 ether_sprintf(ni->ni_bssid)); 1324 ieee80211_print_essid(ic->ic_bss->ni_essid, 1325 ni->ni_esslen); 1326 printf(" channel %d start %uMb\n", 1327 ieee80211_chan2ieee(ic, ic->ic_curchan), 1328 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate])); 1329 } 1330#endif 1331 if (ic->ic_opmode == IEEE80211_M_STA) { 1332 ieee80211_scan_assoc_success(ic, 1333 ni->ni_macaddr); 1334 ieee80211_notify_node_join(ic, ni, 1335 arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP); 1336 } 1337 if_start(ifp); /* XXX not authorized yet */ 1338 break; 1339 } 1340 if (ostate != IEEE80211_S_RUN && 1341 ic->ic_opmode == IEEE80211_M_STA && 1342 (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)) { 1343 /* 1344 * Start s/w beacon miss timer for devices w/o 1345 * hardware support. We fudge a bit here since 1346 * we're doing this in software. 1347 */ 1348 ic->ic_swbmiss_period = IEEE80211_TU_TO_TICKS( 1349 2 * ic->ic_bmissthreshold * ni->ni_intval); 1350 ic->ic_swbmiss_count = 0; 1351 callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period, 1352 ieee80211_swbmiss, ic); 1353 } 1354 /* 1355 * Start/stop the authenticator when operating as an 1356 * AP. We delay until here to allow configuration to 1357 * happen out of order. 1358 */ 1359 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */ 1360 ic->ic_auth->ia_attach != NULL) { 1361 /* XXX check failure */ 1362 ic->ic_auth->ia_attach(ic); 1363 } else if (ic->ic_auth->ia_detach != NULL) { 1364 ic->ic_auth->ia_detach(ic); 1365 } 1366 /* 1367 * When 802.1x is not in use mark the port authorized 1368 * at this point so traffic can flow. 1369 */ 1370 if (ni->ni_authmode != IEEE80211_AUTH_8021X) 1371 ieee80211_node_authorize(ni); 1372 /* 1373 * Enable inactivity processing. 1374 * XXX 1375 */ 1376 callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz, 1377 ieee80211_node_timeout, ic); 1378 break; 1379 } 1380 return 0; 1381} 1382