The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_proto.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2001 Atsushi Onoe
    3  * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 /*
   31  * IEEE 802.11 protocol support.
   32  */
   33 
   34 #include "opt_inet.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/systm.h>
   39 
   40 #include <sys/socket.h>
   41 
   42 #include <net/if.h>
   43 #include <net/if_media.h>
   44 #include <net/ethernet.h>               /* XXX for ether_sprintf */
   45 
   46 #include <net80211/ieee80211_var.h>
   47 
   48 /* XXX tunables */
   49 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS       3       /* pkts / 100ms */
   50 #define HIGH_PRI_SWITCH_THRESH                  10      /* pkts / 100ms */
   51 
   52 #define IEEE80211_RATE2MBS(r)   (((r) & IEEE80211_RATE_VAL) / 2)
   53 
   54 const char *ieee80211_mgt_subtype_name[] = {
   55         "assoc_req",    "assoc_resp",   "reassoc_req",  "reassoc_resp",
   56         "probe_req",    "probe_resp",   "reserved#6",   "reserved#7",
   57         "beacon",       "atim",         "disassoc",     "auth",
   58         "deauth",       "action",       "reserved#14",  "reserved#15"
   59 };
   60 const char *ieee80211_ctl_subtype_name[] = {
   61         "reserved#0",   "reserved#1",   "reserved#2",   "reserved#3",
   62         "reserved#3",   "reserved#5",   "reserved#6",   "reserved#7",
   63         "reserved#8",   "reserved#9",   "ps_poll",      "rts",
   64         "cts",          "ack",          "cf_end",       "cf_end_ack"
   65 };
   66 const char *ieee80211_opmode_name[IEEE80211_OPMODE_MAX] = {
   67         "IBSS",         /* IEEE80211_M_IBSS */
   68         "STA",          /* IEEE80211_M_STA */
   69         "#2",
   70         "AHDEMO",       /* IEEE80211_M_AHDEMO */
   71         "#4", "#5",
   72         "HOSTAP",       /* IEEE80211_M_HOSTAP */
   73         "#7",
   74         "MONITOR"       /* IEEE80211_M_MONITOR */
   75 };
   76 const char *ieee80211_state_name[IEEE80211_S_MAX] = {
   77         "INIT",         /* IEEE80211_S_INIT */
   78         "SCAN",         /* IEEE80211_S_SCAN */
   79         "AUTH",         /* IEEE80211_S_AUTH */
   80         "ASSOC",        /* IEEE80211_S_ASSOC */
   81         "CAC",          /* IEEE80211_S_CAC */
   82         "RUN",          /* IEEE80211_S_RUN */
   83         "CSA",          /* IEEE80211_S_CSA */
   84         "SLEEP",        /* IEEE80211_S_SLEEP */
   85 };
   86 const char *ieee80211_wme_acnames[] = {
   87         "WME_AC_BE",
   88         "WME_AC_BK",
   89         "WME_AC_VI",
   90         "WME_AC_VO",
   91         "WME_UPSD",
   92 };
   93 
   94 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
   95 
   96 static void
   97 null_update_beacon(struct ieee80211com *ic, int item)
   98 {
   99 }
  100 
  101 void
  102 ieee80211_proto_attach(struct ieee80211com *ic)
  103 {
  104         struct ifnet *ifp = ic->ic_ifp;
  105 
  106         /* XXX room for crypto  */
  107         ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
  108 
  109         ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
  110         ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
  111         ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
  112         ic->ic_bmiss_max = IEEE80211_BMISS_MAX;
  113         callout_init(&ic->ic_swbmiss, CALLOUT_MPSAFE);
  114         callout_init(&ic->ic_mgtsend, CALLOUT_MPSAFE);
  115         ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT;
  116         ic->ic_protmode = IEEE80211_PROT_CTSONLY;
  117         ic->ic_roaming = IEEE80211_ROAMING_AUTO;
  118 
  119         ic->ic_wme.wme_hipri_switch_hysteresis =
  120                 AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
  121 
  122         mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_xname, "mgmt send q", MTX_DEF);
  123 
  124         /* protocol state change handler */
  125         ic->ic_newstate = ieee80211_newstate;
  126         ic->ic_update_beacon = null_update_beacon;
  127 
  128         /* initialize management frame handlers */
  129         ic->ic_recv_mgmt = ieee80211_recv_mgmt;
  130         ic->ic_send_mgmt = ieee80211_send_mgmt;
  131         ic->ic_raw_xmit = ieee80211_raw_xmit;
  132 }
  133 
  134 void
  135 ieee80211_proto_detach(struct ieee80211com *ic)
  136 {
  137 
  138         /*
  139          * This should not be needed as we detach when reseting
  140          * the state but be conservative here since the
  141          * authenticator may do things like spawn kernel threads.
  142          */
  143         if (ic->ic_auth->ia_detach)
  144                 ic->ic_auth->ia_detach(ic);
  145 
  146         ieee80211_drain_ifq(&ic->ic_mgtq);
  147         mtx_destroy(&ic->ic_mgtq.ifq_mtx);
  148 
  149         /*
  150          * Detach any ACL'ator.
  151          */
  152         if (ic->ic_acl != NULL)
  153                 ic->ic_acl->iac_detach(ic);
  154 }
  155 
  156 /*
  157  * Simple-minded authenticator module support.
  158  */
  159 
  160 #define IEEE80211_AUTH_MAX      (IEEE80211_AUTH_WPA+1)
  161 /* XXX well-known names */
  162 static const char *auth_modnames[IEEE80211_AUTH_MAX] = {
  163         "wlan_internal",        /* IEEE80211_AUTH_NONE */
  164         "wlan_internal",        /* IEEE80211_AUTH_OPEN */
  165         "wlan_internal",        /* IEEE80211_AUTH_SHARED */
  166         "wlan_xauth",           /* IEEE80211_AUTH_8021X  */
  167         "wlan_internal",        /* IEEE80211_AUTH_AUTO */
  168         "wlan_xauth",           /* IEEE80211_AUTH_WPA */
  169 };
  170 static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];
  171 
  172 static const struct ieee80211_authenticator auth_internal = {
  173         .ia_name                = "wlan_internal",
  174         .ia_attach              = NULL,
  175         .ia_detach              = NULL,
  176         .ia_node_join           = NULL,
  177         .ia_node_leave          = NULL,
  178 };
  179 
  180 /*
  181  * Setup internal authenticators once; they are never unregistered.
  182  */
  183 static void
  184 ieee80211_auth_setup(void)
  185 {
  186         ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal);
  187         ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal);
  188         ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal);
  189 }
  190 SYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL);
  191 
  192 const struct ieee80211_authenticator *
  193 ieee80211_authenticator_get(int auth)
  194 {
  195         if (auth >= IEEE80211_AUTH_MAX)
  196                 return NULL;
  197         if (authenticators[auth] == NULL)
  198                 ieee80211_load_module(auth_modnames[auth]);
  199         return authenticators[auth];
  200 }
  201 
  202 void
  203 ieee80211_authenticator_register(int type,
  204         const struct ieee80211_authenticator *auth)
  205 {
  206         if (type >= IEEE80211_AUTH_MAX)
  207                 return;
  208         authenticators[type] = auth;
  209 }
  210 
  211 void
  212 ieee80211_authenticator_unregister(int type)
  213 {
  214 
  215         if (type >= IEEE80211_AUTH_MAX)
  216                 return;
  217         authenticators[type] = NULL;
  218 }
  219 
  220 /*
  221  * Very simple-minded ACL module support.
  222  */
  223 /* XXX just one for now */
  224 static  const struct ieee80211_aclator *acl = NULL;
  225 
  226 void
  227 ieee80211_aclator_register(const struct ieee80211_aclator *iac)
  228 {
  229         printf("wlan: %s acl policy registered\n", iac->iac_name);
  230         acl = iac;
  231 }
  232 
  233 void
  234 ieee80211_aclator_unregister(const struct ieee80211_aclator *iac)
  235 {
  236         if (acl == iac)
  237                 acl = NULL;
  238         printf("wlan: %s acl policy unregistered\n", iac->iac_name);
  239 }
  240 
  241 const struct ieee80211_aclator *
  242 ieee80211_aclator_get(const char *name)
  243 {
  244         if (acl == NULL)
  245                 ieee80211_load_module("wlan_acl");
  246         return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL;
  247 }
  248 
  249 void
  250 ieee80211_print_essid(const uint8_t *essid, int len)
  251 {
  252         const uint8_t *p;
  253         int i;
  254 
  255         if (len > IEEE80211_NWID_LEN)
  256                 len = IEEE80211_NWID_LEN;
  257         /* determine printable or not */
  258         for (i = 0, p = essid; i < len; i++, p++) {
  259                 if (*p < ' ' || *p > 0x7e)
  260                         break;
  261         }
  262         if (i == len) {
  263                 printf("\"");
  264                 for (i = 0, p = essid; i < len; i++, p++)
  265                         printf("%c", *p);
  266                 printf("\"");
  267         } else {
  268                 printf("0x");
  269                 for (i = 0, p = essid; i < len; i++, p++)
  270                         printf("%02x", *p);
  271         }
  272 }
  273 
  274 void
  275 ieee80211_dump_pkt(struct ieee80211com *ic,
  276         const uint8_t *buf, int len, int rate, int rssi)
  277 {
  278         const struct ieee80211_frame *wh;
  279         int i;
  280 
  281         wh = (const struct ieee80211_frame *)buf;
  282         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
  283         case IEEE80211_FC1_DIR_NODS:
  284                 printf("NODS %s", ether_sprintf(wh->i_addr2));
  285                 printf("->%s", ether_sprintf(wh->i_addr1));
  286                 printf("(%s)", ether_sprintf(wh->i_addr3));
  287                 break;
  288         case IEEE80211_FC1_DIR_TODS:
  289                 printf("TODS %s", ether_sprintf(wh->i_addr2));
  290                 printf("->%s", ether_sprintf(wh->i_addr3));
  291                 printf("(%s)", ether_sprintf(wh->i_addr1));
  292                 break;
  293         case IEEE80211_FC1_DIR_FROMDS:
  294                 printf("FRDS %s", ether_sprintf(wh->i_addr3));
  295                 printf("->%s", ether_sprintf(wh->i_addr1));
  296                 printf("(%s)", ether_sprintf(wh->i_addr2));
  297                 break;
  298         case IEEE80211_FC1_DIR_DSTODS:
  299                 printf("DSDS %s", ether_sprintf((const uint8_t *)&wh[1]));
  300                 printf("->%s", ether_sprintf(wh->i_addr3));
  301                 printf("(%s", ether_sprintf(wh->i_addr2));
  302                 printf("->%s)", ether_sprintf(wh->i_addr1));
  303                 break;
  304         }
  305         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
  306         case IEEE80211_FC0_TYPE_DATA:
  307                 printf(" data");
  308                 break;
  309         case IEEE80211_FC0_TYPE_MGT:
  310                 printf(" %s", ieee80211_mgt_subtype_name[
  311                     (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
  312                     >> IEEE80211_FC0_SUBTYPE_SHIFT]);
  313                 break;
  314         default:
  315                 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
  316                 break;
  317         }
  318         if (IEEE80211_QOS_HAS_SEQ(wh)) {
  319                 const struct ieee80211_qosframe *qwh = 
  320                         (const struct ieee80211_qosframe *)buf;
  321                 printf(" QoS [TID %u%s]", qwh->i_qos[0] & IEEE80211_QOS_TID,
  322                         qwh->i_qos[0] & IEEE80211_QOS_ACKPOLICY ? " ACM" : "");
  323         }
  324         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
  325                 int off;
  326 
  327                 off = ieee80211_anyhdrspace(ic, wh);
  328                 printf(" WEP [IV %.02x %.02x %.02x",
  329                         buf[off+0], buf[off+1], buf[off+2]);
  330                 if (buf[off+IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)
  331                         printf(" %.02x %.02x %.02x",
  332                                 buf[off+4], buf[off+5], buf[off+6]);
  333                 printf(" KID %u]", buf[off+IEEE80211_WEP_IVLEN] >> 6);
  334         }
  335         if (rate >= 0)
  336                 printf(" %dM", rate / 2);
  337         if (rssi >= 0)
  338                 printf(" +%d", rssi);
  339         printf("\n");
  340         if (len > 0) {
  341                 for (i = 0; i < len; i++) {
  342                         if ((i & 1) == 0)
  343                                 printf(" ");
  344                         printf("%02x", buf[i]);
  345                 }
  346                 printf("\n");
  347         }
  348 }
  349 
  350 static __inline int
  351 findrix(const struct ieee80211_rateset *rs, int r)
  352 {
  353         int i;
  354 
  355         for (i = 0; i < rs->rs_nrates; i++)
  356                 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == r)
  357                         return i;
  358         return -1;
  359 }
  360 
  361 int
  362 ieee80211_fix_rate(struct ieee80211_node *ni,
  363         struct ieee80211_rateset *nrs, int flags)
  364 {
  365 #define RV(v)   ((v) & IEEE80211_RATE_VAL)
  366         struct ieee80211com *ic = ni->ni_ic;
  367         int i, j, rix, error;
  368         int okrate, badrate, fixedrate;
  369         const struct ieee80211_rateset *srs;
  370         uint8_t r;
  371 
  372         error = 0;
  373         okrate = badrate = 0;
  374         fixedrate = IEEE80211_FIXED_RATE_NONE;
  375         srs = ieee80211_get_suprates(ic, ni->ni_chan);
  376         for (i = 0; i < nrs->rs_nrates; ) {
  377                 if (flags & IEEE80211_F_DOSORT) {
  378                         /*
  379                          * Sort rates.
  380                          */
  381                         for (j = i + 1; j < nrs->rs_nrates; j++) {
  382                                 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) {
  383                                         r = nrs->rs_rates[i];
  384                                         nrs->rs_rates[i] = nrs->rs_rates[j];
  385                                         nrs->rs_rates[j] = r;
  386                                 }
  387                         }
  388                 }
  389                 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
  390                 badrate = r;
  391                 /*
  392                  * Check for fixed rate.
  393                  */
  394                 if (r == ic->ic_fixed_rate)
  395                         fixedrate = r;
  396                 /*
  397                  * Check against supported rates.
  398                  */
  399                 rix = findrix(srs, r);
  400                 if (flags & IEEE80211_F_DONEGO) {
  401                         if (rix < 0) {
  402                                 /*
  403                                  * A rate in the node's rate set is not
  404                                  * supported.  If this is a basic rate and we
  405                                  * are operating as a STA then this is an error.
  406                                  * Otherwise we just discard/ignore the rate.
  407                                  */
  408                                 if ((flags & IEEE80211_F_JOIN) &&
  409                                     (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
  410                                         error++;
  411                         } else if ((flags & IEEE80211_F_JOIN) == 0) {
  412                                 /*
  413                                  * Overwrite with the supported rate
  414                                  * value so any basic rate bit is set.
  415                                  */
  416                                 nrs->rs_rates[i] = srs->rs_rates[rix];
  417                         }
  418                 }
  419                 if ((flags & IEEE80211_F_DODEL) && rix < 0) {
  420                         /*
  421                          * Delete unacceptable rates.
  422                          */
  423                         nrs->rs_nrates--;
  424                         for (j = i; j < nrs->rs_nrates; j++)
  425                                 nrs->rs_rates[j] = nrs->rs_rates[j + 1];
  426                         nrs->rs_rates[j] = 0;
  427                         continue;
  428                 }
  429                 if (rix >= 0)
  430                         okrate = nrs->rs_rates[i];
  431                 i++;
  432         }
  433         if (okrate == 0 || error != 0 ||
  434             ((flags & IEEE80211_F_DOFRATE) && fixedrate != ic->ic_fixed_rate))
  435                 return badrate | IEEE80211_RATE_BASIC;
  436         else
  437                 return RV(okrate);
  438 #undef RV
  439 }
  440 
  441 /*
  442  * Reset 11g-related state.
  443  */
  444 void
  445 ieee80211_reset_erp(struct ieee80211com *ic)
  446 {
  447         ic->ic_flags &= ~IEEE80211_F_USEPROT;
  448         ic->ic_nonerpsta = 0;
  449         ic->ic_longslotsta = 0;
  450         /*
  451          * Short slot time is enabled only when operating in 11g
  452          * and not in an IBSS.  We must also honor whether or not
  453          * the driver is capable of doing it.
  454          */
  455         ieee80211_set_shortslottime(ic,
  456                 IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
  457                 IEEE80211_IS_CHAN_HT(ic->ic_curchan) ||
  458                 (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) &&
  459                 ic->ic_opmode == IEEE80211_M_HOSTAP &&
  460                 (ic->ic_caps & IEEE80211_C_SHSLOT)));
  461         /*
  462          * Set short preamble and ERP barker-preamble flags.
  463          */
  464         if (IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
  465             (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) {
  466                 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
  467                 ic->ic_flags &= ~IEEE80211_F_USEBARKER;
  468         } else {
  469                 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
  470                 ic->ic_flags |= IEEE80211_F_USEBARKER;
  471         }
  472 }
  473 
  474 /*
  475  * Set the short slot time state and notify the driver.
  476  */
  477 void
  478 ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
  479 {
  480         if (onoff)
  481                 ic->ic_flags |= IEEE80211_F_SHSLOT;
  482         else
  483                 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
  484         /* notify driver */
  485         if (ic->ic_updateslot != NULL)
  486                 ic->ic_updateslot(ic->ic_ifp);
  487 }
  488 
  489 /*
  490  * Check if the specified rate set supports ERP.
  491  * NB: the rate set is assumed to be sorted.
  492  */
  493 int
  494 ieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs)
  495 {
  496 #define N(a)    (sizeof(a) / sizeof(a[0]))
  497         static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 };
  498         int i, j;
  499 
  500         if (rs->rs_nrates < N(rates))
  501                 return 0;
  502         for (i = 0; i < N(rates); i++) {
  503                 for (j = 0; j < rs->rs_nrates; j++) {
  504                         int r = rs->rs_rates[j] & IEEE80211_RATE_VAL;
  505                         if (rates[i] == r)
  506                                 goto next;
  507                         if (r > rates[i])
  508                                 return 0;
  509                 }
  510                 return 0;
  511         next:
  512                 ;
  513         }
  514         return 1;
  515 #undef N
  516 }
  517 
  518 /*
  519  * Mark the basic rates for the 11g rate table based on the
  520  * operating mode.  For real 11g we mark all the 11b rates
  521  * and 6, 12, and 24 OFDM.  For 11b compatibility we mark only
  522  * 11b rates.  There's also a pseudo 11a-mode used to mark only
  523  * the basic OFDM rates.
  524  */
  525 void
  526 ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode)
  527 {
  528         static const struct ieee80211_rateset basic[IEEE80211_MODE_MAX] = {
  529             { .rs_nrates = 0 },         /* IEEE80211_MODE_AUTO */
  530             { 3, { 12, 24, 48 } },      /* IEEE80211_MODE_11A */
  531             { 2, { 2, 4 } },            /* IEEE80211_MODE_11B */
  532             { 4, { 2, 4, 11, 22 } },    /* IEEE80211_MODE_11G (mixed b/g) */
  533             { .rs_nrates = 0 },         /* IEEE80211_MODE_FH */
  534                                         /* IEEE80211_MODE_PUREG (not yet) */
  535             { 7, { 2, 4, 11, 22, 12, 24, 48 } },
  536             { 3, { 12, 24, 48 } },      /* IEEE80211_MODE_11NA */
  537                                         /* IEEE80211_MODE_11NG (mixed b/g) */
  538             { 7, { 2, 4, 11, 22, 12, 24, 48 } },
  539         };
  540         int i, j;
  541 
  542         for (i = 0; i < rs->rs_nrates; i++) {
  543                 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
  544                 for (j = 0; j < basic[mode].rs_nrates; j++)
  545                         if (basic[mode].rs_rates[j] == rs->rs_rates[i]) {
  546                                 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
  547                                 break;
  548                         }
  549         }
  550 }
  551 
  552 /*
  553  * WME protocol support.  The following parameters come from the spec.
  554  */
  555 typedef struct phyParamType {
  556         uint8_t aifsn;
  557         uint8_t logcwmin;
  558         uint8_t logcwmax;
  559         uint16_t txopLimit;
  560         uint8_t acm;
  561 } paramType;
  562 
  563 static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = {
  564         { 3, 4,  6,  0, 0 },    /* IEEE80211_MODE_AUTO */
  565         { 3, 4,  6,  0, 0 },    /* IEEE80211_MODE_11A */
  566         { 3, 4,  6,  0, 0 },    /* IEEE80211_MODE_11B */
  567         { 3, 4,  6,  0, 0 },    /* IEEE80211_MODE_11G */
  568         { 3, 4,  6,  0, 0 },    /* IEEE80211_MODE_FH */
  569         { 2, 3,  5,  0, 0 },    /* IEEE80211_MODE_TURBO_A */
  570         { 2, 3,  5,  0, 0 },    /* IEEE80211_MODE_TURBO_G */
  571         { 2, 3,  5,  0, 0 },    /* IEEE80211_MODE_STURBO_A */
  572         { 3, 4,  6,  0, 0 },    /* IEEE80211_MODE_11NA */
  573         { 3, 4,  6,  0, 0 },    /* IEEE80211_MODE_11NG */
  574 };
  575 static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = {
  576         { 7, 4, 10,  0, 0 },    /* IEEE80211_MODE_AUTO */
  577         { 7, 4, 10,  0, 0 },    /* IEEE80211_MODE_11A */
  578         { 7, 4, 10,  0, 0 },    /* IEEE80211_MODE_11B */
  579         { 7, 4, 10,  0, 0 },    /* IEEE80211_MODE_11G */
  580         { 7, 4, 10,  0, 0 },    /* IEEE80211_MODE_FH */
  581         { 7, 3, 10,  0, 0 },    /* IEEE80211_MODE_TURBO_A */
  582         { 7, 3, 10,  0, 0 },    /* IEEE80211_MODE_TURBO_G */
  583         { 7, 3, 10,  0, 0 },    /* IEEE80211_MODE_STURBO_A */
  584         { 7, 4, 10,  0, 0 },    /* IEEE80211_MODE_11NA */
  585         { 7, 4, 10,  0, 0 },    /* IEEE80211_MODE_11NG */
  586 };
  587 static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = {
  588         { 1, 3, 4,  94, 0 },    /* IEEE80211_MODE_AUTO */
  589         { 1, 3, 4,  94, 0 },    /* IEEE80211_MODE_11A */
  590         { 1, 3, 4, 188, 0 },    /* IEEE80211_MODE_11B */
  591         { 1, 3, 4,  94, 0 },    /* IEEE80211_MODE_11G */
  592         { 1, 3, 4, 188, 0 },    /* IEEE80211_MODE_FH */
  593         { 1, 2, 3,  94, 0 },    /* IEEE80211_MODE_TURBO_A */
  594         { 1, 2, 3,  94, 0 },    /* IEEE80211_MODE_TURBO_G */
  595         { 1, 2, 3,  94, 0 },    /* IEEE80211_MODE_STURBO_A */
  596         { 1, 3, 4,  94, 0 },    /* IEEE80211_MODE_11NA */
  597         { 1, 3, 4,  94, 0 },    /* IEEE80211_MODE_11NG */
  598 };
  599 static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = {
  600         { 1, 2, 3,  47, 0 },    /* IEEE80211_MODE_AUTO */
  601         { 1, 2, 3,  47, 0 },    /* IEEE80211_MODE_11A */
  602         { 1, 2, 3, 102, 0 },    /* IEEE80211_MODE_11B */
  603         { 1, 2, 3,  47, 0 },    /* IEEE80211_MODE_11G */
  604         { 1, 2, 3, 102, 0 },    /* IEEE80211_MODE_FH */
  605         { 1, 2, 2,  47, 0 },    /* IEEE80211_MODE_TURBO_A */
  606         { 1, 2, 2,  47, 0 },    /* IEEE80211_MODE_TURBO_G */
  607         { 1, 2, 2,  47, 0 },    /* IEEE80211_MODE_STURBO_A */
  608         { 1, 2, 3,  47, 0 },    /* IEEE80211_MODE_11NA */
  609         { 1, 2, 3,  47, 0 },    /* IEEE80211_MODE_11NG */
  610 };
  611 
  612 static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = {
  613         { 3, 4, 10,  0, 0 },    /* IEEE80211_MODE_AUTO */
  614         { 3, 4, 10,  0, 0 },    /* IEEE80211_MODE_11A */
  615         { 3, 4, 10,  0, 0 },    /* IEEE80211_MODE_11B */
  616         { 3, 4, 10,  0, 0 },    /* IEEE80211_MODE_11G */
  617         { 3, 4, 10,  0, 0 },    /* IEEE80211_MODE_FH */
  618         { 2, 3, 10,  0, 0 },    /* IEEE80211_MODE_TURBO_A */
  619         { 2, 3, 10,  0, 0 },    /* IEEE80211_MODE_TURBO_G */
  620         { 2, 3, 10,  0, 0 },    /* IEEE80211_MODE_STURBO_A */
  621         { 3, 4, 10,  0, 0 },    /* IEEE80211_MODE_11NA */
  622         { 3, 4, 10,  0, 0 },    /* IEEE80211_MODE_11NG */
  623 };
  624 static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = {
  625         { 2, 3, 4,  94, 0 },    /* IEEE80211_MODE_AUTO */
  626         { 2, 3, 4,  94, 0 },    /* IEEE80211_MODE_11A */
  627         { 2, 3, 4, 188, 0 },    /* IEEE80211_MODE_11B */
  628         { 2, 3, 4,  94, 0 },    /* IEEE80211_MODE_11G */
  629         { 2, 3, 4, 188, 0 },    /* IEEE80211_MODE_FH */
  630         { 2, 2, 3,  94, 0 },    /* IEEE80211_MODE_TURBO_A */
  631         { 2, 2, 3,  94, 0 },    /* IEEE80211_MODE_TURBO_G */
  632         { 2, 2, 3,  94, 0 },    /* IEEE80211_MODE_STURBO_A */
  633         { 2, 3, 4,  94, 0 },    /* IEEE80211_MODE_11NA */
  634         { 2, 3, 4,  94, 0 },    /* IEEE80211_MODE_11NG */
  635 };
  636 static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = {
  637         { 2, 2, 3,  47, 0 },    /* IEEE80211_MODE_AUTO */
  638         { 2, 2, 3,  47, 0 },    /* IEEE80211_MODE_11A */
  639         { 2, 2, 3, 102, 0 },    /* IEEE80211_MODE_11B */
  640         { 2, 2, 3,  47, 0 },    /* IEEE80211_MODE_11G */
  641         { 2, 2, 3, 102, 0 },    /* IEEE80211_MODE_FH */
  642         { 1, 2, 2,  47, 0 },    /* IEEE80211_MODE_TURBO_A */
  643         { 1, 2, 2,  47, 0 },    /* IEEE80211_MODE_TURBO_G */
  644         { 1, 2, 2,  47, 0 },    /* IEEE80211_MODE_STURBO_A */
  645         { 2, 2, 3,  47, 0 },    /* IEEE80211_MODE_11NA */
  646         { 2, 2, 3,  47, 0 },    /* IEEE80211_MODE_11NG */
  647 };
  648 
  649 void
  650 ieee80211_wme_initparams(struct ieee80211com *ic)
  651 {
  652         struct ieee80211_wme_state *wme = &ic->ic_wme;
  653         const paramType *pPhyParam, *pBssPhyParam;
  654         struct wmeParams *wmep;
  655         enum ieee80211_phymode mode;
  656         int i;
  657 
  658         if ((ic->ic_caps & IEEE80211_C_WME) == 0)
  659                 return;
  660 
  661         /*
  662          * Select mode; we can be called early in which case we
  663          * always use auto mode.  We know we'll be called when
  664          * entering the RUN state with bsschan setup properly
  665          * so state will eventually get set correctly
  666          */
  667         if (ic->ic_bsschan != IEEE80211_CHAN_ANYC)
  668                 mode = ieee80211_chan2mode(ic->ic_bsschan);
  669         else
  670                 mode = IEEE80211_MODE_AUTO;
  671         for (i = 0; i < WME_NUM_AC; i++) {
  672                 switch (i) {
  673                 case WME_AC_BK:
  674                         pPhyParam = &phyParamForAC_BK[mode];
  675                         pBssPhyParam = &phyParamForAC_BK[mode];
  676                         break;
  677                 case WME_AC_VI:
  678                         pPhyParam = &phyParamForAC_VI[mode];
  679                         pBssPhyParam = &bssPhyParamForAC_VI[mode];
  680                         break;
  681                 case WME_AC_VO:
  682                         pPhyParam = &phyParamForAC_VO[mode];
  683                         pBssPhyParam = &bssPhyParamForAC_VO[mode];
  684                         break;
  685                 case WME_AC_BE:
  686                 default:
  687                         pPhyParam = &phyParamForAC_BE[mode];
  688                         pBssPhyParam = &bssPhyParamForAC_BE[mode];
  689                         break;
  690                 }
  691 
  692                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
  693                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  694                         wmep->wmep_acm = pPhyParam->acm;
  695                         wmep->wmep_aifsn = pPhyParam->aifsn;    
  696                         wmep->wmep_logcwmin = pPhyParam->logcwmin;      
  697                         wmep->wmep_logcwmax = pPhyParam->logcwmax;              
  698                         wmep->wmep_txopLimit = pPhyParam->txopLimit;
  699                 } else {
  700                         wmep->wmep_acm = pBssPhyParam->acm;
  701                         wmep->wmep_aifsn = pBssPhyParam->aifsn; 
  702                         wmep->wmep_logcwmin = pBssPhyParam->logcwmin;   
  703                         wmep->wmep_logcwmax = pBssPhyParam->logcwmax;           
  704                         wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
  705 
  706                 }       
  707                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  708                         "%s: %s chan [acm %u aifsn %u log2(cwmin) %u "
  709                         "log2(cwmax) %u txpoLimit %u]\n", __func__
  710                         , ieee80211_wme_acnames[i]
  711                         , wmep->wmep_acm
  712                         , wmep->wmep_aifsn
  713                         , wmep->wmep_logcwmin
  714                         , wmep->wmep_logcwmax
  715                         , wmep->wmep_txopLimit
  716                 );
  717 
  718                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
  719                 wmep->wmep_acm = pBssPhyParam->acm;
  720                 wmep->wmep_aifsn = pBssPhyParam->aifsn; 
  721                 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;   
  722                 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;           
  723                 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
  724                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  725                         "%s: %s  bss [acm %u aifsn %u log2(cwmin) %u "
  726                         "log2(cwmax) %u txpoLimit %u]\n", __func__
  727                         , ieee80211_wme_acnames[i]
  728                         , wmep->wmep_acm
  729                         , wmep->wmep_aifsn
  730                         , wmep->wmep_logcwmin
  731                         , wmep->wmep_logcwmax
  732                         , wmep->wmep_txopLimit
  733                 );
  734         }
  735         /* NB: check ic_bss to avoid NULL deref on initial attach */
  736         if (ic->ic_bss != NULL) {
  737                 /*
  738                  * Calculate agressive mode switching threshold based
  739                  * on beacon interval.  This doesn't need locking since
  740                  * we're only called before entering the RUN state at
  741                  * which point we start sending beacon frames.
  742                  */
  743                 wme->wme_hipri_switch_thresh =
  744                         (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100;
  745                 ieee80211_wme_updateparams(ic);
  746         }
  747 }
  748 
  749 /*
  750  * Update WME parameters for ourself and the BSS.
  751  */
  752 void
  753 ieee80211_wme_updateparams_locked(struct ieee80211com *ic)
  754 {
  755         static const paramType phyParam[IEEE80211_MODE_MAX] = {
  756                 { 2, 4, 10, 64, 0 },    /* IEEE80211_MODE_AUTO */
  757                 { 2, 4, 10, 64, 0 },    /* IEEE80211_MODE_11A */
  758                 { 2, 5, 10, 64, 0 },    /* IEEE80211_MODE_11B */
  759                 { 2, 4, 10, 64, 0 },    /* IEEE80211_MODE_11G */
  760                 { 2, 5, 10, 64, 0 },    /* IEEE80211_MODE_FH */
  761                 { 1, 3, 10, 64, 0 },    /* IEEE80211_MODE_TURBO_A */
  762                 { 1, 3, 10, 64, 0 },    /* IEEE80211_MODE_TURBO_G */
  763                 { 1, 3, 10, 64, 0 },    /* IEEE80211_MODE_STURBO_A */
  764                 { 2, 4, 10, 64, 0 },    /* IEEE80211_MODE_11NA */ /*XXXcheck*/
  765                 { 2, 4, 10, 64, 0 },    /* IEEE80211_MODE_11NG */ /*XXXcheck*/
  766         };
  767         struct ieee80211_wme_state *wme = &ic->ic_wme;
  768         const struct wmeParams *wmep;
  769         struct wmeParams *chanp, *bssp;
  770         enum ieee80211_phymode mode;
  771         int i;
  772 
  773         /* set up the channel access parameters for the physical device */
  774         for (i = 0; i < WME_NUM_AC; i++) {
  775                 chanp = &wme->wme_chanParams.cap_wmeParams[i];
  776                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
  777                 chanp->wmep_aifsn = wmep->wmep_aifsn;
  778                 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
  779                 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
  780                 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
  781 
  782                 chanp = &wme->wme_bssChanParams.cap_wmeParams[i];
  783                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
  784                 chanp->wmep_aifsn = wmep->wmep_aifsn;
  785                 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
  786                 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
  787                 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
  788         }
  789 
  790         /*
  791          * Select mode; we can be called early in which case we
  792          * always use auto mode.  We know we'll be called when
  793          * entering the RUN state with bsschan setup properly
  794          * so state will eventually get set correctly
  795          */
  796         if (ic->ic_bsschan != IEEE80211_CHAN_ANYC)
  797                 mode = ieee80211_chan2mode(ic->ic_bsschan);
  798         else
  799                 mode = IEEE80211_MODE_AUTO;
  800 
  801         /*
  802          * This implements agressive mode as found in certain
  803          * vendors' AP's.  When there is significant high
  804          * priority (VI/VO) traffic in the BSS throttle back BE
  805          * traffic by using conservative parameters.  Otherwise
  806          * BE uses agressive params to optimize performance of
  807          * legacy/non-QoS traffic.
  808          */
  809         if ((ic->ic_opmode == IEEE80211_M_HOSTAP &&
  810              (wme->wme_flags & WME_F_AGGRMODE) != 0) ||
  811             (ic->ic_opmode == IEEE80211_M_STA &&
  812              (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) ||
  813             (ic->ic_flags & IEEE80211_F_WME) == 0) {
  814                 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
  815                 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
  816 
  817                 chanp->wmep_aifsn = bssp->wmep_aifsn = phyParam[mode].aifsn;
  818                 chanp->wmep_logcwmin = bssp->wmep_logcwmin =
  819                         phyParam[mode].logcwmin;
  820                 chanp->wmep_logcwmax = bssp->wmep_logcwmax =
  821                         phyParam[mode].logcwmax;
  822                 chanp->wmep_txopLimit = bssp->wmep_txopLimit =
  823                         (ic->ic_flags & IEEE80211_F_BURST) ?
  824                                 phyParam[mode].txopLimit : 0;           
  825                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  826                         "%s: %s [acm %u aifsn %u log2(cwmin) %u "
  827                         "log2(cwmax) %u txpoLimit %u]\n", __func__
  828                         , ieee80211_wme_acnames[WME_AC_BE]
  829                         , chanp->wmep_acm
  830                         , chanp->wmep_aifsn
  831                         , chanp->wmep_logcwmin
  832                         , chanp->wmep_logcwmax
  833                         , chanp->wmep_txopLimit
  834                 );
  835         }
  836         
  837         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  838             ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) {
  839                 static const uint8_t logCwMin[IEEE80211_MODE_MAX] = {
  840                         3,      /* IEEE80211_MODE_AUTO */
  841                         3,      /* IEEE80211_MODE_11A */
  842                         4,      /* IEEE80211_MODE_11B */
  843                         3,      /* IEEE80211_MODE_11G */
  844                         4,      /* IEEE80211_MODE_FH */
  845                         3,      /* IEEE80211_MODE_TURBO_A */
  846                         3,      /* IEEE80211_MODE_TURBO_G */
  847                         3,      /* IEEE80211_MODE_STURBO_A */
  848                         3,      /* IEEE80211_MODE_11NA */
  849                         3,      /* IEEE80211_MODE_11NG */
  850                 };
  851                 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
  852                 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
  853 
  854                 chanp->wmep_logcwmin = bssp->wmep_logcwmin = logCwMin[mode];
  855                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  856                         "%s: %s log2(cwmin) %u\n", __func__
  857                         , ieee80211_wme_acnames[WME_AC_BE]
  858                         , chanp->wmep_logcwmin
  859                 );
  860         }       
  861         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {      /* XXX ibss? */
  862                 /*
  863                  * Arrange for a beacon update and bump the parameter
  864                  * set number so associated stations load the new values.
  865                  */
  866                 wme->wme_bssChanParams.cap_info =
  867                         (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
  868                 ieee80211_beacon_notify(ic, IEEE80211_BEACON_WME);
  869         }
  870 
  871         wme->wme_update(ic);
  872 
  873         IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  874                 "%s: WME params updated, cap_info 0x%x\n", __func__,
  875                 ic->ic_opmode == IEEE80211_M_STA ?
  876                         wme->wme_wmeChanParams.cap_info :
  877                         wme->wme_bssChanParams.cap_info);
  878 }
  879 
  880 void
  881 ieee80211_wme_updateparams(struct ieee80211com *ic)
  882 {
  883 
  884         if (ic->ic_caps & IEEE80211_C_WME) {
  885                 IEEE80211_BEACON_LOCK(ic);
  886                 ieee80211_wme_updateparams_locked(ic);
  887                 IEEE80211_BEACON_UNLOCK(ic);
  888         }
  889 }
  890 
  891 /*
  892  * Start a device.  If this is the first vap running on the
  893  * underlying device then we first bring it up.
  894  */
  895 int
  896 ieee80211_init(struct ieee80211com *ic, int forcescan)
  897 {
  898 
  899         IEEE80211_DPRINTF(ic,
  900                 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
  901                 "%s\n", "start running");
  902 
  903         /*
  904          * Kick the 802.11 state machine as appropriate.
  905          */
  906         if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) {
  907                 if (ic->ic_opmode == IEEE80211_M_STA) {
  908                         ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
  909                 } else {
  910                         /*
  911                          * For monitor+wds modes there's nothing to do but
  912                          * start running.  Otherwise, if this is the first
  913                          * vap to be brought up, start a scan which may be
  914                          * preempted if the station is locked to a particular
  915                          * channel.
  916                          */
  917                         if (ic->ic_opmode == IEEE80211_M_MONITOR ||
  918                             ic->ic_opmode == IEEE80211_M_WDS) {
  919                                 ic->ic_state = IEEE80211_S_INIT;        /* XXX*/
  920                                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
  921                         } else
  922                                 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
  923                 }
  924         }
  925         return 0;
  926 }
  927 
  928 /*
  929  * Switch between turbo and non-turbo operating modes.
  930  * Use the specified channel flags to locate the new
  931  * channel, update 802.11 state, and then call back into
  932  * the driver to effect the change.
  933  */
  934 void
  935 ieee80211_dturbo_switch(struct ieee80211com *ic, int newflags)
  936 {
  937         struct ieee80211_channel *chan;
  938 
  939         chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
  940         if (chan == NULL) {             /* XXX should not happen */
  941                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
  942                     "%s: no channel with freq %u flags 0x%x\n",
  943                     __func__, ic->ic_bsschan->ic_freq, newflags);
  944                 return;
  945         }
  946 
  947         IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
  948             "%s: %s -> %s (freq %u flags 0x%x)\n", __func__,
  949             ieee80211_phymode_name[ieee80211_chan2mode(ic->ic_bsschan)],
  950             ieee80211_phymode_name[ieee80211_chan2mode(chan)],
  951             chan->ic_freq, chan->ic_flags);
  952 
  953         ic->ic_bsschan = chan;
  954         ic->ic_prevchan = ic->ic_curchan;
  955         ic->ic_curchan = chan;
  956         ic->ic_set_channel(ic);
  957         /* NB: do not need to reset ERP state 'cuz we're in sta mode */
  958 }
  959 
  960 void
  961 ieee80211_beacon_miss(struct ieee80211com *ic)
  962 {
  963 
  964         if (ic->ic_flags & IEEE80211_F_SCAN) {
  965                 /* XXX check ic_curchan != ic_bsschan? */
  966                 return;
  967         }
  968         IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
  969                 "%s\n", "beacon miss");
  970 
  971         /*
  972          * Our handling is only meaningful for stations that are
  973          * associated; any other conditions else will be handled
  974          * through different means (e.g. the tx timeout on mgt frames).
  975          */
  976         if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN)
  977                 return;
  978 
  979         if (++ic->ic_bmiss_count < ic->ic_bmiss_max) {
  980                 /*
  981                  * Send a directed probe req before falling back to a scan;
  982                  * if we receive a response ic_bmiss_count will be reset.
  983                  * Some cards mistakenly report beacon miss so this avoids
  984                  * the expensive scan if the ap is still there.
  985                  */
  986                 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr,
  987                         ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid,
  988                         ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen,
  989                         ic->ic_opt_ie, ic->ic_opt_ie_len);
  990                 return;
  991         }
  992         ic->ic_bmiss_count = 0;
  993         if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
  994                 /*
  995                  * If we receive a beacon miss interrupt when using
  996                  * dynamic turbo, attempt to switch modes before
  997                  * reassociating.
  998                  */
  999                 if (IEEE80211_ATH_CAP(ic, ic->ic_bss, IEEE80211_NODE_TURBOP))
 1000                         ieee80211_dturbo_switch(ic,
 1001                             ic->ic_bsschan->ic_flags ^ IEEE80211_CHAN_TURBO);
 1002                 /*
 1003                  * Try to reassociate before scanning for a new ap.
 1004                  */
 1005                 ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
 1006         } else {
 1007                 /*
 1008                  * Somebody else is controlling state changes (e.g.
 1009                  * a user-mode app) don't do anything that would
 1010                  * confuse them; just drop into scan mode so they'll
 1011                  * notified of the state change and given control.
 1012                  */
 1013                 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
 1014         }
 1015 }
 1016 
 1017 /*
 1018  * Software beacon miss handling.  Check if any beacons
 1019  * were received in the last period.  If not post a
 1020  * beacon miss; otherwise reset the counter.
 1021  */
 1022 static void
 1023 ieee80211_swbmiss(void *arg)
 1024 {
 1025         struct ieee80211com *ic = arg;
 1026 
 1027         if (ic->ic_swbmiss_count == 0) {
 1028                 ieee80211_beacon_miss(ic);
 1029                 if (ic->ic_bmiss_count == 0)    /* don't re-arm timer */
 1030                         return;
 1031         } else
 1032                 ic->ic_swbmiss_count = 0;
 1033         callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
 1034                 ieee80211_swbmiss, ic);
 1035 }
 1036 
 1037 static void
 1038 sta_disassoc(void *arg, struct ieee80211_node *ni)
 1039 {
 1040         struct ieee80211com *ic = arg;
 1041 
 1042         if (ni->ni_associd != 0) {
 1043                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
 1044                         IEEE80211_REASON_ASSOC_LEAVE);
 1045                 ieee80211_node_leave(ic, ni);
 1046         }
 1047 }
 1048 
 1049 static void
 1050 sta_deauth(void *arg, struct ieee80211_node *ni)
 1051 {
 1052         struct ieee80211com *ic = arg;
 1053 
 1054         IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
 1055                 IEEE80211_REASON_ASSOC_LEAVE);
 1056 }
 1057 
 1058 /*
 1059  * Handle deauth with reason.  We retry only for
 1060  * the cases where we might succeed.  Otherwise
 1061  * we downgrade the ap and scan.
 1062  */
 1063 static void
 1064 sta_authretry(struct ieee80211com *ic, struct ieee80211_node *ni, int reason)
 1065 {
 1066         switch (reason) {
 1067         case IEEE80211_STATUS_SUCCESS:
 1068         case IEEE80211_STATUS_TIMEOUT:
 1069         case IEEE80211_REASON_ASSOC_EXPIRE:
 1070         case IEEE80211_REASON_NOT_AUTHED:
 1071         case IEEE80211_REASON_NOT_ASSOCED:
 1072         case IEEE80211_REASON_ASSOC_LEAVE:
 1073         case IEEE80211_REASON_ASSOC_NOT_AUTHED:
 1074                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 1);
 1075                 break;
 1076         default:
 1077                 ieee80211_scan_assoc_fail(ic, ic->ic_bss->ni_macaddr, reason);
 1078                 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
 1079                         ieee80211_check_scan(ic,
 1080                                 IEEE80211_SCAN_ACTIVE,
 1081                                 IEEE80211_SCAN_FOREVER,
 1082                                 ic->ic_des_nssid, ic->ic_des_ssid);
 1083                 break;
 1084         }
 1085 }
 1086 
 1087 static int
 1088 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 1089 {
 1090         struct ifnet *ifp = ic->ic_ifp;
 1091         struct ieee80211_node *ni;
 1092         enum ieee80211_state ostate;
 1093 
 1094         ostate = ic->ic_state;
 1095         IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
 1096                 ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
 1097         ic->ic_state = nstate;                  /* state transition */
 1098         callout_stop(&ic->ic_mgtsend);          /* XXX callout_drain */
 1099         if (ostate != IEEE80211_S_SCAN)
 1100                 ieee80211_cancel_scan(ic);      /* background scan */
 1101         ni = ic->ic_bss;                        /* NB: no reference held */
 1102         if (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)
 1103                 callout_stop(&ic->ic_swbmiss);
 1104         switch (nstate) {
 1105         case IEEE80211_S_INIT:
 1106                 switch (ostate) {
 1107                 case IEEE80211_S_INIT:
 1108                         break;
 1109                 case IEEE80211_S_RUN:
 1110                         switch (ic->ic_opmode) {
 1111                         case IEEE80211_M_STA:
 1112                                 IEEE80211_SEND_MGMT(ic, ni,
 1113                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
 1114                                     IEEE80211_REASON_ASSOC_LEAVE);
 1115                                 ieee80211_sta_leave(ic, ni);
 1116                                 break;
 1117                         case IEEE80211_M_HOSTAP:
 1118                                 ieee80211_iterate_nodes(&ic->ic_sta,
 1119                                         sta_disassoc, ic);
 1120                                 break;
 1121                         default:
 1122                                 break;
 1123                         }
 1124                         break;
 1125                 case IEEE80211_S_ASSOC:
 1126                         switch (ic->ic_opmode) {
 1127                         case IEEE80211_M_STA:
 1128                                 IEEE80211_SEND_MGMT(ic, ni,
 1129                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
 1130                                     IEEE80211_REASON_AUTH_LEAVE);
 1131                                 break;
 1132                         case IEEE80211_M_HOSTAP:
 1133                                 ieee80211_iterate_nodes(&ic->ic_sta,
 1134                                         sta_deauth, ic);
 1135                                 break;
 1136                         default:
 1137                                 break;
 1138                         }
 1139                         break;
 1140                 case IEEE80211_S_SCAN:
 1141                         ieee80211_cancel_scan(ic);
 1142                         break;
 1143                 case IEEE80211_S_AUTH:
 1144                         break;
 1145                 default:
 1146                         break;
 1147                 }
 1148                 if (ostate != IEEE80211_S_INIT) {
 1149                         /* NB: optimize INIT -> INIT case */
 1150                         ieee80211_drain_ifq(&ic->ic_mgtq);
 1151                         ieee80211_reset_bss(ic);
 1152                         ieee80211_scan_flush(ic);
 1153                 }
 1154                 if (ic->ic_auth->ia_detach != NULL)
 1155                         ic->ic_auth->ia_detach(ic);
 1156                 break;
 1157         case IEEE80211_S_SCAN:
 1158                 switch (ostate) {
 1159                 case IEEE80211_S_INIT:
 1160                 createibss:
 1161                         if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
 1162                              ic->ic_opmode == IEEE80211_M_IBSS ||
 1163                              ic->ic_opmode == IEEE80211_M_AHDEMO) &&
 1164                             ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
 1165                                 /*
 1166                                  * Already have a channel; bypass the
 1167                                  * scan and startup immediately.  Because
 1168                                  * of this explicitly sync the scanner state.
 1169                                  */
 1170                                 ieee80211_scan_update(ic);
 1171                                 ieee80211_create_ibss(ic, ic->ic_des_chan);
 1172                         } else {
 1173                                 ieee80211_check_scan(ic,
 1174                                         IEEE80211_SCAN_ACTIVE |
 1175                                         IEEE80211_SCAN_FLUSH,
 1176                                         IEEE80211_SCAN_FOREVER,
 1177                                         ic->ic_des_nssid, ic->ic_des_ssid);
 1178                         }
 1179                         break;
 1180                 case IEEE80211_S_SCAN:
 1181                 case IEEE80211_S_AUTH:
 1182                 case IEEE80211_S_ASSOC:
 1183                         /*
 1184                          * These can happen either because of a timeout
 1185                          * on an assoc/auth response or because of a
 1186                          * change in state that requires a reset.  For
 1187                          * the former we're called with a non-zero arg
 1188                          * that is the cause for the failure; pass this
 1189                          * to the scan code so it can update state.
 1190                          * Otherwise trigger a new scan unless we're in
 1191                          * manual roaming mode in which case an application
 1192                          * must issue an explicit scan request.
 1193                          */
 1194                         if (arg != 0)
 1195                                 ieee80211_scan_assoc_fail(ic,
 1196                                         ic->ic_bss->ni_macaddr, arg);
 1197                         if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
 1198                                 ieee80211_check_scan(ic,
 1199                                         IEEE80211_SCAN_ACTIVE,
 1200                                         IEEE80211_SCAN_FOREVER,
 1201                                         ic->ic_des_nssid, ic->ic_des_ssid);
 1202                         break;
 1203                 case IEEE80211_S_RUN:           /* beacon miss */
 1204                         if (ic->ic_opmode == IEEE80211_M_STA) {
 1205                                 ieee80211_sta_leave(ic, ni);
 1206                                 ic->ic_flags &= ~IEEE80211_F_SIBSS;     /* XXX */
 1207                                 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
 1208                                         ieee80211_check_scan(ic,
 1209                                                 IEEE80211_SCAN_ACTIVE,
 1210                                                 IEEE80211_SCAN_FOREVER,
 1211                                                 ic->ic_des_nssid,
 1212                                                 ic->ic_des_ssid);
 1213                         } else {
 1214                                 ieee80211_iterate_nodes(&ic->ic_sta,
 1215                                         sta_disassoc, ic);
 1216                                 goto createibss;
 1217                         }
 1218                         break;
 1219                 default:
 1220                         break;
 1221                 }
 1222                 break;
 1223         case IEEE80211_S_AUTH:
 1224                 KASSERT(ic->ic_opmode == IEEE80211_M_STA,
 1225                         ("switch to %s state when operating in mode %u",
 1226                          ieee80211_state_name[nstate], ic->ic_opmode));
 1227                 switch (ostate) {
 1228                 case IEEE80211_S_INIT:
 1229                 case IEEE80211_S_SCAN:
 1230                         IEEE80211_SEND_MGMT(ic, ni,
 1231                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
 1232                         break;
 1233                 case IEEE80211_S_AUTH:
 1234                 case IEEE80211_S_ASSOC:
 1235                         switch (arg & 0xff) {
 1236                         case IEEE80211_FC0_SUBTYPE_AUTH:
 1237                                 /* ??? */
 1238                                 IEEE80211_SEND_MGMT(ic, ni,
 1239                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
 1240                                 break;
 1241                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1242                                 sta_authretry(ic, ni, arg>>8);
 1243                                 break;
 1244                         }
 1245                         break;
 1246                 case IEEE80211_S_RUN:
 1247                         switch (arg & 0xff) {
 1248                         case IEEE80211_FC0_SUBTYPE_AUTH:
 1249                                 IEEE80211_SEND_MGMT(ic, ni,
 1250                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
 1251                                 ic->ic_state = ostate;  /* stay RUN */
 1252                                 break;
 1253                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1254                                 ieee80211_sta_leave(ic, ni);
 1255                                 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
 1256                                         /* try to reauth */
 1257                                         IEEE80211_SEND_MGMT(ic, ni,
 1258                                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
 1259                                 }
 1260                                 break;
 1261                         }
 1262                         break;
 1263                 default:
 1264                         break;
 1265                 }
 1266                 break;
 1267         case IEEE80211_S_ASSOC:
 1268                 KASSERT(ic->ic_opmode == IEEE80211_M_STA,
 1269                         ("switch to %s state when operating in mode %u",
 1270                          ieee80211_state_name[nstate], ic->ic_opmode));
 1271                 switch (ostate) {
 1272                 case IEEE80211_S_INIT:
 1273                 case IEEE80211_S_SCAN:
 1274                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1275                                 "%s: invalid transition\n", __func__);
 1276                         break;
 1277                 case IEEE80211_S_AUTH:
 1278                 case IEEE80211_S_ASSOC:
 1279                         IEEE80211_SEND_MGMT(ic, ni,
 1280                             IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
 1281                         break;
 1282                 case IEEE80211_S_RUN:
 1283                         ieee80211_sta_leave(ic, ni);
 1284                         if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
 1285                                 IEEE80211_SEND_MGMT(ic, ni, arg ?
 1286                                     IEEE80211_FC0_SUBTYPE_REASSOC_REQ :
 1287                                     IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
 1288                         }
 1289                         break;
 1290                 default:
 1291                         break;
 1292                 }
 1293                 break;
 1294         case IEEE80211_S_RUN:
 1295                 if (ic->ic_flags & IEEE80211_F_WPA) {
 1296                         /* XXX validate prerequisites */
 1297                 }
 1298                 switch (ostate) {
 1299                 case IEEE80211_S_INIT:
 1300                         if (ic->ic_opmode == IEEE80211_M_MONITOR ||
 1301                             ic->ic_opmode == IEEE80211_M_WDS ||
 1302                             ic->ic_opmode == IEEE80211_M_HOSTAP) {
 1303                                 /*
 1304                                  * Already have a channel; bypass the
 1305                                  * scan and startup immediately.  Because
 1306                                  * of this explicitly sync the scanner state.
 1307                                  */
 1308                                 ieee80211_scan_update(ic);
 1309                                 ieee80211_create_ibss(ic,
 1310                                     ieee80211_ht_adjust_channel(ic,
 1311                                         ic->ic_curchan, ic->ic_flags_ext));
 1312                                 break;
 1313                         }
 1314                         /* fall thru... */
 1315                 case IEEE80211_S_AUTH:
 1316                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1317                                 "%s: invalid transition\n", __func__);
 1318                         /* fall thru... */
 1319                 case IEEE80211_S_RUN:
 1320                         break;
 1321                 case IEEE80211_S_SCAN:          /* adhoc/hostap mode */
 1322                 case IEEE80211_S_ASSOC:         /* infra mode */
 1323                         KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,
 1324                                 ("%s: bogus xmit rate %u setup\n", __func__,
 1325                                         ni->ni_txrate));
 1326 #ifdef IEEE80211_DEBUG
 1327                         if (ieee80211_msg_debug(ic)) {
 1328                                 if (ic->ic_opmode == IEEE80211_M_STA)
 1329                                         if_printf(ifp, "associated ");
 1330                                 else
 1331                                         if_printf(ifp, "synchronized ");
 1332                                 printf("with %s ssid ",
 1333                                     ether_sprintf(ni->ni_bssid));
 1334                                 ieee80211_print_essid(ic->ic_bss->ni_essid,
 1335                                     ni->ni_esslen);
 1336                                 printf(" channel %d start %uMb\n",
 1337                                         ieee80211_chan2ieee(ic, ic->ic_curchan),
 1338                                         IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
 1339                         }
 1340 #endif
 1341                         if (ic->ic_opmode == IEEE80211_M_STA) {
 1342                                 ieee80211_scan_assoc_success(ic,
 1343                                         ni->ni_macaddr);
 1344                                 ieee80211_notify_node_join(ic, ni, 
 1345                                         arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
 1346                         }
 1347                         if_start(ifp);          /* XXX not authorized yet */
 1348                         break;
 1349                 default:
 1350                         break;
 1351                 }
 1352                 if (ostate != IEEE80211_S_RUN &&
 1353                     ic->ic_opmode == IEEE80211_M_STA &&
 1354                     (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)) {
 1355                         /*
 1356                          * Start s/w beacon miss timer for devices w/o
 1357                          * hardware support.  We fudge a bit here since
 1358                          * we're doing this in software.
 1359                          */
 1360                         ic->ic_swbmiss_period = IEEE80211_TU_TO_TICKS(
 1361                                 2 * ic->ic_bmissthreshold * ni->ni_intval);
 1362                         ic->ic_swbmiss_count = 0;
 1363                         callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
 1364                                 ieee80211_swbmiss, ic);
 1365                 }
 1366                 /*
 1367                  * Start/stop the authenticator when operating as an
 1368                  * AP.  We delay until here to allow configuration to
 1369                  * happen out of order.
 1370                  */
 1371                 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */
 1372                     ic->ic_auth->ia_attach != NULL) {
 1373                         /* XXX check failure */
 1374                         ic->ic_auth->ia_attach(ic);
 1375                 } else if (ic->ic_auth->ia_detach != NULL) {
 1376                         ic->ic_auth->ia_detach(ic);
 1377                 }
 1378                 /*
 1379                  * When 802.1x is not in use mark the port authorized
 1380                  * at this point so traffic can flow.
 1381                  */
 1382                 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
 1383                         ieee80211_node_authorize(ni);
 1384                 /*
 1385                  * Enable inactivity processing.
 1386                  * XXX
 1387                  */
 1388                 callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
 1389                         ieee80211_node_timeout, ic);
 1390                 break;
 1391         default:
 1392                 break;
 1393         }
 1394         return 0;
 1395 }

Cache object: db6e4fdd211abed836d7350d078befdc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.