1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 * 5 * Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> 6 */ 7 8 /* 9 * Copyright (c) 2001 Atsushi Onoe 10 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * Alternatively, this software may be distributed under the terms of the 25 * GNU General Public License ("GPL") version 2 as published by the Free 26 * Software Foundation. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 29 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 30 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 31 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 33 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 37 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Send out 802.11 frames 42 */ 43 44 #include <sys/byteorder.h> 45 #include <sys/strsun.h> 46 #include "net80211_impl.h" 47 48 /* 49 * Set the direction field and address fields of an outgoing 50 * non-QoS frame. Note this should be called early on in 51 * constructing a frame as it sets i_fc[1]; other bits can 52 * then be or'd in. 53 */ 54 static void 55 ieee80211_send_setup(ieee80211com_t *ic, ieee80211_node_t *in, 56 struct ieee80211_frame *wh, int type, const uint8_t *sa, const uint8_t *da, 57 const uint8_t *bssid) 58 { 59 wh->i_fc[0] = (uint8_t)(IEEE80211_FC0_VERSION_0 | type); 60 if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) { 61 switch (ic->ic_opmode) { 62 case IEEE80211_M_STA: 63 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; 64 IEEE80211_ADDR_COPY(wh->i_addr1, bssid); 65 IEEE80211_ADDR_COPY(wh->i_addr2, sa); 66 IEEE80211_ADDR_COPY(wh->i_addr3, da); 67 break; 68 case IEEE80211_M_IBSS: 69 case IEEE80211_M_AHDEMO: 70 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 71 IEEE80211_ADDR_COPY(wh->i_addr1, da); 72 IEEE80211_ADDR_COPY(wh->i_addr2, sa); 73 IEEE80211_ADDR_COPY(wh->i_addr3, bssid); 74 break; 75 default: 76 ieee80211_err("ieee80211_send_setup: " 77 "Invalid mode %u\n", ic->ic_opmode); 78 return; 79 } 80 } else { 81 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 82 IEEE80211_ADDR_COPY(wh->i_addr1, da); 83 IEEE80211_ADDR_COPY(wh->i_addr2, sa); 84 IEEE80211_ADDR_COPY(wh->i_addr3, bssid); 85 } 86 *(uint16_t *)&wh->i_dur[0] = 0; /* set duration */ 87 /* NB: use non-QoS tid */ 88 *(uint16_t *)&wh->i_seq[0] = 89 LE_16(in->in_txseqs[IEEE80211_NONQOS_TID] << 90 IEEE80211_SEQ_SEQ_SHIFT); 91 in->in_txseqs[IEEE80211_NONQOS_TID]++; 92 } 93 94 /* 95 * Send a management frame to the specified node. The node pointer 96 * must have a reference as the pointer will be passed to the driver 97 * and potentially held for a long time. If the frame is successfully 98 * dispatched to the driver, then it is responsible for freeing the 99 * reference (and potentially free'ing up any associated storage). 100 * 101 * Return 0 on success 102 */ 103 int 104 ieee80211_mgmt_output(ieee80211com_t *ic, ieee80211_node_t *in, mblk_t *mp, 105 int type, int timer) 106 { 107 ieee80211_impl_t *im = ic->ic_private; 108 struct ieee80211_frame *wh; 109 110 ASSERT(in != NULL); 111 112 wh = (struct ieee80211_frame *)mp->b_rptr; 113 ieee80211_send_setup(ic, in, wh, IEEE80211_FC0_TYPE_MGT | type, 114 ic->ic_macaddr, in->in_macaddr, in->in_bssid); 115 if (in->in_challenge != NULL) 116 wh->i_fc[1] |= IEEE80211_FC1_WEP; 117 118 if (timer > 0) { 119 /* 120 * Set the mgt frame timeout. 121 */ 122 im->im_mgt_timer = timer; 123 ieee80211_start_watchdog(ic, 1); 124 } 125 return ((*ic->ic_xmit)(ic, mp, IEEE80211_FC0_TYPE_MGT)); 126 } 127 128 /* 129 * Send a null data frame to the specified node. 130 * 131 * NB: the caller is assumed to have setup a node reference 132 * for use; this is necessary to deal with a race condition 133 * when probing for inactive stations. 134 */ 135 int 136 ieee80211_send_nulldata(ieee80211_node_t *in) 137 { 138 ieee80211com_t *ic = in->in_ic; 139 mblk_t *m; 140 struct ieee80211_frame *wh; 141 uint8_t *frm; 142 143 m = ieee80211_getmgtframe(&frm, 0); 144 if (m == NULL) { 145 ic->ic_stats.is_tx_nobuf++; 146 return (ENOMEM); 147 } 148 149 wh = (struct ieee80211_frame *)m->b_rptr; 150 ieee80211_send_setup(ic, in, wh, 151 IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NODATA, 152 ic->ic_macaddr, in->in_macaddr, in->in_bssid); 153 /* NB: power management bit is never sent by an AP */ 154 if ((in->in_flags & IEEE80211_NODE_PWR_MGT) && 155 ic->ic_opmode != IEEE80211_M_HOSTAP) 156 wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT; 157 m->b_wptr = m->b_rptr + sizeof (struct ieee80211_frame); 158 159 ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS, "net80211: " 160 "send null data frame on channel %u, pwr mgt %s\n", 161 ieee80211_macaddr_sprintf(in->in_macaddr), 162 ieee80211_chan2ieee(ic, ic->ic_curchan), 163 wh->i_fc[1] & IEEE80211_FC1_PWR_MGT ? "ena" : "dis"); 164 165 (void) (*ic->ic_xmit)(ic, m, IEEE80211_FC0_TYPE_MGT); 166 167 return (0); 168 } 169 170 /* 171 * Encapsulate an outbound data frame for GLDv3 based driver. 172 * Fill in the variable part of the 80211 frame 173 */ 174 /* ARGSUSED */ 175 mblk_t * 176 ieee80211_encap(ieee80211com_t *ic, mblk_t *mp, ieee80211_node_t *in) 177 { 178 struct ieee80211_frame *wh; 179 struct ieee80211_key *key; 180 int addqos, ac, tid; 181 182 ASSERT(mp != NULL && MBLKL(mp) >= sizeof (struct ieee80211_frame)); 183 /* 184 * Some ap's don't handle QoS-encapsulated EAPOL 185 * frames so suppress use. This may be an issue if other 186 * ap's require all data frames to be QoS-encapsulated 187 * once negotiated in which case we'll need to make this 188 * configurable. 189 */ 190 addqos = in->in_flags & (IEEE80211_NODE_QOS | IEEE80211_NODE_HT); 191 wh = (struct ieee80211_frame *)mp->b_rptr; 192 *(uint16_t *)wh->i_dur = 0; 193 if (addqos) { 194 struct ieee80211_qosframe *qwh = 195 (struct ieee80211_qosframe *)wh; 196 197 ac = ieee80211_classify(ic, mp, in); 198 /* map from access class/queue to 11e header priorty value */ 199 tid = WME_AC_TO_TID(ac); 200 qwh->i_qos[0] = tid & IEEE80211_QOS_TID; 201 /* 202 * Check if A-MPDU tx aggregation is setup or if we 203 * should try to enable it. The sta must be associated 204 * with HT and A-MPDU enabled for use. On the first 205 * frame that goes out We issue an ADDBA request and 206 * wait for a reply. The frame being encapsulated 207 * will go out w/o using A-MPDU, or possibly it might 208 * be collected by the driver and held/retransmit. 209 * ieee80211_ampdu_request handles staggering requests 210 * in case the receiver NAK's us or we are otherwise 211 * unable to establish a BA stream. 212 */ 213 if ((in->in_flags & IEEE80211_NODE_AMPDU_TX) && 214 (ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX)) { 215 struct ieee80211_tx_ampdu *tap = &in->in_tx_ampdu[ac]; 216 217 if (IEEE80211_AMPDU_RUNNING(tap)) { 218 /* 219 * Operational, mark frame for aggregation. 220 */ 221 qwh->i_qos[0] |= IEEE80211_QOS_ACKPOLICY_BA; 222 } else if (!IEEE80211_AMPDU_REQUESTED(tap)) { 223 /* 224 * Not negotiated yet, request service. 225 */ 226 (void) ieee80211_ampdu_request(in, tap); 227 } 228 } 229 /* works even when BA marked above */ 230 if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[ac]. 231 wmep_noackPolicy) { 232 qwh->i_qos[0] |= IEEE80211_QOS_ACKPOLICY_NOACK; 233 } 234 235 *(uint16_t *)wh->i_seq = 236 LE_16(in->in_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT); 237 in->in_txseqs[tid]++; 238 } else { 239 *(uint16_t *)wh->i_seq = 240 LE_16(in->in_txseqs[IEEE80211_NONQOS_TID] << 241 IEEE80211_SEQ_SEQ_SHIFT); 242 in->in_txseqs[IEEE80211_NONQOS_TID]++; 243 } 244 245 if (ic->ic_flags & IEEE80211_F_PRIVACY) 246 key = ieee80211_crypto_getkey(ic); 247 else 248 key = NULL; 249 250 /* 251 * IEEE 802.1X: send EAPOL frames always in the clear. 252 * WPA/WPA2: encrypt EAPOL keys when pairwise keys are set. 253 */ 254 if (key != NULL && (ic->ic_flags & IEEE80211_F_WPA)) { 255 wh->i_fc[1] |= IEEE80211_FC1_WEP; 256 if (!ieee80211_crypto_enmic(isc, key, mp, 0)) 257 ieee80211_err("ieee80211_crypto_enmic failed.\n"); 258 } 259 260 return (mp); 261 } 262 263 /* 264 * Add supported rates information element to a frame. 265 */ 266 static uint8_t * 267 ieee80211_add_rates(uint8_t *frm, const struct ieee80211_rateset *rs) 268 { 269 uint8_t nrates; 270 271 *frm++ = IEEE80211_ELEMID_RATES; 272 nrates = rs->ir_nrates; 273 if (nrates > IEEE80211_RATE_SIZE) 274 nrates = IEEE80211_RATE_SIZE; 275 *frm++ = nrates; 276 bcopy(rs->ir_rates, frm, nrates); 277 return (frm + nrates); 278 } 279 280 /* 281 * Add extended supported rates element to a frame, usually for 11g mode 282 */ 283 static uint8_t * 284 ieee80211_add_xrates(uint8_t *frm, const struct ieee80211_rateset *rs) 285 { 286 if (rs->ir_nrates > IEEE80211_RATE_SIZE) { 287 uint8_t nrates = rs->ir_nrates - IEEE80211_RATE_SIZE; 288 289 *frm++ = IEEE80211_ELEMID_XRATES; 290 *frm++ = nrates; 291 bcopy(rs->ir_rates + IEEE80211_RATE_SIZE, frm, nrates); 292 frm += nrates; 293 } 294 return (frm); 295 } 296 297 #define WME_OUI_BYTES 0x00, 0x50, 0xf2 298 /* 299 * Add a WME information element to a frame. 300 */ 301 /* ARGSUSED */ 302 static uint8_t * 303 ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme) 304 { 305 static const struct ieee80211_wme_info info = { 306 .wme_id = IEEE80211_ELEMID_VENDOR, 307 .wme_len = sizeof (struct ieee80211_wme_info) - 2, 308 .wme_oui = { WME_OUI_BYTES }, 309 .wme_type = WME_OUI_TYPE, 310 .wme_subtype = WME_INFO_OUI_SUBTYPE, 311 .wme_version = WME_VERSION, 312 .wme_info = 0, 313 }; 314 (void) memcpy(frm, &info, sizeof (info)); 315 return (frm + sizeof (info)); 316 } 317 318 /* 319 * Add a WME parameters element to a frame. 320 */ 321 static uint8_t * 322 ieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme) 323 { 324 #define SM(_v, _f) (((_v) << _f##_S) & _f) 325 #define ADDSHORT(frm, v) do { \ 326 _NOTE(CONSTCOND) \ 327 frm[0] = (v) & 0xff; \ 328 frm[1] = (v) >> 8; \ 329 frm += 2; \ 330 _NOTE(CONSTCOND) \ 331 } while (0) 332 /* NB: this works 'cuz a param has an info at the front */ 333 static const struct ieee80211_wme_info param = { 334 .wme_id = IEEE80211_ELEMID_VENDOR, 335 .wme_len = sizeof (struct ieee80211_wme_param) - 2, 336 .wme_oui = { WME_OUI_BYTES }, 337 .wme_type = WME_OUI_TYPE, 338 .wme_subtype = WME_PARAM_OUI_SUBTYPE, 339 .wme_version = WME_VERSION, 340 }; 341 int i; 342 343 (void) memcpy(frm, ¶m, sizeof (param)); 344 frm += offsetof(struct ieee80211_wme_info, wme_info); 345 *frm++ = wme->wme_bssChanParams.cap_info; /* AC info */ 346 *frm++ = 0; /* reserved field */ 347 for (i = 0; i < WME_NUM_AC; i++) { 348 const struct wmeParams *ac = 349 &wme->wme_bssChanParams.cap_wmeParams[i]; 350 *frm++ = SM(i, WME_PARAM_ACI) 351 | SM(ac->wmep_acm, WME_PARAM_ACM) 352 | SM(ac->wmep_aifsn, WME_PARAM_AIFSN); 353 *frm++ = SM(ac->wmep_logcwmax, WME_PARAM_LOGCWMAX) 354 | SM(ac->wmep_logcwmin, WME_PARAM_LOGCWMIN); 355 ADDSHORT(frm, ac->wmep_txopLimit); 356 } 357 return (frm); 358 #undef SM 359 #undef ADDSHORT 360 } 361 #undef WME_OUI_BYTES 362 363 /* 364 * Add SSID element to a frame 365 */ 366 static uint8_t * 367 ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, uint32_t len) 368 { 369 *frm++ = IEEE80211_ELEMID_SSID; 370 *frm++ = (uint8_t)len; 371 bcopy(ssid, frm, len); 372 return (frm + len); 373 } 374 375 /* 376 * Add an erp element to a frame. 377 */ 378 static uint8_t * 379 ieee80211_add_erp(uint8_t *frm, ieee80211com_t *ic) 380 { 381 uint8_t erp; 382 383 *frm++ = IEEE80211_ELEMID_ERP; 384 *frm++ = 1; 385 erp = 0; 386 if (ic->ic_flags & IEEE80211_F_USEPROT) 387 erp |= IEEE80211_ERP_USE_PROTECTION; 388 if (ic->ic_flags & IEEE80211_F_USEBARKER) 389 erp |= IEEE80211_ERP_LONG_PREAMBLE; 390 *frm++ = erp; 391 return (frm); 392 } 393 394 /* 395 * Get capability information from the interface softc, ic. 396 */ 397 static uint16_t 398 ieee80211_get_capinfo(ieee80211com_t *ic) 399 { 400 uint16_t capinfo; 401 402 if (ic->ic_opmode == IEEE80211_M_IBSS) 403 capinfo = IEEE80211_CAPINFO_IBSS; 404 else 405 capinfo = IEEE80211_CAPINFO_ESS; 406 if (ic->ic_flags & IEEE80211_F_PRIVACY) 407 capinfo |= IEEE80211_CAPINFO_PRIVACY; 408 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 409 IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) { 410 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; 411 } 412 if (ic->ic_flags & IEEE80211_F_SHSLOT) 413 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; 414 415 return (capinfo); 416 } 417 418 /* 419 * Send a probe request frame with the specified ssid 420 * and any optional information element data. 421 */ 422 int 423 ieee80211_send_probereq(ieee80211_node_t *in, 424 const uint8_t *sa, const uint8_t *da, const uint8_t *bssid, 425 const uint8_t *ssid, size_t ssidlen, const void *optie, size_t optielen) 426 { 427 mblk_t *mp; 428 ieee80211com_t *ic = in->in_ic; 429 enum ieee80211_phymode mode; 430 struct ieee80211_frame *wh; 431 uint8_t *frm; 432 433 /* 434 * prreq frame format ([tlv] - 1 byte element ID + 1 byte length) 435 * [tlv] ssid 436 * [tlv] supported rates 437 * [tlv] extended supported rates 438 * [tlv] user-specified ie's 439 */ 440 mp = ieee80211_getmgtframe(&frm, 441 2 + IEEE80211_NWID_LEN 442 + 2 + IEEE80211_RATE_SIZE + 443 + 2 + IEEE80211_XRATE_SIZE 444 + optielen); 445 if (mp == NULL) 446 return (ENOMEM); 447 448 frm = ieee80211_add_ssid(frm, ssid, ssidlen); 449 mode = ieee80211_chan2mode(ic, ic->ic_curchan); 450 frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]); 451 frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]); 452 if (optie != NULL) { 453 (void) memcpy(frm, optie, optielen); 454 frm += optielen; 455 } 456 mp->b_wptr = frm; 457 458 wh = (struct ieee80211_frame *)mp->b_rptr; 459 ieee80211_send_setup(ic, in, wh, 460 IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ, 461 sa, da, bssid); 462 463 ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS, 464 "[%s] send probe req on channel %u\n", 465 ieee80211_macaddr_sprintf(wh->i_addr1), 466 ieee80211_chan2ieee(ic, ic->ic_curchan)); 467 468 (void) (*ic->ic_xmit)(ic, mp, IEEE80211_FC0_TYPE_MGT); 469 return (0); 470 } 471 472 /* 473 * Send a management frame. The node is for the destination (or ic_bss 474 * when in station mode). Nodes other than ic_bss have their reference 475 * count bumped to reflect our use for an indeterminant time. 476 */ 477 int 478 ieee80211_send_mgmt(ieee80211com_t *ic, ieee80211_node_t *in, int type, int arg) 479 { 480 mblk_t *mp; 481 uint8_t *frm; 482 uint16_t capinfo; 483 struct ieee80211_key *key; 484 boolean_t has_challenge; 485 boolean_t is_shared_key; 486 int ret; 487 int timer; 488 int status; 489 490 ASSERT(in != NULL); 491 492 timer = 0; 493 switch (type) { 494 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 495 /* 496 * probe response frame format 497 * [8] time stamp 498 * [2] beacon interval 499 * [2] capability information 500 * [tlv] ssid 501 * [tlv] supported rates 502 * [tlv] parameter set (FH/DS) 503 * [tlv] parameter set (IBSS) 504 * [tlv] extended rate phy (ERP) 505 * [tlv] extended supported rates 506 * [tlv] WPA 507 * [tlv] WME (optional) 508 * [tlv] HT capabilities 509 * [tlv] HT information 510 * [tlv] Vendor OUI HT capabilities (optional) 511 * [tlv] Vendor OUI HT information (optional) 512 */ 513 mp = ieee80211_getmgtframe(&frm, 514 8 /* time stamp */ 515 + sizeof (uint16_t) /* beacon interval */ 516 + sizeof (uint16_t) /* capability */ 517 + 2 + IEEE80211_NWID_LEN 518 + 2 + IEEE80211_RATE_SIZE 519 + 2 + IEEE80211_FH_LEN 520 + 2 + IEEE80211_IBSS_LEN 521 + 2 + IEEE80211_ERP_LEN 522 + 2 + IEEE80211_XRATE_SIZE 523 + (ic->ic_flags & IEEE80211_F_WPA ? 524 2 * sizeof (struct ieee80211_ie_wpa) : 0) 525 /* [tlv] WPA */ 526 + (ic->ic_flags & IEEE80211_F_WME ? 527 sizeof (struct ieee80211_wme_param) : 0) 528 /* [tlv] WME */ 529 /* check for cluster requirement */ 530 + 2 * sizeof (struct ieee80211_ie_htcap) + 4 531 + 2 * sizeof (struct ieee80211_ie_htinfo) + 4); 532 533 if (mp == NULL) 534 return (ENOMEM); 535 536 bzero(frm, 8); /* timestamp should be filled later */ 537 frm += 8; 538 *(uint16_t *)frm = LE_16(ic->ic_bss->in_intval); 539 frm += 2; 540 capinfo = ieee80211_get_capinfo(ic); 541 *(uint16_t *)frm = LE_16(capinfo); 542 frm += 2; 543 544 /* ssid */ 545 frm = ieee80211_add_ssid(frm, ic->ic_bss->in_essid, 546 ic->ic_bss->in_esslen); 547 /* supported rates */ 548 frm = ieee80211_add_rates(frm, &in->in_rates); 549 550 if (IEEE80211_IS_CHAN_FHSS(ic->ic_curchan)) { 551 *frm++ = IEEE80211_ELEMID_FHPARMS; 552 *frm++ = IEEE80211_FH_LEN; 553 *frm++ = in->in_fhdwell & 0x00ff; 554 *frm++ = (in->in_fhdwell >> 8) & 0x00ff; 555 *frm++ = IEEE80211_FH_CHANSET( 556 ieee80211_chan2ieee(ic, ic->ic_curchan)); 557 *frm++ = IEEE80211_FH_CHANPAT( 558 ieee80211_chan2ieee(ic, ic->ic_curchan)); 559 *frm++ = in->in_fhindex; 560 } else { 561 *frm++ = IEEE80211_ELEMID_DSPARMS; 562 *frm++ = IEEE80211_DS_LEN; 563 *frm++ = ieee80211_chan2ieee(ic, ic->ic_curchan); 564 } 565 566 if (ic->ic_opmode == IEEE80211_M_IBSS) { 567 *frm++ = IEEE80211_ELEMID_IBSSPARMS; 568 *frm++ = IEEE80211_IBSS_LEN; 569 *frm++ = 0; *frm++ = 0; /* ATIM window */ 570 } 571 if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) 572 frm = ieee80211_add_erp(frm, ic); 573 frm = ieee80211_add_xrates(frm, &in->in_rates); 574 /* 575 * NB: legacy 11b clients do not get certain ie's. 576 * The caller identifies such clients by passing 577 * a token in arg to us. Could expand this to be 578 * any legacy client for stuff like HT ie's. 579 */ 580 if (IEEE80211_IS_CHAN_HT(ic->ic_curchan) && 581 arg != IEEE80211_SEND_LEGACY_11B) { 582 frm = ieee80211_add_htcap(frm, in); 583 frm = ieee80211_add_htinfo(frm, in); 584 } 585 if (ic->ic_flags & IEEE80211_F_WME) 586 frm = ieee80211_add_wme_param(frm, &ic->ic_wme); 587 if (IEEE80211_IS_CHAN_HT(ic->ic_curchan) && 588 (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) && 589 arg != IEEE80211_SEND_LEGACY_11B) { 590 frm = ieee80211_add_htcap_vendor(frm, in); 591 frm = ieee80211_add_htinfo_vendor(frm, in); 592 } 593 mp->b_wptr = frm; /* allocated is greater than used */ 594 595 break; 596 597 case IEEE80211_FC0_SUBTYPE_AUTH: 598 status = arg >> 16; 599 arg &= 0xffff; 600 has_challenge = ((arg == IEEE80211_AUTH_SHARED_CHALLENGE || 601 arg == IEEE80211_AUTH_SHARED_RESPONSE) && 602 in->in_challenge != NULL); 603 604 /* 605 * Deduce whether we're doing open authentication or 606 * shared key authentication. We do the latter if 607 * we're in the middle of a shared key authentication 608 * handshake or if we're initiating an authentication 609 * request and configured to use shared key. 610 */ 611 is_shared_key = has_challenge || 612 arg >= IEEE80211_AUTH_SHARED_RESPONSE || 613 (arg == IEEE80211_AUTH_SHARED_REQUEST && 614 ic->ic_bss->in_authmode == IEEE80211_AUTH_SHARED); 615 616 if (has_challenge && status == IEEE80211_STATUS_SUCCESS) 617 key = ieee80211_crypto_getkey(ic); 618 else 619 key = NULL; 620 621 mp = ieee80211_getmgtframe(&frm, 622 3 * sizeof (uint16_t) 623 + (has_challenge && status == IEEE80211_STATUS_SUCCESS ? 624 sizeof (uint16_t) + IEEE80211_CHALLENGE_LEN : 0) 625 + (key != NULL ? key->wk_cipher->ic_header : 0)); 626 if (mp == NULL) 627 return (ENOMEM); 628 629 if (key != NULL) 630 frm += key->wk_cipher->ic_header; 631 632 ((uint16_t *)frm)[0] = 633 (is_shared_key) ? LE_16(IEEE80211_AUTH_ALG_SHARED) 634 : LE_16(IEEE80211_AUTH_ALG_OPEN); 635 ((uint16_t *)frm)[1] = LE_16(arg); /* sequence number */ 636 ((uint16_t *)frm)[2] = LE_16(status); /* status */ 637 638 if (has_challenge && status == IEEE80211_STATUS_SUCCESS) { 639 frm += IEEE80211_AUTH_ELEM_MIN; 640 *frm = IEEE80211_ELEMID_CHALLENGE; 641 frm++; 642 *frm = IEEE80211_CHALLENGE_LEN; 643 frm++; 644 bcopy(in->in_challenge, frm, IEEE80211_CHALLENGE_LEN); 645 } 646 647 if (ic->ic_opmode == IEEE80211_M_STA) 648 timer = IEEE80211_TRANS_WAIT; 649 break; 650 651 case IEEE80211_FC0_SUBTYPE_DEAUTH: 652 mp = ieee80211_getmgtframe(&frm, sizeof (uint16_t)); 653 if (mp == NULL) 654 return (ENOMEM); 655 656 *(uint16_t *)frm = LE_16(arg); /* reason */ 657 658 ieee80211_node_unauthorize(in); /* port closed */ 659 break; 660 661 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 662 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: 663 /* 664 * asreq frame format 665 * [2] capability information 666 * [2] listen interval 667 * [6*] current AP address (reassoc only) 668 * [tlv] ssid 669 * [tlv] supported rates 670 * [tlv] extended supported rates 671 * [tlv] WME 672 * [tlv] HT capabilities 673 * [tlv] Vendor OUI HT capabilities (optional) 674 * [tlv] user-specified ie's 675 */ 676 mp = ieee80211_getmgtframe(&frm, 677 sizeof (uint16_t) 678 + sizeof (uint16_t) + IEEE80211_ADDR_LEN 679 + 2 + IEEE80211_NWID_LEN 680 + 2 + IEEE80211_RATE_SIZE 681 + 2 + IEEE80211_XRATE_SIZE 682 + sizeof (struct ieee80211_wme_info) 683 + 2 * sizeof (struct ieee80211_ie_htcap) + 4 684 + ic->ic_opt_ie_len); 685 if (mp == NULL) 686 return (ENOMEM); 687 688 capinfo = ieee80211_get_capinfo(ic); 689 if (!(in->in_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) || 690 !(ic->ic_caps & IEEE80211_C_SHSLOT)) { 691 capinfo &= ~IEEE80211_CAPINFO_SHORT_SLOTTIME; 692 } else { 693 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; 694 } 695 if (!(in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) || 696 !(ic->ic_caps & IEEE80211_C_SHPREAMBLE)) { 697 capinfo &= ~IEEE80211_CAPINFO_SHORT_PREAMBLE; 698 } else { 699 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; 700 } 701 *(uint16_t *)frm = LE_16(capinfo); 702 frm += 2; 703 704 *(uint16_t *)frm = LE_16(ic->ic_lintval); 705 frm += 2; 706 707 if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { 708 IEEE80211_ADDR_COPY(frm, ic->ic_bss->in_bssid); 709 frm += IEEE80211_ADDR_LEN; 710 } 711 712 frm = ieee80211_add_ssid(frm, in->in_essid, in->in_esslen); 713 frm = ieee80211_add_rates(frm, &in->in_rates); 714 frm = ieee80211_add_xrates(frm, &in->in_rates); 715 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) && 716 in->in_htcap_ie != NULL && 717 in->in_htcap_ie[0] == IEEE80211_ELEMID_HTCAP) 718 frm = ieee80211_add_htcap(frm, in); 719 if ((ic->ic_flags & IEEE80211_F_WME) && in->in_wme_ie != NULL) 720 frm = ieee80211_add_wme_info(frm, &ic->ic_wme); 721 if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) && 722 in->in_htcap_ie != NULL && 723 in->in_htcap_ie[0] == IEEE80211_ELEMID_VENDOR) 724 frm = ieee80211_add_htcap_vendor(frm, in); 725 if (ic->ic_opt_ie != NULL) { 726 bcopy(ic->ic_opt_ie, frm, ic->ic_opt_ie_len); 727 frm += ic->ic_opt_ie_len; 728 } 729 mp->b_wptr = frm; /* allocated is greater than used */ 730 731 timer = IEEE80211_TRANS_WAIT; 732 break; 733 734 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 735 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: 736 /* 737 * asreq frame format 738 * [2] capability information 739 * [2] status 740 * [2] association ID 741 * [tlv] supported rates 742 * [tlv] extended supported rates 743 * [tlv] WME (if enabled and STA enabled) 744 * [tlv] HT capabilities (standard or vendor OUI) 745 * [tlv] HT information (standard or vendor OUI) 746 */ 747 mp = ieee80211_getmgtframe(&frm, 748 3 * sizeof (uint16_t) 749 + 2 + IEEE80211_RATE_SIZE 750 + 2 + IEEE80211_XRATE_SIZE); 751 if (mp == NULL) 752 return (ENOMEM); 753 754 capinfo = ieee80211_get_capinfo(ic); 755 *(uint16_t *)frm = LE_16(capinfo); 756 frm += 2; 757 758 *(uint16_t *)frm = LE_16(arg); /* status */ 759 frm += 2; 760 761 if (arg == IEEE80211_STATUS_SUCCESS) 762 *(uint16_t *)frm = LE_16(in->in_associd); 763 else 764 *(uint16_t *)frm = LE_16(0); 765 frm += 2; 766 767 frm = ieee80211_add_rates(frm, &in->in_rates); 768 frm = ieee80211_add_xrates(frm, &in->in_rates); 769 mp->b_wptr = frm; 770 break; 771 772 case IEEE80211_FC0_SUBTYPE_DISASSOC: 773 mp = ieee80211_getmgtframe(&frm, sizeof (uint16_t)); 774 if (mp == NULL) 775 return (ENOMEM); 776 *(uint16_t *)frm = LE_16(arg); /* reason */ 777 break; 778 779 default: 780 ieee80211_dbg(IEEE80211_MSG_ANY, 781 "[%s] invalid mgmt frame type %u\n", 782 ieee80211_macaddr_sprintf(in->in_macaddr), type); 783 return (EINVAL); 784 } /* type */ 785 ret = ieee80211_mgmt_output(ic, in, mp, type, timer); 786 return (ret); 787 } 788 789 /* 790 * Allocate a beacon frame and fillin the appropriate bits. 791 */ 792 mblk_t * 793 ieee80211_beacon_alloc(ieee80211com_t *ic, ieee80211_node_t *in, 794 struct ieee80211_beacon_offsets *bo) 795 { 796 struct ieee80211_frame *wh; 797 struct ieee80211_rateset *rs; 798 mblk_t *m; 799 uint8_t *frm; 800 int pktlen; 801 uint16_t capinfo; 802 803 IEEE80211_LOCK(ic); 804 /* 805 * beacon frame format 806 * [8] time stamp 807 * [2] beacon interval 808 * [2] cabability information 809 * [tlv] ssid 810 * [tlv] supported rates 811 * [3] parameter set (DS) 812 * [tlv] parameter set (IBSS/TIM) 813 * [tlv] extended rate phy (ERP) 814 * [tlv] extended supported rates 815 * [tlv] WME parameters 816 * [tlv] WPA/RSN parameters 817 * [tlv] HT capabilities 818 * [tlv] HT information 819 * [tlv] Vendor OUI HT capabilities (optional) 820 * [tlv] Vendor OUI HT information (optional) 821 * Vendor-specific OIDs (e.g. Atheros) 822 * NB: we allocate the max space required for the TIM bitmap. 823 */ 824 rs = &in->in_rates; 825 pktlen = 8 /* time stamp */ 826 + sizeof (uint16_t) /* beacon interval */ 827 + sizeof (uint16_t) /* capabilities */ 828 + 2 + in->in_esslen /* ssid */ 829 + 2 + IEEE80211_RATE_SIZE /* supported rates */ 830 + 2 + 1 /* DS parameters */ 831 + 2 + 4 + ic->ic_tim_len /* DTIM/IBSSPARMS */ 832 + 2 + 1 /* ERP */ 833 + 2 + IEEE80211_XRATE_SIZE 834 + (ic->ic_caps & IEEE80211_C_WME ? /* WME */ 835 sizeof (struct ieee80211_wme_param) : 0) 836 /* conditional? */ 837 + 4 + 2 * sizeof (struct ieee80211_ie_htcap) /* HT caps */ 838 + 4 + 2 * sizeof (struct ieee80211_ie_htinfo); /* HT info */ 839 840 m = ieee80211_getmgtframe(&frm, pktlen); 841 if (m == NULL) { 842 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_beacon_alloc: " 843 "cannot get buf; size %u\n", pktlen); 844 IEEE80211_UNLOCK(ic); 845 return (NULL); 846 } 847 848 /* timestamp is set by hardware/driver */ 849 (void) memset(frm, 0, 8); 850 frm += 8; 851 *(uint16_t *)frm = LE_16(in->in_intval); 852 frm += 2; 853 capinfo = ieee80211_get_capinfo(ic); 854 bo->bo_caps = (uint16_t *)frm; 855 *(uint16_t *)frm = LE_16(capinfo); 856 frm += 2; 857 *frm++ = IEEE80211_ELEMID_SSID; 858 if (!(ic->ic_flags & IEEE80211_F_HIDESSID)) { 859 *frm++ = in->in_esslen; 860 bcopy(in->in_essid, frm, in->in_esslen); 861 frm += in->in_esslen; 862 } else { 863 *frm++ = 0; 864 } 865 frm = ieee80211_add_rates(frm, rs); 866 if (ic->ic_curmode != IEEE80211_MODE_FH) { 867 *frm++ = IEEE80211_ELEMID_DSPARMS; 868 *frm++ = 1; 869 *frm++ = ieee80211_chan2ieee(ic, in->in_chan); 870 } 871 bo->bo_tim = frm; 872 if (ic->ic_opmode == IEEE80211_M_IBSS) { 873 *frm++ = IEEE80211_ELEMID_IBSSPARMS; 874 *frm++ = 2; 875 *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ 876 bo->bo_tim_len = 0; 877 } else { 878 struct ieee80211_tim_ie *tie = 879 (struct ieee80211_tim_ie *)frm; 880 881 tie->tim_ie = IEEE80211_ELEMID_TIM; 882 tie->tim_len = 4; /* length */ 883 tie->tim_count = 0; /* DTIM count */ 884 tie->tim_period = IEEE80211_DTIM_DEFAULT; 885 tie->tim_bitctl = 0; /* bitmap control */ 886 tie->tim_bitmap[0] = 0; /* Partial Virtual Bitmap */ 887 frm += sizeof (struct ieee80211_tim_ie); 888 bo->bo_tim_len = 1; 889 } 890 bo->bo_trailer = frm; 891 892 if (ic->ic_curmode == IEEE80211_MODE_11G) { 893 bo->bo_erp = frm; 894 frm = ieee80211_add_erp(frm, ic); 895 } 896 frm = ieee80211_add_xrates(frm, rs); 897 if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) { 898 frm = ieee80211_add_htcap(frm, in); 899 bo->bo_htinfo = frm; 900 frm = ieee80211_add_htinfo(frm, in); 901 } 902 if (ic->ic_flags & IEEE80211_F_WME) { 903 bo->bo_wme = frm; 904 frm = ieee80211_add_wme_param(frm, &ic->ic_wme); 905 } 906 if (IEEE80211_IS_CHAN_HT(ic->ic_curchan) && 907 (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT)) { 908 frm = ieee80211_add_htcap_vendor(frm, in); 909 frm = ieee80211_add_htinfo_vendor(frm, in); 910 } 911 bo->bo_trailer_len = _PTRDIFF(frm, bo->bo_trailer); 912 m->b_wptr = frm; 913 914 wh = (struct ieee80211_frame *)m->b_rptr; 915 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 916 IEEE80211_FC0_SUBTYPE_BEACON; 917 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 918 *(uint16_t *)wh->i_dur = 0; 919 IEEE80211_ADDR_COPY(wh->i_addr1, wifi_bcastaddr); 920 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr); 921 IEEE80211_ADDR_COPY(wh->i_addr3, in->in_bssid); 922 *(uint16_t *)wh->i_seq = 0; 923 924 IEEE80211_UNLOCK(ic); 925 return (m); 926 } 927 928 /* 929 * Update the dynamic parts of a beacon frame based on the current state. 930 */ 931 /* ARGSUSED */ 932 int 933 ieee80211_beacon_update(ieee80211com_t *ic, ieee80211_node_t *in, 934 struct ieee80211_beacon_offsets *bo, mblk_t *mp, int mcast) 935 { 936 uint16_t capinfo; 937 938 IEEE80211_LOCK(ic); 939 940 capinfo = ieee80211_get_capinfo(ic); 941 *bo->bo_caps = LE_16(capinfo); 942 943 IEEE80211_UNLOCK(ic); 944 return (0); 945 } 946 947 /* 948 * Assign priority to a frame based on any vlan tag assigned 949 * to the station and/or any Diffserv setting in an IP header. 950 * Finally, if an ACM policy is setup (in station mode) it's 951 * applied. 952 */ 953 /* ARGSUSED */ 954 int 955 ieee80211_classify(struct ieee80211com *ic, mblk_t *m, 956 struct ieee80211_node *ni) 957 { 958 int ac; 959 960 if ((ni->in_flags & IEEE80211_NODE_QOS) == 0) 961 return (WME_AC_BE); 962 963 /* Process VLan */ 964 /* Process IPQoS */ 965 966 ac = WME_AC_BE; 967 968 /* 969 * Apply ACM policy. 970 */ 971 if (ic->ic_opmode == IEEE80211_M_STA) { 972 static const int acmap[4] = { 973 WME_AC_BK, /* WME_AC_BE */ 974 WME_AC_BK, /* WME_AC_BK */ 975 WME_AC_BE, /* WME_AC_VI */ 976 WME_AC_VI, /* WME_AC_VO */ 977 }; 978 while (ac != WME_AC_BK && 979 ic->ic_wme.wme_wmeBssChanParams.cap_wmeParams[ac]. 980 wmep_acm) { 981 ac = acmap[ac]; 982 } 983 } 984 985 return (ac); 986 } 987