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