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