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$");
   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_DATA;
  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 || IEEE80211_IS_PROTECTED(wh)) {
  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_DATA)
  526                         qos = ieee80211_getqos(wh)[0];
  527                 else
  528                         qos = 0;
  529 
  530                 /*
  531                  * Next up, any fragmentation.
  532                  */
  533                 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
  534                         m = ieee80211_defrag(ni, m, hdrspace, has_decrypted);
  535                         if (m == NULL) {
  536                                 /* Fragment dropped or frame not complete yet */
  537                                 goto out;
  538                         }
  539                 }
  540                 wh = NULL;              /* no longer valid, catch any uses */
  541 
  542                 /*
  543                  * Next strip any MSDU crypto bits.
  544                  */
  545                 if (!ieee80211_crypto_demic(vap, key, m, 0)) {
  546                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  547                             ni->ni_macaddr, "data", "%s", "demic error");
  548                         vap->iv_stats.is_rx_demicfail++;
  549                         IEEE80211_NODE_STAT(ni, rx_demicfail);
  550                         goto out;
  551                 }
  552 
  553                 /* copy to listener after decrypt */
  554                 if (ieee80211_radiotap_active_vap(vap))
  555                         ieee80211_radiotap_rx(vap, m);
  556                 need_tap = 0;
  557 
  558                 /*
  559                  * Finally, strip the 802.11 header.
  560                  */
  561                 m = ieee80211_decap(vap, m, hdrspace, qos);
  562                 if (m == NULL) {
  563                         /* XXX mask bit to check for both */
  564                         /* don't count Null data frames as errors */
  565                         if (subtype == IEEE80211_FC0_SUBTYPE_NODATA ||
  566                             subtype == IEEE80211_FC0_SUBTYPE_QOS_NULL)
  567                                 goto out;
  568                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  569                             ni->ni_macaddr, "data", "%s", "decap error");
  570                         vap->iv_stats.is_rx_decap++;
  571                         IEEE80211_NODE_STAT(ni, rx_decap);
  572                         goto err;
  573                 }
  574                 if (!(qos & IEEE80211_QOS_AMSDU))
  575                         eh = mtod(m, struct ether_header *);
  576                 else
  577                         eh = NULL;
  578                 if (!ieee80211_node_is_authorized(ni)) {
  579                         /*
  580                          * Deny any non-PAE frames received prior to
  581                          * authorization.  For open/shared-key
  582                          * authentication the port is mark authorized
  583                          * after authentication completes.  For 802.1x
  584                          * the port is not marked authorized by the
  585                          * authenticator until the handshake has completed.
  586                          */
  587                         if (eh == NULL ||
  588                             eh->ether_type != htons(ETHERTYPE_PAE)) {
  589                                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
  590                                     ni->ni_macaddr, "data", "unauthorized or "
  591                                     "unknown port: ether type 0x%x len %u",
  592                                     eh == NULL ? -1 : eh->ether_type,
  593                                     m->m_pkthdr.len);
  594                                 vap->iv_stats.is_rx_unauth++;
  595                                 IEEE80211_NODE_STAT(ni, rx_unauth);
  596                                 goto err;
  597                         }
  598                 } else {
  599                         /*
  600                          * When denying unencrypted frames, discard
  601                          * any non-PAE frames received without encryption.
  602                          */
  603                         if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
  604                             ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
  605                             (is_hw_decrypted == 0) &&
  606                             (eh == NULL ||
  607                              eh->ether_type != htons(ETHERTYPE_PAE))) {
  608                                 /*
  609                                  * Drop unencrypted frames.
  610                                  */
  611                                 vap->iv_stats.is_rx_unencrypted++;
  612                                 IEEE80211_NODE_STAT(ni, rx_unencrypted);
  613                                 goto out;
  614                         }
  615                 }
  616                 /* XXX require HT? */
  617                 if (qos & IEEE80211_QOS_AMSDU) {
  618                         m = ieee80211_decap_amsdu(ni, m);
  619                         if (m == NULL)
  620                                 return IEEE80211_FC0_TYPE_DATA;
  621                 } else {
  622 #ifdef IEEE80211_SUPPORT_SUPERG
  623                         m = ieee80211_decap_fastframe(vap, ni, m);
  624                         if (m == NULL)
  625                                 return IEEE80211_FC0_TYPE_DATA;
  626 #endif
  627                 }
  628                 if (dir == IEEE80211_FC1_DIR_DSTODS && ni->ni_wdsvap != NULL)
  629                         ieee80211_deliver_data(ni->ni_wdsvap, ni, m);
  630                 else
  631                         ieee80211_deliver_data(vap, ni, m);
  632                 return IEEE80211_FC0_TYPE_DATA;
  633 
  634         case IEEE80211_FC0_TYPE_MGT:
  635                 vap->iv_stats.is_rx_mgmt++;
  636                 IEEE80211_NODE_STAT(ni, rx_mgmt);
  637                 if (dir != IEEE80211_FC1_DIR_NODS) {
  638                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  639                             wh, "data", "incorrect dir 0x%x", dir);
  640                         vap->iv_stats.is_rx_wrongdir++;
  641                         goto err;
  642                 }
  643                 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
  644                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
  645                             ni->ni_macaddr, "mgt", "too short: len %u",
  646                             m->m_pkthdr.len);
  647                         vap->iv_stats.is_rx_tooshort++;
  648                         goto out;
  649                 }
  650 #ifdef IEEE80211_DEBUG
  651                 if ((ieee80211_msg_debug(vap) && doprint(vap, subtype)) ||
  652                     ieee80211_msg_dumppkts(vap)) {
  653                         if_printf(ifp, "received %s from %s rssi %d\n",
  654                             ieee80211_mgt_subtype_name(subtype),
  655                             ether_sprintf(wh->i_addr2), rssi);
  656                 }
  657 #endif
  658                 if (IEEE80211_IS_PROTECTED(wh)) {
  659                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  660                             wh, NULL, "%s", "WEP set but not permitted");
  661                         vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
  662                         goto out;
  663                 }
  664                 vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
  665                 goto out;
  666 
  667         case IEEE80211_FC0_TYPE_CTL:
  668                 vap->iv_stats.is_rx_ctl++;
  669                 IEEE80211_NODE_STAT(ni, rx_ctrl);
  670                 vap->iv_recv_ctl(ni, m, subtype);
  671                 goto out;
  672 
  673         default:
  674                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
  675                     wh, "bad", "frame type 0x%x", type);
  676                 /* should not come here */
  677                 break;
  678         }
  679 err:
  680         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  681 out:
  682         if (m != NULL) {
  683                 if (need_tap && ieee80211_radiotap_active_vap(vap))
  684                         ieee80211_radiotap_rx(vap, m);
  685                 m_freem(m);
  686         }
  687         return type;
  688 }
  689 
  690 static int
  691 is11bclient(const uint8_t *rates, const uint8_t *xrates)
  692 {
  693         static const uint32_t brates = (1<<2*1)|(1<<2*2)|(1<<11)|(1<<2*11);
  694         int i;
  695 
  696         /* NB: the 11b clients we care about will not have xrates */
  697         if (xrates != NULL || rates == NULL)
  698                 return 0;
  699         for (i = 0; i < rates[1]; i++) {
  700                 int r = rates[2+i] & IEEE80211_RATE_VAL;
  701                 if (r > 2*11 || ((1<<r) & brates) == 0)
  702                         return 0;
  703         }
  704         return 1;
  705 }
  706 
  707 static void
  708 adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
  709         int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
  710 {
  711         struct ieee80211vap *vap = ni->ni_vap;
  712         struct ieee80211com *ic = ni->ni_ic;
  713         struct ieee80211_channel *rxchan = ic->ic_curchan;
  714         struct ieee80211_frame *wh;
  715         uint8_t *frm, *efrm;
  716         uint8_t *ssid, *rates, *xrates;
  717 #if 0
  718         int ht_state_change = 0;
  719 #endif
  720 
  721         wh = mtod(m0, struct ieee80211_frame *);
  722         frm = (uint8_t *)&wh[1];
  723         efrm = mtod(m0, uint8_t *) + m0->m_len;
  724 
  725         IEEE80211_DPRINTF(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_DEBUG,
  726             "%s: recv mgmt frame, addr2=%6D, ni=%p (%6D) fc=%.02x %.02x\n",
  727             __func__,
  728             wh->i_addr2, ":",
  729             ni,
  730             ni->ni_macaddr, ":",
  731             wh->i_fc[0],
  732             wh->i_fc[1]);
  733         switch (subtype) {
  734         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
  735         case IEEE80211_FC0_SUBTYPE_BEACON: {
  736                 struct ieee80211_scanparams scan;
  737                 struct ieee80211_channel *c;
  738                 /*
  739                  * We process beacon/probe response
  740                  * frames to discover neighbors.
  741                  */ 
  742                 if (rxs != NULL) {
  743                         c = ieee80211_lookup_channel_rxstatus(vap, rxs);
  744                         if (c != NULL)
  745                                 rxchan = c;
  746                 }
  747                 if (ieee80211_parse_beacon(ni, m0, rxchan, &scan) != 0)
  748                         return;
  749                 /*
  750                  * Count frame now that we know it's to be processed.
  751                  */
  752                 if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
  753                         vap->iv_stats.is_rx_beacon++;           /* XXX remove */
  754                         IEEE80211_NODE_STAT(ni, rx_beacons);
  755                 } else
  756                         IEEE80211_NODE_STAT(ni, rx_proberesp);
  757                 /*
  758                  * If scanning, just pass information to the scan module.
  759                  */
  760                 if (ic->ic_flags & IEEE80211_F_SCAN) {
  761                         if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) {
  762                                 /*
  763                                  * Actively scanning a channel marked passive;
  764                                  * send a probe request now that we know there
  765                                  * is 802.11 traffic present.
  766                                  *
  767                                  * XXX check if the beacon we recv'd gives
  768                                  * us what we need and suppress the probe req
  769                                  */
  770                                 ieee80211_probe_curchan(vap, 1);
  771                                 ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
  772                         }
  773                         ieee80211_add_scan(vap, rxchan, &scan, wh,
  774                             subtype, rssi, nf);
  775                         return;
  776                 }
  777                 if (scan.capinfo & IEEE80211_CAPINFO_IBSS) {
  778                         if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
  779                                 /*
  780                                  * Create a new entry in the neighbor table.
  781                                  *
  782                                  * XXX TODO:
  783                                  *
  784                                  * Here we're not scanning; so if we have an
  785                                  * SSID then make sure it matches our SSID.
  786                                  * Otherwise this code will match on all IBSS
  787                                  * beacons/probe requests for all SSIDs,
  788                                  * filling the node table with nodes that
  789                                  * aren't ours.
  790                                  */
  791                                 if (ieee80211_ibss_node_check_new(ni, &scan)) {
  792                                         ni = ieee80211_add_neighbor(vap, wh, &scan);
  793                                         /*
  794                                          * Send a probe request so we announce 11n
  795                                          * capabilities.
  796                                          */
  797                                         ieee80211_send_probereq(ni, /* node */
  798                                             vap->iv_myaddr, /* SA */
  799                                             ni->ni_macaddr, /* DA */
  800                                             vap->iv_bss->ni_bssid, /* BSSID */
  801                                             vap->iv_bss->ni_essid,
  802                                             vap->iv_bss->ni_esslen); /* SSID */
  803                                 } else
  804                                         ni = NULL;
  805 
  806                                 /*
  807                                  * Send a probe request so we announce 11n
  808                                  * capabilities.
  809                                  *
  810                                  * Don't do this if we're scanning.
  811                                  */
  812                                 if (! (ic->ic_flags & IEEE80211_F_SCAN))
  813                                         ieee80211_send_probereq(ni, /* node */
  814                                                 vap->iv_myaddr, /* SA */
  815                                                 ni->ni_macaddr, /* DA */
  816                                                 vap->iv_bss->ni_bssid, /* BSSID */
  817                                                 vap->iv_bss->ni_essid,
  818                                                 vap->iv_bss->ni_esslen); /* SSID */
  819 
  820                         } else if (ni->ni_capinfo == 0) {
  821                                 /*
  822                                  * Update faked node created on transmit.
  823                                  * Note this also updates the tsf.
  824                                  */
  825                                 ieee80211_init_neighbor(ni, wh, &scan);
  826 
  827                                 /*
  828                                  * Send a probe request so we announce 11n
  829                                  * capabilities.
  830                                  */
  831                                 ieee80211_send_probereq(ni, /* node */
  832                                         vap->iv_myaddr, /* SA */
  833                                         ni->ni_macaddr, /* DA */
  834                                         vap->iv_bss->ni_bssid, /* BSSID */
  835                                         vap->iv_bss->ni_essid,
  836                                         vap->iv_bss->ni_esslen); /* SSID */
  837                         } else {
  838                                 /*
  839                                  * Record tsf for potential resync.
  840                                  */
  841                                 memcpy(ni->ni_tstamp.data, scan.tstamp,
  842                                         sizeof(ni->ni_tstamp));
  843                         }
  844                         /*
  845                          * This isn't enabled yet - otherwise it would
  846                          * update the HT parameters and channel width
  847                          * from any node, which could lead to lots of
  848                          * strange behaviour if the 11n nodes aren't
  849                          * exactly configured to match.
  850                          */
  851 #if 0
  852                         if (scan.htcap != NULL && scan.htinfo != NULL &&
  853                             (vap->iv_flags_ht & IEEE80211_FHT_HT)) {
  854                                 ieee80211_ht_updateparams(ni,
  855                                     scan.htcap, scan.htinfo));
  856                                 if (ieee80211_ht_updateparams_final(ni,
  857                                     scan.htcap, scan.htinfo))
  858                                         ht_state_change = 1;
  859                         }
  860 
  861                         /* XXX same for VHT? */
  862 #endif
  863                         if (ni != NULL) {
  864                                 IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
  865                                 ni->ni_noise = nf;
  866                         }
  867                         /*
  868                          * Same here - the channel width change should
  869                          * be applied to the specific peer node, not
  870                          * to the ic.  Ie, the interface configuration
  871                          * should stay in its current channel width;
  872                          * but it should change the rate control and
  873                          * any queued frames for the given node only.
  874                          *
  875                          * Since there's no (current) way to inform
  876                          * the driver that a channel width change has
  877                          * occurred for a single node, just stub this
  878                          * out.
  879                          */
  880 #if 0
  881                         if (ht_state_change)
  882                                 ieee80211_update_chw(ic);
  883 #endif
  884                 }
  885                 break;
  886         }
  887 
  888         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
  889                 if (vap->iv_state != IEEE80211_S_RUN) {
  890                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  891                             wh, NULL, "wrong state %s",
  892                             ieee80211_state_name[vap->iv_state]);
  893                         vap->iv_stats.is_rx_mgtdiscard++;
  894                         return;
  895                 }
  896                 if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
  897                         /* frame must be directed */
  898                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  899                             wh, NULL, "%s", "not unicast");
  900                         vap->iv_stats.is_rx_mgtdiscard++;       /* XXX stat */
  901                         return;
  902                 }
  903 
  904                 /*
  905                  * prreq frame format
  906                  *      [tlv] ssid
  907                  *      [tlv] supported rates
  908                  *      [tlv] extended supported rates
  909                  */
  910                 ssid = rates = xrates = NULL;
  911                 while (efrm - frm > 1) {
  912                         IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
  913                         switch (*frm) {
  914                         case IEEE80211_ELEMID_SSID:
  915                                 ssid = frm;
  916                                 break;
  917                         case IEEE80211_ELEMID_RATES:
  918                                 rates = frm;
  919                                 break;
  920                         case IEEE80211_ELEMID_XRATES:
  921                                 xrates = frm;
  922                                 break;
  923                         }
  924                         frm += frm[1] + 2;
  925                 }
  926                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, return);
  927                 if (xrates != NULL)
  928                         IEEE80211_VERIFY_ELEMENT(xrates,
  929                                 IEEE80211_RATE_MAXSIZE - rates[1], return);
  930                 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, return);
  931                 IEEE80211_VERIFY_SSID(vap->iv_bss, ssid, return);
  932                 if ((vap->iv_flags & IEEE80211_F_HIDESSID) && ssid[1] == 0) {
  933                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  934                             wh, NULL,
  935                             "%s", "no ssid with ssid suppression enabled");
  936                         vap->iv_stats.is_rx_ssidmismatch++; /*XXX*/
  937                         return;
  938                 }
  939 
  940                 /* XXX find a better class or define it's own */
  941                 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
  942                     "%s", "recv probe req");
  943                 /*
  944                  * Some legacy 11b clients cannot hack a complete
  945                  * probe response frame.  When the request includes
  946                  * only a bare-bones rate set, communicate this to
  947                  * the transmit side.
  948                  */
  949                 ieee80211_send_proberesp(vap, wh->i_addr2,
  950                     is11bclient(rates, xrates) ? IEEE80211_SEND_LEGACY_11B : 0);
  951 
  952                 /*
  953                  * Note: we don't benefit from stashing the probe request
  954                  * IEs away to use for IBSS negotiation, because we
  955                  * typically don't get all of the IEs.
  956                  */
  957                 break;
  958 
  959         case IEEE80211_FC0_SUBTYPE_ACTION:
  960         case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
  961                 if ((ni == vap->iv_bss) &&
  962                     !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
  963                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  964                             wh, NULL, "%s", "unknown node");
  965                         vap->iv_stats.is_rx_mgtdiscard++;
  966                 } else if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) &&
  967                     !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
  968                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_DEBUG,
  969                             wh, NULL, "%s", "not for us");
  970                         vap->iv_stats.is_rx_mgtdiscard++;
  971                 } else if (vap->iv_state != IEEE80211_S_RUN) {
  972                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_DEBUG,
  973                             wh, NULL, "wrong state %s",
  974                             ieee80211_state_name[vap->iv_state]);
  975                         vap->iv_stats.is_rx_mgtdiscard++;
  976                 } else {
  977                         if (ieee80211_parse_action(ni, m0) == 0)
  978                                 (void)ic->ic_recv_action(ni, wh, frm, efrm);
  979                 }
  980                 break;
  981 
  982         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
  983         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
  984         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
  985         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
  986         case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
  987         case IEEE80211_FC0_SUBTYPE_ATIM:
  988         case IEEE80211_FC0_SUBTYPE_DISASSOC:
  989         case IEEE80211_FC0_SUBTYPE_AUTH:
  990         case IEEE80211_FC0_SUBTYPE_DEAUTH:
  991                 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
  992                     wh, NULL, "%s", "not handled");
  993                 vap->iv_stats.is_rx_mgtdiscard++;
  994                 break;
  995 
  996         default:
  997                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
  998                     wh, "mgt", "subtype 0x%x not handled", subtype);
  999                 vap->iv_stats.is_rx_badsubtype++;
 1000                 break;
 1001         }
 1002 }
 1003 #undef IEEE80211_VERIFY_LENGTH
 1004 #undef IEEE80211_VERIFY_ELEMENT
 1005 
 1006 static void
 1007 ahdemo_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
 1008         int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 1009 {
 1010         struct ieee80211vap *vap = ni->ni_vap;
 1011         struct ieee80211com *ic = ni->ni_ic;
 1012 
 1013         /*
 1014          * Process management frames when scanning; useful for doing
 1015          * a site-survey.
 1016          */
 1017         if (ic->ic_flags & IEEE80211_F_SCAN)
 1018                 adhoc_recv_mgmt(ni, m0, subtype, rxs, rssi, nf);
 1019         else {
 1020 #ifdef IEEE80211_DEBUG
 1021                 struct ieee80211_frame *wh;
 1022 
 1023                 wh = mtod(m0, struct ieee80211_frame *);
 1024 #endif
 1025                 switch (subtype) {
 1026                 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
 1027                 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
 1028                 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
 1029                 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
 1030                 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
 1031                 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 1032                 case IEEE80211_FC0_SUBTYPE_TIMING_ADV:
 1033                 case IEEE80211_FC0_SUBTYPE_BEACON:
 1034                 case IEEE80211_FC0_SUBTYPE_ATIM:
 1035                 case IEEE80211_FC0_SUBTYPE_DISASSOC:
 1036                 case IEEE80211_FC0_SUBTYPE_AUTH:
 1037                 case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1038                 case IEEE80211_FC0_SUBTYPE_ACTION:
 1039                 case IEEE80211_FC0_SUBTYPE_ACTION_NOACK:
 1040                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
 1041                              wh, NULL, "%s", "not handled");
 1042                         vap->iv_stats.is_rx_mgtdiscard++;
 1043                         break;
 1044                 default:
 1045                         IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
 1046                              wh, "mgt", "subtype 0x%x not handled", subtype);
 1047                         vap->iv_stats.is_rx_badsubtype++;
 1048                         break;
 1049                 }
 1050         }
 1051 }
 1052 
 1053 static void
 1054 adhoc_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
 1055 {
 1056 
 1057         switch (subtype) {
 1058         case IEEE80211_FC0_SUBTYPE_BAR:
 1059                 ieee80211_recv_bar(ni, m);
 1060                 break;
 1061         }
 1062 }

Cache object: f31cb71f276fb739f70ca3257b988664


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