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

Cache object: 12e6cc35502a2d6ebdddbd386867fce5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.