1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> 8 */ 9 10 /* 11 * Copyright (c) 2001 Atsushi Onoe 12 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 13 * All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. The name of the author may not be used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 */ 41 42 /* 43 * IEEE 802.11 protocol support 44 */ 45 46 #include "net80211_impl.h" 47 48 /* tunables */ 49 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */ 50 #define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */ 51 52 #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) 53 54 const char *ieee80211_mgt_subtype_name[] = { 55 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp", 56 "probe_req", "probe_resp", "reserved#6", "reserved#7", 57 "beacon", "atim", "disassoc", "auth", 58 "deauth", "reserved#13", "reserved#14", "reserved#15" 59 }; 60 const char *ieee80211_ctl_subtype_name[] = { 61 "reserved#0", "reserved#1", "reserved#2", "reserved#3", 62 "reserved#3", "reserved#5", "reserved#6", "reserved#7", 63 "reserved#8", "reserved#9", "ps_poll", "rts", 64 "cts", "ack", "cf_end", "cf_end_ack" 65 }; 66 const char *ieee80211_state_name[IEEE80211_S_MAX] = { 67 "INIT", /* IEEE80211_S_INIT */ 68 "SCAN", /* IEEE80211_S_SCAN */ 69 "AUTH", /* IEEE80211_S_AUTH */ 70 "ASSOC", /* IEEE80211_S_ASSOC */ 71 "RUN" /* IEEE80211_S_RUN */ 72 }; 73 const char *ieee80211_wme_acnames[] = { 74 "WME_AC_BE", 75 "WME_AC_BK", 76 "WME_AC_VI", 77 "WME_AC_VO", 78 "WME_UPSD", 79 }; 80 81 static int ieee80211_newstate(ieee80211com_t *, enum ieee80211_state, int); 82 83 /* 84 * Initialize the interface softc, ic, with protocol management 85 * related data structures and functions. 86 */ 87 void 88 ieee80211_proto_attach(ieee80211com_t *ic) 89 { 90 struct ieee80211_impl *im = ic->ic_private; 91 92 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT; 93 ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT; 94 ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; 95 ic->ic_protmode = IEEE80211_PROT_CTSONLY; 96 im->im_bmiss_max = IEEE80211_BMISS_MAX; 97 98 ic->ic_wme.wme_hipri_switch_hysteresis = 99 AGGRESSIVE_MODE_SWITCH_HYSTERESIS; 100 101 /* protocol state change handler */ 102 ic->ic_newstate = ieee80211_newstate; 103 104 /* initialize management frame handlers */ 105 ic->ic_recv_mgmt = ieee80211_recv_mgmt; 106 ic->ic_send_mgmt = ieee80211_send_mgmt; 107 } 108 109 /* 110 * Print a 802.11 frame header 111 */ 112 void 113 ieee80211_dump_pkt(const uint8_t *buf, int32_t len, int32_t rate, int32_t rssi) 114 { 115 struct ieee80211_frame *wh; 116 int8_t buf1[100]; 117 int8_t buf2[25]; 118 int i; 119 120 bzero(buf1, sizeof (buf1)); 121 bzero(buf2, sizeof (buf2)); 122 wh = (struct ieee80211_frame *)buf; 123 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 124 case IEEE80211_FC1_DIR_NODS: 125 (void) snprintf(buf2, sizeof (buf2), "NODS %s", 126 ieee80211_macaddr_sprintf(wh->i_addr2)); 127 (void) strncat(buf1, buf2, sizeof (buf2)); 128 (void) snprintf(buf2, sizeof (buf2), "->%s", 129 ieee80211_macaddr_sprintf(wh->i_addr1)); 130 (void) strncat(buf1, buf2, sizeof (buf2)); 131 (void) snprintf(buf2, sizeof (buf2), "(%s)", 132 ieee80211_macaddr_sprintf(wh->i_addr3)); 133 (void) strncat(buf1, buf2, sizeof (buf2)); 134 break; 135 case IEEE80211_FC1_DIR_TODS: 136 (void) snprintf(buf2, sizeof (buf2), "TODS %s", 137 ieee80211_macaddr_sprintf(wh->i_addr2)); 138 (void) strncat(buf1, buf2, sizeof (buf2)); 139 (void) snprintf(buf2, sizeof (buf2), "->%s", 140 ieee80211_macaddr_sprintf(wh->i_addr3)); 141 (void) strncat(buf1, buf2, sizeof (buf2)); 142 (void) snprintf(buf2, sizeof (buf2), "(%s)", 143 ieee80211_macaddr_sprintf(wh->i_addr1)); 144 (void) strncat(buf1, buf2, sizeof (buf2)); 145 break; 146 case IEEE80211_FC1_DIR_FROMDS: 147 (void) snprintf(buf2, sizeof (buf2), "FRDS %s", 148 ieee80211_macaddr_sprintf(wh->i_addr3)); 149 (void) strncat(buf1, buf2, sizeof (buf2)); 150 (void) snprintf(buf2, sizeof (buf2), "->%s", 151 ieee80211_macaddr_sprintf(wh->i_addr1)); 152 (void) strncat(buf1, buf2, sizeof (buf2)); 153 (void) snprintf(buf2, sizeof (buf2), "(%s)", 154 ieee80211_macaddr_sprintf(wh->i_addr2)); 155 (void) strncat(buf1, buf2, sizeof (buf2)); 156 break; 157 case IEEE80211_FC1_DIR_DSTODS: 158 (void) snprintf(buf2, sizeof (buf2), "DSDS %s", 159 ieee80211_macaddr_sprintf((uint8_t *)&wh[1])); 160 (void) strncat(buf1, buf2, sizeof (buf2)); 161 (void) snprintf(buf2, sizeof (buf2), "->%s ", 162 ieee80211_macaddr_sprintf(wh->i_addr3)); 163 (void) strncat(buf1, buf2, sizeof (buf2)); 164 (void) snprintf(buf2, sizeof (buf2), "%s", 165 ieee80211_macaddr_sprintf(wh->i_addr2)); 166 (void) strncat(buf1, buf2, sizeof (buf2)); 167 (void) snprintf(buf2, sizeof (buf2), "->%s", 168 ieee80211_macaddr_sprintf(wh->i_addr1)); 169 (void) strncat(buf1, buf2, sizeof (buf2)); 170 break; 171 } 172 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_dump_pkt(): %s", buf1); 173 bzero(buf1, sizeof (buf1)); 174 175 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 176 case IEEE80211_FC0_TYPE_DATA: 177 (void) sprintf(buf2, "data"); 178 break; 179 case IEEE80211_FC0_TYPE_MGT: 180 (void) snprintf(buf2, sizeof (buf2), "%s", 181 ieee80211_mgt_subtype_name[ 182 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) 183 >> IEEE80211_FC0_SUBTYPE_SHIFT]); 184 break; 185 default: 186 (void) snprintf(buf2, sizeof (buf2), "type#%d", 187 wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 188 break; 189 } 190 (void) strncat(buf1, buf2, sizeof (buf2)); 191 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 192 (void) sprintf(buf2, " WEP"); 193 (void) strcat(buf1, buf2); 194 } 195 if (rate >= 0) { 196 (void) snprintf(buf2, sizeof (buf2), " %dM", rate / 2); 197 (void) strncat(buf1, buf2, sizeof (buf2)); 198 } 199 if (rssi >= 0) { 200 (void) snprintf(buf2, sizeof (buf2), " +%d", rssi); 201 (void) strncat(buf1, buf2, sizeof (buf2)); 202 } 203 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_dump_pkt(): %s", buf1); 204 bzero(buf1, sizeof (buf1)); 205 206 if (len > 0) { 207 for (i = 0; i < (len > 40 ? 40 : len); i++) { 208 if ((i & 0x03) == 0) 209 (void) strcat(buf1, " "); 210 (void) snprintf(buf2, 3, "%02x", buf[i]); 211 (void) strncat(buf1, buf2, 3); 212 } 213 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_dump_pkt(): %s", 214 buf1); 215 } 216 } 217 218 /* 219 * Adjust/Fix the specified node's rate table 220 * 221 * in node 222 * flag IEEE80211_F_DOSORT : sort the node's rate table 223 * IEEE80211_F_DONEGO : mark a rate as basic rate if it is 224 * a device's basic rate 225 * IEEE80211_F_DODEL : delete rates not supported by the device 226 * IEEE80211_F_DOFRATE: check if the fixed rate is supported by 227 * the device 228 * 229 * The highest bit of returned rate value is set to 1 on failure. 230 */ 231 int 232 ieee80211_fix_rate(ieee80211_node_t *in, 233 struct ieee80211_rateset *nrs, int flags) 234 { 235 ieee80211com_t *ic = in->in_ic; 236 struct ieee80211_rateset *srs; 237 boolean_t ignore; 238 int i; 239 int okrate; 240 int badrate; 241 int fixedrate; 242 uint8_t r; 243 244 /* 245 * If the fixed rate check was requested but no 246 * fixed has been defined then just remove it. 247 */ 248 if ((flags & IEEE80211_F_DOFRATE) && 249 (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)) { 250 flags &= ~IEEE80211_F_DOFRATE; 251 } 252 if (in->in_chan == IEEE80211_CHAN_ANYC) { 253 return (IEEE80211_RATE_BASIC); 254 } 255 okrate = badrate = fixedrate = 0; 256 srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, in->in_chan)]; 257 for (i = 0; i < nrs->ir_nrates; ) { 258 int j; 259 260 ignore = B_FALSE; 261 if (flags & IEEE80211_F_DOSORT) { 262 /* 263 * Sort rates. 264 */ 265 for (j = i + 1; j < nrs->ir_nrates; j++) { 266 if (IEEE80211_RV(nrs->ir_rates[i]) > 267 IEEE80211_RV(nrs->ir_rates[j])) { 268 r = nrs->ir_rates[i]; 269 nrs->ir_rates[i] = nrs->ir_rates[j]; 270 nrs->ir_rates[j] = r; 271 } 272 } 273 } 274 r = IEEE80211_RV(nrs->ir_rates[i]); 275 badrate = r; 276 277 /* 278 * Check against supported rates. 279 */ 280 for (j = 0; j < srs->ir_nrates; j++) { 281 if (r == IEEE80211_RV(srs->ir_rates[j])) { 282 /* 283 * Overwrite with the supported rate 284 * value so any basic rate bit is set. 285 * This insures that response we send 286 * to stations have the necessary basic 287 * rate bit set. 288 */ 289 if (flags & IEEE80211_F_DONEGO) 290 nrs->ir_rates[i] = srs->ir_rates[j]; 291 break; 292 } 293 } 294 if (j == srs->ir_nrates) { 295 /* 296 * A rate in the node's rate set is not 297 * supported. We just discard/ignore the rate. 298 * Note that this is important for 11b stations 299 * when they want to associate with an 11g AP. 300 */ 301 ignore = B_TRUE; 302 } 303 304 if (flags & IEEE80211_F_DODEL) { 305 /* 306 * Delete unacceptable rates. 307 */ 308 if (ignore) { 309 nrs->ir_nrates--; 310 for (j = i; j < nrs->ir_nrates; j++) 311 nrs->ir_rates[j] = nrs->ir_rates[j + 1]; 312 nrs->ir_rates[j] = 0; 313 continue; 314 } 315 } 316 if (flags & IEEE80211_F_DOFRATE) { 317 /* 318 * Check any fixed rate is included. 319 */ 320 if (r == ic->ic_fixed_rate) 321 fixedrate = r; 322 } 323 if (!ignore) 324 okrate = nrs->ir_rates[i]; 325 i++; 326 } 327 if (okrate == 0 || ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0)) 328 return (badrate | IEEE80211_RATE_BASIC); 329 else 330 return (IEEE80211_RV(okrate)); 331 } 332 333 /* 334 * Reset 11g-related state. 335 */ 336 void 337 ieee80211_reset_erp(ieee80211com_t *ic) 338 { 339 ic->ic_flags &= ~IEEE80211_F_USEPROT; 340 /* 341 * Short slot time is enabled only when operating in 11g 342 * and not in an IBSS. We must also honor whether or not 343 * the driver is capable of doing it. 344 */ 345 ieee80211_set_shortslottime(ic, 346 ic->ic_curmode == IEEE80211_MODE_11A); 347 /* 348 * Set short preamble and ERP barker-preamble flags. 349 */ 350 if (ic->ic_curmode == IEEE80211_MODE_11A || 351 (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) { 352 ic->ic_flags |= IEEE80211_F_SHPREAMBLE; 353 ic->ic_flags &= ~IEEE80211_F_USEBARKER; 354 } else { 355 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; 356 ic->ic_flags |= IEEE80211_F_USEBARKER; 357 } 358 } 359 360 /* 361 * Change current channel to be the next available channel 362 */ 363 void 364 ieee80211_reset_chan(ieee80211com_t *ic) 365 { 366 struct ieee80211_channel *ch = ic->ic_curchan; 367 368 IEEE80211_LOCK(ic); 369 do { 370 if (++ch > &ic->ic_sup_channels[IEEE80211_CHAN_MAX]) 371 ch = &ic->ic_sup_channels[0]; 372 if (ieee80211_isset(ic->ic_chan_active, 373 ieee80211_chan2ieee(ic, ch))) { 374 break; 375 } 376 } while (ch != ic->ic_curchan); 377 ic->ic_curchan = ch; 378 IEEE80211_UNLOCK(ic); 379 } 380 381 /* 382 * Set the short slot time state and notify the driver. 383 */ 384 void 385 ieee80211_set_shortslottime(ieee80211com_t *ic, boolean_t on) 386 { 387 if (on) 388 ic->ic_flags |= IEEE80211_F_SHSLOT; 389 else 390 ic->ic_flags &= ~IEEE80211_F_SHSLOT; 391 /* notify driver */ 392 if (ic->ic_set_shortslot != NULL) 393 ic->ic_set_shortslot(ic, on); 394 } 395 396 /* 397 * Mark the basic rates for the 11g rate table based on the 398 * operating mode. For real 11g we mark all the 11b rates 399 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only 400 * 11b rates. There's also a pseudo 11a-mode used to mark only 401 * the basic OFDM rates. 402 */ 403 void 404 ieee80211_setbasicrates(struct ieee80211_rateset *rs, 405 enum ieee80211_phymode mode) 406 { 407 static const struct ieee80211_rateset basic[] = { 408 { 0 }, /* IEEE80211_MODE_AUTO */ 409 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */ 410 { 2, { 2, 4} }, /* IEEE80211_MODE_11B */ 411 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G mixed b/g */ 412 { 0 }, /* IEEE80211_MODE_FH */ 413 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_TURBO_A */ 414 { 4, { 2, 4, 11, 22 } }, 415 /* IEEE80211_MODE_TURBO_G (mixed b/g) */ 416 { 0 }, /* IEEE80211_MODE_STURBO_A */ 417 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11NA */ 418 /* IEEE80211_MODE_11NG (mixed b/g) */ 419 { 7, { 2, 4, 11, 22, 12, 24, 48 } } 420 }; 421 int i, j; 422 423 ASSERT(mode < IEEE80211_MODE_MAX); 424 for (i = 0; i < rs->ir_nrates; i++) { 425 rs->ir_rates[i] &= IEEE80211_RATE_VAL; 426 for (j = 0; j < basic[mode].ir_nrates; j++) { 427 if (basic[mode].ir_rates[j] == rs->ir_rates[i]) { 428 rs->ir_rates[i] |= IEEE80211_RATE_BASIC; 429 break; 430 } 431 } 432 } 433 } 434 435 /* 436 * WME protocol support. The following parameters come from the spec. 437 */ 438 typedef struct phyParamType { 439 uint8_t aifsn; 440 uint8_t logcwmin; 441 uint8_t logcwmax; 442 uint16_t txopLimit; 443 uint8_t acm; 444 } paramType; 445 446 static const paramType phyParamForAC_BE[IEEE80211_MODE_MAX] = { 447 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_AUTO */ 448 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11A */ 449 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11B */ 450 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11G */ 451 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_FH */ 452 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_A */ 453 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO_G */ 454 { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_STURBO_A */ 455 { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11NA */ 456 { 3, 4, 6, 0, 0 } /* IEEE80211_MODE_11NG */ 457 }; 458 static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = { 459 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */ 460 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */ 461 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11B */ 462 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */ 463 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_FH */ 464 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */ 465 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */ 466 { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */ 467 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */ 468 { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */ 469 }; 470 static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = { 471 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */ 472 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */ 473 { 1, 3, 4, 188, 0 }, /* IEEE80211_MODE_11B */ 474 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */ 475 { 1, 3, 4, 188, 0 }, /* IEEE80211_MODE_FH */ 476 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */ 477 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */ 478 { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */ 479 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */ 480 { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */ 481 }; 482 static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = { 483 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */ 484 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */ 485 { 1, 2, 3, 102, 0 }, /* IEEE80211_MODE_11B */ 486 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */ 487 { 1, 2, 3, 102, 0 }, /* IEEE80211_MODE_FH */ 488 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */ 489 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */ 490 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */ 491 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */ 492 { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */ 493 }; 494 495 static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = { 496 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_AUTO */ 497 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */ 498 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11B */ 499 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11G */ 500 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_FH */ 501 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_A */ 502 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO_G */ 503 { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_STURBO_A */ 504 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NA */ 505 { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11NG */ 506 }; 507 static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = { 508 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_AUTO */ 509 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */ 510 { 2, 3, 4, 188, 0 }, /* IEEE80211_MODE_11B */ 511 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11G */ 512 { 2, 3, 4, 188, 0 }, /* IEEE80211_MODE_FH */ 513 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_A */ 514 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO_G */ 515 { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_STURBO_A */ 516 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NA */ 517 { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11NG */ 518 }; 519 static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = { 520 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_AUTO */ 521 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */ 522 { 2, 2, 3, 102, 0 }, /* IEEE80211_MODE_11B */ 523 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11G */ 524 { 2, 2, 3, 102, 0 }, /* IEEE80211_MODE_FH */ 525 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_A */ 526 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO_G */ 527 { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_STURBO_A */ 528 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NA */ 529 { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11NG */ 530 }; 531 532 void 533 ieee80211_wme_initparams(struct ieee80211com *ic) 534 { 535 struct ieee80211_wme_state *wme = &ic->ic_wme; 536 const paramType *pPhyParam, *pBssPhyParam; 537 struct wmeParams *wmep; 538 enum ieee80211_phymode mode; 539 int i; 540 541 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 542 return; 543 544 /* 545 * Select mode; we can be called early in which case we 546 * always use auto mode. We know we'll be called when 547 * entering the RUN state with bsschan setup properly 548 * so state will eventually get set correctly 549 */ 550 if (ic->ic_curchan != IEEE80211_CHAN_ANYC) 551 mode = ieee80211_chan2mode(ic, ic->ic_curchan); 552 else 553 mode = IEEE80211_MODE_AUTO; 554 for (i = 0; i < WME_NUM_AC; i++) { 555 switch (i) { 556 case WME_AC_BK: 557 pPhyParam = &phyParamForAC_BK[mode]; 558 pBssPhyParam = &phyParamForAC_BK[mode]; 559 break; 560 case WME_AC_VI: 561 pPhyParam = &phyParamForAC_VI[mode]; 562 pBssPhyParam = &bssPhyParamForAC_VI[mode]; 563 break; 564 case WME_AC_VO: 565 pPhyParam = &phyParamForAC_VO[mode]; 566 pBssPhyParam = &bssPhyParamForAC_VO[mode]; 567 break; 568 case WME_AC_BE: 569 default: 570 pPhyParam = &phyParamForAC_BE[mode]; 571 pBssPhyParam = &bssPhyParamForAC_BE[mode]; 572 break; 573 } 574 575 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 576 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 577 wmep->wmep_acm = pPhyParam->acm; 578 wmep->wmep_aifsn = pPhyParam->aifsn; 579 wmep->wmep_logcwmin = pPhyParam->logcwmin; 580 wmep->wmep_logcwmax = pPhyParam->logcwmax; 581 wmep->wmep_txopLimit = pPhyParam->txopLimit; 582 } else { 583 wmep->wmep_acm = pBssPhyParam->acm; 584 wmep->wmep_aifsn = pBssPhyParam->aifsn; 585 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 586 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 587 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 588 589 } 590 ieee80211_dbg(IEEE80211_MSG_WME, "ieee80211_wme_initparams: " 591 "%s chan [acm %u aifsn %u log2(cwmin) %u " 592 "log2(cwmax) %u txpoLimit %u]\n", 593 ieee80211_wme_acnames[i], 594 wmep->wmep_acm, 595 wmep->wmep_aifsn, 596 wmep->wmep_logcwmin, 597 wmep->wmep_logcwmax, 598 wmep->wmep_txopLimit); 599 600 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 601 wmep->wmep_acm = pBssPhyParam->acm; 602 wmep->wmep_aifsn = pBssPhyParam->aifsn; 603 wmep->wmep_logcwmin = pBssPhyParam->logcwmin; 604 wmep->wmep_logcwmax = pBssPhyParam->logcwmax; 605 wmep->wmep_txopLimit = pBssPhyParam->txopLimit; 606 ieee80211_dbg(IEEE80211_MSG_WME, "ieee80211_wme_initparams: " 607 "%s bss [acm %u aifsn %u log2(cwmin) %u " 608 "log2(cwmax) %u txpoLimit %u]\n", 609 ieee80211_wme_acnames[i], 610 wmep->wmep_acm, 611 wmep->wmep_aifsn, 612 wmep->wmep_logcwmin, 613 wmep->wmep_logcwmax, 614 wmep->wmep_txopLimit); 615 } 616 /* NB: check ic_bss to avoid NULL deref on initial attach */ 617 if (ic->ic_bss != NULL) { 618 /* 619 * Calculate agressive mode switching threshold based 620 * on beacon interval. This doesn't need locking since 621 * we're only called before entering the RUN state at 622 * which point we start sending beacon frames. 623 */ 624 wme->wme_hipri_switch_thresh = 625 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->in_intval) / 100; 626 ieee80211_wme_updateparams(ic); 627 } 628 } 629 630 /* 631 * Update WME parameters for ourself and the BSS. 632 */ 633 void 634 ieee80211_wme_updateparams(struct ieee80211com *ic) 635 { 636 static const paramType phyParam[IEEE80211_MODE_MAX] = { 637 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_AUTO */ 638 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11A */ 639 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_11B */ 640 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11G */ 641 { 2, 5, 10, 64, 0 }, /* IEEE80211_MODE_FH */ 642 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_A */ 643 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_TURBO_G */ 644 { 1, 3, 10, 64, 0 }, /* IEEE80211_MODE_STURBO_A */ 645 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NA */ 646 { 2, 4, 10, 64, 0 }, /* IEEE80211_MODE_11NG */ 647 }; 648 struct ieee80211_wme_state *wme = &ic->ic_wme; 649 const struct wmeParams *wmep; 650 struct wmeParams *chanp, *bssp; 651 enum ieee80211_phymode mode; 652 int i; 653 654 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 655 return; 656 657 /* set up the channel access parameters for the physical device */ 658 for (i = 0; i < WME_NUM_AC; i++) { 659 chanp = &wme->wme_chanParams.cap_wmeParams[i]; 660 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i]; 661 chanp->wmep_aifsn = wmep->wmep_aifsn; 662 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 663 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 664 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 665 666 chanp = &wme->wme_bssChanParams.cap_wmeParams[i]; 667 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i]; 668 chanp->wmep_aifsn = wmep->wmep_aifsn; 669 chanp->wmep_logcwmin = wmep->wmep_logcwmin; 670 chanp->wmep_logcwmax = wmep->wmep_logcwmax; 671 chanp->wmep_txopLimit = wmep->wmep_txopLimit; 672 } 673 674 /* 675 * Select mode; we can be called early in which case we 676 * always use auto mode. We know we'll be called when 677 * entering the RUN state with bsschan setup properly 678 * so state will eventually get set correctly 679 */ 680 if (ic->ic_curchan != IEEE80211_CHAN_ANYC) 681 mode = ieee80211_chan2mode(ic, ic->ic_curchan); 682 else 683 mode = IEEE80211_MODE_AUTO; 684 685 /* 686 * This implements agressive mode as found in certain 687 * vendors' AP's. When there is significant high 688 * priority (VI/VO) traffic in the BSS throttle back BE 689 * traffic by using conservative parameters. Otherwise 690 * BE uses agressive params to optimize performance of 691 * legacy/non-QoS traffic. 692 */ 693 if ((ic->ic_opmode == IEEE80211_M_HOSTAP && 694 (wme->wme_flags & WME_F_AGGRMODE) != 0) || 695 (ic->ic_opmode == IEEE80211_M_STA && 696 (ic->ic_bss->in_flags & IEEE80211_NODE_QOS) == 0) || 697 (ic->ic_flags & IEEE80211_F_WME) == 0) { 698 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE]; 699 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE]; 700 701 chanp->wmep_aifsn = bssp->wmep_aifsn = phyParam[mode].aifsn; 702 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 703 phyParam[mode].logcwmin; 704 chanp->wmep_logcwmax = bssp->wmep_logcwmax = 705 phyParam[mode].logcwmax; 706 chanp->wmep_txopLimit = bssp->wmep_txopLimit = 707 (ic->ic_flags & IEEE80211_F_BURST) ? 708 phyParam[mode].txopLimit : 0; 709 ieee80211_dbg(IEEE80211_MSG_WME, 710 "ieee80211_wme_updateparams_locked: " 711 "%s [acm %u aifsn %u log2(cwmin) %u " 712 "log2(cwmax) %u txpoLimit %u]\n", 713 ieee80211_wme_acnames[WME_AC_BE], 714 chanp->wmep_acm, 715 chanp->wmep_aifsn, 716 chanp->wmep_logcwmin, 717 chanp->wmep_logcwmax, 718 chanp->wmep_txopLimit); 719 } 720 721 wme->wme_update(ic); 722 723 ieee80211_dbg(IEEE80211_MSG_WME, "ieee80211_wme_updateparams(): " 724 "WME params updated, cap_info 0x%x\n", 725 ic->ic_opmode == IEEE80211_M_STA ? 726 wme->wme_wmeChanParams.cap_info : 727 wme->wme_bssChanParams.cap_info); 728 } 729 730 /* 731 * Process STA mode beacon miss events. Send a direct probe request 732 * frame to the current ap bmiss_max times (w/o answer) before 733 * scanning for a new ap. 734 */ 735 void 736 ieee80211_beacon_miss(ieee80211com_t *ic) 737 { 738 ieee80211_impl_t *im = ic->ic_private; 739 740 if (ic->ic_flags & IEEE80211_F_SCAN) 741 return; 742 ieee80211_dbg(IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, 743 "%s\n", "beacon miss"); 744 745 /* 746 * Our handling is only meaningful for stations that are 747 * associated; any other conditions else will be handled 748 * through different means (e.g. the tx timeout on mgt frames). 749 */ 750 if (ic->ic_opmode != IEEE80211_M_STA || 751 ic->ic_state != IEEE80211_S_RUN) { 752 return; 753 } 754 755 IEEE80211_LOCK(ic); 756 if (++im->im_bmiss_count < im->im_bmiss_max) { 757 /* 758 * Send a directed probe req before falling back to a scan; 759 * if we receive a response ic_bmiss_count will be reset. 760 * Some cards mistakenly report beacon miss so this avoids 761 * the expensive scan if the ap is still there. 762 */ 763 IEEE80211_UNLOCK(ic); 764 (void) ieee80211_send_probereq(ic->ic_bss, ic->ic_macaddr, 765 ic->ic_bss->in_bssid, ic->ic_bss->in_bssid, 766 ic->ic_bss->in_essid, ic->ic_bss->in_esslen, 767 ic->ic_opt_ie, ic->ic_opt_ie_len); 768 return; 769 } 770 im->im_bmiss_count = 0; 771 IEEE80211_UNLOCK(ic); 772 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 773 } 774 775 /* 776 * Manage state transition between INIT | AUTH | ASSOC | RUN. 777 */ 778 static int 779 ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg) 780 { 781 struct ieee80211_impl *im = ic->ic_private; 782 ieee80211_node_t *in; 783 enum ieee80211_state ostate; 784 wifi_data_t wd = { 0 }; 785 786 IEEE80211_LOCK(ic); 787 ostate = ic->ic_state; 788 ieee80211_dbg(IEEE80211_MSG_STATE, "ieee80211_newstate(): " 789 "%s -> %s\n", 790 ieee80211_state_name[ostate], ieee80211_state_name[nstate]); 791 ic->ic_state = nstate; 792 in = ic->ic_bss; 793 im->im_swbmiss_period = 0; /* Reset software beacon miss period */ 794 795 switch (nstate) { 796 case IEEE80211_S_INIT: 797 IEEE80211_UNLOCK(ic); 798 switch (ostate) { 799 case IEEE80211_S_INIT: 800 return (0); 801 case IEEE80211_S_SCAN: 802 ieee80211_cancel_scan(ic); 803 break; 804 case IEEE80211_S_AUTH: 805 break; 806 case IEEE80211_S_ASSOC: 807 if (ic->ic_opmode == IEEE80211_M_STA) { 808 IEEE80211_SEND_MGMT(ic, in, 809 IEEE80211_FC0_SUBTYPE_DEAUTH, 810 IEEE80211_REASON_AUTH_LEAVE); 811 } 812 break; 813 case IEEE80211_S_RUN: 814 switch (ic->ic_opmode) { 815 case IEEE80211_M_STA: 816 IEEE80211_SEND_MGMT(ic, in, 817 IEEE80211_FC0_SUBTYPE_DEAUTH, 818 IEEE80211_REASON_AUTH_LEAVE); 819 ieee80211_sta_leave(ic, in); 820 break; 821 case IEEE80211_M_IBSS: 822 ieee80211_notify_node_leave(ic, in); 823 break; 824 default: 825 break; 826 } 827 break; 828 } 829 IEEE80211_LOCK(ic); 830 im->im_mgt_timer = 0; 831 ieee80211_reset_bss(ic); 832 break; 833 case IEEE80211_S_SCAN: 834 switch (ostate) { 835 case IEEE80211_S_INIT: 836 IEEE80211_UNLOCK(ic); 837 ieee80211_begin_scan(ic, (arg == 0) ? B_FALSE : B_TRUE); 838 return (0); 839 case IEEE80211_S_SCAN: 840 /* 841 * Scan next. If doing an active scan and the 842 * channel is not marked passive-only then send 843 * a probe request. Otherwise just listen for 844 * beacons on the channel. 845 */ 846 if ((ic->ic_flags & IEEE80211_F_ASCAN) && 847 !IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan)) { 848 IEEE80211_UNLOCK(ic); 849 (void) ieee80211_send_probereq(in, 850 ic->ic_macaddr, wifi_bcastaddr, 851 wifi_bcastaddr, 852 ic->ic_des_essid, ic->ic_des_esslen, 853 ic->ic_opt_ie, ic->ic_opt_ie_len); 854 return (0); 855 } 856 break; 857 case IEEE80211_S_RUN: 858 /* beacon miss */ 859 ieee80211_dbg(IEEE80211_MSG_STATE, 860 "no recent beacons from %s, rescanning\n", 861 ieee80211_macaddr_sprintf(in->in_macaddr)); 862 IEEE80211_UNLOCK(ic); 863 ieee80211_sta_leave(ic, in); 864 IEEE80211_LOCK(ic); 865 ic->ic_flags &= ~IEEE80211_F_SIBSS; 866 /* FALLTHRU */ 867 case IEEE80211_S_AUTH: 868 case IEEE80211_S_ASSOC: 869 /* timeout restart scan */ 870 in = ieee80211_find_node(&ic->ic_scan, 871 ic->ic_bss->in_macaddr); 872 if (in != NULL) { 873 in->in_fails++; 874 ieee80211_unref_node(&in); 875 } 876 break; 877 } 878 break; 879 case IEEE80211_S_AUTH: 880 ASSERT(ic->ic_opmode == IEEE80211_M_STA); 881 switch (ostate) { 882 case IEEE80211_S_INIT: 883 case IEEE80211_S_SCAN: 884 IEEE80211_UNLOCK(ic); 885 IEEE80211_SEND_MGMT(ic, in, IEEE80211_FC0_SUBTYPE_AUTH, 886 1); 887 return (0); 888 case IEEE80211_S_AUTH: 889 case IEEE80211_S_ASSOC: 890 switch (arg) { 891 case IEEE80211_FC0_SUBTYPE_AUTH: 892 IEEE80211_UNLOCK(ic); 893 IEEE80211_SEND_MGMT(ic, in, 894 IEEE80211_FC0_SUBTYPE_AUTH, 2); 895 return (0); 896 case IEEE80211_FC0_SUBTYPE_DEAUTH: 897 /* ignore and retry scan on timeout */ 898 break; 899 } 900 break; 901 case IEEE80211_S_RUN: 902 switch (arg) { 903 case IEEE80211_FC0_SUBTYPE_AUTH: 904 ic->ic_state = ostate; /* stay RUN */ 905 IEEE80211_UNLOCK(ic); 906 IEEE80211_SEND_MGMT(ic, in, 907 IEEE80211_FC0_SUBTYPE_AUTH, 2); 908 return (0); 909 case IEEE80211_FC0_SUBTYPE_DEAUTH: 910 IEEE80211_UNLOCK(ic); 911 ieee80211_sta_leave(ic, in); 912 /* try to re-auth */ 913 IEEE80211_SEND_MGMT(ic, in, 914 IEEE80211_FC0_SUBTYPE_AUTH, 1); 915 return (0); 916 } 917 break; 918 } 919 break; 920 case IEEE80211_S_ASSOC: 921 ASSERT(ic->ic_opmode == IEEE80211_M_STA || 922 ic->ic_opmode == IEEE80211_M_IBSS); 923 switch (ostate) { 924 case IEEE80211_S_INIT: 925 case IEEE80211_S_SCAN: 926 case IEEE80211_S_ASSOC: 927 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_newstate: " 928 "invalid transition\n"); 929 break; 930 case IEEE80211_S_AUTH: 931 IEEE80211_UNLOCK(ic); 932 IEEE80211_SEND_MGMT(ic, in, 933 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); 934 return (0); 935 case IEEE80211_S_RUN: 936 IEEE80211_UNLOCK(ic); 937 ieee80211_sta_leave(ic, in); 938 IEEE80211_SEND_MGMT(ic, in, 939 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); 940 return (0); 941 } 942 break; 943 case IEEE80211_S_RUN: 944 switch (ostate) { 945 case IEEE80211_S_INIT: 946 ieee80211_err("ieee80211_newstate: " 947 "invalid transition\n"); 948 break; 949 case IEEE80211_S_AUTH: 950 ieee80211_err("ieee80211_newstate: " 951 "invalid transition\n"); 952 break; 953 case IEEE80211_S_SCAN: /* adhoc/hostap mode */ 954 case IEEE80211_S_ASSOC: /* infra mode */ 955 ASSERT(in->in_txrate < in->in_rates.ir_nrates); 956 im->im_mgt_timer = 0; 957 ieee80211_notify_node_join(ic, in); 958 959 /* 960 * We can send data now; update the fastpath with our 961 * current associated BSSID and other relevant settings. 962 */ 963 wd.wd_secalloc = ieee80211_crypto_getciphertype(ic); 964 wd.wd_opmode = ic->ic_opmode; 965 IEEE80211_ADDR_COPY(wd.wd_bssid, in->in_bssid); 966 wd.wd_qospad = 0; 967 if (in->in_flags & 968 (IEEE80211_NODE_QOS|IEEE80211_NODE_HT)) { 969 wd.wd_qospad = 2; 970 if (ic->ic_flags & IEEE80211_F_DATAPAD) { 971 wd.wd_qospad = roundup(wd.wd_qospad, 972 sizeof (uint32_t)); 973 } 974 } 975 (void) mac_pdata_update(ic->ic_mach, &wd, sizeof (wd)); 976 break; 977 } 978 979 /* 980 * When 802.1x is not in use mark the port authorized 981 * at this point so traffic can flow. 982 */ 983 if (in->in_authmode != IEEE80211_AUTH_8021X) 984 ieee80211_node_authorize(in); 985 /* 986 * Enable inactivity processing. 987 */ 988 ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT; 989 ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT; 990 break; /* IEEE80211_S_RUN */ 991 } /* switch nstate */ 992 IEEE80211_UNLOCK(ic); 993 994 return (0); 995 } 996