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-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: fb3ea97072b23a4a051b0a38f4fce521


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