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_adhoc.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 #ifdef __FreeBSD__
   30 __FBSDID("$FreeBSD: releng/12.0/sys/net80211/ieee80211_adhoc.c 326272 2017-11-27 15:23:17Z pfg $");
   31 #endif
   32 
   33 /*
   34  * IEEE 802.11 IBSS mode support.
   35  */
   36 #include "opt_inet.h"
   37 #include "opt_wlan.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h> 
   41 #include <sys/mbuf.h>   
   42 #include <sys/malloc.h>
   43 #include <sys/kernel.h>
   44 
   45 #include <sys/socket.h>
   46 #include <sys/sockio.h>
   47 #include <sys/endian.h>
   48 #include <sys/errno.h>
   49 #include <sys/proc.h>
   50 #include <sys/sysctl.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_var.h>
   54 #include <net/if_media.h>
   55 #include <net/if_llc.h>
   56 #include <net/ethernet.h>
   57 
   58 #include <net/bpf.h>
   59 
   60 #include <net80211/ieee80211_var.h>
   61 #include <net80211/ieee80211_adhoc.h>
   62 #include <net80211/ieee80211_input.h>
   63 #ifdef IEEE80211_SUPPORT_SUPERG
   64 #include <net80211/ieee80211_superg.h>
   65 #endif
   66 #ifdef IEEE80211_SUPPORT_TDMA
   67 #include <net80211/ieee80211_tdma.h>
   68 #endif
   69 #include <net80211/ieee80211_sta.h>
   70 
   71 #define IEEE80211_RATE2MBS(r)   (((r) & IEEE80211_RATE_VAL) / 2)
   72 
   73 static  void adhoc_vattach(struct ieee80211vap *);
   74 static  int adhoc_newstate(struct ieee80211vap *, enum ieee80211_state, int);
   75 static int adhoc_input(struct ieee80211_node *, struct mbuf *,
   76             const struct ieee80211_rx_stats *, int, int);
   77 static void adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *,
   78         int subtype, const struct ieee80211_rx_stats *, int, int);
   79 static void ahdemo_recv_mgmt(struct ieee80211_node *, struct mbuf *,
   80             int subtype, const struct ieee80211_rx_stats *rxs, int, int);
   81 static void adhoc_recv_ctl(struct ieee80211_node *, struct mbuf *, int subtype);
   82 
   83 void
   84 ieee80211_adhoc_attach(struct ieee80211com *ic)
   85 {
   86         ic->ic_vattach[IEEE80211_M_IBSS] = adhoc_vattach;
   87         ic->ic_vattach[IEEE80211_M_AHDEMO] = adhoc_vattach;
   88 }
   89 
   90 void
   91 ieee80211_adhoc_detach(struct ieee80211com *ic)
   92 {
   93 }
   94 
   95 static void
   96 adhoc_vdetach(struct ieee80211vap *vap)
   97 {
   98 }
   99 
  100 static void
  101 adhoc_vattach(struct ieee80211vap *vap)
  102 {
  103         vap->iv_newstate = adhoc_newstate;
  104         vap->iv_input = adhoc_input;
  105         if (vap->iv_opmode == IEEE80211_M_IBSS)
  106                 vap->iv_recv_mgmt = adhoc_recv_mgmt;
  107         else
  108                 vap->iv_recv_mgmt = ahdemo_recv_mgmt;
  109         vap->iv_recv_ctl = adhoc_recv_ctl;
  110         vap->iv_opdetach = adhoc_vdetach;
  111 #ifdef IEEE80211_SUPPORT_TDMA
  112         /*
  113          * Throw control to tdma support.  Note we do this
  114          * after setting up our callbacks so it can piggyback
  115          * on top of us.
  116          */
  117         if (vap->iv_caps & IEEE80211_C_TDMA)
  118                 ieee80211_tdma_vattach(vap);
  119 #endif
  120 }
  121 
  122 static void
  123 sta_leave(void *arg, struct ieee80211_node *ni)
  124 {
  125         struct ieee80211vap *vap = ni->ni_vap;
  126 
  127         if (ni != vap->iv_bss)
  128                 ieee80211_node_leave(ni);
  129 }
  130 
  131 /*
  132  * IEEE80211_M_IBSS+IEEE80211_M_AHDEMO vap state machine handler.
  133  */
  134 static int
  135 adhoc_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
  136 {
  137         struct ieee80211com *ic = vap->iv_ic;
  138         struct ieee80211_node *ni;
  139         enum ieee80211_state ostate;
  140 
  141         IEEE80211_LOCK_ASSERT(vap->iv_ic);
  142 
  143         ostate = vap->iv_state;
  144         IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
  145             __func__, ieee80211_state_name[ostate],
  146             ieee80211_state_name[nstate], arg);
  147         vap->iv_state = nstate;                 /* state transition */
  148         if (ostate != IEEE80211_S_SCAN)
  149                 ieee80211_cancel_scan(vap);     /* background scan */
  150         ni = vap->iv_bss;                       /* NB: no reference held */
  151         switch (nstate) {
  152         case IEEE80211_S_INIT:
  153                 switch (ostate) {
  154                 case IEEE80211_S_SCAN:
  155                         ieee80211_cancel_scan(vap);
  156                         break;
  157                 default:
  158                         break;
  159                 }
  160                 if (ostate != IEEE80211_S_INIT) {
  161                         /* NB: optimize INIT -> INIT case */
  162                         ieee80211_reset_bss(vap);
  163                 }
  164                 break;
  165         case IEEE80211_S_SCAN:
  166                 switch (ostate) {
  167                 case IEEE80211_S_RUN:           /* beacon miss */
  168                         /* purge station table; entries are stale */
  169                         ieee80211_iterate_nodes_vap(&ic->ic_sta, vap,
  170                             sta_leave, NULL);
  171                         /* fall thru... */
  172                 case IEEE80211_S_INIT:
  173                         if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
  174                             !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
  175                                 /*
  176                                  * Already have a channel; bypass the
  177                                  * scan and startup immediately.
  178                                  */
  179                                 ieee80211_create_ibss(vap,
  180                                     ieee80211_ht_adjust_channel(ic,
  181                                     vap->iv_des_chan, vap->iv_flags_ht));
  182                                 break;
  183                         }
  184                         /*
  185                          * Initiate a scan.  We can come here as a result
  186                          * of an IEEE80211_IOC_SCAN_REQ too in which case
  187                          * the vap will be marked with IEEE80211_FEXT_SCANREQ
  188                          * and the scan request parameters will be present
  189                          * in iv_scanreq.  Otherwise we do the default.
  190                          */
  191                         if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) {
  192                                 ieee80211_check_scan(vap,
  193                                     vap->iv_scanreq_flags,
  194                                     vap->iv_scanreq_duration,
  195                                     vap->iv_scanreq_mindwell,
  196                                     vap->iv_scanreq_maxdwell,
  197                                     vap->iv_scanreq_nssid, vap->iv_scanreq_ssid);
  198                                 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
  199                         } else
  200                                 ieee80211_check_scan_current(vap);
  201                         break;
  202                 case IEEE80211_S_SCAN:
  203                         /*
  204                          * This can happen because of a change in state
  205                          * that requires a reset.  Trigger a new scan
  206                          * unless we're in manual roaming mode in which
  207                          * case an application must issue an explicit request.
  208                          */
  209                         if (vap->iv_roaming == IEEE80211_ROAMING_AUTO)
  210                                 ieee80211_check_scan_current(vap);
  211                         break;
  212                 default:
  213                         goto invalid;
  214                 }
  215                 break;
  216         case IEEE80211_S_RUN:
  217                 if (vap->iv_flags & IEEE80211_F_WPA) {
  218                         /* XXX validate prerequisites */
  219                 }
  220                 switch (ostate) {
  221                 case IEEE80211_S_INIT:
  222                         /*
  223                          * Already have a channel; bypass the
  224                          * scan and startup immediately.
  225                          * Note that ieee80211_create_ibss will call
  226                          * back to do a RUN->RUN state change.
  227                          */
  228                         ieee80211_create_ibss(vap,
  229                             ieee80211_ht_adjust_channel(ic,
  230                                 ic->ic_curchan, vap->iv_flags_ht));
  231                         /* NB: iv_bss is changed on return */
  232                         ni = vap->iv_bss;
  233                         break;
  234                 case IEEE80211_S_SCAN:
  235 #ifdef IEEE80211_DEBUG
  236                         if (ieee80211_msg_debug(vap)) {
  237                                 ieee80211_note(vap,
  238                                     "synchronized with %s ssid ",
  239                                     ether_sprintf(ni->ni_bssid));
  240                                 ieee80211_print_essid(vap->iv_bss->ni_essid,
  241                                     ni->ni_esslen);
  242                                 /* XXX MCS/HT */
  243                                 printf(" channel %d start %uMb\n",
  244                                     ieee80211_chan2ieee(ic, ic->ic_curchan),
  245                                     IEEE80211_RATE2MBS(ni->ni_txrate));
  246                         }
  247 #endif
  248                         break;
  249                 case IEEE80211_S_RUN:   /* IBSS merge */
  250                         break;
  251                 default:
  252                         goto invalid;
  253                 }
  254                 /*
  255                  * When 802.1x is not in use mark the port authorized
  256                  * at this point so traffic can flow.
  257                  */
  258                 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
  259                         ieee80211_node_authorize(ni);
  260                 /*
  261                  * Fake association when joining an existing bss.
  262                  */
  263                 if (!IEEE80211_ADDR_EQ(ni->ni_macaddr, vap->iv_myaddr) &&
  264                     ic->ic_newassoc != NULL)
  265                         ic->ic_newassoc(ni, ostate != IEEE80211_S_RUN);
  266                 break;
  267         case IEEE80211_S_SLEEP:
  268                 vap->iv_sta_ps(vap, 0);
  269                 break;
  270         default:
  271         invalid:
  272                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
  273                     "%s: unexpected state transition %s -> %s\n", __func__,
  274                     ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
  275                 break;
  276         }
  277         return 0;
  278 }
  279 
  280 /*
  281  * Decide if a received management frame should be
  282  * printed when debugging is enabled.  This filters some
  283  * of the less interesting frames that come frequently
  284  * (e.g. beacons).
  285  */
  286 static __inline int
  287 doprint(struct ieee80211vap *vap, int subtype)
  288 {
  289         switch (subtype) {
  290         case IEEE80211_FC0_SUBTYPE_BEACON:
  291                 return (vap->iv_ic->ic_flags & IEEE80211_F_SCAN);
  292         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
  293                 return 1;
  294         }
  295         return 1;
  296 }
  297 
  298 /*
  299  * Process a received frame.  The node associated with the sender
  300  * should be supplied.  If nothing was found in the node table then
  301  * the caller is assumed to supply a reference to iv_bss instead.
  302  * The RSSI and a timestamp are also supplied.  The RSSI data is used
  303  * during AP scanning to select a AP to associate with; it can have
  304  * any units so long as values have consistent units and higher values
  305  * mean ``better signal''.  The receive timestamp is currently not used
  306  * by the 802.11 layer.
  307  */
  308 static int
  309 adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
  310     const struct ieee80211_rx_stats *rxs, int rssi, int nf)
  311 {
  312         struct ieee80211vap *vap = ni->ni_vap;
  313         struct ieee80211com *ic = ni->ni_ic;
  314         struct ifnet *ifp = vap->iv_ifp;
  315         struct ieee80211_frame *wh;
  316         struct ieee80211_key *key;
  317         struct ether_header *eh;
  318         int hdrspace, need_tap = 1;     /* mbuf need to be tapped. */   
  319         uint8_t dir, type, subtype, qos;
  320         uint8_t *bssid;
  321         int is_hw_decrypted = 0;
  322         int has_decrypted = 0;
  323 
  324         /*
  325          * Some devices do hardware decryption all the way through
  326          * to pretending the frame wasn't encrypted in the first place.
  327          * So, tag it appropriately so it isn't discarded inappropriately.
  328          */
  329         if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
  330                 is_hw_decrypted = 1;
  331 
  332         if (m->m_flags & M_AMPDU_MPDU) {
  333                 /*
  334                  * Fastpath for A-MPDU reorder q resubmission.  Frames
  335                  * w/ M_AMPDU_MPDU marked have already passed through
  336                  * here but were received out of order and been held on
  337                  * the reorder queue.  When resubmitted they are marked
  338                  * with the M_AMPDU_MPDU flag and we can bypass most of
  339                  * the normal processing.
  340                  */
  341                 wh = mtod(m, struct ieee80211_frame *);
  342                 type = IEEE80211_FC0_TYPE_DATA;
  343                 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
  344                 subtype = IEEE80211_FC0_SUBTYPE_QOS;
  345                 hdrspace = ieee80211_hdrspace(ic, wh);  /* XXX optimize? */
  346                 goto resubmit_ampdu;
  347         }
  348 
  349         KASSERT(ni != NULL, ("null node"));
  350         ni->ni_inact = ni->ni_inact_reload;
  351 
  352         type = -1;                      /* undefined */
  353 
  354         if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
  355                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
  356                     ni->ni_macaddr, NULL,
  357                     "too short (1): len %u", m->m_pkthdr.len);
  358                 vap->iv_stats.is_rx_tooshort++;
  359                 goto out;
  360         }
  361         /*
  362          * Bit of a cheat here, we use a pointer for a 3-address
  363          * frame format but don't reference fields past outside
  364          * ieee80211_frame_min w/o first validating the data is
  365          * present.
  366          */
  367         wh = mtod(m, struct ieee80211_frame *);
  368 
  369         if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
  370             IEEE80211_FC0_VERSION_0) {
  371                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
  372                     ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x",
  373                     wh->i_fc[0], wh->i_fc[1]);
  374                 vap->iv_stats.is_rx_badversion++;
  375                 goto err;
  376         }
  377 
  378         dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
  379         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
  380         subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
  381         if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
  382                 if (dir != IEEE80211_FC1_DIR_NODS)
  383                         bssid = wh->i_addr1;
  384                 else if (type == IEEE80211_FC0_TYPE_CTL)
  385                         bssid = wh->i_addr1;
  386                 else {
  387                         if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
  388                                 IEEE80211_DISCARD_MAC(vap,
  389                                     IEEE80211_MSG_ANY, ni->ni_macaddr,
  390                                     NULL, "too short (2): len %u",
  391                                     m->m_pkthdr.len);
  392                                 vap->iv_stats.is_rx_tooshort++;
  393                                 goto out;
  394                         }
  395                         bssid = wh->i_addr3;
  396                 }
  397                 /*
  398                  * Validate the bssid.
  399                  */
  400                 if (!(type == IEEE80211_FC0_TYPE_MGT &&
  401                      (subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
  402                       subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) &&
  403                     !IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) &&
  404                     !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
  405                         /* not interested in */
  406                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  407                             bssid, NULL, "%s", "not to bss");
  408                         vap->iv_stats.is_rx_wrongbss++;
  409                         goto out;
  410                 }
  411                 /*
  412                  * Data frame, cons up a node when it doesn't
  413                  * exist. This should probably done after an ACL check.
  414                  */
  415                 if (type == IEEE80211_FC0_TYPE_DATA &&
  416                     ni == vap->iv_bss &&
  417                     !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
  418                         /*
  419                          * Beware of frames that come in too early; we
  420                          * can receive broadcast frames and creating sta
  421                          * entries will blow up because there is no bss
  422                          * channel yet.
  423                          */
  424                         if (vap->iv_state != IEEE80211_S_RUN) {
  425                                 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  426                                     wh, "data", "not in RUN state (%s)",
  427                                     ieee80211_state_name[vap->iv_state]);
  428                                 vap->iv_stats.is_rx_badstate++;
  429                                 goto err;
  430                         }
  431                         /*
  432                          * Fake up a node for this newly discovered member
  433                          * of the IBSS.
  434                          *
  435                          * Note: This doesn't "upgrade" the node to 11n;
  436                          * that will happen after a probe request/response
  437                          * exchange.
  438                          */
  439                         ni = ieee80211_fakeup_adhoc_node(vap, wh->i_addr2);
  440                         if (ni == NULL) {
  441                                 /* NB: stat kept for alloc failure */
  442                                 goto err;
  443                         }
  444                 }
  445                 IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
  446                 ni->ni_noise = nf;
  447                 if (IEEE80211_HAS_SEQ(type, subtype) &&
  448                     IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
  449                         uint8_t tid = ieee80211_gettid(wh);
  450                         if (IEEE80211_QOS_HAS_SEQ(wh) &&
  451                             TID_TO_WME_AC(tid) >= WME_AC_VI)
  452                                 ic->ic_wme.wme_hipri_traffic++;
  453                         if (! ieee80211_check_rxseq(ni, wh, bssid, rxs))
  454                                 goto out;
  455                 }
  456         }
  457 
  458         switch (type) {
  459         case IEEE80211_FC0_TYPE_DATA:
  460                 hdrspace = ieee80211_hdrspace(ic, wh);
  461                 if (m->m_len < hdrspace &&
  462                     (m = m_pullup(m, hdrspace)) == NULL) {
  463                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
  464                             ni->ni_macaddr, NULL,
  465                             "data too short: expecting %u", hdrspace);
  466                         vap->iv_stats.is_rx_tooshort++;
  467                         goto out;               /* XXX */
  468                 }
  469                 if (dir != IEEE80211_FC1_DIR_NODS) {
  470                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  471                             wh, "data", "incorrect dir 0x%x", dir);
  472                         vap->iv_stats.is_rx_wrongdir++;
  473                         goto out;
  474                 }
  475                 /* XXX no power-save support */
  476 
  477                 /*
  478                  * Handle A-MPDU re-ordering.  If the frame is to be
  479                  * processed directly then ieee80211_ampdu_reorder
  480                  * will return 0; otherwise it has consumed the mbuf
  481                  * and we should do nothing more with it.
  482                  */
  483                 if ((m->m_flags & M_AMPDU) &&
  484                     ieee80211_ampdu_reorder(ni, m, rxs) != 0) {
  485                         m = NULL;
  486                         goto out;
  487                 }
  488         resubmit_ampdu:
  489 
  490                 /*
  491                  * Handle privacy requirements.  Note that we
  492                  * must not be preempted from here until after
  493                  * we (potentially) call ieee80211_crypto_demic;
  494                  * otherwise we may violate assumptions in the
  495                  * crypto cipher modules used to do delayed update
  496                  * of replay sequence numbers.
  497                  */
  498                 if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
  499                         if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
  500                                 /*
  501                                  * Discard encrypted frames when privacy is off.
  502                                  */
  503                                 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  504                                     wh, "WEP", "%s", "PRIVACY off");
  505                                 vap->iv_stats.is_rx_noprivacy++;
  506                                 IEEE80211_NODE_STAT(ni, rx_noprivacy);
  507                                 goto out;
  508                         }
  509                         if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
  510                                 /* NB: stats+msgs handled in crypto_decap */
  511                                 IEEE80211_NODE_STAT(ni, rx_wepfail);
  512                                 goto out;
  513                         }
  514                         wh = mtod(m, struct ieee80211_frame *);
  515                         wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
  516                         has_decrypted = 1;
  517                 } else {
  518                         /* XXX M_WEP and IEEE80211_F_PRIVACY */
  519                         key = NULL;
  520                 }
  521 
  522                 /*
  523                  * Save QoS bits for use below--before we strip the header.
  524                  */
  525                 if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
  526                         qos = (dir == IEEE80211_FC1_DIR_DSTODS) ?
  527                             ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] :
  528                             ((struct ieee80211_qosframe *)wh)->i_qos[0];
  529                 } else
  530                         qos = 0;
  531 
  532                 /*
  533                  * Next up, any fragmentation.
  534                  */
  535                 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
  536                         m = ieee80211_defrag(ni, m, hdrspace);
  537                         if (m == NULL) {
  538                                 /* Fragment dropped or frame not complete yet */
  539                                 goto out;
  540                         }
  541                 }
  542                 wh = NULL;              /* no longer valid, catch any uses */
  543 
  544                 /*
  545                  * Next strip any MSDU crypto bits.
  546                  */
  547                 if (!ieee80211_crypto_demic(vap, key, m, 0)) {
  548                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  549                             ni->ni_macaddr, "data", "%s", "demic error");
  550                         vap->iv_stats.is_rx_demicfail++;
  551                         IEEE80211_NODE_STAT(ni, rx_demicfail);
  552                         goto out;
  553                 }
  554 
  555                 /* copy to listener after decrypt */
  556                 if (ieee80211_radiotap_active_vap(vap))
  557                         ieee80211_radiotap_rx(vap, m);
  558                 need_tap = 0;
  559 
  560                 /*
  561                  * Finally, strip the 802.11 header.
  562                  */
  563                 m = ieee80211_decap(vap, m, hdrspace);
  564                 if (m == NULL) {
  565                         /* XXX mask bit to check for both */
  566                         /* don't count Null data frames as errors */
  567                         if (subtype == IEEE80211_FC0_SUBTYPE_NODATA ||
  568                             subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL)
  569                                 goto out;
  570                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  571                             ni->ni_macaddr, "data", "%s", "decap error");
  572                         vap->iv_stats.is_rx_decap++;
  573                         IEEE80211_NODE_STAT(ni, rx_decap);
  574                         goto err;
  575                 }
  576                 eh = mtod(m, struct ether_header *);
  577                 if (!ieee80211_node_is_authorized(ni)) {
  578                         /*
  579                          * Deny any non-PAE frames received prior to
  580                          * authorization.  For open/shared-key
  581                          * authentication the port is mark authorized
  582                          * after authentication completes.  For 802.1x
  583                          * the port is not marked authorized by the
  584                          * authenticator until the handshake has completed.
  585                          */
  586                         if (eh->ether_type != htons(ETHERTYPE_PAE)) {
  587                                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  588                                     eh->ether_shost, "data",
  589                                     "unauthorized port: ether type 0x%x len %u",
  590                                     eh->ether_type, m->m_pkthdr.len);
  591                                 vap->iv_stats.is_rx_unauth++;
  592                                 IEEE80211_NODE_STAT(ni, rx_unauth);
  593                                 goto err;
  594                         }
  595                 } else {
  596                         /*
  597                          * When denying unencrypted frames, discard
  598                          * any non-PAE frames received without encryption.
  599                          */
  600                         if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
  601                             ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
  602                             (is_hw_decrypted == 0) &&
  603                             eh->ether_type != htons(ETHERTYPE_PAE)) {
  604                                 /*
  605                                  * Drop unencrypted frames.
  606                                  */
  607                                 vap->iv_stats.is_rx_unencrypted++;
  608                                 IEEE80211_NODE_STAT(ni, rx_unencrypted);
  609                                 goto out;
  610                         }
  611                 }
  612                 /* XXX require HT? */
  613                 if (qos & IEEE80211_QOS_AMSDU) {
  614                         m = ieee80211_decap_amsdu(ni, m);
  615                         if (m == NULL)
  616                                 return IEEE80211_FC0_TYPE_DATA;
  617                 } else {
  618 #ifdef IEEE80211_SUPPORT_SUPERG
  619                         m = ieee80211_decap_fastframe(vap, ni, m);
  620                         if (m == NULL)
  621                                 return IEEE80211_FC0_TYPE_DATA;
  622 #endif
  623                 }
  624                 if (dir == IEEE80211_FC1_DIR_DSTODS && ni->ni_wdsvap != NULL)
  625                         ieee80211_deliver_data(ni->ni_wdsvap, ni, m);
  626                 else
  627                         ieee80211_deliver_data(vap, ni, m);
  628                 return IEEE80211_FC0_TYPE_DATA;
  629 
  630         case IEEE80211_FC0_TYPE_MGT:
  631                 vap->iv_stats.is_rx_mgmt++;
  632                 IEEE80211_NODE_STAT(ni, rx_mgmt);
  633                 if (dir != IEEE80211_FC1_DIR_NODS) {
  634                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  635                             wh, "data", "incorrect dir 0x%x", dir);
  636                         vap->iv_stats.is_rx_wrongdir++;
  637                         goto err;
  638                 }
  639                 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
  640                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
  641                             ni->ni_macaddr, "mgt", "too short: len %u",
  642                             m->m_pkthdr.len);
  643                         vap->iv_stats.is_rx_tooshort++;
  644                         goto out;
  645                 }
  646 #ifdef IEEE80211_DEBUG
  647                 if ((ieee80211_msg_debug(vap) && doprint(vap, subtype)) ||
  648                     ieee80211_msg_dumppkts(vap)) {
  649                         if_printf(ifp, "received %s from %s rssi %d\n",
  650                             ieee80211_mgt_subtype_name(subtype),
  651                             ether_sprintf(wh->i_addr2), rssi);
  652                 }
  653 #endif
  654                 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
  655                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  656                             wh, NULL, "%s", "WEP set but not permitted");
  657                         vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
  658                         goto out;
  659                 }
  660                 vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
  661                 goto out;
  662 
  663         case IEEE80211_FC0_TYPE_CTL:
  664                 vap->iv_stats.is_rx_ctl++;
  665                 IEEE80211_NODE_STAT(ni, rx_ctrl);
  666                 vap->iv_recv_ctl(ni, m, subtype);
  667                 goto out;
  668 
  669         default:
  670                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
  671                     wh, "bad", "frame type 0x%x", type);
  672                 /* should not come here */
  673                 break;
  674         }
  675 err:
  676         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  677 out:
  678         if (m != NULL) {
  679                 if (need_tap && ieee80211_radiotap_active_vap(vap))
  680                         ieee80211_radiotap_rx(vap, m);
  681                 m_freem(m);
  682         }
  683         return type;
  684 }
  685 
  686 static int
  687 is11bclient(const uint8_t *rates, const uint8_t *xrates)
  688 {
  689         static const uint32_t brates = (1<<2*1)|(1<<2*2)|(1<<11)|(1<<2*11);
  690         int i;
  691 
  692         /* NB: the 11b clients we care about will not have xrates */
  693         if (xrates != NULL || rates == NULL)
  694                 return 0;
  695         for (i = 0; i < rates[1]; i++) {
  696                 int r = rates[2+i] & IEEE80211_RATE_VAL;
  697                 if (r > 2*11 || ((1<<r) & brates) == 0)
  698                         return 0;
  699         }
  700         return 1;
  701 }
  702 
  703 static void
  704 adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
  705         int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
  706 {
  707         struct ieee80211vap *vap = ni->ni_vap;
  708         struct ieee80211com *ic = ni->ni_ic;
  709         struct ieee80211_channel *rxchan = ic->ic_curchan;
  710         struct ieee80211_frame *wh;
  711         uint8_t *frm, *efrm;
  712         uint8_t *ssid, *rates, *xrates;
  713 #if 0
  714         int ht_state_change = 0;
  715 #endif
  716 
  717         wh = mtod(m0, struct ieee80211_frame *);
  718         frm = (uint8_t *)&wh[1];
  719         efrm = mtod(m0, uint8_t *) + m0->m_len;
  720         switch (subtype) {
  721         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
  722         case IEEE80211_FC0_SUBTYPE_BEACON: {
  723                 struct ieee80211_scanparams scan;
  724                 struct ieee80211_channel *c;
  725                 /*
  726                  * We process beacon/probe response
  727                  * frames to discover neighbors.
  728                  */ 
  729                 if (rxs != NULL) {
  730                         c = ieee80211_lookup_channel_rxstatus(vap, rxs);
  731                         if (c != NULL)
  732                                 rxchan = c;
  733                 }
  734                 if (ieee80211_parse_beacon(ni, m0, rxchan, &scan) != 0)
  735                         return;
  736                 /*
  737                  * Count frame now that we know it's to be processed.
  738                  */
  739                 if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
  740                         vap->iv_stats.is_rx_beacon++;           /* XXX remove */
  741                         IEEE80211_NODE_STAT(ni, rx_beacons);
  742                 } else
  743                         IEEE80211_NODE_STAT(ni, rx_proberesp);
  744                 /*
  745                  * If scanning, just pass information to the scan module.
  746                  */
  747                 if (ic->ic_flags & IEEE80211_F_SCAN) {
  748                         if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) {
  749                                 /*
  750                                  * Actively scanning a channel marked passive;
  751                                  * send a probe request now that we know there
  752                                  * is 802.11 traffic present.
  753                                  *
  754                                  * XXX check if the beacon we recv'd gives
  755                                  * us what we need and suppress the probe req
  756                                  */
  757                                 ieee80211_probe_curchan(vap, 1);
  758                                 ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
  759                         }
  760                         ieee80211_add_scan(vap, rxchan, &scan, wh,
  761                             subtype, rssi, nf);
  762                         return;
  763                 }
  764                 if (scan.capinfo & IEEE80211_CAPINFO_IBSS) {
  765                         if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
  766                                 /*
  767                                  * Create a new entry in the neighbor table.
  768                                  *
  769                                  * XXX TODO:
  770                                  *
  771                                  * Here we're not scanning; so if we have an
  772                                  * SSID then make sure it matches our SSID.
  773                                  * Otherwise this code will match on all IBSS
  774                                  * beacons/probe requests for all SSIDs,
  775                                  * filling the node table with nodes that
  776                                  * aren't ours.
  777                                  */
  778                                 if (ieee80211_ibss_node_check_new(ni, &scan)) {
  779                                         ni = ieee80211_add_neighbor(vap, wh, &scan);
  780                                         /*
  781                                          * Send a probe request so we announce 11n
  782                                          * capabilities.
  783                                          */
  784                                         ieee80211_send_probereq(ni, /* node */
  785                                             vap->iv_myaddr, /* SA */
  786                                             ni->ni_macaddr, /* DA */
  787                                             vap->iv_bss->ni_bssid, /* BSSID */
  788                                             vap->iv_bss->ni_essid,
  789                                             vap->iv_bss->ni_esslen); /* SSID */
  790                                 } else
  791                                         ni = NULL;
  792 
  793                         } else if (ni->ni_capinfo == 0) {
  794                                 /*
  795                                  * Update faked node created on transmit.
  796                                  * Note this also updates the tsf.
  797                                  */
  798                                 ieee80211_init_neighbor(ni, wh, &scan);
  799 
  800                                 /*
  801                                  * Send a probe request so we announce 11n
  802                                  * capabilities.
  803                                  */
  804                                 ieee80211_send_probereq(ni, /* node */
  805                                         vap->iv_myaddr, /* SA */
  806                                         ni->ni_macaddr, /* DA */
  807                                         vap->iv_bss->ni_bssid, /* BSSID */
  808                                         vap->iv_bss->ni_essid,
  809                                         vap->iv_bss->ni_esslen); /* SSID */
  810                         } else {
  811                                 /*
  812                                  * Record tsf for potential resync.
  813                                  */
  814                                 memcpy(ni->ni_tstamp.data, scan.tstamp,
  815                                         sizeof(ni->ni_tstamp));
  816                         }
  817                         /*
  818                          * This isn't enabled yet - otherwise it would
  819                          * update the HT parameters and channel width
  820                          * from any node, which could lead to lots of
  821                          * strange behaviour if the 11n nodes aren't
  822                          * exactly configured to match.
  823                          */
  824 #if 0
  825                         if (scan.htcap != NULL && scan.htinfo != NULL &&
  826                             (vap->iv_flags_ht & IEEE80211_FHT_HT)) {
  827                                 ieee80211_ht_updateparams(ni,
  828                                     scan.htcap, scan.htinfo));
  829                                 if (ieee80211_ht_updateparams_final(ni,
  830                                     scan.htcap, scan.htinfo))
  831                                         ht_state_change = 1;
  832                         }
  833 
  834                         /* XXX same for VHT? */
  835 #endif
  836                         if (ni != NULL) {
  837                                 IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
  838                                 ni->ni_noise = nf;
  839                         }
  840                         /*
  841                          * Same here - the channel width change should
  842                          * be applied to the specific peer node, not
  843                          * to the ic.  Ie, the interface configuration
  844                          * should stay in its current channel width;
  845                          * but it should change the rate control and
  846                          * any queued frames for the given node only.
  847                          *
  848                          * Since there's no (current) way to inform
  849                          * the driver that a channel width change has
  850                          * occurred for a single node, just stub this
  851                          * out.
  852                          */
  853 #if 0
  854                         if (ht_state_change)
  855                                 ieee80211_update_chw(ic);
  856 #endif
  857                 }
  858                 break;
  859         }
  860 
  861         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
  862                 if (vap->iv_state != IEEE80211_S_RUN) {
  863                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  864                             wh, NULL, "wrong state %s",
  865                             ieee80211_state_name[vap->iv_state]);
  866                         vap->iv_stats.is_rx_mgtdiscard++;
  867                         return;
  868                 }
  869                 if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
  870                         /* frame must be directed */
  871                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  872                             wh, NULL, "%s", "not unicast");
  873                         vap->iv_stats.is_rx_mgtdiscard++;       /* XXX stat */
  874                         return;
  875                 }
  876 
  877                 /*
  878                  * prreq frame format
  879                  *      [tlv] ssid
  880                  *      [tlv] supported rates
  881                  *      [tlv] extended supported rates
  882                  */
  883                 ssid = rates = xrates = NULL;
  884                 while (efrm - frm > 1) {
  885                         IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
  886                         switch (*frm) {
  887                         case IEEE80211_ELEMID_SSID:
  888                                 ssid = frm;
  889                                 break;
  890                         case IEEE80211_ELEMID_RATES:
  891                                 rates = frm;
  892                                 break;
  893                         case IEEE80211_ELEMID_XRATES:
  894                                 xrates = frm;
  895                                 break;
  896                         }
  897                         frm += frm[1] + 2;
  898                 }
  899                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, return);
  900                 if (xrates != NULL)
  901                         IEEE80211_VERIFY_ELEMENT(xrates,
  902                                 IEEE80211_RATE_MAXSIZE - rates[1], return);
  903                 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, return);
  904                 IEEE80211_VERIFY_SSID(vap->iv_bss, ssid, return);
  905                 if ((vap->iv_flags & IEEE80211_F_HIDESSID) && ssid[1] == 0) {
  906                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  907                             wh, NULL,
  908                             "%s", "no ssid with ssid suppression enabled");
  909                         vap->iv_stats.is_rx_ssidmismatch++; /*XXX*/
  910                         return;
  911                 }
  912 
  913                 /* XXX find a better class or define it's own */
  914                 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
  915                     "%s", "recv probe req");
  916                 /*
  917                  * Some legacy 11b clients cannot hack a complete
  918                  * probe response frame.  When the request includes
  919                  * only a bare-bones rate set, communicate this to
  920                  * the transmit side.
  921                  */
  922                 ieee80211_send_proberesp(vap, wh->i_addr2,
  923                     is11bclient(rates, xrates) ? IEEE80211_SEND_LEGACY_11B : 0);
  924 
  925                 /*
  926                  * Note: we don't benefit from stashing the probe request
  927                  * IEs away to use for IBSS negotiation, because we
  928                  * typically don't get all of the IEs.
  929                  */
  930                 break;
  931 
  932         case IEEE80211_FC0_SUBTYPE_ACTION:
  933         case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
  934                 if ((ni == vap->iv_bss) &&
  935                     !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
  936                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  937                             wh, NULL, "%s", "unknown node");
  938                         vap->iv_stats.is_rx_mgtdiscard++;
  939                 } else if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) &&
  940                     !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
  941                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  942                             wh, NULL, "%s", "not for us");
  943                         vap->iv_stats.is_rx_mgtdiscard++;
  944                 } else if (vap->iv_state != IEEE80211_S_RUN) {
  945                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  946                             wh, NULL, "wrong state %s",
  947                             ieee80211_state_name[vap->iv_state]);
  948                         vap->iv_stats.is_rx_mgtdiscard++;
  949                 } else {
  950                         if (ieee80211_parse_action(ni, m0) == 0)
  951                                 (void)ic->ic_recv_action(ni, wh, frm, efrm);
  952                 }
  953                 break;
  954 
  955         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
  956         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
  957         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
  958         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
  959         case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
  960         case IEEE80211_FC0_SUBTYPE_ATIM:
  961         case IEEE80211_FC0_SUBTYPE_DISASSOC:
  962         case IEEE80211_FC0_SUBTYPE_AUTH:
  963         case IEEE80211_FC0_SUBTYPE_DEAUTH:
  964                 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  965                     wh, NULL, "%s", "not handled");
  966                 vap->iv_stats.is_rx_mgtdiscard++;
  967                 break;
  968 
  969         default:
  970                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
  971                     wh, "mgt", "subtype 0x%x not handled", subtype);
  972                 vap->iv_stats.is_rx_badsubtype++;
  973                 break;
  974         }
  975 }
  976 #undef IEEE80211_VERIFY_LENGTH
  977 #undef IEEE80211_VERIFY_ELEMENT
  978 
  979 static void
  980 ahdemo_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
  981         int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
  982 {
  983         struct ieee80211vap *vap = ni->ni_vap;
  984         struct ieee80211com *ic = ni->ni_ic;
  985         struct ieee80211_frame *wh;
  986 
  987         /*
  988          * Process management frames when scanning; useful for doing
  989          * a site-survey.
  990          */
  991         if (ic->ic_flags & IEEE80211_F_SCAN)
  992                 adhoc_recv_mgmt(ni, m0, subtype, rxs, rssi, nf);
  993         else {
  994                 wh = mtod(m0, struct ieee80211_frame *);
  995                 switch (subtype) {
  996                 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
  997                 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
  998                 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
  999                 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
 1000                 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
 1001                 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 1002                 case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
 1003                 case IEEE80211_FC0_SUBTYPE_BEACON:
 1004                 case IEEE80211_FC0_SUBTYPE_ATIM:
 1005                 case IEEE80211_FC0_SUBTYPE_DISASSOC:
 1006                 case IEEE80211_FC0_SUBTYPE_AUTH:
 1007                 case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1008                 case IEEE80211_FC0_SUBTYPE_ACTION:
 1009                 case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
 1010                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
 1011                              wh, NULL, "%s", "not handled");
 1012                         vap->iv_stats.is_rx_mgtdiscard++;
 1013                         break;
 1014                 default:
 1015                         IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
 1016                              wh, "mgt", "subtype 0x%x not handled", subtype);
 1017                         vap->iv_stats.is_rx_badsubtype++;
 1018                         break;
 1019                 }
 1020         }
 1021 }
 1022 
 1023 static void
 1024 adhoc_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
 1025 {
 1026 
 1027         switch (subtype) {
 1028         case IEEE80211_FC0_SUBTYPE_BAR:
 1029                 ieee80211_recv_bar(ni, m);
 1030                 break;
 1031         }
 1032 }

Cache object: 624e495f0b1f2e924b1fe3d9e5e17ac7


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