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 /*      $NetBSD: ieee80211_proto.c,v 1.37 2021/07/24 21:31:38 andvar Exp $      */
    2 /*-
    3  * Copyright (c) 2001 Atsushi Onoe
    4  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * Alternatively, this software may be distributed under the terms of the
   19  * GNU General Public License ("GPL") version 2 as published by the Free
   20  * Software Foundation.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 #ifdef __FreeBSD__
   36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.23 2005/08/10 16:22:29 sam Exp $");
   37 #endif
   38 #ifdef __NetBSD__
   39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.37 2021/07/24 21:31:38 andvar Exp $");
   40 #endif
   41 
   42 /*
   43  * IEEE 802.11 protocol support.
   44  */
   45 
   46 #ifdef _KERNEL_OPT
   47 #include "opt_inet.h"
   48 #endif
   49 
   50 #include <sys/param.h>
   51 #include <sys/kernel.h>
   52 #include <sys/systm.h> 
   53  
   54 #include <sys/socket.h>
   55 #include <sys/sockio.h>
   56 #include <sys/endian.h>
   57 #include <sys/errno.h>
   58 #include <sys/proc.h>
   59 #include <sys/sysctl.h>
   60 #include <sys/cpu.h>
   61 
   62 #include <net/if.h>
   63 #include <net/if_media.h>
   64 #include <net/if_arp.h>
   65 #include <net/if_ether.h>
   66 #include <net/if_llc.h>
   67 
   68 #include <net80211/ieee80211_netbsd.h>
   69 #include <net80211/ieee80211_var.h>
   70 
   71 #include <net/bpf.h>
   72 
   73 #ifdef INET
   74 #include <netinet/in.h> 
   75 #include <net/if_ether.h>
   76 #endif
   77 
   78 #include <net/route.h>
   79 /* XXX tunables */
   80 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS       3       /* pkts / 100ms */
   81 #define HIGH_PRI_SWITCH_THRESH                  10      /* pkts / 100ms */
   82 
   83 #define IEEE80211_RATE2MBS(r)   (((r) & IEEE80211_RATE_VAL) / 2)
   84 
   85 const char *ieee80211_mgt_subtype_name[] = {
   86         "assoc_req",    "assoc_resp",   "reassoc_req",  "reassoc_resp",
   87         "probe_req",    "probe_resp",   "reserved#6",   "reserved#7",
   88         "beacon",       "atim",         "disassoc",     "auth",
   89         "deauth",       "reserved#13",  "reserved#14",  "reserved#15"
   90 };
   91 const char *ieee80211_ctl_subtype_name[] = {
   92         "reserved#0",   "reserved#1",   "reserved#2",   "reserved#3",
   93         "reserved#3",   "reserved#5",   "reserved#6",   "reserved#7",
   94         "reserved#8",   "reserved#9",   "ps_poll",      "rts",
   95         "cts",          "ack",          "cf_end",       "cf_end_ack"
   96 };
   97 const char *ieee80211_state_name[IEEE80211_S_MAX] = {
   98         "INIT",         /* IEEE80211_S_INIT */
   99         "SCAN",         /* IEEE80211_S_SCAN */
  100         "AUTH",         /* IEEE80211_S_AUTH */
  101         "ASSOC",        /* IEEE80211_S_ASSOC */
  102         "RUN"           /* IEEE80211_S_RUN */
  103 };
  104 const char *ieee80211_wme_acnames[] = {
  105         "WME_AC_BE",
  106         "WME_AC_BK",
  107         "WME_AC_VI",
  108         "WME_AC_VO",
  109         "WME_UPSD",
  110 };
  111 
  112 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
  113 
  114 void
  115 ieee80211_proto_attach(struct ieee80211com *ic)
  116 {
  117         struct ifnet *ifp = ic->ic_ifp;
  118 
  119         /* XXX room for crypto  */
  120         ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
  121 
  122         ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
  123         ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
  124         ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
  125         ic->ic_bmiss_max = IEEE80211_BMISS_MAX;
  126         ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT;
  127         ic->ic_protmode = IEEE80211_PROT_CTSONLY;
  128         ic->ic_roaming = IEEE80211_ROAMING_AUTO;
  129 
  130         ic->ic_wme.wme_hipri_switch_hysteresis =
  131                 AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
  132 
  133         /* protocol state change handler */
  134         ic->ic_newstate = ieee80211_newstate;
  135 
  136         /* initialize management frame handlers */
  137         ic->ic_recv_mgmt = ieee80211_recv_mgmt;
  138         ic->ic_send_mgmt = ieee80211_send_mgmt;
  139 }
  140 
  141 void
  142 ieee80211_proto_detach(struct ieee80211com *ic)
  143 {
  144 
  145         /*
  146          * This should not be needed as we detach when resetting
  147          * the state but be conservative here since the
  148          * authenticator may do things like spawn kernel threads.
  149          */
  150         if (ic->ic_auth->ia_detach)
  151                 ic->ic_auth->ia_detach(ic);
  152 
  153         ieee80211_drain_ifq(&ic->ic_mgtq);
  154 
  155         /*
  156          * Detach any ACL'ator.
  157          */
  158         if (ic->ic_acl != NULL)
  159                 ic->ic_acl->iac_detach(ic);
  160 }
  161 
  162 /*
  163  * Simple-minded authenticator module support.
  164  */
  165 
  166 #define IEEE80211_AUTH_MAX      (IEEE80211_AUTH_WPA+1)
  167 /* XXX well-known names */
  168 static const char *auth_modnames[IEEE80211_AUTH_MAX] = {
  169         "wlan_internal",        /* IEEE80211_AUTH_NONE */
  170         "wlan_internal",        /* IEEE80211_AUTH_OPEN */
  171         "wlan_internal",        /* IEEE80211_AUTH_SHARED */
  172         "wlan_xauth",           /* IEEE80211_AUTH_8021X  */
  173         "wlan_internal",        /* IEEE80211_AUTH_AUTO */
  174         "wlan_xauth",           /* IEEE80211_AUTH_WPA */
  175 };
  176 static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];
  177 
  178 static const struct ieee80211_authenticator auth_internal = {
  179         .ia_name                = "wlan_internal",
  180         .ia_attach              = NULL,
  181         .ia_detach              = NULL,
  182         .ia_node_join           = NULL,
  183         .ia_node_leave          = NULL,
  184 };
  185 
  186 /*
  187  * Setup internal authenticators once; they are never unregistered.
  188  */
  189 static void
  190 ieee80211_auth_setup(void)
  191 {
  192         ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal);
  193         ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal);
  194         ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal);
  195 }
  196 
  197 const struct ieee80211_authenticator *
  198 ieee80211_authenticator_get(int auth)
  199 {
  200         static int initialized = 0;
  201         if (!initialized) {
  202                 ieee80211_auth_setup();
  203                 initialized = 1;
  204         }
  205         if (auth >= IEEE80211_AUTH_MAX)
  206                 return NULL;
  207         if (authenticators[auth] == NULL)
  208                 ieee80211_load_module(auth_modnames[auth]);
  209         return authenticators[auth];
  210 }
  211 
  212 void
  213 ieee80211_authenticator_register(int type,
  214         const struct ieee80211_authenticator *auth)
  215 {
  216         if (type >= IEEE80211_AUTH_MAX)
  217                 return;
  218         authenticators[type] = auth;
  219 }
  220 
  221 void
  222 ieee80211_authenticator_unregister(int type)
  223 {
  224 
  225         if (type >= IEEE80211_AUTH_MAX)
  226                 return;
  227         authenticators[type] = NULL;
  228 }
  229 
  230 /*
  231  * Very simple-minded ACL module support.
  232  */
  233 /* XXX just one for now */
  234 static  const struct ieee80211_aclator *acl = NULL;
  235 
  236 void
  237 ieee80211_aclator_register(const struct ieee80211_aclator *iac)
  238 {
  239         printf("wlan: %s acl policy registered\n", iac->iac_name);
  240         acl = iac;
  241 }
  242 
  243 void
  244 ieee80211_aclator_unregister(const struct ieee80211_aclator *iac)
  245 {
  246         if (acl == iac)
  247                 acl = NULL;
  248         printf("wlan: %s acl policy unregistered\n", iac->iac_name);
  249 }
  250 
  251 const struct ieee80211_aclator *
  252 ieee80211_aclator_get(const char *name)
  253 {
  254         if (acl == NULL)
  255                 ieee80211_load_module("wlan_acl");
  256         return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL;
  257 }
  258 
  259 void
  260 ieee80211_print_essid(const u_int8_t *essid, int len)
  261 {
  262         const u_int8_t *p;
  263         int i;
  264 
  265         if (len > IEEE80211_NWID_LEN)
  266                 len = IEEE80211_NWID_LEN;
  267         /* determine printable or not */
  268         for (i = 0, p = essid; i < len; i++, p++) {
  269                 if (*p < ' ' || *p > 0x7e)
  270                         break;
  271         }
  272         if (i == len) {
  273                 printf("\"");
  274                 for (i = 0, p = essid; i < len; i++, p++)
  275                         printf("%c", *p);
  276                 printf("\"");
  277         } else {
  278                 printf("0x");
  279                 for (i = 0, p = essid; i < len; i++, p++)
  280                         printf("%02x", *p);
  281         }
  282 }
  283 
  284 void
  285 ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)
  286 {
  287         const struct ieee80211_frame *wh;
  288         int i;
  289 
  290         wh = (const struct ieee80211_frame *)buf;
  291         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
  292         case IEEE80211_FC1_DIR_NODS:
  293                 printf("NODS %s", ether_sprintf(wh->i_addr2));
  294                 printf("->%s", ether_sprintf(wh->i_addr1));
  295                 printf("(%s)", ether_sprintf(wh->i_addr3));
  296                 break;
  297         case IEEE80211_FC1_DIR_TODS:
  298                 printf("TODS %s", ether_sprintf(wh->i_addr2));
  299                 printf("->%s", ether_sprintf(wh->i_addr3));
  300                 printf("(%s)", ether_sprintf(wh->i_addr1));
  301                 break;
  302         case IEEE80211_FC1_DIR_FROMDS:
  303                 printf("FRDS %s", ether_sprintf(wh->i_addr3));
  304                 printf("->%s", ether_sprintf(wh->i_addr1));
  305                 printf("(%s)", ether_sprintf(wh->i_addr2));
  306                 break;
  307         case IEEE80211_FC1_DIR_DSTODS:
  308                 printf("DSDS %s", ether_sprintf((const u_int8_t *)&wh[1]));
  309                 printf("->%s", ether_sprintf(wh->i_addr3));
  310                 printf("(%s", ether_sprintf(wh->i_addr2));
  311                 printf("->%s)", ether_sprintf(wh->i_addr1));
  312                 break;
  313         }
  314         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
  315         case IEEE80211_FC0_TYPE_DATA:
  316                 printf(" data");
  317                 break;
  318         case IEEE80211_FC0_TYPE_MGT:
  319                 printf(" %s", ieee80211_mgt_subtype_name[
  320                     (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
  321                     >> IEEE80211_FC0_SUBTYPE_SHIFT]);
  322                 break;
  323         default:
  324                 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
  325                 break;
  326         }
  327         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
  328                 printf(" WEP [IV");
  329                 for (i = 0; i < IEEE80211_WEP_IVLEN; i++)
  330                         printf(" %.02x", buf[sizeof(*wh)+i]);
  331                 printf(" KID %u]", buf[sizeof(*wh)+i] >> 6);
  332         }
  333         if (rate >= 0)
  334                 printf(" %dM", rate / 2);
  335         if (rssi >= 0)
  336                 printf(" +%d", rssi);
  337         printf("\n");
  338         if (len > 0) {
  339                 for (i = 0; i < len; i++) {
  340                         if ((i & 1) == 0)
  341                                 printf(" ");
  342                         printf("%02x", buf[i]);
  343                 }
  344                 printf("\n");
  345         }
  346 }
  347 
  348 int
  349 ieee80211_fix_rate(struct ieee80211_node *ni, int flags)
  350 {
  351 #define RV(v)   ((v) & IEEE80211_RATE_VAL)
  352         struct ieee80211com *ic = ni->ni_ic;
  353         int i, j, ignore, error;
  354         int okrate, badrate, fixedrate;
  355         struct ieee80211_rateset *srs, *nrs;
  356         u_int8_t r;
  357 
  358         /*
  359          * If the fixed rate check was requested but no
  360          * fixed has been defined then just remove it.
  361          */
  362         if ((flags & IEEE80211_R_DOFRATE) &&
  363             ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
  364                 flags &= ~IEEE80211_R_DOFRATE;
  365         error = 0;
  366         okrate = badrate = fixedrate = 0;
  367         srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
  368         nrs = &ni->ni_rates;
  369         for (i = 0; i < nrs->rs_nrates; ) {
  370                 ignore = 0;
  371                 if (flags & IEEE80211_R_DOSORT) {
  372                         /*
  373                          * Sort rates.
  374                          */
  375                         for (j = i + 1; j < nrs->rs_nrates; j++) {
  376                                 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) {
  377                                         r = nrs->rs_rates[i];
  378                                         nrs->rs_rates[i] = nrs->rs_rates[j];
  379                                         nrs->rs_rates[j] = r;
  380                                 }
  381                         }
  382                 }
  383                 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
  384                 badrate = r;
  385                 if (flags & IEEE80211_R_DOFRATE) {
  386                         /*
  387                          * Check any fixed rate is included. 
  388                          */
  389                         if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
  390                                 fixedrate = r;
  391                 }
  392                 if (flags & IEEE80211_R_DONEGO) {
  393                         /*
  394                          * Check against supported rates.
  395                          */
  396                         for (j = 0; j < srs->rs_nrates; j++) {
  397                                 if (r == RV(srs->rs_rates[j])) {
  398                                         /*
  399                                          * Overwrite with the supported rate
  400                                          * value so any basic rate bit is set.
  401                                          * This insures that response we send
  402                                          * to stations have the necessary basic
  403                                          * rate bit set.
  404                                          */
  405                                         nrs->rs_rates[i] = srs->rs_rates[j];
  406                                         break;
  407                                 }
  408                         }
  409                         if (j == srs->rs_nrates) {
  410                                 /*
  411                                  * A rate in the node's rate set is not
  412                                  * supported.  If this is a basic rate and we
  413                                  * are operating as an AP then this is an error.
  414                                  * Otherwise we just discard/ignore the rate.
  415                                  * Note that this is important for 11b stations
  416                                  * when they want to associate with an 11g AP.
  417                                  */
  418 #ifndef IEEE80211_NO_HOSTAP
  419                                 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  420                                     (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
  421                                         error++;
  422 #endif /* !IEEE80211_NO_HOSTAP */
  423                                 ignore++;
  424                         }
  425                 }
  426                 if (flags & IEEE80211_R_DODEL) {
  427                         /*
  428                          * Delete unacceptable rates.
  429                          */
  430                         if (ignore) {
  431                                 nrs->rs_nrates--;
  432                                 for (j = i; j < nrs->rs_nrates; j++)
  433                                         nrs->rs_rates[j] = nrs->rs_rates[j + 1];
  434                                 nrs->rs_rates[j] = 0;
  435                                 continue;
  436                         }
  437                 }
  438                 if (!ignore) {
  439                         okrate = nrs->rs_rates[i];
  440                         ni->ni_txrate = i;
  441                 }
  442                 i++;
  443         }
  444         if (okrate == 0 || error != 0 ||
  445             ((flags & IEEE80211_R_DOFRATE) && fixedrate == 0))
  446                 return badrate | IEEE80211_RATE_BASIC;
  447         else
  448                 return RV(okrate);
  449 #undef RV
  450 }
  451 
  452 /*
  453  * Reset 11g-related state.
  454  */
  455 void
  456 ieee80211_reset_erp(struct ieee80211com *ic)
  457 {
  458         ic->ic_flags &= ~IEEE80211_F_USEPROT;
  459         ic->ic_nonerpsta = 0;
  460         ic->ic_longslotsta = 0;
  461         /*
  462          * Short slot time is enabled only when operating in 11g
  463          * and not in an IBSS.  We must also honor whether or not
  464          * the driver is capable of doing it.
  465          */
  466         ieee80211_set_shortslottime(ic,
  467                 ic->ic_curmode == IEEE80211_MODE_11A ||
  468                 (ic->ic_curmode == IEEE80211_MODE_11G &&
  469                 ic->ic_opmode == IEEE80211_M_HOSTAP &&
  470                 (ic->ic_caps & IEEE80211_C_SHSLOT)));
  471         /*
  472          * Set short preamble and ERP barker-preamble flags.
  473          */
  474         if (ic->ic_curmode == IEEE80211_MODE_11A ||
  475             (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) {
  476                 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
  477                 ic->ic_flags &= ~IEEE80211_F_USEBARKER;
  478         } else {
  479                 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
  480                 ic->ic_flags |= IEEE80211_F_USEBARKER;
  481         }
  482 }
  483 
  484 /*
  485  * Set the short slot time state and notify the driver.
  486  */
  487 void
  488 ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
  489 {
  490         if (onoff)
  491                 ic->ic_flags |= IEEE80211_F_SHSLOT;
  492         else
  493                 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
  494         /* notify driver */
  495         if (ic->ic_updateslot != NULL)
  496                 ic->ic_updateslot(ic->ic_ifp);
  497 }
  498 
  499 /*
  500  * Check if the specified rate set supports ERP.
  501  * NB: the rate set is assumed to be sorted.
  502  */
  503 int
  504 ieee80211_iserp_rateset(struct ieee80211com *ic,
  505     struct ieee80211_rateset *rs)
  506 {
  507 #define N(a)    (sizeof(a) / sizeof(a[0]))
  508         static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 };
  509         int i, j;
  510 
  511         if (rs->rs_nrates < N(rates))
  512                 return 0;
  513         for (i = 0; i < N(rates); i++) {
  514                 for (j = 0; j < rs->rs_nrates; j++) {
  515                         int r = rs->rs_rates[j] & IEEE80211_RATE_VAL;
  516                         if (rates[i] == r)
  517                                 goto next;
  518                         if (r > rates[i])
  519                                 return 0;
  520                 }
  521                 return 0;
  522         next:
  523                 ;
  524         }
  525         return 1;
  526 #undef N
  527 }
  528 
  529 /*
  530  * Mark the basic rates for the 11g rate table based on the
  531  * operating mode.  For real 11g we mark all the 11b rates
  532  * and 6, 12, and 24 OFDM.  For 11b compatibility we mark only
  533  * 11b rates.  There's also a pseudo 11a-mode used to mark only
  534  * the basic OFDM rates.
  535  */
  536 void
  537 ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode)
  538 {
  539         static const struct ieee80211_rateset basic[] = {
  540             { .rs_nrates = 0 },         /* IEEE80211_MODE_AUTO */
  541             { 3, { 12, 24, 48 } },      /* IEEE80211_MODE_11A */
  542             { 2, { 2, 4 } },            /* IEEE80211_MODE_11B */
  543             { 4, { 2, 4, 11, 22 } },    /* IEEE80211_MODE_11G (mixed b/g) */
  544             { .rs_nrates = 0 },         /* IEEE80211_MODE_FH */
  545                                         /* IEEE80211_MODE_PUREG (not yet) */
  546             { 7, { 2, 4, 11, 22, 12, 24, 48 } },
  547         };
  548         int i, j;
  549 
  550         for (i = 0; i < rs->rs_nrates; i++) {
  551                 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
  552                 for (j = 0; j < basic[mode].rs_nrates; j++)
  553                         if (basic[mode].rs_rates[j] == rs->rs_rates[i]) {
  554                                 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
  555                                 break;
  556                         }
  557         }
  558 }
  559 
  560 /*
  561  * WME protocol support.  The following parameters come from the spec.
  562  */
  563 typedef struct phyParamType {
  564         u_int8_t aifsn;
  565         u_int8_t logcwmin;
  566         u_int8_t logcwmax;
  567         u_int16_t txopLimit;
  568         u_int8_t acm;
  569 } paramType;
  570 
  571 static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = {
  572         { 3, 4, 6, 0, 0, },             /* IEEE80211_MODE_AUTO */
  573         { 3, 4, 6, 0, 0, },             /* IEEE80211_MODE_11A */ 
  574         { 3, 5, 7, 0, 0, },             /* IEEE80211_MODE_11B */ 
  575         { 3, 4, 6, 0, 0, },             /* IEEE80211_MODE_11G */ 
  576         { 3, 5, 7, 0, 0, },             /* IEEE80211_MODE_FH */ 
  577         { 2, 3, 5, 0, 0, },             /* IEEE80211_MODE_TURBO_A */ 
  578         { 2, 3, 5, 0, 0, },             /* IEEE80211_MODE_TURBO_G */ 
  579 };
  580 static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = {
  581         { 7, 4, 10, 0, 0, },            /* IEEE80211_MODE_AUTO */
  582         { 7, 4, 10, 0, 0, },            /* IEEE80211_MODE_11A */ 
  583         { 7, 5, 10, 0, 0, },            /* IEEE80211_MODE_11B */ 
  584         { 7, 4, 10, 0, 0, },            /* IEEE80211_MODE_11G */ 
  585         { 7, 5, 10, 0, 0, },            /* IEEE80211_MODE_FH */ 
  586         { 7, 3, 10, 0, 0, },            /* IEEE80211_MODE_TURBO_A */ 
  587         { 7, 3, 10, 0, 0, },            /* IEEE80211_MODE_TURBO_G */ 
  588 };
  589 static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = {
  590         { 1, 3, 4,  94, 0, },   /* IEEE80211_MODE_AUTO */
  591         { 1, 3, 4,  94, 0, },   /* IEEE80211_MODE_11A */ 
  592         { 1, 4, 5, 188, 0, },   /* IEEE80211_MODE_11B */ 
  593         { 1, 3, 4,  94, 0, },   /* IEEE80211_MODE_11G */ 
  594         { 1, 4, 5, 188, 0, },   /* IEEE80211_MODE_FH */ 
  595         { 1, 2, 3,  94, 0, },   /* IEEE80211_MODE_TURBO_A */ 
  596         { 1, 2, 3,  94, 0, },   /* IEEE80211_MODE_TURBO_G */ 
  597 };
  598 static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = {
  599         { 1, 2, 3,  47, 0, },   /* IEEE80211_MODE_AUTO */
  600         { 1, 2, 3,  47, 0, },   /* IEEE80211_MODE_11A */ 
  601         { 1, 3, 4, 102, 0, },   /* IEEE80211_MODE_11B */ 
  602         { 1, 2, 3,  47, 0, },   /* IEEE80211_MODE_11G */ 
  603         { 1, 3, 4, 102, 0, },   /* IEEE80211_MODE_FH */ 
  604         { 1, 2, 2,  47, 0, },   /* IEEE80211_MODE_TURBO_A */ 
  605         { 1, 2, 2,  47, 0, },   /* IEEE80211_MODE_TURBO_G */ 
  606 };
  607 
  608 static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = {
  609         { 3, 4, 10, 0, 0, },            /* IEEE80211_MODE_AUTO */
  610         { 3, 4, 10, 0, 0, },            /* IEEE80211_MODE_11A */ 
  611         { 3, 5, 10, 0, 0, },            /* IEEE80211_MODE_11B */ 
  612         { 3, 4, 10, 0, 0, },            /* IEEE80211_MODE_11G */ 
  613         { 3, 5, 10, 0, 0, },            /* IEEE80211_MODE_FH */ 
  614         { 2, 3, 10, 0, 0, },            /* IEEE80211_MODE_TURBO_A */ 
  615         { 2, 3, 10, 0, 0, },            /* IEEE80211_MODE_TURBO_G */ 
  616 };
  617 static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = {
  618         { 2, 3, 4,  94, 0, },   /* IEEE80211_MODE_AUTO */
  619         { 2, 3, 4,  94, 0, },   /* IEEE80211_MODE_11A */ 
  620         { 2, 4, 5, 188, 0, },   /* IEEE80211_MODE_11B */ 
  621         { 2, 3, 4,  94, 0, },   /* IEEE80211_MODE_11G */ 
  622         { 2, 4, 5, 188, 0, },   /* IEEE80211_MODE_FH */ 
  623         { 2, 2, 3,  94, 0, },   /* IEEE80211_MODE_TURBO_A */ 
  624         { 2, 2, 3,  94, 0, },   /* IEEE80211_MODE_TURBO_G */ 
  625 };
  626 static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = {
  627         { 2, 2, 3,  47, 0, },   /* IEEE80211_MODE_AUTO */
  628         { 2, 2, 3,  47, 0, },   /* IEEE80211_MODE_11A */ 
  629         { 2, 3, 4, 102, 0, },   /* IEEE80211_MODE_11B */ 
  630         { 2, 2, 3,  47, 0, },   /* IEEE80211_MODE_11G */ 
  631         { 2, 3, 4, 102, 0, },   /* IEEE80211_MODE_FH */ 
  632         { 1, 2, 2,  47, 0, },   /* IEEE80211_MODE_TURBO_A */ 
  633         { 1, 2, 2,  47, 0, },   /* IEEE80211_MODE_TURBO_G */ 
  634 };
  635 
  636 void
  637 ieee80211_wme_initparams(struct ieee80211com *ic)
  638 {
  639         struct ieee80211_wme_state *wme = &ic->ic_wme;
  640         const paramType *pPhyParam, *pBssPhyParam;
  641         struct wmeParams *wmep;
  642         int i;
  643 
  644         if ((ic->ic_caps & IEEE80211_C_WME) == 0)
  645                 return;
  646 
  647         for (i = 0; i < WME_NUM_AC; i++) {
  648                 switch (i) {
  649                 case WME_AC_BK:
  650                         pPhyParam = &phyParamForAC_BK[ic->ic_curmode];
  651                         pBssPhyParam = &phyParamForAC_BK[ic->ic_curmode];
  652                         break;
  653                 case WME_AC_VI:
  654                         pPhyParam = &phyParamForAC_VI[ic->ic_curmode];
  655                         pBssPhyParam = &bssPhyParamForAC_VI[ic->ic_curmode];
  656                         break;
  657                 case WME_AC_VO:
  658                         pPhyParam = &phyParamForAC_VO[ic->ic_curmode];
  659                         pBssPhyParam = &bssPhyParamForAC_VO[ic->ic_curmode];
  660                         break;
  661                 case WME_AC_BE:
  662                 default:
  663                         pPhyParam = &phyParamForAC_BE[ic->ic_curmode];
  664                         pBssPhyParam = &bssPhyParamForAC_BE[ic->ic_curmode];
  665                         break;
  666                 }
  667 
  668                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
  669                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  670                         wmep->wmep_acm = pPhyParam->acm;
  671                         wmep->wmep_aifsn = pPhyParam->aifsn;
  672                         wmep->wmep_logcwmin = pPhyParam->logcwmin;
  673                         wmep->wmep_logcwmax = pPhyParam->logcwmax;
  674                         wmep->wmep_txopLimit = pPhyParam->txopLimit;
  675                 } else {
  676                         wmep->wmep_acm = pBssPhyParam->acm;
  677                         wmep->wmep_aifsn = pBssPhyParam->aifsn;
  678                         wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
  679                         wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
  680                         wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
  681 
  682                 }       
  683                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  684                         "%s: %s chan [acm %u aifsn %u log2(cwmin) %u "
  685                         "log2(cwmax) %u txpoLimit %u]\n", __func__
  686                         , ieee80211_wme_acnames[i]
  687                         , wmep->wmep_acm
  688                         , wmep->wmep_aifsn
  689                         , wmep->wmep_logcwmin
  690                         , wmep->wmep_logcwmax
  691                         , wmep->wmep_txopLimit
  692                 );
  693 
  694                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
  695                 wmep->wmep_acm = pBssPhyParam->acm;
  696                 wmep->wmep_aifsn = pBssPhyParam->aifsn;
  697                 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
  698                 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
  699                 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
  700                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  701                         "%s: %s  bss [acm %u aifsn %u log2(cwmin) %u "
  702                         "log2(cwmax) %u txpoLimit %u]\n", __func__
  703                         , ieee80211_wme_acnames[i]
  704                         , wmep->wmep_acm
  705                         , wmep->wmep_aifsn
  706                         , wmep->wmep_logcwmin
  707                         , wmep->wmep_logcwmax
  708                         , wmep->wmep_txopLimit
  709                 );
  710         }
  711         /* NB: check ic_bss to avoid NULL deref on initial attach */
  712         if (ic->ic_bss != NULL) {
  713                 /*
  714                  * Calculate aggressive mode switching threshold based
  715                  * on beacon interval.  This doesn't need locking since
  716                  * we're only called before entering the RUN state at
  717                  * which point we start sending beacon frames.
  718                  */
  719                 wme->wme_hipri_switch_thresh =
  720                         (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100;
  721                 ieee80211_wme_updateparams(ic);
  722         }
  723 }
  724 
  725 /*
  726  * Update WME parameters for ourself and the BSS.
  727  */
  728 void
  729 ieee80211_wme_updateparams_locked(struct ieee80211com *ic)
  730 {
  731         static const paramType phyParam[IEEE80211_MODE_MAX] = {
  732                 { 2, 4, 10, 64, 0, },   /* IEEE80211_MODE_AUTO */ 
  733                 { 2, 4, 10, 64, 0, },   /* IEEE80211_MODE_11A */ 
  734                 { 2, 5, 10, 64, 0, },   /* IEEE80211_MODE_11B */ 
  735                 { 2, 4, 10, 64, 0, },   /* IEEE80211_MODE_11G */ 
  736                 { 2, 5, 10, 64, 0, },   /* IEEE80211_MODE_FH */ 
  737                 { 1, 3, 10, 64, 0, },   /* IEEE80211_MODE_TURBO_A */ 
  738                 { 1, 3, 10, 64, 0, },   /* IEEE80211_MODE_TURBO_G */ 
  739         };
  740         struct ieee80211_wme_state *wme = &ic->ic_wme;
  741         const struct wmeParams *wmep;
  742         struct wmeParams *chanp, *bssp;
  743         int i;
  744 
  745         /* set up the channel access parameters for the physical device */
  746         for (i = 0; i < WME_NUM_AC; i++) {
  747                 chanp = &wme->wme_chanParams.cap_wmeParams[i];
  748                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
  749                 chanp->wmep_aifsn = wmep->wmep_aifsn;
  750                 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
  751                 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
  752                 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
  753 
  754                 chanp = &wme->wme_bssChanParams.cap_wmeParams[i];
  755                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
  756                 chanp->wmep_aifsn = wmep->wmep_aifsn;
  757                 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
  758                 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
  759                 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
  760         }
  761 
  762         /*
  763          * This implements aggressive mode as found in certain
  764          * vendors' AP's.  When there is significant high
  765          * priority (VI/VO) traffic in the BSS throttle back BE
  766          * traffic by using conservative parameters.  Otherwise
  767          * BE uses aggressive params to optimize performance of
  768          * legacy/non-QoS traffic.
  769          */
  770         if ((ic->ic_opmode == IEEE80211_M_HOSTAP &&
  771              (wme->wme_flags & WME_F_AGGRMODE) == 0) ||
  772             (ic->ic_opmode != IEEE80211_M_HOSTAP &&
  773              (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) ||
  774             (ic->ic_flags & IEEE80211_F_WME) == 0) {
  775                 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
  776                 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
  777 
  778                 chanp->wmep_aifsn = bssp->wmep_aifsn =
  779                         phyParam[ic->ic_curmode].aifsn;
  780                 chanp->wmep_logcwmin = bssp->wmep_logcwmin =
  781                         phyParam[ic->ic_curmode].logcwmin;
  782                 chanp->wmep_logcwmax = bssp->wmep_logcwmax =
  783                         phyParam[ic->ic_curmode].logcwmax;
  784                 chanp->wmep_txopLimit = bssp->wmep_txopLimit =
  785                         (ic->ic_caps & IEEE80211_C_BURST) ?
  786                                 phyParam[ic->ic_curmode].txopLimit : 0;
  787                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  788                         "%s: %s [acm %u aifsn %u log2(cwmin) %u "
  789                         "log2(cwmax) %u txpoLimit %u]\n", __func__
  790                         , ieee80211_wme_acnames[WME_AC_BE]
  791                         , chanp->wmep_acm
  792                         , chanp->wmep_aifsn
  793                         , chanp->wmep_logcwmin
  794                         , chanp->wmep_logcwmax
  795                         , chanp->wmep_txopLimit
  796                 );
  797         }
  798         
  799 #ifndef IEEE80211_NO_HOSTAP
  800         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  801             ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) == 0) {
  802                 static const u_int8_t logCwMin[IEEE80211_MODE_MAX] = {
  803                         3,      /* IEEE80211_MODE_AUTO */
  804                         3,      /* IEEE80211_MODE_11A */
  805                         4,      /* IEEE80211_MODE_11B */
  806                         3,      /* IEEE80211_MODE_11G */
  807                         4,      /* IEEE80211_MODE_FH */
  808                         3,      /* IEEE80211_MODE_TURBO_A */
  809                         3,      /* IEEE80211_MODE_TURBO_G */
  810                 };
  811                 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
  812                 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
  813 
  814                 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 
  815                         logCwMin[ic->ic_curmode];
  816                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  817                         "%s: %s log2(cwmin) %u\n", __func__
  818                         , ieee80211_wme_acnames[WME_AC_BE]
  819                         , chanp->wmep_logcwmin
  820                 );
  821         }       
  822         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {      /* XXX ibss? */
  823                 /*
  824                  * Arrange for a beacon update and bump the parameter
  825                  * set number so associated stations load the new values.
  826                  */
  827                 wme->wme_bssChanParams.cap_info =
  828                         (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
  829                 ic->ic_flags |= IEEE80211_F_WMEUPDATE;
  830         }
  831 #endif /* !IEEE80211_NO_HOSTAP */
  832 
  833         wme->wme_update(ic);
  834 
  835         IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
  836                 "%s: WME params updated, cap_info 0x%x\n", __func__,
  837                 ic->ic_opmode == IEEE80211_M_STA ?
  838                         wme->wme_wmeChanParams.cap_info :
  839                         wme->wme_bssChanParams.cap_info);
  840 }
  841 
  842 void
  843 ieee80211_wme_updateparams(struct ieee80211com *ic)
  844 {
  845 
  846         if (ic->ic_caps & IEEE80211_C_WME) {
  847                 IEEE80211_BEACON_LOCK(ic);
  848                 ieee80211_wme_updateparams_locked(ic);
  849                 IEEE80211_BEACON_UNLOCK(ic);
  850         }
  851 }
  852 
  853 #ifndef IEEE80211_NO_HOSTAP
  854 static void
  855 sta_disassoc(void *arg, struct ieee80211_node *ni)
  856 {
  857         struct ieee80211com *ic = arg;
  858 
  859         if (ni->ni_associd != 0) {
  860                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
  861                         IEEE80211_REASON_ASSOC_LEAVE);
  862                 ieee80211_node_leave(ic, ni);
  863         }
  864 }
  865 #endif /* !IEEE80211_NO_HOSTAP */
  866 
  867 void
  868 ieee80211_beacon_miss(struct ieee80211com *ic)
  869 {
  870 
  871         if (ic->ic_flags & IEEE80211_F_SCAN) {
  872                 /* XXX check ic_curchan != ic_bsschan? */
  873                 return;
  874         }
  875         IEEE80211_DPRINTF(ic,
  876                 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
  877                 "%s\n", "beacon miss");
  878 
  879         /*
  880          * Our handling is only meaningful for stations that are
  881          * associated; any other conditions else will be handled
  882          * through different means (e.g. the tx timeout on mgt frames).
  883          */
  884         if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN)
  885                 return;
  886 
  887         if (++ic->ic_bmiss_count < ic->ic_bmiss_max) {
  888                 /*
  889                  * Send a directed probe req before falling back to a scan;
  890                  * if we receive a response ic_bmiss_count will be reset.
  891                  * Some cards mistakenly report beacon miss so this avoids
  892                  * the expensive scan if the ap is still there.
  893                  */
  894                 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr,
  895                         ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid,
  896                         ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen,
  897                         ic->ic_opt_ie, ic->ic_opt_ie_len);
  898                 return;
  899         }
  900         ic->ic_bmiss_count = 0;
  901         ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
  902 }
  903 
  904 #ifndef IEEE80211_NO_HOSTAP
  905 static void
  906 sta_deauth(void *arg, struct ieee80211_node *ni)
  907 {
  908         struct ieee80211com *ic = arg;
  909 
  910         IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
  911                 IEEE80211_REASON_ASSOC_LEAVE);
  912 }
  913 #endif /* !IEEE80211_NO_HOSTAP */
  914 
  915 static int
  916 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
  917 {
  918         struct ifnet *ifp = ic->ic_ifp;
  919         struct ieee80211_node *ni;
  920         enum ieee80211_state ostate;
  921 
  922         KASSERT(!cpu_intr_p());
  923 
  924         ostate = ic->ic_state;
  925         IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
  926                 ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
  927         ic->ic_state = nstate;                  /* state transition */
  928         ni = ic->ic_bss;                        /* NB: no reference held */
  929         switch (nstate) {
  930         case IEEE80211_S_INIT:
  931                 switch (ostate) {
  932                 case IEEE80211_S_INIT:
  933                         break;
  934                 case IEEE80211_S_RUN:
  935                         switch (ic->ic_opmode) {
  936                         case IEEE80211_M_STA:
  937                                 IEEE80211_SEND_MGMT(ic, ni,
  938                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
  939                                     IEEE80211_REASON_ASSOC_LEAVE);
  940                                 ieee80211_sta_leave(ic, ni);
  941                                 break;
  942                         case IEEE80211_M_HOSTAP:
  943 #ifndef IEEE80211_NO_HOSTAP
  944                                 ieee80211_iterate_nodes(&ic->ic_sta,
  945                                         sta_disassoc, ic);
  946 #endif /* !IEEE80211_NO_HOSTAP */
  947                                 break;
  948                         default:
  949                                 break;
  950                         }
  951                         goto reset;
  952                 case IEEE80211_S_ASSOC:
  953                         switch (ic->ic_opmode) {
  954                         case IEEE80211_M_STA:
  955                                 IEEE80211_SEND_MGMT(ic, ni,
  956                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
  957                                     IEEE80211_REASON_AUTH_LEAVE);
  958                                 break;
  959                         case IEEE80211_M_HOSTAP:
  960 #ifndef IEEE80211_NO_HOSTAP
  961                                 ieee80211_iterate_nodes(&ic->ic_sta,
  962                                         sta_deauth, ic);
  963 #endif /* !IEEE80211_NO_HOSTAP */
  964                                 break;
  965                         default:
  966                                 break;
  967                         }
  968                         goto reset;
  969                 case IEEE80211_S_SCAN:
  970                         ieee80211_cancel_scan(ic);
  971                         goto reset;
  972                 case IEEE80211_S_AUTH:
  973                 reset:
  974                         ic->ic_mgt_timer = 0;
  975                         ieee80211_drain_ifq(&ic->ic_mgtq);
  976                         ieee80211_reset_bss(ic);
  977                         break;
  978                 }
  979                 if (ic->ic_auth->ia_detach != NULL)
  980                         ic->ic_auth->ia_detach(ic);
  981                 break;
  982         case IEEE80211_S_SCAN:
  983                 switch (ostate) {
  984                 case IEEE80211_S_INIT:
  985                         if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
  986                              ic->ic_opmode == IEEE80211_M_IBSS ||
  987                              ic->ic_opmode == IEEE80211_M_AHDEMO) &&
  988                             ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
  989                                 /*
  990                                  * AP operation and we already have a channel;
  991                                  * bypass the scan and startup immediately.
  992                                  */
  993                                 ieee80211_create_ibss(ic, ic->ic_des_chan);
  994                         } else {
  995                                 ieee80211_begin_scan(ic, arg);
  996                         }
  997                         break;
  998                 case IEEE80211_S_SCAN:
  999                         /*
 1000                          * Scan next. If doing an active scan probe
 1001                          * for the requested ap (if any).
 1002                          */
 1003                         if (ic->ic_flags & IEEE80211_F_ASCAN)
 1004                                 ieee80211_probe_curchan(ic, 0);
 1005                         break;
 1006                 case IEEE80211_S_RUN:
 1007                         /* beacon miss */
 1008                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE,
 1009                                 "no recent beacons from %s; rescanning\n",
 1010                                 ether_sprintf(ic->ic_bss->ni_bssid));
 1011                         ieee80211_sta_leave(ic, ni);
 1012                         ic->ic_flags &= ~IEEE80211_F_SIBSS;     /* XXX */
 1013                         /* FALLTHRU */
 1014                 case IEEE80211_S_AUTH:
 1015                 case IEEE80211_S_ASSOC:
 1016                         /* timeout restart scan */
 1017                         ni = ieee80211_find_node(&ic->ic_scan,
 1018                                 ic->ic_bss->ni_macaddr);
 1019                         if (ni != NULL) {
 1020                                 ni->ni_fails++;
 1021                                 ieee80211_unref_node(&ni);
 1022                         }
 1023                         if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
 1024                                 ieee80211_begin_scan(ic, arg);
 1025                         break;
 1026                 }
 1027                 break;
 1028         case IEEE80211_S_AUTH:
 1029                 switch (ostate) {
 1030                 case IEEE80211_S_INIT:
 1031                 case IEEE80211_S_SCAN:
 1032                         IEEE80211_SEND_MGMT(ic, ni,
 1033                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
 1034                         break;
 1035                 case IEEE80211_S_AUTH:
 1036                 case IEEE80211_S_ASSOC:
 1037                         switch (arg) {
 1038                         case IEEE80211_FC0_SUBTYPE_AUTH:
 1039                                 /* ??? */
 1040                                 IEEE80211_SEND_MGMT(ic, ni,
 1041                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
 1042                                 break;
 1043                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1044                                 /* ignore and retry scan on timeout */
 1045                                 break;
 1046                         }
 1047                         break;
 1048                 case IEEE80211_S_RUN:
 1049                         switch (arg) {
 1050                         case IEEE80211_FC0_SUBTYPE_AUTH:
 1051                                 IEEE80211_SEND_MGMT(ic, ni,
 1052                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
 1053                                 ic->ic_state = ostate;  /* stay RUN */
 1054                                 break;
 1055                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1056                                 ieee80211_sta_leave(ic, ni);
 1057                                 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
 1058                                         /* try to reauth */
 1059                                         IEEE80211_SEND_MGMT(ic, ni,
 1060                                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
 1061                                 }
 1062                                 break;
 1063                         }
 1064                         break;
 1065                 }
 1066                 break;
 1067         case IEEE80211_S_ASSOC:
 1068                 switch (ostate) {
 1069                 case IEEE80211_S_INIT:
 1070                 case IEEE80211_S_SCAN:
 1071                 case IEEE80211_S_ASSOC:
 1072                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1073                                 "%s: invalid transition\n", __func__);
 1074                         break;
 1075                 case IEEE80211_S_AUTH:
 1076                         IEEE80211_SEND_MGMT(ic, ni,
 1077                             IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
 1078                         break;
 1079                 case IEEE80211_S_RUN:
 1080                         ieee80211_sta_leave(ic, ni);
 1081                         if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
 1082                                 IEEE80211_SEND_MGMT(ic, ni,
 1083                                     IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
 1084                         }
 1085                         break;
 1086                 }
 1087                 break;
 1088         case IEEE80211_S_RUN:
 1089                 if (ic->ic_flags & IEEE80211_F_WPA) {
 1090                         /* XXX validate prerequisites */
 1091                 }
 1092                 switch (ostate) {
 1093                 case IEEE80211_S_INIT:
 1094                         if (ic->ic_opmode == IEEE80211_M_MONITOR)
 1095                                 break;
 1096                         /* fall thru... */
 1097                 case IEEE80211_S_AUTH:
 1098                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1099                                 "%s: invalid transition\n", __func__);
 1100                         /* fall thru... */
 1101                 case IEEE80211_S_RUN:
 1102                         break;
 1103                 case IEEE80211_S_SCAN:          /* adhoc/hostap mode */
 1104                 case IEEE80211_S_ASSOC:         /* infra mode */
 1105                         IASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,
 1106                                 ("%s: bogus xmit rate %u setup ostate %x "
 1107                                  "nstate %x\n", __func__, ni->ni_txrate,
 1108                                  ostate, nstate));
 1109 #ifdef IEEE80211_DEBUG
 1110                         if (ieee80211_msg_debug(ic)) {
 1111                                 if (ic->ic_opmode == IEEE80211_M_STA)
 1112                                         if_printf(ifp, "associated ");
 1113                                 else
 1114                                         if_printf(ifp, "synchronized ");
 1115                                 printf("with %s ssid ",
 1116                                     ether_sprintf(ni->ni_bssid));
 1117                                 ieee80211_print_essid(ic->ic_bss->ni_essid,
 1118                                     ni->ni_esslen);
 1119                                 printf(" channel %d start %uMb\n",
 1120                                         ieee80211_chan2ieee(ic, ic->ic_curchan),
 1121                                         IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
 1122                         }
 1123 #endif
 1124                         ic->ic_mgt_timer = 0;
 1125                         if (ic->ic_opmode == IEEE80211_M_STA)
 1126                                 ieee80211_notify_node_join(ic, ni, 
 1127                                         arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
 1128                         if_start_lock(ifp);     /* XXX not authorized yet */
 1129                         break;
 1130                 }
 1131                 /*
 1132                  * Start/stop the authenticator when operating as an
 1133                  * AP.  We delay until here to allow configuration to
 1134                  * happen out of order.
 1135                  */
 1136                 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */
 1137                     ic->ic_auth->ia_attach != NULL) {
 1138                         /* XXX check failure */
 1139                         ic->ic_auth->ia_attach(ic);
 1140                 } else if (ic->ic_auth->ia_detach != NULL) {
 1141                         ic->ic_auth->ia_detach(ic);
 1142                 }
 1143                 /*
 1144                  * When 802.1x is not in use mark the port authorized
 1145                  * at this point so traffic can flow.
 1146                  */
 1147                 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
 1148                         ieee80211_node_authorize(ni);
 1149                 /*
 1150                  * Enable inactivity processing.
 1151                  * XXX
 1152                  */
 1153                 ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT;
 1154                 ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT;
 1155                 break;
 1156         }
 1157         return 0;
 1158 }

Cache object: df834053b0441bf8d8a8abb1aa0c154a


[ 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.