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-2005 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 generic handler 40 */ 41 42 #include <sys/param.h> 43 #include <sys/types.h> 44 #include <sys/cmn_err.h> 45 #include <sys/modctl.h> 46 #include <sys/stropts.h> 47 #include <sys/door.h> 48 #include <sys/mac_provider.h> 49 #include "net80211_impl.h" 50 51 uint32_t ieee80211_debug = 0x0; /* debug msg flags */ 52 53 const char *ieee80211_phymode_name[] = { 54 "auto", /* IEEE80211_MODE_AUTO */ 55 "11a", /* IEEE80211_MODE_11A */ 56 "11b", /* IEEE80211_MODE_11B */ 57 "11g", /* IEEE80211_MODE_11G */ 58 "FH", /* IEEE80211_MODE_FH */ 59 "turboA", /* IEEE80211_MODE_TURBO_A */ 60 "turboG", /* IEEE80211_MODE_TURBO_G */ 61 "sturboA", /* IEEE80211_MODE_STURBO_A */ 62 "11na", /* IEEE80211_MODE_11NA */ 63 "11ng", /* IEEE80211_MODE_11NG */ 64 }; 65 66 #define IEEE80211_DPRINT(_level, _fmt) do { \ 67 _NOTE(CONSTCOND) \ 68 va_list ap; \ 69 va_start(ap, (_fmt)); \ 70 vcmn_err((_level), (_fmt), ap); \ 71 va_end(ap); \ 72 _NOTE(CONSTCOND) \ 73 } while (0) 74 75 /* 76 * Print error messages 77 */ 78 void 79 ieee80211_err(const int8_t *fmt, ...) 80 { 81 IEEE80211_DPRINT(CE_WARN, fmt); 82 } 83 84 /* 85 * Print debug messages 86 */ 87 void 88 ieee80211_dbg(uint32_t flag, const int8_t *fmt, ...) 89 { 90 if (flag & ieee80211_debug) 91 IEEE80211_DPRINT(CE_CONT, fmt); 92 } 93 94 /* 95 * Alloc memory, and save the size 96 */ 97 void * 98 ieee80211_malloc(size_t size) 99 { 100 void *p = kmem_zalloc((size + 4), KM_SLEEP); 101 *(int *)p = size; 102 p = (char *)p + 4; 103 104 return (p); 105 } 106 107 void 108 ieee80211_free(void *p) 109 { 110 void *tp = (char *)p - 4; 111 kmem_free((char *)p - 4, *(int *)tp + 4); 112 } 113 114 void 115 ieee80211_mac_update(ieee80211com_t *ic) 116 { 117 wifi_data_t wd = { 0 }; 118 ieee80211_node_t *in; 119 120 /* 121 * We can send data now; update the fastpath with our 122 * current associated BSSID and other relevant settings. 123 */ 124 in = ic->ic_bss; 125 wd.wd_secalloc = ieee80211_crypto_getciphertype(ic); 126 wd.wd_opmode = ic->ic_opmode; 127 IEEE80211_ADDR_COPY(wd.wd_bssid, in->in_bssid); 128 wd.wd_qospad = 0; 129 if (in->in_flags & (IEEE80211_NODE_QOS|IEEE80211_NODE_HT)) { 130 wd.wd_qospad = 2; 131 if (ic->ic_flags & IEEE80211_F_DATAPAD) 132 wd.wd_qospad = roundup(wd.wd_qospad, sizeof (uint32_t)); 133 } 134 (void) mac_pdata_update(ic->ic_mach, &wd, sizeof (wd)); 135 mac_tx_update(ic->ic_mach); 136 ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_mac_update" 137 "(cipher = %d)\n", wd.wd_secalloc); 138 } 139 140 /* 141 * ieee80211_event_thread 142 * open door of wpa, send event to wpad service 143 */ 144 static void 145 ieee80211_event_thread(void *arg) 146 { 147 ieee80211com_t *ic = arg; 148 door_handle_t event_door = NULL; /* Door for upcalls */ 149 wl_events_t ev; 150 door_arg_t darg; 151 152 mutex_enter(&ic->ic_doorlock); 153 154 ev.event = ic->ic_eventq[ic->ic_evq_head]; 155 ic->ic_evq_head ++; 156 if (ic->ic_evq_head >= MAX_EVENT) 157 ic->ic_evq_head = 0; 158 159 ieee80211_dbg(IEEE80211_MSG_DEBUG, "ieee80211_event(%d)\n", ev.event); 160 /* 161 * Locate the door used for upcalls 162 */ 163 if (door_ki_open(ic->ic_wpadoor, &event_door) != 0) { 164 ieee80211_err("ieee80211_event: door_ki_open(%s) failed\n", 165 ic->ic_wpadoor); 166 goto out; 167 } 168 169 darg.data_ptr = (char *)&ev; 170 darg.data_size = sizeof (wl_events_t); 171 darg.desc_ptr = NULL; 172 darg.desc_num = 0; 173 darg.rbuf = NULL; 174 darg.rsize = 0; 175 176 if (door_ki_upcall_limited(event_door, &darg, NULL, SIZE_MAX, 0) != 0) { 177 ieee80211_err("ieee80211_event: door_ki_upcall() failed\n"); 178 } 179 180 if (event_door) { /* release our hold (if any) */ 181 door_ki_rele(event_door); 182 } 183 184 out: 185 mutex_exit(&ic->ic_doorlock); 186 } 187 188 /* 189 * Notify state transition event message to WPA daemon 190 */ 191 void 192 ieee80211_notify(ieee80211com_t *ic, wpa_event_type event) 193 { 194 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) 195 return; /* Not running on WPA mode */ 196 197 ic->ic_eventq[ic->ic_evq_tail] = event; 198 ic->ic_evq_tail ++; 199 if (ic->ic_evq_tail >= MAX_EVENT) ic->ic_evq_tail = 0; 200 201 /* async */ 202 (void) timeout(ieee80211_event_thread, (void *)ic, 0); 203 } 204 205 /* 206 * Register WPA door 207 */ 208 void 209 ieee80211_register_door(ieee80211com_t *ic, const char *drvname, int inst) 210 { 211 (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", 212 WPA_DOOR, drvname, inst); 213 } 214 215 /* 216 * Default reset method for use with the ioctl support. This 217 * method is invoked after any state change in the 802.11 218 * layer that should be propagated to the hardware but not 219 * require re-initialization of the 802.11 state machine (e.g 220 * rescanning for an ap). We always return ENETRESET which 221 * should cause the driver to re-initialize the device. Drivers 222 * can override this method to implement more optimized support. 223 */ 224 /* ARGSUSED */ 225 static int 226 ieee80211_default_reset(ieee80211com_t *ic) 227 { 228 return (ENETRESET); 229 } 230 231 /* 232 * Convert channel to IEEE channel number. 233 */ 234 uint32_t 235 ieee80211_chan2ieee(ieee80211com_t *ic, struct ieee80211_channel *ch) 236 { 237 if ((ic->ic_sup_channels <= ch) && 238 (ch <= &ic->ic_sup_channels[IEEE80211_CHAN_MAX])) { 239 return (ch - ic->ic_sup_channels); 240 } else if (ch == IEEE80211_CHAN_ANYC) { 241 return (IEEE80211_CHAN_ANY); 242 } else if (ch != NULL) { 243 ieee80211_err("invalid channel freq %u flags %x\n", 244 ch->ich_freq, ch->ich_flags); 245 return (0); 246 } 247 ieee80211_err("invalid channel (NULL)\n"); /* ch == NULL */ 248 return (0); 249 } 250 251 /* 252 * Convert IEEE channel number to MHz frequency. 253 * chan IEEE channel number 254 * flags specify whether the frequency is in the 2GHz ISM 255 * band or the 5GHz band 256 * 257 * 802.11b 2GHz: 14 channels, each 5 MHz wide. Channel 1 is placed 258 * at 2.412 GHz, channel 2 at 2.417 GHz, and so on up to channel 13 259 * at 2.472 GHz. Channel 14 was defined especially for operation in 260 * Japan, and has a center frequency 2.484 GHz. 261 * 802.11g 2GHz: adopts the frequency plan of 802.11b. Japan only 262 * allows 802.11g operation in channels 1-13 263 * 802.11a 5GHz: starting every 5 MHz 264 * 802.11b/g channels 15-24 (2512-2692) are used by some implementation 265 * (Atheros etc.) 266 */ 267 uint32_t 268 ieee80211_ieee2mhz(uint32_t chan, uint32_t flags) 269 { 270 if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ 271 if (chan == 14) 272 return (2484); 273 if (chan < 14) 274 return (2412 + (chan - 1) * 5); 275 else 276 return (2512 + ((chan - 15) * 20)); 277 } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */ 278 return (5000 + (chan * 5)); /* OFDM */ 279 } else { /* either, guess */ 280 if (chan == 14) 281 return (2484); 282 if (chan < 14) /* 0-13 */ 283 return (2412 + (chan - 1) * 5); 284 if (chan < 27) /* 15-26 */ 285 return (2512 + ((chan - 15) * 20)); 286 return (5000 + (chan * 5)); 287 } 288 } 289 290 /* 291 * Do late attach work. It must be called by the driver after 292 * calling ieee80211_attach() and before calling most ieee80211 293 * functions. 294 */ 295 void 296 ieee80211_media_init(ieee80211com_t *ic) 297 { 298 /* 299 * Do late attach work that must wait for any subclass 300 * (i.e. driver) work such as overriding methods. 301 */ 302 ieee80211_node_lateattach(ic); 303 } 304 305 /* 306 * Start Watchdog timer. After count down timer(s), ic_watchdog 307 * will be called 308 */ 309 void 310 ieee80211_start_watchdog(ieee80211com_t *ic, uint32_t timer) 311 { 312 if (ic->ic_watchdog_timer == 0 && ic->ic_watchdog != NULL) { 313 ic->ic_watchdog_timer = timeout(ic->ic_watchdog, ic, 314 drv_usectohz(1000000 * timer)); 315 } 316 } 317 318 /* 319 * Stop watchdog timer. 320 */ 321 void 322 ieee80211_stop_watchdog(ieee80211com_t *ic) 323 { 324 if (ic->ic_watchdog_timer != 0) { 325 if (ic->ic_watchdog != NULL) 326 (void) untimeout(ic->ic_watchdog_timer); 327 ic->ic_watchdog_timer = 0; 328 } 329 } 330 331 /* 332 * Called from a driver's xxx_watchdog routine. It is used to 333 * perform periodic cleanup of state for net80211, as well as 334 * timeout scans. 335 */ 336 void 337 ieee80211_watchdog(void *arg) 338 { 339 ieee80211com_t *ic = arg; 340 struct ieee80211_impl *im = ic->ic_private; 341 ieee80211_node_table_t *nt; 342 int inact_timer = 0; 343 344 if (ic->ic_state == IEEE80211_S_INIT) 345 return; 346 347 IEEE80211_LOCK(ic); 348 if ((im->im_mgt_timer != 0) && (--im->im_mgt_timer == 0)) { 349 IEEE80211_UNLOCK(ic); 350 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 351 IEEE80211_LOCK(ic); 352 } 353 354 nt = &ic->ic_scan; 355 if (nt->nt_inact_timer != 0) { 356 if (--nt->nt_inact_timer == 0) 357 nt->nt_timeout(nt); 358 inact_timer += nt->nt_inact_timer; 359 } 360 nt = &ic->ic_sta; 361 if (nt->nt_inact_timer != 0) { 362 if (--nt->nt_inact_timer == 0) 363 nt->nt_timeout(nt); 364 inact_timer += nt->nt_inact_timer; 365 } 366 367 IEEE80211_UNLOCK(ic); 368 369 if (im->im_mgt_timer != 0 || inact_timer > 0) 370 ieee80211_start_watchdog(ic, 1); 371 } 372 373 /* 374 * Set the current phy mode and recalculate the active channel 375 * set and supported rates based on the available channels for 376 * this mode. Also select a new BSS channel if the current one 377 * is inappropriate for this mode. 378 * This function is called by net80211, and not intended to be 379 * called directly. 380 */ 381 static int 382 ieee80211_setmode(ieee80211com_t *ic, enum ieee80211_phymode mode) 383 { 384 static const uint32_t chanflags[] = { 385 0, /* IEEE80211_MODE_AUTO */ 386 IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ 387 IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ 388 IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ 389 IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ 390 IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO_A */ 391 IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ 392 IEEE80211_CHAN_ST, /* IEEE80211_MODE_STURBO_A */ 393 IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA (check legacy) */ 394 IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG (check legacy) */ 395 }; 396 struct ieee80211_channel *ch; 397 uint32_t modeflags; 398 int i; 399 int achannels = 0; 400 401 /* validate new mode */ 402 if ((ic->ic_modecaps & (1 << mode)) == 0) { 403 ieee80211_err("ieee80211_setmode(): mode %u not supported" 404 " (caps 0x%x)\n", mode, ic->ic_modecaps); 405 return (EINVAL); 406 } 407 408 /* 409 * Verify at least one channel is present in the available 410 * channel list before committing to the new mode. 411 * Calculate the active channel set. 412 */ 413 ASSERT(mode < IEEE80211_N(chanflags)); 414 modeflags = chanflags[mode]; 415 bzero(ic->ic_chan_active, sizeof (ic->ic_chan_active)); 416 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 417 ch = &ic->ic_sup_channels[i]; 418 if (ch->ich_flags == 0) 419 continue; 420 if (mode == IEEE80211_MODE_AUTO) { 421 /* take anything but pure turbo channels */ 422 if ((ch->ich_flags & ~IEEE80211_CHAN_TURBO) != 0) { 423 ieee80211_setbit(ic->ic_chan_active, i); 424 achannels++; 425 } 426 } else { 427 if ((ch->ich_flags & modeflags) == modeflags) { 428 ieee80211_setbit(ic->ic_chan_active, i); 429 achannels++; 430 } 431 } 432 } 433 if (achannels == 0) { 434 ieee80211_err("ieee80211_setmode(): " 435 "no channel found for mode %u\n", mode); 436 return (EINVAL); 437 } 438 439 /* 440 * If no current/default channel is setup or the current 441 * channel is wrong for the mode then pick the first 442 * available channel from the active list. This is likely 443 * not the right one. 444 */ 445 if (ic->ic_ibss_chan == NULL || 446 ieee80211_isclr(ic->ic_chan_active, 447 ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 448 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 449 if (ieee80211_isset(ic->ic_chan_active, i)) { 450 ic->ic_ibss_chan = &ic->ic_sup_channels[i]; 451 break; 452 } 453 } 454 } 455 /* 456 * If the desired channel is set but no longer valid then reset it. 457 */ 458 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 459 ieee80211_isclr(ic->ic_chan_active, 460 ieee80211_chan2ieee(ic, ic->ic_des_chan))) { 461 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 462 } 463 464 /* 465 * Do mode-specific rate setup. 466 */ 467 if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11B) 468 ieee80211_setbasicrates(&ic->ic_sup_rates[mode], mode); 469 470 /* 471 * Setup an initial rate set according to the 472 * current/default channel. This will be changed 473 * when scanning but must exist now so drivers have 474 * consistent state of ic_bsschan. 475 */ 476 if (ic->ic_bss != NULL) 477 ic->ic_bss->in_rates = ic->ic_sup_rates[mode]; 478 ic->ic_curmode = mode; 479 ieee80211_reset_erp(ic); /* reset ERP state */ 480 ieee80211_wme_initparams(ic); /* reset WME stat */ 481 482 return (0); 483 } 484 485 /* 486 * Return the phy mode for with the specified channel so the 487 * caller can select a rate set. This is problematic for channels 488 * where multiple operating modes are possible (e.g. 11g+11b). 489 * In those cases we defer to the current operating mode when set. 490 */ 491 /* ARGSUSED */ 492 enum ieee80211_phymode 493 ieee80211_chan2mode(ieee80211com_t *ic, struct ieee80211_channel *chan) 494 { 495 if (IEEE80211_IS_CHAN_HTA(chan)) 496 return (IEEE80211_MODE_11NA); 497 else if (IEEE80211_IS_CHAN_HTG(chan)) 498 return (IEEE80211_MODE_11NG); 499 else if (IEEE80211_IS_CHAN_108G(chan)) 500 return (IEEE80211_MODE_TURBO_G); 501 else if (IEEE80211_IS_CHAN_ST(chan)) 502 return (IEEE80211_MODE_STURBO_A); 503 else if (IEEE80211_IS_CHAN_T(chan)) 504 return (IEEE80211_MODE_TURBO_A); 505 else if (IEEE80211_IS_CHAN_A(chan)) 506 return (IEEE80211_MODE_11A); 507 else if (IEEE80211_IS_CHAN_ANYG(chan)) 508 return (IEEE80211_MODE_11G); 509 else if (IEEE80211_IS_CHAN_B(chan)) 510 return (IEEE80211_MODE_11B); 511 else if (IEEE80211_IS_CHAN_FHSS(chan)) 512 return (IEEE80211_MODE_FH); 513 514 /* NB: should not get here */ 515 ieee80211_err("cannot map channel to mode; freq %u flags 0x%x\n", 516 chan->ich_freq, chan->ich_flags); 517 518 return (IEEE80211_MODE_11B); 519 } 520 521 const struct ieee80211_rateset * 522 ieee80211_get_suprates(ieee80211com_t *ic, struct ieee80211_channel *c) 523 { 524 if (IEEE80211_IS_CHAN_HTA(c)) 525 return (&ic->ic_sup_rates[IEEE80211_MODE_11A]); 526 if (IEEE80211_IS_CHAN_HTG(c)) { 527 return (&ic->ic_sup_rates[IEEE80211_MODE_11G]); 528 } 529 return (&ic->ic_sup_rates[ieee80211_chan2mode(ic, c)]); 530 } 531 532 /* 533 * Locate a channel given a frequency+flags. We cache 534 * the previous lookup to optimize swithing between two 535 * channels--as happens with dynamic turbo. 536 */ 537 struct ieee80211_channel * 538 ieee80211_find_channel(ieee80211com_t *ic, int freq, int flags) 539 { 540 struct ieee80211_channel *c; 541 int i; 542 543 flags &= IEEE80211_CHAN_ALLTURBO; 544 /* brute force search */ 545 for (i = 0; i < IEEE80211_CHAN_MAX; i++) { 546 c = &ic->ic_sup_channels[i]; 547 if (c->ich_freq == freq && 548 (c->ich_flags & IEEE80211_CHAN_ALLTURBO) == flags) 549 return (c); 550 } 551 return (NULL); 552 } 553 554 /* 555 * Return the size of the 802.11 header for a management or data frame. 556 */ 557 int 558 ieee80211_hdrsize(const void *data) 559 { 560 const struct ieee80211_frame *wh = data; 561 int size = sizeof (struct ieee80211_frame); 562 563 /* NB: we don't handle control frames */ 564 ASSERT((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) != 565 IEEE80211_FC0_TYPE_CTL); 566 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) 567 size += IEEE80211_ADDR_LEN; 568 if (IEEE80211_QOS_HAS_SEQ(wh)) 569 size += sizeof (uint16_t); 570 571 return (size); 572 } 573 574 /* 575 * Return the space occupied by the 802.11 header and any 576 * padding required by the driver. This works for a 577 * management or data frame. 578 */ 579 int 580 ieee80211_hdrspace(ieee80211com_t *ic, const void *data) 581 { 582 int size = ieee80211_hdrsize(data); 583 if (ic->ic_flags & IEEE80211_F_DATAPAD) 584 size = roundup(size, sizeof (uint32_t)); 585 return (size); 586 } 587 588 /* 589 * Like ieee80211_hdrsize, but handles any type of frame. 590 */ 591 int 592 ieee80211_anyhdrsize(const void *data) 593 { 594 const struct ieee80211_frame *wh = data; 595 596 if ((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) { 597 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) { 598 case IEEE80211_FC0_SUBTYPE_CTS: 599 case IEEE80211_FC0_SUBTYPE_ACK: 600 return (sizeof (struct ieee80211_frame_ack)); 601 case IEEE80211_FC0_SUBTYPE_BAR: 602 return (sizeof (struct ieee80211_frame_bar)); 603 } 604 return (sizeof (struct ieee80211_frame_min)); 605 } else 606 return (ieee80211_hdrsize(data)); 607 } 608 609 /* 610 * Like ieee80211_hdrspace, but handles any type of frame. 611 */ 612 int 613 ieee80211_anyhdrspace(ieee80211com_t *ic, const void *data) 614 { 615 int size = ieee80211_anyhdrsize(data); 616 if (ic->ic_flags & IEEE80211_F_DATAPAD) 617 size = roundup(size, sizeof (uint32_t)); 618 return (size); 619 } 620 621 /* 622 * Allocate and setup a management frame of the specified 623 * size. We return the mblk and a pointer to the start 624 * of the contiguous data area that's been reserved based 625 * on the packet length. 626 */ 627 mblk_t * 628 ieee80211_getmgtframe(uint8_t **frm, int pktlen) 629 { 630 mblk_t *mp; 631 int len; 632 633 len = sizeof (struct ieee80211_frame) + pktlen; 634 mp = allocb(len, BPRI_MED); 635 if (mp != NULL) { 636 *frm = mp->b_rptr + sizeof (struct ieee80211_frame); 637 mp->b_wptr = mp->b_rptr + len; 638 } else { 639 ieee80211_err("ieee80211_getmgtframe: " 640 "alloc frame failed, %d\n", len); 641 } 642 return (mp); 643 } 644 645 /* 646 * Send system messages to notify the device has joined a WLAN. 647 * This is an OS specific function. Solaris marks link status 648 * as up. 649 */ 650 void 651 ieee80211_notify_node_join(ieee80211com_t *ic, ieee80211_node_t *in) 652 { 653 if (in == ic->ic_bss) 654 mac_link_update(ic->ic_mach, LINK_STATE_UP); 655 ieee80211_notify(ic, EVENT_ASSOC); /* notify WPA service */ 656 } 657 658 /* 659 * Send system messages to notify the device has left a WLAN. 660 * This is an OS specific function. Solaris marks link status 661 * as down. 662 */ 663 void 664 ieee80211_notify_node_leave(ieee80211com_t *ic, ieee80211_node_t *in) 665 { 666 if (in == ic->ic_bss) 667 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 668 ieee80211_notify(ic, EVENT_DISASSOC); /* notify WPA service */ 669 } 670 671 672 /* 673 * Get 802.11 kstats defined in ieee802.11(5) 674 * 675 * Return 0 on success 676 */ 677 int 678 ieee80211_stat(ieee80211com_t *ic, uint_t stat, uint64_t *val) 679 { 680 ASSERT(val != NULL); 681 IEEE80211_LOCK(ic); 682 switch (stat) { 683 case WIFI_STAT_TX_FRAGS: 684 *val = ic->ic_stats.is_tx_frags; 685 break; 686 case WIFI_STAT_MCAST_TX: 687 *val = ic->ic_stats.is_tx_mcast; 688 break; 689 case WIFI_STAT_TX_FAILED: 690 *val = ic->ic_stats.is_tx_failed; 691 break; 692 case WIFI_STAT_TX_RETRANS: 693 *val = ic->ic_stats.is_tx_retries; 694 break; 695 case WIFI_STAT_RTS_SUCCESS: 696 *val = ic->ic_stats.is_rts_success; 697 break; 698 case WIFI_STAT_RTS_FAILURE: 699 *val = ic->ic_stats.is_rts_failure; 700 break; 701 case WIFI_STAT_ACK_FAILURE: 702 *val = ic->ic_stats.is_ack_failure; 703 break; 704 case WIFI_STAT_RX_FRAGS: 705 *val = ic->ic_stats.is_rx_frags; 706 break; 707 case WIFI_STAT_MCAST_RX: 708 *val = ic->ic_stats.is_rx_mcast; 709 break; 710 case WIFI_STAT_RX_DUPS: 711 *val = ic->ic_stats.is_rx_dups; 712 break; 713 case WIFI_STAT_FCS_ERRORS: 714 *val = ic->ic_stats.is_fcs_errors; 715 break; 716 case WIFI_STAT_WEP_ERRORS: 717 *val = ic->ic_stats.is_wep_errors; 718 break; 719 } 720 IEEE80211_UNLOCK(ic); 721 return (0); 722 } 723 724 /* 725 * Attach network interface to the 802.11 support module. This 726 * function must be called before using any of the ieee80211 727 * functionss. The parameter "ic" MUST be initialized to tell 728 * net80211 about interface's capabilities. 729 */ 730 void 731 ieee80211_attach(ieee80211com_t *ic) 732 { 733 struct ieee80211_impl *im; 734 struct ieee80211_channel *ch; 735 int i; 736 737 /* Check mandatory callback functions not NULL */ 738 ASSERT(ic->ic_xmit != NULL); 739 740 mutex_init(&ic->ic_genlock, NULL, MUTEX_DRIVER, NULL); 741 mutex_init(&ic->ic_doorlock, NULL, MUTEX_DRIVER, NULL); 742 743 im = kmem_alloc(sizeof (ieee80211_impl_t), KM_SLEEP); 744 ic->ic_private = im; 745 cv_init(&im->im_scan_cv, NULL, CV_DRIVER, NULL); 746 747 /* 748 * Fill in 802.11 available channel set, mark 749 * all available channels as active, and pick 750 * a default channel if not already specified. 751 */ 752 bzero(im->im_chan_avail, sizeof (im->im_chan_avail)); 753 ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; 754 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { 755 ch = &ic->ic_sup_channels[i]; 756 if (ch->ich_flags) { 757 /* Verify driver passed us valid data */ 758 if (i != ieee80211_chan2ieee(ic, ch)) { 759 ieee80211_err("bad channel ignored: " 760 "freq %u flags%x number %u\n", 761 ch->ich_freq, ch->ich_flags, i); 762 ch->ich_flags = 0; 763 continue; 764 } 765 ieee80211_setbit(im->im_chan_avail, i); 766 /* Identify mode capabilities */ 767 if (IEEE80211_IS_CHAN_A(ch)) 768 ic->ic_modecaps |= 1 << IEEE80211_MODE_11A; 769 if (IEEE80211_IS_CHAN_B(ch)) 770 ic->ic_modecaps |= 1 << IEEE80211_MODE_11B; 771 if (IEEE80211_IS_CHAN_PUREG(ch)) 772 ic->ic_modecaps |= 1 << IEEE80211_MODE_11G; 773 if (IEEE80211_IS_CHAN_FHSS(ch)) 774 ic->ic_modecaps |= 1 << IEEE80211_MODE_FH; 775 if (IEEE80211_IS_CHAN_T(ch)) 776 ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A; 777 if (IEEE80211_IS_CHAN_108G(ch)) 778 ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G; 779 if (IEEE80211_IS_CHAN_ST(ch)) 780 ic->ic_modecaps |= 1 << IEEE80211_MODE_STURBO_A; 781 if (IEEE80211_IS_CHAN_HTA(ch)) 782 ic->ic_modecaps |= 1 << IEEE80211_MODE_11NA; 783 if (IEEE80211_IS_CHAN_HTG(ch)) 784 ic->ic_modecaps |= 1 << IEEE80211_MODE_11NG; 785 if (ic->ic_curchan == NULL) { 786 /* arbitrarily pick the first channel */ 787 ic->ic_curchan = &ic->ic_sup_channels[i]; 788 } 789 } 790 } 791 /* validate ic->ic_curmode */ 792 if ((ic->ic_modecaps & (1 << ic->ic_curmode)) == 0) 793 ic->ic_curmode = IEEE80211_MODE_AUTO; 794 ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ 795 (void) ieee80211_setmode(ic, ic->ic_curmode); 796 797 if (ic->ic_caps & IEEE80211_C_WME) /* enable if capable */ 798 ic->ic_flags |= IEEE80211_F_WME; 799 if (ic->ic_caps & IEEE80211_C_BURST) 800 ic->ic_flags |= IEEE80211_F_BURST; 801 ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT; 802 ic->ic_lintval = ic->ic_bintval; 803 ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; 804 ic->ic_bmissthreshold = IEEE80211_HWBMISS_DEFAULT; 805 806 ic->ic_reset = ieee80211_default_reset; 807 808 ieee80211_node_attach(ic); 809 ieee80211_proto_attach(ic); 810 ieee80211_crypto_attach(ic); 811 ieee80211_ht_attach(ic); 812 813 ic->ic_watchdog_timer = 0; 814 } 815 816 /* 817 * Free any ieee80211 structures associated with the driver. 818 */ 819 void 820 ieee80211_detach(ieee80211com_t *ic) 821 { 822 struct ieee80211_impl *im = ic->ic_private; 823 824 ieee80211_stop_watchdog(ic); 825 cv_destroy(&im->im_scan_cv); 826 kmem_free(im, sizeof (ieee80211_impl_t)); 827 828 if (ic->ic_opt_ie != NULL) 829 ieee80211_free(ic->ic_opt_ie); 830 831 ieee80211_ht_detach(ic); 832 ieee80211_node_detach(ic); 833 ieee80211_crypto_detach(ic); 834 835 mutex_destroy(&ic->ic_genlock); 836 mutex_destroy(&ic->ic_doorlock); 837 } 838 839 static struct modlmisc i_wifi_modlmisc = { 840 &mod_miscops, 841 "IEEE80211 Kernel Module v2.0" 842 }; 843 844 static struct modlinkage i_wifi_modlinkage = { 845 MODREV_1, 846 { &i_wifi_modlmisc, NULL } 847 }; 848 849 /* 850 * modlinkage functions 851 */ 852 int 853 _init(void) 854 { 855 return (mod_install(&i_wifi_modlinkage)); 856 } 857 858 int 859 _fini(void) 860 { 861 return (mod_remove(&i_wifi_modlinkage)); 862 } 863 864 int 865 _info(struct modinfo *modinfop) 866 { 867 return (mod_info(&i_wifi_modlinkage, modinfop)); 868 }