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_input.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2001 Atsushi Onoe
    3  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * Alternatively, this software may be distributed under the terms of the
   18  * GNU General Public License ("GPL") version 2 as published by the Free
   19  * Software Foundation.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: releng/6.0/sys/net80211/ieee80211_input.c 149772 2005-09-03 22:40:02Z sam $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/mbuf.h>   
   39 #include <sys/malloc.h>
   40 #include <sys/endian.h>
   41 #include <sys/kernel.h>
   42  
   43 #include <sys/socket.h>
   44 
   45 #include <net/if.h>
   46 #include <net/if_media.h>
   47 #include <net/ethernet.h>
   48 #include <net/if_llc.h>
   49 #include <net/if_vlan_var.h>
   50 
   51 #include <net80211/ieee80211_var.h>
   52 
   53 #include <net/bpf.h>
   54 
   55 #ifdef IEEE80211_DEBUG
   56 #include <machine/stdarg.h>
   57 
   58 /*
   59  * Decide if a received management frame should be
   60  * printed when debugging is enabled.  This filters some
   61  * of the less interesting frames that come frequently
   62  * (e.g. beacons).
   63  */
   64 static __inline int
   65 doprint(struct ieee80211com *ic, int subtype)
   66 {
   67         switch (subtype) {
   68         case IEEE80211_FC0_SUBTYPE_BEACON:
   69                 return (ic->ic_flags & IEEE80211_F_SCAN);
   70         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
   71                 return (ic->ic_opmode == IEEE80211_M_IBSS);
   72         }
   73         return 1;
   74 }
   75 
   76 /*
   77  * Emit a debug message about discarding a frame or information
   78  * element.  One format is for extracting the mac address from
   79  * the frame header; the other is for when a header is not
   80  * available or otherwise appropriate.
   81  */
   82 #define IEEE80211_DISCARD(_ic, _m, _wh, _type, _fmt, ...) do {          \
   83         if ((_ic)->ic_debug & (_m))                                     \
   84                 ieee80211_discard_frame(_ic, _wh, _type, _fmt, __VA_ARGS__);\
   85 } while (0)
   86 #define IEEE80211_DISCARD_IE(_ic, _m, _wh, _type, _fmt, ...) do {       \
   87         if ((_ic)->ic_debug & (_m))                                     \
   88                 ieee80211_discard_ie(_ic, _wh, _type, _fmt, __VA_ARGS__);\
   89 } while (0)
   90 #define IEEE80211_DISCARD_MAC(_ic, _m, _mac, _type, _fmt, ...) do {     \
   91         if ((_ic)->ic_debug & (_m))                                     \
   92                 ieee80211_discard_mac(_ic, _mac, _type, _fmt, __VA_ARGS__);\
   93 } while (0)
   94 
   95 static const u_int8_t *ieee80211_getbssid(struct ieee80211com *,
   96         const struct ieee80211_frame *);
   97 static void ieee80211_discard_frame(struct ieee80211com *,
   98         const struct ieee80211_frame *, const char *type, const char *fmt, ...);
   99 static void ieee80211_discard_ie(struct ieee80211com *,
  100         const struct ieee80211_frame *, const char *type, const char *fmt, ...);
  101 static void ieee80211_discard_mac(struct ieee80211com *,
  102         const u_int8_t mac[IEEE80211_ADDR_LEN], const char *type,
  103         const char *fmt, ...);
  104 #else
  105 #define IEEE80211_DISCARD(_ic, _m, _wh, _type, _fmt, ...)
  106 #define IEEE80211_DISCARD_IE(_ic, _m, _wh, _type, _fmt, ...)
  107 #define IEEE80211_DISCARD_MAC(_ic, _m, _mac, _type, _fmt, ...)
  108 #endif /* IEEE80211_DEBUG */
  109 
  110 static struct mbuf *ieee80211_defrag(struct ieee80211com *,
  111         struct ieee80211_node *, struct mbuf *, int);
  112 static struct mbuf *ieee80211_decap(struct ieee80211com *, struct mbuf *, int);
  113 static void ieee80211_send_error(struct ieee80211com *, struct ieee80211_node *,
  114                 const u_int8_t *mac, int subtype, int arg);
  115 static void ieee80211_deliver_data(struct ieee80211com *,
  116         struct ieee80211_node *, struct mbuf *);
  117 static void ieee80211_node_pwrsave(struct ieee80211_node *, int enable);
  118 static void ieee80211_recv_pspoll(struct ieee80211com *,
  119         struct ieee80211_node *, struct mbuf *);
  120 
  121 /*
  122  * Process a received frame.  The node associated with the sender
  123  * should be supplied.  If nothing was found in the node table then
  124  * the caller is assumed to supply a reference to ic_bss instead.
  125  * The RSSI and a timestamp are also supplied.  The RSSI data is used
  126  * during AP scanning to select a AP to associate with; it can have
  127  * any units so long as values have consistent units and higher values
  128  * mean ``better signal''.  The receive timestamp is currently not used
  129  * by the 802.11 layer.
  130  */
  131 int
  132 ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
  133         struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
  134 {
  135 #define SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
  136 #define HAS_SEQ(type)   ((type & 0x4) == 0)
  137         struct ifnet *ifp = ic->ic_ifp;
  138         struct ieee80211_frame *wh;
  139         struct ieee80211_key *key;
  140         struct ether_header *eh;
  141         int hdrspace;
  142         u_int8_t dir, type, subtype;
  143         u_int8_t *bssid;
  144         u_int16_t rxseq;
  145 
  146         KASSERT(ni != NULL, ("null node"));
  147         ni->ni_inact = ni->ni_inact_reload;
  148 
  149         /* trim CRC here so WEP can find its own CRC at the end of packet. */
  150         if (m->m_flags & M_HASFCS) {
  151                 m_adj(m, -IEEE80211_CRC_LEN);
  152                 m->m_flags &= ~M_HASFCS;
  153         }
  154         type = -1;                      /* undefined */
  155         /*
  156          * In monitor mode, send everything directly to bpf.
  157          * XXX may want to include the CRC
  158          */
  159         if (ic->ic_opmode == IEEE80211_M_MONITOR)
  160                 goto out;
  161 
  162         if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
  163                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
  164                     ni->ni_macaddr, NULL,
  165                     "too short (1): len %u", m->m_pkthdr.len);
  166                 ic->ic_stats.is_rx_tooshort++;
  167                 goto out;
  168         }
  169         /*
  170          * Bit of a cheat here, we use a pointer for a 3-address
  171          * frame format but don't reference fields past outside
  172          * ieee80211_frame_min w/o first validating the data is
  173          * present.
  174          */
  175         wh = mtod(m, struct ieee80211_frame *);
  176 
  177         if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
  178             IEEE80211_FC0_VERSION_0) {
  179                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
  180                     ni->ni_macaddr, NULL, "wrong version %x", wh->i_fc[0]);
  181                 ic->ic_stats.is_rx_badversion++;
  182                 goto err;
  183         }
  184 
  185         dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
  186         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
  187         subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
  188         if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
  189                 switch (ic->ic_opmode) {
  190                 case IEEE80211_M_STA:
  191                         bssid = wh->i_addr2;
  192                         if (!IEEE80211_ADDR_EQ(bssid, ni->ni_bssid)) {
  193                                 /* not interested in */
  194                                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
  195                                     bssid, NULL, "%s", "not to bss");
  196                                 ic->ic_stats.is_rx_wrongbss++;
  197                                 goto out;
  198                         }
  199                         break;
  200                 case IEEE80211_M_IBSS:
  201                 case IEEE80211_M_AHDEMO:
  202                 case IEEE80211_M_HOSTAP:
  203                         if (dir != IEEE80211_FC1_DIR_NODS)
  204                                 bssid = wh->i_addr1;
  205                         else if (type == IEEE80211_FC0_TYPE_CTL)
  206                                 bssid = wh->i_addr1;
  207                         else {
  208                                 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
  209                                         IEEE80211_DISCARD_MAC(ic,
  210                                             IEEE80211_MSG_ANY, ni->ni_macaddr,
  211                                             NULL, "too short (2): len %u",
  212                                             m->m_pkthdr.len);
  213                                         ic->ic_stats.is_rx_tooshort++;
  214                                         goto out;
  215                                 }
  216                                 bssid = wh->i_addr3;
  217                         }
  218                         if (type != IEEE80211_FC0_TYPE_DATA)
  219                                 break;
  220                         /*
  221                          * Data frame, validate the bssid.
  222                          */
  223                         if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) &&
  224                             !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) {
  225                                 /* not interested in */
  226                                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
  227                                     bssid, NULL, "%s", "not to bss");
  228                                 ic->ic_stats.is_rx_wrongbss++;
  229                                 goto out;
  230                         }
  231                         /*
  232                          * For adhoc mode we cons up a node when it doesn't
  233                          * exist. This should probably done after an ACL check.
  234                          */
  235                         if (ni == ic->ic_bss &&
  236                             ic->ic_opmode != IEEE80211_M_HOSTAP) {
  237                                 /*
  238                                  * Fake up a node for this newly
  239                                  * discovered member of the IBSS.
  240                                  */
  241                                 ni = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
  242                                                     wh->i_addr2);
  243                                 if (ni == NULL) {
  244                                         /* NB: stat kept for alloc failure */
  245                                         goto err;
  246                                 }
  247                         }
  248                         break;
  249                 default:
  250                         goto out;
  251                 }
  252                 ni->ni_rssi = rssi;
  253                 ni->ni_rstamp = rstamp;
  254                 if (HAS_SEQ(type)) {
  255                         u_int8_t tid;
  256                         if (IEEE80211_QOS_HAS_SEQ(wh)) {
  257                                 tid = ((struct ieee80211_qosframe *)wh)->
  258                                         i_qos[0] & IEEE80211_QOS_TID;
  259                                 if (TID_TO_WME_AC(tid) >= WME_AC_VI)
  260                                         ic->ic_wme.wme_hipri_traffic++;
  261                                 tid++;
  262                         } else
  263                                 tid = 0;
  264                         rxseq = le16toh(*(u_int16_t *)wh->i_seq);
  265                         if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
  266                             SEQ_LEQ(rxseq, ni->ni_rxseqs[tid])) {
  267                                 /* duplicate, discard */
  268                                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
  269                                     bssid, "duplicate",
  270                                     "seqno <%u,%u> fragno <%u,%u> tid %u",
  271                                     rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
  272                                     ni->ni_rxseqs[tid] >>
  273                                         IEEE80211_SEQ_SEQ_SHIFT,
  274                                     rxseq & IEEE80211_SEQ_FRAG_MASK,
  275                                     ni->ni_rxseqs[tid] &
  276                                         IEEE80211_SEQ_FRAG_MASK,
  277                                     tid);
  278                                 ic->ic_stats.is_rx_dup++;
  279                                 IEEE80211_NODE_STAT(ni, rx_dup);
  280                                 goto out;
  281                         }
  282                         ni->ni_rxseqs[tid] = rxseq;
  283                 }
  284         }
  285 
  286         switch (type) {
  287         case IEEE80211_FC0_TYPE_DATA:
  288                 hdrspace = ieee80211_hdrspace(ic, wh);
  289                 if (m->m_len < hdrspace &&
  290                     (m = m_pullup(m, hdrspace)) == NULL) {
  291                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
  292                             ni->ni_macaddr, NULL,
  293                             "data too short: expecting %u", hdrspace);
  294                         ic->ic_stats.is_rx_tooshort++;
  295                         goto out;               /* XXX */
  296                 }
  297                 switch (ic->ic_opmode) {
  298                 case IEEE80211_M_STA:
  299                         if (dir != IEEE80211_FC1_DIR_FROMDS) {
  300                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  301                                     wh, "data", "%s", "unknown dir 0x%x", dir);
  302                                 ic->ic_stats.is_rx_wrongdir++;
  303                                 goto out;
  304                         }
  305                         if ((ifp->if_flags & IFF_SIMPLEX) &&
  306                             IEEE80211_IS_MULTICAST(wh->i_addr1) &&
  307                             IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
  308                                 /*
  309                                  * In IEEE802.11 network, multicast packet
  310                                  * sent from me is broadcasted from AP.
  311                                  * It should be silently discarded for
  312                                  * SIMPLEX interface.
  313                                  */
  314                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  315                                     wh, NULL, "%s", "multicast echo");
  316                                 ic->ic_stats.is_rx_mcastecho++;
  317                                 goto out;
  318                         }
  319                         break;
  320                 case IEEE80211_M_IBSS:
  321                 case IEEE80211_M_AHDEMO:
  322                         if (dir != IEEE80211_FC1_DIR_NODS) {
  323                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  324                                     wh, "data", "%s", "unknown dir 0x%x", dir);
  325                                 ic->ic_stats.is_rx_wrongdir++;
  326                                 goto out;
  327                         }
  328                         /* XXX no power-save support */
  329                         break;
  330                 case IEEE80211_M_HOSTAP:
  331                         if (dir != IEEE80211_FC1_DIR_TODS) {
  332                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  333                                     wh, "data", "%s", "unknown dir 0x%x", dir);
  334                                 ic->ic_stats.is_rx_wrongdir++;
  335                                 goto out;
  336                         }
  337                         /* check if source STA is associated */
  338                         if (ni == ic->ic_bss) {
  339                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  340                                     wh, "data", "%s", "unknown src");
  341                                 ieee80211_send_error(ic, ni, wh->i_addr2,
  342                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
  343                                     IEEE80211_REASON_NOT_AUTHED);
  344                                 ic->ic_stats.is_rx_notassoc++;
  345                                 goto err;
  346                         }
  347                         if (ni->ni_associd == 0) {
  348                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  349                                     wh, "data", "%s", "unassoc src");
  350                                 IEEE80211_SEND_MGMT(ic, ni,
  351                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
  352                                     IEEE80211_REASON_NOT_ASSOCED);
  353                                 ic->ic_stats.is_rx_notassoc++;
  354                                 goto err;
  355                         }
  356 
  357                         /*
  358                          * Check for power save state change.
  359                          */
  360                         if (((wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) ^
  361                             (ni->ni_flags & IEEE80211_NODE_PWR_MGT)))
  362                                 ieee80211_node_pwrsave(ni,
  363                                         wh->i_fc[1] & IEEE80211_FC1_PWR_MGT);
  364                         break;
  365                 default:
  366                         /* XXX here to keep compiler happy */
  367                         goto out;
  368                 }
  369 
  370                 /*
  371                  * Handle privacy requirements.  Note that we
  372                  * must not be preempted from here until after
  373                  * we (potentially) call ieee80211_crypto_demic;
  374                  * otherwise we may violate assumptions in the
  375                  * crypto cipher modules used to do delayed update
  376                  * of replay sequence numbers.
  377                  */
  378                 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
  379                         if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
  380                                 /*
  381                                  * Discard encrypted frames when privacy is off.
  382                                  */
  383                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  384                                     wh, "WEP", "%s", "PRIVACY off");
  385                                 ic->ic_stats.is_rx_noprivacy++;
  386                                 IEEE80211_NODE_STAT(ni, rx_noprivacy);
  387                                 goto out;
  388                         }
  389                         key = ieee80211_crypto_decap(ic, ni, m, hdrspace);
  390                         if (key == NULL) {
  391                                 /* NB: stats+msgs handled in crypto_decap */
  392                                 IEEE80211_NODE_STAT(ni, rx_wepfail);
  393                                 goto out;
  394                         }
  395                         wh = mtod(m, struct ieee80211_frame *);
  396                         wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
  397                 } else {
  398                         key = NULL;
  399                 }
  400 
  401                 /*
  402                  * Next up, any fragmentation.
  403                  */
  404                 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
  405                         m = ieee80211_defrag(ic, ni, m, hdrspace);
  406                         if (m == NULL) {
  407                                 /* Fragment dropped or frame not complete yet */
  408                                 goto out;
  409                         }
  410                 }
  411                 wh = NULL;              /* no longer valid, catch any uses */
  412 
  413                 /*
  414                  * Next strip any MSDU crypto bits.
  415                  */
  416                 if (key != NULL && !ieee80211_crypto_demic(ic, key, m, 0)) {
  417                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
  418                             ni->ni_macaddr, "data", "%s", "demic error");
  419                         IEEE80211_NODE_STAT(ni, rx_demicfail);
  420                         goto out;
  421                 }
  422 
  423                 /* copy to listener after decrypt */
  424                 if (ic->ic_rawbpf)
  425                         bpf_mtap(ic->ic_rawbpf, m);
  426 
  427                 /*
  428                  * Finally, strip the 802.11 header.
  429                  */
  430                 m = ieee80211_decap(ic, m, hdrspace);
  431                 if (m == NULL) {
  432                         /* don't count Null data frames as errors */
  433                         if (subtype == IEEE80211_FC0_SUBTYPE_NODATA)
  434                                 goto out;
  435                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
  436                             ni->ni_macaddr, "data", "%s", "decap error");
  437                         ic->ic_stats.is_rx_decap++;
  438                         IEEE80211_NODE_STAT(ni, rx_decap);
  439                         goto err;
  440                 }
  441                 eh = mtod(m, struct ether_header *);
  442                 if (!ieee80211_node_is_authorized(ni)) {
  443                         /*
  444                          * Deny any non-PAE frames received prior to
  445                          * authorization.  For open/shared-key
  446                          * authentication the port is mark authorized
  447                          * after authentication completes.  For 802.1x
  448                          * the port is not marked authorized by the
  449                          * authenticator until the handshake has completed.
  450                          */
  451                         if (eh->ether_type != htons(ETHERTYPE_PAE)) {
  452                                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
  453                                     eh->ether_shost, "data",
  454                                     "unauthorized port: ether type 0x%x len %u",
  455                                     eh->ether_type, m->m_pkthdr.len);
  456                                 ic->ic_stats.is_rx_unauth++;
  457                                 IEEE80211_NODE_STAT(ni, rx_unauth);
  458                                 goto err;
  459                         }
  460                 } else {
  461                         /*
  462                          * When denying unencrypted frames, discard
  463                          * any non-PAE frames received without encryption.
  464                          */
  465                         if ((ic->ic_flags & IEEE80211_F_DROPUNENC) &&
  466                             key == NULL &&
  467                             eh->ether_type != htons(ETHERTYPE_PAE)) {
  468                                 /*
  469                                  * Drop unencrypted frames.
  470                                  */
  471                                 ic->ic_stats.is_rx_unencrypted++;
  472                                 IEEE80211_NODE_STAT(ni, rx_unencrypted);
  473                                 goto out;
  474                         }
  475                 }
  476                 ifp->if_ipackets++;
  477                 IEEE80211_NODE_STAT(ni, rx_data);
  478                 IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len);
  479 
  480                 ieee80211_deliver_data(ic, ni, m);
  481                 return IEEE80211_FC0_TYPE_DATA;
  482 
  483         case IEEE80211_FC0_TYPE_MGT:
  484                 IEEE80211_NODE_STAT(ni, rx_mgmt);
  485                 if (dir != IEEE80211_FC1_DIR_NODS) {
  486                         IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  487                             wh, "data", "%s", "unknown dir 0x%x", dir);
  488                         ic->ic_stats.is_rx_wrongdir++;
  489                         goto err;
  490                 }
  491                 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
  492                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
  493                             ni->ni_macaddr, "mgt", "too short: len %u",
  494                             m->m_pkthdr.len);
  495                         ic->ic_stats.is_rx_tooshort++;
  496                         goto out;
  497                 }
  498 #ifdef IEEE80211_DEBUG
  499                 if ((ieee80211_msg_debug(ic) && doprint(ic, subtype)) ||
  500                     ieee80211_msg_dumppkts(ic)) {
  501                         if_printf(ic->ic_ifp, "received %s from %s rssi %d\n",
  502                             ieee80211_mgt_subtype_name[subtype >>
  503                                 IEEE80211_FC0_SUBTYPE_SHIFT],
  504                             ether_sprintf(wh->i_addr2), rssi);
  505                 }
  506 #endif
  507                 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
  508                         if (subtype != IEEE80211_FC0_SUBTYPE_AUTH) {
  509                                 /*
  510                                  * Only shared key auth frames with a challenge
  511                                  * should be encrypted, discard all others.
  512                                  */
  513                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  514                                     wh, ieee80211_mgt_subtype_name[subtype >>
  515                                         IEEE80211_FC0_SUBTYPE_SHIFT],
  516                                     "%s", "WEP set but not permitted");
  517                                 ic->ic_stats.is_rx_mgtdiscard++; /* XXX */
  518                                 goto out;
  519                         }
  520                         if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
  521                                 /*
  522                                  * Discard encrypted frames when privacy is off.
  523                                  */
  524                                 IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
  525                                     wh, "mgt", "%s", "WEP set but PRIVACY off");
  526                                 ic->ic_stats.is_rx_noprivacy++;
  527                                 goto out;
  528                         }
  529                         hdrspace = ieee80211_hdrspace(ic, wh);
  530                         key = ieee80211_crypto_decap(ic, ni, m, hdrspace);
  531                         if (key == NULL) {
  532                                 /* NB: stats+msgs handled in crypto_decap */
  533                                 goto out;
  534                         }
  535                         wh = mtod(m, struct ieee80211_frame *);
  536                         wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
  537                 }
  538                 if (ic->ic_rawbpf)
  539                         bpf_mtap(ic->ic_rawbpf, m);
  540                 (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
  541                 m_freem(m);
  542                 return type;
  543 
  544         case IEEE80211_FC0_TYPE_CTL:
  545                 IEEE80211_NODE_STAT(ni, rx_ctrl);
  546                 ic->ic_stats.is_rx_ctl++;
  547                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  548                         switch (subtype) {
  549                         case IEEE80211_FC0_SUBTYPE_PS_POLL:
  550                                 ieee80211_recv_pspoll(ic, ni, m);
  551                                 break;
  552                         }
  553                 }
  554                 goto out;
  555         default:
  556                 IEEE80211_DISCARD(ic, IEEE80211_MSG_ANY,
  557                     wh, NULL, "bad frame type 0x%x", type);
  558                 /* should not come here */
  559                 break;
  560         }
  561 err:
  562         ifp->if_ierrors++;
  563 out:
  564         if (m != NULL) {
  565                 if (ic->ic_rawbpf)
  566                         bpf_mtap(ic->ic_rawbpf, m);
  567                 m_freem(m);
  568         }
  569         return type;
  570 #undef SEQ_LEQ
  571 }
  572 
  573 /*
  574  * This function reassemble fragments.
  575  */
  576 static struct mbuf *
  577 ieee80211_defrag(struct ieee80211com *ic, struct ieee80211_node *ni,
  578         struct mbuf *m, int hdrspace)
  579 {
  580         struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
  581         struct ieee80211_frame *lwh;
  582         u_int16_t rxseq;
  583         u_int8_t fragno;
  584         u_int8_t more_frag = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
  585         struct mbuf *mfrag;
  586 
  587         KASSERT(!IEEE80211_IS_MULTICAST(wh->i_addr1), ("multicast fragm?"));
  588 
  589         rxseq = le16toh(*(u_int16_t *)wh->i_seq);
  590         fragno = rxseq & IEEE80211_SEQ_FRAG_MASK;
  591 
  592         /* Quick way out, if there's nothing to defragment */
  593         if (!more_frag && fragno == 0 && ni->ni_rxfrag[0] == NULL)
  594                 return m;
  595 
  596         /*
  597          * Remove frag to insure it doesn't get reaped by timer.
  598          */
  599         if (ni->ni_table == NULL) {
  600                 /*
  601                  * Should never happen.  If the node is orphaned (not in
  602                  * the table) then input packets should not reach here.
  603                  * Otherwise, a concurrent request that yanks the table
  604                  * should be blocked by other interlocking and/or by first
  605                  * shutting the driver down.  Regardless, be defensive
  606                  * here and just bail
  607                  */
  608                 /* XXX need msg+stat */
  609                 m_freem(m);
  610                 return NULL;
  611         }
  612         IEEE80211_NODE_LOCK(ni->ni_table);
  613         mfrag = ni->ni_rxfrag[0];
  614         ni->ni_rxfrag[0] = NULL;
  615         IEEE80211_NODE_UNLOCK(ni->ni_table);
  616 
  617         /*
  618          * Validate new fragment is in order and
  619          * related to the previous ones.
  620          */
  621         if (mfrag != NULL) {
  622                 u_int16_t last_rxseq;
  623 
  624                 lwh = mtod(mfrag, struct ieee80211_frame *);
  625                 last_rxseq = le16toh(*(u_int16_t *)lwh->i_seq);
  626                 /* NB: check seq # and frag together */
  627                 if (rxseq != last_rxseq+1 ||
  628                     !IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
  629                     !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
  630                         /*
  631                          * Unrelated fragment or no space for it,
  632                          * clear current fragments.
  633                          */
  634                         m_freem(mfrag);
  635                         mfrag = NULL;
  636                 }
  637         }
  638 
  639         if (mfrag == NULL) {
  640                 if (fragno != 0) {              /* !first fragment, discard */
  641                         IEEE80211_NODE_STAT(ni, rx_defrag);
  642                         m_freem(m);
  643                         return NULL;
  644                 }
  645                 mfrag = m;
  646         } else {                                /* concatenate */
  647                 m_adj(m, hdrspace);             /* strip header */
  648                 m_cat(mfrag, m);
  649                 /* NB: m_cat doesn't update the packet header */
  650                 mfrag->m_pkthdr.len += m->m_pkthdr.len;
  651                 /* track last seqnum and fragno */
  652                 lwh = mtod(mfrag, struct ieee80211_frame *);
  653                 *(u_int16_t *) lwh->i_seq = *(u_int16_t *) wh->i_seq;
  654         }
  655         if (more_frag) {                        /* more to come, save */
  656                 ni->ni_rxfragstamp = ticks;
  657                 ni->ni_rxfrag[0] = mfrag;
  658                 mfrag = NULL;
  659         }
  660         return mfrag;
  661 }
  662 
  663 static void
  664 ieee80211_deliver_data(struct ieee80211com *ic,
  665         struct ieee80211_node *ni, struct mbuf *m)
  666 {
  667         struct ether_header *eh = mtod(m, struct ether_header *);
  668         struct ifnet *ifp = ic->ic_ifp;
  669 
  670         /* perform as a bridge within the AP */
  671         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  672             (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0) {
  673                 struct mbuf *m1 = NULL;
  674 
  675                 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
  676                         m1 = m_copypacket(m, M_DONTWAIT);
  677                         if (m1 == NULL)
  678                                 ifp->if_oerrors++;
  679                         else
  680                                 m1->m_flags |= M_MCAST;
  681                 } else {
  682                         /*
  683                          * Check if the destination is known; if so
  684                          * and the port is authorized dispatch directly.
  685                          */
  686                         struct ieee80211_node *sta =
  687                             ieee80211_find_node(&ic->ic_sta, eh->ether_dhost);
  688                         if (sta != NULL) {
  689                                 if (ieee80211_node_is_authorized(sta)) {
  690                                         /*
  691                                          * Beware of sending to ourself; this
  692                                          * needs to happen via the normal
  693                                          * input path.
  694                                          */
  695                                         if (sta != ic->ic_bss) {
  696                                                 m1 = m;
  697                                                 m = NULL;
  698                                         }
  699                                 } else {
  700                                         ic->ic_stats.is_rx_unauth++;
  701                                         IEEE80211_NODE_STAT(sta, rx_unauth);
  702                                 }
  703                                 ieee80211_free_node(sta);
  704                         }
  705                 }
  706                 if (m1 != NULL)
  707                         IF_HANDOFF(&ifp->if_snd, m1, ifp);
  708         }
  709         if (m != NULL) {
  710                 if (ni->ni_vlan != 0) {
  711                         /* attach vlan tag */
  712                         /* XXX goto err? */
  713                         VLAN_INPUT_TAG(ifp, m, ni->ni_vlan, goto out);
  714                 }
  715                 (*ifp->if_input)(ifp, m);
  716         }
  717         return;
  718   out:
  719         if (m != NULL) {
  720                 if (ic->ic_rawbpf)
  721                         bpf_mtap(ic->ic_rawbpf, m);
  722                 m_freem(m);
  723         }
  724 }
  725 
  726 static struct mbuf *
  727 ieee80211_decap(struct ieee80211com *ic, struct mbuf *m, int hdrlen)
  728 {
  729         struct ieee80211_qosframe_addr4 wh;     /* Max size address frames */
  730         struct ether_header *eh;
  731         struct llc *llc;
  732 
  733         if (m->m_len < hdrlen + sizeof(*llc) &&
  734             (m = m_pullup(m, hdrlen + sizeof(*llc))) == NULL) {
  735                 /* XXX stat, msg */
  736                 return NULL;
  737         }
  738         memcpy(&wh, mtod(m, caddr_t), hdrlen);
  739         llc = (struct llc *)(mtod(m, caddr_t) + hdrlen);
  740         if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
  741             llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
  742             llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
  743                 m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
  744                 llc = NULL;
  745         } else {
  746                 m_adj(m, hdrlen - sizeof(*eh));
  747         }
  748         eh = mtod(m, struct ether_header *);
  749         switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
  750         case IEEE80211_FC1_DIR_NODS:
  751                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
  752                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
  753                 break;
  754         case IEEE80211_FC1_DIR_TODS:
  755                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
  756                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
  757                 break;
  758         case IEEE80211_FC1_DIR_FROMDS:
  759                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
  760                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
  761                 break;
  762         case IEEE80211_FC1_DIR_DSTODS:
  763                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
  764                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr4);
  765                 break;
  766         }
  767 #ifdef ALIGNED_POINTER
  768         if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
  769                 struct mbuf *n, *n0, **np;
  770                 caddr_t newdata;
  771                 int off, pktlen;
  772 
  773                 n0 = NULL;
  774                 np = &n0;
  775                 off = 0;
  776                 pktlen = m->m_pkthdr.len;
  777                 while (pktlen > off) {
  778                         if (n0 == NULL) {
  779                                 MGETHDR(n, M_DONTWAIT, MT_DATA);
  780                                 if (n == NULL) {
  781                                         m_freem(m);
  782                                         return NULL;
  783                                 }
  784                                 M_MOVE_PKTHDR(n, m);
  785                                 n->m_len = MHLEN;
  786                         } else {
  787                                 MGET(n, M_DONTWAIT, MT_DATA);
  788                                 if (n == NULL) {
  789                                         m_freem(m);
  790                                         m_freem(n0);
  791                                         return NULL;
  792                                 }
  793                                 n->m_len = MLEN;
  794                         }
  795                         if (pktlen - off >= MINCLSIZE) {
  796                                 MCLGET(n, M_DONTWAIT);
  797                                 if (n->m_flags & M_EXT)
  798                                         n->m_len = n->m_ext.ext_size;
  799                         }
  800                         if (n0 == NULL) {
  801                                 newdata =
  802                                     (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
  803                                     sizeof(*eh);
  804                                 n->m_len -= newdata - n->m_data;
  805                                 n->m_data = newdata;
  806                         }
  807                         if (n->m_len > pktlen - off)
  808                                 n->m_len = pktlen - off;
  809                         m_copydata(m, off, n->m_len, mtod(n, caddr_t));
  810                         off += n->m_len;
  811                         *np = n;
  812                         np = &n->m_next;
  813                 }
  814                 m_freem(m);
  815                 m = n0;
  816         }
  817 #endif /* ALIGNED_POINTER */
  818         if (llc != NULL) {
  819                 eh = mtod(m, struct ether_header *);
  820                 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
  821         }
  822         return m;
  823 }
  824 
  825 /*
  826  * Install received rate set information in the node's state block.
  827  */
  828 int
  829 ieee80211_setup_rates(struct ieee80211_node *ni,
  830         const u_int8_t *rates, const u_int8_t *xrates, int flags)
  831 {
  832         struct ieee80211com *ic = ni->ni_ic;
  833         struct ieee80211_rateset *rs = &ni->ni_rates;
  834 
  835         memset(rs, 0, sizeof(*rs));
  836         rs->rs_nrates = rates[1];
  837         memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);
  838         if (xrates != NULL) {
  839                 u_int8_t nxrates;
  840                 /*
  841                  * Tack on 11g extended supported rate element.
  842                  */
  843                 nxrates = xrates[1];
  844                 if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
  845                         nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;
  846                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_XRATE,
  847                              "[%s] extended rate set too large;"
  848                              " only using %u of %u rates\n",
  849                              ether_sprintf(ni->ni_macaddr), nxrates, xrates[1]);
  850                         ic->ic_stats.is_rx_rstoobig++;
  851                 }
  852                 memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
  853                 rs->rs_nrates += nxrates;
  854         }
  855         return ieee80211_fix_rate(ni, flags);
  856 }
  857 
  858 static void
  859 ieee80211_auth_open(struct ieee80211com *ic, struct ieee80211_frame *wh,
  860     struct ieee80211_node *ni, int rssi, u_int32_t rstamp, u_int16_t seq,
  861     u_int16_t status)
  862 {
  863 
  864         if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
  865                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
  866                     ni->ni_macaddr, "open auth",
  867                     "bad sta auth mode %u", ni->ni_authmode);
  868                 ic->ic_stats.is_rx_bad_auth++;  /* XXX */
  869                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  870                         /* XXX hack to workaround calling convention */
  871                         ieee80211_send_error(ic, ni, wh->i_addr2, 
  872                             IEEE80211_FC0_SUBTYPE_AUTH,
  873                             (seq + 1) | (IEEE80211_STATUS_ALG<<16));
  874                 }
  875                 return;
  876         }
  877         switch (ic->ic_opmode) {
  878         case IEEE80211_M_IBSS:
  879         case IEEE80211_M_AHDEMO:
  880         case IEEE80211_M_MONITOR:
  881                 /* should not come here */
  882                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
  883                     ni->ni_macaddr, "open auth",
  884                     "bad operating mode %u", ic->ic_opmode);
  885                 break;
  886 
  887         case IEEE80211_M_HOSTAP:
  888                 if (ic->ic_state != IEEE80211_S_RUN ||
  889                     seq != IEEE80211_AUTH_OPEN_REQUEST) {
  890                         ic->ic_stats.is_rx_bad_auth++;
  891                         return;
  892                 }
  893                 /* always accept open authentication requests */
  894                 if (ni == ic->ic_bss) {
  895                         ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);
  896                         if (ni == NULL)
  897                                 return;
  898                 } else if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
  899                         (void) ieee80211_ref_node(ni);
  900                 /*
  901                  * Mark the node as referenced to reflect that it's
  902                  * reference count has been bumped to insure it remains
  903                  * after the transaction completes.
  904                  */
  905                 ni->ni_flags |= IEEE80211_NODE_AREF;
  906 
  907                 IEEE80211_SEND_MGMT(ic, ni,
  908                         IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
  909                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  910                     "[%s] station authenticated (open)\n",
  911                     ether_sprintf(ni->ni_macaddr));
  912                 /*
  913                  * When 802.1x is not in use mark the port
  914                  * authorized at this point so traffic can flow.
  915                  */
  916                 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
  917                         ieee80211_node_authorize(ni);
  918                 break;
  919 
  920         case IEEE80211_M_STA:
  921                 if (ic->ic_state != IEEE80211_S_AUTH ||
  922                     seq != IEEE80211_AUTH_OPEN_RESPONSE) {
  923                         ic->ic_stats.is_rx_bad_auth++;
  924                         return;
  925                 }
  926                 if (status != 0) {
  927                         IEEE80211_DPRINTF(ic,
  928                             IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  929                             "[%s] open auth failed (reason %d)\n",
  930                             ether_sprintf(ni->ni_macaddr), status);
  931                         /* XXX can this happen? */
  932                         if (ni != ic->ic_bss)
  933                                 ni->ni_fails++;
  934                         ic->ic_stats.is_rx_auth_fail++;
  935                         ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
  936                 } else
  937                         ieee80211_new_state(ic, IEEE80211_S_ASSOC,
  938                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
  939                 break;
  940         }
  941 }
  942 
  943 /*
  944  * Send a management frame error response to the specified
  945  * station.  If ni is associated with the station then use
  946  * it; otherwise allocate a temporary node suitable for
  947  * transmitting the frame and then free the reference so
  948  * it will go away as soon as the frame has been transmitted.
  949  */
  950 static void
  951 ieee80211_send_error(struct ieee80211com *ic, struct ieee80211_node *ni,
  952         const u_int8_t *mac, int subtype, int arg)
  953 {
  954         int istmp;
  955 
  956         if (ni == ic->ic_bss) {
  957                 ni = ieee80211_tmp_node(ic, mac);
  958                 if (ni == NULL) {
  959                         /* XXX msg */
  960                         return;
  961                 }
  962                 istmp = 1;
  963         } else
  964                 istmp = 0;
  965         IEEE80211_SEND_MGMT(ic, ni, subtype, arg);
  966         if (istmp)
  967                 ieee80211_free_node(ni);
  968 }
  969 
  970 static int
  971 alloc_challenge(struct ieee80211com *ic, struct ieee80211_node *ni)
  972 {
  973         if (ni->ni_challenge == NULL)
  974                 MALLOC(ni->ni_challenge, u_int32_t*, IEEE80211_CHALLENGE_LEN,
  975                     M_DEVBUF, M_NOWAIT);
  976         if (ni->ni_challenge == NULL) {
  977                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  978                     "[%s] shared key challenge alloc failed\n",
  979                     ether_sprintf(ni->ni_macaddr));
  980                 /* XXX statistic */
  981         }
  982         return (ni->ni_challenge != NULL);
  983 }
  984 
  985 /* XXX TODO: add statistics */
  986 static void
  987 ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh,
  988     u_int8_t *frm, u_int8_t *efrm, struct ieee80211_node *ni, int rssi,
  989     u_int32_t rstamp, u_int16_t seq, u_int16_t status)
  990 {
  991         u_int8_t *challenge;
  992         int allocbs, estatus;
  993 
  994         /*
  995          * NB: this can happen as we allow pre-shared key
  996          * authentication to be enabled w/o wep being turned
  997          * on so that configuration of these can be done
  998          * in any order.  It may be better to enforce the
  999          * ordering in which case this check would just be
 1000          * for sanity/consistency.
 1001          */
 1002         if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
 1003                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1004                     ni->ni_macaddr, "shared key auth",
 1005                     "%s", " PRIVACY is disabled");
 1006                 estatus = IEEE80211_STATUS_ALG;
 1007                 goto bad;
 1008         }
 1009         /*
 1010          * Pre-shared key authentication is evil; accept
 1011          * it only if explicitly configured (it is supported
 1012          * mainly for compatibility with clients like OS X).
 1013          */
 1014         if (ni->ni_authmode != IEEE80211_AUTH_AUTO &&
 1015             ni->ni_authmode != IEEE80211_AUTH_SHARED) {
 1016                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1017                     ni->ni_macaddr, "shared key auth",
 1018                     "bad sta auth mode %u", ni->ni_authmode);
 1019                 ic->ic_stats.is_rx_bad_auth++;  /* XXX maybe a unique error? */
 1020                 estatus = IEEE80211_STATUS_ALG;
 1021                 goto bad;
 1022         }
 1023 
 1024         challenge = NULL;
 1025         if (frm + 1 < efrm) {
 1026                 if ((frm[1] + 2) > (efrm - frm)) {
 1027                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1028                             ni->ni_macaddr, "shared key auth",
 1029                             "ie %d/%d too long",
 1030                             frm[0], (frm[1] + 2) - (efrm - frm));
 1031                         ic->ic_stats.is_rx_bad_auth++;
 1032                         estatus = IEEE80211_STATUS_CHALLENGE;
 1033                         goto bad;
 1034                 }
 1035                 if (*frm == IEEE80211_ELEMID_CHALLENGE)
 1036                         challenge = frm;
 1037                 frm += frm[1] + 2;
 1038         }
 1039         switch (seq) {
 1040         case IEEE80211_AUTH_SHARED_CHALLENGE:
 1041         case IEEE80211_AUTH_SHARED_RESPONSE:
 1042                 if (challenge == NULL) {
 1043                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1044                             ni->ni_macaddr, "shared key auth",
 1045                             "%s", "no challenge");
 1046                         ic->ic_stats.is_rx_bad_auth++;
 1047                         estatus = IEEE80211_STATUS_CHALLENGE;
 1048                         goto bad;
 1049                 }
 1050                 if (challenge[1] != IEEE80211_CHALLENGE_LEN) {
 1051                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1052                             ni->ni_macaddr, "shared key auth",
 1053                             "bad challenge len %d", challenge[1]);
 1054                         ic->ic_stats.is_rx_bad_auth++;
 1055                         estatus = IEEE80211_STATUS_CHALLENGE;
 1056                         goto bad;
 1057                 }
 1058         default:
 1059                 break;
 1060         }
 1061         switch (ic->ic_opmode) {
 1062         case IEEE80211_M_MONITOR:
 1063         case IEEE80211_M_AHDEMO:
 1064         case IEEE80211_M_IBSS:
 1065                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1066                     ni->ni_macaddr, "shared key auth",
 1067                     "bad operating mode %u", ic->ic_opmode);
 1068                 return;
 1069         case IEEE80211_M_HOSTAP:
 1070                 if (ic->ic_state != IEEE80211_S_RUN) {
 1071                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1072                             ni->ni_macaddr, "shared key auth",
 1073                             "bad state %u", ic->ic_state);
 1074                         estatus = IEEE80211_STATUS_ALG; /* XXX */
 1075                         goto bad;
 1076                 }
 1077                 switch (seq) {
 1078                 case IEEE80211_AUTH_SHARED_REQUEST:
 1079                         if (ni == ic->ic_bss) {
 1080                                 ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);
 1081                                 if (ni == NULL) {
 1082                                         /* NB: no way to return an error */
 1083                                         return;
 1084                                 }
 1085                                 allocbs = 1;
 1086                         } else {
 1087                                 if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
 1088                                         (void) ieee80211_ref_node(ni);
 1089                                 allocbs = 0;
 1090                         }
 1091                         /*
 1092                          * Mark the node as referenced to reflect that it's
 1093                          * reference count has been bumped to insure it remains
 1094                          * after the transaction completes.
 1095                          */
 1096                         ni->ni_flags |= IEEE80211_NODE_AREF;
 1097                         ni->ni_rssi = rssi;
 1098                         ni->ni_rstamp = rstamp;
 1099                         if (!alloc_challenge(ic, ni)) {
 1100                                 /* NB: don't return error so they rexmit */
 1101                                 return;
 1102                         }
 1103                         get_random_bytes(ni->ni_challenge,
 1104                                 IEEE80211_CHALLENGE_LEN);
 1105                         IEEE80211_DPRINTF(ic,
 1106                                 IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
 1107                                 "[%s] shared key %sauth request\n",
 1108                                 ether_sprintf(ni->ni_macaddr),
 1109                                 allocbs ? "" : "re");
 1110                         break;
 1111                 case IEEE80211_AUTH_SHARED_RESPONSE:
 1112                         if (ni == ic->ic_bss) {
 1113                                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1114                                     ni->ni_macaddr, "shared key response",
 1115                                     "%s", "unknown station");
 1116                                 /* NB: don't send a response */
 1117                                 return;
 1118                         }
 1119                         if (ni->ni_challenge == NULL) {
 1120                                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1121                                     ni->ni_macaddr, "shared key response",
 1122                                     "%s", "no challenge recorded");
 1123                                 ic->ic_stats.is_rx_bad_auth++;
 1124                                 estatus = IEEE80211_STATUS_CHALLENGE;
 1125                                 goto bad;
 1126                         }
 1127                         if (memcmp(ni->ni_challenge, &challenge[2],
 1128                                    challenge[1]) != 0) {
 1129                                 IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1130                                     ni->ni_macaddr, "shared key response",
 1131                                     "%s", "challenge mismatch");
 1132                                 ic->ic_stats.is_rx_auth_fail++;
 1133                                 estatus = IEEE80211_STATUS_CHALLENGE;
 1134                                 goto bad;
 1135                         }
 1136                         IEEE80211_DPRINTF(ic,
 1137                             IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
 1138                             "[%s] station authenticated (shared key)\n",
 1139                             ether_sprintf(ni->ni_macaddr));
 1140                         ieee80211_node_authorize(ni);
 1141                         break;
 1142                 default:
 1143                         IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_AUTH,
 1144                             ni->ni_macaddr, "shared key auth",
 1145                             "bad seq %d", seq);
 1146                         ic->ic_stats.is_rx_bad_auth++;
 1147                         estatus = IEEE80211_STATUS_SEQUENCE;
 1148                         goto bad;
 1149                 }
 1150                 IEEE80211_SEND_MGMT(ic, ni,
 1151                         IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
 1152                 break;
 1153 
 1154         case IEEE80211_M_STA:
 1155                 if (ic->ic_state != IEEE80211_S_AUTH)
 1156                         return;
 1157                 switch (seq) {
 1158                 case IEEE80211_AUTH_SHARED_PASS:
 1159                         if (ni->ni_challenge != NULL) {
 1160                                 FREE(ni->ni_challenge, M_DEVBUF);
 1161                                 ni->ni_challenge = NULL;
 1162                         }
 1163                         if (status != 0) {
 1164                                 IEEE80211_DPRINTF(ic,
 1165                                     IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
 1166                                     "[%s] shared key auth failed (reason %d)\n",
 1167                                     ether_sprintf(ieee80211_getbssid(ic, wh)),
 1168                                     status);
 1169                                 /* XXX can this happen? */
 1170                                 if (ni != ic->ic_bss)
 1171                                         ni->ni_fails++;
 1172                                 ic->ic_stats.is_rx_auth_fail++;
 1173                                 return;
 1174                         }
 1175                         ieee80211_new_state(ic, IEEE80211_S_ASSOC,
 1176                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 1177                         break;
 1178                 case IEEE80211_AUTH_SHARED_CHALLENGE:
 1179                         if (!alloc_challenge(ic, ni))
 1180                                 return;
 1181                         /* XXX could optimize by passing recvd challenge */
 1182                         memcpy(ni->ni_challenge, &challenge[2], challenge[1]);
 1183                         IEEE80211_SEND_MGMT(ic, ni,
 1184                                 IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
 1185                         break;
 1186                 default:
 1187                         IEEE80211_DISCARD(ic, IEEE80211_MSG_AUTH,
 1188                             wh, "shared key auth", "bad seq %d", seq);
 1189                         ic->ic_stats.is_rx_bad_auth++;
 1190                         return;
 1191                 }
 1192                 break;
 1193         }
 1194         return;
 1195 bad:
 1196         /*
 1197          * Send an error response; but only when operating as an AP.
 1198          */
 1199         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
 1200                 /* XXX hack to workaround calling convention */
 1201                 ieee80211_send_error(ic, ni, wh->i_addr2,
 1202                     IEEE80211_FC0_SUBTYPE_AUTH,
 1203                     (seq + 1) | (estatus<<16));
 1204         } else if (ic->ic_opmode == IEEE80211_M_STA) {
 1205                 /*
 1206                  * Kick the state machine.  This short-circuits
 1207                  * using the mgt frame timeout to trigger the
 1208                  * state transition.
 1209                  */
 1210                 if (ic->ic_state == IEEE80211_S_AUTH)
 1211                         ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
 1212         }
 1213 }
 1214 
 1215 /* Verify the existence and length of __elem or get out. */
 1216 #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do {                 \
 1217         if ((__elem) == NULL) {                                         \
 1218                 IEEE80211_DISCARD(ic, IEEE80211_MSG_ELEMID,             \
 1219                     wh, ieee80211_mgt_subtype_name[subtype >>           \
 1220                         IEEE80211_FC0_SUBTYPE_SHIFT],                   \
 1221                     "%s", "no " #__elem );                              \
 1222                 ic->ic_stats.is_rx_elem_missing++;                      \
 1223                 return;                                                 \
 1224         }                                                               \
 1225         if ((__elem)[1] > (__maxlen)) {                                 \
 1226                 IEEE80211_DISCARD(ic, IEEE80211_MSG_ELEMID,             \
 1227                     wh, ieee80211_mgt_subtype_name[subtype >>           \
 1228                         IEEE80211_FC0_SUBTYPE_SHIFT],                   \
 1229                     "bad " #__elem " len %d", (__elem)[1]);             \
 1230                 ic->ic_stats.is_rx_elem_toobig++;                       \
 1231                 return;                                                 \
 1232         }                                                               \
 1233 } while (0)
 1234 
 1235 #define IEEE80211_VERIFY_LENGTH(_len, _minlen) do {                     \
 1236         if ((_len) < (_minlen)) {                                       \
 1237                 IEEE80211_DISCARD(ic, IEEE80211_MSG_ELEMID,             \
 1238                     wh, ieee80211_mgt_subtype_name[subtype >>           \
 1239                         IEEE80211_FC0_SUBTYPE_SHIFT],                   \
 1240                     "%s", "ie too short");                              \
 1241                 ic->ic_stats.is_rx_elem_toosmall++;                     \
 1242                 return;                                                 \
 1243         }                                                               \
 1244 } while (0)
 1245 
 1246 #ifdef IEEE80211_DEBUG
 1247 static void
 1248 ieee80211_ssid_mismatch(struct ieee80211com *ic, const char *tag,
 1249         u_int8_t mac[IEEE80211_ADDR_LEN], u_int8_t *ssid)
 1250 {
 1251         printf("[%s] discard %s frame, ssid mismatch: ",
 1252                 ether_sprintf(mac), tag);
 1253         ieee80211_print_essid(ssid + 2, ssid[1]);
 1254         printf("\n");
 1255 }
 1256 
 1257 #define IEEE80211_VERIFY_SSID(_ni, _ssid) do {                          \
 1258         if ((_ssid)[1] != 0 &&                                          \
 1259             ((_ssid)[1] != (_ni)->ni_esslen ||                          \
 1260             memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
 1261                 if (ieee80211_msg_input(ic))                            \
 1262                         ieee80211_ssid_mismatch(ic,                     \
 1263                             ieee80211_mgt_subtype_name[subtype >>       \
 1264                                 IEEE80211_FC0_SUBTYPE_SHIFT],           \
 1265                                 wh->i_addr2, _ssid);                    \
 1266                 ic->ic_stats.is_rx_ssidmismatch++;                      \
 1267                 return;                                                 \
 1268         }                                                               \
 1269 } while (0)
 1270 #else /* !IEEE80211_DEBUG */
 1271 #define IEEE80211_VERIFY_SSID(_ni, _ssid) do {                          \
 1272         if ((_ssid)[1] != 0 &&                                          \
 1273             ((_ssid)[1] != (_ni)->ni_esslen ||                          \
 1274             memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
 1275                 ic->ic_stats.is_rx_ssidmismatch++;                      \
 1276                 return;                                                 \
 1277         }                                                               \
 1278 } while (0)
 1279 #endif /* !IEEE80211_DEBUG */
 1280 
 1281 /* unalligned little endian access */     
 1282 #define LE_READ_2(p)                                    \
 1283         ((u_int16_t)                                    \
 1284          ((((const u_int8_t *)(p))[0]      ) |          \
 1285           (((const u_int8_t *)(p))[1] <<  8)))
 1286 #define LE_READ_4(p)                                    \
 1287         ((u_int32_t)                                    \
 1288          ((((const u_int8_t *)(p))[0]      ) |          \
 1289           (((const u_int8_t *)(p))[1] <<  8) |          \
 1290           (((const u_int8_t *)(p))[2] << 16) |          \
 1291           (((const u_int8_t *)(p))[3] << 24)))
 1292 
 1293 static int __inline
 1294 iswpaoui(const u_int8_t *frm)
 1295 {
 1296         return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
 1297 }
 1298 
 1299 static int __inline
 1300 iswmeoui(const u_int8_t *frm)
 1301 {
 1302         return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);
 1303 }
 1304 
 1305 static int __inline
 1306 iswmeparam(const u_int8_t *frm)
 1307 {
 1308         return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
 1309                 frm[6] == WME_PARAM_OUI_SUBTYPE;
 1310 }
 1311 
 1312 static int __inline
 1313 iswmeinfo(const u_int8_t *frm)
 1314 {
 1315         return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
 1316                 frm[6] == WME_INFO_OUI_SUBTYPE;
 1317 }
 1318 
 1319 static int __inline
 1320 isatherosoui(const u_int8_t *frm)
 1321 {
 1322         return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
 1323 }
 1324 
 1325 /*
 1326  * Convert a WPA cipher selector OUI to an internal
 1327  * cipher algorithm.  Where appropriate we also
 1328  * record any key length.
 1329  */
 1330 static int
 1331 wpa_cipher(u_int8_t *sel, u_int8_t *keylen)
 1332 {
 1333 #define WPA_SEL(x)      (((x)<<24)|WPA_OUI)
 1334         u_int32_t w = LE_READ_4(sel);
 1335 
 1336         switch (w) {
 1337         case WPA_SEL(WPA_CSE_NULL):
 1338                 return IEEE80211_CIPHER_NONE;
 1339         case WPA_SEL(WPA_CSE_WEP40):
 1340                 if (keylen)
 1341                         *keylen = 40 / NBBY;
 1342                 return IEEE80211_CIPHER_WEP;
 1343         case WPA_SEL(WPA_CSE_WEP104):
 1344                 if (keylen)
 1345                         *keylen = 104 / NBBY;
 1346                 return IEEE80211_CIPHER_WEP;
 1347         case WPA_SEL(WPA_CSE_TKIP):
 1348                 return IEEE80211_CIPHER_TKIP;
 1349         case WPA_SEL(WPA_CSE_CCMP):
 1350                 return IEEE80211_CIPHER_AES_CCM;
 1351         }
 1352         return 32;              /* NB: so 1<< is discarded */
 1353 #undef WPA_SEL
 1354 }
 1355 
 1356 /*
 1357  * Convert a WPA key management/authentication algorithm
 1358  * to an internal code.
 1359  */
 1360 static int
 1361 wpa_keymgmt(u_int8_t *sel)
 1362 {
 1363 #define WPA_SEL(x)      (((x)<<24)|WPA_OUI)
 1364         u_int32_t w = LE_READ_4(sel);
 1365 
 1366         switch (w) {
 1367         case WPA_SEL(WPA_ASE_8021X_UNSPEC):
 1368                 return WPA_ASE_8021X_UNSPEC;
 1369         case WPA_SEL(WPA_ASE_8021X_PSK):
 1370                 return WPA_ASE_8021X_PSK;
 1371         case WPA_SEL(WPA_ASE_NONE):
 1372                 return WPA_ASE_NONE;
 1373         }
 1374         return 0;               /* NB: so is discarded */
 1375 #undef WPA_SEL
 1376 }
 1377 
 1378 /*
 1379  * Parse a WPA information element to collect parameters
 1380  * and validate the parameters against what has been
 1381  * configured for the system.
 1382  */
 1383 static int
 1384 ieee80211_parse_wpa(struct ieee80211com *ic, u_int8_t *frm,
 1385         struct ieee80211_rsnparms *rsn, const struct ieee80211_frame *wh)
 1386 {
 1387         u_int8_t len = frm[1];
 1388         u_int32_t w;
 1389         int n;
 1390 
 1391         /*
 1392          * Check the length once for fixed parts: OUI, type,
 1393          * version, mcast cipher, and 2 selector counts.
 1394          * Other, variable-length data, must be checked separately.
 1395          */
 1396         if ((ic->ic_flags & IEEE80211_F_WPA1) == 0) {
 1397                 IEEE80211_DISCARD_IE(ic,
 1398                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1399                     wh, "WPA", "not WPA, flags 0x%x", ic->ic_flags);
 1400                 return IEEE80211_REASON_IE_INVALID;
 1401         }
 1402         if (len < 14) {
 1403                 IEEE80211_DISCARD_IE(ic,
 1404                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1405                     wh, "WPA", "too short, len %u", len);
 1406                 return IEEE80211_REASON_IE_INVALID;
 1407         }
 1408         frm += 6, len -= 4;             /* NB: len is payload only */
 1409         /* NB: iswapoui already validated the OUI and type */
 1410         w = LE_READ_2(frm);
 1411         if (w != WPA_VERSION) {
 1412                 IEEE80211_DISCARD_IE(ic,
 1413                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1414                     wh, "WPA", "bad version %u", w);
 1415                 return IEEE80211_REASON_IE_INVALID;
 1416         }
 1417         frm += 2, len -= 2;
 1418 
 1419         /* multicast/group cipher */
 1420         w = wpa_cipher(frm, &rsn->rsn_mcastkeylen);
 1421         if (w != rsn->rsn_mcastcipher) {
 1422                 IEEE80211_DISCARD_IE(ic,
 1423                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1424                     wh, "WPA", "mcast cipher mismatch; got %u, expected %u",
 1425                     w, rsn->rsn_mcastcipher);
 1426                 return IEEE80211_REASON_IE_INVALID;
 1427         }
 1428         frm += 4, len -= 4;
 1429 
 1430         /* unicast ciphers */
 1431         n = LE_READ_2(frm);
 1432         frm += 2, len -= 2;
 1433         if (len < n*4+2) {
 1434                 IEEE80211_DISCARD_IE(ic,
 1435                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1436                     wh, "WPA", "ucast cipher data too short; len %u, n %u",
 1437                     len, n);
 1438                 return IEEE80211_REASON_IE_INVALID;
 1439         }
 1440         w = 0;
 1441         for (; n > 0; n--) {
 1442                 w |= 1<<wpa_cipher(frm, &rsn->rsn_ucastkeylen);
 1443                 frm += 4, len -= 4;
 1444         }
 1445         w &= rsn->rsn_ucastcipherset;
 1446         if (w == 0) {
 1447                 IEEE80211_DISCARD_IE(ic,
 1448                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1449                     wh, "WPA", "%s", "ucast cipher set empty");
 1450                 return IEEE80211_REASON_IE_INVALID;
 1451         }
 1452         if (w & (1<<IEEE80211_CIPHER_TKIP))
 1453                 rsn->rsn_ucastcipher = IEEE80211_CIPHER_TKIP;
 1454         else
 1455                 rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;
 1456 
 1457         /* key management algorithms */
 1458         n = LE_READ_2(frm);
 1459         frm += 2, len -= 2;
 1460         if (len < n*4) {
 1461                 IEEE80211_DISCARD_IE(ic,
 1462                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1463                     wh, "WPA", "key mgmt alg data too short; len %u, n %u",
 1464                     len, n);
 1465                 return IEEE80211_REASON_IE_INVALID;
 1466         }
 1467         w = 0;
 1468         for (; n > 0; n--) {
 1469                 w |= wpa_keymgmt(frm);
 1470                 frm += 4, len -= 4;
 1471         }
 1472         w &= rsn->rsn_keymgmtset;
 1473         if (w == 0) {
 1474                 IEEE80211_DISCARD_IE(ic,
 1475                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1476                     wh, "WPA", "%s", "no acceptable key mgmt alg");
 1477                 return IEEE80211_REASON_IE_INVALID;
 1478         }
 1479         if (w & WPA_ASE_8021X_UNSPEC)
 1480                 rsn->rsn_keymgmt = WPA_ASE_8021X_UNSPEC;
 1481         else
 1482                 rsn->rsn_keymgmt = WPA_ASE_8021X_PSK;
 1483 
 1484         if (len > 2)            /* optional capabilities */
 1485                 rsn->rsn_caps = LE_READ_2(frm);
 1486 
 1487         return 0;
 1488 }
 1489 
 1490 /*
 1491  * Convert an RSN cipher selector OUI to an internal
 1492  * cipher algorithm.  Where appropriate we also
 1493  * record any key length.
 1494  */
 1495 static int
 1496 rsn_cipher(u_int8_t *sel, u_int8_t *keylen)
 1497 {
 1498 #define RSN_SEL(x)      (((x)<<24)|RSN_OUI)
 1499         u_int32_t w = LE_READ_4(sel);
 1500 
 1501         switch (w) {
 1502         case RSN_SEL(RSN_CSE_NULL):
 1503                 return IEEE80211_CIPHER_NONE;
 1504         case RSN_SEL(RSN_CSE_WEP40):
 1505                 if (keylen)
 1506                         *keylen = 40 / NBBY;
 1507                 return IEEE80211_CIPHER_WEP;
 1508         case RSN_SEL(RSN_CSE_WEP104):
 1509                 if (keylen)
 1510                         *keylen = 104 / NBBY;
 1511                 return IEEE80211_CIPHER_WEP;
 1512         case RSN_SEL(RSN_CSE_TKIP):
 1513                 return IEEE80211_CIPHER_TKIP;
 1514         case RSN_SEL(RSN_CSE_CCMP):
 1515                 return IEEE80211_CIPHER_AES_CCM;
 1516         case RSN_SEL(RSN_CSE_WRAP):
 1517                 return IEEE80211_CIPHER_AES_OCB;
 1518         }
 1519         return 32;              /* NB: so 1<< is discarded */
 1520 #undef WPA_SEL
 1521 }
 1522 
 1523 /*
 1524  * Convert an RSN key management/authentication algorithm
 1525  * to an internal code.
 1526  */
 1527 static int
 1528 rsn_keymgmt(u_int8_t *sel)
 1529 {
 1530 #define RSN_SEL(x)      (((x)<<24)|RSN_OUI)
 1531         u_int32_t w = LE_READ_4(sel);
 1532 
 1533         switch (w) {
 1534         case RSN_SEL(RSN_ASE_8021X_UNSPEC):
 1535                 return RSN_ASE_8021X_UNSPEC;
 1536         case RSN_SEL(RSN_ASE_8021X_PSK):
 1537                 return RSN_ASE_8021X_PSK;
 1538         case RSN_SEL(RSN_ASE_NONE):
 1539                 return RSN_ASE_NONE;
 1540         }
 1541         return 0;               /* NB: so is discarded */
 1542 #undef RSN_SEL
 1543 }
 1544 
 1545 /*
 1546  * Parse a WPA/RSN information element to collect parameters
 1547  * and validate the parameters against what has been
 1548  * configured for the system.
 1549  */
 1550 static int
 1551 ieee80211_parse_rsn(struct ieee80211com *ic, u_int8_t *frm,
 1552         struct ieee80211_rsnparms *rsn, const struct ieee80211_frame *wh)
 1553 {
 1554         u_int8_t len = frm[1];
 1555         u_int32_t w;
 1556         int n;
 1557 
 1558         /*
 1559          * Check the length once for fixed parts: 
 1560          * version, mcast cipher, and 2 selector counts.
 1561          * Other, variable-length data, must be checked separately.
 1562          */
 1563         if ((ic->ic_flags & IEEE80211_F_WPA2) == 0) {
 1564                 IEEE80211_DISCARD_IE(ic,
 1565                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1566                     wh, "WPA", "not RSN, flags 0x%x", ic->ic_flags);
 1567                 return IEEE80211_REASON_IE_INVALID;
 1568         }
 1569         if (len < 10) {
 1570                 IEEE80211_DISCARD_IE(ic,
 1571                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1572                     wh, "RSN", "too short, len %u", len);
 1573                 return IEEE80211_REASON_IE_INVALID;
 1574         }
 1575         frm += 2;
 1576         w = LE_READ_2(frm);
 1577         if (w != RSN_VERSION) {
 1578                 IEEE80211_DISCARD_IE(ic,
 1579                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1580                     wh, "RSN", "bad version %u", w);
 1581                 return IEEE80211_REASON_IE_INVALID;
 1582         }
 1583         frm += 2, len -= 2;
 1584 
 1585         /* multicast/group cipher */
 1586         w = rsn_cipher(frm, &rsn->rsn_mcastkeylen);
 1587         if (w != rsn->rsn_mcastcipher) {
 1588                 IEEE80211_DISCARD_IE(ic,
 1589                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1590                     wh, "RSN", "mcast cipher mismatch; got %u, expected %u",
 1591                     w, rsn->rsn_mcastcipher);
 1592                 return IEEE80211_REASON_IE_INVALID;
 1593         }
 1594         frm += 4, len -= 4;
 1595 
 1596         /* unicast ciphers */
 1597         n = LE_READ_2(frm);
 1598         frm += 2, len -= 2;
 1599         if (len < n*4+2) {
 1600                 IEEE80211_DISCARD_IE(ic,
 1601                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1602                     wh, "RSN", "ucast cipher data too short; len %u, n %u",
 1603                     len, n);
 1604                 return IEEE80211_REASON_IE_INVALID;
 1605         }
 1606         w = 0;
 1607         for (; n > 0; n--) {
 1608                 w |= 1<<rsn_cipher(frm, &rsn->rsn_ucastkeylen);
 1609                 frm += 4, len -= 4;
 1610         }
 1611         w &= rsn->rsn_ucastcipherset;
 1612         if (w == 0) {
 1613                 IEEE80211_DISCARD_IE(ic,
 1614                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1615                     wh, "RSN", "%s", "ucast cipher set empty");
 1616                 return IEEE80211_REASON_IE_INVALID;
 1617         }
 1618         if (w & (1<<IEEE80211_CIPHER_TKIP))
 1619                 rsn->rsn_ucastcipher = IEEE80211_CIPHER_TKIP;
 1620         else
 1621                 rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;
 1622 
 1623         /* key management algorithms */
 1624         n = LE_READ_2(frm);
 1625         frm += 2, len -= 2;
 1626         if (len < n*4) {
 1627                 IEEE80211_DISCARD_IE(ic, 
 1628                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1629                     wh, "RSN", "key mgmt alg data too short; len %u, n %u",
 1630                     len, n);
 1631                 return IEEE80211_REASON_IE_INVALID;
 1632         }
 1633         w = 0;
 1634         for (; n > 0; n--) {
 1635                 w |= rsn_keymgmt(frm);
 1636                 frm += 4, len -= 4;
 1637         }
 1638         w &= rsn->rsn_keymgmtset;
 1639         if (w == 0) {
 1640                 IEEE80211_DISCARD_IE(ic,
 1641                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,
 1642                     wh, "RSN", "%s", "no acceptable key mgmt alg");
 1643                 return IEEE80211_REASON_IE_INVALID;
 1644         }
 1645         if (w & RSN_ASE_8021X_UNSPEC)
 1646                 rsn->rsn_keymgmt = RSN_ASE_8021X_UNSPEC;
 1647         else
 1648                 rsn->rsn_keymgmt = RSN_ASE_8021X_PSK;
 1649 
 1650         /* optional RSN capabilities */
 1651         if (len > 2)
 1652                 rsn->rsn_caps = LE_READ_2(frm);
 1653         /* XXXPMKID */
 1654 
 1655         return 0;
 1656 }
 1657 
 1658 static int
 1659 ieee80211_parse_wmeparams(struct ieee80211com *ic, u_int8_t *frm,
 1660         const struct ieee80211_frame *wh)
 1661 {
 1662 #define MS(_v, _f)      (((_v) & _f) >> _f##_S)
 1663         struct ieee80211_wme_state *wme = &ic->ic_wme;
 1664         u_int len = frm[1], qosinfo;
 1665         int i;
 1666 
 1667         if (len < sizeof(struct ieee80211_wme_param)-2) {
 1668                 IEEE80211_DISCARD_IE(ic,
 1669                     IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME,
 1670                     wh, "WME", "too short, len %u", len);
 1671                 return -1;
 1672         }
 1673         qosinfo = frm[__offsetof(struct ieee80211_wme_param, param_qosInfo)];
 1674         qosinfo &= WME_QOSINFO_COUNT;
 1675         /* XXX do proper check for wraparound */
 1676         if (qosinfo == wme->wme_wmeChanParams.cap_info)
 1677                 return 0;
 1678         frm += __offsetof(struct ieee80211_wme_param, params_acParams);
 1679         for (i = 0; i < WME_NUM_AC; i++) {
 1680                 struct wmeParams *wmep =
 1681                         &wme->wme_wmeChanParams.cap_wmeParams[i];
 1682                 /* NB: ACI not used */
 1683                 wmep->wmep_acm = MS(frm[0], WME_PARAM_ACM);
 1684                 wmep->wmep_aifsn = MS(frm[0], WME_PARAM_AIFSN);
 1685                 wmep->wmep_logcwmin = MS(frm[1], WME_PARAM_LOGCWMIN);
 1686                 wmep->wmep_logcwmax = MS(frm[1], WME_PARAM_LOGCWMAX);
 1687                 wmep->wmep_txopLimit = LE_READ_2(frm+2);
 1688                 frm += 4;
 1689         }
 1690         wme->wme_wmeChanParams.cap_info = qosinfo;
 1691         return 1;
 1692 #undef MS
 1693 }
 1694 
 1695 void
 1696 ieee80211_saveie(u_int8_t **iep, const u_int8_t *ie)
 1697 {
 1698         u_int ielen = ie[1]+2;
 1699         /*
 1700          * Record information element for later use.
 1701          */
 1702         if (*iep == NULL || (*iep)[1] != ie[1]) {
 1703                 if (*iep != NULL)
 1704                         FREE(*iep, M_DEVBUF);
 1705                 MALLOC(*iep, void*, ielen, M_DEVBUF, M_NOWAIT);
 1706         }
 1707         if (*iep != NULL)
 1708                 memcpy(*iep, ie, ielen);
 1709         /* XXX note failure */
 1710 }
 1711 
 1712 void
 1713 ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
 1714         struct ieee80211_node *ni,
 1715         int subtype, int rssi, u_int32_t rstamp)
 1716 {
 1717 #define ISPROBE(_st)    ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
 1718 #define ISREASSOC(_st)  ((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)
 1719         struct ieee80211_frame *wh;
 1720         u_int8_t *frm, *efrm;
 1721         u_int8_t *ssid, *rates, *xrates, *wpa, *wme;
 1722         int reassoc, resp, allocbs;
 1723         u_int8_t rate;
 1724 
 1725         wh = mtod(m0, struct ieee80211_frame *);
 1726         frm = (u_int8_t *)&wh[1];
 1727         efrm = mtod(m0, u_int8_t *) + m0->m_len;
 1728         switch (subtype) {
 1729         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 1730         case IEEE80211_FC0_SUBTYPE_BEACON: {
 1731                 struct ieee80211_scanparams scan;
 1732 
 1733                 /*
 1734                  * We process beacon/probe response frames:
 1735                  *    o when scanning, or
 1736                  *    o station mode when associated (to collect state
 1737                  *      updates such as 802.11g slot time), or
 1738                  *    o adhoc mode (to discover neighbors)
 1739                  * Frames otherwise received are discarded.
 1740                  */ 
 1741                 if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
 1742                       (ic->ic_opmode == IEEE80211_M_STA && ni->ni_associd) ||
 1743                        ic->ic_opmode == IEEE80211_M_IBSS)) {
 1744                         ic->ic_stats.is_rx_mgtdiscard++;
 1745                         return;
 1746                 }
 1747                 /*
 1748                  * beacon/probe response frame format
 1749                  *      [8] time stamp
 1750                  *      [2] beacon interval
 1751                  *      [2] capability information
 1752                  *      [tlv] ssid
 1753                  *      [tlv] supported rates
 1754                  *      [tlv] country information
 1755                  *      [tlv] parameter set (FH/DS)
 1756                  *      [tlv] erp information
 1757                  *      [tlv] extended supported rates
 1758                  *      [tlv] WME
 1759                  *      [tlv] WPA or RSN
 1760                  */
 1761                 IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
 1762                 memset(&scan, 0, sizeof(scan));
 1763                 scan.tstamp  = frm;                             frm += 8;
 1764                 scan.bintval = le16toh(*(u_int16_t *)frm);      frm += 2;
 1765                 scan.capinfo = le16toh(*(u_int16_t *)frm);      frm += 2;
 1766                 scan.bchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
 1767                 scan.chan = scan.bchan;
 1768 
 1769                 while (frm < efrm) {
 1770                         switch (*frm) {
 1771                         case IEEE80211_ELEMID_SSID:
 1772                                 scan.ssid = frm;
 1773                                 break;
 1774                         case IEEE80211_ELEMID_RATES:
 1775                                 scan.rates = frm;
 1776                                 break;
 1777                         case IEEE80211_ELEMID_COUNTRY:
 1778                                 scan.country = frm;
 1779                                 break;
 1780                         case IEEE80211_ELEMID_FHPARMS:
 1781                                 if (ic->ic_phytype == IEEE80211_T_FH) {
 1782                                         scan.fhdwell = LE_READ_2(&frm[2]);
 1783                                         scan.chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
 1784                                         scan.fhindex = frm[6];
 1785                                 }
 1786                                 break;
 1787                         case IEEE80211_ELEMID_DSPARMS:
 1788                                 /*
 1789                                  * XXX hack this since depending on phytype
 1790                                  * is problematic for multi-mode devices.
 1791                                  */
 1792                                 if (ic->ic_phytype != IEEE80211_T_FH)
 1793                                         scan.chan = frm[2];
 1794                                 break;
 1795                         case IEEE80211_ELEMID_TIM:
 1796                                 /* XXX ATIM? */
 1797                                 scan.tim = frm;
 1798                                 scan.timoff = frm - mtod(m0, u_int8_t *);
 1799                                 break;
 1800                         case IEEE80211_ELEMID_IBSSPARMS:
 1801                                 break;
 1802                         case IEEE80211_ELEMID_XRATES:
 1803                                 scan.xrates = frm;
 1804                                 break;
 1805                         case IEEE80211_ELEMID_ERP:
 1806                                 if (frm[1] != 1) {
 1807                                         IEEE80211_DISCARD_IE(ic,
 1808                                             IEEE80211_MSG_ELEMID, wh, "ERP",
 1809                                             "bad len %u", frm[1]);
 1810                                         ic->ic_stats.is_rx_elem_toobig++;
 1811                                         break;
 1812                                 }
 1813                                 scan.erp = frm[2];
 1814                                 break;
 1815                         case IEEE80211_ELEMID_RSN:
 1816                                 scan.wpa = frm;
 1817                                 break;
 1818                         case IEEE80211_ELEMID_VENDOR:
 1819                                 if (iswpaoui(frm))
 1820                                         scan.wpa = frm;
 1821                                 else if (iswmeparam(frm) || iswmeinfo(frm))
 1822                                         scan.wme = frm;
 1823                                 /* XXX Atheros OUI support */
 1824                                 break;
 1825                         default:
 1826                                 IEEE80211_DISCARD_IE(ic, IEEE80211_MSG_ELEMID,
 1827                                     wh, "unhandled",
 1828                                     "id %u, len %u", *frm, frm[1]);
 1829                                 ic->ic_stats.is_rx_elem_unknown++;
 1830                                 break;
 1831                         }
 1832                         frm += frm[1] + 2;
 1833                 }
 1834                 IEEE80211_VERIFY_ELEMENT(scan.rates, IEEE80211_RATE_MAXSIZE);
 1835                 IEEE80211_VERIFY_ELEMENT(scan.ssid, IEEE80211_NWID_LEN);
 1836                 if (
 1837 #if IEEE80211_CHAN_MAX < 255
 1838                     scan.chan > IEEE80211_CHAN_MAX ||
 1839 #endif
 1840                     isclr(ic->ic_chan_active, scan.chan)) {
 1841                         IEEE80211_DISCARD(ic,
 1842                             IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
 1843                             wh, ieee80211_mgt_subtype_name[subtype >>
 1844                                 IEEE80211_FC0_SUBTYPE_SHIFT],
 1845                             "invalid channel %u", scan.chan);
 1846                         ic->ic_stats.is_rx_badchan++;
 1847                         return;
 1848                 }
 1849                 if (scan.chan != scan.bchan &&
 1850                     ic->ic_phytype != IEEE80211_T_FH) {
 1851                         /*
 1852                          * Frame was received on a channel different from the
 1853                          * one indicated in the DS params element id;
 1854                          * silently discard it.
 1855                          *
 1856                          * NB: this can happen due to signal leakage.
 1857                          *     But we should take it for FH phy because
 1858                          *     the rssi value should be correct even for
 1859                          *     different hop pattern in FH.
 1860                          */
 1861                         IEEE80211_DISCARD(ic,
 1862                             IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
 1863                             wh, ieee80211_mgt_subtype_name[subtype >>
 1864                                 IEEE80211_FC0_SUBTYPE_SHIFT],
 1865                             "for off-channel %u", scan.chan);
 1866                         ic->ic_stats.is_rx_chanmismatch++;
 1867                         return;
 1868                 }
 1869                 if (!(IEEE80211_BINTVAL_MIN <= scan.bintval &&
 1870                       scan.bintval <= IEEE80211_BINTVAL_MAX)) {
 1871                         IEEE80211_DISCARD(ic,
 1872                             IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
 1873                             wh, ieee80211_mgt_subtype_name[subtype >>
 1874                                 IEEE80211_FC0_SUBTYPE_SHIFT],
 1875                             "bogus beacon interval", scan.bintval);
 1876                         ic->ic_stats.is_rx_badbintval++;
 1877                         return;
 1878                 }
 1879 
 1880                 /*
 1881                  * Count frame now that we know it's to be processed.
 1882                  */
 1883                 if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
 1884                         ic->ic_stats.is_rx_beacon++;            /* XXX remove */
 1885                         IEEE80211_NODE_STAT(ni, rx_beacons);
 1886                 } else
 1887                         IEEE80211_NODE_STAT(ni, rx_proberesp);
 1888 
 1889                 /*
 1890                  * When operating in station mode, check for state updates.
 1891                  * Be careful to ignore beacons received while doing a
 1892                  * background scan.  We consider only 11g/WMM stuff right now.
 1893                  */
 1894                 if (ic->ic_opmode == IEEE80211_M_STA &&
 1895                     ni->ni_associd != 0 &&
 1896                     ((ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
 1897                      IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))) {
 1898                         /* record tsf of last beacon */
 1899                         memcpy(ni->ni_tstamp.data, scan.tstamp,
 1900                                 sizeof(ni->ni_tstamp));
 1901                         if (ni->ni_erp != scan.erp) {
 1902                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 1903                                     "[%s] erp change: was 0x%x, now 0x%x\n",
 1904                                     ether_sprintf(wh->i_addr2),
 1905                                     ni->ni_erp, scan.erp);
 1906                                 if (ic->ic_curmode == IEEE80211_MODE_11G &&
 1907                                     (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION))
 1908                                         ic->ic_flags |= IEEE80211_F_USEPROT;
 1909                                 else
 1910                                         ic->ic_flags &= ~IEEE80211_F_USEPROT;
 1911                                 ni->ni_erp = scan.erp;
 1912                                 /* XXX statistic */
 1913                         }
 1914                         if ((ni->ni_capinfo ^ scan.capinfo) & IEEE80211_CAPINFO_SHORT_SLOTTIME) {
 1915                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 1916                                     "[%s] capabilities change: before 0x%x,"
 1917                                      " now 0x%x\n",
 1918                                      ether_sprintf(wh->i_addr2),
 1919                                      ni->ni_capinfo, scan.capinfo);
 1920                                 /*
 1921                                  * NB: we assume short preamble doesn't
 1922                                  *     change dynamically
 1923                                  */
 1924                                 ieee80211_set_shortslottime(ic,
 1925                                         ic->ic_curmode == IEEE80211_MODE_11A ||
 1926                                         (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
 1927                                 ni->ni_capinfo = scan.capinfo;
 1928                                 /* XXX statistic */
 1929                         }
 1930                         if (scan.wme != NULL &&
 1931                             (ni->ni_flags & IEEE80211_NODE_QOS) &&
 1932                             ieee80211_parse_wmeparams(ic, scan.wme, wh) > 0)
 1933                                 ieee80211_wme_updateparams(ic);
 1934                         if (scan.tim != NULL) {
 1935                                 struct ieee80211_tim_ie *ie =
 1936                                     (struct ieee80211_tim_ie *) scan.tim;
 1937 
 1938                                 ni->ni_dtim_count = ie->tim_count;
 1939                                 ni->ni_dtim_period = ie->tim_period;
 1940                         }
 1941                         if (ic->ic_flags & IEEE80211_F_SCAN)
 1942                                 ieee80211_add_scan(ic, &scan, wh,
 1943                                         subtype, rssi, rstamp);
 1944                         return;
 1945                 }
 1946                 /*
 1947                  * If scanning, just pass information to the scan module.
 1948                  */
 1949                 if (ic->ic_flags & IEEE80211_F_SCAN) {
 1950                         ieee80211_add_scan(ic, &scan, wh,
 1951                                 subtype, rssi, rstamp);
 1952                         return;
 1953                 }
 1954                 if (scan.capinfo & IEEE80211_CAPINFO_IBSS) {
 1955                         if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
 1956                                 /*
 1957                                  * Create a new entry in the neighbor table.
 1958                                  */
 1959                                 ni = ieee80211_add_neighbor(ic, wh, &scan);
 1960                         } else {
 1961                                 /*
 1962                                  * Record tsf for potential resync.
 1963                                  */
 1964                                 memcpy(ni->ni_tstamp.data, scan.tstamp,
 1965                                         sizeof(ni->ni_tstamp));
 1966                         }
 1967                         if (ni != NULL) {
 1968                                 ni->ni_rssi = rssi;
 1969                                 ni->ni_rstamp = rstamp;
 1970                         }
 1971                 }
 1972                 break;
 1973         }
 1974 
 1975         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
 1976                 if (ic->ic_opmode == IEEE80211_M_STA ||
 1977                     ic->ic_state != IEEE80211_S_RUN) {
 1978                         ic->ic_stats.is_rx_mgtdiscard++;
 1979                         return;
 1980                 }
 1981                 if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
 1982                         /* frame must be directed */
 1983                         ic->ic_stats.is_rx_mgtdiscard++;        /* XXX stat */
 1984                         return;
 1985                 }
 1986 
 1987                 /*
 1988                  * prreq frame format
 1989                  *      [tlv] ssid
 1990                  *      [tlv] supported rates
 1991                  *      [tlv] extended supported rates
 1992                  */
 1993                 ssid = rates = xrates = NULL;
 1994                 while (frm < efrm) {
 1995                         switch (*frm) {
 1996                         case IEEE80211_ELEMID_SSID:
 1997                                 ssid = frm;
 1998                                 break;
 1999                         case IEEE80211_ELEMID_RATES:
 2000                                 rates = frm;
 2001                                 break;
 2002                         case IEEE80211_ELEMID_XRATES:
 2003                                 xrates = frm;
 2004                                 break;
 2005                         }
 2006                         frm += frm[1] + 2;
 2007                 }
 2008                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 2009                 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
 2010                 IEEE80211_VERIFY_SSID(ic->ic_bss, ssid);
 2011                 if ((ic->ic_flags & IEEE80211_F_HIDESSID) && ssid[1] == 0) {
 2012                         IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
 2013                             wh, ieee80211_mgt_subtype_name[subtype >>
 2014                                 IEEE80211_FC0_SUBTYPE_SHIFT],
 2015                             "%s", "no ssid with ssid suppression enabled");
 2016                         ic->ic_stats.is_rx_ssidmismatch++; /*XXX*/
 2017                         return;
 2018                 }
 2019 
 2020                 if (ni == ic->ic_bss) {
 2021                         if (ic->ic_opmode == IEEE80211_M_IBSS) {
 2022                                 /*
 2023                                  * XXX Cannot tell if the sender is operating
 2024                                  * in ibss mode.  But we need a new node to
 2025                                  * send the response so blindly add them to the
 2026                                  * neighbor table.
 2027                                  */
 2028                                 ni = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
 2029                                         wh->i_addr2);
 2030                         } else
 2031                                 ni = ieee80211_tmp_node(ic, wh->i_addr2);
 2032                         if (ni == NULL)
 2033                                 return;
 2034                         allocbs = 1;
 2035                 } else
 2036                         allocbs = 0;
 2037                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 2038                     "[%s] recv probe req\n", ether_sprintf(wh->i_addr2));
 2039                 ni->ni_rssi = rssi;
 2040                 ni->ni_rstamp = rstamp;
 2041                 rate = ieee80211_setup_rates(ni, rates, xrates,
 2042                           IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
 2043                         | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
 2044                 if (rate & IEEE80211_RATE_BASIC) {
 2045                         IEEE80211_DISCARD(ic, IEEE80211_MSG_XRATE,
 2046                             wh, ieee80211_mgt_subtype_name[subtype >>
 2047                                 IEEE80211_FC0_SUBTYPE_SHIFT],
 2048                             "%s", "recv'd rate set invalid");
 2049                 } else {
 2050                         IEEE80211_SEND_MGMT(ic, ni,
 2051                                 IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
 2052                 }
 2053                 if (allocbs && ic->ic_opmode != IEEE80211_M_IBSS) {
 2054                         /* reclaim immediately */
 2055                         ieee80211_free_node(ni);
 2056                 }
 2057                 break;
 2058 
 2059         case IEEE80211_FC0_SUBTYPE_AUTH: {
 2060                 u_int16_t algo, seq, status;
 2061                 /*
 2062                  * auth frame format
 2063                  *      [2] algorithm
 2064                  *      [2] sequence
 2065                  *      [2] status
 2066                  *      [tlv*] challenge
 2067                  */
 2068                 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
 2069                 algo   = le16toh(*(u_int16_t *)frm);
 2070                 seq    = le16toh(*(u_int16_t *)(frm + 2));
 2071                 status = le16toh(*(u_int16_t *)(frm + 4));
 2072                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 2073                     "[%s] recv auth frame with algorithm %d seq %d\n",
 2074                     ether_sprintf(wh->i_addr2), algo, seq);
 2075                 /*
 2076                  * Consult the ACL policy module if setup.
 2077                  */
 2078                 if (ic->ic_acl != NULL &&
 2079                     !ic->ic_acl->iac_check(ic, wh->i_addr2)) {
 2080                         IEEE80211_DISCARD(ic, IEEE80211_MSG_ACL,
 2081                             wh, "auth", "%s", "disallowed by ACL");
 2082                         ic->ic_stats.is_rx_acl++;
 2083                         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
 2084                                 IEEE80211_SEND_MGMT(ic, ni,
 2085                                     IEEE80211_FC0_SUBTYPE_AUTH,
 2086                                     (seq+1) | (IEEE80211_STATUS_UNSPECIFIED<<16));
 2087                         }
 2088                         return;
 2089                 }
 2090                 if (ic->ic_flags & IEEE80211_F_COUNTERM) {
 2091                         IEEE80211_DISCARD(ic,
 2092                             IEEE80211_MSG_AUTH | IEEE80211_MSG_CRYPTO,
 2093                             wh, "auth", "%s", "TKIP countermeasures enabled");
 2094                         ic->ic_stats.is_rx_auth_countermeasures++;
 2095                         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
 2096                                 IEEE80211_SEND_MGMT(ic, ni,
 2097                                         IEEE80211_FC0_SUBTYPE_AUTH,
 2098                                         IEEE80211_REASON_MIC_FAILURE);
 2099                         }
 2100                         return;
 2101                 }
 2102                 if (algo == IEEE80211_AUTH_ALG_SHARED)
 2103                         ieee80211_auth_shared(ic, wh, frm + 6, efrm, ni, rssi,
 2104                             rstamp, seq, status);
 2105                 else if (algo == IEEE80211_AUTH_ALG_OPEN)
 2106                         ieee80211_auth_open(ic, wh, ni, rssi, rstamp, seq,
 2107                             status);
 2108                 else {
 2109                         IEEE80211_DISCARD(ic, IEEE80211_MSG_ANY,
 2110                             wh, "auth", "unsupported alg %d", algo);
 2111                         ic->ic_stats.is_rx_auth_unsupported++;
 2112                         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
 2113                                 /* XXX not right */
 2114                                 IEEE80211_SEND_MGMT(ic, ni,
 2115                                         IEEE80211_FC0_SUBTYPE_AUTH,
 2116                                         (seq+1) | (IEEE80211_STATUS_ALG<<16));
 2117                         }
 2118                         return;
 2119                 } 
 2120                 break;
 2121         }
 2122 
 2123         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
 2124         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
 2125                 u_int16_t capinfo, lintval;
 2126                 struct ieee80211_rsnparms rsn;
 2127                 u_int8_t reason;
 2128 
 2129                 if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
 2130                     ic->ic_state != IEEE80211_S_RUN) {
 2131                         ic->ic_stats.is_rx_mgtdiscard++;
 2132                         return;
 2133                 }
 2134 
 2135                 if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
 2136                         reassoc = 1;
 2137                         resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
 2138                 } else {
 2139                         reassoc = 0;
 2140                         resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
 2141                 }
 2142                 /*
 2143                  * asreq frame format
 2144                  *      [2] capability information
 2145                  *      [2] listen interval
 2146                  *      [6*] current AP address (reassoc only)
 2147                  *      [tlv] ssid
 2148                  *      [tlv] supported rates
 2149                  *      [tlv] extended supported rates
 2150                  *      [tlv] WPA or RSN
 2151                  */
 2152                 IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
 2153                 if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
 2154                         IEEE80211_DISCARD(ic, IEEE80211_MSG_ANY,
 2155                             wh, ieee80211_mgt_subtype_name[subtype >>
 2156                                 IEEE80211_FC0_SUBTYPE_SHIFT],
 2157                             "%s", "wrong bssid");
 2158                         ic->ic_stats.is_rx_assoc_bss++;
 2159                         return;
 2160                 }
 2161                 capinfo = le16toh(*(u_int16_t *)frm);   frm += 2;
 2162                 lintval = le16toh(*(u_int16_t *)frm);   frm += 2;
 2163                 if (reassoc)
 2164                         frm += 6;       /* ignore current AP info */
 2165                 ssid = rates = xrates = wpa = wme = NULL;
 2166                 while (frm < efrm) {
 2167                         switch (*frm) {
 2168                         case IEEE80211_ELEMID_SSID:
 2169                                 ssid = frm;
 2170                                 break;
 2171                         case IEEE80211_ELEMID_RATES:
 2172                                 rates = frm;
 2173                                 break;
 2174                         case IEEE80211_ELEMID_XRATES:
 2175                                 xrates = frm;
 2176                                 break;
 2177                         /* XXX verify only one of RSN and WPA ie's? */
 2178                         case IEEE80211_ELEMID_RSN:
 2179                                 wpa = frm;
 2180                                 break;
 2181                         case IEEE80211_ELEMID_VENDOR:
 2182                                 if (iswpaoui(frm))
 2183                                         wpa = frm;
 2184                                 else if (iswmeinfo(frm))
 2185                                         wme = frm;
 2186                                 /* XXX Atheros OUI support */
 2187                                 break;
 2188                         }
 2189                         frm += frm[1] + 2;
 2190                 }
 2191                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 2192                 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
 2193                 IEEE80211_VERIFY_SSID(ic->ic_bss, ssid);
 2194 
 2195                 if (ni == ic->ic_bss) {
 2196                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 2197                             "[%s] deny %s request, sta not authenticated\n",
 2198                             ether_sprintf(wh->i_addr2),
 2199                             reassoc ? "reassoc" : "assoc");
 2200                         ieee80211_send_error(ic, ni, wh->i_addr2,
 2201                             IEEE80211_FC0_SUBTYPE_DEAUTH,
 2202                             IEEE80211_REASON_ASSOC_NOT_AUTHED);
 2203                         ic->ic_stats.is_rx_assoc_notauth++;
 2204                         return;
 2205                 }
 2206                 /* assert right associstion security credentials */
 2207                 if (wpa == NULL && (ic->ic_flags & IEEE80211_F_WPA)) {
 2208                         IEEE80211_DPRINTF(ic,
 2209                             IEEE80211_MSG_ASSOC | IEEE80211_MSG_WPA,
 2210                             "[%s] no WPA/RSN IE in association request\n",
 2211                             ether_sprintf(wh->i_addr2));
 2212                         IEEE80211_SEND_MGMT(ic, ni,
 2213                             IEEE80211_FC0_SUBTYPE_DEAUTH,
 2214                             IEEE80211_REASON_RSN_REQUIRED);
 2215                         ieee80211_node_leave(ic, ni);
 2216                         /* XXX distinguish WPA/RSN? */
 2217                         ic->ic_stats.is_rx_assoc_badwpaie++;
 2218                         return; 
 2219                 }
 2220                 if (wpa != NULL) {
 2221                         /*
 2222                          * Parse WPA information element.  Note that
 2223                          * we initialize the param block from the node
 2224                          * state so that information in the IE overrides
 2225                          * our defaults.  The resulting parameters are
 2226                          * installed below after the association is assured.
 2227                          */
 2228                         rsn = ni->ni_rsn;
 2229                         if (wpa[0] != IEEE80211_ELEMID_RSN)
 2230                                 reason = ieee80211_parse_wpa(ic, wpa, &rsn, wh);
 2231                         else
 2232                                 reason = ieee80211_parse_rsn(ic, wpa, &rsn, wh);
 2233                         if (reason != 0) {
 2234                                 IEEE80211_SEND_MGMT(ic, ni,
 2235                                     IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
 2236                                 ieee80211_node_leave(ic, ni);
 2237                                 /* XXX distinguish WPA/RSN? */
 2238                                 ic->ic_stats.is_rx_assoc_badwpaie++;
 2239                                 return;
 2240                         }
 2241                         IEEE80211_DPRINTF(ic,
 2242                             IEEE80211_MSG_ASSOC | IEEE80211_MSG_WPA,
 2243                             "[%s] %s ie: mc %u/%u uc %u/%u key %u caps 0x%x\n",
 2244                             ether_sprintf(wh->i_addr2),
 2245                             wpa[0] != IEEE80211_ELEMID_RSN ?  "WPA" : "RSN",
 2246                             rsn.rsn_mcastcipher, rsn.rsn_mcastkeylen,
 2247                             rsn.rsn_ucastcipher, rsn.rsn_ucastkeylen,
 2248                             rsn.rsn_keymgmt, rsn.rsn_caps);
 2249                 }
 2250                 /* discard challenge after association */
 2251                 if (ni->ni_challenge != NULL) {
 2252                         FREE(ni->ni_challenge, M_DEVBUF);
 2253                         ni->ni_challenge = NULL;
 2254                 }
 2255                 /* NB: 802.11 spec says to ignore station's privacy bit */
 2256                 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0) {
 2257                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 2258                             "[%s] deny %s request, capability mismatch 0x%x\n",
 2259                             ether_sprintf(wh->i_addr2),
 2260                             reassoc ? "reassoc" : "assoc", capinfo);
 2261                         IEEE80211_SEND_MGMT(ic, ni, resp,
 2262                                 IEEE80211_STATUS_CAPINFO);
 2263                         ieee80211_node_leave(ic, ni);
 2264                         ic->ic_stats.is_rx_assoc_capmismatch++;
 2265                         return;
 2266                 }
 2267                 rate = ieee80211_setup_rates(ni, rates, xrates,
 2268                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
 2269                                 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
 2270                 /*
 2271                  * If constrained to 11g-only stations reject an
 2272                  * 11b-only station.  We cheat a bit here by looking
 2273                  * at the max negotiated xmit rate and assuming anyone
 2274                  * with a best rate <24Mb/s is an 11b station.
 2275                  */
 2276                 if ((rate & IEEE80211_RATE_BASIC) ||
 2277                     ((ic->ic_flags & IEEE80211_F_PUREG) && rate < 48)) {
 2278                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 2279                             "[%s] deny %s request, rate set mismatch\n",
 2280                             ether_sprintf(wh->i_addr2),
 2281                             reassoc ? "reassoc" : "assoc");
 2282                         IEEE80211_SEND_MGMT(ic, ni, resp,
 2283                                 IEEE80211_STATUS_BASIC_RATE);
 2284                         ieee80211_node_leave(ic, ni);
 2285                         ic->ic_stats.is_rx_assoc_norate++;
 2286                         return;
 2287                 }
 2288                 ni->ni_rssi = rssi;
 2289                 ni->ni_rstamp = rstamp;
 2290                 ni->ni_intval = lintval;
 2291                 ni->ni_capinfo = capinfo;
 2292                 ni->ni_chan = ic->ic_bss->ni_chan;
 2293                 ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
 2294                 ni->ni_fhindex = ic->ic_bss->ni_fhindex;
 2295                 if (wpa != NULL) {
 2296                         /*
 2297                          * Record WPA/RSN parameters for station, mark
 2298                          * node as using WPA and record information element
 2299                          * for applications that require it.
 2300                          */
 2301                         ni->ni_rsn = rsn;
 2302                         ieee80211_saveie(&ni->ni_wpa_ie, wpa);
 2303                 } else if (ni->ni_wpa_ie != NULL) {
 2304                         /*
 2305                          * Flush any state from a previous association.
 2306                          */
 2307                         FREE(ni->ni_wpa_ie, M_DEVBUF);
 2308                         ni->ni_wpa_ie = NULL;
 2309                 }
 2310                 if (wme != NULL) {
 2311                         /*
 2312                          * Record WME parameters for station, mark node
 2313                          * as capable of QoS and record information
 2314                          * element for applications that require it.
 2315                          */
 2316                         ieee80211_saveie(&ni->ni_wme_ie, wme);
 2317                         ni->ni_flags |= IEEE80211_NODE_QOS;
 2318                 } else if (ni->ni_wme_ie != NULL) {
 2319                         /*
 2320                          * Flush any state from a previous association.
 2321                          */
 2322                         FREE(ni->ni_wme_ie, M_DEVBUF);
 2323                         ni->ni_wme_ie = NULL;
 2324                         ni->ni_flags &= ~IEEE80211_NODE_QOS;
 2325                 }
 2326                 ieee80211_node_join(ic, ni, resp);
 2327                 break;
 2328         }
 2329 
 2330         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
 2331         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: {
 2332                 u_int16_t capinfo, associd;
 2333                 u_int16_t status;
 2334 
 2335                 if (ic->ic_opmode != IEEE80211_M_STA ||
 2336                     ic->ic_state != IEEE80211_S_ASSOC) {
 2337                         ic->ic_stats.is_rx_mgtdiscard++;
 2338                         return;
 2339                 }
 2340 
 2341                 /*
 2342                  * asresp frame format
 2343                  *      [2] capability information
 2344                  *      [2] status
 2345                  *      [2] association ID
 2346                  *      [tlv] supported rates
 2347                  *      [tlv] extended supported rates
 2348                  *      [tlv] WME
 2349                  */
 2350                 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
 2351                 ni = ic->ic_bss;
 2352                 capinfo = le16toh(*(u_int16_t *)frm);
 2353                 frm += 2;
 2354                 status = le16toh(*(u_int16_t *)frm);
 2355                 frm += 2;
 2356                 if (status != 0) {
 2357                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 2358                             "[%s] %sassoc failed (reason %d)\n",
 2359                             ether_sprintf(wh->i_addr2),
 2360                             ISREASSOC(subtype) ?  "re" : "", status);
 2361                         if (ni != ic->ic_bss)   /* XXX never true? */
 2362                                 ni->ni_fails++;
 2363                         ic->ic_stats.is_rx_auth_fail++; /* XXX */
 2364                         return;
 2365                 }
 2366                 associd = le16toh(*(u_int16_t *)frm);
 2367                 frm += 2;
 2368 
 2369                 rates = xrates = wpa = wme = NULL;
 2370                 while (frm < efrm) {
 2371                         switch (*frm) {
 2372                         case IEEE80211_ELEMID_RATES:
 2373                                 rates = frm;
 2374                                 break;
 2375                         case IEEE80211_ELEMID_XRATES:
 2376                                 xrates = frm;
 2377                                 break;
 2378                         case IEEE80211_ELEMID_VENDOR:
 2379                                 if (iswmeoui(frm))
 2380                                         wme = frm;
 2381                                 /* XXX Atheros OUI support */
 2382                                 break;
 2383                         }
 2384                         frm += frm[1] + 2;
 2385                 }
 2386 
 2387                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 2388                 rate = ieee80211_setup_rates(ni, rates, xrates,
 2389                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
 2390                                 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
 2391                 if (rate & IEEE80211_RATE_BASIC) {
 2392                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 2393                             "[%s] %sassoc failed (rate set mismatch)\n",
 2394                             ether_sprintf(wh->i_addr2),
 2395                             ISREASSOC(subtype) ?  "re" : "");
 2396                         if (ni != ic->ic_bss)   /* XXX never true? */
 2397                                 ni->ni_fails++;
 2398                         ic->ic_stats.is_rx_assoc_norate++;
 2399                         ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
 2400                         return;
 2401                 }
 2402 
 2403                 ni->ni_capinfo = capinfo;
 2404                 ni->ni_associd = associd;
 2405                 if (wme != NULL &&
 2406                     ieee80211_parse_wmeparams(ic, wme, wh) >= 0) {
 2407                         ni->ni_flags |= IEEE80211_NODE_QOS;
 2408                         ieee80211_wme_updateparams(ic);
 2409                 } else
 2410                         ni->ni_flags &= ~IEEE80211_NODE_QOS;
 2411                 /*
 2412                  * Configure state now that we are associated.
 2413                  *
 2414                  * XXX may need different/additional driver callbacks?
 2415                  */
 2416                 if (ic->ic_curmode == IEEE80211_MODE_11A ||
 2417                     (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
 2418                         ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
 2419                         ic->ic_flags &= ~IEEE80211_F_USEBARKER;
 2420                 } else {
 2421                         ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
 2422                         ic->ic_flags |= IEEE80211_F_USEBARKER;
 2423                 }
 2424                 ieee80211_set_shortslottime(ic,
 2425                         ic->ic_curmode == IEEE80211_MODE_11A ||
 2426                         (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
 2427                 /*
 2428                  * Honor ERP protection.
 2429                  *
 2430                  * NB: ni_erp should zero for non-11g operation.
 2431                  * XXX check ic_curmode anyway?
 2432                  */
 2433                 if (ic->ic_curmode == IEEE80211_MODE_11G &&
 2434                     (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION))
 2435                         ic->ic_flags |= IEEE80211_F_USEPROT;
 2436                 else
 2437                         ic->ic_flags &= ~IEEE80211_F_USEPROT;
 2438                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 2439                     "[%s] %sassoc success: %s preamble, %s slot time%s%s\n",
 2440                     ether_sprintf(wh->i_addr2),
 2441                     ISREASSOC(subtype) ? "re" : "",
 2442                     ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
 2443                     ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
 2444                     ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "",
 2445                     ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : ""
 2446                 );
 2447                 ieee80211_new_state(ic, IEEE80211_S_RUN, subtype);
 2448                 break;
 2449         }
 2450 
 2451         case IEEE80211_FC0_SUBTYPE_DEAUTH: {
 2452                 u_int16_t reason;
 2453 
 2454                 if (ic->ic_state == IEEE80211_S_SCAN) {
 2455                         ic->ic_stats.is_rx_mgtdiscard++;
 2456                         return;
 2457                 }
 2458                 /*
 2459                  * deauth frame format
 2460                  *      [2] reason
 2461                  */
 2462                 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
 2463                 reason = le16toh(*(u_int16_t *)frm);
 2464                 ic->ic_stats.is_rx_deauth++;
 2465                 IEEE80211_NODE_STAT(ni, rx_deauth);
 2466 
 2467                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 2468                     "[%s] recv deauthenticate (reason %d)\n",
 2469                     ether_sprintf(ni->ni_macaddr), reason);
 2470                 switch (ic->ic_opmode) {
 2471                 case IEEE80211_M_STA:
 2472                         ieee80211_new_state(ic, IEEE80211_S_AUTH,
 2473                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 2474                         break;
 2475                 case IEEE80211_M_HOSTAP:
 2476                         if (ni != ic->ic_bss)
 2477                                 ieee80211_node_leave(ic, ni);
 2478                         break;
 2479                 default:
 2480                         ic->ic_stats.is_rx_mgtdiscard++;
 2481                         break;
 2482                 }
 2483                 break;
 2484         }
 2485 
 2486         case IEEE80211_FC0_SUBTYPE_DISASSOC: {
 2487                 u_int16_t reason;
 2488 
 2489                 if (ic->ic_state != IEEE80211_S_RUN &&
 2490                     ic->ic_state != IEEE80211_S_ASSOC &&
 2491                     ic->ic_state != IEEE80211_S_AUTH) {
 2492                         ic->ic_stats.is_rx_mgtdiscard++;
 2493                         return;
 2494                 }
 2495                 /*
 2496                  * disassoc frame format
 2497                  *      [2] reason
 2498                  */
 2499                 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
 2500                 reason = le16toh(*(u_int16_t *)frm);
 2501                 ic->ic_stats.is_rx_disassoc++;
 2502                 IEEE80211_NODE_STAT(ni, rx_disassoc);
 2503 
 2504                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 2505                     "[%s] recv disassociate (reason %d)\n",
 2506                     ether_sprintf(ni->ni_macaddr), reason);
 2507                 switch (ic->ic_opmode) {
 2508                 case IEEE80211_M_STA:
 2509                         ieee80211_new_state(ic, IEEE80211_S_ASSOC,
 2510                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 2511                         break;
 2512                 case IEEE80211_M_HOSTAP:
 2513                         if (ni != ic->ic_bss)
 2514                                 ieee80211_node_leave(ic, ni);
 2515                         break;
 2516                 default:
 2517                         ic->ic_stats.is_rx_mgtdiscard++;
 2518                         break;
 2519                 }
 2520                 break;
 2521         }
 2522         default:
 2523                 IEEE80211_DISCARD(ic, IEEE80211_MSG_ANY,
 2524                      wh, "mgt", "subtype 0x%x not handled", subtype);
 2525                 ic->ic_stats.is_rx_badsubtype++;
 2526                 break;
 2527         }
 2528 #undef ISREASSOC
 2529 #undef ISPROBE
 2530 }
 2531 #undef IEEE80211_VERIFY_LENGTH
 2532 #undef IEEE80211_VERIFY_ELEMENT
 2533 
 2534 /*
 2535  * Handle station power-save state change.
 2536  */
 2537 static void
 2538 ieee80211_node_pwrsave(struct ieee80211_node *ni, int enable)
 2539 {
 2540         struct ieee80211com *ic = ni->ni_ic;
 2541         struct mbuf *m;
 2542 
 2543         if (enable) {
 2544                 if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) == 0)
 2545                         ic->ic_ps_sta++;
 2546                 ni->ni_flags |= IEEE80211_NODE_PWR_MGT;
 2547                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2548                     "[%s] power save mode on, %u sta's in ps mode\n",
 2549                     ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
 2550                 return;
 2551         }
 2552 
 2553         if (ni->ni_flags & IEEE80211_NODE_PWR_MGT)
 2554                 ic->ic_ps_sta--;
 2555         ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
 2556         IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2557             "[%s] power save mode off, %u sta's in ps mode\n",
 2558             ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
 2559         /* XXX if no stations in ps mode, flush mc frames */
 2560 
 2561         /*
 2562          * Flush queued unicast frames.
 2563          */
 2564         if (IEEE80211_NODE_SAVEQ_QLEN(ni) == 0) {
 2565                 if (ic->ic_set_tim != NULL)
 2566                         ic->ic_set_tim(ni, 0);          /* just in case */
 2567                 return;
 2568         }
 2569         IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2570             "[%s] flush ps queue, %u packets queued\n",
 2571             ether_sprintf(ni->ni_macaddr), IEEE80211_NODE_SAVEQ_QLEN(ni));
 2572         for (;;) {
 2573                 int qlen;
 2574 
 2575                 IEEE80211_NODE_SAVEQ_DEQUEUE(ni, m, qlen);
 2576                 if (m == NULL)
 2577                         break;
 2578                 /* 
 2579                  * If this is the last packet, turn off the TIM bit.
 2580                  * If there are more packets, set the more packets bit
 2581                  * in the mbuf so ieee80211_encap will mark the 802.11
 2582                  * head to indicate more data frames will follow.
 2583                  */
 2584                 if (qlen != 0)
 2585                         m->m_flags |= M_MORE_DATA;
 2586                 /* XXX need different driver interface */
 2587                 /* XXX bypasses q max */
 2588                 IF_ENQUEUE(&ic->ic_ifp->if_snd, m);
 2589         }
 2590         if (ic->ic_set_tim != NULL)
 2591                 ic->ic_set_tim(ni, 0);
 2592 }
 2593 
 2594 /*
 2595  * Process a received ps-poll frame.
 2596  */
 2597 static void
 2598 ieee80211_recv_pspoll(struct ieee80211com *ic,
 2599         struct ieee80211_node *ni, struct mbuf *m0)
 2600 {
 2601         struct ieee80211_frame_min *wh;
 2602         struct mbuf *m;
 2603         u_int16_t aid;
 2604         int qlen;
 2605 
 2606         wh = mtod(m0, struct ieee80211_frame_min *);
 2607         if (ni->ni_associd == 0) {
 2608                 IEEE80211_DISCARD(ic, IEEE80211_MSG_POWER | IEEE80211_MSG_DEBUG,
 2609                     (struct ieee80211_frame *) wh, "ps-poll",
 2610                     "%s", "unassociated station");
 2611                 ic->ic_stats.is_ps_unassoc++;
 2612                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
 2613                         IEEE80211_REASON_NOT_ASSOCED);
 2614                 return;
 2615         }
 2616 
 2617         aid = le16toh(*(u_int16_t *)wh->i_dur);
 2618         if (aid != ni->ni_associd) {
 2619                 IEEE80211_DISCARD(ic, IEEE80211_MSG_POWER | IEEE80211_MSG_DEBUG,
 2620                     (struct ieee80211_frame *) wh, "ps-poll",
 2621                     "aid mismatch: sta aid 0x%x poll aid 0x%x",
 2622                     ni->ni_associd, aid);
 2623                 ic->ic_stats.is_ps_badaid++;
 2624                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
 2625                         IEEE80211_REASON_NOT_ASSOCED);
 2626                 return;
 2627         }
 2628 
 2629         /* Okay, take the first queued packet and put it out... */
 2630         IEEE80211_NODE_SAVEQ_DEQUEUE(ni, m, qlen);
 2631         if (m == NULL) {
 2632                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2633                     "[%s] recv ps-poll, but queue empty\n",
 2634                     ether_sprintf(wh->i_addr2));
 2635                 ieee80211_send_nulldata(ieee80211_ref_node(ni));
 2636                 ic->ic_stats.is_ps_qempty++;    /* XXX node stat */
 2637                 if (ic->ic_set_tim != NULL)
 2638                         ic->ic_set_tim(ni, 0);  /* just in case */
 2639                 return;
 2640         }
 2641         /* 
 2642          * If there are more packets, set the more packets bit
 2643          * in the packet dispatched to the station; otherwise
 2644          * turn off the TIM bit.
 2645          */
 2646         if (qlen != 0) {
 2647                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2648                     "[%s] recv ps-poll, send packet, %u still queued\n",
 2649                     ether_sprintf(ni->ni_macaddr), qlen);
 2650                 m->m_flags |= M_MORE_DATA;
 2651         } else {
 2652                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2653                     "[%s] recv ps-poll, send packet, queue empty\n",
 2654                     ether_sprintf(ni->ni_macaddr));
 2655                 if (ic->ic_set_tim != NULL)
 2656                         ic->ic_set_tim(ni, 0);
 2657         }
 2658         m->m_flags |= M_PWR_SAV;                /* bypass PS handling */
 2659         IF_ENQUEUE(&ic->ic_ifp->if_snd, m);
 2660 }
 2661 
 2662 #ifdef IEEE80211_DEBUG
 2663 /*
 2664  * Debugging support.
 2665  */
 2666 
 2667 /*
 2668  * Return the bssid of a frame.
 2669  */
 2670 static const u_int8_t *
 2671 ieee80211_getbssid(struct ieee80211com *ic, const struct ieee80211_frame *wh)
 2672 {
 2673         if (ic->ic_opmode == IEEE80211_M_STA)
 2674                 return wh->i_addr2;
 2675         if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != IEEE80211_FC1_DIR_NODS)
 2676                 return wh->i_addr1;
 2677         if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
 2678                 return wh->i_addr1;
 2679         return wh->i_addr3;
 2680 }
 2681 
 2682 void
 2683 ieee80211_note(struct ieee80211com *ic, const char *fmt, ...)
 2684 {
 2685         char buf[128];          /* XXX */
 2686         va_list ap;
 2687 
 2688         va_start(ap, fmt);
 2689         vsnprintf(buf, sizeof(buf), fmt, ap);
 2690         va_end(ap);
 2691 
 2692         if_printf(ic->ic_ifp, "%s", buf);       /* NB: no \n */
 2693 }
 2694 
 2695 void
 2696 ieee80211_note_frame(struct ieee80211com *ic,
 2697         const struct ieee80211_frame *wh,
 2698         const char *fmt, ...)
 2699 {
 2700         char buf[128];          /* XXX */
 2701         va_list ap;
 2702 
 2703         va_start(ap, fmt);
 2704         vsnprintf(buf, sizeof(buf), fmt, ap);
 2705         va_end(ap);
 2706         if_printf(ic->ic_ifp, "[%s] %s\n",
 2707                 ether_sprintf(ieee80211_getbssid(ic, wh)), buf);
 2708 }
 2709 
 2710 void
 2711 ieee80211_note_mac(struct ieee80211com *ic,
 2712         const u_int8_t mac[IEEE80211_ADDR_LEN],
 2713         const char *fmt, ...)
 2714 {
 2715         char buf[128];          /* XXX */
 2716         va_list ap;
 2717 
 2718         va_start(ap, fmt);
 2719         vsnprintf(buf, sizeof(buf), fmt, ap);
 2720         va_end(ap);
 2721         if_printf(ic->ic_ifp, "[%s] %s\n", ether_sprintf(mac), buf);
 2722 }
 2723 
 2724 static void
 2725 ieee80211_discard_frame(struct ieee80211com *ic,
 2726         const struct ieee80211_frame *wh,
 2727         const char *type, const char *fmt, ...)
 2728 {
 2729         va_list ap;
 2730 
 2731         printf("[%s:%s] discard ", ic->ic_ifp->if_xname,
 2732                 ether_sprintf(ieee80211_getbssid(ic, wh)));
 2733         if (type != NULL)
 2734                 printf("%s frame, ", type);
 2735         else
 2736                 printf("frame, ");
 2737         va_start(ap, fmt);
 2738         vprintf(fmt, ap);
 2739         va_end(ap);
 2740         printf("\n");
 2741 }
 2742 
 2743 static void
 2744 ieee80211_discard_ie(struct ieee80211com *ic,
 2745         const struct ieee80211_frame *wh,
 2746         const char *type, const char *fmt, ...)
 2747 {
 2748         va_list ap;
 2749 
 2750         printf("[%s:%s] discard ", ic->ic_ifp->if_xname,
 2751                 ether_sprintf(ieee80211_getbssid(ic, wh)));
 2752         if (type != NULL)
 2753                 printf("%s information element, ", type);
 2754         else
 2755                 printf("information element, ");
 2756         va_start(ap, fmt);
 2757         vprintf(fmt, ap);
 2758         va_end(ap);
 2759         printf("\n");
 2760 }
 2761 
 2762 static void
 2763 ieee80211_discard_mac(struct ieee80211com *ic,
 2764         const u_int8_t mac[IEEE80211_ADDR_LEN],
 2765         const char *type, const char *fmt, ...)
 2766 {
 2767         va_list ap;
 2768 
 2769         printf("[%s:%s] discard ", ic->ic_ifp->if_xname, ether_sprintf(mac));
 2770         if (type != NULL)
 2771                 printf("%s frame, ", type);
 2772         else
 2773                 printf("frame, ");
 2774         va_start(ap, fmt);
 2775         vprintf(fmt, ap);
 2776         va_end(ap);
 2777         printf("\n");
 2778 }
 2779 #endif /* IEEE80211_DEBUG */

Cache object: fcceafb77050d752e91e7d883bcbc5d8


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