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.38 2005/02/26 22:45:09 perry Exp $       */
    2 /*-
    3  * Copyright (c) 2001 Atsushi Onoe
    4  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * Alternatively, this software may be distributed under the terms of the
   19  * GNU General Public License ("GPL") version 2 as published by the Free
   20  * Software Foundation.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 #ifdef __FreeBSD__
   36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.20 2004/04/02 23:35:24 sam Exp $");
   37 #else
   38 __KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.38 2005/02/26 22:45:09 perry Exp $");
   39 #endif
   40 
   41 #include "opt_inet.h"
   42 
   43 #ifdef __NetBSD__
   44 #include "bpfilter.h"
   45 #endif /* __NetBSD__ */
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/mbuf.h>
   50 #include <sys/malloc.h>
   51 #include <sys/kernel.h>
   52 #include <sys/socket.h>
   53 #include <sys/sockio.h>
   54 #include <sys/endian.h>
   55 #include <sys/errno.h>
   56 #ifdef __FreeBSD__
   57 #include <sys/bus.h>
   58 #endif
   59 #include <sys/proc.h>
   60 #include <sys/sysctl.h>
   61 
   62 #ifdef __FreeBSD__
   63 #include <machine/atomic.h>
   64 #endif
   65 
   66 #include <net/if.h>
   67 #include <net/if_dl.h>
   68 #include <net/if_media.h>
   69 #include <net/if_arp.h>
   70 #ifdef __FreeBSD__
   71 #include <net/ethernet.h>
   72 #else
   73 #include <net/if_ether.h>
   74 #endif
   75 #include <net/if_llc.h>
   76 
   77 #include <net80211/ieee80211_var.h>
   78 #include <net80211/ieee80211_compat.h>
   79 
   80 #if NBPFILTER > 0
   81 #include <net/bpf.h>
   82 #endif
   83 
   84 #ifdef INET
   85 #include <netinet/in.h>
   86 #ifdef __FreeBSD__
   87 #include <netinet/if_ether.h>
   88 #else
   89 #include <net/if_ether.h>
   90 #endif
   91 #endif
   92 
   93 const struct timeval ieee80211_merge_print_intvl = {.tv_sec = 1, .tv_usec = 0};
   94 
   95 static void ieee80211_recv_pspoll(struct ieee80211com *,
   96     struct mbuf *, int, u_int32_t);
   97 
   98 #ifdef IEEE80211_DEBUG
   99 /*
  100  * Decide if a received management frame should be
  101  * printed when debugging is enabled.  This filters some
  102  * of the less interesting frames that come frequently
  103  * (e.g. beacons).
  104  */
  105 static __inline int
  106 doprint(struct ieee80211com *ic, int subtype)
  107 {
  108         switch (subtype) {
  109         case IEEE80211_FC0_SUBTYPE_BEACON:
  110                 return (ic->ic_state == IEEE80211_S_SCAN);
  111         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
  112                 return (ic->ic_opmode == IEEE80211_M_IBSS);
  113         }
  114         return 1;
  115 }
  116 #endif
  117 
  118 /*
  119  * Process a received frame.  The node associated with the sender
  120  * should be supplied.  If nothing was found in the node table then
  121  * the caller is assumed to supply a reference to ic_bss instead.
  122  * The RSSI and a timestamp are also supplied.  The RSSI data is used
  123  * during AP scanning to select a AP to associate with; it can have
  124  * any units so long as values have consistent units and higher values
  125  * mean ``better signal''.  The receive timestamp is currently not used
  126  * by the 802.11 layer.
  127  */
  128 void
  129 ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
  130         int rssi, u_int32_t rstamp)
  131 {
  132         struct ieee80211com *ic = (void *)ifp;
  133         struct ieee80211_frame *wh;
  134         struct ether_header *eh;
  135         struct mbuf *m1;
  136         int len;
  137         u_int8_t dir, type, subtype;
  138         u_int16_t rxseq;
  139         ALTQ_DECL(struct altq_pktattr pktattr;)
  140 
  141         IASSERT(ni != NULL, ("null node"));
  142 
  143         /* trim CRC here so WEP can find its own CRC at the end of packet. */
  144         if (m->m_flags & M_HASFCS) {
  145                 m_adj(m, -IEEE80211_CRC_LEN);
  146                 m->m_flags &= ~M_HASFCS;
  147         }
  148 
  149         /*
  150          * In monitor mode, send everything directly to bpf.
  151          * Also do not process frames w/o i_addr2 any further.
  152          * XXX may want to include the CRC
  153          */
  154         if (ic->ic_opmode == IEEE80211_M_MONITOR ||
  155             m->m_pkthdr.len < sizeof(struct ieee80211_frame_min))
  156                 goto out;
  157 
  158         wh = mtod(m, struct ieee80211_frame *);
  159         if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
  160             IEEE80211_FC0_VERSION_0) {
  161                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
  162                         ("receive packet with wrong version: %x\n",
  163                         wh->i_fc[0]));
  164                 ic->ic_stats.is_rx_badversion++;
  165                 goto err;
  166         }
  167 
  168         dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
  169         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
  170         /*
  171          * NB: We are not yet prepared to handle control frames,
  172          *     but permitting drivers to send them to us allows
  173          *     them to go through bpf tapping at the 802.11 layer.
  174          */
  175         if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
  176                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
  177                         ("%s: frame too short, len %u\n",
  178                         __func__, m->m_pkthdr.len));
  179                 ic->ic_stats.is_rx_tooshort++;
  180                 goto out;
  181         }
  182         if (ic->ic_state != IEEE80211_S_SCAN) {
  183                 ni->ni_rssi = rssi;
  184                 ni->ni_rstamp = rstamp;
  185                 rxseq = ni->ni_rxseq;
  186                 ni->ni_rxseq =
  187                     le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
  188                 /* TODO: fragment */
  189                 if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
  190                     rxseq == ni->ni_rxseq) {
  191                         /* duplicate, silently discarded */
  192                         ic->ic_stats.is_rx_dup++; /* XXX per-station stat */
  193                         goto out;
  194                 }
  195                 ni->ni_inact = 0;
  196                 if (ic->ic_opmode == IEEE80211_M_MONITOR)
  197                         goto out;
  198         }
  199 
  200         if (ic->ic_set_tim != NULL &&
  201             (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT)
  202             && ni->ni_pwrsave == 0) {
  203                 /* turn on power save mode */
  204 
  205                 if (ifp->if_flags & IFF_DEBUG)
  206                         printf("%s: power save mode on for %s\n",
  207                             ifp->if_xname, ether_sprintf(wh->i_addr2));
  208 
  209                 ni->ni_pwrsave = IEEE80211_PS_SLEEP;
  210         }
  211         if (ic->ic_set_tim != NULL &&
  212             (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) == 0 &&
  213             ni->ni_pwrsave != 0) {
  214                 /* turn off power save mode, dequeue stored packets */
  215 
  216                 ni->ni_pwrsave = 0;
  217                 if (ic->ic_set_tim)
  218                         ic->ic_set_tim(ic, ni->ni_associd, 0);
  219 
  220                 if (ifp->if_flags & IFF_DEBUG)
  221                         printf("%s: power save mode off for %s\n",
  222                             ifp->if_xname, ether_sprintf(wh->i_addr2));
  223 
  224                 while (!IF_IS_EMPTY(&ni->ni_savedq)) {
  225                         struct mbuf *m;
  226                         IF_DEQUEUE(&ni->ni_savedq, m);
  227                         IF_ENQUEUE(&ic->ic_pwrsaveq, m);
  228                         (*ifp->if_start)(ifp);
  229                 }
  230         }
  231 
  232         switch (type) {
  233         case IEEE80211_FC0_TYPE_DATA:
  234                 switch (ic->ic_opmode) {
  235                 case IEEE80211_M_STA:
  236                         if (dir != IEEE80211_FC1_DIR_FROMDS) {
  237                                 ic->ic_stats.is_rx_wrongdir++;
  238                                 goto out;
  239                         }
  240                         if (ic->ic_state != IEEE80211_S_SCAN &&
  241                             !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
  242                                 /* Source address is not our BSS. */
  243                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT,
  244                                         ("%s: discard frame from SA %s\n",
  245                                         __func__, ether_sprintf(wh->i_addr2)));
  246                                 ic->ic_stats.is_rx_wrongbss++;
  247                                 goto out;
  248                         }
  249                         if ((ifp->if_flags & IFF_SIMPLEX) &&
  250                             IEEE80211_IS_MULTICAST(wh->i_addr1) &&
  251                             IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
  252                                 /*
  253                                  * In IEEE802.11 network, multicast packet
  254                                  * sent from me is broadcasted from AP.
  255                                  * It should be silently discarded for
  256                                  * SIMPLEX interface.
  257                                  */
  258                                 ic->ic_stats.is_rx_mcastecho++;
  259                                 goto out;
  260                         }
  261                         break;
  262                 case IEEE80211_M_IBSS:
  263                 case IEEE80211_M_AHDEMO:
  264                         if (dir != IEEE80211_FC1_DIR_NODS) {
  265                                 ic->ic_stats.is_rx_wrongdir++;
  266                                 goto out;
  267                         }
  268                         if (ic->ic_state != IEEE80211_S_SCAN &&
  269                             !IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid) &&
  270                             !IEEE80211_ADDR_EQ(wh->i_addr3, ifp->if_broadcastaddr)) {
  271                                 /* Destination is not our BSS or broadcast. */
  272                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT,
  273                                         ("%s: discard data frame to DA %s\n",
  274                                         __func__, ether_sprintf(wh->i_addr3)));
  275                                 ic->ic_stats.is_rx_wrongbss++;
  276                                 goto out;
  277                         }
  278                         break;
  279                 case IEEE80211_M_HOSTAP:
  280                         if (dir != IEEE80211_FC1_DIR_TODS) {
  281                                 ic->ic_stats.is_rx_wrongdir++;
  282                                 goto out;
  283                         }
  284                         if (ic->ic_state != IEEE80211_S_SCAN &&
  285                             !IEEE80211_ADDR_EQ(wh->i_addr1, ic->ic_bss->ni_bssid) &&
  286                             !IEEE80211_ADDR_EQ(wh->i_addr1, ifp->if_broadcastaddr)) {
  287                                 /* BSS is not us or broadcast. */
  288                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT,
  289                                         ("%s: discard data frame to BSS %s\n",
  290                                         __func__, ether_sprintf(wh->i_addr1)));
  291                                 ic->ic_stats.is_rx_wrongbss++;
  292                                 goto out;
  293                         }
  294                         /* check if source STA is associated */
  295                         if (ni == ic->ic_bss) {
  296                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT,
  297                                         ("%s: data from unknown src %s\n",
  298                                         __func__, ether_sprintf(wh->i_addr2)));
  299                                 /* NB: caller deals with reference */
  300                                 ni = ieee80211_dup_bss(ic, wh->i_addr2);
  301                                 if (ni != NULL) {
  302                                         IEEE80211_SEND_MGMT(ic, ni,
  303                                             IEEE80211_FC0_SUBTYPE_DEAUTH,
  304                                             IEEE80211_REASON_NOT_AUTHED);
  305                                 }
  306                                 ic->ic_stats.is_rx_notassoc++;
  307                                 goto err;
  308                         }
  309                         if (ni->ni_associd == 0) {
  310                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT,
  311                                         ("%s: data from unassoc src %s\n",
  312                                         __func__, ether_sprintf(wh->i_addr2)));
  313                                 IEEE80211_SEND_MGMT(ic, ni,
  314                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
  315                                     IEEE80211_REASON_NOT_ASSOCED);
  316                                 ic->ic_stats.is_rx_notassoc++;
  317                                 goto err;
  318                         }
  319                         break;
  320                 case IEEE80211_M_MONITOR:
  321                         break;
  322                 }
  323                 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
  324                         if (ic->ic_flags & IEEE80211_F_PRIVACY) {
  325                                 m = ieee80211_wep_crypt(ifp, m, 0);
  326                                 if (m == NULL) {
  327                                         ic->ic_stats.is_rx_wepfail++;
  328                                         goto err;
  329                                 }
  330                                 wh = mtod(m, struct ieee80211_frame *);
  331                         } else {
  332                                 ic->ic_stats.is_rx_nowep++;
  333                                 goto out;
  334                         }
  335                 }
  336 #if NBPFILTER > 0
  337                 /* copy to listener after decrypt */
  338                 if (ic->ic_rawbpf)
  339                         bpf_mtap(ic->ic_rawbpf, m);
  340 #endif
  341                 m = ieee80211_decap(ifp, m);
  342                 if (m == NULL) {
  343                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT,
  344                                 ("%s: decapsulation error for src %s\n",
  345                                 __func__, ether_sprintf(wh->i_addr2)));
  346                         ic->ic_stats.is_rx_decap++;
  347                         goto err;
  348                 }
  349                 ifp->if_ipackets++;
  350 
  351                 /* perform as a bridge within the AP */
  352                 m1 = NULL;
  353                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  354                         eh = mtod(m, struct ether_header *);
  355                         if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
  356                                 m1 = m_copypacket(m, M_DONTWAIT);
  357                                 if (m1 == NULL)
  358                                         ifp->if_oerrors++;
  359                                 else
  360                                         m1->m_flags |= M_MCAST;
  361                         } else {
  362                                 ni = ieee80211_find_node(ic, eh->ether_dhost);
  363                                 if (ni != NULL) {
  364                                         if (ni->ni_associd != 0) {
  365                                                 m1 = m;
  366                                                 m = NULL;
  367                                         }
  368                                 }
  369                         }
  370                         if (m1 != NULL) {
  371 #ifdef ALTQ
  372                                 if (ALTQ_IS_ENABLED(&ifp->if_snd))
  373                                         altq_etherclassify(&ifp->if_snd, m1,
  374                                             &pktattr);
  375 #endif
  376                                 len = m1->m_pkthdr.len;
  377                                 IF_ENQUEUE(&ifp->if_snd, m1);
  378                                 if (m != NULL)
  379                                         ifp->if_omcasts++;
  380                                 ifp->if_obytes += len;
  381                         }
  382                 }
  383                 if (m != NULL) {
  384 #if NBPFILTER > 0
  385                         /*
  386                          * If we forward packet into transmitter of the AP,
  387                          * we don't need to duplicate for DLT_EN10MB.
  388                          */
  389                         if (ifp->if_bpf && m1 == NULL)
  390                                 bpf_mtap(ifp->if_bpf, m);
  391 #endif
  392                         (*ifp->if_input)(ifp, m);
  393                 }
  394                 return;
  395 
  396         case IEEE80211_FC0_TYPE_MGT:
  397                 if (dir != IEEE80211_FC1_DIR_NODS) {
  398                         ic->ic_stats.is_rx_wrongdir++;
  399                         goto err;
  400                 }
  401                 if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
  402                         ic->ic_stats.is_rx_ahdemo_mgt++;
  403                         goto out;
  404                 }
  405                 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
  406 
  407                 /* drop frames without interest */
  408                 if (ic->ic_state == IEEE80211_S_SCAN) {
  409                         if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
  410                             subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
  411                                 ic->ic_stats.is_rx_mgtdiscard++;
  412                                 goto out;
  413                         }
  414                 }
  415 
  416 #ifdef IEEE80211_DEBUG
  417                 if ((ieee80211_msg_debug(ic) && doprint(ic, subtype)) ||
  418                     ieee80211_msg_dumppkts(ic)) {
  419                         if_printf(ifp, "received %s from %s rssi %d\n",
  420                             ieee80211_mgt_subtype_name[subtype
  421                             >> IEEE80211_FC0_SUBTYPE_SHIFT],
  422                             ether_sprintf(wh->i_addr2), rssi);
  423                 }
  424 #endif
  425 #if NBPFILTER > 0
  426                 if (ic->ic_rawbpf)
  427                         bpf_mtap(ic->ic_rawbpf, m);
  428 #endif
  429                 (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
  430                 m_freem(m);
  431                 return;
  432 
  433         case IEEE80211_FC0_TYPE_CTL:
  434                 ic->ic_stats.is_rx_ctl++;
  435                 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
  436                         goto out;
  437                 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
  438                 if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL) {
  439                         /* XXX statistic */
  440                         /* Dump out a single packet from the host */
  441                         if (ifp->if_flags & IFF_DEBUG)
  442                                 printf("%s: got power save probe from %s\n",
  443                                     ifp->if_xname,
  444                                     ether_sprintf(wh->i_addr2));
  445                         ieee80211_recv_pspoll(ic, m, rssi, rstamp);
  446                 }
  447                 goto out;
  448         default:
  449                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
  450                         ("%s: bad frame type %x\n", __func__, type));
  451                 /* should not come here */
  452                 break;
  453         }
  454   err:
  455         ifp->if_ierrors++;
  456   out:
  457         if (m != NULL) {
  458 #if NBPFILTER > 0
  459                 if (ic->ic_rawbpf)
  460                         bpf_mtap(ic->ic_rawbpf, m);
  461 #endif
  462                 m_freem(m);
  463         }
  464 }
  465 
  466 struct mbuf *
  467 ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
  468 {
  469         struct ether_header *eh;
  470         struct ieee80211_frame wh;
  471         struct llc *llc;
  472 
  473         if (m->m_len < sizeof(wh) + sizeof(*llc)) {
  474                 m = m_pullup(m, sizeof(wh) + sizeof(*llc));
  475                 if (m == NULL)
  476                         return NULL;
  477         }
  478         memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
  479         llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
  480         if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
  481             llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
  482             llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
  483                 m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh));
  484                 llc = NULL;
  485         } else {
  486                 m_adj(m, sizeof(wh) - sizeof(*eh));
  487         }
  488         eh = mtod(m, struct ether_header *);
  489         switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
  490         case IEEE80211_FC1_DIR_NODS:
  491                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
  492                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
  493                 break;
  494         case IEEE80211_FC1_DIR_TODS:
  495                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
  496                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
  497                 break;
  498         case IEEE80211_FC1_DIR_FROMDS:
  499                 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
  500                 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
  501                 break;
  502         case IEEE80211_FC1_DIR_DSTODS:
  503                 /* not yet supported */
  504                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
  505                         ("%s: discard DS to DS frame\n", __func__));
  506                 m_freem(m);
  507                 return NULL;
  508         }
  509 #ifdef ALIGNED_POINTER
  510         if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), u_int32_t)) {
  511                 struct mbuf *n, *n0, **np;
  512                 caddr_t newdata;
  513                 int off, pktlen;
  514 
  515                 n0 = NULL;
  516                 np = &n0;
  517                 off = 0;
  518                 pktlen = m->m_pkthdr.len;
  519                 while (pktlen > off) {
  520                         if (n0 == NULL) {
  521                                 MGETHDR(n, M_DONTWAIT, MT_DATA);
  522                                 if (n == NULL) {
  523                                         m_freem(m);
  524                                         return NULL;
  525                                 }
  526 #ifdef __FreeBSD__
  527                                 M_MOVE_PKTHDR(n, m);
  528 #else
  529                                 M_COPY_PKTHDR(n, m);
  530 #endif
  531                                 n->m_len = MHLEN;
  532                         } else {
  533                                 MGET(n, M_DONTWAIT, MT_DATA);
  534                                 if (n == NULL) {
  535                                         m_freem(m);
  536                                         m_freem(n0);
  537                                         return NULL;
  538                                 }
  539                                 n->m_len = MLEN;
  540                         }
  541                         if (pktlen - off >= MINCLSIZE) {
  542                                 MCLGET(n, M_DONTWAIT);
  543                                 if (n->m_flags & M_EXT)
  544                                         n->m_len = n->m_ext.ext_size;
  545                         }
  546                         if (n0 == NULL) {
  547                                 newdata =
  548                                     (caddr_t)ALIGN(n->m_data + sizeof(*eh)) -
  549                                     sizeof(*eh);
  550                                 n->m_len -= newdata - n->m_data;
  551                                 n->m_data = newdata;
  552                         }
  553                         if (n->m_len > pktlen - off)
  554                                 n->m_len = pktlen - off;
  555                         m_copydata(m, off, n->m_len, mtod(n, caddr_t));
  556                         off += n->m_len;
  557                         *np = n;
  558                         np = &n->m_next;
  559                 }
  560                 m_freem(m);
  561                 m = n0;
  562         }
  563 #endif /* ALIGNED_POINTER */
  564         if (llc != NULL) {
  565                 eh = mtod(m, struct ether_header *);
  566                 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
  567         }
  568         return m;
  569 }
  570 
  571 /*
  572  * Install received rate set information in the node's state block.
  573  */
  574 static int
  575 ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
  576         u_int8_t *rates, u_int8_t *xrates, int flags)
  577 {
  578         struct ieee80211_rateset *rs = &ni->ni_rates;
  579 
  580         memset(rs, 0, sizeof(*rs));
  581         rs->rs_nrates = rates[1];
  582         memcpy(rs->rs_rates, rates + 2, rs->rs_nrates);
  583         if (xrates != NULL) {
  584                 u_int8_t nxrates;
  585                 /*
  586                  * Tack on 11g extended supported rate element.
  587                  */
  588                 nxrates = xrates[1];
  589                 if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
  590                         nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates;
  591                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_XRATE,
  592                                 ("%s: extended rate set too large;"
  593                                 " only using %u of %u rates\n",
  594                                 __func__, nxrates, xrates[1]));
  595                         ic->ic_stats.is_rx_rstoobig++;
  596                 }
  597                 memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
  598                 rs->rs_nrates += nxrates;
  599         }
  600         return ieee80211_fix_rate(ic, ni, flags);
  601 }
  602 
  603 /* Verify the existence and length of __elem or get out. */
  604 #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do {                 \
  605         if ((__elem) == NULL) {                                         \
  606                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ELEMID,             \
  607                         ("%s: no " #__elem "in %s frame\n",             \
  608                         __func__, ieee80211_mgt_subtype_name[subtype >> \
  609                                 IEEE80211_FC0_SUBTYPE_SHIFT]));         \
  610                 ic->ic_stats.is_rx_elem_missing++;                      \
  611                 return;                                                 \
  612         }                                                               \
  613         if ((__elem)[1] > (__maxlen)) {                                 \
  614                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ELEMID,             \
  615                         ("%s: bad " #__elem " len %d in %s frame from %s\n",\
  616                         __func__, (__elem)[1],                          \
  617                         ieee80211_mgt_subtype_name[subtype >>           \
  618                                 IEEE80211_FC0_SUBTYPE_SHIFT],           \
  619                         ether_sprintf(wh->i_addr2)));                   \
  620                 ic->ic_stats.is_rx_elem_toobig++;                       \
  621                 return;                                                 \
  622         }                                                               \
  623 } while (0)
  624 
  625 #define IEEE80211_VERIFY_LENGTH(_len, _minlen) do {                     \
  626         if ((_len) < (_minlen)) {                                       \
  627                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ELEMID,             \
  628                         ("%s: %s frame too short from %s\n",            \
  629                         __func__,                                       \
  630                         ieee80211_mgt_subtype_name[subtype >>           \
  631                                 IEEE80211_FC0_SUBTYPE_SHIFT],           \
  632                         ether_sprintf(wh->i_addr2)));                   \
  633                 ic->ic_stats.is_rx_elem_toosmall++;                     \
  634                 return;                                                 \
  635         }                                                               \
  636 } while (0)
  637 
  638 #ifdef IEEE80211_DEBUG
  639 static void
  640 ieee80211_ssid_mismatch(struct ieee80211com *ic, const char *tag,
  641         u_int8_t mac[IEEE80211_ADDR_LEN], u_int8_t *ssid)
  642 {
  643         printf("[%s] %s req ssid mismatch: ", ether_sprintf(mac), tag);
  644         ieee80211_print_essid(ssid + 2, ssid[1]);
  645         printf("\n");
  646 }
  647 
  648 #define IEEE80211_VERIFY_SSID(_ni, _ssid, _packet_type) do {            \
  649         if ((_ssid)[1] != 0 &&                                          \
  650             ((_ssid)[1] != (_ni)->ni_esslen ||                          \
  651             memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
  652                 if (ieee80211_msg_input(ic))                            \
  653                         ieee80211_ssid_mismatch(ic, _packet_type,       \
  654                                 wh->i_addr2, _ssid);                    \
  655                 ic->ic_stats.is_rx_ssidmismatch++;                      \
  656                 return;                                                 \
  657         }                                                               \
  658 } while (0)
  659 #else /* !IEEE80211_DEBUG */
  660 #define IEEE80211_VERIFY_SSID(_ni, _ssid, _packet_type) do {            \
  661         if ((_ssid)[1] != 0 &&                                          \
  662             ((_ssid)[1] != (_ni)->ni_esslen ||                          \
  663             memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
  664                 ic->ic_stats.is_rx_ssidmismatch++;                      \
  665                 return;                                                 \
  666         }                                                               \
  667 } while (0)
  668 #endif /* !IEEE80211_DEBUG */
  669 
  670 static void
  671 ieee80211_auth_open(struct ieee80211com *ic, struct ieee80211_frame *wh,
  672     struct ieee80211_node *ni, int rssi, u_int32_t rstamp, u_int16_t seq,
  673     u_int16_t status)
  674 {
  675         switch (ic->ic_opmode) {
  676         case IEEE80211_M_IBSS:
  677                 if (ic->ic_state != IEEE80211_S_RUN ||
  678                     seq != IEEE80211_AUTH_OPEN_REQUEST) {
  679                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  680                                 ("%s: discard auth from %s; state %u, seq %u\n",
  681                                 __func__, ether_sprintf(wh->i_addr2),
  682                                 ic->ic_state, seq));
  683                         ic->ic_stats.is_rx_bad_auth++;
  684                         return;
  685                 }
  686                 ieee80211_new_state(ic, IEEE80211_S_AUTH,
  687                     wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
  688                 break;
  689 
  690         case IEEE80211_M_AHDEMO:
  691                 /* should not come here */
  692                 break;
  693 
  694         case IEEE80211_M_HOSTAP:
  695                 if (ic->ic_state != IEEE80211_S_RUN ||
  696                     seq != IEEE80211_AUTH_OPEN_REQUEST) {
  697                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  698                                 ("%s: discard auth from %s; state %u, seq %u\n",
  699                                 __func__, ether_sprintf(wh->i_addr2),
  700                                 ic->ic_state, seq));
  701                         ic->ic_stats.is_rx_bad_auth++;
  702                         return;
  703                 }
  704                 if (ni == ic->ic_bss) {
  705                         ni = ieee80211_alloc_node(ic, wh->i_addr2);
  706                         if (ni == NULL) {
  707                                 ic->ic_stats.is_rx_nodealloc++;
  708                                 return;
  709                         }
  710                         IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
  711                         ni->ni_rssi = rssi;
  712                         ni->ni_rstamp = rstamp;
  713                         ni->ni_chan = ic->ic_bss->ni_chan;
  714                 }
  715                 IEEE80211_SEND_MGMT(ic, ni,
  716                         IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
  717                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  718                         ("station %s %s authenticated (open)\n",
  719                         ether_sprintf(ni->ni_macaddr),
  720                         ((ni->ni_state != IEEE80211_STA_CACHE)
  721                             ? "newly" : "already")));
  722                 ieee80211_node_newstate(ni, IEEE80211_STA_AUTH);
  723                 break;
  724 
  725         case IEEE80211_M_STA:
  726                 if (ic->ic_state != IEEE80211_S_AUTH ||
  727                     seq != IEEE80211_AUTH_OPEN_RESPONSE) {
  728                         ic->ic_stats.is_rx_bad_auth++;
  729                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  730                                 ("%s: discard auth from %s; state %u, seq %u\n",
  731                                 __func__, ether_sprintf(wh->i_addr2),
  732                                 ic->ic_state, seq));
  733                         return;
  734                 }
  735                 if (status != 0) {
  736                         IEEE80211_DPRINTF(ic,
  737                             IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  738                             ("open authentication failed (reason %d) for %s\n",
  739                             status,
  740                             ether_sprintf(wh->i_addr3)));
  741                         if (ni != ic->ic_bss)
  742                                 ni->ni_fails++;
  743                         ic->ic_stats.is_rx_auth_fail++;
  744                         return;
  745                 }
  746                 ieee80211_new_state(ic, IEEE80211_S_ASSOC,
  747                     wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
  748                 break;
  749         case IEEE80211_M_MONITOR:
  750                 break;
  751         }
  752 }
  753 
  754 /* TBD send appropriate responses on error? */
  755 static void
  756 ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh,
  757     u_int8_t *frm, u_int8_t *efrm, struct ieee80211_node *ni, int rssi,
  758     u_int32_t rstamp, u_int16_t seq, u_int16_t status)
  759 {
  760         u_int8_t *challenge = NULL;
  761         int i;
  762 
  763         if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
  764                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  765                         ("%s: WEP is off\n", __func__));
  766                 return;
  767         }
  768 
  769         if (frm + 1 < efrm) {
  770                 if (frm[1] + 2 > efrm - frm) {
  771                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  772                                 ("%s: elt %d %d bytes too long\n", __func__,
  773                                 frm[0], (frm[1] + 2) - (int)(efrm - frm)));
  774                         ic->ic_stats.is_rx_bad_auth++;
  775                         return;
  776                 }
  777                 if (*frm == IEEE80211_ELEMID_CHALLENGE)
  778                         challenge = frm;
  779                 frm += frm[1] + 2;
  780         }
  781         switch (seq) {
  782         case IEEE80211_AUTH_SHARED_CHALLENGE:
  783         case IEEE80211_AUTH_SHARED_RESPONSE:
  784                 if (challenge == NULL) {
  785                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  786                                 ("%s: no challenge sent\n", __func__));
  787                         ic->ic_stats.is_rx_bad_auth++;
  788                         return;
  789                 }
  790                 if (challenge[1] != IEEE80211_CHALLENGE_LEN) {
  791                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  792                                 ("%s: bad challenge len %d\n",
  793                                 __func__, challenge[1]));
  794                         ic->ic_stats.is_rx_bad_auth++;
  795                         return;
  796                 }
  797         default:
  798                 break;
  799         }
  800         switch (ic->ic_opmode) {
  801         case IEEE80211_M_MONITOR:
  802         case IEEE80211_M_AHDEMO:
  803         case IEEE80211_M_IBSS:
  804                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  805                         ("%s: unexpected operating mode\n", __func__));
  806                 return;
  807         case IEEE80211_M_HOSTAP:
  808                 if (ic->ic_state != IEEE80211_S_RUN) {
  809                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  810                                 ("%s: not running\n", __func__));
  811                         return;
  812                 }
  813                 switch (seq) {
  814                 case IEEE80211_AUTH_SHARED_REQUEST:
  815                         if (ni == ic->ic_bss) {
  816                                 ni = ieee80211_alloc_node(ic, wh->i_addr2);
  817                                 if (ni == NULL) {
  818                                         ic->ic_stats.is_rx_nodealloc++;
  819                                         return;
  820                                 }
  821                                 IEEE80211_ADDR_COPY(ni->ni_bssid,
  822                                     ic->ic_bss->ni_bssid);
  823                                 ni->ni_rssi = rssi;
  824                                 ni->ni_rstamp = rstamp;
  825                                 ni->ni_chan = ic->ic_bss->ni_chan;
  826                         }
  827                         if (ni->ni_challenge == NULL)
  828                                 ni->ni_challenge = (u_int32_t*)malloc(
  829                                     IEEE80211_CHALLENGE_LEN, M_DEVBUF,
  830                                     M_NOWAIT);
  831                         if (ni->ni_challenge == NULL) {
  832                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  833                                         ("%s: challenge alloc failed\n",
  834                                         __func__));
  835                                 /* XXX statistic */
  836                                 return;
  837                         }
  838                         for (i = IEEE80211_CHALLENGE_LEN / sizeof(u_int32_t);
  839                              --i >= 0; )
  840                                 ni->ni_challenge[i] = arc4random();
  841                         IEEE80211_DPRINTF(ic,
  842                                 IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  843                                 ("shared key %sauth request from station %s\n",
  844                                 ((ni->ni_state != IEEE80211_STA_CACHE)
  845                                     ? "" : "re"),
  846                                 ether_sprintf(ni->ni_macaddr)));
  847                         break;
  848                 case IEEE80211_AUTH_SHARED_RESPONSE:
  849                         if (ni == ic->ic_bss) {
  850                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  851                                         ("%s: unknown STA\n", __func__));
  852                                 return;
  853                         }
  854                         if (ni->ni_challenge == NULL) {
  855                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  856                                         ("%s: no challenge recorded\n",
  857                                         __func__));
  858                                 ic->ic_stats.is_rx_bad_auth++;
  859                                 return;
  860                         }
  861                         if (memcmp(ni->ni_challenge, &challenge[2],
  862                                    challenge[1]) != 0) {
  863                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  864                                         ("%s: challenge mismatch\n", __func__));
  865                                 ic->ic_stats.is_rx_auth_fail++;
  866                                 return;
  867                         }
  868                         IEEE80211_DPRINTF(ic,
  869                                 IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  870                                 ("station %s authenticated (shared key)\n",
  871                                 ether_sprintf(ni->ni_macaddr)));
  872                         ieee80211_node_newstate(ni, IEEE80211_STA_AUTH);
  873                         break;
  874                 default:
  875                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  876                                 ("%s: bad shared key auth seq %d from %s\n",
  877                                 __func__, seq, ether_sprintf(wh->i_addr2)));
  878                         ic->ic_stats.is_rx_bad_auth++;
  879                         return;
  880                 }
  881                 IEEE80211_SEND_MGMT(ic, ni,
  882                         IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
  883                 break;
  884 
  885         case IEEE80211_M_STA:
  886                 if (ic->ic_state != IEEE80211_S_AUTH)
  887                         return;
  888                 switch (seq) {
  889                 case IEEE80211_AUTH_SHARED_PASS:
  890                         if (ni->ni_challenge != NULL) {
  891                                 FREE(ni->ni_challenge, M_DEVBUF);
  892                                 ni->ni_challenge = NULL;
  893                         }
  894                         if (status != 0) {
  895                                 IEEE80211_DPRINTF(ic,
  896                                     IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
  897                                     ("%s: auth failed (reason %d) for %s\n",
  898                                     __func__, status,
  899                                     ether_sprintf(wh->i_addr3)));
  900                                 if (ni != ic->ic_bss)
  901                                         ni->ni_fails++;
  902                                 ic->ic_stats.is_rx_auth_fail++;
  903                                 return;
  904                         }
  905                         ieee80211_new_state(ic, IEEE80211_S_ASSOC,
  906                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
  907                         break;
  908                 case IEEE80211_AUTH_SHARED_CHALLENGE:
  909                         if (ni->ni_challenge == NULL)
  910                                 ni->ni_challenge = (u_int32_t*)malloc(
  911                                     challenge[1], M_DEVBUF, M_NOWAIT);
  912                         if (ni->ni_challenge == NULL) {
  913                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  914                                     ("%s: challenge alloc failed\n", __func__));
  915                                 /* XXX statistic */
  916                                 return;
  917                         }
  918                         memcpy(ni->ni_challenge, &challenge[2], challenge[1]);
  919                         IEEE80211_SEND_MGMT(ic, ni,
  920                                 IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
  921                         break;
  922                 default:
  923                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  924                                 ("%s: bad seq %d from %s\n", __func__, seq,
  925                                 ether_sprintf(wh->i_addr2)));
  926                         ic->ic_stats.is_rx_bad_auth++;
  927                         return;
  928                 }
  929                 break;
  930         }
  931 }
  932 
  933 void
  934 ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
  935         struct ieee80211_node *ni,
  936         int subtype, int rssi, u_int32_t rstamp)
  937 {
  938 #define ISPROBE(_st)    ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
  939 #define ISREASSOC(_st)  ((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)
  940         struct ieee80211_frame *wh;
  941         u_int8_t *frm, *efrm;
  942         u_int8_t *ssid, *rates, *xrates;
  943         int is_new, reassoc, resp;
  944 
  945         wh = mtod(m0, struct ieee80211_frame *);
  946         frm = (u_int8_t *)&wh[1];
  947         efrm = mtod(m0, u_int8_t *) + m0->m_len;
  948         switch (subtype) {
  949         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
  950         case IEEE80211_FC0_SUBTYPE_BEACON: {
  951                 u_int8_t *tstamp, *bintval, *capinfo, *country;
  952                 u_int8_t chan, bchan, fhindex, erp;
  953                 u_int16_t fhdwell;
  954 
  955                 /*
  956                  * We process beacon/probe response frames for:
  957                  *    o station mode: to collect state
  958                  *      updates such as 802.11g slot time and for passive
  959                  *      scanning of APs
  960                  *    o adhoc mode: to discover neighbors
  961                  *    o hostap mode: for passive scanning of neighbor APs
  962                  *    o when scanning
  963                  * In other words, in all modes other than monitor (which
  964                  * does not process incoming packets) and adhoc-demo (which
  965                  * does not use management frames at all).
  966                  */
  967 #ifdef DIAGNOSTIC
  968                 if (ic->ic_opmode != IEEE80211_M_STA &&
  969                     ic->ic_opmode != IEEE80211_M_IBSS &&
  970                     ic->ic_opmode != IEEE80211_M_HOSTAP &&
  971                     ic->ic_state != IEEE80211_S_SCAN) {
  972                         panic("%s: impossible", __func__);
  973                 }
  974 #endif
  975                 /*
  976                  * beacon/probe response frame format
  977                  *      [8] time stamp
  978                  *      [2] beacon interval
  979                  *      [2] capability information
  980                  *      [tlv] ssid
  981                  *      [tlv] supported rates
  982                  *      [tlv] country information
  983                  *      [tlv] parameter set (FH/DS)
  984                  *      [tlv] erp information
  985                  *      [tlv] extended supported rates
  986                  */
  987                 IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
  988                 tstamp  = frm;  frm += 8;
  989                 bintval = frm;  frm += 2;
  990                 capinfo = frm;  frm += 2;
  991                 ssid = rates = xrates = country = NULL;
  992                 bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
  993                 chan = bchan;
  994                 fhdwell = 0;
  995                 fhindex = 0;
  996                 erp = 0;
  997                 while (frm < efrm) {
  998                         switch (*frm) {
  999                         case IEEE80211_ELEMID_SSID:
 1000                                 ssid = frm;
 1001                                 break;
 1002                         case IEEE80211_ELEMID_RATES:
 1003                                 rates = frm;
 1004                                 break;
 1005                         case IEEE80211_ELEMID_COUNTRY:
 1006                                 country = frm;
 1007                                 break;
 1008                         case IEEE80211_ELEMID_FHPARMS:
 1009                                 if (ic->ic_phytype == IEEE80211_T_FH) {
 1010                                         fhdwell = (frm[3] << 8) | frm[2];
 1011                                         chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
 1012                                         fhindex = frm[6];
 1013                                 }
 1014                                 break;
 1015                         case IEEE80211_ELEMID_DSPARMS:
 1016                                 /*
 1017                                  * XXX hack this since depending on phytype
 1018                                  * is problematic for multi-mode devices.
 1019                                  */
 1020                                 if (ic->ic_phytype != IEEE80211_T_FH)
 1021                                         chan = frm[2];
 1022                                 break;
 1023                         case IEEE80211_ELEMID_TIM:
 1024                                 break;
 1025                         case IEEE80211_ELEMID_IBSSPARMS:
 1026                                 break;
 1027                         case IEEE80211_ELEMID_XRATES:
 1028                                 xrates = frm;
 1029                                 break;
 1030                         case IEEE80211_ELEMID_ERP:
 1031                                 if (frm[1] != 1) {
 1032                                         IEEE80211_DPRINTF(ic,
 1033                                                 IEEE80211_MSG_ELEMID,
 1034                                                 ("%s: invalid ERP element; "
 1035                                                 "length %u, expecting 1\n",
 1036                                                 __func__, frm[1]));
 1037                                         ic->ic_stats.is_rx_elem_toobig++;
 1038                                         break;
 1039                                 }
 1040                                 erp = frm[2];
 1041                                 break;
 1042                         default:
 1043                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ELEMID,
 1044                                         ("%s: element id %u/len %u ignored\n",
 1045                                         __func__, *frm, frm[1]));
 1046                                 ic->ic_stats.is_rx_elem_unknown++;
 1047                                 break;
 1048                         }
 1049                         frm += frm[1] + 2;
 1050                 }
 1051                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 1052                 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
 1053                 if (
 1054 #if IEEE80211_CHAN_MAX < 255
 1055                     chan > IEEE80211_CHAN_MAX ||
 1056 #endif
 1057                     isclr(ic->ic_chan_active, chan)) {
 1058                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ELEMID,
 1059                                 ("%s: ignore %s with invalid channel %u\n",
 1060                                 __func__,
 1061                                 ISPROBE(subtype) ? "probe response" : "beacon",
 1062                                 chan));
 1063                         ic->ic_stats.is_rx_badchan++;
 1064                         return;
 1065                 }
 1066                 if (chan != bchan && ic->ic_phytype != IEEE80211_T_FH) {
 1067                         /*
 1068                          * Frame was received on a channel different from the
 1069                          * one indicated in the DS params element id;
 1070                          * silently discard it.
 1071                          *
 1072                          * NB: this can happen due to signal leakage.
 1073                          *     But we should take it for FH phy because
 1074                          *     the rssi value should be correct even for
 1075                          *     different hop pattern in FH.
 1076                          */
 1077                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ELEMID,
 1078                                 ("%s: ignore %s on channel %u marked "
 1079                                 "for channel %u\n", __func__,
 1080                                 ISPROBE(subtype) ? "probe response" : "beacon",
 1081                                 bchan, chan));
 1082                         ic->ic_stats.is_rx_chanmismatch++;
 1083                         return;
 1084                 }
 1085 
 1086                 /*
 1087                  * Use mac and channel for lookup so we collect all
 1088                  * potential AP's when scanning.  Otherwise we may
 1089                  * see the same AP on multiple channels and will only
 1090                  * record the last one.  We could filter APs here based
 1091                  * on rssi, etc. but leave that to the end of the scan
 1092                  * so we can keep the selection criteria in one spot.
 1093                  * This may result in a bloat of the scanned AP list but
 1094                  * it shouldn't be too much.
 1095                  */
 1096                 ni = ieee80211_find_node_for_beacon(ic, wh->i_addr2,
 1097                                 &ic->ic_channels[chan], ssid);
 1098 #ifdef IEEE80211_DEBUG
 1099                 if (ieee80211_debug &&
 1100                     (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) {
 1101                         printf("%s: %s%s on chan %u (bss chan %u) ",
 1102                             __func__, (ni == NULL ? "new " : ""),
 1103                             ISPROBE(subtype) ? "probe response" : "beacon",
 1104                             chan, bchan);
 1105                         ieee80211_print_essid(ssid + 2, ssid[1]);
 1106                         printf(" from %s\n", ether_sprintf(wh->i_addr2));
 1107                         printf("%s: caps 0x%x bintval %u erp 0x%x\n",
 1108                                 __func__, le16toh(*(u_int16_t *)capinfo),
 1109                                 le16toh(*(u_int16_t *)bintval), erp);
 1110                         if (country) {
 1111                                 int i;
 1112                                 printf("%s: country info", __func__);
 1113                                 for (i = 0; i < country[1]; i++)
 1114                                         printf(" %02x", country[i+2]);
 1115                                 printf("\n");
 1116                         }
 1117                 }
 1118 #endif
 1119                 if (ni == NULL) {
 1120                         ni = ieee80211_alloc_node(ic, wh->i_addr2);
 1121                         if (ni == NULL)
 1122                                 return;
 1123                         is_new = 1;
 1124                 } else
 1125                         is_new = 0;
 1126                 if (ssid[1] != 0 && ni->ni_esslen == 0) {
 1127                         /*
 1128                          * Update ESSID at probe response to adopt hidden AP by
 1129                          * Lucent/Cisco, which announces null ESSID in beacon.
 1130                          */
 1131                         ni->ni_esslen = ssid[1];
 1132                         memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
 1133                         memcpy(ni->ni_essid, ssid + 2, ssid[1]);
 1134                 }
 1135                 IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
 1136                 ni->ni_rssi = rssi;
 1137                 ni->ni_rstamp = rstamp;
 1138                 memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
 1139                 ni->ni_intval = le16toh(*(u_int16_t *)bintval);
 1140                 ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo);
 1141                 /* XXX validate channel # */
 1142                 ni->ni_chan = &ic->ic_channels[chan];
 1143                 ni->ni_fhdwell = fhdwell;
 1144                 ni->ni_fhindex = fhindex;
 1145                 ni->ni_erp = erp;
 1146                 /* NB: must be after ni_chan is setup */
 1147                 ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
 1148                 /*
 1149                  * When scanning we record results (nodes) with a zero
 1150                  * refcnt.  Otherwise we want to hold the reference for
 1151                  * ibss neighbors so the nodes don't get released prematurely.
 1152                  * Anything else can be discarded (XXX and should be handled
 1153                  * above so we don't do so much work).
 1154                  */
 1155                 if (ic->ic_opmode == IEEE80211_M_IBSS || (is_new &&
 1156                     ISPROBE(subtype))) {
 1157                         /*
 1158                          * Fake an association so the driver can setup it's
 1159                          * private state.  The rate set has been setup above;
 1160                          * there is no handshake as in ap/station operation.
 1161                          */
 1162                         if (ic->ic_newassoc)
 1163                                 (*ic->ic_newassoc)(ic, ni, 1);
 1164                 }
 1165                 break;
 1166         }
 1167 
 1168         case IEEE80211_FC0_SUBTYPE_PROBE_REQ: {
 1169                 u_int8_t rate;
 1170 
 1171                 if (ic->ic_opmode == IEEE80211_M_STA)
 1172                         return;
 1173                 if (ic->ic_state != IEEE80211_S_RUN)
 1174                         return;
 1175 
 1176                 /*
 1177                  * prreq frame format
 1178                  *      [tlv] ssid
 1179                  *      [tlv] supported rates
 1180                  *      [tlv] extended supported rates
 1181                  */
 1182                 ssid = rates = xrates = NULL;
 1183                 while (frm < efrm) {
 1184                         switch (*frm) {
 1185                         case IEEE80211_ELEMID_SSID:
 1186                                 ssid = frm;
 1187                                 break;
 1188                         case IEEE80211_ELEMID_RATES:
 1189                                 rates = frm;
 1190                                 break;
 1191                         case IEEE80211_ELEMID_XRATES:
 1192                                 xrates = frm;
 1193                                 break;
 1194                         }
 1195                         frm += frm[1] + 2;
 1196                 }
 1197                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 1198                 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
 1199                 IEEE80211_VERIFY_SSID(ic->ic_bss, ssid, "probe");
 1200 
 1201                 if (ni == ic->ic_bss) {
 1202                         ni = ieee80211_dup_bss(ic, wh->i_addr2);
 1203                         if (ni == NULL)
 1204                                 return;
 1205                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 1206                                 ("%s: new probe req from %s\n",
 1207                                 __func__, ether_sprintf(wh->i_addr2)));
 1208                 }
 1209                 ni->ni_rssi = rssi;
 1210                 ni->ni_rstamp = rstamp;
 1211                 rate = ieee80211_setup_rates(ic, ni, rates, xrates,
 1212                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE
 1213                                 | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
 1214                 if (rate & IEEE80211_RATE_BASIC) {
 1215                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_XRATE,
 1216                                 ("%s: rate negotiation failed: %s\n",
 1217                                 __func__,ether_sprintf(wh->i_addr2)));
 1218                 } else {
 1219                         IEEE80211_SEND_MGMT(ic, ni,
 1220                                 IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
 1221                 }
 1222                 break;
 1223         }
 1224 
 1225         case IEEE80211_FC0_SUBTYPE_AUTH: {
 1226                 u_int16_t algo, seq, status;
 1227                 /*
 1228                  * auth frame format
 1229                  *      [2] algorithm
 1230                  *      [2] sequence
 1231                  *      [2] status
 1232                  *      [tlv*] challenge
 1233                  */
 1234                 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
 1235                 algo   = le16toh(*(u_int16_t *)frm);
 1236                 seq    = le16toh(*(u_int16_t *)(frm + 2));
 1237                 status = le16toh(*(u_int16_t *)(frm + 4));
 1238                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 1239                         ("%s: algorithm %d seq %d from %s\n",
 1240                         __func__, algo, seq, ether_sprintf(wh->i_addr2)));
 1241 
 1242                 if (algo == IEEE80211_AUTH_ALG_SHARED)
 1243                         ieee80211_auth_shared(ic, wh, frm + 6, efrm, ni, rssi,
 1244                             rstamp, seq, status);
 1245                 else if (algo == IEEE80211_AUTH_ALG_OPEN)
 1246                         ieee80211_auth_open(ic, wh, ni, rssi, rstamp, seq,
 1247                             status);
 1248                 else {
 1249                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1250                                 ("%s: unsupported auth algorithm %d from %s\n",
 1251                                 __func__, algo, ether_sprintf(wh->i_addr2)));
 1252                         ic->ic_stats.is_rx_auth_unsupported++;
 1253                         return;
 1254                 }
 1255                 break;
 1256         }
 1257 
 1258         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
 1259         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
 1260                 u_int16_t capinfo, bintval;
 1261 
 1262                 if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
 1263                     (ic->ic_state != IEEE80211_S_RUN))
 1264                         return;
 1265 
 1266                 if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
 1267                         reassoc = 1;
 1268                         resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
 1269                 } else {
 1270                         reassoc = 0;
 1271                         resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
 1272                 }
 1273                 /*
 1274                  * asreq frame format
 1275                  *      [2] capability information
 1276                  *      [2] listen interval
 1277                  *      [6*] current AP address (reassoc only)
 1278                  *      [tlv] ssid
 1279                  *      [tlv] supported rates
 1280                  *      [tlv] extended supported rates
 1281                  */
 1282                 IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
 1283                 if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
 1284                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1285                                 ("%s: ignore assoc request with bss %s not "
 1286                                 "our own\n",
 1287                                 __func__, ether_sprintf(wh->i_addr2)));
 1288                         ic->ic_stats.is_rx_assoc_bss++;
 1289                         return;
 1290                 }
 1291                 capinfo = le16toh(*(u_int16_t *)frm);   frm += 2;
 1292                 bintval = le16toh(*(u_int16_t *)frm);   frm += 2;
 1293                 if (reassoc)
 1294                         frm += 6;       /* ignore current AP info */
 1295                 ssid = rates = xrates = NULL;
 1296                 while (frm < efrm) {
 1297                         switch (*frm) {
 1298                         case IEEE80211_ELEMID_SSID:
 1299                                 ssid = frm;
 1300                                 break;
 1301                         case IEEE80211_ELEMID_RATES:
 1302                                 rates = frm;
 1303                                 break;
 1304                         case IEEE80211_ELEMID_XRATES:
 1305                                 xrates = frm;
 1306                                 break;
 1307                         }
 1308                         frm += frm[1] + 2;
 1309                 }
 1310                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 1311                 IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
 1312                 IEEE80211_VERIFY_SSID(ic->ic_bss, ssid,
 1313                         reassoc ? "reassoc" : "assoc");
 1314 
 1315                 if (ni->ni_state != IEEE80211_STA_AUTH &&
 1316                     ni->ni_state != IEEE80211_STA_ASSOC) {
 1317                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1318                             ("%s: deny %sassoc from %s, not authenticated\n",
 1319                             __func__, reassoc ? "re" : "",
 1320                             ether_sprintf(wh->i_addr2)));
 1321                         ni = ieee80211_dup_bss(ic, wh->i_addr2);
 1322                         if (ni != NULL) {
 1323                                 IEEE80211_SEND_MGMT(ic, ni,
 1324                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
 1325                                     IEEE80211_REASON_ASSOC_NOT_AUTHED);
 1326                         }
 1327                         ic->ic_stats.is_rx_assoc_notauth++;
 1328                         return;
 1329                 }
 1330                 /* discard challenge after association */
 1331                 if (ni->ni_challenge != NULL) {
 1332                         FREE(ni->ni_challenge, M_DEVBUF);
 1333                         ni->ni_challenge = NULL;
 1334                 }
 1335                 /* XXX per-node cipher suite */
 1336                 /* XXX some stations use the privacy bit for handling APs
 1337                        that suport both encrypted and unencrypted traffic */
 1338                 if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 ||
 1339                     (capinfo & IEEE80211_CAPINFO_PRIVACY) !=
 1340                     ((ic->ic_flags & IEEE80211_F_PRIVACY) ?
 1341                      IEEE80211_CAPINFO_PRIVACY : 0)) {
 1342                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1343                                 ("%s: capability mismatch %x for %s\n",
 1344                                 __func__, capinfo, ether_sprintf(wh->i_addr2)));
 1345                         IEEE80211_SEND_MGMT(ic, ni, resp,
 1346                                 IEEE80211_STATUS_CAPINFO);
 1347                         ieee80211_node_leave(ic, ni);
 1348                         ic->ic_stats.is_rx_assoc_capmismatch++;
 1349                         return;
 1350                 }
 1351                 ieee80211_setup_rates(ic, ni, rates, xrates,
 1352                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
 1353                                 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
 1354                 if (ni->ni_rates.rs_nrates == 0) {
 1355                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1356                                 ("%s: rate mismatch for %s\n",
 1357                                 __func__, ether_sprintf(wh->i_addr2)));
 1358                         /* XXX what rate will we send this at? */
 1359                         IEEE80211_SEND_MGMT(ic, ni, resp,
 1360                                 IEEE80211_STATUS_BASIC_RATE);
 1361                         ieee80211_node_leave(ic, ni);
 1362                         ic->ic_stats.is_rx_assoc_norate++;
 1363                         return;
 1364                 }
 1365                 ni->ni_rssi = rssi;
 1366                 ni->ni_rstamp = rstamp;
 1367                 ni->ni_intval = bintval;
 1368                 ni->ni_capinfo = capinfo;
 1369                 ni->ni_chan = ic->ic_bss->ni_chan;
 1370                 ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
 1371                 ni->ni_fhindex = ic->ic_bss->ni_fhindex;
 1372                 ieee80211_node_join(ic, ni, resp);
 1373                 break;
 1374         }
 1375 
 1376         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
 1377         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: {
 1378                 u_int16_t status;
 1379 
 1380                 if (ic->ic_opmode != IEEE80211_M_STA ||
 1381                     ic->ic_state != IEEE80211_S_ASSOC) {
 1382                         ic->ic_stats.is_rx_mgtdiscard++;
 1383                         return;
 1384                 }
 1385 
 1386                 /*
 1387                  * asresp frame format
 1388                  *      [2] capability information
 1389                  *      [2] status
 1390                  *      [2] association ID
 1391                  *      [tlv] supported rates
 1392                  *      [tlv] extended supported rates
 1393                  */
 1394                 IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
 1395                 ni = ic->ic_bss;
 1396                 ni->ni_capinfo = le16toh(*(u_int16_t *)frm);
 1397                 frm += 2;
 1398 
 1399                 status = le16toh(*(u_int16_t *)frm);
 1400                 frm += 2;
 1401                 if (status != 0) {
 1402                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 1403                                 ("%sassociation failed (reason %d) for %s\n",
 1404                                 ISREASSOC(subtype) ?  "re" : "",
 1405                                 status, ether_sprintf(wh->i_addr3)));
 1406                         if (ni != ic->ic_bss)
 1407                                 ni->ni_fails++;
 1408                         ic->ic_stats.is_rx_auth_fail++;
 1409                         return;
 1410                 }
 1411                 ni->ni_associd = le16toh(*(u_int16_t *)frm);
 1412                 frm += 2;
 1413 
 1414                 rates = xrates = NULL;
 1415                 while (frm < efrm) {
 1416                         switch (*frm) {
 1417                         case IEEE80211_ELEMID_RATES:
 1418                                 rates = frm;
 1419                                 break;
 1420                         case IEEE80211_ELEMID_XRATES:
 1421                                 xrates = frm;
 1422                                 break;
 1423                         }
 1424                         frm += frm[1] + 2;
 1425                 }
 1426 
 1427                 IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
 1428                 ieee80211_setup_rates(ic, ni, rates, xrates,
 1429                                 IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
 1430                                 IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
 1431                 if (ni->ni_rates.rs_nrates != 0)
 1432                         ieee80211_new_state(ic, IEEE80211_S_RUN,
 1433                                 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 1434                 break;
 1435         }
 1436 
 1437         case IEEE80211_FC0_SUBTYPE_DEAUTH: {
 1438                 u_int16_t reason;
 1439                 /*
 1440                  * deauth frame format
 1441                  *      [2] reason
 1442                  */
 1443                 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
 1444                 reason = le16toh(*(u_int16_t *)frm);
 1445                 ic->ic_stats.is_rx_deauth++;
 1446                 switch (ic->ic_opmode) {
 1447                 case IEEE80211_M_STA:
 1448                         ieee80211_new_state(ic, IEEE80211_S_AUTH,
 1449                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 1450                         break;
 1451                 case IEEE80211_M_HOSTAP:
 1452                         if (ni != ic->ic_bss) {
 1453                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 1454                                         ("station %s deauthenticated by "
 1455                                         "peer (reason %d)\n",
 1456                                         ether_sprintf(ni->ni_macaddr), reason));
 1457                                 ieee80211_node_leave(ic, ni);
 1458                         }
 1459                         break;
 1460                 default:
 1461                         break;
 1462                 }
 1463                 break;
 1464         }
 1465 
 1466         case IEEE80211_FC0_SUBTYPE_DISASSOC: {
 1467                 u_int16_t reason;
 1468                 /*
 1469                  * disassoc frame format
 1470                  *      [2] reason
 1471                  */
 1472                 IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
 1473                 reason = le16toh(*(u_int16_t *)frm);
 1474                 ic->ic_stats.is_rx_disassoc++;
 1475                 switch (ic->ic_opmode) {
 1476                 case IEEE80211_M_STA:
 1477                         ieee80211_new_state(ic, IEEE80211_S_ASSOC,
 1478                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 1479                         break;
 1480                 case IEEE80211_M_HOSTAP:
 1481                         if (ni != ic->ic_bss) {
 1482                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 1483                                         ("station %s disassociated by "
 1484                                         "peer (reason %d)\n",
 1485                                         ether_sprintf(ni->ni_macaddr), reason));
 1486                                 ieee80211_node_leave(ic, ni);
 1487                         }
 1488                         break;
 1489                 default:
 1490                         break;
 1491                 }
 1492                 break;
 1493         }
 1494         default:
 1495                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1496                         ("%s: mgmt frame with subtype 0x%x not handled\n",
 1497                         __func__, subtype));
 1498                 ic->ic_stats.is_rx_badsubtype++;
 1499                 break;
 1500         }
 1501 }
 1502 
 1503 static void
 1504 ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi,
 1505                       u_int32_t rstamp)
 1506 {
 1507         struct ifnet *ifp = &ic->ic_if;
 1508         struct ieee80211_frame *wh;
 1509         struct ieee80211_node *ni;
 1510         struct mbuf *m;
 1511         u_int16_t aid;
 1512 
 1513         if (ic->ic_set_tim == NULL)  /* No powersaving functionality */
 1514                 return;
 1515 
 1516         wh = mtod(m0, struct ieee80211_frame *);
 1517 
 1518         if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) {
 1519                 if (ifp->if_flags & IFF_DEBUG)
 1520                         printf("%s: station %s sent bogus power save poll\n",
 1521                                ifp->if_xname, ether_sprintf(wh->i_addr2));
 1522                 return;
 1523         }
 1524 
 1525         memcpy(&aid, wh->i_dur, sizeof(wh->i_dur));
 1526         if ((aid & 0xc000) != 0xc000) {
 1527                 if (ifp->if_flags & IFF_DEBUG)
 1528                         printf("%s: station %s sent bogus aid %x\n",
 1529                                ifp->if_xname, ether_sprintf(wh->i_addr2), aid);
 1530                 return;
 1531         }
 1532 
 1533         if (aid != ni->ni_associd) {
 1534                 if (ifp->if_flags & IFF_DEBUG)
 1535                         printf("%s: station %s aid %x doesn't match pspoll "
 1536                                "aid %x\n",
 1537                                ifp->if_xname, ether_sprintf(wh->i_addr2),
 1538                                ni->ni_associd, aid);
 1539                 return;
 1540         }
 1541 
 1542         /* Okay, take the first queued packet and put it out... */
 1543 
 1544         IF_DEQUEUE(&ni->ni_savedq, m);
 1545         if (m == NULL) {
 1546                 if (ifp->if_flags & IFF_DEBUG)
 1547                         printf("%s: station %s sent pspoll, "
 1548                                "but no packets are saved\n",
 1549                                ifp->if_xname, ether_sprintf(wh->i_addr2));
 1550                 return;
 1551         }
 1552         wh = mtod(m, struct ieee80211_frame *);
 1553 
 1554         /*
 1555          * If this is the last packet, turn off the TIM fields.
 1556          * If there are more packets, set the more packets bit.
 1557          */
 1558 
 1559         if (IF_IS_EMPTY(&ni->ni_savedq)) {
 1560                 if (ic->ic_set_tim)
 1561                         ic->ic_set_tim(ic, ni->ni_associd, 0);
 1562         } else {
 1563                 wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
 1564         }
 1565 
 1566         if (ifp->if_flags & IFF_DEBUG)
 1567                 printf("%s: enqueued power saving packet for station %s\n",
 1568                        ifp->if_xname, ether_sprintf(ni->ni_macaddr));
 1569 
 1570         IF_ENQUEUE(&ic->ic_pwrsaveq, m);
 1571         (*ifp->if_start)(ifp);
 1572 }
 1573 
 1574 static int
 1575 do_slow_print(struct ieee80211com *ic, int *did_print)
 1576 {
 1577         if ((ic->ic_if.if_flags & IFF_LINK0) == 0)
 1578                 return 0;
 1579         if (!*did_print && (ic->ic_if.if_flags & IFF_DEBUG) == 0 &&
 1580             !ratecheck(&ic->ic_last_merge_print, &ieee80211_merge_print_intvl))
 1581                 return 0;
 1582 
 1583         *did_print = 1;
 1584         return 1;
 1585 }
 1586 
 1587 /* ieee80211_ibss_merge helps merge 802.11 ad hoc networks.  The
 1588  * convention, set by the Wireless Ethernet Compatibility Alliance
 1589  * (WECA), is that an 802.11 station will change its BSSID to match
 1590  * the "oldest" 802.11 ad hoc network, on the same channel, that
 1591  * has the station's desired SSID.  The "oldest" 802.11 network
 1592  * sends beacons with the greatest TSF timestamp.
 1593  *
 1594  * Return ENETRESET if the BSSID changed, 0 otherwise.
 1595  *
 1596  * XXX Perhaps we should compensate for the time that elapses
 1597  * between the MAC receiving the beacon and the host processing it
 1598  * in ieee80211_ibss_merge.
 1599  */
 1600 int
 1601 ieee80211_ibss_merge(struct ieee80211com *ic, struct ieee80211_node *ni)
 1602 {
 1603         int did_print = 0;
 1604 
 1605         if (memcmp(ni->ni_bssid, ic->ic_bss->ni_bssid, IEEE80211_ADDR_LEN) == 0)
 1606                 return 0;
 1607 
 1608         if (ieee80211_match_bss(ic, ni) != 0)
 1609                 return 0;
 1610 
 1611         ic->ic_flags &= ~IEEE80211_F_SIBSS;
 1612 
 1613         /* negotiate rates with new IBSS */
 1614         ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE |
 1615             IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
 1616         if (ni->ni_rates.rs_nrates == 0) {
 1617                 if (do_slow_print(ic, &did_print)) {
 1618                         printf("%s: rates mismatch, BSSID %s\n",
 1619                             ic->ic_if.if_xname, ether_sprintf(ni->ni_bssid));
 1620                 }
 1621                 return 0;
 1622         }
 1623 
 1624         printf("%s: bss merge %s -> ", ic->ic_if.if_xname,
 1625             ether_sprintf(ic->ic_bss->ni_bssid));
 1626 
 1627         (*ic->ic_node_copy)(ic, ic->ic_bss, ni);
 1628         ieee80211_node_newstate(ic->ic_bss, IEEE80211_STA_BSS);
 1629 
 1630         printf("%s\n", ether_sprintf(ic->ic_bss->ni_bssid));
 1631         return ENETRESET;
 1632 }
 1633 #undef IEEE80211_VERIFY_LENGTH
 1634 #undef IEEE80211_VERIFY_ELEMENT

Cache object: c46bfdb8a05913be7d01684d052ebe25


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