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.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, 2003 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/5.2/sys/net80211/ieee80211.c 120067 2003-09-14 22:32:18Z sam $");
   35 
   36 /*
   37  * IEEE 802.11 generic handler
   38  */
   39 
   40 #include "opt_inet.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h> 
   44 #include <sys/mbuf.h>   
   45 #include <sys/malloc.h>
   46 #include <sys/kernel.h>
   47 #include <sys/socket.h>
   48 #include <sys/sockio.h>
   49 #include <sys/endian.h>
   50 #include <sys/errno.h>
   51 #include <sys/bus.h>
   52 #include <sys/proc.h>
   53 #include <sys/sysctl.h>
   54 
   55 #include <machine/atomic.h>
   56  
   57 #include <net/if.h>
   58 #include <net/if_dl.h>
   59 #include <net/if_media.h>
   60 #include <net/if_arp.h>
   61 #include <net/ethernet.h>
   62 #include <net/if_llc.h>
   63 
   64 #include <net80211/ieee80211_var.h>
   65 
   66 #include <net/bpf.h>
   67 
   68 #ifdef INET
   69 #include <netinet/in.h> 
   70 #include <netinet/if_ether.h>
   71 #endif
   72 
   73 #ifdef IEEE80211_DEBUG
   74 int     ieee80211_debug = 0;
   75 SYSCTL_INT(_debug, OID_AUTO, ieee80211, CTLFLAG_RW, &ieee80211_debug,
   76             0, "IEEE 802.11 media debugging printfs");
   77 #endif
   78 
   79 static void ieee80211_set11gbasicrates(struct ieee80211_rateset *,
   80                 enum ieee80211_phymode);
   81 
   82 static const char *ieee80211_phymode_name[] = {
   83         "auto",         /* IEEE80211_MODE_AUTO */
   84         "11a",          /* IEEE80211_MODE_11A */
   85         "11b",          /* IEEE80211_MODE_11B */
   86         "11g",          /* IEEE80211_MODE_11G */
   87         "turbo",        /* IEEE80211_MODE_TURBO */
   88 };
   89 
   90 void
   91 ieee80211_ifattach(struct ifnet *ifp)
   92 {
   93         struct ieee80211com *ic = (void *)ifp;
   94         struct ieee80211_channel *c;
   95         int i;
   96 
   97         ether_ifattach(ifp, ic->ic_myaddr);
   98         bpfattach2(ifp, DLT_IEEE802_11,
   99             sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
  100         ieee80211_crypto_attach(ifp);
  101 
  102         /*
  103          * Fill in 802.11 available channel set, mark
  104          * all available channels as active, and pick
  105          * a default channel if not already specified.
  106          */
  107         memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
  108         ic->ic_modecaps |= 1<<IEEE80211_MODE_AUTO;
  109         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  110                 c = &ic->ic_channels[i];
  111                 if (c->ic_flags) {
  112                         /*
  113                          * Verify driver passed us valid data.
  114                          */
  115                         if (i != ieee80211_chan2ieee(ic, c)) {
  116                                 if_printf(ifp, "bad channel ignored; "
  117                                         "freq %u flags %x number %u\n",
  118                                         c->ic_freq, c->ic_flags, i);
  119                                 c->ic_flags = 0;        /* NB: remove */
  120                                 continue;
  121                         }
  122                         setbit(ic->ic_chan_avail, i);
  123                         /*
  124                          * Identify mode capabilities.
  125                          */
  126                         if (IEEE80211_IS_CHAN_A(c))
  127                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11A;
  128                         if (IEEE80211_IS_CHAN_B(c))
  129                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;
  130                         if (IEEE80211_IS_CHAN_PUREG(c))
  131                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;
  132                         if (IEEE80211_IS_CHAN_T(c))
  133                                 ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO;
  134                 }
  135         }
  136         /* validate ic->ic_curmode */
  137         if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0)
  138                 ic->ic_curmode = IEEE80211_MODE_AUTO;
  139 
  140         (void) ieee80211_setmode(ic, ic->ic_curmode);
  141 
  142         ic->ic_des_chan = IEEE80211_CHAN_ANYC;  /* any channel is ok */
  143         if (ic->ic_lintval == 0)
  144                 ic->ic_lintval = 100;           /* default sleep */
  145         ic->ic_bmisstimeout = 7*ic->ic_lintval; /* default 7 beacons */
  146 
  147         ieee80211_node_attach(ifp);
  148         ieee80211_proto_attach(ifp);
  149 }
  150 
  151 void
  152 ieee80211_ifdetach(struct ifnet *ifp)
  153 {
  154         struct ieee80211com *ic = (void *)ifp;
  155 
  156         ieee80211_proto_detach(ifp);
  157         ieee80211_crypto_detach(ifp);
  158         ieee80211_node_detach(ifp);
  159         ifmedia_removeall(&ic->ic_media);
  160         bpfdetach(ifp);
  161         ether_ifdetach(ifp);
  162 }
  163 
  164 /*
  165  * Convert MHz frequency to IEEE channel number.
  166  */
  167 u_int
  168 ieee80211_mhz2ieee(u_int freq, u_int flags)
  169 {
  170         if (flags & IEEE80211_CHAN_2GHZ) {      /* 2GHz band */
  171                 if (freq == 2484)
  172                         return 14;
  173                 if (freq < 2484)
  174                         return (freq - 2407) / 5;
  175                 else
  176                         return 15 + ((freq - 2512) / 20);
  177         } else if (flags & IEEE80211_CHAN_5GHZ) {       /* 5Ghz band */
  178                 return (freq - 5000) / 5;
  179         } else {                                /* either, guess */
  180                 if (freq == 2484)
  181                         return 14;
  182                 if (freq < 2484)
  183                         return (freq - 2407) / 5;
  184                 if (freq < 5000)
  185                         return 15 + ((freq - 2512) / 20);
  186                 return (freq - 5000) / 5;
  187         }
  188 }
  189 
  190 /*
  191  * Convert channel to IEEE channel number.
  192  */
  193 u_int
  194 ieee80211_chan2ieee(struct ieee80211com *ic, struct ieee80211_channel *c)
  195 {
  196         if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX])
  197                 return c - ic->ic_channels;
  198         else if (c == IEEE80211_CHAN_ANYC)
  199                 return IEEE80211_CHAN_ANY;
  200         else if (c != NULL) {
  201                 if_printf(&ic->ic_if, "invalid channel freq %u flags %x\n",
  202                         c->ic_freq, c->ic_flags);
  203                 return 0;               /* XXX */
  204         } else {
  205                 if_printf(&ic->ic_if, "invalid channel (NULL)\n");
  206                 return 0;               /* XXX */
  207         }
  208 }
  209 
  210 /*
  211  * Convert IEEE channel number to MHz frequency.
  212  */
  213 u_int
  214 ieee80211_ieee2mhz(u_int chan, u_int flags)
  215 {
  216         if (flags & IEEE80211_CHAN_2GHZ) {      /* 2GHz band */
  217                 if (chan == 14)
  218                         return 2484;
  219                 if (chan < 14)
  220                         return 2407 + chan*5;
  221                 else
  222                         return 2512 + ((chan-15)*20);
  223         } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */
  224                 return 5000 + (chan*5);
  225         } else {                                /* either, guess */
  226                 if (chan == 14)
  227                         return 2484;
  228                 if (chan < 14)                  /* 0-13 */
  229                         return 2407 + chan*5;
  230                 if (chan < 27)                  /* 15-26 */
  231                         return 2512 + ((chan-15)*20);
  232                 return 5000 + (chan*5);
  233         }
  234 }
  235 
  236 /*
  237  * Setup the media data structures according to the channel and
  238  * rate tables.  This must be called by the driver after
  239  * ieee80211_attach and before most anything else.
  240  */
  241 void
  242 ieee80211_media_init(struct ifnet *ifp,
  243         ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
  244 {
  245 #define ADD(_ic, _s, _o) \
  246         ifmedia_add(&(_ic)->ic_media, \
  247                 IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
  248         struct ieee80211com *ic = (void *)ifp;
  249         struct ifmediareq imr;
  250         int i, j, mode, rate, maxrate, mword, mopt, r;
  251         struct ieee80211_rateset *rs;
  252         struct ieee80211_rateset allrates;
  253 
  254         /*
  255          * Do late attach work that must wait for any subclass
  256          * (i.e. driver) work such as overriding methods.
  257          */
  258         ieee80211_node_lateattach(ifp);
  259 
  260         /*
  261          * Fill in media characteristics.
  262          */
  263         ifmedia_init(&ic->ic_media, 0, media_change, media_stat);
  264         maxrate = 0;
  265         memset(&allrates, 0, sizeof(allrates));
  266         for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) {
  267                 static const u_int mopts[] = { 
  268                         IFM_AUTO,
  269                         IFM_MAKEMODE(IFM_IEEE80211_11A),
  270                         IFM_MAKEMODE(IFM_IEEE80211_11B),
  271                         IFM_MAKEMODE(IFM_IEEE80211_11G),
  272                         IFM_MAKEMODE(IFM_IEEE80211_11A) | IFM_IEEE80211_TURBO,
  273                 };
  274                 if ((ic->ic_modecaps & (1<<mode)) == 0)
  275                         continue;
  276                 mopt = mopts[mode];
  277                 ADD(ic, IFM_AUTO, mopt);        /* e.g. 11a auto */
  278                 if (ic->ic_caps & IEEE80211_C_IBSS)
  279                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC);
  280                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  281                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);
  282                 if (ic->ic_caps & IEEE80211_C_AHDEMO)
  283                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0);
  284                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  285                         ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);
  286                 if (mode == IEEE80211_MODE_AUTO)
  287                         continue;
  288                 if_printf(ifp, "%s rates: ", ieee80211_phymode_name[mode]);
  289                 rs = &ic->ic_sup_rates[mode];
  290                 for (i = 0; i < rs->rs_nrates; i++) {
  291                         rate = rs->rs_rates[i];
  292                         mword = ieee80211_rate2media(ic, rate, mode);
  293                         if (mword == 0)
  294                                 continue;
  295                         printf("%s%d%sMbps", (i != 0 ? " " : ""),
  296                             (rate & IEEE80211_RATE_VAL) / 2,
  297                             ((rate & 0x1) != 0 ? ".5" : ""));
  298                         ADD(ic, mword, mopt);
  299                         if (ic->ic_caps & IEEE80211_C_IBSS)
  300                                 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC);
  301                         if (ic->ic_caps & IEEE80211_C_HOSTAP)
  302                                 ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP);
  303                         if (ic->ic_caps & IEEE80211_C_AHDEMO)
  304                                 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0);
  305                         if (ic->ic_caps & IEEE80211_C_MONITOR)
  306                                 ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR);
  307                         /*
  308                          * Add rate to the collection of all rates.
  309                          */
  310                         r = rate & IEEE80211_RATE_VAL;
  311                         for (j = 0; j < allrates.rs_nrates; j++)
  312                                 if (allrates.rs_rates[j] == r)
  313                                         break;
  314                         if (j == allrates.rs_nrates) {
  315                                 /* unique, add to the set */
  316                                 allrates.rs_rates[j] = r;
  317                                 allrates.rs_nrates++;
  318                         }
  319                         rate = (rate & IEEE80211_RATE_VAL) / 2;
  320                         if (rate > maxrate)
  321                                 maxrate = rate;
  322                 }
  323                 printf("\n");
  324         }
  325         for (i = 0; i < allrates.rs_nrates; i++) {
  326                 mword = ieee80211_rate2media(ic, allrates.rs_rates[i],
  327                                 IEEE80211_MODE_AUTO);
  328                 if (mword == 0)
  329                         continue;
  330                 mword = IFM_SUBTYPE(mword);     /* remove media options */
  331                 ADD(ic, mword, 0);
  332                 if (ic->ic_caps & IEEE80211_C_IBSS)
  333                         ADD(ic, mword, IFM_IEEE80211_ADHOC);
  334                 if (ic->ic_caps & IEEE80211_C_HOSTAP)
  335                         ADD(ic, mword, IFM_IEEE80211_HOSTAP);
  336                 if (ic->ic_caps & IEEE80211_C_AHDEMO)
  337                         ADD(ic, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0);
  338                 if (ic->ic_caps & IEEE80211_C_MONITOR)
  339                         ADD(ic, mword, IFM_IEEE80211_MONITOR);
  340         }
  341         ieee80211_media_status(ifp, &imr);
  342         ifmedia_set(&ic->ic_media, imr.ifm_active);
  343 
  344         if (maxrate)
  345                 ifp->if_baudrate = IF_Mbps(maxrate);
  346 #undef ADD
  347 }
  348 
  349 static int
  350 findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate)
  351 {
  352 #define IEEERATE(_ic,_m,_i) \
  353         ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
  354         int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
  355         for (i = 0; i < nrates; i++)
  356                 if (IEEERATE(ic, mode, i) == rate)
  357                         return i;
  358         return -1;
  359 #undef IEEERATE
  360 }
  361 
  362 /*
  363  * Handle a media change request.
  364  */
  365 int
  366 ieee80211_media_change(struct ifnet *ifp)
  367 {
  368         struct ieee80211com *ic = (void *)ifp;
  369         struct ifmedia_entry *ime;
  370         enum ieee80211_opmode newopmode;
  371         enum ieee80211_phymode newphymode;
  372         int i, j, newrate, error = 0;
  373 
  374         ime = ic->ic_media.ifm_cur;
  375         /*
  376          * First, identify the phy mode.
  377          */
  378         switch (IFM_MODE(ime->ifm_media)) {
  379         case IFM_IEEE80211_11A:
  380                 newphymode = IEEE80211_MODE_11A;
  381                 break;
  382         case IFM_IEEE80211_11B:
  383                 newphymode = IEEE80211_MODE_11B;
  384                 break;
  385         case IFM_IEEE80211_11G:
  386                 newphymode = IEEE80211_MODE_11G;
  387                 break;
  388         case IFM_AUTO:
  389                 newphymode = IEEE80211_MODE_AUTO;
  390                 break;
  391         default:
  392                 return EINVAL;
  393         }
  394         /*
  395          * Turbo mode is an ``option''.  Eventually it
  396          * needs to be applied to 11g too.
  397          */
  398         if (ime->ifm_media & IFM_IEEE80211_TURBO) {
  399                 if (newphymode != IEEE80211_MODE_11A)
  400                         return EINVAL;
  401                 newphymode = IEEE80211_MODE_TURBO;
  402         }
  403         /*
  404          * Validate requested mode is available.
  405          */
  406         if ((ic->ic_modecaps & (1<<newphymode)) == 0)
  407                 return EINVAL;
  408 
  409         /*
  410          * Next, the fixed/variable rate.
  411          */
  412         i = -1;
  413         if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) {
  414                 /*
  415                  * Convert media subtype to rate.
  416                  */
  417                 newrate = ieee80211_media2rate(ime->ifm_media);
  418                 if (newrate == 0)
  419                         return EINVAL;
  420                 /*
  421                  * Check the rate table for the specified/current phy.
  422                  */
  423                 if (newphymode == IEEE80211_MODE_AUTO) {
  424                         /*
  425                          * In autoselect mode search for the rate.
  426                          */
  427                         for (j = IEEE80211_MODE_11A;
  428                              j < IEEE80211_MODE_MAX; j++) {
  429                                 if ((ic->ic_modecaps & (1<<j)) == 0)
  430                                         continue;
  431                                 i = findrate(ic, j, newrate);
  432                                 if (i != -1) {
  433                                         /* lock mode too */
  434                                         newphymode = j;
  435                                         break;
  436                                 }
  437                         }
  438                 } else {
  439                         i = findrate(ic, newphymode, newrate);
  440                 }
  441                 if (i == -1)                    /* mode/rate mismatch */
  442                         return EINVAL;
  443         }
  444         /* NB: defer rate setting to later */
  445 
  446         /*
  447          * Deduce new operating mode but don't install it just yet.
  448          */
  449         if ((ime->ifm_media & (IFM_IEEE80211_ADHOC|IFM_FLAG0)) ==
  450             (IFM_IEEE80211_ADHOC|IFM_FLAG0))
  451                 newopmode = IEEE80211_M_AHDEMO;
  452         else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
  453                 newopmode = IEEE80211_M_HOSTAP;
  454         else if (ime->ifm_media & IFM_IEEE80211_ADHOC)
  455                 newopmode = IEEE80211_M_IBSS;
  456         else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
  457                 newopmode = IEEE80211_M_MONITOR;
  458         else
  459                 newopmode = IEEE80211_M_STA;
  460 
  461         /*
  462          * Autoselect doesn't make sense when operating as an AP.
  463          * If no phy mode has been selected, pick one and lock it
  464          * down so rate tables can be used in forming beacon frames
  465          * and the like.
  466          */
  467         if (newopmode == IEEE80211_M_HOSTAP &&
  468             newphymode == IEEE80211_MODE_AUTO) {
  469                 for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++)
  470                         if (ic->ic_modecaps & (1<<j)) {
  471                                 newphymode = j;
  472                                 break;
  473                         }
  474         }
  475 
  476         /*
  477          * Handle phy mode change.
  478          */
  479         if (ic->ic_curmode != newphymode) {             /* change phy mode */
  480                 error = ieee80211_setmode(ic, newphymode);
  481                 if (error != 0)
  482                         return error;
  483                 error = ENETRESET;
  484         }
  485 
  486         /*
  487          * Committed to changes, install the rate setting.
  488          */
  489         if (ic->ic_fixed_rate != i) {
  490                 ic->ic_fixed_rate = i;                  /* set fixed tx rate */
  491                 error = ENETRESET;
  492         }
  493 
  494         /*
  495          * Handle operating mode change.
  496          */
  497         if (ic->ic_opmode != newopmode) {
  498                 ic->ic_opmode = newopmode;
  499                 switch (newopmode) {
  500                 case IEEE80211_M_AHDEMO:
  501                 case IEEE80211_M_HOSTAP:
  502                 case IEEE80211_M_STA:
  503                 case IEEE80211_M_MONITOR:
  504                         ic->ic_flags &= ~IEEE80211_F_IBSSON;
  505                         break;
  506                 case IEEE80211_M_IBSS:
  507                         ic->ic_flags |= IEEE80211_F_IBSSON;
  508 #ifdef notdef
  509                         if (ic->ic_curmode == IEEE80211_MODE_11G)
  510                                 ieee80211_set11gbasicrates(
  511                                         &ic->ic_suprates[newphymode],
  512                                         IEEE80211_MODE_11B);
  513 #endif
  514                         break;
  515                 }
  516                 error = ENETRESET;
  517         }
  518 #ifdef notdef
  519         if (error == 0)
  520                 ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);
  521 #endif
  522         return error;
  523 }
  524 
  525 void
  526 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
  527 {
  528         struct ieee80211com *ic = (void *)ifp;
  529         struct ieee80211_node *ni = NULL;
  530 
  531         imr->ifm_status = IFM_AVALID;
  532         imr->ifm_active = IFM_IEEE80211;
  533         if (ic->ic_state == IEEE80211_S_RUN)
  534                 imr->ifm_status |= IFM_ACTIVE;
  535         imr->ifm_active |= IFM_AUTO;
  536         switch (ic->ic_opmode) {
  537         case IEEE80211_M_STA:
  538                 ni = ic->ic_bss;
  539                 /* calculate rate subtype */
  540                 imr->ifm_active |= ieee80211_rate2media(ic,
  541                         ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode);
  542                 break;
  543         case IEEE80211_M_IBSS:
  544                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
  545                 break;
  546         case IEEE80211_M_AHDEMO:
  547                 /* should not come here */
  548                 break;
  549         case IEEE80211_M_HOSTAP:
  550                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
  551                 break;
  552         case IEEE80211_M_MONITOR:
  553                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
  554                 break;
  555         }
  556         switch (ic->ic_curmode) {
  557         case IEEE80211_MODE_11A:
  558                 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A);
  559                 break;
  560         case IEEE80211_MODE_11B:
  561                 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11B);
  562                 break;
  563         case IEEE80211_MODE_11G:
  564                 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11G);
  565                 break;
  566         case IEEE80211_MODE_TURBO:
  567                 imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A)
  568                                 |  IFM_IEEE80211_TURBO;
  569                 break;
  570         }
  571 }
  572 
  573 void
  574 ieee80211_watchdog(struct ifnet *ifp)
  575 {
  576         struct ieee80211com *ic = (void *)ifp;
  577 
  578         if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0)
  579                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  580         if (ic->ic_inact_timer && --ic->ic_inact_timer == 0)
  581                 ieee80211_timeout_nodes(ic);
  582 
  583         if (ic->ic_mgt_timer != 0 || ic->ic_inact_timer != 0)
  584                 ifp->if_timer = 1;
  585 }
  586 
  587 /*
  588  * Mark the basic rates for the 11g rate table based on the
  589  * operating mode.  For real 11g we mark all the 11b rates
  590  * and 6, 12, and 24 OFDM.  For 11b compatibility we mark only
  591  * 11b rates.  There's also a pseudo 11a-mode used to mark only
  592  * the basic OFDM rates.
  593  */
  594 static void
  595 ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode)
  596 {
  597         static const struct ieee80211_rateset basic[] = {
  598             { 3, { 12, 24, 48 } },              /* IEEE80211_MODE_11A */
  599             { 4, { 2, 4, 11, 22 } },            /* IEEE80211_MODE_11B */
  600             { 7, { 2, 4, 11, 22, 12, 24, 48 } },/* IEEE80211_MODE_11G */
  601             { 0 },                              /* IEEE80211_MODE_TURBO */
  602         };
  603         int i, j;
  604 
  605         for (i = 0; i < rs->rs_nrates; i++) {
  606                 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
  607                 for (j = 0; j < basic[mode].rs_nrates; j++)
  608                         if (basic[mode].rs_rates[j] == rs->rs_rates[i]) {
  609                                 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
  610                                 break;
  611                         }
  612         }
  613 }
  614 
  615 /*
  616  * Set the current phy mode and recalculate the active channel
  617  * set based on the available channels for this mode.  Also
  618  * select a new default/current channel if the current one is
  619  * inappropriate for this mode.
  620  */
  621 int
  622 ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)
  623 {
  624 #define N(a)    (sizeof(a) / sizeof(a[0]))
  625         static const u_int chanflags[] = {
  626                 0,                      /* IEEE80211_MODE_AUTO */
  627                 IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */
  628                 IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */
  629                 IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */
  630                 IEEE80211_CHAN_T,       /* IEEE80211_MODE_TURBO */
  631         };
  632         struct ieee80211_channel *c;
  633         u_int modeflags;
  634         int i;
  635 
  636         /* validate new mode */
  637         if ((ic->ic_modecaps & (1<<mode)) == 0) {
  638                 IEEE80211_DPRINTF(("%s: mode %u not supported (caps 0x%x)\n",
  639                         __func__, mode, ic->ic_modecaps));
  640                 return EINVAL;
  641         }
  642 
  643         /*
  644          * Verify at least one channel is present in the available
  645          * channel list before committing to the new mode.
  646          */
  647         KASSERT(mode < N(chanflags), ("Unexpected mode %u\n", mode));
  648         modeflags = chanflags[mode];
  649         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  650                 c = &ic->ic_channels[i];
  651                 if (mode == IEEE80211_MODE_AUTO) {
  652                         /* ignore turbo channels for autoselect */
  653                         if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0)
  654                                 break;
  655                 } else {
  656                         if ((c->ic_flags & modeflags) == modeflags)
  657                                 break;
  658                 }
  659         }
  660         if (i > IEEE80211_CHAN_MAX) {
  661                 IEEE80211_DPRINTF(("%s: no channels found for mode %u\n",
  662                         __func__, mode));
  663                 return EINVAL;
  664         }
  665 
  666         /*
  667          * Calculate the active channel set.
  668          */
  669         memset(ic->ic_chan_active, 0, sizeof(ic->ic_chan_active));
  670         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
  671                 c = &ic->ic_channels[i];
  672                 if (mode == IEEE80211_MODE_AUTO) {
  673                         /* take anything but pure turbo channels */
  674                         if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0)
  675                                 setbit(ic->ic_chan_active, i);
  676                 } else {
  677                         if ((c->ic_flags & modeflags) == modeflags)
  678                                 setbit(ic->ic_chan_active, i);
  679                 }
  680         }
  681         /*
  682          * If no current/default channel is setup or the current
  683          * channel is wrong for the mode then pick the first
  684          * available channel from the active list.  This is likely
  685          * not the right one.
  686          */
  687         if (ic->ic_ibss_chan == NULL ||
  688             isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
  689                 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
  690                         if (isset(ic->ic_chan_active, i)) {
  691                                 ic->ic_ibss_chan = &ic->ic_channels[i];
  692                                 break;
  693                         }
  694         }
  695 
  696         /*
  697          * Set/reset state flags that influence beacon contents, etc.
  698          *
  699          * XXX what if we have stations already associated???
  700          * XXX probably not right for autoselect?
  701          */
  702         if (ic->ic_caps & IEEE80211_C_SHPREAMBLE)
  703                 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
  704         if (mode == IEEE80211_MODE_11G) {
  705                 if (ic->ic_caps & IEEE80211_C_SHSLOT)
  706                         ic->ic_flags |= IEEE80211_F_SHSLOT;
  707                 ieee80211_set11gbasicrates(&ic->ic_sup_rates[mode],
  708                         IEEE80211_MODE_11G);
  709         } else {
  710                 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
  711         }
  712 
  713         ic->ic_curmode = mode;
  714         return 0;
  715 #undef N
  716 }
  717 
  718 /*
  719  * Return the phy mode for with the specified channel so the
  720  * caller can select a rate set.  This is problematic and the
  721  * work here assumes how things work elsewhere in this code.
  722  */
  723 enum ieee80211_phymode
  724 ieee80211_chan2mode(struct ieee80211com *ic, struct ieee80211_channel *chan)
  725 {
  726         /*
  727          * NB: this assumes the channel would not be supplied to us
  728          *     unless it was already compatible with the current mode.
  729          */
  730         if (ic->ic_curmode != IEEE80211_MODE_AUTO)
  731                 return ic->ic_curmode;
  732         /*
  733          * In autoselect mode; deduce a mode based on the channel
  734          * characteristics.  We assume that turbo-only channels
  735          * are not considered when the channel set is constructed.
  736          */
  737         if (IEEE80211_IS_CHAN_5GHZ(chan))
  738                 return IEEE80211_MODE_11A;
  739         else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
  740                 return IEEE80211_MODE_11G;
  741         else
  742                 return IEEE80211_MODE_11B;
  743 }
  744 
  745 /*
  746  * convert IEEE80211 rate value to ifmedia subtype.
  747  * ieee80211 rate is in unit of 0.5Mbps.
  748  */
  749 int
  750 ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode mode)
  751 {
  752 #define N(a)    (sizeof(a) / sizeof(a[0]))
  753         static const struct {
  754                 u_int   m;      /* rate + mode */
  755                 u_int   r;      /* if_media rate */
  756         } rates[] = {
  757                 {   2 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS1 },
  758                 {   4 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS2 },
  759                 {  11 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS5 },
  760                 {  22 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS11 },
  761                 {  44 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS22 },
  762                 {  12 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM6 },
  763                 {  18 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM9 },
  764                 {  24 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM12 },
  765                 {  36 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM18 },
  766                 {  48 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM24 },
  767                 {  72 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM36 },
  768                 {  96 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM48 },
  769                 { 108 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM54 },
  770                 {   2 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS1 },
  771                 {   4 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS2 },
  772                 {  11 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS5 },
  773                 {  22 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS11 },
  774                 {  12 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM6 },
  775                 {  18 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM9 },
  776                 {  24 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM12 },
  777                 {  36 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM18 },
  778                 {  48 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM24 },
  779                 {  72 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM36 },
  780                 {  96 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM48 },
  781                 { 108 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM54 },
  782                 /* NB: OFDM72 doesn't realy exist so we don't handle it */
  783         };
  784         u_int mask, i;
  785 
  786         mask = rate & IEEE80211_RATE_VAL;
  787         switch (mode) {
  788         case IEEE80211_MODE_11A:
  789         case IEEE80211_MODE_TURBO:
  790                 mask |= IFM_MAKEMODE(IFM_IEEE80211_11A);
  791                 break;
  792         case IEEE80211_MODE_11B:
  793                 mask |= IFM_MAKEMODE(IFM_IEEE80211_11B);
  794                 break;
  795         case IEEE80211_MODE_AUTO:
  796                 /* NB: ic may be NULL for some drivers */
  797                 if (ic && ic->ic_phytype == IEEE80211_T_FH) {
  798                         /* must handle these specially */
  799                         switch (mask) {
  800                         case 2:         return IFM_IEEE80211_FH1;
  801                         case 4:         return IFM_IEEE80211_FH2;
  802                         }
  803                         return IFM_AUTO;
  804                 }
  805                 /* NB: hack, 11g matches both 11b+11a rates */
  806                 /* fall thru... */
  807         case IEEE80211_MODE_11G:
  808                 mask |= IFM_MAKEMODE(IFM_IEEE80211_11G);
  809                 break;
  810         }
  811         for (i = 0; i < N(rates); i++)
  812                 if (rates[i].m == mask)
  813                         return rates[i].r;
  814         return IFM_AUTO;
  815 #undef N
  816 }
  817 
  818 int
  819 ieee80211_media2rate(int mword)
  820 {
  821 #define N(a)    (sizeof(a) / sizeof(a[0]))
  822         static const int ieeerates[] = {
  823                 -1,             /* IFM_AUTO */
  824                 0,              /* IFM_MANUAL */
  825                 0,              /* IFM_NONE */
  826                 2,              /* IFM_IEEE80211_FH1 */
  827                 4,              /* IFM_IEEE80211_FH2 */
  828                 2,              /* IFM_IEEE80211_DS1 */
  829                 4,              /* IFM_IEEE80211_DS2 */
  830                 11,             /* IFM_IEEE80211_DS5 */
  831                 22,             /* IFM_IEEE80211_DS11 */
  832                 44,             /* IFM_IEEE80211_DS22 */
  833                 12,             /* IFM_IEEE80211_OFDM6 */
  834                 18,             /* IFM_IEEE80211_OFDM9 */
  835                 24,             /* IFM_IEEE80211_OFDM12 */
  836                 36,             /* IFM_IEEE80211_OFDM18 */
  837                 48,             /* IFM_IEEE80211_OFDM24 */
  838                 72,             /* IFM_IEEE80211_OFDM36 */
  839                 96,             /* IFM_IEEE80211_OFDM48 */
  840                 108,            /* IFM_IEEE80211_OFDM54 */
  841                 144,            /* IFM_IEEE80211_OFDM72 */
  842         };
  843         return IFM_SUBTYPE(mword) < N(ieeerates) ?
  844                 ieeerates[IFM_SUBTYPE(mword)] : 0;
  845 #undef N
  846 }
  847 
  848 /*
  849  * Module glue.
  850  *
  851  * NB: the module name is "wlan" for compatibility with NetBSD.
  852  */
  853 
  854 static int
  855 ieee80211_modevent(module_t mod, int type, void *unused)
  856 {
  857         switch (type) {
  858         case MOD_LOAD:
  859                 if (bootverbose)
  860                         printf("wlan: <802.11 Link Layer>\n");
  861                 return 0;
  862         case MOD_UNLOAD:
  863                 return 0;
  864         }
  865         return EINVAL;
  866 }
  867 
  868 static moduledata_t ieee80211_mod = {
  869         "wlan",
  870         ieee80211_modevent,
  871         0
  872 };
  873 DECLARE_MODULE(wlan, ieee80211_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
  874 MODULE_VERSION(wlan, 1);
  875 MODULE_DEPEND(wlan, rc4, 1, 1, 1);

Cache object: 2cd82507a4dcea5bbfb4986752d62b39


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