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

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

    1 /*      $NetBSD: ieee80211_output.c,v 1.50 2011/02/21 23:50:08 jmcneill Exp $   */
    2 /*-
    3  * Copyright (c) 2001 Atsushi Onoe
    4  * Copyright (c) 2002-2005 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_output.c,v 1.34 2005/08/10 16:22:29 sam Exp $");
   37 #endif
   38 #ifdef __NetBSD__
   39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_output.c,v 1.50 2011/02/21 23:50:08 jmcneill Exp $");
   40 #endif
   41 
   42 #include "opt_inet.h"
   43 
   44 #ifdef __NetBSD__
   45 #endif /* __NetBSD__ */
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h> 
   49 #include <sys/mbuf.h>   
   50 #include <sys/kernel.h>
   51 #include <sys/endian.h>
   52 #include <sys/errno.h>
   53 #include <sys/proc.h>
   54 #include <sys/sysctl.h>
   55 
   56 #include <net/if.h>
   57 #include <net/if_llc.h>
   58 #include <net/if_media.h>
   59 #include <net/if_arp.h>
   60 #include <net/if_ether.h>
   61 #include <net/if_llc.h>
   62 #include <net/if_vlanvar.h>
   63 
   64 #include <net80211/ieee80211_netbsd.h>
   65 #include <net80211/ieee80211_var.h>
   66 
   67 #include <net/bpf.h>
   68 
   69 #ifdef INET
   70 #include <netinet/in.h>
   71 #include <netinet/in_systm.h>
   72 #include <netinet/in_var.h>
   73 #include <netinet/ip.h>
   74 #include <net/if_ether.h>
   75 #endif
   76 
   77 static int ieee80211_fragment(struct ieee80211com *, struct mbuf *,
   78         u_int hdrsize, u_int ciphdrsize, u_int mtu);
   79 
   80 #ifdef IEEE80211_DEBUG
   81 /*
   82  * Decide if an outbound 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_PROBE_RESP:
   92                 return (ic->ic_opmode == IEEE80211_M_IBSS);
   93         }
   94         return 1;
   95 }
   96 #endif
   97 
   98 /*
   99  * Set the direction field and address fields of an outgoing
  100  * non-QoS frame.  Note this should be called early on in
  101  * constructing a frame as it sets i_fc[1]; other bits can
  102  * then be or'd in.
  103  */
  104 static void
  105 ieee80211_send_setup(struct ieee80211com *ic,
  106         struct ieee80211_node *ni,
  107         struct ieee80211_frame *wh,
  108         int type,
  109         const u_int8_t sa[IEEE80211_ADDR_LEN],
  110         const u_int8_t da[IEEE80211_ADDR_LEN],
  111         const u_int8_t bssid[IEEE80211_ADDR_LEN])
  112 {
  113 #define WH4(wh) ((struct ieee80211_frame_addr4 *)wh)
  114 
  115         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | type;
  116         if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
  117                 switch (ic->ic_opmode) {
  118                 case IEEE80211_M_STA:
  119                         wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
  120                         IEEE80211_ADDR_COPY(wh->i_addr1, bssid);
  121                         IEEE80211_ADDR_COPY(wh->i_addr2, sa);
  122                         IEEE80211_ADDR_COPY(wh->i_addr3, da);
  123                         break;
  124                 case IEEE80211_M_IBSS:
  125                 case IEEE80211_M_AHDEMO:
  126                         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
  127                         IEEE80211_ADDR_COPY(wh->i_addr1, da);
  128                         IEEE80211_ADDR_COPY(wh->i_addr2, sa);
  129                         IEEE80211_ADDR_COPY(wh->i_addr3, bssid);
  130                         break;
  131                 case IEEE80211_M_HOSTAP:
  132                         wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
  133                         IEEE80211_ADDR_COPY(wh->i_addr1, da);
  134                         IEEE80211_ADDR_COPY(wh->i_addr2, bssid);
  135                         IEEE80211_ADDR_COPY(wh->i_addr3, sa);
  136                         break;
  137                 case IEEE80211_M_MONITOR:       /* NB: to quiet compiler */
  138                         break;
  139                 }
  140         } else {
  141                 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
  142                 IEEE80211_ADDR_COPY(wh->i_addr1, da);
  143                 IEEE80211_ADDR_COPY(wh->i_addr2, sa);
  144                 IEEE80211_ADDR_COPY(wh->i_addr3, bssid);
  145         }
  146         *(u_int16_t *)&wh->i_dur[0] = 0;
  147         /* NB: use non-QoS tid */
  148         *(u_int16_t *)&wh->i_seq[0] =
  149             htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
  150         ni->ni_txseqs[0]++;
  151 #undef WH4
  152 }
  153 
  154 /*
  155  * Send a management frame to the specified node.  The node pointer
  156  * must have a reference as the pointer will be passed to the driver
  157  * and potentially held for a long time.  If the frame is successfully
  158  * dispatched to the driver, then it is responsible for freeing the
  159  * reference (and potentially free'ing up any associated storage).
  160  */
  161 static int
  162 ieee80211_mgmt_output(struct ieee80211com *ic, struct ieee80211_node *ni,
  163     struct mbuf *m, int type, int timer)
  164 {
  165         struct ifnet *ifp = ic->ic_ifp;
  166         struct ieee80211_frame *wh;
  167 
  168         IASSERT(ni != NULL, ("null node"));
  169 
  170         /*
  171          * Yech, hack alert!  We want to pass the node down to the
  172          * driver's start routine.  If we don't do so then the start
  173          * routine must immediately look it up again and that can
  174          * cause a lock order reversal if, for example, this frame
  175          * is being sent because the station is being timedout and
  176          * the frame being sent is a DEAUTH message.  We could stick
  177          * this in an m_tag and tack that on to the mbuf.  However
  178          * that's rather expensive to do for every frame so instead
  179          * we stuff it in the rcvif field since outbound frames do
  180          * not (presently) use this.
  181          */
  182         M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
  183         if (m == NULL)
  184                 return ENOMEM;
  185 #ifdef __FreeBSD__
  186         KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null"));
  187 #endif
  188         m->m_pkthdr.rcvif = (void *)ni;
  189 
  190         wh = mtod(m, struct ieee80211_frame *);
  191         ieee80211_send_setup(ic, ni, wh, 
  192                 IEEE80211_FC0_TYPE_MGT | type,
  193                 ic->ic_myaddr, ni->ni_macaddr, ni->ni_bssid);
  194         if ((m->m_flags & M_LINK0) != 0 && ni->ni_challenge != NULL) {
  195                 m->m_flags &= ~M_LINK0;
  196                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
  197                         "[%s] encrypting frame (%s)\n",
  198                         ether_sprintf(wh->i_addr1), __func__);
  199                 wh->i_fc[1] |= IEEE80211_FC1_WEP;
  200         }
  201 #ifdef IEEE80211_DEBUG
  202         /* avoid printing too many frames */
  203         if ((ieee80211_msg_debug(ic) && doprint(ic, type)) ||
  204             ieee80211_msg_dumppkts(ic)) {
  205                 printf("[%s] send %s on channel %u\n",
  206                     ether_sprintf(wh->i_addr1),
  207                     ieee80211_mgt_subtype_name[
  208                         (type & IEEE80211_FC0_SUBTYPE_MASK) >>
  209                                 IEEE80211_FC0_SUBTYPE_SHIFT],
  210                     ieee80211_chan2ieee(ic, ic->ic_curchan));
  211         }
  212 #endif
  213         IEEE80211_NODE_STAT(ni, tx_mgmt);
  214         IF_ENQUEUE(&ic->ic_mgtq, m);
  215         if (timer) {
  216                 /*
  217                  * Set the mgt frame timeout.
  218                  */
  219                 ic->ic_mgt_timer = timer;
  220                 ifp->if_timer = 1;
  221         }
  222         (*ifp->if_start)(ifp);
  223         return 0;
  224 }
  225 
  226 /*
  227  * Send a null data frame to the specified node.
  228  *
  229  * NB: the caller is assumed to have setup a node reference
  230  *     for use; this is necessary to deal with a race condition
  231  *     when probing for inactive stations.
  232  */
  233 int
  234 ieee80211_send_nulldata(struct ieee80211_node *ni)
  235 {
  236         struct ieee80211com *ic = ni->ni_ic;
  237         struct ifnet *ifp = ic->ic_ifp;
  238         struct mbuf *m;
  239         struct ieee80211_frame *wh;
  240 
  241         MGETHDR(m, M_NOWAIT, MT_HEADER);
  242         if (m == NULL) {
  243                 /* XXX debug msg */
  244                 ic->ic_stats.is_tx_nobuf++;
  245                 ieee80211_unref_node(&ni);
  246                 return ENOMEM;
  247         }
  248         m->m_pkthdr.rcvif = (void *) ni;
  249 
  250         wh = mtod(m, struct ieee80211_frame *);
  251         ieee80211_send_setup(ic, ni, wh,
  252                 IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NODATA,
  253                 ic->ic_myaddr, ni->ni_macaddr, ni->ni_bssid);
  254         /* NB: power management bit is never sent by an AP */
  255         if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
  256             ic->ic_opmode != IEEE80211_M_HOSTAP)
  257                 wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT;
  258         m->m_len = m->m_pkthdr.len = sizeof(struct ieee80211_frame);
  259 
  260         IEEE80211_NODE_STAT(ni, tx_data);
  261 
  262         IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
  263             "[%s] send null data frame on channel %u, pwr mgt %s\n",
  264             ether_sprintf(ni->ni_macaddr),
  265             ieee80211_chan2ieee(ic, ic->ic_curchan),
  266             wh->i_fc[1] & IEEE80211_FC1_PWR_MGT ? "ena" : "dis");
  267 
  268         IF_ENQUEUE(&ic->ic_mgtq, m);            /* cheat */
  269         (*ifp->if_start)(ifp);
  270 
  271         return 0;
  272 }
  273 
  274 /* 
  275  * Assign priority to a frame based on any vlan tag assigned
  276  * to the station and/or any Diffserv setting in an IP header.
  277  * Finally, if an ACM policy is setup (in station mode) it's
  278  * applied.
  279  */
  280 int
  281 ieee80211_classify(struct ieee80211com *ic, struct mbuf *m, struct ieee80211_node *ni)
  282 {
  283         int v_wme_ac, d_wme_ac, ac;
  284 #ifdef INET
  285         struct ether_header *eh;
  286 #endif
  287 
  288         if ((ni->ni_flags & IEEE80211_NODE_QOS) == 0) {
  289                 ac = WME_AC_BE;
  290                 goto done;
  291         }
  292 
  293         /* 
  294          * If node has a vlan tag then all traffic
  295          * to it must have a matching tag.
  296          */
  297         v_wme_ac = 0;
  298         if (ni->ni_vlan != 0) {
  299                 /* XXX used to check ec_nvlans. */
  300                 struct m_tag *mtag = m_tag_find(m, PACKET_TAG_VLAN, NULL);
  301                 if (mtag == NULL) {
  302                         IEEE80211_NODE_STAT(ni, tx_novlantag);
  303                         return 1;
  304                 }
  305                 if (EVL_VLANOFTAG(VLAN_TAG_VALUE(mtag)) !=
  306                     EVL_VLANOFTAG(ni->ni_vlan)) {
  307                         IEEE80211_NODE_STAT(ni, tx_vlanmismatch);
  308                         return 1;
  309                 }
  310                 /* map vlan priority to AC */
  311                 switch (EVL_PRIOFTAG(ni->ni_vlan)) {
  312                 case 1:
  313                 case 2:
  314                         v_wme_ac = WME_AC_BK;
  315                         break;
  316                 case 0:
  317                 case 3:
  318                         v_wme_ac = WME_AC_BE;
  319                         break;
  320                 case 4:
  321                 case 5:
  322                         v_wme_ac = WME_AC_VI;
  323                         break;
  324                 case 6:
  325                 case 7:
  326                         v_wme_ac = WME_AC_VO;
  327                         break;
  328                 }
  329         }
  330 
  331 #ifdef INET
  332         eh = mtod(m, struct ether_header *);
  333         if (eh->ether_type == htons(ETHERTYPE_IP)) {
  334                 const struct ip *ip = (struct ip *)
  335                         (mtod(m, u_int8_t *) + sizeof (*eh));
  336                 /*
  337                  * IP frame, map the TOS field.
  338                  */
  339                 switch (ip->ip_tos) {
  340                 case 0x08:
  341                 case 0x20:
  342                         d_wme_ac = WME_AC_BK;   /* background */
  343                         break;
  344                 case 0x28:
  345                 case 0xa0:
  346                         d_wme_ac = WME_AC_VI;   /* video */
  347                         break;
  348                 case 0x30:                      /* voice */
  349                 case 0xe0:
  350                 case 0x88:                      /* XXX UPSD */
  351                 case 0xb8:
  352                         d_wme_ac = WME_AC_VO;
  353                         break;
  354                 default:
  355                         d_wme_ac = WME_AC_BE;
  356                         break;
  357                 }
  358         } else {
  359 #endif /* INET */
  360                 d_wme_ac = WME_AC_BE;
  361 #ifdef INET
  362         }
  363 #endif
  364         /*
  365          * Use highest priority AC.
  366          */
  367         if (v_wme_ac > d_wme_ac)
  368                 ac = v_wme_ac;
  369         else
  370                 ac = d_wme_ac;
  371 
  372         /*
  373          * Apply ACM policy.
  374          */
  375         if (ic->ic_opmode == IEEE80211_M_STA) {
  376                 static const int acmap[4] = {
  377                         WME_AC_BK,      /* WME_AC_BE */
  378                         WME_AC_BK,      /* WME_AC_BK */
  379                         WME_AC_BE,      /* WME_AC_VI */
  380                         WME_AC_VI,      /* WME_AC_VO */
  381                 };
  382                 while (ac != WME_AC_BK &&
  383                     ic->ic_wme.wme_wmeBssChanParams.cap_wmeParams[ac].wmep_acm)
  384                         ac = acmap[ac];
  385         }
  386 done:
  387         M_WME_SETAC(m, ac);
  388         return 0;
  389 }
  390 
  391 /*
  392  * Insure there is sufficient contiguous space to encapsulate the
  393  * 802.11 data frame.  If room isn't already there, arrange for it.
  394  * Drivers and cipher modules assume we have done the necessary work
  395  * and fail rudely if they don't find the space they need.
  396  */
  397 static struct mbuf *
  398 ieee80211_mbuf_adjust(struct ieee80211com *ic, int hdrsize,
  399         struct ieee80211_key *key, struct mbuf *m)
  400 {
  401 #define TO_BE_RECLAIMED (sizeof(struct ether_header) - sizeof(struct llc))
  402         int needed_space = hdrsize;
  403         int wlen = 0;
  404 
  405         if (key != NULL) {
  406                 /* XXX belongs in crypto code? */
  407                 needed_space += key->wk_cipher->ic_header;
  408                 /* XXX frags */
  409         }
  410         /*
  411          * We know we are called just before stripping an Ethernet
  412          * header and prepending an LLC header.  This means we know
  413          * there will be
  414          *      sizeof(struct ether_header) - sizeof(struct llc)
  415          * bytes recovered to which we need additional space for the
  416          * 802.11 header and any crypto header.
  417          */
  418         /* XXX check trailing space and copy instead? */
  419         if (M_LEADINGSPACE(m) < needed_space - TO_BE_RECLAIMED) {
  420                 struct mbuf *n = m_gethdr(M_NOWAIT, m->m_type);
  421                 if (n == NULL) {
  422                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_OUTPUT,
  423                             "%s: cannot expand storage\n", __func__);
  424                         ic->ic_stats.is_tx_nobuf++;
  425                         m_freem(m);
  426                         return NULL;
  427                 }
  428                 IASSERT(needed_space <= MHLEN,
  429                     ("not enough room, need %u got %zu\n", needed_space, MHLEN));
  430                 /*
  431                  * Setup new mbuf to have leading space to prepend the
  432                  * 802.11 header and any crypto header bits that are
  433                  * required (the latter are added when the driver calls
  434                  * back to ieee80211_crypto_encap to do crypto encapsulation).
  435                  */
  436                 /* NB: must be first 'cuz it clobbers m_data */
  437                 M_MOVE_PKTHDR(n, m);
  438                 n->m_len = 0;                   /* NB: m_gethdr does not set */
  439                 n->m_data += needed_space;
  440                 /*
  441                  * Pull up Ethernet header to create the expected layout.
  442                  * We could use m_pullup but that's overkill (i.e. we don't
  443                  * need the actual data) and it cannot fail so do it inline
  444                  * for speed.
  445                  */
  446                 /* NB: struct ether_header is known to be contiguous */
  447                 n->m_len += sizeof(struct ether_header);
  448                 m->m_len -= sizeof(struct ether_header);
  449                 m->m_data += sizeof(struct ether_header);
  450                 /*
  451                  * Replace the head of the chain.
  452                  */
  453                 n->m_next = m;
  454                 m = n;
  455         } else {
  456                 /* We will overwrite the ethernet header in the
  457                  * 802.11 encapsulation stage.  Make sure that it
  458                  * is writable.
  459                  */
  460                 wlen = sizeof(struct ether_header);
  461         }
  462 
  463         /*
  464          * If we're going to s/w encrypt the mbuf chain make sure it is
  465          * writable.
  466          */
  467         if (key != NULL && (key->wk_flags & IEEE80211_KEY_SWCRYPT) != 0)
  468                 wlen = M_COPYALL;
  469 
  470         if (wlen != 0 && m_makewritable(&m, 0, wlen, M_DONTWAIT) != 0) {
  471                 m_freem(m);
  472                 return NULL;
  473         }
  474         return m;
  475 #undef TO_BE_RECLAIMED
  476 }
  477 
  478 /*
  479  * Return the transmit key to use in sending a unicast frame.
  480  * If a unicast key is set we use that.  When no unicast key is set
  481  * we fall back to the default transmit key.
  482  */ 
  483 static __inline struct ieee80211_key *
  484 ieee80211_crypto_getucastkey(struct ieee80211com *ic, struct ieee80211_node *ni)
  485 {
  486         if (IEEE80211_KEY_UNDEFINED(ni->ni_ucastkey)) {
  487                 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE ||
  488                     IEEE80211_KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey]))
  489                         return NULL;
  490                 return &ic->ic_nw_keys[ic->ic_def_txkey];
  491         } else {
  492                 return &ni->ni_ucastkey;
  493         }
  494 }
  495 
  496 /*
  497  * Return the transmit key to use in sending a multicast frame.
  498  * Multicast traffic always uses the group key which is installed as
  499  * the default tx key.
  500  */ 
  501 static __inline struct ieee80211_key *
  502 ieee80211_crypto_getmcastkey(struct ieee80211com *ic,
  503     struct ieee80211_node *ni)
  504 {
  505         if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE ||
  506             IEEE80211_KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey]))
  507                 return NULL;
  508         return &ic->ic_nw_keys[ic->ic_def_txkey];
  509 }
  510 
  511 /*
  512  * Encapsulate an outbound data frame.  The mbuf chain is updated.
  513  * If an error is encountered NULL is returned.  The caller is required
  514  * to provide a node reference and pullup the ethernet header in the
  515  * first mbuf.
  516  */
  517 struct mbuf *
  518 ieee80211_encap(struct ieee80211com *ic, struct mbuf *m,
  519         struct ieee80211_node *ni)
  520 {
  521         struct ether_header eh;
  522         struct ieee80211_frame *wh;
  523         struct ieee80211_key *key;
  524         struct llc *llc;
  525         int hdrsize, datalen, addqos, txfrag;
  526 
  527         IASSERT(m->m_len >= sizeof(eh), ("no ethernet header!"));
  528         memcpy(&eh, mtod(m, void *), sizeof(struct ether_header));
  529 
  530         /*
  531          * Insure space for additional headers.  First identify
  532          * transmit key to use in calculating any buffer adjustments
  533          * required.  This is also used below to do privacy
  534          * encapsulation work.  Then calculate the 802.11 header
  535          * size and any padding required by the driver.
  536          *
  537          * Note key may be NULL if we fall back to the default
  538          * transmit key and that is not set.  In that case the
  539          * buffer may not be expanded as needed by the cipher
  540          * routines, but they will/should discard it.
  541          */
  542         if (ic->ic_flags & IEEE80211_F_PRIVACY) {
  543                 if (ic->ic_opmode == IEEE80211_M_STA ||
  544                     !IEEE80211_IS_MULTICAST(eh.ether_dhost))
  545                         key = ieee80211_crypto_getucastkey(ic, ni);
  546                 else
  547                         key = ieee80211_crypto_getmcastkey(ic, ni);
  548                 if (key == NULL && eh.ether_type != htons(ETHERTYPE_PAE)) {
  549                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
  550                             "[%s] no default transmit key (%s) deftxkey %u\n",
  551                             ether_sprintf(eh.ether_dhost), __func__,
  552                             ic->ic_def_txkey);
  553                         ic->ic_stats.is_tx_nodefkey++;
  554                 }
  555         } else
  556                 key = NULL;
  557         /* XXX 4-address format */
  558         /*
  559          * XXX Some ap's don't handle QoS-encapsulated EAPOL
  560          * frames so suppress use.  This may be an issue if other
  561          * ap's require all data frames to be QoS-encapsulated
  562          * once negotiated in which case we'll need to make this
  563          * configurable.
  564          */
  565         addqos = (ni->ni_flags & IEEE80211_NODE_QOS) &&
  566                  eh.ether_type != htons(ETHERTYPE_PAE);
  567         if (addqos)
  568                 hdrsize = sizeof(struct ieee80211_qosframe);
  569         else
  570                 hdrsize = sizeof(struct ieee80211_frame);
  571         if (ic->ic_flags & IEEE80211_F_DATAPAD)
  572                 hdrsize = roundup(hdrsize, sizeof(u_int32_t));
  573         m = ieee80211_mbuf_adjust(ic, hdrsize, key, m);
  574         if (m == NULL) {
  575                 /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
  576                 goto bad;
  577         }
  578 
  579         /* NB: this could be optimized because of ieee80211_mbuf_adjust */
  580         m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
  581         llc = mtod(m, struct llc *);
  582         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
  583         llc->llc_control = LLC_UI;
  584         llc->llc_snap.org_code[0] = 0;
  585         llc->llc_snap.org_code[1] = 0;
  586         llc->llc_snap.org_code[2] = 0;
  587         llc->llc_snap.ether_type = eh.ether_type;
  588         datalen = m->m_pkthdr.len;              /* NB: w/o 802.11 header */
  589 
  590         M_PREPEND(m, hdrsize, M_DONTWAIT);
  591         if (m == NULL) {
  592                 ic->ic_stats.is_tx_nobuf++;
  593                 goto bad;
  594         }
  595         wh = mtod(m, struct ieee80211_frame *);
  596         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
  597         *(u_int16_t *)wh->i_dur = 0;
  598         switch (ic->ic_opmode) {
  599         case IEEE80211_M_STA:
  600                 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
  601                 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
  602                 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
  603                 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
  604                 break;
  605         case IEEE80211_M_IBSS:
  606         case IEEE80211_M_AHDEMO:
  607                 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
  608                 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
  609                 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
  610                 /*
  611                  * NB: always use the bssid from ic_bss as the
  612                  *     neighbor's may be stale after an ibss merge
  613                  */
  614                 IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid);
  615                 break;
  616         case IEEE80211_M_HOSTAP:
  617 #ifndef IEEE80211_NO_HOSTAP
  618                 wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
  619                 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
  620                 IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
  621                 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
  622 #endif /* !IEEE80211_NO_HOSTAP */
  623                 break;
  624         case IEEE80211_M_MONITOR:
  625                 goto bad;
  626         }
  627         if (m->m_flags & M_MORE_DATA)
  628                 wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
  629         if (addqos) {
  630                 struct ieee80211_qosframe *qwh =
  631                         (struct ieee80211_qosframe *) wh;
  632                 int ac, tid;
  633 
  634                 ac = M_WME_GETAC(m);
  635                 /* map from access class/queue to 11e header priorty value */
  636                 tid = WME_AC_TO_TID(ac);
  637                 qwh->i_qos[0] = tid & IEEE80211_QOS_TID;
  638                 if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[ac].wmep_noackPolicy)
  639                         qwh->i_qos[0] |= 1 << IEEE80211_QOS_ACKPOLICY_S;
  640                 qwh->i_qos[1] = 0;
  641                 qwh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;
  642 
  643                 *(u_int16_t *)wh->i_seq =
  644                     htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
  645                 ni->ni_txseqs[tid]++;
  646         } else {
  647                 *(u_int16_t *)wh->i_seq =
  648                     htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
  649                 ni->ni_txseqs[0]++;
  650         }
  651         /* check if xmit fragmentation is required */
  652         txfrag = (m->m_pkthdr.len > ic->ic_fragthreshold &&
  653             !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
  654             (m->m_flags & M_FF) == 0);          /* NB: don't fragment ff's */
  655         if (key != NULL) {
  656                 /*
  657                  * IEEE 802.1X: send EAPOL frames always in the clear.
  658                  * WPA/WPA2: encrypt EAPOL keys when pairwise keys are set.
  659                  */
  660                 if (eh.ether_type != htons(ETHERTYPE_PAE) ||
  661                     ((ic->ic_flags & IEEE80211_F_WPA) &&
  662                      (ic->ic_opmode == IEEE80211_M_STA ?
  663                       !IEEE80211_KEY_UNDEFINED(*key) :
  664                       !IEEE80211_KEY_UNDEFINED(ni->ni_ucastkey)))) {
  665                         wh->i_fc[1] |= IEEE80211_FC1_WEP;
  666                         if (!ieee80211_crypto_enmic(ic, key, m, txfrag)) {
  667                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_OUTPUT,
  668                                     "[%s] enmic failed, discard frame\n",
  669                                     ether_sprintf(eh.ether_dhost));
  670                                 ic->ic_stats.is_crypto_enmicfail++;
  671                                 goto bad;
  672                         }
  673                 }
  674         }
  675         if (txfrag && !ieee80211_fragment(ic, m, hdrsize,
  676             key != NULL ? key->wk_cipher->ic_header : 0, ic->ic_fragthreshold))
  677                 goto bad;
  678 
  679         IEEE80211_NODE_STAT(ni, tx_data);
  680         IEEE80211_NODE_STAT_ADD(ni, tx_bytes, datalen);
  681 
  682         return m;
  683 bad:
  684         if (m != NULL)
  685                 m_freem(m);
  686         return NULL;
  687 }
  688 
  689 /*
  690  * Arguments in:
  691  *
  692  * paylen:  payload length (no FCS, no WEP header)
  693  *
  694  * hdrlen:  header length
  695  *
  696  * rate:    MSDU speed, units 500kb/s
  697  *
  698  * flags:   IEEE80211_F_SHPREAMBLE (use short preamble),
  699  *          IEEE80211_F_SHSLOT (use short slot length)
  700  *
  701  * Arguments out:
  702  *
  703  * d:       802.11 Duration field for RTS,
  704  *          802.11 Duration field for data frame,
  705  *          PLCP Length for data frame,
  706  *          residual octets at end of data slot
  707  */
  708 static int
  709 ieee80211_compute_duration1(int len, int use_ack, uint32_t icflags, int rate,
  710     struct ieee80211_duration *d)
  711 {
  712         int pre, ctsrate;
  713         int ack, bitlen, data_dur, remainder;
  714 
  715         /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
  716          * DATA reserves medium for SIFS | ACK,
  717          *
  718          * (XXX or SIFS | ACK | SIFS | DATA | SIFS | ACK, if more fragments)
  719          *
  720          * XXXMYC: no ACK on multicast/broadcast or control packets
  721          */
  722 
  723         bitlen = len * 8;
  724 
  725         pre = IEEE80211_DUR_DS_SIFS;
  726         if ((icflags & IEEE80211_F_SHPREAMBLE) != 0)
  727                 pre += IEEE80211_DUR_DS_SHORT_PREAMBLE + IEEE80211_DUR_DS_FAST_PLCPHDR;
  728         else
  729                 pre += IEEE80211_DUR_DS_LONG_PREAMBLE + IEEE80211_DUR_DS_SLOW_PLCPHDR;
  730 
  731         d->d_residue = 0;
  732         data_dur = (bitlen * 2) / rate;
  733         remainder = (bitlen * 2) % rate;
  734         if (remainder != 0) {
  735                 d->d_residue = (rate - remainder) / 16;
  736                 data_dur++;
  737         }
  738 
  739         switch (rate) {
  740         case 2:         /* 1 Mb/s */
  741         case 4:         /* 2 Mb/s */
  742                 /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
  743                 ctsrate = 2;
  744                 break;
  745         case 11:        /* 5.5 Mb/s */
  746         case 22:        /* 11  Mb/s */
  747         case 44:        /* 22  Mb/s */
  748                 /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
  749                 ctsrate = 4;
  750                 break;
  751         default:
  752                 /* TBD */
  753                 return -1;
  754         }
  755 
  756         d->d_plcp_len = data_dur;
  757 
  758         ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
  759 
  760         d->d_rts_dur =
  761             pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate +
  762             pre + data_dur +
  763             ack;
  764 
  765         d->d_data_dur = ack;
  766 
  767         return 0;
  768 }
  769 
  770 /*
  771  * Arguments in:
  772  *
  773  * wh:      802.11 header
  774  *
  775  * paylen:  payload length (no FCS, no WEP header)
  776  *
  777  * rate:    MSDU speed, units 500kb/s
  778  *
  779  * fraglen: fragment length, set to maximum (or higher) for no
  780  *          fragmentation
  781  *
  782  * flags:   IEEE80211_F_PRIVACY (hardware adds WEP),
  783  *          IEEE80211_F_SHPREAMBLE (use short preamble),
  784  *          IEEE80211_F_SHSLOT (use short slot length)
  785  *
  786  * Arguments out:
  787  *
  788  * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
  789  *     of first/only fragment
  790  *
  791  * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
  792  *     of last fragment
  793  *
  794  * ieee80211_compute_duration assumes crypto-encapsulation, if any,
  795  * has already taken place.
  796  */
  797 int
  798 ieee80211_compute_duration(const struct ieee80211_frame_min *wh,
  799     const struct ieee80211_key *wk, int len,
  800     uint32_t icflags, int fraglen, int rate, struct ieee80211_duration *d0,
  801     struct ieee80211_duration *dn, int *npktp, int debug)
  802 {
  803         int ack, rc;
  804         int cryptolen,  /* crypto overhead: header+trailer */
  805             firstlen,   /* first fragment's payload + overhead length */
  806             hdrlen,     /* header length w/o driver padding */
  807             lastlen,    /* last fragment's payload length w/ overhead */
  808             lastlen0,   /* last fragment's payload length w/o overhead */
  809             npkt,       /* number of fragments */
  810             overlen,    /* non-802.11 header overhead per fragment */
  811             paylen;     /* payload length w/o overhead */
  812 
  813         hdrlen = ieee80211_anyhdrsize((const void *)wh);
  814 
  815         /* Account for padding required by the driver. */
  816         if (icflags & IEEE80211_F_DATAPAD)
  817                 paylen = len - roundup(hdrlen, sizeof(u_int32_t));
  818         else
  819                 paylen = len - hdrlen;
  820 
  821         overlen = IEEE80211_CRC_LEN;
  822 
  823         if (wk != NULL) {
  824                 cryptolen = wk->wk_cipher->ic_header +
  825                             wk->wk_cipher->ic_trailer;
  826                 paylen -= cryptolen;
  827                 overlen += cryptolen;
  828         }
  829 
  830         npkt = paylen / fraglen;
  831         lastlen0 = paylen % fraglen;
  832 
  833         if (npkt == 0)                  /* no fragments */
  834                 lastlen = paylen + overlen;
  835         else if (lastlen0 != 0) {       /* a short "tail" fragment */
  836                 lastlen = lastlen0 + overlen;
  837                 npkt++;
  838         } else                          /* full-length "tail" fragment */
  839                 lastlen = fraglen + overlen;
  840 
  841         if (npktp != NULL)
  842                 *npktp = npkt;
  843 
  844         if (npkt > 1)
  845                 firstlen = fraglen + overlen;
  846         else
  847                 firstlen = paylen + overlen;
  848 
  849         if (debug) {
  850                 printf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d "
  851                     "fraglen %d overlen %d len %d rate %d icflags %08x\n",
  852                     __func__, npkt, firstlen, lastlen0, lastlen, fraglen,
  853                     overlen, len, rate, icflags);
  854         }
  855 
  856         ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
  857             (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL;
  858 
  859         rc = ieee80211_compute_duration1(firstlen + hdrlen,
  860             ack, icflags, rate, d0);
  861         if (rc == -1)
  862                 return rc;
  863 
  864         if (npkt <= 1) {
  865                 *dn = *d0;
  866                 return 0;
  867         }
  868         return ieee80211_compute_duration1(lastlen + hdrlen, ack, icflags, rate,
  869             dn);
  870 }
  871 
  872 /*
  873  * Fragment the frame according to the specified mtu.
  874  * The size of the 802.11 header (w/o padding) is provided
  875  * so we don't need to recalculate it.  We create a new
  876  * mbuf for each fragment and chain it through m_nextpkt;
  877  * we might be able to optimize this by reusing the original
  878  * packet's mbufs but that is significantly more complicated.
  879  */
  880 static int
  881 ieee80211_fragment(struct ieee80211com *ic, struct mbuf *m0,
  882         u_int hdrsize, u_int ciphdrsize, u_int mtu)
  883 {
  884         struct ieee80211_frame *wh, *whf;
  885         struct mbuf *m, *prev, *next;
  886         u_int totalhdrsize, fragno, fragsize, off, remainder, payload;
  887 
  888         IASSERT(m0->m_nextpkt == NULL, ("mbuf already chained?"));
  889         IASSERT(m0->m_pkthdr.len > mtu,
  890                 ("pktlen %u mtu %u", m0->m_pkthdr.len, mtu));
  891 
  892         wh = mtod(m0, struct ieee80211_frame *);
  893         /* NB: mark the first frag; it will be propagated below */
  894         wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
  895         totalhdrsize = hdrsize + ciphdrsize;
  896         fragno = 1;
  897         off = mtu - ciphdrsize;
  898         remainder = m0->m_pkthdr.len - off;
  899         prev = m0;
  900         do {
  901                 fragsize = totalhdrsize + remainder;
  902                 if (fragsize > mtu)
  903                         fragsize = mtu;
  904                 IASSERT(fragsize < MCLBYTES,
  905                         ("fragment size %u too big!", fragsize));
  906                 if (fragsize > MHLEN)
  907                         m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
  908                 else
  909                         m = m_gethdr(M_DONTWAIT, MT_DATA);
  910                 if (m == NULL)
  911                         goto bad;
  912                 /* leave room to prepend any cipher header */
  913                 m_align(m, fragsize - ciphdrsize);
  914 
  915                 /*
  916                  * Form the header in the fragment.  Note that since
  917                  * we mark the first fragment with the MORE_FRAG bit
  918                  * it automatically is propagated to each fragment; we
  919                  * need only clear it on the last fragment (done below).
  920                  */
  921                 whf = mtod(m, struct ieee80211_frame *);
  922                 memcpy(whf, wh, hdrsize);
  923                 *(u_int16_t *)&whf->i_seq[0] |= htole16(
  924                         (fragno & IEEE80211_SEQ_FRAG_MASK) <<
  925                                 IEEE80211_SEQ_FRAG_SHIFT);
  926                 fragno++;
  927 
  928                 payload = fragsize - totalhdrsize;
  929                 /* NB: destination is known to be contiguous */
  930                 m_copydata(m0, off, payload, mtod(m, u_int8_t *) + hdrsize);
  931                 m->m_len = hdrsize + payload;
  932                 m->m_pkthdr.len = hdrsize + payload;
  933                 m->m_flags |= M_FRAG;
  934 
  935                 /* chain up the fragment */
  936                 prev->m_nextpkt = m;
  937                 prev = m;
  938 
  939                 /* deduct fragment just formed */
  940                 remainder -= payload;
  941                 off += payload;
  942         } while (remainder != 0);
  943         whf->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;
  944 
  945         /* strip first mbuf now that everything has been copied */
  946         m_adj(m0, -(m0->m_pkthdr.len - (mtu - ciphdrsize)));
  947         m0->m_flags |= M_FIRSTFRAG | M_FRAG;
  948 
  949         ic->ic_stats.is_tx_fragframes++;
  950         ic->ic_stats.is_tx_frags += fragno-1;
  951 
  952         return 1;
  953 bad:
  954         /* reclaim fragments but leave original frame for caller to free */
  955         for (m = m0->m_nextpkt; m != NULL; m = next) {
  956                 next = m->m_nextpkt;
  957                 m->m_nextpkt = NULL;            /* XXX paranoid */
  958                 m_freem(m);
  959         }
  960         m0->m_nextpkt = NULL;
  961         return 0;
  962 }
  963 
  964 /*
  965  * Add a supported rates element id to a frame.
  966  */
  967 static u_int8_t *
  968 ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs)
  969 {
  970         int nrates;
  971 
  972         *frm++ = IEEE80211_ELEMID_RATES;
  973         nrates = rs->rs_nrates;
  974         if (nrates > IEEE80211_RATE_SIZE)
  975                 nrates = IEEE80211_RATE_SIZE;
  976         *frm++ = nrates;
  977         memcpy(frm, rs->rs_rates, nrates);
  978         return frm + nrates;
  979 }
  980 
  981 /*
  982  * Add an extended supported rates element id to a frame.
  983  */
  984 static u_int8_t *
  985 ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs)
  986 {
  987         /*
  988          * Add an extended supported rates element if operating in 11g mode.
  989          */
  990         if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
  991                 int nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
  992                 *frm++ = IEEE80211_ELEMID_XRATES;
  993                 *frm++ = nrates;
  994                 memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
  995                 frm += nrates;
  996         }
  997         return frm;
  998 }
  999 
 1000 /* 
 1001  * Add an ssid elemet to a frame.
 1002  */
 1003 static u_int8_t *
 1004 ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
 1005 {
 1006         *frm++ = IEEE80211_ELEMID_SSID;
 1007         *frm++ = len;
 1008         memcpy(frm, ssid, len);
 1009         return frm + len;
 1010 }
 1011 
 1012 /*
 1013  * Add an erp element to a frame.
 1014  */
 1015 static u_int8_t *
 1016 ieee80211_add_erp(u_int8_t *frm, struct ieee80211com *ic)
 1017 {
 1018         u_int8_t erp;
 1019 
 1020         *frm++ = IEEE80211_ELEMID_ERP;
 1021         *frm++ = 1;
 1022         erp = 0;
 1023         if (ic->ic_nonerpsta != 0)
 1024                 erp |= IEEE80211_ERP_NON_ERP_PRESENT;
 1025         if (ic->ic_flags & IEEE80211_F_USEPROT)
 1026                 erp |= IEEE80211_ERP_USE_PROTECTION;
 1027         if (ic->ic_flags & IEEE80211_F_USEBARKER)
 1028                 erp |= IEEE80211_ERP_LONG_PREAMBLE;
 1029         *frm++ = erp;
 1030         return frm;
 1031 }
 1032 
 1033 static u_int8_t *
 1034 ieee80211_setup_wpa_ie(struct ieee80211com *ic, u_int8_t *ie)
 1035 {
 1036 #define WPA_OUI_BYTES           0x00, 0x50, 0xf2
 1037 #define ADDSHORT(frm, v) do {                   \
 1038         frm[0] = (v) & 0xff;                    \
 1039         frm[1] = (v) >> 8;                      \
 1040         frm += 2;                               \
 1041 } while (0)
 1042 #define ADDSELECTOR(frm, sel) do {              \
 1043         memcpy(frm, sel, 4);                    \
 1044         frm += 4;                               \
 1045 } while (0)
 1046         static const u_int8_t oui[4] = { WPA_OUI_BYTES, WPA_OUI_TYPE };
 1047         static const u_int8_t cipher_suite[][4] = {
 1048                 { WPA_OUI_BYTES, WPA_CSE_WEP40 },       /* NB: 40-bit */
 1049                 { WPA_OUI_BYTES, WPA_CSE_TKIP },
 1050                 { 0x00, 0x00, 0x00, 0x00 },             /* XXX WRAP */
 1051                 { WPA_OUI_BYTES, WPA_CSE_CCMP },
 1052                 { 0x00, 0x00, 0x00, 0x00 },             /* XXX CKIP */
 1053                 { WPA_OUI_BYTES, WPA_CSE_NULL },
 1054         };
 1055         static const u_int8_t wep104_suite[4] =
 1056                 { WPA_OUI_BYTES, WPA_CSE_WEP104 };
 1057         static const u_int8_t key_mgt_unspec[4] =
 1058                 { WPA_OUI_BYTES, WPA_ASE_8021X_UNSPEC };
 1059         static const u_int8_t key_mgt_psk[4] =
 1060                 { WPA_OUI_BYTES, WPA_ASE_8021X_PSK };
 1061         const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
 1062         u_int8_t *frm = ie;
 1063         u_int8_t *selcnt;
 1064 
 1065         *frm++ = IEEE80211_ELEMID_VENDOR;
 1066         *frm++ = 0;                             /* length filled in below */
 1067         memcpy(frm, oui, sizeof(oui));          /* WPA OUI */
 1068         frm += sizeof(oui);
 1069         ADDSHORT(frm, WPA_VERSION);
 1070 
 1071         /* XXX filter out CKIP */
 1072 
 1073         /* multicast cipher */
 1074         if (rsn->rsn_mcastcipher == IEEE80211_CIPHER_WEP &&
 1075             rsn->rsn_mcastkeylen >= 13)
 1076                 ADDSELECTOR(frm, wep104_suite);
 1077         else
 1078                 ADDSELECTOR(frm, cipher_suite[rsn->rsn_mcastcipher]);
 1079 
 1080         /* unicast cipher list */
 1081         selcnt = frm;
 1082         ADDSHORT(frm, 0);                       /* selector count */
 1083         if (rsn->rsn_ucastcipherset & (1<<IEEE80211_CIPHER_AES_CCM)) {
 1084                 selcnt[0]++;
 1085                 ADDSELECTOR(frm, cipher_suite[IEEE80211_CIPHER_AES_CCM]);
 1086         }
 1087         if (rsn->rsn_ucastcipherset & (1<<IEEE80211_CIPHER_TKIP)) {
 1088                 selcnt[0]++;
 1089                 ADDSELECTOR(frm, cipher_suite[IEEE80211_CIPHER_TKIP]);
 1090         }
 1091 
 1092         /* authenticator selector list */
 1093         selcnt = frm;
 1094         ADDSHORT(frm, 0);                       /* selector count */
 1095         if (rsn->rsn_keymgmtset & WPA_ASE_8021X_UNSPEC) {
 1096                 selcnt[0]++;
 1097                 ADDSELECTOR(frm, key_mgt_unspec);
 1098         }
 1099         if (rsn->rsn_keymgmtset & WPA_ASE_8021X_PSK) {
 1100                 selcnt[0]++;
 1101                 ADDSELECTOR(frm, key_mgt_psk);
 1102         }
 1103 
 1104         /* optional capabilities */
 1105         if (rsn->rsn_caps != 0 && rsn->rsn_caps != RSN_CAP_PREAUTH)
 1106                 ADDSHORT(frm, rsn->rsn_caps);
 1107 
 1108         /* calculate element length */
 1109         ie[1] = frm - ie - 2;
 1110         IASSERT(ie[1]+2 <= sizeof(struct ieee80211_ie_wpa),
 1111                 ("WPA IE too big, %u > %zu",
 1112                 ie[1]+2, sizeof(struct ieee80211_ie_wpa)));
 1113         return frm;
 1114 #undef ADDSHORT
 1115 #undef ADDSELECTOR
 1116 #undef WPA_OUI_BYTES
 1117 }
 1118 
 1119 static u_int8_t *
 1120 ieee80211_setup_rsn_ie(struct ieee80211com *ic, u_int8_t *ie)
 1121 {
 1122 #define RSN_OUI_BYTES           0x00, 0x0f, 0xac
 1123 #define ADDSHORT(frm, v) do {                   \
 1124         frm[0] = (v) & 0xff;                    \
 1125         frm[1] = (v) >> 8;                      \
 1126         frm += 2;                               \
 1127 } while (0)
 1128 #define ADDSELECTOR(frm, sel) do {              \
 1129         memcpy(frm, sel, 4);                    \
 1130         frm += 4;                               \
 1131 } while (0)
 1132         static const u_int8_t cipher_suite[][4] = {
 1133                 { RSN_OUI_BYTES, RSN_CSE_WEP40 },       /* NB: 40-bit */
 1134                 { RSN_OUI_BYTES, RSN_CSE_TKIP },
 1135                 { RSN_OUI_BYTES, RSN_CSE_WRAP },
 1136                 { RSN_OUI_BYTES, RSN_CSE_CCMP },
 1137                 { 0x00, 0x00, 0x00, 0x00 },             /* XXX CKIP */
 1138                 { RSN_OUI_BYTES, RSN_CSE_NULL },
 1139         };
 1140         static const u_int8_t wep104_suite[4] =
 1141                 { RSN_OUI_BYTES, RSN_CSE_WEP104 };
 1142         static const u_int8_t key_mgt_unspec[4] =
 1143                 { RSN_OUI_BYTES, RSN_ASE_8021X_UNSPEC };
 1144         static const u_int8_t key_mgt_psk[4] =
 1145                 { RSN_OUI_BYTES, RSN_ASE_8021X_PSK };
 1146         const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
 1147         u_int8_t *frm = ie;
 1148         u_int8_t *selcnt;
 1149 
 1150         *frm++ = IEEE80211_ELEMID_RSN;
 1151         *frm++ = 0;                             /* length filled in below */
 1152         ADDSHORT(frm, RSN_VERSION);
 1153 
 1154         /* XXX filter out CKIP */
 1155 
 1156         /* multicast cipher */
 1157         if (rsn->rsn_mcastcipher == IEEE80211_CIPHER_WEP &&
 1158             rsn->rsn_mcastkeylen >= 13)
 1159                 ADDSELECTOR(frm, wep104_suite);
 1160         else
 1161                 ADDSELECTOR(frm, cipher_suite[rsn->rsn_mcastcipher]);
 1162 
 1163         /* unicast cipher list */
 1164         selcnt = frm;
 1165         ADDSHORT(frm, 0);                       /* selector count */
 1166         if (rsn->rsn_ucastcipherset & (1<<IEEE80211_CIPHER_AES_CCM)) {
 1167                 selcnt[0]++;
 1168                 ADDSELECTOR(frm, cipher_suite[IEEE80211_CIPHER_AES_CCM]);
 1169         }
 1170         if (rsn->rsn_ucastcipherset & (1<<IEEE80211_CIPHER_TKIP)) {
 1171                 selcnt[0]++;
 1172                 ADDSELECTOR(frm, cipher_suite[IEEE80211_CIPHER_TKIP]);
 1173         }
 1174 
 1175         /* authenticator selector list */
 1176         selcnt = frm;
 1177         ADDSHORT(frm, 0);                       /* selector count */
 1178         if (rsn->rsn_keymgmtset & WPA_ASE_8021X_UNSPEC) {
 1179                 selcnt[0]++;
 1180                 ADDSELECTOR(frm, key_mgt_unspec);
 1181         }
 1182         if (rsn->rsn_keymgmtset & WPA_ASE_8021X_PSK) {
 1183                 selcnt[0]++;
 1184                 ADDSELECTOR(frm, key_mgt_psk);
 1185         }
 1186 
 1187         /* optional capabilities */
 1188         ADDSHORT(frm, rsn->rsn_caps);
 1189         /* XXX PMKID */
 1190 
 1191         /* calculate element length */
 1192         ie[1] = frm - ie - 2;
 1193         IASSERT(ie[1]+2 <= sizeof(struct ieee80211_ie_wpa),
 1194                 ("RSN IE too big, %u > %zu",
 1195                 ie[1]+2, sizeof(struct ieee80211_ie_wpa)));
 1196         return frm;
 1197 #undef ADDSELECTOR
 1198 #undef ADDSHORT
 1199 #undef RSN_OUI_BYTES
 1200 }
 1201 
 1202 /*
 1203  * Add a WPA/RSN element to a frame.
 1204  */
 1205 static u_int8_t *
 1206 ieee80211_add_wpa(u_int8_t *frm, struct ieee80211com *ic)
 1207 {
 1208 
 1209         IASSERT(ic->ic_flags & IEEE80211_F_WPA, ("no WPA/RSN!"));
 1210         if (ic->ic_flags & IEEE80211_F_WPA2)
 1211                 frm = ieee80211_setup_rsn_ie(ic, frm);
 1212         if (ic->ic_flags & IEEE80211_F_WPA1)
 1213                 frm = ieee80211_setup_wpa_ie(ic, frm);
 1214         return frm;
 1215 }
 1216 
 1217 #define WME_OUI_BYTES           0x00, 0x50, 0xf2
 1218 /*
 1219  * Add a WME information element to a frame.
 1220  */
 1221 static u_int8_t *
 1222 ieee80211_add_wme_info(u_int8_t *frm, struct ieee80211_wme_state *wme)
 1223 {
 1224         static const struct ieee80211_wme_info info = {
 1225                 .wme_id         = IEEE80211_ELEMID_VENDOR,
 1226                 .wme_len        = sizeof(struct ieee80211_wme_info) - 2,
 1227                 .wme_oui        = { WME_OUI_BYTES },
 1228                 .wme_type       = WME_OUI_TYPE,
 1229                 .wme_subtype    = WME_INFO_OUI_SUBTYPE,
 1230                 .wme_version    = WME_VERSION,
 1231                 .wme_info       = 0,
 1232         };
 1233         memcpy(frm, &info, sizeof(info));
 1234         return frm + sizeof(info); 
 1235 }
 1236 
 1237 /*
 1238  * Add a WME parameters element to a frame.
 1239  */
 1240 static u_int8_t *
 1241 ieee80211_add_wme_param(u_int8_t *frm, struct ieee80211_wme_state *wme)
 1242 {
 1243 #define SM(_v, _f)      (((_v) << _f##_S) & _f)
 1244 #define ADDSHORT(frm, v) do {                   \
 1245         frm[0] = (v) & 0xff;                    \
 1246         frm[1] = (v) >> 8;                      \
 1247         frm += 2;                               \
 1248 } while (0)
 1249         /* NB: this works 'cuz a param has an info at the front */
 1250         static const struct ieee80211_wme_info param = {
 1251                 .wme_id         = IEEE80211_ELEMID_VENDOR,
 1252                 .wme_len        = sizeof(struct ieee80211_wme_param) - 2,
 1253                 .wme_oui        = { WME_OUI_BYTES },
 1254                 .wme_type       = WME_OUI_TYPE,
 1255                 .wme_subtype    = WME_PARAM_OUI_SUBTYPE,
 1256                 .wme_version    = WME_VERSION,
 1257         };
 1258         int i;
 1259 
 1260         memcpy(frm, &param, sizeof(param));
 1261         frm += __offsetof(struct ieee80211_wme_info, wme_info);
 1262         *frm++ = wme->wme_bssChanParams.cap_info;       /* AC info */
 1263         *frm++ = 0;                                     /* reserved field */
 1264         for (i = 0; i < WME_NUM_AC; i++) {
 1265                 const struct wmeParams *ac =
 1266                        &wme->wme_bssChanParams.cap_wmeParams[i];
 1267                 *frm++ = SM(i, WME_PARAM_ACI)
 1268                        | SM(ac->wmep_acm, WME_PARAM_ACM)
 1269                        | SM(ac->wmep_aifsn, WME_PARAM_AIFSN)
 1270                        ;
 1271                 *frm++ = SM(ac->wmep_logcwmax, WME_PARAM_LOGCWMAX)
 1272                        | SM(ac->wmep_logcwmin, WME_PARAM_LOGCWMIN)
 1273                        ;
 1274                 ADDSHORT(frm, ac->wmep_txopLimit);
 1275         }
 1276         return frm;
 1277 #undef SM
 1278 #undef ADDSHORT
 1279 }
 1280 #undef WME_OUI_BYTES
 1281 
 1282 /*
 1283  * Send a probe request frame with the specified ssid
 1284  * and any optional information element data.
 1285  */
 1286 int
 1287 ieee80211_send_probereq(struct ieee80211_node *ni,
 1288         const u_int8_t sa[IEEE80211_ADDR_LEN],
 1289         const u_int8_t da[IEEE80211_ADDR_LEN],
 1290         const u_int8_t bssid[IEEE80211_ADDR_LEN],
 1291         const u_int8_t *ssid, size_t ssidlen,
 1292         const void *optie, size_t optielen)
 1293 {
 1294         struct ieee80211com *ic = ni->ni_ic;
 1295         enum ieee80211_phymode mode;
 1296         struct ieee80211_frame *wh;
 1297         struct mbuf *m;
 1298         u_int8_t *frm;
 1299 
 1300         /*
 1301          * Hold a reference on the node so it doesn't go away until after
 1302          * the xmit is complete all the way in the driver.  On error we
 1303          * will remove our reference.
 1304          */
 1305         IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
 1306                 "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
 1307                 __func__, __LINE__,
 1308                 ni, ether_sprintf(ni->ni_macaddr),
 1309                 ieee80211_node_refcnt(ni)+1);
 1310         ieee80211_ref_node(ni);
 1311 
 1312         /*
 1313          * prreq frame format
 1314          *      [tlv] ssid
 1315          *      [tlv] supported rates
 1316          *      [tlv] extended supported rates
 1317          *      [tlv] user-specified ie's
 1318          */
 1319         m = ieee80211_getmgtframe(&frm,
 1320                  2 + IEEE80211_NWID_LEN
 1321                + 2 + IEEE80211_RATE_SIZE
 1322                + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
 1323                + (optie != NULL ? optielen : 0)
 1324         );
 1325         if (m == NULL) {
 1326                 ic->ic_stats.is_tx_nobuf++;
 1327                 ieee80211_free_node(ni);
 1328                 return ENOMEM;
 1329         }
 1330 
 1331         frm = ieee80211_add_ssid(frm, ssid, ssidlen);
 1332         mode = ieee80211_chan2mode(ic, ic->ic_curchan);
 1333         frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);
 1334         frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);
 1335 
 1336         if (optie != NULL) {
 1337                 memcpy(frm, optie, optielen);
 1338                 frm += optielen;
 1339         }
 1340         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
 1341 
 1342         M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
 1343         if (m == NULL)
 1344                 return ENOMEM;
 1345         IASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null"));
 1346         m->m_pkthdr.rcvif = (void *)ni;
 1347 
 1348         wh = mtod(m, struct ieee80211_frame *);
 1349         ieee80211_send_setup(ic, ni, wh,
 1350                 IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ,
 1351                 sa, da, bssid);
 1352         /* XXX power management? */
 1353 
 1354         IEEE80211_NODE_STAT(ni, tx_probereq);
 1355         IEEE80211_NODE_STAT(ni, tx_mgmt);
 1356 
 1357         IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
 1358             "[%s] send probe req on channel %u\n",
 1359             ether_sprintf(wh->i_addr1),
 1360             ieee80211_chan2ieee(ic, ic->ic_curchan));
 1361 
 1362         IF_ENQUEUE(&ic->ic_mgtq, m);
 1363         (*ic->ic_ifp->if_start)(ic->ic_ifp);
 1364         return 0;
 1365 }
 1366 
 1367 /*
 1368  * Send a management frame.  The node is for the destination (or ic_bss
 1369  * when in station mode).  Nodes other than ic_bss have their reference
 1370  * count bumped to reflect our use for an indeterminant time.
 1371  */
 1372 int
 1373 ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
 1374         int type, int arg)
 1375 {
 1376 #define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)
 1377         struct mbuf *m;
 1378         u_int8_t *frm;
 1379         u_int16_t capinfo;
 1380         int has_challenge, is_shared_key, ret, timer, status;
 1381 
 1382         IASSERT(ni != NULL, ("null node"));
 1383 
 1384         /*
 1385          * Hold a reference on the node so it doesn't go away until after
 1386          * the xmit is complete all the way in the driver.  On error we
 1387          * will remove our reference.
 1388          */
 1389         IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
 1390                 "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n",
 1391                 __func__, __LINE__,
 1392                 ni, ether_sprintf(ni->ni_macaddr),
 1393                 ieee80211_node_refcnt(ni)+1);
 1394         ieee80211_ref_node(ni);
 1395 
 1396         timer = 0;
 1397         switch (type) {
 1398         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 1399                 /*
 1400                  * probe response frame format
 1401                  *      [8] time stamp
 1402                  *      [2] beacon interval
 1403                  *      [2] cabability information
 1404                  *      [tlv] ssid
 1405                  *      [tlv] supported rates
 1406                  *      [tlv] parameter set (FH/DS)
 1407                  *      [tlv] parameter set (IBSS)
 1408                  *      [tlv] extended rate phy (ERP)
 1409                  *      [tlv] extended supported rates
 1410                  *      [tlv] WPA
 1411                  *      [tlv] WME (optional)
 1412                  */
 1413                 m = ieee80211_getmgtframe(&frm,
 1414                          8
 1415                        + sizeof(u_int16_t)
 1416                        + sizeof(u_int16_t)
 1417                        + 2 + IEEE80211_NWID_LEN
 1418                        + 2 + IEEE80211_RATE_SIZE
 1419                        + 7      /* max(7,3) */
 1420                        + 6
 1421                        + 3
 1422                        + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
 1423                        /* XXX !WPA1+WPA2 fits w/o a cluster */
 1424                        + (ic->ic_flags & IEEE80211_F_WPA ?
 1425                                 2*sizeof(struct ieee80211_ie_wpa) : 0)
 1426                        + sizeof(struct ieee80211_wme_param)
 1427                 );
 1428                 if (m == NULL)
 1429                         senderr(ENOMEM, is_tx_nobuf);
 1430 
 1431                 memset(frm, 0, 8);      /* timestamp should be filled later */
 1432                 frm += 8;
 1433                 *(u_int16_t *)frm = htole16(ic->ic_bss->ni_intval);
 1434                 frm += 2;
 1435                 if (ic->ic_opmode == IEEE80211_M_IBSS)
 1436                         capinfo = IEEE80211_CAPINFO_IBSS;
 1437                 else
 1438                         capinfo = IEEE80211_CAPINFO_ESS;
 1439                 if (ic->ic_flags & IEEE80211_F_PRIVACY)
 1440                         capinfo |= IEEE80211_CAPINFO_PRIVACY;
 1441                 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
 1442                     IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
 1443                         capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
 1444                 if (ic->ic_flags & IEEE80211_F_SHSLOT)
 1445                         capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
 1446                 *(u_int16_t *)frm = htole16(capinfo);
 1447                 frm += 2;
 1448 
 1449                 frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,
 1450                                 ic->ic_bss->ni_esslen);
 1451                 frm = ieee80211_add_rates(frm, &ni->ni_rates);
 1452 
 1453                 if (ic->ic_phytype == IEEE80211_T_FH) {
 1454                         *frm++ = IEEE80211_ELEMID_FHPARMS;
 1455                         *frm++ = 5;
 1456                         *frm++ = ni->ni_fhdwell & 0x00ff;
 1457                         *frm++ = (ni->ni_fhdwell >> 8) & 0x00ff;
 1458                         *frm++ = IEEE80211_FH_CHANSET(
 1459                             ieee80211_chan2ieee(ic, ic->ic_curchan));
 1460                         *frm++ = IEEE80211_FH_CHANPAT(
 1461                             ieee80211_chan2ieee(ic, ic->ic_curchan));
 1462                         *frm++ = ni->ni_fhindex;
 1463                 } else {
 1464                         *frm++ = IEEE80211_ELEMID_DSPARMS;
 1465                         *frm++ = 1;
 1466                         *frm++ = ieee80211_chan2ieee(ic, ic->ic_curchan);
 1467                 }
 1468 
 1469                 if (ic->ic_opmode == IEEE80211_M_IBSS) {
 1470                         *frm++ = IEEE80211_ELEMID_IBSSPARMS;
 1471                         *frm++ = 2;
 1472                         *frm++ = 0; *frm++ = 0;         /* TODO: ATIM window */
 1473                 }
 1474                 if (ic->ic_flags & IEEE80211_F_WPA)
 1475                         frm = ieee80211_add_wpa(frm, ic);
 1476                 if (ic->ic_curmode == IEEE80211_MODE_11G)
 1477                         frm = ieee80211_add_erp(frm, ic);
 1478                 frm = ieee80211_add_xrates(frm, &ni->ni_rates);
 1479                 if (ic->ic_flags & IEEE80211_F_WME)
 1480                         frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
 1481                 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
 1482                 break;
 1483 
 1484         case IEEE80211_FC0_SUBTYPE_AUTH:
 1485                 status = arg >> 16;
 1486                 arg &= 0xffff;
 1487                 has_challenge = ((arg == IEEE80211_AUTH_SHARED_CHALLENGE ||
 1488                     arg == IEEE80211_AUTH_SHARED_RESPONSE) &&
 1489                     ni->ni_challenge != NULL);
 1490 
 1491                 /*
 1492                  * Deduce whether we're doing open authentication or
 1493                  * shared key authentication.  We do the latter if
 1494                  * we're in the middle of a shared key authentication
 1495                  * handshake or if we're initiating an authentication
 1496                  * request and configured to use shared key.
 1497                  */
 1498                 is_shared_key = has_challenge ||
 1499                      arg >= IEEE80211_AUTH_SHARED_RESPONSE ||
 1500                      (arg == IEEE80211_AUTH_SHARED_REQUEST &&
 1501                       ic->ic_bss->ni_authmode == IEEE80211_AUTH_SHARED);
 1502 
 1503                 m = ieee80211_getmgtframe(&frm,
 1504                           3 * sizeof(u_int16_t)
 1505                         + (has_challenge && status == IEEE80211_STATUS_SUCCESS ?
 1506                                 sizeof(u_int16_t)+IEEE80211_CHALLENGE_LEN : 0)
 1507                 );
 1508                 if (m == NULL)
 1509                         senderr(ENOMEM, is_tx_nobuf);
 1510 
 1511                 ((u_int16_t *)frm)[0] =
 1512                     (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED)
 1513                                     : htole16(IEEE80211_AUTH_ALG_OPEN);
 1514                 ((u_int16_t *)frm)[1] = htole16(arg);   /* sequence number */
 1515                 ((u_int16_t *)frm)[2] = htole16(status);/* status */
 1516 
 1517                 if (has_challenge && status == IEEE80211_STATUS_SUCCESS) {
 1518                         ((u_int16_t *)frm)[3] =
 1519                             htole16((IEEE80211_CHALLENGE_LEN << 8) |
 1520                             IEEE80211_ELEMID_CHALLENGE);
 1521                         memcpy(&((u_int16_t *)frm)[4], ni->ni_challenge,
 1522                             IEEE80211_CHALLENGE_LEN);
 1523                         m->m_pkthdr.len = m->m_len =
 1524                                 4 * sizeof(u_int16_t) + IEEE80211_CHALLENGE_LEN;
 1525                         if (arg == IEEE80211_AUTH_SHARED_RESPONSE) {
 1526                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 1527                                     "[%s] request encrypt frame (%s)\n",
 1528                                     ether_sprintf(ni->ni_macaddr), __func__);
 1529                                 m->m_flags |= M_LINK0; /* WEP-encrypt, please */
 1530                         }
 1531                 } else
 1532                         m->m_pkthdr.len = m->m_len = 3 * sizeof(u_int16_t);
 1533 
 1534                 /* XXX not right for shared key */
 1535                 if (status == IEEE80211_STATUS_SUCCESS)
 1536                         IEEE80211_NODE_STAT(ni, tx_auth);
 1537                 else
 1538                         IEEE80211_NODE_STAT(ni, tx_auth_fail);
 1539 
 1540                 if (ic->ic_opmode == IEEE80211_M_STA)
 1541                         timer = IEEE80211_TRANS_WAIT;
 1542                 break;
 1543 
 1544         case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1545                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 1546                         "[%s] send station deauthenticate (reason %d)\n",
 1547                         ether_sprintf(ni->ni_macaddr), arg);
 1548                 m = ieee80211_getmgtframe(&frm, sizeof(u_int16_t));
 1549                 if (m == NULL)
 1550                         senderr(ENOMEM, is_tx_nobuf);
 1551                 *(u_int16_t *)frm = htole16(arg);       /* reason */
 1552                 m->m_pkthdr.len = m->m_len = sizeof(u_int16_t);
 1553 
 1554                 IEEE80211_NODE_STAT(ni, tx_deauth);
 1555                 IEEE80211_NODE_STAT_SET(ni, tx_deauth_code, arg);
 1556 
 1557                 ieee80211_node_unauthorize(ni);         /* port closed */
 1558                 break;
 1559 
 1560         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
 1561         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
 1562                 /*
 1563                  * asreq frame format
 1564                  *      [2] capability information
 1565                  *      [2] listen interval
 1566                  *      [6*] current AP address (reassoc only)
 1567                  *      [tlv] ssid
 1568                  *      [tlv] supported rates
 1569                  *      [tlv] extended supported rates
 1570                  *      [tlv] WME
 1571                  *      [tlv] user-specified ie's
 1572                  */
 1573                 m = ieee80211_getmgtframe(&frm,
 1574                          sizeof(u_int16_t)
 1575                        + sizeof(u_int16_t)
 1576                        + IEEE80211_ADDR_LEN
 1577                        + 2 + IEEE80211_NWID_LEN
 1578                        + 2 + IEEE80211_RATE_SIZE
 1579                        + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
 1580                        + sizeof(struct ieee80211_wme_info)
 1581                        + (ic->ic_opt_ie != NULL ? ic->ic_opt_ie_len : 0)
 1582                 );
 1583                 if (m == NULL)
 1584                         senderr(ENOMEM, is_tx_nobuf);
 1585 
 1586                 capinfo = 0;
 1587                 if (ic->ic_opmode == IEEE80211_M_IBSS)
 1588                         capinfo |= IEEE80211_CAPINFO_IBSS;
 1589                 else            /* IEEE80211_M_STA */
 1590                         capinfo |= IEEE80211_CAPINFO_ESS;
 1591                 if (ic->ic_flags & IEEE80211_F_PRIVACY)
 1592                         capinfo |= IEEE80211_CAPINFO_PRIVACY;
 1593                 /*
 1594                  * NB: Some 11a AP's reject the request when
 1595                  *     short premable is set.
 1596                  */
 1597                 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
 1598                     IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
 1599                         capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
 1600                 if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) &&
 1601                     (ic->ic_caps & IEEE80211_C_SHSLOT))
 1602                         capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
 1603                 *(u_int16_t *)frm = htole16(capinfo);
 1604                 frm += 2;
 1605 
 1606                 *(u_int16_t *)frm = htole16(ic->ic_lintval);
 1607                 frm += 2;
 1608 
 1609                 if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
 1610                         IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid);
 1611                         frm += IEEE80211_ADDR_LEN;
 1612                 }
 1613 
 1614                 frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
 1615                 frm = ieee80211_add_rates(frm, &ni->ni_rates);
 1616                 frm = ieee80211_add_xrates(frm, &ni->ni_rates);
 1617                 if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL)
 1618                         frm = ieee80211_add_wme_info(frm, &ic->ic_wme);
 1619                 if (ic->ic_opt_ie != NULL) {
 1620                         memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len);
 1621                         frm += ic->ic_opt_ie_len;
 1622                 }
 1623                 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
 1624 
 1625                 timer = IEEE80211_TRANS_WAIT;
 1626                 break;
 1627 
 1628         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
 1629         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
 1630                 /*
 1631                  * asreq frame format
 1632                  *      [2] capability information
 1633                  *      [2] status
 1634                  *      [2] association ID
 1635                  *      [tlv] supported rates
 1636                  *      [tlv] extended supported rates
 1637                  *      [tlv] WME (if enabled and STA enabled)
 1638                  */
 1639                 m = ieee80211_getmgtframe(&frm,
 1640                          sizeof(u_int16_t)
 1641                        + sizeof(u_int16_t)
 1642                        + sizeof(u_int16_t)
 1643                        + 2 + IEEE80211_RATE_SIZE
 1644                        + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
 1645                        + sizeof(struct ieee80211_wme_param)
 1646                 );
 1647                 if (m == NULL)
 1648                         senderr(ENOMEM, is_tx_nobuf);
 1649 
 1650                 capinfo = IEEE80211_CAPINFO_ESS;
 1651                 if (ic->ic_flags & IEEE80211_F_PRIVACY)
 1652                         capinfo |= IEEE80211_CAPINFO_PRIVACY;
 1653                 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
 1654                     IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
 1655                         capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
 1656                 if (ic->ic_flags & IEEE80211_F_SHSLOT)
 1657                         capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
 1658                 *(u_int16_t *)frm = htole16(capinfo);
 1659                 frm += 2;
 1660 
 1661                 *(u_int16_t *)frm = htole16(arg);       /* status */
 1662                 frm += 2;
 1663 
 1664                 if (arg == IEEE80211_STATUS_SUCCESS) {
 1665                         *(u_int16_t *)frm = htole16(ni->ni_associd);
 1666                         IEEE80211_NODE_STAT(ni, tx_assoc);
 1667                 } else
 1668                         IEEE80211_NODE_STAT(ni, tx_assoc_fail);
 1669                 frm += 2;
 1670 
 1671                 frm = ieee80211_add_rates(frm, &ni->ni_rates);
 1672                 frm = ieee80211_add_xrates(frm, &ni->ni_rates);
 1673                 if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL)
 1674                         frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
 1675                 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
 1676                 break;
 1677 
 1678         case IEEE80211_FC0_SUBTYPE_DISASSOC:
 1679                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
 1680                         "[%s] send station disassociate (reason %d)\n",
 1681                         ether_sprintf(ni->ni_macaddr), arg);
 1682                 m = ieee80211_getmgtframe(&frm, sizeof(u_int16_t));
 1683                 if (m == NULL)
 1684                         senderr(ENOMEM, is_tx_nobuf);
 1685                 *(u_int16_t *)frm = htole16(arg);       /* reason */
 1686                 m->m_pkthdr.len = m->m_len = sizeof(u_int16_t);
 1687 
 1688                 IEEE80211_NODE_STAT(ni, tx_disassoc);
 1689                 IEEE80211_NODE_STAT_SET(ni, tx_disassoc_code, arg);
 1690                 break;
 1691 
 1692         default:
 1693                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1694                         "[%s] invalid mgmt frame type %u\n",
 1695                         ether_sprintf(ni->ni_macaddr), type);
 1696                 senderr(EINVAL, is_tx_unknownmgt);
 1697                 /* NOTREACHED */
 1698         }
 1699         ret = ieee80211_mgmt_output(ic, ni, m, type, timer);
 1700         if (ret != 0) {
 1701 bad:
 1702                 ieee80211_free_node(ni);
 1703         }
 1704         return ret;
 1705 #undef senderr
 1706 }
 1707 
 1708 /*
 1709  * Build a RTS (Request To Send) control frame.
 1710  */
 1711 struct mbuf *
 1712 ieee80211_get_rts(struct ieee80211com *ic, const struct ieee80211_frame *wh,
 1713     uint16_t dur)
 1714 {
 1715         struct ieee80211_frame_rts *rts;
 1716         struct mbuf *m;
 1717 
 1718         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1719         if (m == NULL)
 1720                 return NULL;
 1721 
 1722         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_rts);
 1723 
 1724         rts = mtod(m, struct ieee80211_frame_rts *);
 1725         rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
 1726             IEEE80211_FC0_SUBTYPE_RTS;
 1727         rts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 1728         *(uint16_t *)rts->i_dur = htole16(dur);
 1729         IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1);
 1730         IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2);
 1731 
 1732         return m;
 1733 }
 1734 
 1735 /*
 1736  * Build a CTS-to-self (Clear To Send) control frame.
 1737  */
 1738 struct mbuf *
 1739 ieee80211_get_cts_to_self(struct ieee80211com *ic, uint16_t dur)
 1740 {
 1741         struct ieee80211_frame_cts *cts;
 1742         struct mbuf *m;
 1743 
 1744         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1745         if (m == NULL)
 1746                 return NULL;
 1747 
 1748         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_cts);
 1749 
 1750         cts = mtod(m, struct ieee80211_frame_cts *);
 1751         cts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
 1752             IEEE80211_FC0_SUBTYPE_CTS;
 1753         cts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 1754         *(uint16_t *)cts->i_dur = htole16(dur);
 1755         IEEE80211_ADDR_COPY(cts->i_ra, ic->ic_myaddr);
 1756 
 1757         return m;
 1758 }
 1759 
 1760 /*
 1761  * Allocate a beacon frame and fillin the appropriate bits.
 1762  */
 1763 struct mbuf *
 1764 ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni,
 1765         struct ieee80211_beacon_offsets *bo)
 1766 {
 1767         struct ifnet *ifp = ic->ic_ifp;
 1768         struct ieee80211_frame *wh;
 1769         struct mbuf *m;
 1770         int pktlen;
 1771         u_int8_t *frm, *efrm;
 1772         u_int16_t capinfo;
 1773         struct ieee80211_rateset *rs;
 1774 
 1775         /*
 1776          * beacon frame format
 1777          *      [8] time stamp
 1778          *      [2] beacon interval
 1779          *      [2] cabability information
 1780          *      [tlv] ssid
 1781          *      [tlv] supported rates
 1782          *      [3] parameter set (DS)
 1783          *      [tlv] parameter set (IBSS/TIM)
 1784          *      [tlv] extended rate phy (ERP)
 1785          *      [tlv] extended supported rates
 1786          *      [tlv] WME parameters
 1787          *      [tlv] WPA/RSN parameters
 1788          * XXX Vendor-specific OIDs (e.g. Atheros)
 1789          * NB: we allocate the max space required for the TIM bitmap.
 1790          */
 1791         rs = &ni->ni_rates;
 1792         pktlen =   8                                    /* time stamp */
 1793                  + sizeof(u_int16_t)                    /* beacon interval */
 1794                  + sizeof(u_int16_t)                    /* capabilities */
 1795                  + 2 + ni->ni_esslen                    /* ssid */
 1796                  + 2 + IEEE80211_RATE_SIZE              /* supported rates */
 1797                  + 2 + 1                                /* DS parameters */
 1798                  + 2 + 4 + ic->ic_tim_len               /* DTIM/IBSSPARMS */
 1799                  + 2 + 1                                /* ERP */
 1800                  + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
 1801                  + (ic->ic_caps & IEEE80211_C_WME ?     /* WME */
 1802                         sizeof(struct ieee80211_wme_param) : 0)
 1803                  + (ic->ic_caps & IEEE80211_C_WPA ?     /* WPA 1+2 */
 1804                         2*sizeof(struct ieee80211_ie_wpa) : 0)
 1805                  ;
 1806         m = ieee80211_getmgtframe(&frm, pktlen);
 1807         if (m == NULL) {
 1808                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 1809                         "%s: cannot get buf; size %u\n", __func__, pktlen);
 1810                 ic->ic_stats.is_tx_nobuf++;
 1811                 return NULL;
 1812         }
 1813 
 1814         memset(frm, 0, 8);      /* XXX timestamp is set by hardware/driver */
 1815         frm += 8;
 1816         *(u_int16_t *)frm = htole16(ni->ni_intval);
 1817         frm += 2;
 1818         if (ic->ic_opmode == IEEE80211_M_IBSS)
 1819                 capinfo = IEEE80211_CAPINFO_IBSS;
 1820         else
 1821                 capinfo = IEEE80211_CAPINFO_ESS;
 1822         if (ic->ic_flags & IEEE80211_F_PRIVACY)
 1823                 capinfo |= IEEE80211_CAPINFO_PRIVACY;
 1824         if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
 1825             IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
 1826                 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
 1827         if (ic->ic_flags & IEEE80211_F_SHSLOT)
 1828                 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
 1829         bo->bo_caps = (u_int16_t *)frm;
 1830         *(u_int16_t *)frm = htole16(capinfo);
 1831         frm += 2;
 1832         *frm++ = IEEE80211_ELEMID_SSID;
 1833         if ((ic->ic_flags & IEEE80211_F_HIDESSID) == 0) {
 1834                 *frm++ = ni->ni_esslen;
 1835                 memcpy(frm, ni->ni_essid, ni->ni_esslen);
 1836                 frm += ni->ni_esslen;
 1837         } else
 1838                 *frm++ = 0;
 1839         frm = ieee80211_add_rates(frm, rs);
 1840         if (ic->ic_curmode != IEEE80211_MODE_FH) {
 1841                 *frm++ = IEEE80211_ELEMID_DSPARMS;
 1842                 *frm++ = 1;
 1843                 *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
 1844         }
 1845         bo->bo_tim = frm;
 1846         if (ic->ic_opmode == IEEE80211_M_IBSS) {
 1847                 *frm++ = IEEE80211_ELEMID_IBSSPARMS;
 1848                 *frm++ = 2;
 1849                 *frm++ = 0; *frm++ = 0;         /* TODO: ATIM window */
 1850                 bo->bo_tim_len = 0;
 1851         } else {
 1852                 struct ieee80211_tim_ie *tie = (struct ieee80211_tim_ie *) frm;
 1853 
 1854                 tie->tim_ie = IEEE80211_ELEMID_TIM;
 1855                 tie->tim_len = 4;       /* length */
 1856                 tie->tim_count = 0;     /* DTIM count */ 
 1857                 tie->tim_period = ic->ic_dtim_period;   /* DTIM period */
 1858                 tie->tim_bitctl = 0;    /* bitmap control */
 1859                 tie->tim_bitmap[0] = 0; /* Partial Virtual Bitmap */
 1860                 frm += sizeof(struct ieee80211_tim_ie);
 1861                 bo->bo_tim_len = 1;
 1862         }
 1863         bo->bo_trailer = frm;
 1864         if (ic->ic_flags & IEEE80211_F_WME) {
 1865                 bo->bo_wme = frm;
 1866                 frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
 1867                 ic->ic_flags &= ~IEEE80211_F_WMEUPDATE;
 1868         }
 1869         if (ic->ic_flags & IEEE80211_F_WPA)
 1870                 frm = ieee80211_add_wpa(frm, ic);
 1871         if (ic->ic_curmode == IEEE80211_MODE_11G)
 1872                 frm = ieee80211_add_erp(frm, ic);
 1873         efrm = ieee80211_add_xrates(frm, rs);
 1874         bo->bo_trailer_len = efrm - bo->bo_trailer;
 1875         m->m_pkthdr.len = m->m_len = efrm - mtod(m, u_int8_t *);
 1876 
 1877         M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
 1878         IASSERT(m != NULL, ("no space for 802.11 header?"));
 1879         wh = mtod(m, struct ieee80211_frame *);
 1880         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
 1881             IEEE80211_FC0_SUBTYPE_BEACON;
 1882         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 1883         *(u_int16_t *)wh->i_dur = 0;
 1884         IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
 1885         IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
 1886         IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
 1887         *(u_int16_t *)wh->i_seq = 0;
 1888 
 1889         return m;
 1890 }
 1891 
 1892 /*
 1893  * Update the dynamic parts of a beacon frame based on the current state.
 1894  */
 1895 int
 1896 ieee80211_beacon_update(struct ieee80211com *ic, struct ieee80211_node *ni,
 1897     struct ieee80211_beacon_offsets *bo, struct mbuf *m, int mcast)
 1898 {
 1899         int len_changed = 0;
 1900         u_int16_t capinfo;
 1901 
 1902         IEEE80211_BEACON_LOCK(ic);
 1903         /* XXX faster to recalculate entirely or just changes? */
 1904         if (ic->ic_opmode == IEEE80211_M_IBSS)
 1905                 capinfo = IEEE80211_CAPINFO_IBSS;
 1906         else
 1907                 capinfo = IEEE80211_CAPINFO_ESS;
 1908         if (ic->ic_flags & IEEE80211_F_PRIVACY)
 1909                 capinfo |= IEEE80211_CAPINFO_PRIVACY;
 1910         if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
 1911             IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
 1912                 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
 1913         if (ic->ic_flags & IEEE80211_F_SHSLOT)
 1914                 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
 1915         *bo->bo_caps = htole16(capinfo);
 1916 
 1917         if (ic->ic_flags & IEEE80211_F_WME) {
 1918                 struct ieee80211_wme_state *wme = &ic->ic_wme;
 1919 
 1920                 /*
 1921                  * Check for agressive mode change.  When there is
 1922                  * significant high priority traffic in the BSS
 1923                  * throttle back BE traffic by using conservative
 1924                  * parameters.  Otherwise BE uses agressive params
 1925                  * to optimize performance of legacy/non-QoS traffic.
 1926                  */
 1927                 if (wme->wme_flags & WME_F_AGGRMODE) {
 1928                         if (wme->wme_hipri_traffic >
 1929                             wme->wme_hipri_switch_thresh) {
 1930                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
 1931                                     "%s: traffic %u, disable aggressive mode\n",
 1932                                     __func__, wme->wme_hipri_traffic);
 1933                                 wme->wme_flags &= ~WME_F_AGGRMODE;
 1934                                 ieee80211_wme_updateparams_locked(ic);
 1935                                 wme->wme_hipri_traffic =
 1936                                         wme->wme_hipri_switch_hysteresis;
 1937                         } else
 1938                                 wme->wme_hipri_traffic = 0;
 1939                 } else {
 1940                         if (wme->wme_hipri_traffic <=
 1941                             wme->wme_hipri_switch_thresh) {
 1942                                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
 1943                                     "%s: traffic %u, enable aggressive mode\n",
 1944                                     __func__, wme->wme_hipri_traffic);
 1945                                 wme->wme_flags |= WME_F_AGGRMODE;
 1946                                 ieee80211_wme_updateparams_locked(ic);
 1947                                 wme->wme_hipri_traffic = 0;
 1948                         } else
 1949                                 wme->wme_hipri_traffic =
 1950                                         wme->wme_hipri_switch_hysteresis;
 1951                 }
 1952                 if (ic->ic_flags & IEEE80211_F_WMEUPDATE) {
 1953                         (void) ieee80211_add_wme_param(bo->bo_wme, wme);
 1954                         ic->ic_flags &= ~IEEE80211_F_WMEUPDATE;
 1955                 }
 1956         }
 1957 
 1958 #ifndef IEEE80211_NO_HOSTAP
 1959         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {      /* NB: no IBSS support*/
 1960                 struct ieee80211_tim_ie *tie =
 1961                         (struct ieee80211_tim_ie *) bo->bo_tim;
 1962                 if (ic->ic_flags & IEEE80211_F_TIMUPDATE) {
 1963                         u_int timlen, timoff, i;
 1964                         /* 
 1965                          * ATIM/DTIM needs updating.  If it fits in the
 1966                          * current space allocated then just copy in the
 1967                          * new bits.  Otherwise we need to move any trailing
 1968                          * data to make room.  Note that we know there is
 1969                          * contiguous space because ieee80211_beacon_allocate
 1970                          * insures there is space in the mbuf to write a
 1971                          * maximal-size virtual bitmap (based on ic_max_aid).
 1972                          */
 1973                         /*
 1974                          * Calculate the bitmap size and offset, copy any
 1975                          * trailer out of the way, and then copy in the
 1976                          * new bitmap and update the information element.
 1977                          * Note that the tim bitmap must contain at least
 1978                          * one byte and any offset must be even.
 1979                          */
 1980                         if (ic->ic_ps_pending != 0) {
 1981                                 timoff = 128;           /* impossibly large */
 1982                                 for (i = 0; i < ic->ic_tim_len; i++)
 1983                                         if (ic->ic_tim_bitmap[i]) {
 1984                                                 timoff = i &~ 1;
 1985                                                 break;
 1986                                         }
 1987                                 IASSERT(timoff != 128, ("tim bitmap empty!"));
 1988                                 for (i = ic->ic_tim_len-1; i >= timoff; i--)
 1989                                         if (ic->ic_tim_bitmap[i])
 1990                                                 break;
 1991                                 timlen = 1 + (i - timoff);
 1992                         } else {
 1993                                 timoff = 0;
 1994                                 timlen = 1;
 1995                         }
 1996                         if (timlen != bo->bo_tim_len) {
 1997                                 /* copy up/down trailer */
 1998                                 ovbcopy(bo->bo_trailer, tie->tim_bitmap+timlen,
 1999                                         bo->bo_trailer_len);
 2000                                 bo->bo_trailer = tie->tim_bitmap+timlen;
 2001                                 bo->bo_wme = bo->bo_trailer;
 2002                                 bo->bo_tim_len = timlen;
 2003 
 2004                                 /* update information element */
 2005                                 tie->tim_len = 3 + timlen;
 2006                                 tie->tim_bitctl = timoff;
 2007                                 len_changed = 1;
 2008                         }
 2009                         memcpy(tie->tim_bitmap, ic->ic_tim_bitmap + timoff,
 2010                                 bo->bo_tim_len);
 2011 
 2012                         ic->ic_flags &= ~IEEE80211_F_TIMUPDATE;
 2013 
 2014                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2015                                 "%s: TIM updated, pending %u, off %u, len %u\n",
 2016                                 __func__, ic->ic_ps_pending, timoff, timlen);
 2017                 }
 2018                 /* count down DTIM period */
 2019                 if (tie->tim_count == 0)
 2020                         tie->tim_count = tie->tim_period - 1;
 2021                 else
 2022                         tie->tim_count--;
 2023                 /* update state for buffered multicast frames on DTIM */
 2024                 if (mcast && (tie->tim_count == 1 || tie->tim_period == 1))
 2025                         tie->tim_bitctl |= 1;
 2026                 else
 2027                         tie->tim_bitctl &= ~1;
 2028         }
 2029 #endif /* !IEEE80211_NO_HOSTAP */
 2030         IEEE80211_BEACON_UNLOCK(ic);
 2031 
 2032         return len_changed;
 2033 }
 2034 
 2035 /*
 2036  * Save an outbound packet for a node in power-save sleep state.
 2037  * The new packet is placed on the node's saved queue, and the TIM
 2038  * is changed, if necessary.
 2039  */
 2040 void
 2041 ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni, 
 2042                   struct mbuf *m)
 2043 {
 2044         int qlen, age;
 2045 
 2046         IEEE80211_NODE_SAVEQ_LOCK(ni);
 2047         if (IF_QFULL(&ni->ni_savedq)) {
 2048                 IF_DROP(&ni->ni_savedq);
 2049                 IEEE80211_NODE_SAVEQ_UNLOCK(ni);
 2050                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
 2051                         "[%s] pwr save q overflow, drops %d (size %d)\n",
 2052                         ether_sprintf(ni->ni_macaddr), 
 2053                         ni->ni_savedq.ifq_drops, IEEE80211_PS_MAX_QUEUE);
 2054 #ifdef IEEE80211_DEBUG
 2055                 if (ieee80211_msg_dumppkts(ic))
 2056                         ieee80211_dump_pkt(mtod(m, void *), m->m_len, -1, -1);
 2057 #endif
 2058                 m_freem(m);
 2059                 return;
 2060         }
 2061         /*
 2062          * Tag the frame with it's expiry time and insert
 2063          * it in the queue.  The aging interval is 4 times
 2064          * the listen interval specified by the station. 
 2065          * Frames that sit around too long are reclaimed
 2066          * using this information.
 2067          */
 2068         /* XXX handle overflow? */
 2069         age = ((ni->ni_intval * ic->ic_bintval) << 2) / 1024; /* TU -> secs */
 2070         _IEEE80211_NODE_SAVEQ_ENQUEUE(ni, m, qlen, age);
 2071         IEEE80211_NODE_SAVEQ_UNLOCK(ni);
 2072 
 2073         IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
 2074                 "[%s] save frame with age %d, %u now queued\n",
 2075                 ether_sprintf(ni->ni_macaddr), age, qlen);
 2076 
 2077         if (qlen == 1)
 2078                 ic->ic_set_tim(ni, 1);
 2079 }

Cache object: 12e6cc35502a2d6ebdddbd386867fce5


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