root/net80211/ieee80211_proto.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ieee80211_proto_attach
  2. ieee80211_proto_detach
  3. ieee80211_print_essid
  4. ieee80211_dump_pkt
  5. ieee80211_fix_rate
  6. ieee80211_reset_erp
  7. ieee80211_set_shortslottime
  8. ieee80211_newstate

    1 /*      $OpenBSD: ieee80211_proto.c,v 1.20 2007/07/28 11:24:06 damien Exp $     */
    2 /*      $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $       */
    3 
    4 /*-
    5  * Copyright (c) 2001 Atsushi Onoe
    6  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * IEEE 802.11 protocol support.
   34  */
   35 
   36 #include "bpfilter.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/kernel.h>
   42 #include <sys/socket.h>
   43 #include <sys/sockio.h>
   44 #include <sys/endian.h>
   45 #include <sys/errno.h>
   46 #include <sys/proc.h>
   47 #include <sys/sysctl.h>
   48 
   49 #include <net/if.h>
   50 #include <net/if_dl.h>
   51 #include <net/if_media.h>
   52 #include <net/if_arp.h>
   53 #include <net/if_llc.h>
   54 
   55 #if NBPFILTER > 0
   56 #include <net/bpf.h>
   57 #endif
   58 
   59 #ifdef INET
   60 #include <netinet/in.h>
   61 #include <netinet/if_ether.h>
   62 #endif
   63 
   64 #include <net80211/ieee80211_var.h>
   65 
   66 const char * const ieee80211_mgt_subtype_name[] = {
   67         "assoc_req",    "assoc_resp",   "reassoc_req",  "reassoc_resp",
   68         "probe_req",    "probe_resp",   "reserved#6",   "reserved#7",
   69         "beacon",       "atim",         "disassoc",     "auth",
   70         "deauth",       "action",       "action_noack", "reserved#15"
   71 };
   72 const char * const 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 * const ieee80211_phymode_name[] = {
   80         "auto",         /* IEEE80211_MODE_AUTO */
   81         "11a",          /* IEEE80211_MODE_11A */
   82         "11b",          /* IEEE80211_MODE_11B */
   83         "11g",          /* IEEE80211_MODE_11G */
   84         "fh",           /* IEEE80211_MODE_FH */
   85         "turbo",        /* IEEE80211_MODE_TURBO */
   86 };
   87 
   88 int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
   89 
   90 void
   91 ieee80211_proto_attach(struct ifnet *ifp)
   92 {
   93         struct ieee80211com *ic = (void *)ifp;
   94 
   95         ifp->if_hdrlen = sizeof(struct ieee80211_frame);
   96 
   97 #ifdef notdef
   98         ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
   99 #else
  100         ic->ic_rtsthreshold = IEEE80211_RTS_MAX;
  101 #endif
  102         ic->ic_fragthreshold = 2346;            /* XXX not used yet */
  103         ic->ic_fixed_rate = -1;                 /* no fixed rate */
  104         ic->ic_protmode = IEEE80211_PROT_CTSONLY;
  105 
  106         /* protocol state change handler */
  107         ic->ic_newstate = ieee80211_newstate;
  108 
  109         /* initialize management frame handlers */
  110         ic->ic_recv_mgmt = ieee80211_recv_mgmt;
  111         ic->ic_send_mgmt = ieee80211_send_mgmt;
  112 
  113         /* initialize EAPOL frame handler */
  114         ic->ic_recv_eapol = ieee80211_recv_eapol;
  115 }
  116 
  117 void
  118 ieee80211_proto_detach(struct ifnet *ifp)
  119 {
  120         struct ieee80211com *ic = (void *)ifp;
  121 
  122         IF_PURGE(&ic->ic_mgtq);
  123         IF_PURGE(&ic->ic_pwrsaveq);
  124 }
  125 
  126 void
  127 ieee80211_print_essid(const u_int8_t *essid, int len)
  128 {
  129         int i;
  130         const u_int8_t *p;
  131 
  132         if (len > IEEE80211_NWID_LEN)
  133                 len = IEEE80211_NWID_LEN;
  134         /* determine printable or not */
  135         for (i = 0, p = essid; i < len; i++, p++) {
  136                 if (*p < ' ' || *p > 0x7e)
  137                         break;
  138         }
  139         if (i == len) {
  140                 printf("\"");
  141                 for (i = 0, p = essid; i < len; i++, p++)
  142                         printf("%c", *p);
  143                 printf("\"");
  144         } else {
  145                 printf("0x");
  146                 for (i = 0, p = essid; i < len; i++, p++)
  147                         printf("%02x", *p);
  148         }
  149 }
  150 
  151 void
  152 ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)
  153 {
  154         struct ieee80211_frame *wh;
  155         int i;
  156 
  157         wh = (struct ieee80211_frame *)buf;
  158         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
  159         case IEEE80211_FC1_DIR_NODS:
  160                 printf("NODS %s", ether_sprintf(wh->i_addr2));
  161                 printf("->%s", ether_sprintf(wh->i_addr1));
  162                 printf("(%s)", ether_sprintf(wh->i_addr3));
  163                 break;
  164         case IEEE80211_FC1_DIR_TODS:
  165                 printf("TODS %s", ether_sprintf(wh->i_addr2));
  166                 printf("->%s", ether_sprintf(wh->i_addr3));
  167                 printf("(%s)", ether_sprintf(wh->i_addr1));
  168                 break;
  169         case IEEE80211_FC1_DIR_FROMDS:
  170                 printf("FRDS %s", ether_sprintf(wh->i_addr3));
  171                 printf("->%s", ether_sprintf(wh->i_addr1));
  172                 printf("(%s)", ether_sprintf(wh->i_addr2));
  173                 break;
  174         case IEEE80211_FC1_DIR_DSTODS:
  175                 printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
  176                 printf("->%s", ether_sprintf(wh->i_addr3));
  177                 printf("(%s", ether_sprintf(wh->i_addr2));
  178                 printf("->%s)", ether_sprintf(wh->i_addr1));
  179                 break;
  180         }
  181         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
  182         case IEEE80211_FC0_TYPE_DATA:
  183                 printf(" data");
  184                 break;
  185         case IEEE80211_FC0_TYPE_MGT:
  186                 printf(" %s", ieee80211_mgt_subtype_name[
  187                     (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
  188                     >> IEEE80211_FC0_SUBTYPE_SHIFT]);
  189                 break;
  190         default:
  191                 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
  192                 break;
  193         }
  194         if (wh->i_fc[1] & IEEE80211_FC1_WEP)
  195                 printf(" WEP");
  196         if (rate >= 0)
  197                 printf(" %d%sM", rate / 2, (rate & 1) ? ".5" : "");
  198         if (rssi >= 0)
  199                 printf(" +%d", rssi);
  200         printf("\n");
  201         if (len > 0) {
  202                 for (i = 0; i < len; i++) {
  203                         if ((i & 1) == 0)
  204                                 printf(" ");
  205                         printf("%02x", buf[i]);
  206                 }
  207                 printf("\n");
  208         }
  209 }
  210 
  211 int
  212 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
  213     int flags)
  214 {
  215 #define RV(v)   ((v) & IEEE80211_RATE_VAL)
  216         int i, j, ignore, error;
  217         int okrate, badrate, fixedrate;
  218         const struct ieee80211_rateset *srs;
  219         struct ieee80211_rateset *nrs;
  220         u_int8_t r;
  221 
  222         /*
  223          * If the fixed rate check was requested but no fixed rate has been
  224          * defined then just remove the check.
  225          */
  226         if ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate == -1)
  227                 flags &= ~IEEE80211_F_DOFRATE;
  228 
  229         error = 0;
  230         okrate = badrate = fixedrate = 0;
  231         srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
  232         nrs = &ni->ni_rates;
  233         for (i = 0; i < nrs->rs_nrates; ) {
  234                 ignore = 0;
  235                 if (flags & IEEE80211_F_DOSORT) {
  236                         /*
  237                          * Sort rates.
  238                          */
  239                         for (j = i + 1; j < nrs->rs_nrates; j++) {
  240                                 if (RV(nrs->rs_rates[i]) >
  241                                     RV(nrs->rs_rates[j])) {
  242                                         r = nrs->rs_rates[i];
  243                                         nrs->rs_rates[i] = nrs->rs_rates[j];
  244                                         nrs->rs_rates[j] = r;
  245                                 }
  246                         }
  247                 }
  248                 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
  249                 badrate = r;
  250                 if (flags & IEEE80211_F_DOFRATE) {
  251                         /*
  252                          * Check fixed rate is included.
  253                          */
  254                         if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
  255                                 fixedrate = r;
  256                 }
  257                 if (flags & IEEE80211_F_DONEGO) {
  258                         /*
  259                          * Check against supported rates.
  260                          */
  261                         for (j = 0; j < srs->rs_nrates; j++) {
  262                                 if (r == RV(srs->rs_rates[j])) {
  263                                         /*
  264                                          * Overwrite with the supported rate
  265                                          * value so any basic rate bit is set.
  266                                          * This insures that response we send
  267                                          * to stations have the necessary basic
  268                                          * rate bit set.
  269                                          */
  270                                         nrs->rs_rates[i] = srs->rs_rates[j];
  271                                         break;
  272                                 }
  273                         }
  274                         if (j == srs->rs_nrates) {
  275                                 /*
  276                                  * A rate in the node's rate set is not
  277                                  * supported.  If this is a basic rate and we
  278                                  * are operating as an AP then this is an error.
  279                                  * Otherwise we just discard/ignore the rate.
  280                                  * Note that this is important for 11b stations
  281                                  * when they want to associate with an 11g AP.
  282                                  */
  283                                 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  284                                     (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
  285                                         error++;
  286                                 ignore++;
  287                         }
  288                 }
  289                 if (flags & IEEE80211_F_DODEL) {
  290                         /*
  291                          * Delete unacceptable rates.
  292                          */
  293                         if (ignore) {
  294                                 nrs->rs_nrates--;
  295                                 for (j = i; j < nrs->rs_nrates; j++)
  296                                         nrs->rs_rates[j] = nrs->rs_rates[j + 1];
  297                                 nrs->rs_rates[j] = 0;
  298                                 continue;
  299                         }
  300                 }
  301                 if (!ignore)
  302                         okrate = nrs->rs_rates[i];
  303                 i++;
  304         }
  305         if (okrate == 0 || error != 0 ||
  306             ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
  307                 return badrate | IEEE80211_RATE_BASIC;
  308         else
  309                 return RV(okrate);
  310 #undef RV
  311 }
  312 
  313 /*
  314  * Reset 11g-related state.
  315  */
  316 void
  317 ieee80211_reset_erp(struct ieee80211com *ic)
  318 {
  319         ic->ic_flags &= ~IEEE80211_F_USEPROT;
  320         ic->ic_nonerpsta = 0;
  321         ic->ic_longslotsta = 0;
  322 
  323         /*
  324          * Enable short slot time iff:
  325          * - we're operating in 802.11a or
  326          * - we're operating in 802.11g and we're not in IBSS mode and
  327          *   the device supports short slot time
  328          */
  329         ieee80211_set_shortslottime(ic,
  330             ic->ic_curmode == IEEE80211_MODE_11A ||
  331             (ic->ic_curmode == IEEE80211_MODE_11G &&
  332              ic->ic_opmode == IEEE80211_M_HOSTAP &&
  333              (ic->ic_caps & IEEE80211_C_SHSLOT)));
  334 
  335         if (ic->ic_curmode == IEEE80211_MODE_11A ||
  336             (ic->ic_caps & IEEE80211_C_SHPREAMBLE))
  337                 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
  338         else
  339                 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
  340 }
  341 
  342 /*
  343  * Set the short slot time state and notify the driver.
  344  */
  345 void
  346 ieee80211_set_shortslottime(struct ieee80211com *ic, int on)
  347 {
  348         if (on)
  349                 ic->ic_flags |= IEEE80211_F_SHSLOT;
  350         else
  351                 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
  352 
  353         /* notify the driver */
  354         if (ic->ic_updateslot != NULL)
  355                 ic->ic_updateslot(ic);
  356 }
  357 
  358 int
  359 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
  360     int mgt)
  361 {
  362         struct ifnet *ifp = &ic->ic_if;
  363         struct ieee80211_node *ni;
  364         enum ieee80211_state ostate;
  365         u_int rate;
  366         int s;
  367 
  368         ostate = ic->ic_state;
  369         IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__,
  370             ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
  371         ic->ic_state = nstate;                  /* state transition */
  372         ni = ic->ic_bss;                        /* NB: no reference held */
  373         switch (nstate) {
  374         case IEEE80211_S_INIT:
  375                 switch (ostate) {
  376                 case IEEE80211_S_INIT:
  377                         break;
  378                 case IEEE80211_S_RUN:
  379                         switch (ic->ic_opmode) {
  380                         case IEEE80211_M_STA:
  381                                 IEEE80211_SEND_MGMT(ic, ni,
  382                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
  383                                     IEEE80211_REASON_ASSOC_LEAVE);
  384                                 break;
  385                         case IEEE80211_M_HOSTAP:
  386                                 s = splnet();
  387                                 RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
  388                                         if (ni->ni_associd == 0)
  389                                                 continue;
  390                                         IEEE80211_SEND_MGMT(ic, ni,
  391                                             IEEE80211_FC0_SUBTYPE_DISASSOC,
  392                                             IEEE80211_REASON_ASSOC_LEAVE);
  393                                 }
  394                                 splx(s);
  395                                 break;
  396                         default:
  397                                 break;
  398                         }
  399                         /* FALLTHROUGH */
  400                 case IEEE80211_S_ASSOC:
  401                         switch (ic->ic_opmode) {
  402                         case IEEE80211_M_STA:
  403                                 IEEE80211_SEND_MGMT(ic, ni,
  404                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
  405                                     IEEE80211_REASON_AUTH_LEAVE);
  406                                 break;
  407                         case IEEE80211_M_HOSTAP:
  408                                 s = splnet();
  409                                 RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
  410                                         IEEE80211_SEND_MGMT(ic, ni,
  411                                             IEEE80211_FC0_SUBTYPE_DEAUTH,
  412                                             IEEE80211_REASON_AUTH_LEAVE);
  413                                 }
  414                                 splx(s);
  415                                 break;
  416                         default:
  417                                 break;
  418                         }
  419                         /* FALLTHROUGH */
  420                 case IEEE80211_S_AUTH:
  421                 case IEEE80211_S_SCAN:
  422                         ic->ic_mgt_timer = 0;
  423                         IF_PURGE(&ic->ic_mgtq);
  424                         IF_PURGE(&ic->ic_pwrsaveq);
  425                         if (ic->ic_wep_ctx != NULL) {
  426                                 free(ic->ic_wep_ctx, M_DEVBUF);
  427                                 ic->ic_wep_ctx = NULL;
  428                         }
  429                         ieee80211_free_allnodes(ic);
  430                         break;
  431                 }
  432                 break;
  433         case IEEE80211_S_SCAN:
  434                 ic->ic_flags &= ~IEEE80211_F_SIBSS;
  435                 /* initialize bss for probe request */
  436                 IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr);
  437                 IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr);
  438                 ni->ni_rates = ic->ic_sup_rates[
  439                         ieee80211_chan2mode(ic, ni->ni_chan)];
  440                 ni->ni_associd = 0;
  441                 ni->ni_rstamp = 0;
  442                 switch (ostate) {
  443                 case IEEE80211_S_INIT:
  444                         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  445                             ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
  446                                 /*
  447                                  * AP operation and we already have a channel;
  448                                  * bypass the scan and startup immediately.
  449                                  */
  450                                 ieee80211_create_ibss(ic, ic->ic_des_chan);
  451                         } else {
  452                                 ieee80211_begin_scan(ifp);
  453                         }
  454                         break;
  455                 case IEEE80211_S_SCAN:
  456                         /* scan next */
  457                         if (ic->ic_flags & IEEE80211_F_ASCAN) {
  458                                 IEEE80211_SEND_MGMT(ic, ni,
  459                                     IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
  460                         }
  461                         break;
  462                 case IEEE80211_S_RUN:
  463                         /* beacon miss */
  464                         if (ifp->if_flags & IFF_DEBUG) {
  465                                 /* XXX bssid clobbered above */
  466                                 printf("%s: no recent beacons from %s;"
  467                                     " rescanning\n", ifp->if_xname,
  468                                     ether_sprintf(ic->ic_bss->ni_bssid));
  469                         }
  470                         ieee80211_free_allnodes(ic);
  471                         /* FALLTHROUGH */
  472                 case IEEE80211_S_AUTH:
  473                 case IEEE80211_S_ASSOC:
  474                         /* timeout restart scan */
  475                         ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
  476                         if (ni != NULL)
  477                                 ni->ni_fails++;
  478                         ieee80211_begin_scan(ifp);
  479                         break;
  480                 }
  481                 break;
  482         case IEEE80211_S_AUTH:
  483                 switch (ostate) {
  484                 case IEEE80211_S_INIT:
  485                         IEEE80211_DPRINTF(("%s: invalid transition\n",
  486                                 __func__));
  487                         break;
  488                 case IEEE80211_S_SCAN:
  489                         IEEE80211_SEND_MGMT(ic, ni,
  490                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
  491                         break;
  492                 case IEEE80211_S_AUTH:
  493                 case IEEE80211_S_ASSOC:
  494                         switch (mgt) {
  495                         case IEEE80211_FC0_SUBTYPE_AUTH:
  496                                 /* ??? */
  497                                 IEEE80211_SEND_MGMT(ic, ni,
  498                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
  499                                 break;
  500                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
  501                                 /* ignore and retry scan on timeout */
  502                                 break;
  503                         }
  504                         break;
  505                 case IEEE80211_S_RUN:
  506                         switch (mgt) {
  507                         case IEEE80211_FC0_SUBTYPE_AUTH:
  508                                 IEEE80211_SEND_MGMT(ic, ni,
  509                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
  510                                 ic->ic_state = ostate;  /* stay RUN */
  511                                 break;
  512                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
  513                                 /* try to reauth */
  514                                 IEEE80211_SEND_MGMT(ic, ni,
  515                                     IEEE80211_FC0_SUBTYPE_AUTH, 1);
  516                                 break;
  517                         }
  518                         break;
  519                 }
  520                 break;
  521         case IEEE80211_S_ASSOC:
  522                 switch (ostate) {
  523                 case IEEE80211_S_INIT:
  524                 case IEEE80211_S_SCAN:
  525                 case IEEE80211_S_ASSOC:
  526                         IEEE80211_DPRINTF(("%s: invalid transition\n",
  527                                 __func__));
  528                         break;
  529                 case IEEE80211_S_AUTH:
  530                         IEEE80211_SEND_MGMT(ic, ni,
  531                             IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
  532                         break;
  533                 case IEEE80211_S_RUN:
  534                         IEEE80211_SEND_MGMT(ic, ni,
  535                             IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
  536                         break;
  537                 }
  538                 break;
  539         case IEEE80211_S_RUN:
  540                 switch (ostate) {
  541                 case IEEE80211_S_INIT:
  542                 case IEEE80211_S_AUTH:
  543                 case IEEE80211_S_RUN:
  544                         IEEE80211_DPRINTF(("%s: invalid transition\n",
  545                                 __func__));
  546                         break;
  547                 case IEEE80211_S_SCAN:          /* adhoc/hostap mode */
  548                 case IEEE80211_S_ASSOC:         /* infra mode */
  549                         if (ni->ni_txrate >= ni->ni_rates.rs_nrates)
  550                                 panic("%s: bogus xmit rate %u setup\n",
  551                                     __func__, ni->ni_txrate);
  552                         if (ifp->if_flags & IFF_DEBUG) {
  553                                 printf("%s: %s with %s ssid ",
  554                                     ifp->if_xname,
  555                                     ic->ic_opmode == IEEE80211_M_STA ?
  556                                     "associated" : "synchronized",
  557                                     ether_sprintf(ni->ni_bssid));
  558                                 ieee80211_print_essid(ic->ic_bss->ni_essid,
  559                                     ni->ni_esslen);
  560                                 rate = ni->ni_rates.rs_rates[ni->ni_txrate] &
  561                                     IEEE80211_RATE_VAL;
  562                                 printf(" channel %d start %u%sMb",
  563                                     ieee80211_chan2ieee(ic, ni->ni_chan),
  564                                     rate / 2, (rate & 1) ? ".5" : "");
  565                                 printf(" %s preamble %s slot time%s\n",
  566                                     (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
  567                                         "short" : "long",
  568                                     (ic->ic_flags & IEEE80211_F_SHSLOT) ?
  569                                         "short" : "long",
  570                                     (ic->ic_flags & IEEE80211_F_USEPROT) ?
  571                                         " protection enabled" : "");
  572                         }
  573                         ic->ic_mgt_timer = 0;
  574                         (*ifp->if_start)(ifp);
  575                         break;
  576                 }
  577                 break;
  578         }
  579         return 0;
  580 }

/* [<][>][^][v][top][bottom][index][help] */