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

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

Cache object: e1bb60dd47722b29db65b45ba4fe8b5a


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