ieee80211_proto.c revision 153349
150276Speter/*- 2262629Sdelphij * Copyright (c) 2001 Atsushi Onoe 350276Speter * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 450276Speter * All rights reserved. 550276Speter * 650276Speter * Redistribution and use in source and binary forms, with or without 750276Speter * modification, are permitted provided that the following conditions 850276Speter * are met: 950276Speter * 1. Redistributions of source code must retain the above copyright 1050276Speter * notice, this list of conditions and the following disclaimer. 1150276Speter * 2. Redistributions in binary form must reproduce the above copyright 1250276Speter * notice, this list of conditions and the following disclaimer in the 1350276Speter * documentation and/or other materials provided with the distribution. 1450276Speter * 3. The name of the author may not be used to endorse or promote products 1550276Speter * derived from this software without specific prior written permission. 1650276Speter * 1750276Speter * Alternatively, this software may be distributed under the terms of the 1850276Speter * GNU General Public License ("GPL") version 2 as published by the Free 1950276Speter * Software Foundation. 2050276Speter * 2150276Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2250276Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2350276Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2450276Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2550276Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2650276Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2750276Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2850276Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2950276Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30262629Sdelphij * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3150276Speter */ 3250276Speter 3350276Speter#include <sys/cdefs.h> 3450276Speter__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_proto.c 153349 2005-12-12 18:04:44Z sam $"); 3550276Speter 36262629Sdelphij/* 3750276Speter * IEEE 802.11 protocol support. 38166124Srafan */ 39166124Srafan 40166124Srafan#include "opt_inet.h" 41166124Srafan 4250276Speter#include <sys/param.h> 43166124Srafan#include <sys/kernel.h> 44166124Srafan#include <sys/systm.h> 45166124Srafan 46166124Srafan#include <sys/socket.h> 47166124Srafan 48166124Srafan#include <net/if.h> 49166124Srafan#include <net/if_media.h> 50166124Srafan#include <net/ethernet.h> /* XXX for ether_sprintf */ 51166124Srafan 52166124Srafan#include <net80211/ieee80211_var.h> 53166124Srafan 54166124Srafan/* XXX tunables */ 55166124Srafan#define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */ 56166124Srafan#define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */ 57166124Srafan 58166124Srafan#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) 59166124Srafan 60166124Srafanconst char *ieee80211_mgt_subtype_name[] = { 61166124Srafan "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp", 62166124Srafan "probe_req", "probe_resp", "reserved#6", "reserved#7", 63166124Srafan "beacon", "atim", "disassoc", "auth", 64166124Srafan "deauth", "reserved#13", "reserved#14", "reserved#15" 65166124Srafan}; 66166124Srafanconst char *ieee80211_ctl_subtype_name[] = { 67166124Srafan "reserved#0", "reserved#1", "reserved#2", "reserved#3", 68166124Srafan "reserved#3", "reserved#5", "reserved#6", "reserved#7", 69166124Srafan "reserved#8", "reserved#9", "ps_poll", "rts", 70166124Srafan "cts", "ack", "cf_end", "cf_end_ack" 71166124Srafan}; 72166124Srafanconst char *ieee80211_state_name[IEEE80211_S_MAX] = { 73166124Srafan "INIT", /* IEEE80211_S_INIT */ 74166124Srafan "SCAN", /* IEEE80211_S_SCAN */ 75166124Srafan "AUTH", /* IEEE80211_S_AUTH */ 76166124Srafan "ASSOC", /* IEEE80211_S_ASSOC */ 77166124Srafan "RUN" /* IEEE80211_S_RUN */ 7850276Speter}; 7950276Speterconst char *ieee80211_wme_acnames[] = { 80262629Sdelphij "WME_AC_BE", 81262629Sdelphij "WME_AC_BK", 82262629Sdelphij "WME_AC_VI", 83262629Sdelphij "WME_AC_VO", 84262629Sdelphij "WME_UPSD", 8550276Speter}; 8650276Speter 8750276Speterstatic int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int); 8850276Speter 8950276Spetervoid 9050276Speterieee80211_proto_attach(struct ieee80211com *ic) 9150276Speter{ 92262629Sdelphij struct ifnet *ifp = ic->ic_ifp; 93262629Sdelphij 94262629Sdelphij /* XXX room for crypto */ 95262629Sdelphij ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4); 96262629Sdelphij 9750276Speter ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT; 9850276Speter ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT; 9950276Speter ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 10050276Speter ic->ic_bmiss_max = IEEE80211_BMISS_MAX; 10150276Speter ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT; 10250276Speter ic->ic_protmode = IEEE80211_PROT_CTSONLY; 10350276Speter ic->ic_roaming = IEEE80211_ROAMING_AUTO; 10450276Speter 10550276Speter ic->ic_wme.wme_hipri_switch_hysteresis = 10650276Speter AGGRESSIVE_MODE_SWITCH_HYSTERESIS; 10750276Speter 10850276Speter mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_xname, "mgmt send q", MTX_DEF); 10950276Speter 11050276Speter /* protocol state change handler */ 11150276Speter ic->ic_newstate = ieee80211_newstate; 11250276Speter 11350276Speter /* initialize management frame handlers */ 11450276Speter ic->ic_recv_mgmt = ieee80211_recv_mgmt; 11550276Speter ic->ic_send_mgmt = ieee80211_send_mgmt; 11650276Speter} 11750276Speter 11850276Spetervoid 11950276Speterieee80211_proto_detach(struct ieee80211com *ic) 12050276Speter{ 12150276Speter 12250276Speter /* 12350276Speter * This should not be needed as we detach when reseting 12450276Speter * the state but be conservative here since the 12550276Speter * authenticator may do things like spawn kernel threads. 12650276Speter */ 12750276Speter if (ic->ic_auth->ia_detach) 12850276Speter ic->ic_auth->ia_detach(ic); 12950276Speter 13050276Speter IF_DRAIN(&ic->ic_mgtq); 13150276Speter mtx_destroy(&ic->ic_mgtq.ifq_mtx); 13250276Speter 13350276Speter /* 13450276Speter * Detach any ACL'ator. 13550276Speter */ 13650276Speter if (ic->ic_acl != NULL) 13750276Speter ic->ic_acl->iac_detach(ic); 13850276Speter} 13950276Speter 14050276Speter/* 14150276Speter * Simple-minded authenticator module support. 14250276Speter */ 14350276Speter 14450276Speter#define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1) 14550276Speter/* XXX well-known names */ 14650276Speterstatic const char *auth_modnames[IEEE80211_AUTH_MAX] = { 14750276Speter "wlan_internal", /* IEEE80211_AUTH_NONE */ 14850276Speter "wlan_internal", /* IEEE80211_AUTH_OPEN */ 14950276Speter "wlan_internal", /* IEEE80211_AUTH_SHARED */ 15050276Speter "wlan_xauth", /* IEEE80211_AUTH_8021X */ 15150276Speter "wlan_internal", /* IEEE80211_AUTH_AUTO */ 15250276Speter "wlan_xauth", /* IEEE80211_AUTH_WPA */ 15350276Speter}; 15450276Speterstatic const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX]; 15550276Speter 15650276Speterstatic const struct ieee80211_authenticator auth_internal = { 15750276Speter .ia_name = "wlan_internal", 15850276Speter .ia_attach = NULL, 15950276Speter .ia_detach = NULL, 16050276Speter .ia_node_join = NULL, 16150276Speter .ia_node_leave = NULL, 16250276Speter}; 16350276Speter 16450276Speter/* 16550276Speter * Setup internal authenticators once; they are never unregistered. 16650276Speter */ 16750276Speterstatic void 16850276Speterieee80211_auth_setup(void) 16950276Speter{ 170262629Sdelphij ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal); 171262629Sdelphij ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal); 172262629Sdelphij ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal); 173262629Sdelphij} 174262629SdelphijSYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL); 17550276Speter 17650276Speterconst struct ieee80211_authenticator * 17750276Speterieee80211_authenticator_get(int auth) 17850276Speter{ 17950276Speter if (auth >= IEEE80211_AUTH_MAX) 18050276Speter return NULL; 18150276Speter if (authenticators[auth] == NULL) 18250276Speter ieee80211_load_module(auth_modnames[auth]); 18350276Speter return authenticators[auth]; 18450276Speter} 18550276Speter 18650276Spetervoid 18750276Speterieee80211_authenticator_register(int type, 18850276Speter const struct ieee80211_authenticator *auth) 18950276Speter{ 19050276Speter if (type >= IEEE80211_AUTH_MAX) 19150276Speter return; 19250276Speter authenticators[type] = auth; 19350276Speter} 19450276Speter 19550276Spetervoid 19650276Speterieee80211_authenticator_unregister(int type) 19750276Speter{ 198 199 if (type >= IEEE80211_AUTH_MAX) 200 return; 201 authenticators[type] = NULL; 202} 203 204/* 205 * Very simple-minded ACL module support. 206 */ 207/* XXX just one for now */ 208static const struct ieee80211_aclator *acl = NULL; 209 210void 211ieee80211_aclator_register(const struct ieee80211_aclator *iac) 212{ 213 printf("wlan: %s acl policy registered\n", iac->iac_name); 214 acl = iac; 215} 216 217void 218ieee80211_aclator_unregister(const struct ieee80211_aclator *iac) 219{ 220 if (acl == iac) 221 acl = NULL; 222 printf("wlan: %s acl policy unregistered\n", iac->iac_name); 223} 224 225const struct ieee80211_aclator * 226ieee80211_aclator_get(const char *name) 227{ 228 if (acl == NULL) 229 ieee80211_load_module("wlan_acl"); 230 return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL; 231} 232 233void 234ieee80211_print_essid(const u_int8_t *essid, int len) 235{ 236 const u_int8_t *p; 237 int i; 238 239 if (len > IEEE80211_NWID_LEN) 240 len = IEEE80211_NWID_LEN; 241 /* determine printable or not */ 242 for (i = 0, p = essid; i < len; i++, p++) { 243 if (*p < ' ' || *p > 0x7e) 244 break; 245 } 246 if (i == len) { 247 printf("\""); 248 for (i = 0, p = essid; i < len; i++, p++) 249 printf("%c", *p); 250 printf("\""); 251 } else { 252 printf("0x"); 253 for (i = 0, p = essid; i < len; i++, p++) 254 printf("%02x", *p); 255 } 256} 257 258void 259ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi) 260{ 261 const struct ieee80211_frame *wh; 262 int i; 263 264 wh = (const struct ieee80211_frame *)buf; 265 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 266 case IEEE80211_FC1_DIR_NODS: 267 printf("NODS %s", ether_sprintf(wh->i_addr2)); 268 printf("->%s", ether_sprintf(wh->i_addr1)); 269 printf("(%s)", ether_sprintf(wh->i_addr3)); 270 break; 271 case IEEE80211_FC1_DIR_TODS: 272 printf("TODS %s", ether_sprintf(wh->i_addr2)); 273 printf("->%s", ether_sprintf(wh->i_addr3)); 274 printf("(%s)", ether_sprintf(wh->i_addr1)); 275 break; 276 case IEEE80211_FC1_DIR_FROMDS: 277 printf("FRDS %s", ether_sprintf(wh->i_addr3)); 278 printf("->%s", ether_sprintf(wh->i_addr1)); 279 printf("(%s)", ether_sprintf(wh->i_addr2)); 280 break; 281 case IEEE80211_FC1_DIR_DSTODS: 282 printf("DSDS %s", ether_sprintf((const u_int8_t *)&wh[1])); 283 printf("->%s", ether_sprintf(wh->i_addr3)); 284 printf("(%s", ether_sprintf(wh->i_addr2)); 285 printf("->%s)", ether_sprintf(wh->i_addr1)); 286 break; 287 } 288 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 289 case IEEE80211_FC0_TYPE_DATA: 290 printf(" data"); 291 break; 292 case IEEE80211_FC0_TYPE_MGT: 293 printf(" %s", ieee80211_mgt_subtype_name[ 294 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) 295 >> IEEE80211_FC0_SUBTYPE_SHIFT]); 296 break; 297 default: 298 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 299 break; 300 } 301 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 302 int i; 303 printf(" WEP [IV"); 304 for (i = 0; i < IEEE80211_WEP_IVLEN; i++) 305 printf(" %.02x", buf[sizeof(*wh)+i]); 306 printf(" KID %u]", buf[sizeof(*wh)+i] >> 6); 307 } 308 if (rate >= 0) 309 printf(" %dM", rate / 2); 310 if (rssi >= 0) 311 printf(" +%d", rssi); 312 printf("\n"); 313 if (len > 0) { 314 for (i = 0; i < len; i++) { 315 if ((i & 1) == 0) 316 printf(" "); 317 printf("%02x", buf[i]); 318 } 319 printf("\n"); 320 } 321} 322 323int 324ieee80211_fix_rate(struct ieee80211_node *ni, int flags) 325{ 326#define RV(v) ((v) & IEEE80211_RATE_VAL) 327 struct ieee80211com *ic = ni->ni_ic; 328 int i, j, ignore, error; 329 int okrate, badrate, fixedrate; 330 struct ieee80211_rateset *srs, *nrs; 331 u_int8_t r; 332 333 /* 334 * If the fixed rate check was requested but no 335 * fixed has been defined then just remove it. 336 */ 337 if ((flags & IEEE80211_F_DOFRATE) && 338 ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) 339 flags &= ~IEEE80211_F_DOFRATE; 340 error = 0; 341 okrate = badrate = fixedrate = 0; 342 srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; 343 nrs = &ni->ni_rates; 344 for (i = 0; i < nrs->rs_nrates; ) { 345 ignore = 0; 346 if (flags & IEEE80211_F_DOSORT) { 347 /* 348 * Sort rates. 349 */ 350 for (j = i + 1; j < nrs->rs_nrates; j++) { 351 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) { 352 r = nrs->rs_rates[i]; 353 nrs->rs_rates[i] = nrs->rs_rates[j]; 354 nrs->rs_rates[j] = r; 355 } 356 } 357 } 358 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL; 359 badrate = r; 360 if (flags & IEEE80211_F_DOFRATE) { 361 /* 362 * Check any fixed rate is included. 363 */ 364 if (r == RV(srs->rs_rates[ic->ic_fixed_rate])) 365 fixedrate = r; 366 } 367 if (flags & IEEE80211_F_DONEGO) { 368 /* 369 * Check against supported rates. 370 */ 371 for (j = 0; j < srs->rs_nrates; j++) { 372 if (r == RV(srs->rs_rates[j])) { 373 /* 374 * Overwrite with the supported rate 375 * value so any basic rate bit is set. 376 * This insures that response we send 377 * to stations have the necessary basic 378 * rate bit set. 379 */ 380 nrs->rs_rates[i] = srs->rs_rates[j]; 381 break; 382 } 383 } 384 if (j == srs->rs_nrates) { 385 /* 386 * A rate in the node's rate set is not 387 * supported. If this is a basic rate and we 388 * are operating as an AP then this is an error. 389 * Otherwise we just discard/ignore the rate. 390 * Note that this is important for 11b stations 391 * when they want to associate with an 11g AP. 392 */ 393 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 394 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) 395 error++; 396 ignore++; 397 } 398 } 399 if (flags & IEEE80211_F_DODEL) { 400 /* 401 * Delete unacceptable rates. 402 */ 403 if (ignore) { 404 nrs->rs_nrates--; 405 for (j = i; j < nrs->rs_nrates; j++) 406 nrs->rs_rates[j] = nrs->rs_rates[j + 1]; 407 nrs->rs_rates[j] = 0; 408 continue; 409 } 410 } 411 if (!ignore) 412 okrate = nrs->rs_rates[i]; 413 i++; 414 } 415 if (okrate == 0 || error != 0 || 416 ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0)) 417 return badrate | IEEE80211_RATE_BASIC; 418 else 419 return RV(okrate); 420#undef RV 421} 422 423/* 424 * Reset 11g-related state. 425 */ 426void 427ieee80211_reset_erp(struct ieee80211com *ic) 428{ 429 ic->ic_flags &= ~IEEE80211_F_USEPROT; 430 ic->ic_nonerpsta = 0; 431 ic->ic_longslotsta = 0; 432 /* 433 * Short slot time is enabled only when operating in 11g 434 * and not in an IBSS. We must also honor whether or not 435 * the driver is capable of doing it. 436 */ 437 ieee80211_set_shortslottime(ic, 438 ic->ic_curmode == IEEE80211_MODE_11A || 439 (ic->ic_curmode == IEEE80211_MODE_11G && 440 ic->ic_opmode == IEEE80211_M_HOSTAP && 441 (ic->ic_caps & IEEE80211_C_SHSLOT))); 442 /* 443 * Set short preamble and ERP barker-preamble flags. 444 */ 445 if (ic->ic_curmode == IEEE80211_MODE_11A || 446 (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) { 447 ic->ic_flags |= IEEE80211_F_SHPREAMBLE; 448 ic->ic_flags &= ~IEEE80211_F_USEBARKER; 449 } else { 450 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; 451 ic->ic_flags |= IEEE80211_F_USEBARKER; 452 } 453} 454 455/* 456 * Set the short slot time state and notify the driver. 457 */ 458void 459ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff) 460{ 461 if (onoff) 462 ic->ic_flags |= IEEE80211_F_SHSLOT; 463 else 464 ic->ic_flags &= ~IEEE80211_F_SHSLOT; 465 /* notify driver */ 466 if (ic->ic_updateslot != NULL) 467 ic->ic_updateslot(ic->ic_ifp); 468} 469 470/* 471 * Check if the specified rate set supports ERP. 472 * NB: the rate set is assumed to be sorted. 473 */ 474int 475ieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs) 476{ 477#define N(a) (sizeof(a) / sizeof(a[0])) 478 static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 }; 479 int i, j; 480 481 if (rs->rs_nrates < N(rates)) 482 return 0; 483 for (i = 0; i < N(rates); i++) { 484 for (j = 0; j < rs->rs_nrates; j++) { 485 int r = rs->rs_rates[j] & IEEE80211_RATE_VAL; 486 if (rates[i] == r) 487 goto next; 488 if (r > rates[i]) 489 return 0; 490 } 491 return 0; 492 next: 493 ; 494 } 495 return 1; 496#undef N 497} 498 499/* 500 * Mark the basic rates for the 11g rate table based on the 501 * operating mode. For real 11g we mark all the 11b rates 502 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only 503 * 11b rates. There's also a pseudo 11a-mode used to mark only 504 * the basic OFDM rates. 505 */ 506void 507ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode) 508{ 509 static const struct ieee80211_rateset basic[] = { 510 { 0 }, /* IEEE80211_MODE_AUTO */ 511 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */ 512 { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */ 513 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */ 514 { 0 }, /* IEEE80211_MODE_FH */ 515 /* IEEE80211_MODE_PUREG (not yet) */ 516 { 7, { 2, 4, 11, 22, 12, 24, 48 } }, 517 }; 518 int i, j; 519 520 for (i = 0; i < rs->rs_nrates; i++) { 521 rs->rs_rates[i] &= IEEE80211_RATE_VAL; 522 for (j = 0; j < basic[mode].rs_nrates; j++) 523 if (basic[mode].rs_rates[j] == rs->rs_rates[i]) { 524 rs->rs_rates[i] |= IEEE80211_RATE_BASIC; 525 break; 526 } 527 } 528} 529 530/* 531 * WME protocol support. The following parameters come from the spec. 532 */ 533typedef struct phyParamType { 534 u_int8_t aifsn; 535 u_int8_t logcwmin; 536 u_int8_t logcwmax; 537 u_int16_t txopLimit; 538 u_int8_t acm; 539} paramType; 540 541static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = { 542 { 3, 4, 6 }, /* IEEE80211_MODE_AUTO */ 543 { 3, 4, 6 }, /* IEEE80211_MODE_11A */ 544 { 3, 5, 7 }, /* IEEE80211_MODE_11B */ 545 { 3, 4, 6 }, /* IEEE80211_MODE_11G */ 546 { 3, 5, 7 }, /* IEEE80211_MODE_FH */ 547 { 2, 3, 5 }, /* IEEE80211_MODE_TURBO_A */ 548 { 2, 3, 5 }, /* IEEE80211_MODE_TURBO_G */ 549}; 550static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = { 551 { 7, 4, 10 }, /* IEEE80211_MODE_AUTO */ 552 { 7, 4, 10 }, /* IEEE80211_MODE_11A */ 553 { 7, 5, 10 }, /* IEEE80211_MODE_11B */ 554 { 7, 4, 10 }, /* IEEE80211_MODE_11G */ 555 { 7, 5, 10 }, /* IEEE80211_MODE_FH */ 556 { 7, 3, 10 }, /* IEEE80211_MODE_TURBO_A */ 557 { 7, 3, 10 }, /* IEEE80211_MODE_TURBO_G */ 558}; 559static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = { 560 { 1, 3, 4, 94 }, /* IEEE80211_MODE_AUTO */ 561 { 1, 3, 4, 94 }, /* IEEE80211_MODE_11A */ 562 { 1, 4, 5, 188 }, /* IEEE80211_MODE_11B */ 563 { 1, 3, 4, 94 }, /* IEEE80211_MODE_11G */ 564 { 1, 4, 5, 188 }, /* IEEE80211_MODE_FH */ 565 { 1, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_A */ 566 { 1, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_G */ 567}; 568static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = { 569 { 1, 2, 3, 47 }, /* IEEE80211_MODE_AUTO */ 570 { 1, 2, 3, 47 }, /* IEEE80211_MODE_11A */ 571 { 1, 3, 4, 102 }, /* IEEE80211_MODE_11B */ 572 { 1, 2, 3, 47 }, /* IEEE80211_MODE_11G */ 573 { 1, 3, 4, 102 }, /* IEEE80211_MODE_FH */ 574 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_A */ 575 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_G */ 576}; 577 578static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = { 579 { 3, 4, 10 }, /* IEEE80211_MODE_AUTO */ 580 { 3, 4, 10 }, /* IEEE80211_MODE_11A */ 581 { 3, 5, 10 }, /* IEEE80211_MODE_11B */ 582 { 3, 4, 10 }, /* IEEE80211_MODE_11G */ 583 { 3, 5, 10 }, /* IEEE80211_MODE_FH */ 584 { 2, 3, 10 }, /* IEEE80211_MODE_TURBO_A */ 585 { 2, 3, 10 }, /* IEEE80211_MODE_TURBO_G */ 586}; 587static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = { 588 { 2, 3, 4, 94 }, /* IEEE80211_MODE_AUTO */ 589 { 2, 3, 4, 94 }, /* IEEE80211_MODE_11A */ 590 { 2, 4, 5, 188 }, /* IEEE80211_MODE_11B */ 591 { 2, 3, 4, 94 }, /* IEEE80211_MODE_11G */ 592 { 2, 4, 5, 188 }, /* IEEE80211_MODE_FH */ 593 { 2, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_A */ 594 { 2, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_G */ 595}; 596static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = { 597 { 2, 2, 3, 47 }, /* IEEE80211_MODE_AUTO */ 598 { 2, 2, 3, 47 }, /* IEEE80211_MODE_11A */ 599 { 2, 3, 4, 102 }, /* IEEE80211_MODE_11B */ 600 { 2, 2, 3, 47 }, /* IEEE80211_MODE_11G */ 601 { 2, 3, 4, 102 }, /* IEEE80211_MODE_FH */ 602 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_A */ 603 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_G */ 604}; 605 606void 607ieee80211_wme_initparams(struct ieee80211com *ic) 608{ 609 struct ieee80211_wme_state *wme = &ic->ic_wme; 610 const paramType *pPhyParam, *pBssPhyParam; 611 struct wmeParams *wmep; 612 int i; 613 614 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 615 return; 616 617 for (i = 0; i < WME_NUM_AC; i++) { 618 switch (i) { 619 case WME_AC_BK: 620 pPhyParam = &phyParamForAC_BK[ic->ic_curmode]; 621 pBssPhyParam = &phyParamForAC_BK[ic->ic_curmode]; 622 break; 623 case WME_AC_VI: 624 pPhyParam = &phyParamForAC_VI[ic->ic_curmode]; 625 pBssPhyParam = &bssPhyParamForAC_VI[ic->ic_curmode]; 626 break; 627 case WME_AC_VO: 628 pPhyParam = &phyParamForAC_VO[ic->ic_curmode]; 629 pBssPhyParam = &bssPhyParamForAC_VO[ic->ic_curmode]; 630 break; 631 case WME_AC_BE: 632 default: 633 pPhyParam = &phyParamForAC_BE[ic->ic_curmode]; 634 pBssPhyParam = &bssPhyParamForAC_BE[ic->ic_curmode]; 635 break; 636 } 637 638 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 639 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 640 wmep->wmep_acm = pPhyParam->acm; 641 wmep->wmep_aifsn = pPhyParam->aifsn; 642 wmep->wmep_logcwmin = pPhyParam->logcwmin; 643 wmep->wmep_logcwmax = pPhyParam->logcwmax; 644 wmep->wmep_txopLimit = pPhyParam->txopLimit; 645 } else { 646 wmep->wmep_acm = pBssPhyParam->acm; 647 wmep->wmep_aifsn = pBssPhyParam->aifsn; 648 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 649 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 650 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 651 652 } 653 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 654 "%s: %s chan [acm %u aifsn %u log2(cwmin) %u " 655 "log2(cwmax) %u txpoLimit %u]\n", __func__ 656 , ieee80211_wme_acnames[i] 657 , wmep->wmep_acm 658 , wmep->wmep_aifsn 659 , wmep->wmep_logcwmin 660 , wmep->wmep_logcwmax 661 , wmep->wmep_txopLimit 662 ); 663 664 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 665 wmep->wmep_acm = pBssPhyParam->acm; 666 wmep->wmep_aifsn = pBssPhyParam->aifsn; 667 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 668 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 669 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 670 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 671 "%s: %s bss [acm %u aifsn %u log2(cwmin) %u " 672 "log2(cwmax) %u txpoLimit %u]\n", __func__ 673 , ieee80211_wme_acnames[i] 674 , wmep->wmep_acm 675 , wmep->wmep_aifsn 676 , wmep->wmep_logcwmin 677 , wmep->wmep_logcwmax 678 , wmep->wmep_txopLimit 679 ); 680 } 681 /* NB: check ic_bss to avoid NULL deref on initial attach */ 682 if (ic->ic_bss != NULL) { 683 /* 684 * Calculate agressive mode switching threshold based 685 * on beacon interval. This doesn't need locking since 686 * we're only called before entering the RUN state at 687 * which point we start sending beacon frames. 688 */ 689 wme->wme_hipri_switch_thresh = 690 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100; 691 ieee80211_wme_updateparams(ic); 692 } 693} 694 695/* 696 * Update WME parameters for ourself and the BSS. 697 */ 698void 699ieee80211_wme_updateparams_locked(struct ieee80211com *ic) 700{ 701 static const paramType phyParam[IEEE80211_MODE_MAX] = { 702 { 2, 4, 10, 64 }, /* IEEE80211_MODE_AUTO */ 703 { 2, 4, 10, 64 }, /* IEEE80211_MODE_11A */ 704 { 2, 5, 10, 64 }, /* IEEE80211_MODE_11B */ 705 { 2, 4, 10, 64 }, /* IEEE80211_MODE_11G */ 706 { 2, 5, 10, 64 }, /* IEEE80211_MODE_FH */ 707 { 1, 3, 10, 64 }, /* IEEE80211_MODE_TURBO_A */ 708 { 1, 3, 10, 64 }, /* IEEE80211_MODE_TURBO_G */ 709 }; 710 struct ieee80211_wme_state *wme = &ic->ic_wme; 711 const struct wmeParams *wmep; 712 struct wmeParams *chanp, *bssp; 713 int i; 714 715 /* set up the channel access parameters for the physical device */ 716 for (i = 0; i < WME_NUM_AC; i++) { 717 chanp = &wme->wme_chanParams.cap_wmeParams[i]; 718 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 719 chanp->wmep_aifsn = wmep->wmep_aifsn; 720 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 721 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 722 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 723 724 chanp = &wme->wme_bssChanParams.cap_wmeParams[i]; 725 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 726 chanp->wmep_aifsn = wmep->wmep_aifsn; 727 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 728 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 729 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 730 } 731 732 /* 733 * This implements agressive mode as found in certain 734 * vendors' AP's. When there is significant high 735 * priority (VI/VO) traffic in the BSS throttle back BE 736 * traffic by using conservative parameters. Otherwise 737 * BE uses agressive params to optimize performance of 738 * legacy/non-QoS traffic. 739 */ 740 if ((ic->ic_opmode == IEEE80211_M_HOSTAP && 741 (wme->wme_flags & WME_F_AGGRMODE) == 0) || 742 (ic->ic_opmode != IEEE80211_M_HOSTAP && 743 (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) || 744 (ic->ic_flags & IEEE80211_F_WME) == 0) { 745 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE]; 746 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE]; 747 748 chanp->wmep_aifsn = bssp->wmep_aifsn = 749 phyParam[ic->ic_curmode].aifsn; 750 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 751 phyParam[ic->ic_curmode].logcwmin; 752 chanp->wmep_logcwmax = bssp->wmep_logcwmax = 753 phyParam[ic->ic_curmode].logcwmax; 754 chanp->wmep_txopLimit = bssp->wmep_txopLimit = 755 (ic->ic_caps & IEEE80211_C_BURST) ? 756 phyParam[ic->ic_curmode].txopLimit : 0; 757 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 758 "%s: %s [acm %u aifsn %u log2(cwmin) %u " 759 "log2(cwmax) %u txpoLimit %u]\n", __func__ 760 , ieee80211_wme_acnames[WME_AC_BE] 761 , chanp->wmep_acm 762 , chanp->wmep_aifsn 763 , chanp->wmep_logcwmin 764 , chanp->wmep_logcwmax 765 , chanp->wmep_txopLimit 766 ); 767 } 768 769 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 770 ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) == 0) { 771 static const u_int8_t logCwMin[IEEE80211_MODE_MAX] = { 772 3, /* IEEE80211_MODE_AUTO */ 773 3, /* IEEE80211_MODE_11A */ 774 4, /* IEEE80211_MODE_11B */ 775 3, /* IEEE80211_MODE_11G */ 776 4, /* IEEE80211_MODE_FH */ 777 3, /* IEEE80211_MODE_TURBO_A */ 778 3, /* IEEE80211_MODE_TURBO_G */ 779 }; 780 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE]; 781 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE]; 782 783 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 784 logCwMin[ic->ic_curmode]; 785 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 786 "%s: %s log2(cwmin) %u\n", __func__ 787 , ieee80211_wme_acnames[WME_AC_BE] 788 , chanp->wmep_logcwmin 789 ); 790 } 791 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */ 792 /* 793 * Arrange for a beacon update and bump the parameter 794 * set number so associated stations load the new values. 795 */ 796 wme->wme_bssChanParams.cap_info = 797 (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT; 798 ic->ic_flags |= IEEE80211_F_WMEUPDATE; 799 } 800 801 wme->wme_update(ic); 802 803 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME, 804 "%s: WME params updated, cap_info 0x%x\n", __func__, 805 ic->ic_opmode == IEEE80211_M_STA ? 806 wme->wme_wmeChanParams.cap_info : 807 wme->wme_bssChanParams.cap_info); 808} 809 810void 811ieee80211_wme_updateparams(struct ieee80211com *ic) 812{ 813 814 if (ic->ic_caps & IEEE80211_C_WME) { 815 IEEE80211_BEACON_LOCK(ic); 816 ieee80211_wme_updateparams_locked(ic); 817 IEEE80211_BEACON_UNLOCK(ic); 818 } 819} 820 821void 822ieee80211_beacon_miss(struct ieee80211com *ic) 823{ 824 825 if (ic->ic_flags & IEEE80211_F_SCAN) { 826 /* XXX check ic_curchan != ic_bsschan? */ 827 return; 828 } 829 IEEE80211_DPRINTF(ic, 830 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, 831 "%s\n", "beacon miss"); 832 833 /* 834 * Our handling is only meaningful for stations that are 835 * associated; any other conditions else will be handled 836 * through different means (e.g. the tx timeout on mgt frames). 837 */ 838 if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN) 839 return; 840 841 if (++ic->ic_bmiss_count < ic->ic_bmiss_max) { 842 /* 843 * Send a directed probe req before falling back to a scan; 844 * if we receive a response ic_bmiss_count will be reset. 845 * Some cards mistakenly report beacon miss so this avoids 846 * the expensive scan if the ap is still there. 847 */ 848 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr, 849 ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid, 850 ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen, 851 ic->ic_opt_ie, ic->ic_opt_ie_len); 852 return; 853 } 854 ic->ic_bmiss_count = 0; 855 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 856} 857 858static void 859sta_disassoc(void *arg, struct ieee80211_node *ni) 860{ 861 struct ieee80211com *ic = arg; 862 863 if (ni->ni_associd != 0) { 864 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC, 865 IEEE80211_REASON_ASSOC_LEAVE); 866 ieee80211_node_leave(ic, ni); 867 } 868} 869 870static void 871sta_deauth(void *arg, struct ieee80211_node *ni) 872{ 873 struct ieee80211com *ic = arg; 874 875 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, 876 IEEE80211_REASON_ASSOC_LEAVE); 877} 878 879static int 880ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 881{ 882 struct ifnet *ifp = ic->ic_ifp; 883 struct ieee80211_node *ni; 884 enum ieee80211_state ostate; 885 886 ostate = ic->ic_state; 887 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__, 888 ieee80211_state_name[ostate], ieee80211_state_name[nstate]); 889 ic->ic_state = nstate; /* state transition */ 890 ni = ic->ic_bss; /* NB: no reference held */ 891 switch (nstate) { 892 case IEEE80211_S_INIT: 893 switch (ostate) { 894 case IEEE80211_S_INIT: 895 break; 896 case IEEE80211_S_RUN: 897 switch (ic->ic_opmode) { 898 case IEEE80211_M_STA: 899 IEEE80211_SEND_MGMT(ic, ni, 900 IEEE80211_FC0_SUBTYPE_DISASSOC, 901 IEEE80211_REASON_ASSOC_LEAVE); 902 ieee80211_sta_leave(ic, ni); 903 break; 904 case IEEE80211_M_HOSTAP: 905 ieee80211_iterate_nodes(&ic->ic_sta, 906 sta_disassoc, ic); 907 break; 908 default: 909 break; 910 } 911 goto reset; 912 case IEEE80211_S_ASSOC: 913 switch (ic->ic_opmode) { 914 case IEEE80211_M_STA: 915 IEEE80211_SEND_MGMT(ic, ni, 916 IEEE80211_FC0_SUBTYPE_DEAUTH, 917 IEEE80211_REASON_AUTH_LEAVE); 918 break; 919 case IEEE80211_M_HOSTAP: 920 ieee80211_iterate_nodes(&ic->ic_sta, 921 sta_deauth, ic); 922 break; 923 default: 924 break; 925 } 926 goto reset; 927 case IEEE80211_S_SCAN: 928 ieee80211_cancel_scan(ic); 929 goto reset; 930 case IEEE80211_S_AUTH: 931 reset: 932 ic->ic_mgt_timer = 0; 933 IF_DRAIN(&ic->ic_mgtq); 934 ieee80211_reset_bss(ic); 935 break; 936 } 937 if (ic->ic_auth->ia_detach != NULL) 938 ic->ic_auth->ia_detach(ic); 939 break; 940 case IEEE80211_S_SCAN: 941 switch (ostate) { 942 case IEEE80211_S_INIT: 943 if ((ic->ic_opmode == IEEE80211_M_HOSTAP || 944 ic->ic_opmode == IEEE80211_M_IBSS || 945 ic->ic_opmode == IEEE80211_M_AHDEMO) && 946 ic->ic_des_chan != IEEE80211_CHAN_ANYC) { 947 /* 948 * AP operation and we already have a channel; 949 * bypass the scan and startup immediately. 950 */ 951 ieee80211_create_ibss(ic, ic->ic_des_chan); 952 } else { 953 ieee80211_begin_scan(ic, arg); 954 } 955 break; 956 case IEEE80211_S_SCAN: 957 /* 958 * Scan next. If doing an active scan and the 959 * channel is not marked passive-only then send 960 * a probe request. Otherwise just listen for 961 * beacons on the channel. 962 */ 963 if ((ic->ic_flags & IEEE80211_F_ASCAN) && 964 (ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) { 965 ieee80211_send_probereq(ni, 966 ic->ic_myaddr, ifp->if_broadcastaddr, 967 ifp->if_broadcastaddr, 968 ic->ic_des_essid, ic->ic_des_esslen, 969 ic->ic_opt_ie, ic->ic_opt_ie_len); 970 } 971 break; 972 case IEEE80211_S_RUN: 973 /* beacon miss */ 974 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, 975 "no recent beacons from %s; rescanning\n", 976 ether_sprintf(ic->ic_bss->ni_bssid)); 977 ieee80211_sta_leave(ic, ni); 978 ic->ic_flags &= ~IEEE80211_F_SIBSS; /* XXX */ 979 /* FALLTHRU */ 980 case IEEE80211_S_AUTH: 981 case IEEE80211_S_ASSOC: 982 /* timeout restart scan */ 983 ni = ieee80211_find_node(&ic->ic_scan, 984 ic->ic_bss->ni_macaddr); 985 if (ni != NULL) { 986 ni->ni_fails++; 987 ieee80211_unref_node(&ni); 988 } 989 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) 990 ieee80211_begin_scan(ic, arg); 991 break; 992 } 993 break; 994 case IEEE80211_S_AUTH: 995 switch (ostate) { 996 case IEEE80211_S_INIT: 997 case IEEE80211_S_SCAN: 998 IEEE80211_SEND_MGMT(ic, ni, 999 IEEE80211_FC0_SUBTYPE_AUTH, 1); 1000 break; 1001 case IEEE80211_S_AUTH: 1002 case IEEE80211_S_ASSOC: 1003 switch (arg) { 1004 case IEEE80211_FC0_SUBTYPE_AUTH: 1005 /* ??? */ 1006 IEEE80211_SEND_MGMT(ic, ni, 1007 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1008 break; 1009 case IEEE80211_FC0_SUBTYPE_DEAUTH: 1010 /* ignore and retry scan on timeout */ 1011 break; 1012 } 1013 break; 1014 case IEEE80211_S_RUN: 1015 switch (arg) { 1016 case IEEE80211_FC0_SUBTYPE_AUTH: 1017 IEEE80211_SEND_MGMT(ic, ni, 1018 IEEE80211_FC0_SUBTYPE_AUTH, 2); 1019 ic->ic_state = ostate; /* stay RUN */ 1020 break; 1021 case IEEE80211_FC0_SUBTYPE_DEAUTH: 1022 ieee80211_sta_leave(ic, ni); 1023 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { 1024 /* try to reauth */ 1025 IEEE80211_SEND_MGMT(ic, ni, 1026 IEEE80211_FC0_SUBTYPE_AUTH, 1); 1027 } 1028 break; 1029 } 1030 break; 1031 } 1032 break; 1033 case IEEE80211_S_ASSOC: 1034 switch (ostate) { 1035 case IEEE80211_S_INIT: 1036 case IEEE80211_S_SCAN: 1037 case IEEE80211_S_ASSOC: 1038 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, 1039 "%s: invalid transition\n", __func__); 1040 break; 1041 case IEEE80211_S_AUTH: 1042 IEEE80211_SEND_MGMT(ic, ni, 1043 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 1044 break; 1045 case IEEE80211_S_RUN: 1046 ieee80211_sta_leave(ic, ni); 1047 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { 1048 IEEE80211_SEND_MGMT(ic, ni, 1049 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); 1050 } 1051 break; 1052 } 1053 break; 1054 case IEEE80211_S_RUN: 1055 if (ic->ic_flags & IEEE80211_F_WPA) { 1056 /* XXX validate prerequisites */ 1057 } 1058 switch (ostate) { 1059 case IEEE80211_S_INIT: 1060 if (ic->ic_opmode == IEEE80211_M_MONITOR) 1061 break; 1062 /* fall thru... */ 1063 case IEEE80211_S_AUTH: 1064 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, 1065 "%s: invalid transition\n", __func__); 1066 /* fall thru... */ 1067 case IEEE80211_S_RUN: 1068 break; 1069 case IEEE80211_S_SCAN: /* adhoc/hostap mode */ 1070 case IEEE80211_S_ASSOC: /* infra mode */ 1071 KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates, 1072 ("%s: bogus xmit rate %u setup\n", __func__, 1073 ni->ni_txrate)); 1074#ifdef IEEE80211_DEBUG 1075 if (ieee80211_msg_debug(ic)) { 1076 if (ic->ic_opmode == IEEE80211_M_STA) 1077 if_printf(ifp, "associated "); 1078 else 1079 if_printf(ifp, "synchronized "); 1080 printf("with %s ssid ", 1081 ether_sprintf(ni->ni_bssid)); 1082 ieee80211_print_essid(ic->ic_bss->ni_essid, 1083 ni->ni_esslen); 1084 printf(" channel %d start %uMb\n", 1085 ieee80211_chan2ieee(ic, ic->ic_curchan), 1086 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate])); 1087 } 1088#endif 1089 ic->ic_mgt_timer = 0; 1090 if (ic->ic_opmode == IEEE80211_M_STA) 1091 ieee80211_notify_node_join(ic, ni, 1092 arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP); 1093 if_start(ifp); /* XXX not authorized yet */ 1094 break; 1095 } 1096 /* 1097 * Start/stop the authenticator when operating as an 1098 * AP. We delay until here to allow configuration to 1099 * happen out of order. 1100 */ 1101 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */ 1102 ic->ic_auth->ia_attach != NULL) { 1103 /* XXX check failure */ 1104 ic->ic_auth->ia_attach(ic); 1105 } else if (ic->ic_auth->ia_detach != NULL) { 1106 ic->ic_auth->ia_detach(ic); 1107 } 1108 /* 1109 * When 802.1x is not in use mark the port authorized 1110 * at this point so traffic can flow. 1111 */ 1112 if (ni->ni_authmode != IEEE80211_AUTH_8021X) 1113 ieee80211_node_authorize(ni); 1114 /* 1115 * Enable inactivity processing. 1116 * XXX 1117 */ 1118 ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT; 1119 ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT; 1120 break; 1121 } 1122 return 0; 1123} 1124