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,
 847         NULL
 848 };
 849 
 850 /*
 851  * modlinkage functions
 852  */
 853 int
 854 _init(void)
 855 {
 856         return (mod_install(&i_wifi_modlinkage));
 857 }
 858 
 859 int
 860 _fini(void)
 861 {
 862         return (mod_remove(&i_wifi_modlinkage));
 863 }
 864 
 865 int
 866 _info(struct modinfo *modinfop)
 867 {
 868         return (mod_info(&i_wifi_modlinkage, modinfop));
 869 }