1 /* $NetBSD: ieee80211_output.c,v 1.27 2005/01/21 22:57:30 dyoung Exp $ */ 2 /*- 3 * Copyright (c) 2001 Atsushi Onoe 4 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * Alternatively, this software may be distributed under the terms of the 19 * GNU General Public License ("GPL") version 2 as published by the Free 20 * Software Foundation. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 #ifdef __FreeBSD__ 36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.10 2004/04/02 23:25:39 sam Exp $"); 37 #else 38 __KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.27 2005/01/21 22:57:30 dyoung Exp $"); 39 #endif 40 41 #include "opt_inet.h" 42 43 #ifdef __NetBSD__ 44 #include "bpfilter.h" 45 #endif /* __NetBSD__ */ 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/mbuf.h> 50 #include <sys/malloc.h> 51 #include <sys/kernel.h> 52 #include <sys/socket.h> 53 #include <sys/sockio.h> 54 #include <sys/endian.h> 55 #include <sys/errno.h> 56 #ifdef __FreeBSD__ 57 #include <sys/bus.h> 58 #endif 59 #include <sys/proc.h> 60 #include <sys/sysctl.h> 61 62 #ifdef __FreeBSD__ 63 #include <machine/atomic.h> 64 #endif 65 66 #include <net/if.h> 67 #include <net/if_dl.h> 68 #include <net/if_media.h> 69 #include <net/if_arp.h> 70 #ifdef __FreeBSD__ 71 #include <net/ethernet.h> 72 #else 73 #include <net/if_ether.h> 74 #endif 75 #include <net/if_llc.h> 76 77 #include <net80211/ieee80211_var.h> 78 #include <net80211/ieee80211_compat.h> 79 80 #if NBPFILTER > 0 81 #include <net/bpf.h> 82 #endif 83 84 #ifdef INET 85 #include <netinet/in.h> 86 #ifdef __FreeBSD__ 87 #include <netinet/if_ether.h> 88 #else 89 #include <net/if_ether.h> 90 #endif 91 #endif 92 93 #ifdef IEEE80211_DEBUG 94 /* 95 * Decide if an outbound management frame should be 96 * printed when debugging is enabled. This filters some 97 * of the less interesting frames that come frequently 98 * (e.g. beacons). 99 */ 100 static __inline int 101 doprint(struct ieee80211com *ic, int subtype) 102 { 103 switch (subtype) { 104 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 105 return (ic->ic_opmode == IEEE80211_M_IBSS); 106 } 107 return 1; 108 } 109 #endif 110 111 /* 112 * Send a management frame to the specified node. The node pointer 113 * must have a reference as the pointer will be passed to the driver 114 * and potentially held for a long time. If the frame is successfully 115 * dispatched to the driver, then it is responsible for freeing the 116 * reference (and potentially free'ing up any associated storage). 117 */ 118 static int 119 ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni, 120 struct mbuf *m, int type) 121 { 122 struct ieee80211com *ic = (void *)ifp; 123 struct ieee80211_frame *wh; 124 125 IASSERT(ni != NULL, ("null node")); 126 ni->ni_inact = 0; 127 128 /* 129 * Yech, hack alert! We want to pass the node down to the 130 * driver's start routine. If we don't do so then the start 131 * routine must immediately look it up again and that can 132 * cause a lock order reversal if, for example, this frame 133 * is being sent because the station is being timedout and 134 * the frame being sent is a DEAUTH message. We could stick 135 * this in an m_tag and tack that on to the mbuf. However 136 * that's rather expensive to do for every frame so instead 137 * we stuff it in the rcvif field since outbound frames do 138 * not (presently) use this. 139 */ 140 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); 141 if (m == NULL) 142 return ENOMEM; 143 #ifdef __FreeBSD__ 144 KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null")); 145 #endif 146 m->m_pkthdr.rcvif = (void *)ni; 147 148 wh = mtod(m, struct ieee80211_frame *); 149 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type; 150 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 151 *(u_int16_t *)&wh->i_dur[0] = 0; 152 *(u_int16_t *)&wh->i_seq[0] = 153 htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); 154 ni->ni_txseq++; 155 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr); 156 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr); 157 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); 158 159 if ((m->m_flags & M_LINK0) != 0 && ni->ni_challenge != NULL) { 160 m->m_flags &= ~M_LINK0; 161 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH, 162 ("%s: encrypting frame for %s\n", 163 __func__, ether_sprintf(wh->i_addr1))); 164 wh->i_fc[1] |= IEEE80211_FC1_WEP; 165 } 166 #ifdef IEEE80211_DEBUG 167 /* avoid printing too many frames */ 168 if ((ieee80211_msg_debug(ic) && doprint(ic, type)) || 169 ieee80211_msg_dumppkts(ic)) { 170 if_printf(ifp, "sending %s to %s on channel %u\n", 171 ieee80211_mgt_subtype_name[ 172 (type & IEEE80211_FC0_SUBTYPE_MASK) 173 >> IEEE80211_FC0_SUBTYPE_SHIFT], 174 ether_sprintf(ni->ni_macaddr), 175 ieee80211_chan2ieee(ic, ni->ni_chan)); 176 } 177 #endif 178 IF_ENQUEUE(&ic->ic_mgtq, m); 179 ifp->if_timer = 1; 180 (*ifp->if_start)(ifp); 181 return 0; 182 } 183 184 /* 185 * Encapsulate an outbound data frame. The mbuf chain is updated and 186 * a reference to the destination node is returned. If an error is 187 * encountered NULL is returned and the node reference will also be NULL. 188 * 189 * NB: The caller is responsible for free'ing a returned node reference. 190 * The convention is ic_bss is not reference counted; the caller must 191 * maintain that. 192 */ 193 struct mbuf * 194 ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni) 195 { 196 struct ieee80211com *ic = (void *)ifp; 197 struct ether_header eh; 198 struct ieee80211_frame *wh; 199 struct ieee80211_node *ni = NULL; 200 struct llc *llc; 201 202 if (m->m_len < sizeof(struct ether_header)) { 203 m = m_pullup(m, sizeof(struct ether_header)); 204 if (m == NULL) { 205 ic->ic_stats.is_tx_nombuf++; 206 goto bad; 207 } 208 } 209 memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header)); 210 211 ni = ieee80211_find_txnode(ic, eh.ether_dhost); 212 if (ni == NULL) { 213 IEEE80211_DPRINTF(ic, IEEE80211_MSG_OUTPUT, 214 ("%s: no node for dst %s, discard frame\n", 215 __func__, ether_sprintf(eh.ether_dhost))); 216 ic->ic_stats.is_tx_nonode++; 217 goto bad; 218 } 219 ni->ni_inact = 0; 220 221 m_adj(m, sizeof(struct ether_header) - sizeof(struct llc)); 222 llc = mtod(m, struct llc *); 223 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 224 llc->llc_control = LLC_UI; 225 llc->llc_snap.org_code[0] = 0; 226 llc->llc_snap.org_code[1] = 0; 227 llc->llc_snap.org_code[2] = 0; 228 llc->llc_snap.ether_type = eh.ether_type; 229 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); 230 if (m == NULL) { 231 ic->ic_stats.is_tx_nombuf++; 232 goto bad; 233 } 234 wh = mtod(m, struct ieee80211_frame *); 235 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; 236 *(u_int16_t *)&wh->i_dur[0] = 0; 237 *(u_int16_t *)&wh->i_seq[0] = 238 htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); 239 ni->ni_txseq++; 240 switch (ic->ic_opmode) { 241 case IEEE80211_M_STA: 242 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; 243 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid); 244 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost); 245 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost); 246 break; 247 case IEEE80211_M_IBSS: 248 case IEEE80211_M_AHDEMO: 249 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 250 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost); 251 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost); 252 IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid); 253 break; 254 case IEEE80211_M_HOSTAP: 255 wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS; 256 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost); 257 IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid); 258 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost); 259 break; 260 case IEEE80211_M_MONITOR: 261 goto bad; 262 } 263 if (ic->ic_flags & IEEE80211_F_PRIVACY) 264 wh->i_fc[1] |= IEEE80211_FC1_WEP; 265 *pni = ni; 266 return m; 267 bad: 268 if (m != NULL) 269 m_freem(m); 270 if (ni != NULL) 271 ieee80211_release_node(ic, ni); 272 *pni = NULL; 273 return NULL; 274 } 275 276 /* 277 * Arguments in: 278 * 279 * paylen: payload length (no FCS, no WEP header) 280 * 281 * hdrlen: header length 282 * 283 * rate: MSDU speed, units 500kb/s 284 * 285 * flags: IEEE80211_F_SHPREAMBLE (use short preamble), 286 * IEEE80211_F_SHSLOT (use short slot length) 287 * 288 * Arguments out: 289 * 290 * d: 802.11 Duration field for RTS, 291 * 802.11 Duration field for data frame, 292 * PLCP Length for data frame, 293 * residual octets at end of data slot 294 */ 295 static int 296 ieee80211_compute_duration1(int len, int use_ack, uint32_t flags, int rate, 297 struct ieee80211_duration *d) 298 { 299 int pre, ctsrate; 300 int ack, bitlen, data_dur, remainder; 301 302 /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK 303 * DATA reserves medium for SIFS | ACK 304 * 305 * XXXMYC: no ACK on multicast/broadcast or control packets 306 */ 307 308 bitlen = len * 8; 309 310 pre = IEEE80211_DUR_DS_SIFS; 311 if ((flags & IEEE80211_F_SHPREAMBLE) != 0) 312 pre += IEEE80211_DUR_DS_SHORT_PREAMBLE + IEEE80211_DUR_DS_FAST_PLCPHDR; 313 else 314 pre += IEEE80211_DUR_DS_LONG_PREAMBLE + IEEE80211_DUR_DS_SLOW_PLCPHDR; 315 316 d->d_residue = 0; 317 data_dur = (bitlen * 2) / rate; 318 remainder = (bitlen * 2) % rate; 319 if (remainder != 0) { 320 d->d_residue = (rate - remainder) / 16; 321 data_dur++; 322 } 323 324 switch (rate) { 325 case 2: /* 1 Mb/s */ 326 case 4: /* 2 Mb/s */ 327 /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */ 328 ctsrate = 2; 329 break; 330 case 11: /* 5.5 Mb/s */ 331 case 22: /* 11 Mb/s */ 332 case 44: /* 22 Mb/s */ 333 /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */ 334 ctsrate = 4; 335 break; 336 default: 337 /* TBD */ 338 return -1; 339 } 340 341 d->d_plcp_len = data_dur; 342 343 ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0; 344 345 d->d_rts_dur = 346 pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate + 347 pre + data_dur + 348 ack; 349 350 d->d_data_dur = ack; 351 352 return 0; 353 } 354 355 /* 356 * Arguments in: 357 * 358 * wh: 802.11 header 359 * 360 * paylen: payload length (no FCS, no WEP header) 361 * 362 * rate: MSDU speed, units 500kb/s 363 * 364 * fraglen: fragment length, set to maximum (or higher) for no 365 * fragmentation 366 * 367 * flags: IEEE80211_F_PRIVACY (hardware adds WEP), 368 * IEEE80211_F_SHPREAMBLE (use short preamble), 369 * IEEE80211_F_SHSLOT (use short slot length) 370 * 371 * Arguments out: 372 * 373 * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields 374 * of first/only fragment 375 * 376 * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields 377 * of first/only fragment 378 */ 379 int 380 ieee80211_compute_duration(struct ieee80211_frame *wh, int len, 381 uint32_t flags, int fraglen, int rate, struct ieee80211_duration *d0, 382 struct ieee80211_duration *dn, int *npktp, int debug) 383 { 384 int ack, rc; 385 int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen; 386 387 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) 388 hdrlen = sizeof(struct ieee80211_frame_addr4); 389 else 390 hdrlen = sizeof(struct ieee80211_frame); 391 392 paylen = len - hdrlen; 393 394 if ((flags & IEEE80211_F_PRIVACY) != 0) 395 overlen = IEEE80211_WEP_TOTLEN + IEEE80211_CRC_LEN; 396 else 397 overlen = IEEE80211_CRC_LEN; 398 399 npkt = paylen / fraglen; 400 lastlen0 = paylen % fraglen; 401 402 if (npkt == 0) /* no fragments */ 403 lastlen = paylen + overlen; 404 else if (lastlen0 != 0) { /* a short "tail" fragment */ 405 lastlen = lastlen0 + overlen; 406 npkt++; 407 } else /* full-length "tail" fragment */ 408 lastlen = fraglen + overlen; 409 410 if (npktp != NULL) 411 *npktp = npkt; 412 413 if (npkt > 1) 414 firstlen = fraglen + overlen; 415 else 416 firstlen = paylen + overlen; 417 418 if (debug) { 419 printf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d " 420 "fraglen %d overlen %d len %d rate %d flags %08x\n", 421 __func__, npkt, firstlen, lastlen0, lastlen, fraglen, 422 overlen, len, rate, flags); 423 } 424 425 ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) && 426 (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL; 427 428 rc = ieee80211_compute_duration1(firstlen + hdrlen, 429 ack, flags, rate, d0); 430 if (rc == -1) 431 return rc; 432 433 if (npkt <= 1) { 434 *dn = *d0; 435 return 0; 436 } 437 return ieee80211_compute_duration1(lastlen + hdrlen, ack, flags, rate, 438 dn); 439 } 440 441 /* 442 * Add a supported rates element id to a frame. 443 */ 444 u_int8_t * 445 ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs) 446 { 447 int nrates; 448 449 *frm++ = IEEE80211_ELEMID_RATES; 450 nrates = rs->rs_nrates; 451 if (nrates > IEEE80211_RATE_SIZE) 452 nrates = IEEE80211_RATE_SIZE; 453 *frm++ = nrates; 454 memcpy(frm, rs->rs_rates, nrates); 455 return frm + nrates; 456 } 457 458 /* 459 * Add an extended supported rates element id to a frame. 460 */ 461 u_int8_t * 462 ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs) 463 { 464 /* 465 * Add an extended supported rates element if operating in 11g mode. 466 */ 467 if (rs->rs_nrates > IEEE80211_RATE_SIZE) { 468 int nrates = rs->rs_nrates - IEEE80211_RATE_SIZE; 469 *frm++ = IEEE80211_ELEMID_XRATES; 470 *frm++ = nrates; 471 memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates); 472 frm += nrates; 473 } 474 return frm; 475 } 476 477 /* 478 * Add an ssid elemet to a frame. 479 */ 480 static u_int8_t * 481 ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len) 482 { 483 *frm++ = IEEE80211_ELEMID_SSID; 484 *frm++ = len; 485 memcpy(frm, ssid, len); 486 return frm + len; 487 } 488 489 static struct mbuf * 490 ieee80211_getmbuf(int flags, int type, u_int pktlen) 491 { 492 struct mbuf *m; 493 494 IASSERT(pktlen <= MCLBYTES, ("802.11 packet too large: %u", pktlen)); 495 MGETHDR(m, flags, type); 496 if (m == NULL || pktlen <= MHLEN) 497 return m; 498 MCLGET(m, flags); 499 if ((m->m_flags & M_EXT) != 0) 500 return m; 501 m_free(m); 502 return NULL; 503 } 504 505 /* 506 * Send a management frame. The node is for the destination (or ic_bss 507 * when in station mode). Nodes other than ic_bss have their reference 508 * count bumped to reflect our use for an indeterminant time. 509 */ 510 int 511 ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni, 512 int type, int arg) 513 { 514 #define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0) 515 struct ifnet *ifp = &ic->ic_if; 516 struct mbuf *m; 517 u_int8_t *frm; 518 enum ieee80211_phymode mode; 519 u_int16_t capinfo; 520 int has_challenge, is_shared_key, ret, timer; 521 522 IASSERT(ni != NULL, ("null node")); 523 524 /* 525 * Hold a reference on the node so it doesn't go away until after 526 * the xmit is complete all the way in the driver. On error we 527 * will remove our reference. 528 */ 529 ieee80211_ref_node(ni); 530 timer = 0; 531 switch (type) { 532 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 533 /* 534 * prreq frame format 535 * [tlv] ssid 536 * [tlv] supported rates 537 * [tlv] extended supported rates 538 */ 539 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA, 540 2 + ic->ic_des_esslen 541 + 2 + IEEE80211_RATE_SIZE 542 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); 543 if (m == NULL) 544 senderr(ENOMEM, is_tx_nombuf); 545 m->m_data += sizeof(struct ieee80211_frame); 546 frm = mtod(m, u_int8_t *); 547 frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen); 548 mode = ieee80211_chan2mode(ic, ni->ni_chan); 549 frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]); 550 frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]); 551 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); 552 553 timer = IEEE80211_TRANS_WAIT; 554 break; 555 556 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 557 /* 558 * probe response frame format 559 * [8] time stamp 560 * [2] beacon interval 561 * [2] cabability information 562 * [tlv] ssid 563 * [tlv] supported rates 564 * [tlv] parameter set (FH/DS) 565 * [tlv] parameter set (IBSS) 566 * [tlv] extended supported rates 567 */ 568 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA, 569 8 + 2 + 2 + 2 570 + 2 + ni->ni_esslen 571 + 2 + IEEE80211_RATE_SIZE 572 + (ic->ic_phytype == IEEE80211_T_FH ? 7 : 3) 573 + 6 574 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); 575 if (m == NULL) 576 senderr(ENOMEM, is_tx_nombuf); 577 m->m_data += sizeof(struct ieee80211_frame); 578 frm = mtod(m, u_int8_t *); 579 580 memset(frm, 0, 8); /* timestamp should be filled later */ 581 frm += 8; 582 *(u_int16_t *)frm = htole16(ic->ic_bss->ni_intval); 583 frm += 2; 584 if (ic->ic_opmode == IEEE80211_M_IBSS) 585 capinfo = IEEE80211_CAPINFO_IBSS; 586 else 587 capinfo = IEEE80211_CAPINFO_ESS; 588 if (ic->ic_flags & IEEE80211_F_PRIVACY) 589 capinfo |= IEEE80211_CAPINFO_PRIVACY; 590 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 591 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 592 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; 593 *(u_int16_t *)frm = htole16(capinfo); 594 frm += 2; 595 596 frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid, 597 ic->ic_bss->ni_esslen); 598 frm = ieee80211_add_rates(frm, &ic->ic_bss->ni_rates); 599 600 if (ic->ic_phytype == IEEE80211_T_FH) { 601 *frm++ = IEEE80211_ELEMID_FHPARMS; 602 *frm++ = 5; 603 *frm++ = ni->ni_fhdwell & 0x00ff; 604 *frm++ = (ni->ni_fhdwell >> 8) & 0x00ff; 605 *frm++ = IEEE80211_FH_CHANSET( 606 ieee80211_chan2ieee(ic, ni->ni_chan)); 607 *frm++ = IEEE80211_FH_CHANPAT( 608 ieee80211_chan2ieee(ic, ni->ni_chan)); 609 *frm++ = ni->ni_fhindex; 610 } else { 611 *frm++ = IEEE80211_ELEMID_DSPARMS; 612 *frm++ = 1; 613 *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan); 614 } 615 616 if (ic->ic_opmode == IEEE80211_M_IBSS) { 617 *frm++ = IEEE80211_ELEMID_IBSSPARMS; 618 *frm++ = 2; 619 *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ 620 } else { /* IEEE80211_M_HOSTAP */ 621 /* TODO: TIM */ 622 *frm++ = IEEE80211_ELEMID_TIM; 623 *frm++ = 4; /* length */ 624 *frm++ = 0; /* DTIM count */ 625 *frm++ = 1; /* DTIM period */ 626 *frm++ = 0; /* bitmap control */ 627 *frm++ = 0; /* Partial Virtual Bitmap (variable length) */ 628 } 629 frm = ieee80211_add_xrates(frm, &ic->ic_bss->ni_rates); 630 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); 631 break; 632 633 case IEEE80211_FC0_SUBTYPE_AUTH: 634 MGETHDR(m, M_DONTWAIT, MT_DATA); 635 if (m == NULL) 636 senderr(ENOMEM, is_tx_nombuf); 637 638 has_challenge = ((arg == IEEE80211_AUTH_SHARED_CHALLENGE || 639 arg == IEEE80211_AUTH_SHARED_RESPONSE) && 640 ni->ni_challenge != NULL); 641 642 is_shared_key = has_challenge || (ni->ni_challenge != NULL && 643 arg == IEEE80211_AUTH_SHARED_PASS); 644 645 if (has_challenge) { 646 MH_ALIGN(m, 2 * 3 + 2 + IEEE80211_CHALLENGE_LEN); 647 m->m_pkthdr.len = m->m_len = 648 2 * 3 + 2 + IEEE80211_CHALLENGE_LEN; 649 } else { 650 MH_ALIGN(m, 2 * 3); 651 m->m_pkthdr.len = m->m_len = 2 * 3; 652 } 653 frm = mtod(m, u_int8_t *); 654 ((u_int16_t *)frm)[0] = 655 (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED) 656 : htole16(IEEE80211_AUTH_ALG_OPEN); 657 ((u_int16_t *)frm)[1] = htole16(arg); /* sequence number */ 658 ((u_int16_t *)frm)[2] = 0; /* status */ 659 660 if (has_challenge) { 661 ((u_int16_t *)frm)[3] = 662 htole16((IEEE80211_CHALLENGE_LEN << 8) | 663 IEEE80211_ELEMID_CHALLENGE); 664 memcpy(&((u_int16_t *)frm)[4], ni->ni_challenge, 665 IEEE80211_CHALLENGE_LEN); 666 if (arg == IEEE80211_AUTH_SHARED_RESPONSE) { 667 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH, 668 ("%s: request encrypt frame\n", __func__)); 669 m->m_flags |= M_LINK0; /* WEP-encrypt, please */ 670 } 671 } 672 if (ic->ic_opmode == IEEE80211_M_STA) 673 timer = IEEE80211_TRANS_WAIT; 674 break; 675 676 case IEEE80211_FC0_SUBTYPE_DEAUTH: 677 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH, 678 ("send station %s deauthenticate (reason %d)\n", 679 ether_sprintf(ni->ni_macaddr), arg)); 680 MGETHDR(m, M_DONTWAIT, MT_DATA); 681 if (m == NULL) 682 senderr(ENOMEM, is_tx_nombuf); 683 MH_ALIGN(m, 2); 684 m->m_pkthdr.len = m->m_len = 2; 685 *mtod(m, u_int16_t *) = htole16(arg); /* reason */ 686 break; 687 688 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 689 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: 690 /* 691 * asreq frame format 692 * [2] capability information 693 * [2] listen interval 694 * [6*] current AP address (reassoc only) 695 * [tlv] ssid 696 * [tlv] supported rates 697 * [tlv] extended supported rates 698 */ 699 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA, 700 sizeof(capinfo) 701 + sizeof(u_int16_t) 702 + IEEE80211_ADDR_LEN 703 + 2 + ni->ni_esslen 704 + 2 + IEEE80211_RATE_SIZE 705 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); 706 if (m == NULL) 707 senderr(ENOMEM, is_tx_nombuf); 708 m->m_data += sizeof(struct ieee80211_frame); 709 frm = mtod(m, u_int8_t *); 710 711 capinfo = 0; 712 if (ic->ic_opmode == IEEE80211_M_IBSS) 713 capinfo |= IEEE80211_CAPINFO_IBSS; 714 else /* IEEE80211_M_STA */ 715 capinfo |= IEEE80211_CAPINFO_ESS; 716 if (ic->ic_flags & IEEE80211_F_PRIVACY) 717 capinfo |= IEEE80211_CAPINFO_PRIVACY; 718 /* 719 * NB: Some 11a AP's reject the request when 720 * short premable is set. 721 */ 722 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 723 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 724 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; 725 if (ic->ic_flags & IEEE80211_F_SHSLOT) 726 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; 727 *(u_int16_t *)frm = htole16(capinfo); 728 frm += 2; 729 730 *(u_int16_t *)frm = htole16(ic->ic_lintval); 731 frm += 2; 732 733 if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { 734 IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid); 735 frm += IEEE80211_ADDR_LEN; 736 } 737 738 frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen); 739 frm = ieee80211_add_rates(frm, &ni->ni_rates); 740 frm = ieee80211_add_xrates(frm, &ni->ni_rates); 741 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); 742 743 timer = IEEE80211_TRANS_WAIT; 744 break; 745 746 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 747 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: 748 /* 749 * asreq frame format 750 * [2] capability information 751 * [2] status 752 * [2] association ID 753 * [tlv] supported rates 754 * [tlv] extended supported rates 755 */ 756 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA, 757 sizeof(capinfo) 758 + sizeof(u_int16_t) 759 + sizeof(u_int16_t) 760 + 2 + IEEE80211_RATE_SIZE 761 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); 762 if (m == NULL) 763 senderr(ENOMEM, is_tx_nombuf); 764 m->m_data += sizeof(struct ieee80211_frame); 765 frm = mtod(m, u_int8_t *); 766 767 capinfo = IEEE80211_CAPINFO_ESS; 768 if (ic->ic_flags & IEEE80211_F_PRIVACY) 769 capinfo |= IEEE80211_CAPINFO_PRIVACY; 770 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 771 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 772 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; 773 *(u_int16_t *)frm = htole16(capinfo); 774 frm += 2; 775 776 *(u_int16_t *)frm = htole16(arg); /* status */ 777 frm += 2; 778 779 if (arg == IEEE80211_STATUS_SUCCESS) 780 *(u_int16_t *)frm = htole16(ni->ni_associd); 781 frm += 2; 782 783 frm = ieee80211_add_rates(frm, &ni->ni_rates); 784 frm = ieee80211_add_xrates(frm, &ni->ni_rates); 785 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); 786 break; 787 788 case IEEE80211_FC0_SUBTYPE_DISASSOC: 789 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC, 790 ("send station %s disassociate (reason %d)\n", 791 ether_sprintf(ni->ni_macaddr), arg)); 792 MGETHDR(m, M_DONTWAIT, MT_DATA); 793 if (m == NULL) 794 senderr(ENOMEM, is_tx_nombuf); 795 MH_ALIGN(m, 2); 796 m->m_pkthdr.len = m->m_len = 2; 797 *mtod(m, u_int16_t *) = htole16(arg); /* reason */ 798 break; 799 800 default: 801 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, 802 ("%s: invalid mgmt frame type %u\n", __func__, type)); 803 senderr(EINVAL, is_tx_unknownmgt); 804 /* NOTREACHED */ 805 } 806 807 ret = ieee80211_mgmt_output(ifp, ni, m, type); 808 if (ret == 0) { 809 if (timer) 810 ic->ic_mgt_timer = timer; 811 } else { 812 bad: 813 ieee80211_release_node(ic, ni); 814 } 815 return ret; 816 #undef senderr 817 } 818 819 void 820 ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni, 821 struct mbuf *m) 822 { 823 /* Store the new packet on our queue, changing the TIM if necessary */ 824 825 if (IF_IS_EMPTY(&ni->ni_savedq)) { 826 ic->ic_set_tim(ic, ni->ni_associd, 1); 827 } 828 if (ni->ni_savedq.ifq_len >= IEEE80211_PS_MAX_QUEUE) { 829 IF_DROP(&ni->ni_savedq); 830 m_freem(m); 831 if (ic->ic_if.if_flags & IFF_DEBUG) 832 printf("%s: station %s power save queue overflow" 833 " of size %d drops %d\n", 834 ic->ic_if.if_xname, 835 ether_sprintf(ni->ni_macaddr), 836 IEEE80211_PS_MAX_QUEUE, 837 ni->ni_savedq.ifq_drops); 838 } else { 839 /* Similar to ieee80211_mgmt_output, store the node in 840 * the rcvif field. 841 */ 842 IF_ENQUEUE(&ni->ni_savedq, m); 843 m->m_pkthdr.rcvif = (void *)ni; 844 } 845 } 846 847