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

Cache object: 976916564426fb19aae8649c9116516e


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