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