1 /* $NetBSD: ieee80211_proto.c,v 1.37 2021/07/24 21:31:38 andvar Exp $ */ 2 /*- 3 * Copyright (c) 2001 Atsushi Onoe 4 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * Alternatively, this software may be distributed under the terms of the 19 * GNU General Public License ("GPL") version 2 as published by the Free 20 * Software Foundation. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 #ifdef __FreeBSD__ 36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.23 2005/08/10 16:22:29 sam Exp $"); 37 #endif 38 #ifdef __NetBSD__ 39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.37 2021/07/24 21:31:38 andvar Exp $"); 40 #endif 41 42 /* 43 * IEEE 802.11 protocol support. 44 */ 45 46 #ifdef _KERNEL_OPT 47 #include "opt_inet.h" 48 #endif 49 50 #include <sys/param.h> 51 #include <sys/kernel.h> 52 #include <sys/systm.h> 53 54 #include <sys/socket.h> 55 #include <sys/sockio.h> 56 #include <sys/endian.h> 57 #include <sys/errno.h> 58 #include <sys/proc.h> 59 #include <sys/sysctl.h> 60 #include <sys/cpu.h> 61 62 #include <net/if.h> 63 #include <net/if_media.h> 64 #include <net/if_arp.h> 65 #include <net/if_ether.h> 66 #include <net/if_llc.h> 67 68 #include <net80211/ieee80211_netbsd.h> 69 #include <net80211/ieee80211_var.h> 70 71 #include <net/bpf.h> 72 73 #ifdef INET 74 #include <netinet/in.h> 75 #include <net/if_ether.h> 76 #endif 77 78 #include <net/route.h> 79 /* XXX tunables */ 80 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */ 81 #define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */ 82 83 #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) 84 85 const char *ieee80211_mgt_subtype_name[] = { 86 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp", 87 "probe_req", "probe_resp", "reserved#6", "reserved#7", 88 "beacon", "atim", "disassoc", "auth", 89 "deauth", "reserved#13", "reserved#14", "reserved#15" 90 }; 91 const char *ieee80211_ctl_subtype_name[] = { 92 "reserved#0", "reserved#1", "reserved#2", "reserved#3", 93 "reserved#3", "reserved#5", "reserved#6", "reserved#7", 94 "reserved#8", "reserved#9", "ps_poll", "rts", 95 "cts", "ack", "cf_end", "cf_end_ack" 96 }; 97 const char *ieee80211_state_name[IEEE80211_S_MAX] = { 98 "INIT", /* IEEE80211_S_INIT */ 99 "SCAN", /* IEEE80211_S_SCAN */ 100 "AUTH", /* IEEE80211_S_AUTH */ 101 "ASSOC", /* IEEE80211_S_ASSOC */ 102 "RUN" /* IEEE80211_S_RUN */ 103 }; 104 const char *ieee80211_wme_acnames[] = { 105 "WME_AC_BE", 106 "WME_AC_BK", 107 "WME_AC_VI", 108 "WME_AC_VO", 109 "WME_UPSD", 110 }; 111 112 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int); 113 114 void 115 ieee80211_proto_attach(struct ieee80211com *ic) 116 { 117 struct ifnet *ifp = ic->ic_ifp; 118 119 /* XXX room for crypto */ 120 ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4); 121 122 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT; 123 ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT; 124 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 125 ic->ic_bmiss_max = IEEE80211_BMISS_MAX; 126 ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT; 127 ic->ic_protmode = IEEE80211_PROT_CTSONLY; 128 ic->ic_roaming = IEEE80211_ROAMING_AUTO; 129 130 ic->ic_wme.wme_hipri_switch_hysteresis = 131 AGGRESSIVE_MODE_SWITCH_HYSTERESIS; 132 133 /* protocol state change handler */ 134 ic->ic_newstate = ieee80211_newstate; 135 136 /* initialize management frame handlers */ 137 ic->ic_recv_mgmt = ieee80211_recv_mgmt; 138 ic->ic_send_mgmt = ieee80211_send_mgmt; 139 } 140 141 void 142 ieee80211_proto_detach(struct ieee80211com *ic) 143 { 144 145 /* 146 * This should not be needed as we detach when resetting 147 * the state but be conservative here since the 148 * authenticator may do things like spawn kernel threads. 149 */ 150 if (ic->ic_auth->ia_detach) 151 ic->ic_auth->ia_detach(ic); 152 153 ieee80211_drain_ifq(&ic->ic_mgtq); 154 155 /* 156 * Detach any ACL'ator. 157 */ 158 if (ic->ic_acl != NULL) 159 ic->ic_acl->iac_detach(ic); 160 } 161 162 /* 163 * Simple-minded authenticator module support. 164 */ 165 166 #define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1) 167 /* XXX well-known names */ 168 static const char *auth_modnames[IEEE80211_AUTH_MAX] = { 169 "wlan_internal", /* IEEE80211_AUTH_NONE */ 170 "wlan_internal", /* IEEE80211_AUTH_OPEN */ 171 "wlan_internal", /* IEEE80211_AUTH_SHARED */ 172 "wlan_xauth", /* IEEE80211_AUTH_8021X */ 173 "wlan_internal", /* IEEE80211_AUTH_AUTO */ 174 "wlan_xauth", /* IEEE80211_AUTH_WPA */ 175 }; 176 static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX]; 177 178 static const struct ieee80211_authenticator auth_internal = { 179 .ia_name = "wlan_internal", 180 .ia_attach = NULL, 181 .ia_detach = NULL, 182 .ia_node_join = NULL, 183 .ia_node_leave = NULL, 184 }; 185 186 /* 187 * Setup internal authenticators once; they are never unregistered. 188 */ 189 static void 190 ieee80211_auth_setup(void) 191 { 192 ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal); 193 ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal); 194 ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal); 195 } 196 197 const struct ieee80211_authenticator * 198 ieee80211_authenticator_get(int auth) 199 { 200 static int initialized = 0; 201 if (!initialized) { 202 ieee80211_auth_setup(); 203 initialized = 1; 204 } 205 if (auth >= IEEE80211_AUTH_MAX) 206 return NULL; 207 if (authenticators[auth] == NULL) 208 ieee80211_load_module(auth_modnames[auth]); 209 return authenticators[auth]; 210 } 211 212 void 213 ieee80211_authenticator_register(int type, 214 const struct ieee80211_authenticator *auth) 215 { 216 if (type >= IEEE80211_AUTH_MAX) 217 return; 218 authenticators[type] = auth; 219 } 220 221 void 222 ieee80211_authenticator_unregister(int type) 223 { 224 225 if (type >= IEEE80211_AUTH_MAX) 226 return; 227 authenticators[type] = NULL; 228 } 229 230 /* 231 * Very simple-minded ACL module support. 232 */ 233 /* XXX just one for now */ 234 static const struct ieee80211_aclator *acl = NULL; 235 236 void 237 ieee80211_aclator_register(const struct ieee80211_aclator *iac) 238 { 239 printf("wlan: %s acl policy registered\n", iac->iac_name); 240 acl = iac; 241 } 242 243 void 244 ieee80211_aclator_unregister(const struct ieee80211_aclator *iac) 245 { 246 if (acl == iac) 247 acl = NULL; 248 printf("wlan: %s acl policy unregistered\n", iac->iac_name); 249 } 250 251 const struct ieee80211_aclator * 252 ieee80211_aclator_get(const char *name) 253 { 254 if (acl == NULL) 255 ieee80211_load_module("wlan_acl"); 256 return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL; 257 } 258 259 void 260 ieee80211_print_essid(const u_int8_t *essid, int len) 261 { 262 const u_int8_t *p; 263 int i; 264 265 if (len > IEEE80211_NWID_LEN) 266 len = IEEE80211_NWID_LEN; 267 /* determine printable or not */ 268 for (i = 0, p = essid; i < len; i++, p++) { 269 if (*p < ' ' || *p > 0x7e) 270 break; 271 } 272 if (i == len) { 273 printf("\""); 274 for (i = 0, p = essid; i < len; i++, p++) 275 printf("%c", *p); 276 printf("\""); 277 } else { 278 printf("0x"); 279 for (i = 0, p = essid; i < len; i++, p++) 280 printf("%02x", *p); 281 } 282 } 283 284 void 285 ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi) 286 { 287 const struct ieee80211_frame *wh; 288 int i; 289 290 wh = (const struct ieee80211_frame *)buf; 291 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 292 case IEEE80211_FC1_DIR_NODS: 293 printf("NODS %s", ether_sprintf(wh->i_addr2)); 294 printf("->%s", ether_sprintf(wh->i_addr1)); 295 printf("(%s)", ether_sprintf(wh->i_addr3)); 296 break; 297 case IEEE80211_FC1_DIR_TODS: 298 printf("TODS %s", ether_sprintf(wh->i_addr2)); 299 printf("->%s", ether_sprintf(wh->i_addr3)); 300 printf("(%s)", ether_sprintf(wh->i_addr1)); 301 break; 302 case IEEE80211_FC1_DIR_FROMDS: 303 printf("FRDS %s", ether_sprintf(wh->i_addr3)); 304 printf("->%s", ether_sprintf(wh->i_addr1)); 305 printf("(%s)", ether_sprintf(wh->i_addr2)); 306 break; 307 case IEEE80211_FC1_DIR_DSTODS: 308 printf("DSDS %s", ether_sprintf((const u_int8_t *)&wh[1])); 309 printf("->%s", ether_sprintf(wh->i_addr3)); 310 printf("(%s", ether_sprintf(wh->i_addr2)); 311 printf("->%s)", ether_sprintf(wh->i_addr1)); 312 break; 313 } 314 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 315 case IEEE80211_FC0_TYPE_DATA: 316 printf(" data"); 317 break; 318 case IEEE80211_FC0_TYPE_MGT: 319 printf(" %s", ieee80211_mgt_subtype_name[ 320 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) 321 >> IEEE80211_FC0_SUBTYPE_SHIFT]); 322 break; 323 default: 324 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 325 break; 326 } 327 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 328 printf(" WEP [IV"); 329 for (i = 0; i < IEEE80211_WEP_IVLEN; i++) 330 printf(" %.02x", buf[sizeof(*wh)+i]); 331 printf(" KID %u]", buf[sizeof(*wh)+i] >> 6); 332 } 333 if (rate >= 0) 334 printf(" %dM", rate / 2); 335 if (rssi >= 0) 336 printf(" +%d", rssi); 337 printf("\n"); 338 if (len > 0) { 339 for (i = 0; i < len; i++) { 340 if ((i & 1) == 0) 341 printf(" "); 342 printf("%02x", buf[i]); 343 } 344 printf("\n"); 345 } 346 } 347 348 int 349 ieee80211_fix_rate(struct ieee80211_node *ni, int flags) 350 { 351 #define RV(v) ((v) & IEEE80211_RATE_VAL) 352 struct ieee80211com *ic = ni->ni_ic; 353 int i, j, ignore, error; 354 int okrate, badrate, fixedrate; 355 struct ieee80211_rateset *srs, *nrs; 356 u_int8_t r; 357 358 /* 359 * If the fixed rate check was requested but no 360 * fixed has been defined then just remove it. 361 */ 362 if ((flags & IEEE80211_R_DOFRATE) && 363 ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) 364 flags &= ~IEEE80211_R_DOFRATE; 365 error = 0; 366 okrate = badrate = fixedrate = 0; 367 srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; 368 nrs = &ni->ni_rates; 369 for (i = 0; i < nrs->rs_nrates; ) { 370 ignore = 0; 371 if (flags & IEEE80211_R_DOSORT) { 372 /* 373 * Sort rates. 374 */ 375 for (j = i + 1; j < nrs->rs_nrates; j++) { 376 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) { 377 r = nrs->rs_rates[i]; 378 nrs->rs_rates[i] = nrs->rs_rates[j]; 379 nrs->rs_rates[j] = r; 380 } 381 } 382 } 383 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL; 384 badrate = r; 385 if (flags & IEEE80211_R_DOFRATE) { 386 /* 387 * Check any fixed rate is included. 388 */ 389 if (r == RV(srs->rs_rates[ic->ic_fixed_rate])) 390 fixedrate = r; 391 } 392 if (flags & IEEE80211_R_DONEGO) { 393 /* 394 * Check against supported rates. 395 */ 396 for (j = 0; j < srs->rs_nrates; j++) { 397 if (r == RV(srs->rs_rates[j])) { 398 /* 399 * Overwrite with the supported rate 400 * value so any basic rate bit is set. 401 * This insures that response we send 402 * to stations have the necessary basic 403 * rate bit set. 404 */ 405 nrs->rs_rates[i] = srs->rs_rates[j]; 406 break; 407 } 408 } 409 if (j == srs->rs_nrates) { 410 /* 411 * A rate in the node's rate set is not 412 * supported. If this is a basic rate and we 413 * are operating as an AP then this is an error. 414 * Otherwise we just discard/ignore the rate. 415 * Note that this is important for 11b stations 416 * when they want to associate with an 11g AP. 417 */ 418 #ifndef IEEE80211_NO_HOSTAP 419 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 420 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) 421 error++; 422 #endif /* !IEEE80211_NO_HOSTAP */ 423 ignore++; 424 } 425 } 426 if (flags & IEEE80211_R_DODEL) { 427 /* 428 * Delete unacceptable rates. 429 */ 430 if (ignore) { 431 nrs->rs_nrates--; 432 for (j = i; j < nrs->rs_nrates; j++) 433 nrs->rs_rates[j] = nrs->rs_rates[j + 1]; 434 nrs->rs_rates[j] = 0; 435 continue; 436 } 437 } 438 if (!ignore) { 439 okrate = nrs->rs_rates[i]; 440 ni->ni_txrate = i; 441 } 442 i++; 443 } 444 if (okrate == 0 || error != 0 || 445 ((flags & IEEE80211_R_DOFRATE) && fixedrate == 0)) 446 return badrate | IEEE80211_RATE_BASIC; 447 else 448 return RV(okrate); 449 #undef RV 450 } 451 452 /* 453 * Reset 11g-related state. 454 */ 455 void 456 ieee80211_reset_erp(struct ieee80211com *ic) 457 { 458 ic->ic_flags &= ~IEEE80211_F_USEPROT; 459 ic->ic_nonerpsta = 0; 460 ic->ic_longslotsta = 0; 461 /* 462 * Short slot time is enabled only when operating in 11g 463 * and not in an IBSS. We must also honor whether or not 464 * the driver is capable of doing it. 465 */ 466 ieee80211_set_shortslottime(ic, 467 ic->ic_curmode == IEEE80211_MODE_11A || 468 (ic->ic_curmode == IEEE80211_MODE_11G && 469 ic->ic_opmode == IEEE80211_M_HOSTAP && 470 (ic->ic_caps & IEEE80211_C_SHSLOT))); 471 /* 472 * Set short preamble and ERP barker-preamble flags. 473 */ 474 if (ic->ic_curmode == IEEE80211_MODE_11A || 475 (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) { 476 ic->ic_flags |= IEEE80211_F_SHPREAMBLE; 477 ic->ic_flags &= ~IEEE80211_F_USEBARKER; 478 } else { 479 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; 480 ic->ic_flags |= IEEE80211_F_USEBARKER; 481 } 482 } 483 484 /* 485 * Set the short slot time state and notify the driver. 486 */ 487 void 488 ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff) 489 { 490 if (onoff) 491 ic->ic_flags |= IEEE80211_F_SHSLOT; 492 else 493 ic->ic_flags &= ~IEEE80211_F_SHSLOT; 494 /* notify driver */ 495 if (ic->ic_updateslot != NULL) 496 ic->ic_updateslot(ic->ic_ifp); 497 } 498 499 /* 500 * Check if the specified rate set supports ERP. 501 * NB: the rate set is assumed to be sorted. 502 */ 503 int 504 ieee80211_iserp_rateset(struct ieee80211com *ic, 505 struct ieee80211_rateset *rs) 506 { 507 #define N(a) (sizeof(a) / sizeof(a[0])) 508 static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 }; 509 int i, j; 510 511 if (rs->rs_nrates < N(rates)) 512 return 0; 513 for (i = 0; i < N(rates); i++) { 514 for (j = 0; j < rs->rs_nrates; j++) { 515 int r = rs->rs_rates[j] & IEEE80211_RATE_VAL; 516 if (rates[i] == r) 517 goto next; 518 if (r > rates[i]) 519 return 0; 520 } 521 return 0; 522 next: 523 ; 524 } 525 return 1; 526 #undef N 527 } 528 529 /* 530 * Mark the basic rates for the 11g rate table based on the 531 * operating mode. For real 11g we mark all the 11b rates 532 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only 533 * 11b rates. There's also a pseudo 11a-mode used to mark only 534 * the basic OFDM rates. 535 */ 536 void 537 ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode) 538 { 539 static const struct ieee80211_rateset basic[] = { 540 { .rs_nrates = 0 }, /* IEEE80211_MODE_AUTO */ 541 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */ 542 { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */ 543 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */ 544 { .rs_nrates = 0 }, /* IEEE80211_MODE_FH */ 545 /* IEEE80211_MODE_PUREG (not yet) */ 546 { 7, { 2, 4, 11, 22, 12, 24, 48 } }, 547 }; 548 int i, j; 549 550 for (i = 0; i < rs->rs_nrates; i++) { 551 rs->rs_rates[i] &= IEEE80211_RATE_VAL; 552 for (j = 0; j < basic[mode].rs_nrates; j++) 553 if (basic[mode].rs_rates[j] == rs->rs_rates[i]) { 554 rs->rs_rates[i] |= IEEE80211_RATE_BASIC; 555 break; 556 } 557 } 558 } 559 560 /* 561 * WME protocol support. The following parameters come from the spec. 562 */ 563 typedef struct phyParamType { 564 u_int8_t aifsn; 565 u_int8_t logcwmin; 566 u_int8_t logcwmax; 567 u_int16_t txopLimit; 568 u_int8_t acm; 569 } paramType; 570 571 static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = { 572 { 3, 4, 6, 0, 0, }, /* IEEE80211_MODE_AUTO */ 573 { 3, 4, 6, 0, 0, }, /* IEEE80211_MODE_11A */ 574 { 3, 5, 7, 0, 0, }, /* IEEE80211_MODE_11B */ 575 { 3, 4, 6, 0, 0, }, /* IEEE80211_MODE_11G */ 576 { 3, 5, 7, 0, 0, }, /* IEEE80211_MODE_FH */ 577 { 2, 3, 5, 0, 0, }, /* IEEE80211_MODE_TURBO_A */ 578 { 2, 3, 5, 0, 0, }, /* IEEE80211_MODE_TURBO_G */ 579 }; 580 static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = { 581 { 7, 4, 10, 0, 0, }, /* IEEE80211_MODE_AUTO */ 582 { 7, 4, 10, 0, 0, }, /* IEEE80211_MODE_11A */ 583 { 7, 5, 10, 0, 0, }, /* IEEE80211_MODE_11B */ 584 { 7, 4, 10, 0, 0, }, /* IEEE80211_MODE_11G */ 585 { 7, 5, 10, 0, 0, }, /* IEEE80211_MODE_FH */ 586 { 7, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_A */ 587 { 7, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_G */ 588 }; 589 static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = { 590 { 1, 3, 4, 94, 0, }, /* IEEE80211_MODE_AUTO */ 591 { 1, 3, 4, 94, 0, }, /* IEEE80211_MODE_11A */ 592 { 1, 4, 5, 188, 0, }, /* IEEE80211_MODE_11B */ 593 { 1, 3, 4, 94, 0, }, /* IEEE80211_MODE_11G */ 594 { 1, 4, 5, 188, 0, }, /* IEEE80211_MODE_FH */ 595 { 1, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_A */ 596 { 1, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_G */ 597 }; 598 static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = { 599 { 1, 2, 3, 47, 0, }, /* IEEE80211_MODE_AUTO */ 600 { 1, 2, 3, 47, 0, }, /* IEEE80211_MODE_11A */ 601 { 1, 3, 4, 102, 0, }, /* IEEE80211_MODE_11B */ 602 { 1, 2, 3, 47, 0, }, /* IEEE80211_MODE_11G */ 603 { 1, 3, 4, 102, 0, }, /* IEEE80211_MODE_FH */ 604 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_A */ 605 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_G */ 606 }; 607 608 static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = { 609 { 3, 4, 10, 0, 0, }, /* IEEE80211_MODE_AUTO */ 610 { 3, 4, 10, 0, 0, }, /* IEEE80211_MODE_11A */ 611 { 3, 5, 10, 0, 0, }, /* IEEE80211_MODE_11B */ 612 { 3, 4, 10, 0, 0, }, /* IEEE80211_MODE_11G */ 613 { 3, 5, 10, 0, 0, }, /* IEEE80211_MODE_FH */ 614 { 2, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_A */ 615 { 2, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_G */ 616 }; 617 static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = { 618 { 2, 3, 4, 94, 0, }, /* IEEE80211_MODE_AUTO */ 619 { 2, 3, 4, 94, 0, }, /* IEEE80211_MODE_11A */ 620 { 2, 4, 5, 188, 0, }, /* IEEE80211_MODE_11B */ 621 { 2, 3, 4, 94, 0, }, /* IEEE80211_MODE_11G */ 622 { 2, 4, 5, 188, 0, }, /* IEEE80211_MODE_FH */ 623 { 2, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_A */ 624 { 2, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_G */ 625 }; 626 static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = { 627 { 2, 2, 3, 47, 0, }, /* IEEE80211_MODE_AUTO */ 628 { 2, 2, 3, 47, 0, }, /* IEEE80211_MODE_11A */ 629 { 2, 3, 4, 102, 0, }, /* IEEE80211_MODE_11B */ 630 { 2, 2, 3, 47, 0, }, /* IEEE80211_MODE_11G */ 631 { 2, 3, 4, 102, 0, }, /* IEEE80211_MODE_FH */ 632 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_A */ 633 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_G */ 634 }; 635 636 void 637 ieee80211_wme_initparams(struct ieee80211com *ic) 638 { 639 struct ieee80211_wme_state *wme = &ic->ic_wme; 640 const paramType *pPhyParam, *pBssPhyParam; 641 struct wmeParams *wmep; 642 int i; 643 644 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 645 return; 646 647 for (i = 0; i < WME_NUM_AC; i++) { 648 switch (i) { 649 case WME_AC_BK: 650 pPhyParam = &phyParamForAC_BK[ic->ic_curmode]; 651 pBssPhyParam = &phyParamForAC_BK[ic->ic_curmode]; 652 break; 653 case WME_AC_VI: 654 pPhyParam = &phyParamForAC_VI[ic->ic_curmode]; 655 pBssPhyParam = &bssPhyParamForAC_VI[ic->ic_curmode]; 656 break; 657 case WME_AC_VO: 658 pPhyParam = &phyParamForAC_VO[ic->ic_curmode]; 659 pBssPhyParam = &bssPhyParamForAC_VO[ic->ic_curmode]; 660 break; 661 case WME_AC_BE: 662 default: 663 pPhyParam = &phyParamForAC_BE[ic->ic_curmode]; 664 pBssPhyParam = &bssPhyParamForAC_BE[ic->ic_curmode]; 665 break; 666 } 667 668 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 669 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 670 wmep->wmep_acm = pPhyParam->acm; 671 wmep->wmep_aifsn = pPhyParam->aifsn; 672 wmep->wmep_logcwmin = pPhyParam->logcwmin; 673 wmep->wmep_logcwmax = pPhyParam->logcwmax; 674 wmep->wmep_txopLimit = pPhyParam->txopLimit; 675 } else { 676 wmep->wmep_acm = pBssPhyParam->acm; 677 wmep->wmep_aifsn = pBssPhyParam->aifsn; 678 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 679 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 680 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 681 682 } 683 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 684 "%s: %s chan [acm %u aifsn %u log2(cwmin) %u " 685 "log2(cwmax) %u txpoLimit %u]\n", __func__ 686 , ieee80211_wme_acnames[i] 687 , wmep->wmep_acm 688 , wmep->wmep_aifsn 689 , wmep->wmep_logcwmin 690 , wmep->wmep_logcwmax 691 , wmep->wmep_txopLimit 692 ); 693 694 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 695 wmep->wmep_acm = pBssPhyParam->acm; 696 wmep->wmep_aifsn = pBssPhyParam->aifsn; 697 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 698 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 699 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 700 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 701 "%s: %s bss [acm %u aifsn %u log2(cwmin) %u " 702 "log2(cwmax) %u txpoLimit %u]\n", __func__ 703 , ieee80211_wme_acnames[i] 704 , wmep->wmep_acm 705 , wmep->wmep_aifsn 706 , wmep->wmep_logcwmin 707 , wmep->wmep_logcwmax 708 , wmep->wmep_txopLimit 709 ); 710 } 711 /* NB: check ic_bss to avoid NULL deref on initial attach */ 712 if (ic->ic_bss != NULL) { 713 /* 714 * Calculate aggressive mode switching threshold based 715 * on beacon interval. This doesn't need locking since 716 * we're only called before entering the RUN state at 717 * which point we start sending beacon frames. 718 */ 719 wme->wme_hipri_switch_thresh = 720 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100; 721 ieee80211_wme_updateparams(ic); 722 } 723 } 724 725 /* 726 * Update WME parameters for ourself and the BSS. 727 */ 728 void 729 ieee80211_wme_updateparams_locked(struct ieee80211com *ic) 730 { 731 static const paramType phyParam[IEEE80211_MODE_MAX] = { 732 { 2, 4, 10, 64, 0, }, /* IEEE80211_MODE_AUTO */ 733 { 2, 4, 10, 64, 0, }, /* IEEE80211_MODE_11A */ 734 { 2, 5, 10, 64, 0, }, /* IEEE80211_MODE_11B */ 735 { 2, 4, 10, 64, 0, }, /* IEEE80211_MODE_11G */ 736 { 2, 5, 10, 64, 0, }, /* IEEE80211_MODE_FH */ 737 { 1, 3, 10, 64, 0, }, /* IEEE80211_MODE_TURBO_A */ 738 { 1, 3, 10, 64, 0, }, /* IEEE80211_MODE_TURBO_G */ 739 }; 740 struct ieee80211_wme_state *wme = &ic->ic_wme; 741 const struct wmeParams *wmep; 742 struct wmeParams *chanp, *bssp; 743 int i; 744 745 /* set up the channel access parameters for the physical device */ 746 for (i = 0; i < WME_NUM_AC; i++) { 747 chanp = &wme->wme_chanParams.cap_wmeParams[i]; 748 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 749 chanp->wmep_aifsn = wmep->wmep_aifsn; 750 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 751 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 752 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 753 754 chanp = &wme->wme_bssChanParams.cap_wmeParams[i]; 755 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 756 chanp->wmep_aifsn = wmep->wmep_aifsn; 757 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 758 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 759 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 760 } 761 762 /* 763 * This implements aggressive mode as found in certain 764 * vendors' AP's. When there is significant high 765 * priority (VI/VO) traffic in the BSS throttle back BE 766 * traffic by using conservative parameters. Otherwise 767 * BE uses aggressive params to optimize performance of 768 * legacy/non-QoS traffic. 769 */ 770 if ((ic->ic_opmode == IEEE80211_M_HOSTAP && 771 (wme->wme_flags & WME_F_AGGRMODE) == 0) || 772 (ic->ic_opmode != IEEE80211_M_HOSTAP && 773 (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) || 774 (ic->ic_flags & IEEE80211_F_WME) == 0) { 775 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE]; 776 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE]; 777 778 chanp->wmep_aifsn = bssp->wmep_aifsn = 779 phyParam[ic->ic_curmode].aifsn; 780 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 781 phyParam[ic->ic_curmode].logcwmin; 782 chanp->wmep_logcwmax = bssp->wmep_logcwmax = 783 phyParam[ic->ic_curmode].logcwmax; 784 chanp->wmep_txopLimit = bssp->wmep_txopLimit = 785 (ic->ic_caps & IEEE80211_C_BURST) ? 786 phyParam[ic->ic_curmode].txopLimit : 0; 787 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 788 "%s: %s [acm %u aifsn %u log2(cwmin) %u " 789 "log2(cwmax) %u txpoLimit %u]\n", __func__ 790 , ieee80211_wme_acnames[WME_AC_BE] 791 , chanp->wmep_acm 792 , chanp->wmep_aifsn 793 , chanp->wmep_logcwmin 794 , chanp->wmep_logcwmax 795 , chanp->wmep_txopLimit 796 ); 797 } 798 799 #ifndef IEEE80211_NO_HOSTAP 800 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 801 ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) == 0) { 802 static const u_int8_t logCwMin[IEEE80211_MODE_MAX] = { 803 3, /* IEEE80211_MODE_AUTO */ 804 3, /* IEEE80211_MODE_11A */ 805 4, /* IEEE80211_MODE_11B */ 806 3, /* IEEE80211_MODE_11G */ 807 4, /* IEEE80211_MODE_FH */ 808 3, /* IEEE80211_MODE_TURBO_A */ 809 3, /* IEEE80211_MODE_TURBO_G */ 810 }; 811 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE]; 812 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE]; 813 814 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 815 logCwMin[ic->ic_curmode]; 816 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 817 "%s: %s log2(cwmin) %u\n", __func__ 818 , ieee80211_wme_acnames[WME_AC_BE] 819 , chanp->wmep_logcwmin 820 ); 821 } 822 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */ 823 /* 824 * Arrange for a beacon update and bump the parameter 825 * set number so associated stations load the new values. 826 */ 827 wme->wme_bssChanParams.cap_info = 828 (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT; 829 ic->ic_flags |= IEEE80211_F_WMEUPDATE; 830 } 831 #endif /* !IEEE80211_NO_HOSTAP */ 832 833 wme->wme_update(ic); 834 835 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 836 "%s: WME params updated, cap_info 0x%x\n", __func__, 837 ic->ic_opmode == IEEE80211_M_STA ? 838 wme->wme_wmeChanParams.cap_info : 839 wme->wme_bssChanParams.cap_info); 840 } 841 842 void 843 ieee80211_wme_updateparams(struct ieee80211com *ic) 844 { 845 846 if (ic->ic_caps & IEEE80211_C_WME) { 847 IEEE80211_BEACON_LOCK(ic); 848 ieee80211_wme_updateparams_locked(ic); 849 IEEE80211_BEACON_UNLOCK(ic); 850 } 851 } 852 853 #ifndef IEEE80211_NO_HOSTAP 854 static void 855 sta_disassoc(void *arg, struct ieee80211_node *ni) 856 { 857 struct ieee80211com *ic = arg; 858 859 if (ni->ni_associd != 0) { 860 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC, 861 IEEE80211_REASON_ASSOC_LEAVE); 862 ieee80211_node_leave(ic, ni); 863 } 864 } 865 #endif /* !IEEE80211_NO_HOSTAP */ 866 867 void 868 ieee80211_beacon_miss(struct ieee80211com *ic) 869 { 870 871 if (ic->ic_flags & IEEE80211_F_SCAN) { 872 /* XXX check ic_curchan != ic_bsschan? */ 873 return; 874 } 875 IEEE80211_DPRINTF(ic, 876 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, 877 "%s\n", "beacon miss"); 878 879 /* 880 * Our handling is only meaningful for stations that are 881 * associated; any other conditions else will be handled 882 * through different means (e.g. the tx timeout on mgt frames). 883 */ 884 if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN) 885 return; 886 887 if (++ic->ic_bmiss_count < ic->ic_bmiss_max) { 888 /* 889 * Send a directed probe req before falling back to a scan; 890 * if we receive a response ic_bmiss_count will be reset. 891 * Some cards mistakenly report beacon miss so this avoids 892 * the expensive scan if the ap is still there. 893 */ 894 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr, 895 ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid, 896 ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen, 897 ic->ic_opt_ie, ic->ic_opt_ie_len); 898 return; 899 } 900 ic->ic_bmiss_count = 0; 901 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 902 } 903 904 #ifndef IEEE80211_NO_HOSTAP 905 static void 906 sta_deauth(void *arg, struct ieee80211_node *ni) 907 { 908 struct ieee80211com *ic = arg; 909 910 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, 911 IEEE80211_REASON_ASSOC_LEAVE); 912 } 913 #endif /* !IEEE80211_NO_HOSTAP */ 914 915 static int 916 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 917 { 918 struct ifnet *ifp = ic->ic_ifp; 919 struct ieee80211_node *ni; 920 enum ieee80211_state ostate; 921 922 KASSERT(!cpu_intr_p()); 923 924 ostate = ic->ic_state; 925 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__, 926 ieee80211_state_name[ostate], ieee80211_state_name[nstate]); 927 ic->ic_state = nstate; /* state transition */ 928 ni = ic->ic_bss; /* NB: no reference held */ 929 switch (nstate) { 930 case IEEE80211_S_INIT: 931 switch (ostate) { 932 case IEEE80211_S_INIT: 933 break; 934 case IEEE80211_S_RUN: 935 switch (ic->ic_opmode) { 936 case IEEE80211_M_STA: 937 IEEE80211_SEND_MGMT(ic, ni, 938 IEEE80211_FC0_SUBTYPE_DISASSOC, 939 IEEE80211_REASON_ASSOC_LEAVE); 940 ieee80211_sta_leave(ic, ni); 941 break; 942 case IEEE80211_M_HOSTAP: 943 #ifndef IEEE80211_NO_HOSTAP 944 ieee80211_iterate_nodes(&ic->ic_sta, 945 sta_disassoc, ic); 946 #endif /* !IEEE80211_NO_HOSTAP */ 947 break; 948 default: 949 break; 950 } 951 goto reset; 952 case IEEE80211_S_ASSOC: 953 switch (ic->ic_opmode) { 954 case IEEE80211_M_STA: 955 IEEE80211_SEND_MGMT(ic, ni, 956 IEEE80211_FC0_SUBTYPE_DEAUTH, 957 IEEE80211_REASON_AUTH_LEAVE); 958 break; 959 case IEEE80211_M_HOSTAP: 960 #ifndef IEEE80211_NO_HOSTAP 961 ieee80211_iterate_nodes(&ic->ic_sta, 962 sta_deauth, ic); 963 #endif /* !IEEE80211_NO_HOSTAP */ 964 break; 965 default: 966 break; 967 } 968 goto reset; 969 case IEEE80211_S_SCAN: 970 ieee80211_cancel_scan(ic); 971 goto reset; 972 case IEEE80211_S_AUTH: 973 reset: 974 ic->ic_mgt_timer = 0; 975 ieee80211_drain_ifq(&ic->ic_mgtq); 976 ieee80211_reset_bss(ic); 977 break; 978 } 979 if (ic->ic_auth->ia_detach != NULL) 980 ic->ic_auth->ia_detach(ic); 981 break; 982 case IEEE80211_S_SCAN: 983 switch (ostate) { 984 case IEEE80211_S_INIT: 985 if ((ic->ic_opmode == IEEE80211_M_HOSTAP || 986 ic->ic_opmode == IEEE80211_M_IBSS || 987 ic->ic_opmode == IEEE80211_M_AHDEMO) && 988 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 989 /* 990 * AP operation and we already have a channel; 991 * bypass the scan and startup immediately. 992 */ 993 ieee80211_create_ibss(ic, ic->ic_des_chan); 994 } else { 995 ieee80211_begin_scan(ic, arg); 996 } 997 break; 998 case IEEE80211_S_SCAN: 999 /* 1000 * Scan next. If doing an active scan probe 1001 * for the requested ap (if any). 1002 */ 1003 if (ic->ic_flags & IEEE80211_F_ASCAN) 1004 ieee80211_probe_curchan(ic, 0); 1005 break; 1006 case IEEE80211_S_RUN: 1007 /* beacon miss */ 1008 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, 1009 "no recent beacons from %s; rescanning\n", 1010 ether_sprintf(ic->ic_bss->ni_bssid)); 1011 ieee80211_sta_leave(ic, ni); 1012 ic->ic_flags &= ~IEEE80211_F_SIBSS; /* XXX */ 1013 /* FALLTHRU */ 1014 case IEEE80211_S_AUTH: 1015 case IEEE80211_S_ASSOC: 1016 /* timeout restart scan */ 1017 ni = ieee80211_find_node(&ic->ic_scan, 1018 ic->ic_bss->ni_macaddr); 1019 if (ni != NULL) { 1020 ni->ni_fails++; 1021 ieee80211_unref_node(&ni); 1022 } 1023 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) 1024 ieee80211_begin_scan(ic, arg); 1025 break; 1026 } 1027 break; 1028 case IEEE80211_S_AUTH: 1029 switch (ostate) { 1030 case IEEE80211_S_INIT: 1031 case IEEE80211_S_SCAN: 1032 IEEE80211_SEND_MGMT(ic, ni, 1033 IEEE80211_FC0_SUBTYPE_AUTH, 1); 1034 break; 1035 case IEEE80211_S_AUTH: 1036 case IEEE80211_S_ASSOC: 1037 switch (arg) { 1038 case IEEE80211_FC0_SUBTYPE_AUTH: 1039 /* ??? */ 1040 IEEE80211_SEND_MGMT(ic, ni, 1041 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1042 break; 1043 case IEEE80211_FC0_SUBTYPE_DEAUTH: 1044 /* ignore and retry scan on timeout */ 1045 break; 1046 } 1047 break; 1048 case IEEE80211_S_RUN: 1049 switch (arg) { 1050 case IEEE80211_FC0_SUBTYPE_AUTH: 1051 IEEE80211_SEND_MGMT(ic, ni, 1052 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1053 ic->ic_state = ostate; /* stay RUN */ 1054 break; 1055 case IEEE80211_FC0_SUBTYPE_DEAUTH: 1056 ieee80211_sta_leave(ic, ni); 1057 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { 1058 /* try to reauth */ 1059 IEEE80211_SEND_MGMT(ic, ni, 1060 IEEE80211_FC0_SUBTYPE_AUTH, 1); 1061 } 1062 break; 1063 } 1064 break; 1065 } 1066 break; 1067 case IEEE80211_S_ASSOC: 1068 switch (ostate) { 1069 case IEEE80211_S_INIT: 1070 case IEEE80211_S_SCAN: 1071 case IEEE80211_S_ASSOC: 1072 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, 1073 "%s: invalid transition\n", __func__); 1074 break; 1075 case IEEE80211_S_AUTH: 1076 IEEE80211_SEND_MGMT(ic, ni, 1077 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 1078 break; 1079 case IEEE80211_S_RUN: 1080 ieee80211_sta_leave(ic, ni); 1081 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { 1082 IEEE80211_SEND_MGMT(ic, ni, 1083 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); 1084 } 1085 break; 1086 } 1087 break; 1088 case IEEE80211_S_RUN: 1089 if (ic->ic_flags & IEEE80211_F_WPA) { 1090 /* XXX validate prerequisites */ 1091 } 1092 switch (ostate) { 1093 case IEEE80211_S_INIT: 1094 if (ic->ic_opmode == IEEE80211_M_MONITOR) 1095 break; 1096 /* fall thru... */ 1097 case IEEE80211_S_AUTH: 1098 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, 1099 "%s: invalid transition\n", __func__); 1100 /* fall thru... */ 1101 case IEEE80211_S_RUN: 1102 break; 1103 case IEEE80211_S_SCAN: /* adhoc/hostap mode */ 1104 case IEEE80211_S_ASSOC: /* infra mode */ 1105 IASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates, 1106 ("%s: bogus xmit rate %u setup ostate %x " 1107 "nstate %x\n", __func__, ni->ni_txrate, 1108 ostate, nstate)); 1109 #ifdef IEEE80211_DEBUG 1110 if (ieee80211_msg_debug(ic)) { 1111 if (ic->ic_opmode == IEEE80211_M_STA) 1112 if_printf(ifp, "associated "); 1113 else 1114 if_printf(ifp, "synchronized "); 1115 printf("with %s ssid ", 1116 ether_sprintf(ni->ni_bssid)); 1117 ieee80211_print_essid(ic->ic_bss->ni_essid, 1118 ni->ni_esslen); 1119 printf(" channel %d start %uMb\n", 1120 ieee80211_chan2ieee(ic, ic->ic_curchan), 1121 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate])); 1122 } 1123 #endif 1124 ic->ic_mgt_timer = 0; 1125 if (ic->ic_opmode == IEEE80211_M_STA) 1126 ieee80211_notify_node_join(ic, ni, 1127 arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP); 1128 if_start_lock(ifp); /* XXX not authorized yet */ 1129 break; 1130 } 1131 /* 1132 * Start/stop the authenticator when operating as an 1133 * AP. We delay until here to allow configuration to 1134 * happen out of order. 1135 */ 1136 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */ 1137 ic->ic_auth->ia_attach != NULL) { 1138 /* XXX check failure */ 1139 ic->ic_auth->ia_attach(ic); 1140 } else if (ic->ic_auth->ia_detach != NULL) { 1141 ic->ic_auth->ia_detach(ic); 1142 } 1143 /* 1144 * When 802.1x is not in use mark the port authorized 1145 * at this point so traffic can flow. 1146 */ 1147 if (ni->ni_authmode != IEEE80211_AUTH_8021X) 1148 ieee80211_node_authorize(ni); 1149 /* 1150 * Enable inactivity processing. 1151 * XXX 1152 */ 1153 ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT; 1154 ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT; 1155 break; 1156 } 1157 return 0; 1158 } 1159