LCOV - code coverage report
Current view: top level - net80211 - ieee80211_output.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 882 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 41 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ieee80211_output.c,v 1.122 2017/12/14 18:52:17 stsp Exp $     */
       2             : /*      $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $     */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 2001 Atsushi Onoe
       6             :  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
       7             :  * Copyright (c) 2007-2009 Damien Bergamini
       8             :  * All rights reserved.
       9             :  *
      10             :  * Redistribution and use in source and binary forms, with or without
      11             :  * modification, are permitted provided that the following conditions
      12             :  * are met:
      13             :  * 1. Redistributions of source code must retain the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer.
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  * 3. The name of the author may not be used to endorse or promote products
      19             :  *    derived from this software without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      22             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      23             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      24             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      25             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      26             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      30             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : #include "bpfilter.h"
      34             : #include "vlan.h"
      35             : 
      36             : #include <sys/param.h>
      37             : #include <sys/systm.h>
      38             : #include <sys/mbuf.h>
      39             : #include <sys/kernel.h>
      40             : #include <sys/socket.h>
      41             : #include <sys/sockio.h>
      42             : #include <sys/endian.h>
      43             : #include <sys/errno.h>
      44             : #include <sys/sysctl.h>
      45             : 
      46             : #include <net/if.h>
      47             : #include <net/if_dl.h>
      48             : #include <net/if_media.h>
      49             : #include <net/if_llc.h>
      50             : #include <net/bpf.h>
      51             : 
      52             : #include <netinet/in.h>
      53             : #include <netinet/if_ether.h>
      54             : #include <netinet/ip.h>
      55             : #ifdef INET6
      56             : #include <netinet/ip6.h>
      57             : #endif
      58             : 
      59             : #if NVLAN > 0
      60             : #include <net/if_vlan_var.h>
      61             : #endif
      62             : 
      63             : #include <net80211/ieee80211_var.h>
      64             : #include <net80211/ieee80211_priv.h>
      65             : 
      66             : int     ieee80211_mgmt_output(struct ifnet *, struct ieee80211_node *,
      67             :             struct mbuf *, int);
      68             : u_int8_t *ieee80211_add_rsn_body(u_int8_t *, struct ieee80211com *,
      69             :             const struct ieee80211_node *, int);
      70             : struct  mbuf *ieee80211_getmgmt(int, int, u_int);
      71             : struct  mbuf *ieee80211_get_probe_req(struct ieee80211com *,
      72             :             struct ieee80211_node *);
      73             : #ifndef IEEE80211_STA_ONLY
      74             : struct  mbuf *ieee80211_get_probe_resp(struct ieee80211com *,
      75             :             struct ieee80211_node *);
      76             : #endif
      77             : struct  mbuf *ieee80211_get_auth(struct ieee80211com *,
      78             :             struct ieee80211_node *, u_int16_t, u_int16_t);
      79             : struct  mbuf *ieee80211_get_deauth(struct ieee80211com *,
      80             :             struct ieee80211_node *, u_int16_t);
      81             : struct  mbuf *ieee80211_get_assoc_req(struct ieee80211com *,
      82             :             struct ieee80211_node *, int);
      83             : #ifndef IEEE80211_STA_ONLY
      84             : struct  mbuf *ieee80211_get_assoc_resp(struct ieee80211com *,
      85             :             struct ieee80211_node *, u_int16_t);
      86             : #endif
      87             : struct  mbuf *ieee80211_get_disassoc(struct ieee80211com *,
      88             :             struct ieee80211_node *, u_int16_t);
      89             : struct  mbuf *ieee80211_get_addba_req(struct ieee80211com *,
      90             :             struct ieee80211_node *, u_int8_t);
      91             : struct  mbuf *ieee80211_get_addba_resp(struct ieee80211com *,
      92             :             struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t);
      93             : struct  mbuf *ieee80211_get_delba(struct ieee80211com *,
      94             :             struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t);
      95             : uint8_t *ieee80211_add_wme_info(uint8_t *, struct ieee80211com *);
      96             : #ifndef IEEE80211_STA_ONLY
      97             : uint8_t *ieee80211_add_wme_param(uint8_t *, struct ieee80211com *);
      98             : #endif
      99             : struct  mbuf *ieee80211_get_sa_query(struct ieee80211com *,
     100             :             struct ieee80211_node *, u_int8_t);
     101             : struct  mbuf *ieee80211_get_action(struct ieee80211com *,
     102             :             struct ieee80211_node *, u_int8_t, u_int8_t, int);
     103             : 
     104             : /*
     105             :  * IEEE 802.11 output routine. Normally this will directly call the
     106             :  * Ethernet output routine because 802.11 encapsulation is called
     107             :  * later by the driver. This function can be used to send raw frames
     108             :  * if the mbuf has been tagged with a 802.11 data link type.
     109             :  */
     110             : int
     111           0 : ieee80211_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
     112             :     struct rtentry *rt)
     113             : {
     114             :         struct ieee80211_frame *wh;
     115             :         struct m_tag *mtag;
     116             :         int error = 0;
     117             : 
     118             :         /* Interface has to be up and running */
     119           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
     120             :             (IFF_UP | IFF_RUNNING)) {
     121             :                 error = ENETDOWN;
     122             :                 goto bad;
     123             :         }
     124             : 
     125             :         /* Try to get the DLT from a mbuf tag */
     126           0 :         if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
     127           0 :                 struct ieee80211com *ic = (void *)ifp;
     128           0 :                 u_int dlt = *(u_int *)(mtag + 1);
     129             : 
     130             :                 /* Fallback to ethernet for non-802.11 linktypes */
     131           0 :                 if (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))
     132           0 :                         goto fallback;
     133             : 
     134           0 :                 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min))
     135           0 :                         return (EINVAL);
     136           0 :                 wh = mtod(m, struct ieee80211_frame *);
     137           0 :                 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
     138             :                     IEEE80211_FC0_VERSION_0)
     139           0 :                         return (EINVAL);
     140           0 :                 if (!(ic->ic_caps & IEEE80211_C_RAWCTL) &&
     141           0 :                     (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
     142             :                     IEEE80211_FC0_TYPE_CTL)
     143           0 :                         return (EINVAL);
     144             : 
     145           0 :                 return (if_enqueue(ifp, m));
     146             :         }
     147             : 
     148             :  fallback:
     149           0 :         return (ether_output(ifp, m, dst, rt));
     150             : 
     151             :  bad:
     152           0 :         m_freem(m);
     153           0 :         return (error);
     154           0 : }
     155             : 
     156             : /*
     157             :  * Send a management frame to the specified node.  The node pointer
     158             :  * must have a reference as the pointer will be passed to the driver
     159             :  * and potentially held for a long time.  If the frame is successfully
     160             :  * dispatched to the driver, then it is responsible for freeing the
     161             :  * reference (and potentially free'ing up any associated storage).
     162             :  */
     163             : int
     164           0 : ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
     165             :     struct mbuf *m, int type)
     166             : {
     167           0 :         struct ieee80211com *ic = (void *)ifp;
     168             :         struct ieee80211_frame *wh;
     169             : 
     170           0 :         if (ni == NULL)
     171           0 :                 panic("null node");
     172           0 :         ni->ni_inact = 0;
     173             : 
     174             :         /*
     175             :          * We want to pass the node down to the driver's start
     176             :          * routine.  We could stick this in an m_tag and tack that
     177             :          * on to the mbuf.  However that's rather expensive to do
     178             :          * for every frame so instead we stuff it in a special pkthdr
     179             :          * field.
     180             :          */
     181           0 :         M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
     182           0 :         if (m == NULL)
     183           0 :                 return ENOMEM;
     184           0 :         m->m_pkthdr.ph_cookie = ni;
     185             : 
     186           0 :         wh = mtod(m, struct ieee80211_frame *);
     187           0 :         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
     188           0 :         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
     189           0 :         *(u_int16_t *)&wh->i_dur[0] = 0;
     190           0 :         *(u_int16_t *)&wh->i_seq[0] =
     191           0 :             htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
     192           0 :         ni->ni_txseq++;
     193           0 :         IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
     194           0 :         IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
     195           0 :         IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
     196             : 
     197             :         /* check if protection is required for this mgmt frame */
     198           0 :         if ((ic->ic_caps & IEEE80211_C_MFP) &&
     199           0 :             (type == IEEE80211_FC0_SUBTYPE_DISASSOC ||
     200           0 :              type == IEEE80211_FC0_SUBTYPE_DEAUTH ||
     201           0 :              type == IEEE80211_FC0_SUBTYPE_ACTION)) {
     202             :                 /*
     203             :                  * Hack: we should not set the Protected bit in outgoing
     204             :                  * group management frames, however it is used as an
     205             :                  * indication to the drivers that they must encrypt the
     206             :                  * frame.  Drivers should clear this bit from group
     207             :                  * management frames (software crypto code will do it).
     208             :                  * XXX could use an mbuf flag..
     209             :                  */
     210           0 :                 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
     211           0 :                     (ni->ni_flags & IEEE80211_NODE_TXMGMTPROT))
     212           0 :                         wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
     213             :         }
     214             : 
     215           0 :         if (ifp->if_flags & IFF_DEBUG) {
     216             :                 /* avoid to print too many frames */
     217             :                 if (
     218             : #ifndef IEEE80211_STA_ONLY
     219           0 :                     ic->ic_opmode == IEEE80211_M_IBSS ||
     220             : #endif
     221             : #ifdef IEEE80211_DEBUG
     222             :                     ieee80211_debug > 1 ||
     223             : #endif
     224           0 :                     (type & IEEE80211_FC0_SUBTYPE_MASK) !=
     225             :                     IEEE80211_FC0_SUBTYPE_PROBE_RESP)
     226           0 :                         printf("%s: sending %s to %s on channel %u mode %s\n",
     227           0 :                             ifp->if_xname,
     228           0 :                             ieee80211_mgt_subtype_name[
     229           0 :                             (type & IEEE80211_FC0_SUBTYPE_MASK)
     230           0 :                             >> IEEE80211_FC0_SUBTYPE_SHIFT],
     231           0 :                             ether_sprintf(ni->ni_macaddr),
     232           0 :                             ieee80211_chan2ieee(ic, ni->ni_chan),
     233           0 :                             ieee80211_phymode_name[ic->ic_curmode]);
     234             :         }
     235             : 
     236             : #ifndef IEEE80211_STA_ONLY
     237           0 :         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
     238           0 :             ieee80211_pwrsave(ic, m, ni) != 0)
     239           0 :                 return 0;
     240             : #endif
     241           0 :         mq_enqueue(&ic->ic_mgtq, m);
     242           0 :         ifp->if_timer = 1;
     243           0 :         if_start(ifp);
     244           0 :         return 0;
     245           0 : }
     246             : 
     247             : /*-
     248             :  * EDCA tables are computed using the following formulas:
     249             :  *
     250             :  * 1) EDCATable (non-AP QSTA)
     251             :  *
     252             :  * AC     CWmin            CWmax           AIFSN  TXOP limit(ms)
     253             :  * -------------------------------------------------------------
     254             :  * AC_BK  aCWmin           aCWmax          7      0
     255             :  * AC_BE  aCWmin           aCWmax          3      0
     256             :  * AC_VI  (aCWmin+1)/2-1   aCWmin          2      agn=3.008 b=6.016 others=0
     257             :  * AC_VO  (aCWmin+1)/4-1   (aCWmin+1)/2-1  2      agn=1.504 b=3.264 others=0
     258             :  *
     259             :  * 2) QAPEDCATable (QAP)
     260             :  *
     261             :  * AC     CWmin            CWmax           AIFSN  TXOP limit(ms)
     262             :  * -------------------------------------------------------------
     263             :  * AC_BK  aCWmin           aCWmax          7      0
     264             :  * AC_BE  aCWmin           4*(aCWmin+1)-1  3      0
     265             :  * AC_VI  (aCWmin+1)/2-1   aCWmin          1      agn=3.008 b=6.016 others=0
     266             :  * AC_VO  (aCWmin+1)/4-1   (aCWmin+1)/2-1  1      agn=1.504 b=3.264 others=0
     267             :  *
     268             :  * and the following aCWmin/aCWmax values:
     269             :  *
     270             :  * PHY          aCWmin  aCWmax
     271             :  * ---------------------------
     272             :  * 11A          15      1023
     273             :  * 11B          31      1023
     274             :  * 11G          15*     1023    (*) aCWmin(1)
     275             :  * 11N          15      1023
     276             :  */
     277             : const struct ieee80211_edca_ac_params
     278             :     ieee80211_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {
     279             :         [IEEE80211_MODE_11B] = {
     280             :                 [EDCA_AC_BK] = { 5, 10, 7,   0 },
     281             :                 [EDCA_AC_BE] = { 5, 10, 3,   0 },
     282             :                 [EDCA_AC_VI] = { 4,  5, 2, 188 },
     283             :                 [EDCA_AC_VO] = { 3,  4, 2, 102 }
     284             :         },
     285             :         [IEEE80211_MODE_11A] = {
     286             :                 [EDCA_AC_BK] = { 4, 10, 7,   0 },
     287             :                 [EDCA_AC_BE] = { 4, 10, 3,   0 },
     288             :                 [EDCA_AC_VI] = { 3,  4, 2,  94 },
     289             :                 [EDCA_AC_VO] = { 2,  3, 2,  47 }
     290             :         },
     291             :         [IEEE80211_MODE_11G] = {
     292             :                 [EDCA_AC_BK] = { 4, 10, 7,   0 },
     293             :                 [EDCA_AC_BE] = { 4, 10, 3,   0 },
     294             :                 [EDCA_AC_VI] = { 3,  4, 2,  94 },
     295             :                 [EDCA_AC_VO] = { 2,  3, 2,  47 }
     296             :         },
     297             :         [IEEE80211_MODE_11N] = {
     298             :                 [EDCA_AC_BK] = { 4, 10, 7,   0 },
     299             :                 [EDCA_AC_BE] = { 4, 10, 3,   0 },
     300             :                 [EDCA_AC_VI] = { 3,  4, 2,  94 },
     301             :                 [EDCA_AC_VO] = { 2,  3, 2,  47 }
     302             :         },
     303             : };
     304             : 
     305             : #ifndef IEEE80211_STA_ONLY
     306             : const struct ieee80211_edca_ac_params
     307             :     ieee80211_qap_edca_table[IEEE80211_MODE_MAX][EDCA_NUM_AC] = {
     308             :         [IEEE80211_MODE_11B] = {
     309             :                 [EDCA_AC_BK] = { 5, 10, 7,   0 },
     310             :                 [EDCA_AC_BE] = { 5,  7, 3,   0 },
     311             :                 [EDCA_AC_VI] = { 4,  5, 1, 188 },
     312             :                 [EDCA_AC_VO] = { 3,  4, 1, 102 }
     313             :         },
     314             :         [IEEE80211_MODE_11A] = {
     315             :                 [EDCA_AC_BK] = { 4, 10, 7,   0 },
     316             :                 [EDCA_AC_BE] = { 4,  6, 3,   0 },
     317             :                 [EDCA_AC_VI] = { 3,  4, 1,  94 },
     318             :                 [EDCA_AC_VO] = { 2,  3, 1,  47 }
     319             :         },
     320             :         [IEEE80211_MODE_11G] = {
     321             :                 [EDCA_AC_BK] = { 4, 10, 7,   0 },
     322             :                 [EDCA_AC_BE] = { 4,  6, 3,   0 },
     323             :                 [EDCA_AC_VI] = { 3,  4, 1,  94 },
     324             :                 [EDCA_AC_VO] = { 2,  3, 1,  47 }
     325             :         },
     326             :         [IEEE80211_MODE_11N] = {
     327             :                 [EDCA_AC_BK] = { 4, 10, 7,   0 },
     328             :                 [EDCA_AC_BE] = { 4,  6, 3,   0 },
     329             :                 [EDCA_AC_VI] = { 3,  4, 1,  94 },
     330             :                 [EDCA_AC_VO] = { 2,  3, 1,  47 }
     331             :         },
     332             : };
     333             : #endif  /* IEEE80211_STA_ONLY */
     334             : 
     335             : /*
     336             :  * Return the EDCA Access Category to be used for transmitting a frame with
     337             :  * user-priority `up'.
     338             :  */
     339             : enum ieee80211_edca_ac
     340           0 : ieee80211_up_to_ac(struct ieee80211com *ic, int up)
     341             : {
     342             :         /* see Table 9-1 */
     343             :         static const enum ieee80211_edca_ac up_to_ac[] = {
     344             :                 EDCA_AC_BE,     /* BE */
     345             :                 EDCA_AC_BK,     /* BK */
     346             :                 EDCA_AC_BK,     /* -- */
     347             :                 EDCA_AC_BE,     /* EE */
     348             :                 EDCA_AC_VI,     /* CL */
     349             :                 EDCA_AC_VI,     /* VI */
     350             :                 EDCA_AC_VO,     /* VO */
     351             :                 EDCA_AC_VO      /* NC */
     352             :         };
     353             :         enum ieee80211_edca_ac ac;
     354             : 
     355           0 :         ac = (up <= 7) ? up_to_ac[up] : EDCA_AC_BE;
     356             : 
     357             : #ifndef IEEE80211_STA_ONLY
     358           0 :         if (ic->ic_opmode == IEEE80211_M_HOSTAP)
     359           0 :                 return ac;
     360             : #endif
     361             :         /*
     362             :          * We do not support the admission control procedure defined in
     363             :          * IEEE Std 802.11-2012 section 9.19.4.2.3. The spec says that
     364             :          * non-AP QSTAs that don't support this procedure shall use EDCA
     365             :          * parameters of a lower priority AC that does not require
     366             :          * admission control.
     367             :          */
     368           0 :         while (ac != EDCA_AC_BK && ic->ic_edca_ac[ac].ac_acm) {
     369           0 :                 switch (ac) {
     370             :                 case EDCA_AC_BK:
     371             :                         /* can't get there */
     372             :                         break;
     373             :                 case EDCA_AC_BE:
     374             :                         /* BE shouldn't require admission control */
     375             :                         ac = EDCA_AC_BK;
     376           0 :                         break;
     377             :                 case EDCA_AC_VI:
     378             :                         ac = EDCA_AC_BE;
     379           0 :                         break;
     380             :                 case EDCA_AC_VO:
     381             :                         ac = EDCA_AC_VI;
     382           0 :                         break;
     383             :                 }
     384             :         }
     385           0 :         return ac;
     386           0 : }
     387             : 
     388             : /*
     389             :  * Get mbuf's user-priority: if mbuf is not VLAN tagged, select user-priority
     390             :  * based on the DSCP (Differentiated Services Codepoint) field.
     391             :  */
     392             : int
     393           0 : ieee80211_classify(struct ieee80211com *ic, struct mbuf *m)
     394             : {
     395             :         struct ether_header *eh;
     396             :         u_int8_t ds_field;
     397             : #if NVLAN > 0
     398           0 :         if (m->m_flags & M_VLANTAG)      /* use VLAN 802.1D user-priority */
     399           0 :                 return EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
     400             : #endif
     401           0 :         eh = mtod(m, struct ether_header *);
     402           0 :         if (eh->ether_type == htons(ETHERTYPE_IP)) {
     403           0 :                 struct ip *ip = (struct ip *)&eh[1];
     404           0 :                 if (ip->ip_v != 4)
     405           0 :                         return 0;
     406           0 :                 ds_field = ip->ip_tos;
     407           0 :         }
     408             : #ifdef INET6
     409           0 :         else if (eh->ether_type == htons(ETHERTYPE_IPV6)) {
     410           0 :                 struct ip6_hdr *ip6 = (struct ip6_hdr *)&eh[1];
     411             :                 u_int32_t flowlabel;
     412             : 
     413           0 :                 flowlabel = ntohl(ip6->ip6_flow);
     414           0 :                 if ((flowlabel >> 28) != 6)
     415           0 :                         return 0;
     416           0 :                 ds_field = (flowlabel >> 20) & 0xff;
     417           0 :         }
     418             : #endif  /* INET6 */
     419             :         else    /* neither IPv4 nor IPv6 */
     420           0 :                 return 0;
     421             : 
     422             :         /*
     423             :          * Map Differentiated Services Codepoint field (see RFC2474).
     424             :          * Preserves backward compatibility with IP Precedence field.
     425             :          */
     426           0 :         switch (ds_field & 0xfc) {
     427             :         case IPTOS_PREC_PRIORITY:
     428           0 :                 return 2;
     429             :         case IPTOS_PREC_IMMEDIATE:
     430           0 :                 return 1;
     431             :         case IPTOS_PREC_FLASH:
     432           0 :                 return 3;
     433             :         case IPTOS_PREC_FLASHOVERRIDE:
     434           0 :                 return 4;
     435             :         case IPTOS_PREC_CRITIC_ECP:
     436           0 :                 return 5;
     437             :         case IPTOS_PREC_INTERNETCONTROL:
     438           0 :                 return 6;
     439             :         case IPTOS_PREC_NETCONTROL:
     440           0 :                 return 7;
     441             :         }
     442           0 :         return 0;       /* default to Best-Effort */
     443           0 : }
     444             : 
     445             : /*
     446             :  * Encapsulate an outbound data frame.  The mbuf chain is updated and
     447             :  * a reference to the destination node is returned.  If an error is
     448             :  * encountered NULL is returned and the node reference will also be NULL.
     449             :  *
     450             :  * NB: The caller is responsible for free'ing a returned node reference.
     451             :  *     The convention is ic_bss is not reference counted; the caller must
     452             :  *     maintain that.
     453             :  */
     454             : struct mbuf *
     455           0 : ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
     456             : {
     457           0 :         struct ieee80211com *ic = (void *)ifp;
     458           0 :         struct ether_header eh;
     459             :         struct ieee80211_frame *wh;
     460             :         struct ieee80211_node *ni = NULL;
     461             :         struct llc *llc;
     462             :         struct m_tag *mtag;
     463             :         u_int8_t *addr;
     464             :         u_int dlt, hdrlen;
     465             :         int addqos, tid;
     466             : 
     467             :         /* Handle raw frames if mbuf is tagged as 802.11 */
     468           0 :         if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
     469           0 :                 dlt = *(u_int *)(mtag + 1);
     470             : 
     471           0 :                 if (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO))
     472             :                         goto fallback;
     473             : 
     474           0 :                 wh = mtod(m, struct ieee80211_frame *);
     475           0 :                 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
     476             :                 case IEEE80211_FC1_DIR_NODS:
     477             :                 case IEEE80211_FC1_DIR_FROMDS:
     478           0 :                         addr = wh->i_addr1;
     479           0 :                         break;
     480             :                 case IEEE80211_FC1_DIR_DSTODS:
     481             :                 case IEEE80211_FC1_DIR_TODS:
     482           0 :                         addr = wh->i_addr3;
     483           0 :                         break;
     484             :                 default:
     485             :                         goto bad;
     486             :                 }
     487             : 
     488           0 :                 ni = ieee80211_find_txnode(ic, addr);
     489           0 :                 if (ni == NULL)
     490           0 :                         ni = ieee80211_ref_node(ic->ic_bss);
     491           0 :                 if (ni == NULL) {
     492           0 :                         printf("%s: no node for dst %s, "
     493           0 :                             "discard raw tx frame\n", ifp->if_xname,
     494           0 :                             ether_sprintf(addr));
     495           0 :                         ic->ic_stats.is_tx_nonode++;
     496           0 :                         goto bad;
     497             :                 }
     498           0 :                 ni->ni_inact = 0;
     499             : 
     500           0 :                 *pni = ni;
     501           0 :                 return (m);
     502             :         }
     503             : 
     504             :  fallback:
     505           0 :         if (m->m_len < sizeof(struct ether_header)) {
     506           0 :                 m = m_pullup(m, sizeof(struct ether_header));
     507           0 :                 if (m == NULL) {
     508           0 :                         ic->ic_stats.is_tx_nombuf++;
     509           0 :                         goto bad;
     510             :                 }
     511             :         }
     512           0 :         memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
     513             : 
     514           0 :         ni = ieee80211_find_txnode(ic, eh.ether_dhost);
     515           0 :         if (ni == NULL) {
     516             :                 DPRINTF(("no node for dst %s, discard frame\n",
     517             :                     ether_sprintf(eh.ether_dhost)));
     518           0 :                 ic->ic_stats.is_tx_nonode++;
     519           0 :                 goto bad;
     520             :         }
     521             : 
     522           0 :         if ((ic->ic_flags & IEEE80211_F_RSNON) &&
     523           0 :             !ni->ni_port_valid &&
     524           0 :             eh.ether_type != htons(ETHERTYPE_PAE)) {
     525             :                 DPRINTF(("port not valid: %s\n",
     526             :                     ether_sprintf(eh.ether_dhost)));
     527           0 :                 ic->ic_stats.is_tx_noauth++;
     528           0 :                 goto bad;
     529             :         }
     530             : 
     531           0 :         if ((ic->ic_flags & IEEE80211_F_COUNTERM) &&
     532             :             ni->ni_rsncipher == IEEE80211_CIPHER_TKIP)
     533             :                 /* XXX TKIP countermeasures! */;
     534             : 
     535           0 :         ni->ni_inact = 0;
     536             : 
     537           0 :         if ((ic->ic_flags & IEEE80211_F_QOS) &&
     538           0 :             (ni->ni_flags & IEEE80211_NODE_QOS) &&
     539             :             /* do not QoS-encapsulate EAPOL frames */
     540           0 :             eh.ether_type != htons(ETHERTYPE_PAE)) {
     541           0 :                 tid = ieee80211_classify(ic, m);
     542             :                 hdrlen = sizeof(struct ieee80211_qosframe);
     543             :                 addqos = 1;
     544           0 :         } else {
     545             :                 hdrlen = sizeof(struct ieee80211_frame);
     546             :                 addqos = 0;
     547             :         }
     548           0 :         m_adj(m, sizeof(struct ether_header) - LLC_SNAPFRAMELEN);
     549           0 :         llc = mtod(m, struct llc *);
     550           0 :         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
     551           0 :         llc->llc_control = LLC_UI;
     552           0 :         llc->llc_snap.org_code[0] = 0;
     553           0 :         llc->llc_snap.org_code[1] = 0;
     554           0 :         llc->llc_snap.org_code[2] = 0;
     555           0 :         llc->llc_snap.ether_type = eh.ether_type;
     556           0 :         M_PREPEND(m, hdrlen, M_DONTWAIT);
     557           0 :         if (m == NULL) {
     558           0 :                 ic->ic_stats.is_tx_nombuf++;
     559           0 :                 goto bad;
     560             :         }
     561           0 :         wh = mtod(m, struct ieee80211_frame *);
     562           0 :         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
     563           0 :         *(u_int16_t *)&wh->i_dur[0] = 0;
     564           0 :         if (addqos) {
     565             :                 struct ieee80211_qosframe *qwh =
     566           0 :                     (struct ieee80211_qosframe *)wh;
     567           0 :                 u_int16_t qos = tid;
     568             : 
     569           0 :                 if (ic->ic_tid_noack & (1 << tid))
     570           0 :                         qos |= IEEE80211_QOS_ACK_POLICY_NOACK;
     571           0 :                 else if (ni->ni_tx_ba[tid].ba_state == IEEE80211_BA_AGREED)
     572           0 :                         qos |= IEEE80211_QOS_ACK_POLICY_BA;
     573           0 :                 qwh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;
     574           0 :                 *(u_int16_t *)qwh->i_qos = htole16(qos);
     575           0 :                 *(u_int16_t *)qwh->i_seq =
     576           0 :                     htole16(ni->ni_qos_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
     577           0 :                 ni->ni_qos_txseqs[tid]++;
     578           0 :         } else {
     579           0 :                 *(u_int16_t *)&wh->i_seq[0] =
     580           0 :                     htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
     581           0 :                 ni->ni_txseq++;
     582             :         }
     583           0 :         switch (ic->ic_opmode) {
     584             :         case IEEE80211_M_STA:
     585           0 :                 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
     586           0 :                 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
     587           0 :                 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
     588           0 :                 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
     589           0 :                 break;
     590             : #ifndef IEEE80211_STA_ONLY
     591             :         case IEEE80211_M_IBSS:
     592             :         case IEEE80211_M_AHDEMO:
     593           0 :                 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
     594           0 :                 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
     595           0 :                 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
     596           0 :                 IEEE80211_ADDR_COPY(wh->i_addr3, ic->ic_bss->ni_bssid);
     597           0 :                 break;
     598             :         case IEEE80211_M_HOSTAP:
     599           0 :                 wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
     600           0 :                 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
     601           0 :                 IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
     602           0 :                 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
     603           0 :                 break;
     604             : #endif
     605             :         default:
     606             :                 /* should not get there */
     607             :                 goto bad;
     608             :         }
     609             : 
     610           0 :         if ((ic->ic_flags & IEEE80211_F_WEPON) ||
     611           0 :             ((ic->ic_flags & IEEE80211_F_RSNON) &&
     612           0 :              (ni->ni_flags & IEEE80211_NODE_TXPROT)))
     613           0 :                 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
     614             : 
     615             : #ifndef IEEE80211_STA_ONLY
     616           0 :         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
     617           0 :             ieee80211_pwrsave(ic, m, ni) != 0) {
     618           0 :                 *pni = NULL;
     619           0 :                 return NULL;
     620             :         }
     621             : #endif
     622           0 :         *pni = ni;
     623           0 :         return m;
     624             : bad:
     625           0 :         m_freem(m);
     626           0 :         if (ni != NULL)
     627           0 :                 ieee80211_release_node(ic, ni);
     628           0 :         *pni = NULL;
     629           0 :         return NULL;
     630           0 : }
     631             : 
     632             : /*
     633             :  * Add a Capability Information field to a frame (see 7.3.1.4).
     634             :  */
     635             : u_int8_t *
     636           0 : ieee80211_add_capinfo(u_int8_t *frm, struct ieee80211com *ic,
     637             :     const struct ieee80211_node *ni)
     638             : {
     639             :         u_int16_t capinfo;
     640             : 
     641             : #ifndef IEEE80211_STA_ONLY
     642           0 :         if (ic->ic_opmode == IEEE80211_M_IBSS)
     643           0 :                 capinfo = IEEE80211_CAPINFO_IBSS;
     644           0 :         else if (ic->ic_opmode == IEEE80211_M_HOSTAP)
     645           0 :                 capinfo = IEEE80211_CAPINFO_ESS;
     646             :         else
     647             : #endif
     648             :                 capinfo = 0;
     649             : #ifndef IEEE80211_STA_ONLY
     650           0 :         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
     651           0 :             (ic->ic_flags & (IEEE80211_F_WEPON | IEEE80211_F_RSNON)))
     652           0 :                 capinfo |= IEEE80211_CAPINFO_PRIVACY;
     653             : #endif
     654             :         /* NB: some 11a AP's reject the request when short preamble is set */
     655           0 :         if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
     656           0 :             IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
     657           0 :                 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
     658           0 :         if (ic->ic_flags & IEEE80211_F_SHSLOT)
     659           0 :                 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
     660           0 :         LE_WRITE_2(frm, capinfo);
     661           0 :         return frm + 2;
     662             : }
     663             : 
     664             : /*
     665             :  * Add an SSID element to a frame (see 7.3.2.1).
     666             :  */
     667             : u_int8_t *
     668           0 : ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
     669             : {
     670           0 :         *frm++ = IEEE80211_ELEMID_SSID;
     671           0 :         *frm++ = len;
     672           0 :         memcpy(frm, ssid, len);
     673           0 :         return frm + len;
     674             : }
     675             : 
     676             : /*
     677             :  * Add a supported rates element to a frame (see 7.3.2.2).
     678             :  */
     679             : u_int8_t *
     680           0 : ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs)
     681             : {
     682             :         int nrates;
     683             : 
     684           0 :         *frm++ = IEEE80211_ELEMID_RATES;
     685           0 :         nrates = min(rs->rs_nrates, IEEE80211_RATE_SIZE);
     686           0 :         *frm++ = nrates;
     687           0 :         memcpy(frm, rs->rs_rates, nrates);
     688           0 :         return frm + nrates;
     689             : }
     690             : 
     691             : #ifndef IEEE80211_STA_ONLY
     692             : /*
     693             :  * Add a DS Parameter Set element to a frame (see 7.3.2.4).
     694             :  */
     695             : u_int8_t *
     696           0 : ieee80211_add_ds_params(u_int8_t *frm, struct ieee80211com *ic,
     697             :     const struct ieee80211_node *ni)
     698             : {
     699           0 :         *frm++ = IEEE80211_ELEMID_DSPARMS;
     700           0 :         *frm++ = 1;
     701           0 :         *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
     702           0 :         return frm;
     703             : }
     704             : 
     705             : /*
     706             :  * Add a TIM element to a frame (see 7.3.2.6 and Annex L).
     707             :  */
     708             : u_int8_t *
     709           0 : ieee80211_add_tim(u_int8_t *frm, struct ieee80211com *ic)
     710             : {
     711             :         u_int i, offset = 0, len;
     712             : 
     713             :         /* find first non-zero octet in the virtual bit map */
     714           0 :         for (i = 0; i < ic->ic_tim_len && ic->ic_tim_bitmap[i] == 0; i++);
     715             : 
     716             :         /* clear the lsb as it is reserved for the broadcast indication bit */
     717           0 :         if (i < ic->ic_tim_len)
     718           0 :                 offset = i & ~1;
     719             : 
     720             :         /* find last non-zero octet in the virtual bit map */
     721           0 :         for (i = ic->ic_tim_len - 1; i > 0 && ic->ic_tim_bitmap[i] == 0; i--);
     722             : 
     723           0 :         len = i - offset + 1;
     724             : 
     725           0 :         *frm++ = IEEE80211_ELEMID_TIM;
     726           0 :         *frm++ = len + 3;               /* length */
     727           0 :         *frm++ = ic->ic_dtim_count;  /* DTIM count */
     728           0 :         *frm++ = ic->ic_dtim_period; /* DTIM period */
     729             : 
     730             :         /* Bitmap Control */
     731           0 :         *frm = offset;
     732             :         /* set broadcast/multicast indication bit if necessary */
     733           0 :         if (ic->ic_dtim_count == 0 && ic->ic_tim_mcast_pending)
     734           0 :                 *frm |= 0x01;
     735           0 :         frm++;
     736             : 
     737             :         /* Partial Virtual Bitmap */
     738           0 :         memcpy(frm, &ic->ic_tim_bitmap[offset], len);
     739           0 :         return frm + len;
     740             : }
     741             : 
     742             : /*
     743             :  * Add an IBSS Parameter Set element to a frame (see 7.3.2.7).
     744             :  */
     745             : u_int8_t *
     746           0 : ieee80211_add_ibss_params(u_int8_t *frm, const struct ieee80211_node *ni)
     747             : {
     748           0 :         *frm++ = IEEE80211_ELEMID_IBSSPARMS;
     749           0 :         *frm++ = 2;
     750           0 :         LE_WRITE_2(frm, 0);     /* TODO: ATIM window */
     751           0 :         return frm + 2;
     752             : }
     753             : 
     754             : /*
     755             :  * Add an EDCA Parameter Set element to a frame (see 7.3.2.29).
     756             :  */
     757             : u_int8_t *
     758           0 : ieee80211_add_edca_params(u_int8_t *frm, struct ieee80211com *ic)
     759             : {
     760             :         const struct ieee80211_edca_ac_params *edca;
     761             :         int aci;
     762             : 
     763           0 :         *frm++ = IEEE80211_ELEMID_EDCAPARMS;
     764           0 :         *frm++ = 18;    /* length */
     765           0 :         *frm++ = 0;     /* QoS Info */
     766           0 :         *frm++ = 0;     /* reserved */
     767             : 
     768             :         /* setup AC Parameter Records */
     769           0 :         edca = ieee80211_edca_table[ic->ic_curmode];
     770           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++) {
     771           0 :                 const struct ieee80211_edca_ac_params *ac = &edca[aci];
     772             : 
     773           0 :                 *frm++ = (aci << 5) | ((ac->ac_acm & 0x1) << 4) |
     774           0 :                          (ac->ac_aifsn & 0xf);
     775           0 :                 *frm++ = (ac->ac_ecwmax << 4) |
     776           0 :                          (ac->ac_ecwmin & 0xf);
     777           0 :                 LE_WRITE_2(frm, ac->ac_txoplimit); frm += 2;
     778             :         }
     779           0 :         return frm;
     780             : }
     781             : 
     782             : /*
     783             :  * Add an ERP element to a frame (see 7.3.2.13).
     784             :  */
     785             : u_int8_t *
     786           0 : ieee80211_add_erp(u_int8_t *frm, struct ieee80211com *ic)
     787             : {
     788             :         u_int8_t erp;
     789           0 :         int nonerpsta = 0;
     790             : 
     791           0 :         *frm++ = IEEE80211_ELEMID_ERP;
     792           0 :         *frm++ = 1;
     793             :         erp = 0;
     794             :         /*
     795             :          * The NonERP_Present bit shall be set to 1 when a NonERP STA
     796             :          * is associated with the BSS.
     797             :          */
     798           0 :         ieee80211_iterate_nodes(ic, ieee80211_count_nonerpsta, &nonerpsta);
     799           0 :         if (nonerpsta != 0)
     800           0 :                 erp |= IEEE80211_ERP_NON_ERP_PRESENT;
     801             :         /*
     802             :          * If one or more NonERP STAs are associated in the BSS, the
     803             :          * Use_Protection bit shall be set to 1 in transmitted ERP
     804             :          * Information Elements.
     805             :          */
     806           0 :         if (ic->ic_flags & IEEE80211_F_USEPROT)
     807           0 :                 erp |= IEEE80211_ERP_USE_PROTECTION;
     808             :         /*
     809             :          * The Barker_Preamble_Mode bit shall be set to 1 by the ERP
     810             :          * Information Element sender if one or more associated NonERP
     811             :          * STAs are not short preamble capable.
     812             :          */
     813           0 :         if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE))
     814           0 :                 erp |= IEEE80211_ERP_BARKER_MODE;
     815           0 :         *frm++ = erp;
     816           0 :         return frm;
     817           0 : }
     818             : #endif  /* IEEE80211_STA_ONLY */
     819             : 
     820             : /*
     821             :  * Add a QoS Capability element to a frame (see 7.3.2.35).
     822             :  */
     823             : u_int8_t *
     824           0 : ieee80211_add_qos_capability(u_int8_t *frm, struct ieee80211com *ic)
     825             : {
     826           0 :         *frm++ = IEEE80211_ELEMID_QOS_CAP;
     827           0 :         *frm++ = 1;
     828           0 :         *frm++ = 0;     /* QoS Info */
     829           0 :         return frm;
     830             : }
     831             : 
     832             : /*
     833             :  * Add a Wifi-Alliance WME (aka WMM) info element to a frame.
     834             :  * WME is a requirement for Wifi-Alliance compliance and some
     835             :  * 11n APs will not negotiate HT if this element is missing.
     836             :  */
     837             : uint8_t *
     838           0 : ieee80211_add_wme_info(uint8_t *frm, struct ieee80211com *ic)
     839             : {
     840           0 :         *frm++ = IEEE80211_ELEMID_VENDOR;
     841           0 :         *frm++ = 7;
     842           0 :         memcpy(frm, MICROSOFT_OUI, 3); frm += 3;
     843           0 :         *frm++ = 2; /* OUI type */
     844           0 :         *frm++ = 0; /* OUI subtype */
     845           0 :         *frm++ = 1; /* version */
     846           0 :         *frm++ = 0; /* info */
     847             : 
     848           0 :         return frm;
     849             : }
     850             : 
     851             : #ifndef IEEE80211_STA_ONLY
     852             : /*
     853             :  * Add a Wifi-Alliance WMM (aka WME) parameter element to a frame.
     854             :  */
     855             : uint8_t *
     856           0 : ieee80211_add_wme_param(uint8_t *frm, struct ieee80211com *ic)
     857             : {
     858             :         const struct ieee80211_edca_ac_params *edca;
     859             :         int aci;
     860             : 
     861           0 :         *frm++ = IEEE80211_ELEMID_VENDOR;
     862           0 :         *frm++ = 24;
     863           0 :         memcpy(frm, MICROSOFT_OUI, 3); frm += 3;
     864           0 :         *frm++ = 2; /* OUI type */
     865           0 :         *frm++ = 1; /* OUI subtype */
     866           0 :         *frm++ = 1; /* version */
     867           0 :         *frm++ = 0; /* info */
     868           0 :         *frm++ = 0; /* reserved */
     869             : 
     870             :         /* setup AC Parameter Records */
     871           0 :         edca = ieee80211_edca_table[ic->ic_curmode];
     872           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++) {
     873           0 :                 const struct ieee80211_edca_ac_params *ac = &edca[aci];
     874             : 
     875           0 :                 *frm++ = (aci << 5) | ((ac->ac_acm & 0x1) << 4) |
     876           0 :                          (ac->ac_aifsn & 0xf);
     877           0 :                 *frm++ = (ac->ac_ecwmax << 4) |
     878           0 :                          (ac->ac_ecwmin & 0xf);
     879           0 :                 LE_WRITE_2(frm, ac->ac_txoplimit); frm += 2;
     880             :         }
     881             : 
     882           0 :         return frm;
     883             : }
     884             : #endif
     885             : 
     886             : /*
     887             :  * Add an RSN element to a frame (see 802.11-2012 8.4.2.27)
     888             :  */
     889             : u_int8_t *
     890           0 : ieee80211_add_rsn_body(u_int8_t *frm, struct ieee80211com *ic,
     891             :     const struct ieee80211_node *ni, int wpa)
     892             : {
     893           0 :         const u_int8_t *oui = wpa ? MICROSOFT_OUI : IEEE80211_OUI;
     894             :         u_int8_t *pcount;
     895             :         u_int16_t count;
     896             : 
     897             :         /* write Version field */
     898           0 :         LE_WRITE_2(frm, 1); frm += 2;
     899             : 
     900             :         /* write Group Data Cipher Suite field (see 802.11-2012 Table 8-99) */
     901           0 :         memcpy(frm, oui, 3); frm += 3;
     902           0 :         switch (ni->ni_rsngroupcipher) {
     903             :         case IEEE80211_CIPHER_WEP40:
     904           0 :                 *frm++ = 1;
     905           0 :                 break;
     906             :         case IEEE80211_CIPHER_TKIP:
     907           0 :                 *frm++ = 2;
     908           0 :                 break;
     909             :         case IEEE80211_CIPHER_CCMP:
     910           0 :                 *frm++ = 4;
     911           0 :                 break;
     912             :         case IEEE80211_CIPHER_WEP104:
     913           0 :                 *frm++ = 5;
     914           0 :                 break;
     915             :         default:
     916             :                 /* can't get there */
     917           0 :                 panic("invalid group data cipher!");
     918             :         }
     919             : 
     920           0 :         pcount = frm; frm += 2;
     921             :         count = 0;
     922             :         /* write Pairwise Cipher Suite List */
     923           0 :         if (ni->ni_rsnciphers & IEEE80211_CIPHER_USEGROUP) {
     924           0 :                 memcpy(frm, oui, 3); frm += 3;
     925           0 :                 *frm++ = 0;
     926             :                 count++;
     927           0 :         }
     928           0 :         if (ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP) {
     929           0 :                 memcpy(frm, oui, 3); frm += 3;
     930           0 :                 *frm++ = 2;
     931           0 :                 count++;
     932           0 :         }
     933           0 :         if (ni->ni_rsnciphers & IEEE80211_CIPHER_CCMP) {
     934           0 :                 memcpy(frm, oui, 3); frm += 3;
     935           0 :                 *frm++ = 4;
     936           0 :                 count++;
     937           0 :         }
     938             :         /* write Pairwise Cipher Suite Count field */
     939           0 :         LE_WRITE_2(pcount, count);
     940             : 
     941           0 :         pcount = frm; frm += 2;
     942             :         count = 0;
     943             :         /* write AKM Suite List (see Table 20dc) */
     944           0 :         if (ni->ni_rsnakms & IEEE80211_AKM_8021X) {
     945           0 :                 memcpy(frm, oui, 3); frm += 3;
     946           0 :                 *frm++ = 1;
     947             :                 count++;
     948           0 :         }
     949           0 :         if (ni->ni_rsnakms & IEEE80211_AKM_PSK) {
     950           0 :                 memcpy(frm, oui, 3); frm += 3;
     951           0 :                 *frm++ = 2;
     952           0 :                 count++;
     953           0 :         }
     954           0 :         if (!wpa && (ni->ni_rsnakms & IEEE80211_AKM_SHA256_8021X)) {
     955           0 :                 memcpy(frm, oui, 3); frm += 3;
     956           0 :                 *frm++ = 5;
     957           0 :                 count++;
     958           0 :         }
     959           0 :         if (!wpa && (ni->ni_rsnakms & IEEE80211_AKM_SHA256_PSK)) {
     960           0 :                 memcpy(frm, oui, 3); frm += 3;
     961           0 :                 *frm++ = 6;
     962           0 :                 count++;
     963           0 :         }
     964             :         /* write AKM Suite List Count field */
     965           0 :         LE_WRITE_2(pcount, count);
     966             : 
     967           0 :         if (wpa)
     968           0 :                 return frm;
     969             : 
     970             :         /* write RSN Capabilities field */
     971           0 :         LE_WRITE_2(frm, ni->ni_rsncaps); frm += 2;
     972             : 
     973           0 :         if (ni->ni_flags & IEEE80211_NODE_PMKID) {
     974             :                 /* write PMKID Count field */
     975           0 :                 LE_WRITE_2(frm, 1); frm += 2;
     976             :                 /* write PMKID List (only 1) */
     977           0 :                 memcpy(frm, ni->ni_pmkid, IEEE80211_PMKID_LEN);
     978           0 :                 frm += IEEE80211_PMKID_LEN;
     979           0 :         }
     980             : 
     981           0 :         if (!(ic->ic_caps & IEEE80211_C_MFP))
     982           0 :                 return frm;
     983             : 
     984           0 :         if ((ni->ni_flags & IEEE80211_NODE_PMKID) == 0) {
     985             :                 /* no PMKID (PMKID Count=0) */
     986           0 :                 LE_WRITE_2(frm, 0); frm += 2;
     987           0 :         }
     988             : 
     989             :         /* write Group Integrity Cipher Suite field */
     990           0 :         memcpy(frm, oui, 3); frm += 3;
     991           0 :         switch (ic->ic_rsngroupmgmtcipher) {
     992             :         case IEEE80211_CIPHER_BIP:
     993           0 :                 *frm++ = 6;
     994             :                 break;
     995             :         default:
     996             :                 /* can't get there */
     997           0 :                 panic("invalid integrity group cipher!");
     998             :         }
     999           0 :         return frm;
    1000           0 : }
    1001             : 
    1002             : u_int8_t *
    1003           0 : ieee80211_add_rsn(u_int8_t *frm, struct ieee80211com *ic,
    1004             :     const struct ieee80211_node *ni)
    1005             : {
    1006             :         u_int8_t *plen;
    1007             : 
    1008           0 :         *frm++ = IEEE80211_ELEMID_RSN;
    1009           0 :         plen = frm++;   /* length filled in later */
    1010           0 :         frm = ieee80211_add_rsn_body(frm, ic, ni, 0);
    1011             : 
    1012             :         /* write length field */
    1013           0 :         *plen = frm - plen - 1;
    1014           0 :         return frm;
    1015             : }
    1016             : 
    1017             : /*
    1018             :  * Add a vendor-specific WPA element to a frame.
    1019             :  * This is required for compatibility with Wi-Fi Alliance WPA.
    1020             :  */
    1021             : u_int8_t *
    1022           0 : ieee80211_add_wpa(u_int8_t *frm, struct ieee80211com *ic,
    1023             :     const struct ieee80211_node *ni)
    1024             : {
    1025             :         u_int8_t *plen;
    1026             : 
    1027           0 :         *frm++ = IEEE80211_ELEMID_VENDOR;
    1028           0 :         plen = frm++;   /* length filled in later */
    1029           0 :         memcpy(frm, MICROSOFT_OUI, 3); frm += 3;
    1030           0 :         *frm++ = 1;     /* WPA */
    1031           0 :         frm = ieee80211_add_rsn_body(frm, ic, ni, 1);
    1032             : 
    1033             :         /* write length field */
    1034           0 :         *plen = frm - plen - 1;
    1035           0 :         return frm;
    1036             : }
    1037             : 
    1038             : /*
    1039             :  * Add an extended supported rates element to a frame (see 7.3.2.14).
    1040             :  */
    1041             : u_int8_t *
    1042           0 : ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs)
    1043             : {
    1044             :         int nrates;
    1045             : 
    1046           0 :         KASSERT(rs->rs_nrates > IEEE80211_RATE_SIZE);
    1047             : 
    1048           0 :         *frm++ = IEEE80211_ELEMID_XRATES;
    1049           0 :         nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
    1050           0 :         *frm++ = nrates;
    1051           0 :         memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
    1052           0 :         return frm + nrates;
    1053             : }
    1054             : 
    1055             : /*
    1056             :  * Add an HT Capabilities element to a frame (see 7.3.2.57).
    1057             :  */
    1058             : u_int8_t *
    1059           0 : ieee80211_add_htcaps(u_int8_t *frm, struct ieee80211com *ic)
    1060             : {
    1061           0 :         *frm++ = IEEE80211_ELEMID_HTCAPS;
    1062           0 :         *frm++ = 26;
    1063           0 :         LE_WRITE_2(frm, ic->ic_htcaps); frm += 2;
    1064           0 :         *frm++ = ic->ic_ampdu_params;
    1065           0 :         memcpy(frm, ic->ic_sup_mcs, 10); frm += 10;
    1066           0 :         LE_WRITE_2(frm, (ic->ic_max_rxrate & IEEE80211_MCS_RX_RATE_HIGH));
    1067           0 :         frm += 2;
    1068           0 :         *frm++ = ic->ic_tx_mcs_set;
    1069           0 :         *frm++ = 0; /* reserved */
    1070           0 :         *frm++ = 0; /* reserved */
    1071           0 :         *frm++ = 0; /* reserved */
    1072           0 :         LE_WRITE_2(frm, ic->ic_htxcaps); frm += 2;
    1073           0 :         LE_WRITE_4(frm, ic->ic_txbfcaps); frm += 4;
    1074           0 :         *frm++ = ic->ic_aselcaps;
    1075           0 :         return frm;
    1076             : }
    1077             : 
    1078             : #ifndef IEEE80211_STA_ONLY
    1079             : /*
    1080             :  * Add an HT Operation element to a frame (see 7.3.2.58).
    1081             :  */
    1082             : u_int8_t *
    1083           0 : ieee80211_add_htop(u_int8_t *frm, struct ieee80211com *ic)
    1084             : {
    1085           0 :         *frm++ = IEEE80211_ELEMID_HTOP;
    1086           0 :         *frm++ = 22;
    1087           0 :         *frm++ = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
    1088           0 :         *frm++ = ic->ic_bss->ni_htop0;
    1089           0 :         LE_WRITE_2(frm, ic->ic_bss->ni_htop1); frm += 2;
    1090           0 :         LE_WRITE_2(frm, ic->ic_bss->ni_htop2); frm += 2;
    1091           0 :         memset(frm, 0, 16); frm += 16;
    1092           0 :         return frm;
    1093             : }
    1094             : #endif  /* !IEEE80211_STA_ONLY */
    1095             : 
    1096             : #ifndef IEEE80211_STA_ONLY
    1097             : /*
    1098             :  * Add a Timeout Interval element to a frame (see 7.3.2.49).
    1099             :  */
    1100             : u_int8_t *
    1101           0 : ieee80211_add_tie(u_int8_t *frm, u_int8_t type, u_int32_t value)
    1102             : {
    1103           0 :         *frm++ = IEEE80211_ELEMID_TIE;
    1104           0 :         *frm++ = 5;     /* length */
    1105           0 :         *frm++ = type;  /* Timeout Interval type */
    1106           0 :         LE_WRITE_4(frm, value);
    1107           0 :         return frm + 4;
    1108             : }
    1109             : #endif
    1110             : 
    1111             : struct mbuf *
    1112           0 : ieee80211_getmgmt(int flags, int type, u_int pktlen)
    1113             : {
    1114             :         struct mbuf *m;
    1115             : 
    1116             :         /* reserve space for 802.11 header */
    1117           0 :         pktlen += sizeof(struct ieee80211_frame);
    1118             : 
    1119           0 :         if (pktlen > MCLBYTES)
    1120           0 :                 panic("management frame too large: %u", pktlen);
    1121           0 :         MGETHDR(m, flags, type);
    1122           0 :         if (m == NULL)
    1123           0 :                 return NULL;
    1124           0 :         if (pktlen > MHLEN) {
    1125           0 :                 MCLGET(m, flags);
    1126           0 :                 if (!(m->m_flags & M_EXT))
    1127           0 :                         return m_free(m);
    1128             :         }
    1129           0 :         m->m_data += sizeof(struct ieee80211_frame);
    1130           0 :         return m;
    1131           0 : }
    1132             : 
    1133             : /*-
    1134             :  * Probe request frame format:
    1135             :  * [tlv] SSID
    1136             :  * [tlv] Supported rates
    1137             :  * [tlv] Extended Supported Rates (802.11g)
    1138             :  * [tlv] HT Capabilities (802.11n)
    1139             :  */
    1140             : struct mbuf *
    1141           0 : ieee80211_get_probe_req(struct ieee80211com *ic, struct ieee80211_node *ni)
    1142             : {
    1143             :         const struct ieee80211_rateset *rs =
    1144           0 :             &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
    1145             :         struct mbuf *m;
    1146             :         u_int8_t *frm;
    1147             : 
    1148           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
    1149           0 :             2 + ic->ic_des_esslen +
    1150           0 :             2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
    1151           0 :             ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
    1152           0 :                 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
    1153           0 :             ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 9 : 0));
    1154           0 :         if (m == NULL)
    1155           0 :                 return NULL;
    1156             : 
    1157           0 :         frm = mtod(m, u_int8_t *);
    1158           0 :         frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
    1159           0 :         frm = ieee80211_add_rates(frm, rs);
    1160           0 :         if (rs->rs_nrates > IEEE80211_RATE_SIZE)
    1161           0 :                 frm = ieee80211_add_xrates(frm, rs);
    1162           0 :         if (ic->ic_flags & IEEE80211_F_HTON) {
    1163           0 :                 frm = ieee80211_add_htcaps(frm, ic);
    1164           0 :                 frm = ieee80211_add_wme_info(frm, ic);
    1165           0 :         }
    1166             : 
    1167           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1168             : 
    1169           0 :         return m;
    1170           0 : }
    1171             : 
    1172             : #ifndef IEEE80211_STA_ONLY
    1173             : /*-
    1174             :  * Probe response frame format:
    1175             :  * [8]   Timestamp
    1176             :  * [2]   Beacon interval
    1177             :  * [2]   Capability
    1178             :  * [tlv] Service Set Identifier (SSID)
    1179             :  * [tlv] Supported rates
    1180             :  * [tlv] DS Parameter Set (802.11g)
    1181             :  * [tlv] ERP Information (802.11g)
    1182             :  * [tlv] Extended Supported Rates (802.11g)
    1183             :  * [tlv] RSN (802.11i)
    1184             :  * [tlv] EDCA Parameter Set (802.11e)
    1185             :  * [tlv] HT Capabilities (802.11n)
    1186             :  * [tlv] HT Operation (802.11n)
    1187             :  */
    1188             : struct mbuf *
    1189           0 : ieee80211_get_probe_resp(struct ieee80211com *ic, struct ieee80211_node *ni)
    1190             : {
    1191           0 :         const struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
    1192             :         struct mbuf *m;
    1193             :         u_int8_t *frm;
    1194             : 
    1195           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
    1196             :             8 + 2 + 2 +
    1197           0 :             2 + ni->ni_esslen +
    1198           0 :             2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
    1199           0 :             2 + 1 +
    1200           0 :             ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 + 2 : 0) +
    1201           0 :             ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +
    1202           0 :             ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
    1203           0 :                 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
    1204           0 :             (((ic->ic_flags & IEEE80211_F_RSNON) &&
    1205           0 :               (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?
    1206           0 :                 2 + IEEE80211_RSNIE_MAXLEN : 0) +
    1207           0 :             ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +
    1208           0 :             (((ic->ic_flags & IEEE80211_F_RSNON) &&
    1209           0 :               (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?
    1210           0 :                 2 + IEEE80211_WPAIE_MAXLEN : 0) +
    1211           0 :             ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));
    1212           0 :         if (m == NULL)
    1213           0 :                 return NULL;
    1214             : 
    1215           0 :         frm = mtod(m, u_int8_t *);
    1216           0 :         memset(frm, 0, 8); frm += 8;    /* timestamp is set by hardware */
    1217           0 :         LE_WRITE_2(frm, ic->ic_bss->ni_intval); frm += 2;
    1218           0 :         frm = ieee80211_add_capinfo(frm, ic, ni);
    1219           0 :         frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,
    1220           0 :             ic->ic_bss->ni_esslen);
    1221           0 :         frm = ieee80211_add_rates(frm, rs);
    1222           0 :         frm = ieee80211_add_ds_params(frm, ic, ni);
    1223           0 :         if (ic->ic_opmode == IEEE80211_M_IBSS)
    1224           0 :                 frm = ieee80211_add_ibss_params(frm, ni);
    1225           0 :         if (ic->ic_curmode == IEEE80211_MODE_11G)
    1226           0 :                 frm = ieee80211_add_erp(frm, ic);
    1227           0 :         if (rs->rs_nrates > IEEE80211_RATE_SIZE)
    1228           0 :                 frm = ieee80211_add_xrates(frm, rs);
    1229           0 :         if ((ic->ic_flags & IEEE80211_F_RSNON) &&
    1230           0 :             (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_RSN))
    1231           0 :                 frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
    1232           0 :         if (ic->ic_flags & IEEE80211_F_QOS)
    1233           0 :                 frm = ieee80211_add_edca_params(frm, ic);
    1234           0 :         if ((ic->ic_flags & IEEE80211_F_RSNON) &&
    1235           0 :             (ic->ic_bss->ni_rsnprotos & IEEE80211_PROTO_WPA))
    1236           0 :                 frm = ieee80211_add_wpa(frm, ic, ic->ic_bss);
    1237           0 :         if (ic->ic_flags & IEEE80211_F_HTON) {
    1238           0 :                 frm = ieee80211_add_htcaps(frm, ic);
    1239           0 :                 frm = ieee80211_add_htop(frm, ic);
    1240           0 :                 frm = ieee80211_add_wme_param(frm, ic);
    1241           0 :         }
    1242             : 
    1243           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1244             : 
    1245           0 :         return m;
    1246           0 : }
    1247             : #endif  /* IEEE80211_STA_ONLY */
    1248             : 
    1249             : /*-
    1250             :  * Authentication frame format:
    1251             :  * [2] Authentication algorithm number
    1252             :  * [2] Authentication transaction sequence number
    1253             :  * [2] Status code
    1254             :  */
    1255             : struct mbuf *
    1256           0 : ieee80211_get_auth(struct ieee80211com *ic, struct ieee80211_node *ni,
    1257             :     u_int16_t status, u_int16_t seq)
    1258             : {
    1259             :         struct mbuf *m;
    1260             :         u_int8_t *frm;
    1261             : 
    1262           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    1263           0 :         if (m == NULL)
    1264           0 :                 return NULL;
    1265           0 :         MH_ALIGN(m, 2 * 3);
    1266           0 :         m->m_pkthdr.len = m->m_len = 2 * 3;
    1267             : 
    1268           0 :         frm = mtod(m, u_int8_t *);
    1269           0 :         LE_WRITE_2(frm, IEEE80211_AUTH_ALG_OPEN); frm += 2;
    1270           0 :         LE_WRITE_2(frm, seq); frm += 2;
    1271           0 :         LE_WRITE_2(frm, status);
    1272             : 
    1273           0 :         return m;
    1274           0 : }
    1275             : 
    1276             : /*-
    1277             :  * Deauthentication frame format:
    1278             :  * [2] Reason code
    1279             :  */
    1280             : struct mbuf *
    1281           0 : ieee80211_get_deauth(struct ieee80211com *ic, struct ieee80211_node *ni,
    1282             :     u_int16_t reason)
    1283             : {
    1284             :         struct mbuf *m;
    1285             : 
    1286           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    1287           0 :         if (m == NULL)
    1288           0 :                 return NULL;
    1289           0 :         MH_ALIGN(m, 2);
    1290             : 
    1291           0 :         m->m_pkthdr.len = m->m_len = 2;
    1292           0 :         *mtod(m, u_int16_t *) = htole16(reason);
    1293             : 
    1294           0 :         return m;
    1295           0 : }
    1296             : 
    1297             : /*-
    1298             :  * (Re)Association request frame format:
    1299             :  * [2]   Capability information
    1300             :  * [2]   Listen interval
    1301             :  * [6*]  Current AP address (Reassociation only)
    1302             :  * [tlv] SSID
    1303             :  * [tlv] Supported rates
    1304             :  * [tlv] Extended Supported Rates (802.11g)
    1305             :  * [tlv] RSN (802.11i)
    1306             :  * [tlv] QoS Capability (802.11e)
    1307             :  * [tlv] HT Capabilities (802.11n)
    1308             :  */
    1309             : struct mbuf *
    1310           0 : ieee80211_get_assoc_req(struct ieee80211com *ic, struct ieee80211_node *ni,
    1311             :     int type)
    1312             : {
    1313           0 :         const struct ieee80211_rateset *rs = &ni->ni_rates;
    1314             :         struct mbuf *m;
    1315             :         u_int8_t *frm;
    1316             :         u_int16_t capinfo;
    1317             : 
    1318           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
    1319           0 :             2 + 2 +
    1320           0 :             ((type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) ?
    1321           0 :                 IEEE80211_ADDR_LEN : 0) +
    1322           0 :             2 + ni->ni_esslen +
    1323           0 :             2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
    1324           0 :             ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
    1325           0 :                 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
    1326           0 :             (((ic->ic_flags & IEEE80211_F_RSNON) &&
    1327           0 :               (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?
    1328           0 :                 2 + IEEE80211_RSNIE_MAXLEN : 0) +
    1329           0 :             ((ni->ni_flags & IEEE80211_NODE_QOS) ? 2 + 1 : 0) +
    1330           0 :             (((ic->ic_flags & IEEE80211_F_RSNON) &&
    1331           0 :               (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?
    1332           0 :                 2 + IEEE80211_WPAIE_MAXLEN : 0) +
    1333           0 :             ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 9 : 0));
    1334           0 :         if (m == NULL)
    1335           0 :                 return NULL;
    1336             : 
    1337           0 :         frm = mtod(m, u_int8_t *);
    1338             :         capinfo = IEEE80211_CAPINFO_ESS;
    1339           0 :         if (ic->ic_flags & IEEE80211_F_WEPON)
    1340           0 :                 capinfo |= IEEE80211_CAPINFO_PRIVACY;
    1341           0 :         if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
    1342           0 :             IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
    1343           0 :                 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
    1344           0 :         if (ic->ic_caps & IEEE80211_C_SHSLOT)
    1345           0 :                 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
    1346           0 :         LE_WRITE_2(frm, capinfo); frm += 2;
    1347           0 :         LE_WRITE_2(frm, ic->ic_lintval); frm += 2;
    1348           0 :         if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
    1349           0 :                 IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid);
    1350           0 :                 frm += IEEE80211_ADDR_LEN;
    1351           0 :         }
    1352           0 :         frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
    1353           0 :         frm = ieee80211_add_rates(frm, rs);
    1354           0 :         if (rs->rs_nrates > IEEE80211_RATE_SIZE)
    1355           0 :                 frm = ieee80211_add_xrates(frm, rs);
    1356           0 :         if ((ic->ic_flags & IEEE80211_F_RSNON) &&
    1357           0 :             (ni->ni_rsnprotos & IEEE80211_PROTO_RSN))
    1358           0 :                 frm = ieee80211_add_rsn(frm, ic, ni);
    1359           0 :         if (ni->ni_flags & IEEE80211_NODE_QOS)
    1360           0 :                 frm = ieee80211_add_qos_capability(frm, ic);
    1361           0 :         if ((ic->ic_flags & IEEE80211_F_RSNON) &&
    1362           0 :             (ni->ni_rsnprotos & IEEE80211_PROTO_WPA))
    1363           0 :                 frm = ieee80211_add_wpa(frm, ic, ni);
    1364           0 :         if (ic->ic_flags & IEEE80211_F_HTON) {
    1365           0 :                 frm = ieee80211_add_htcaps(frm, ic);
    1366           0 :                 frm = ieee80211_add_wme_info(frm, ic);
    1367           0 :         }
    1368             : 
    1369           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1370             : 
    1371           0 :         return m;
    1372           0 : }
    1373             : 
    1374             : #ifndef IEEE80211_STA_ONLY
    1375             : /*-
    1376             :  * (Re)Association response frame format:
    1377             :  * [2]   Capability information
    1378             :  * [2]   Status code
    1379             :  * [2]   Association ID (AID)
    1380             :  * [tlv] Supported rates
    1381             :  * [tlv] Extended Supported Rates (802.11g)
    1382             :  * [tlv] EDCA Parameter Set (802.11e)
    1383             :  * [tlv] Timeout Interval (802.11w)
    1384             :  * [tlv] HT Capabilities (802.11n)
    1385             :  * [tlv] HT Operation (802.11n)
    1386             :  */
    1387             : struct mbuf *
    1388           0 : ieee80211_get_assoc_resp(struct ieee80211com *ic, struct ieee80211_node *ni,
    1389             :     u_int16_t status)
    1390             : {
    1391           0 :         const struct ieee80211_rateset *rs = &ni->ni_rates;
    1392             :         struct mbuf *m;
    1393             :         u_int8_t *frm;
    1394             : 
    1395           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
    1396             :             2 + 2 + 2 +
    1397           0 :             2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
    1398           0 :             ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
    1399           0 :                 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
    1400           0 :             ((ni->ni_flags & IEEE80211_NODE_QOS) ? 2 + 18 : 0) +
    1401           0 :             ((status == IEEE80211_STATUS_TRY_AGAIN_LATER) ? 2 + 7 : 0) +
    1402           0 :             ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));
    1403           0 :         if (m == NULL)
    1404           0 :                 return NULL;
    1405             : 
    1406           0 :         frm = mtod(m, u_int8_t *);
    1407           0 :         frm = ieee80211_add_capinfo(frm, ic, ni);
    1408           0 :         LE_WRITE_2(frm, status); frm += 2;
    1409           0 :         if (status == IEEE80211_STATUS_SUCCESS)
    1410           0 :                 LE_WRITE_2(frm, ni->ni_associd);
    1411             :         else
    1412           0 :                 LE_WRITE_2(frm, 0);
    1413           0 :         frm += 2;
    1414           0 :         frm = ieee80211_add_rates(frm, rs);
    1415           0 :         if (rs->rs_nrates > IEEE80211_RATE_SIZE)
    1416           0 :                 frm = ieee80211_add_xrates(frm, rs);
    1417           0 :         if (ni->ni_flags & IEEE80211_NODE_QOS)
    1418           0 :                 frm = ieee80211_add_edca_params(frm, ic);
    1419           0 :         if ((ni->ni_flags & IEEE80211_NODE_MFP) &&
    1420             :             status == IEEE80211_STATUS_TRY_AGAIN_LATER) {
    1421             :                 /* Association Comeback Time */
    1422           0 :                 frm = ieee80211_add_tie(frm, 3, 1000 /* XXX */);
    1423           0 :         }
    1424           0 :         if (ic->ic_flags & IEEE80211_F_HTON) {
    1425           0 :                 frm = ieee80211_add_htcaps(frm, ic);
    1426           0 :                 frm = ieee80211_add_htop(frm, ic);
    1427           0 :                 frm = ieee80211_add_wme_param(frm, ic);
    1428           0 :         }
    1429             : 
    1430           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1431             : 
    1432           0 :         return m;
    1433           0 : }
    1434             : #endif  /* IEEE80211_STA_ONLY */
    1435             : 
    1436             : /*-
    1437             :  * Disassociation frame format:
    1438             :  * [2] Reason code
    1439             :  */
    1440             : struct mbuf *
    1441           0 : ieee80211_get_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
    1442             :     u_int16_t reason)
    1443             : {
    1444             :         struct mbuf *m;
    1445             : 
    1446           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    1447           0 :         if (m == NULL)
    1448           0 :                 return NULL;
    1449           0 :         MH_ALIGN(m, 2);
    1450             : 
    1451           0 :         m->m_pkthdr.len = m->m_len = 2;
    1452           0 :         *mtod(m, u_int16_t *) = htole16(reason);
    1453             : 
    1454           0 :         return m;
    1455           0 : }
    1456             : 
    1457             : /*-
    1458             :  * ADDBA Request frame format:
    1459             :  * [1] Category
    1460             :  * [1] Action
    1461             :  * [1] Dialog Token
    1462             :  * [2] Block Ack Parameter Set
    1463             :  * [2] Block Ack Timeout Value
    1464             :  * [2] Block Ack Starting Sequence Control
    1465             :  */
    1466             : struct mbuf *
    1467           0 : ieee80211_get_addba_req(struct ieee80211com *ic, struct ieee80211_node *ni,
    1468             :     u_int8_t tid)
    1469             : {
    1470           0 :         struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];
    1471             :         struct mbuf *m;
    1472             :         u_int8_t *frm;
    1473             : 
    1474           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 9);
    1475           0 :         if (m == NULL)
    1476           0 :                 return m;
    1477             : 
    1478           0 :         frm = mtod(m, u_int8_t *);
    1479           0 :         *frm++ = IEEE80211_CATEG_BA;
    1480           0 :         *frm++ = IEEE80211_ACTION_ADDBA_REQ;
    1481           0 :         *frm++ = ba->ba_token;
    1482           0 :         LE_WRITE_2(frm, ba->ba_params); frm += 2;
    1483           0 :         LE_WRITE_2(frm, ba->ba_timeout_val / IEEE80211_DUR_TU); frm += 2;
    1484           0 :         LE_WRITE_2(frm, ba->ba_winstart); frm += 2;
    1485             : 
    1486           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1487             : 
    1488           0 :         return m;
    1489           0 : }
    1490             : 
    1491             : /*-
    1492             :  * ADDBA Response frame format:
    1493             :  * [1] Category
    1494             :  * [1] Action
    1495             :  * [1] Dialog Token
    1496             :  * [2] Status Code
    1497             :  * [2] Block Ack Parameter Set
    1498             :  * [2] Block Ack Timeout Value
    1499             :  */
    1500             : struct mbuf *
    1501           0 : ieee80211_get_addba_resp(struct ieee80211com *ic, struct ieee80211_node *ni,
    1502             :     u_int8_t tid, u_int8_t token, u_int16_t status)
    1503             : {
    1504           0 :         struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
    1505             :         struct mbuf *m;
    1506             :         u_int8_t *frm;
    1507             :         u_int16_t params;
    1508             : 
    1509           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 9);
    1510           0 :         if (m == NULL)
    1511           0 :                 return m;
    1512             : 
    1513           0 :         frm = mtod(m, u_int8_t *);
    1514           0 :         *frm++ = IEEE80211_CATEG_BA;
    1515           0 :         *frm++ = IEEE80211_ACTION_ADDBA_RESP;
    1516           0 :         *frm++ = token;
    1517           0 :         LE_WRITE_2(frm, status); frm += 2;
    1518           0 :         if (status == 0)
    1519           0 :                 params = ba->ba_params;
    1520             :         else
    1521           0 :                 params = tid << IEEE80211_ADDBA_TID_SHIFT;
    1522           0 :         LE_WRITE_2(frm, params); frm += 2;
    1523           0 :         if (status == 0)
    1524           0 :                 LE_WRITE_2(frm, ba->ba_timeout_val / IEEE80211_DUR_TU);
    1525             :         else
    1526           0 :                 LE_WRITE_2(frm, 0);
    1527           0 :         frm += 2;
    1528             : 
    1529           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1530             : 
    1531           0 :         return m;
    1532           0 : }
    1533             : 
    1534             : /*-
    1535             :  * DELBA frame format:
    1536             :  * [1] Category
    1537             :  * [1] Action
    1538             :  * [2] DELBA Parameter Set
    1539             :  * [2] Reason Code
    1540             :  */
    1541             : struct mbuf *
    1542           0 : ieee80211_get_delba(struct ieee80211com *ic, struct ieee80211_node *ni,
    1543             :     u_int8_t tid, u_int8_t dir, u_int16_t reason)
    1544             : {
    1545             :         struct mbuf *m;
    1546             :         u_int8_t *frm;
    1547             :         u_int16_t params;
    1548             : 
    1549           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 6);
    1550           0 :         if (m == NULL)
    1551           0 :                 return m;
    1552             : 
    1553           0 :         frm = mtod(m, u_int8_t *);
    1554           0 :         *frm++ = IEEE80211_CATEG_BA;
    1555           0 :         *frm++ = IEEE80211_ACTION_DELBA;
    1556           0 :         params = tid << 12;
    1557           0 :         if (dir)
    1558           0 :                 params |= IEEE80211_DELBA_INITIATOR;
    1559           0 :         LE_WRITE_2(frm, params); frm += 2;
    1560           0 :         LE_WRITE_2(frm, reason); frm += 2;
    1561             : 
    1562           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1563             : 
    1564           0 :         return m;
    1565           0 : }
    1566             : 
    1567             : /*-
    1568             :  * SA Query Request/Reponse frame format:
    1569             :  * [1]  Category
    1570             :  * [1]  Action
    1571             :  * [16] Transaction Identifier
    1572             :  */
    1573             : struct mbuf *
    1574           0 : ieee80211_get_sa_query(struct ieee80211com *ic, struct ieee80211_node *ni,
    1575             :     u_int8_t action)
    1576             : {
    1577             :         struct mbuf *m;
    1578             :         u_int8_t *frm;
    1579             : 
    1580           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, 4);
    1581           0 :         if (m == NULL)
    1582           0 :                 return NULL;
    1583             : 
    1584           0 :         frm = mtod(m, u_int8_t *);
    1585           0 :         *frm++ = IEEE80211_CATEG_SA_QUERY;
    1586           0 :         *frm++ = action;        /* ACTION_SA_QUERY_REQ/RESP */
    1587           0 :         LE_WRITE_2(frm, ni->ni_sa_query_trid); frm += 2;
    1588             : 
    1589           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1590             : 
    1591           0 :         return m;
    1592           0 : }
    1593             : 
    1594             : struct mbuf *
    1595           0 : ieee80211_get_action(struct ieee80211com *ic, struct ieee80211_node *ni,
    1596             :     u_int8_t categ, u_int8_t action, int arg)
    1597             : {
    1598             :         struct mbuf *m = NULL;
    1599             : 
    1600           0 :         switch (categ) {
    1601             :         case IEEE80211_CATEG_BA:
    1602           0 :                 switch (action) {
    1603             :                 case IEEE80211_ACTION_ADDBA_REQ:
    1604           0 :                         m = ieee80211_get_addba_req(ic, ni, arg & 0xffff);
    1605           0 :                         break;
    1606             :                 case IEEE80211_ACTION_ADDBA_RESP:
    1607           0 :                         m = ieee80211_get_addba_resp(ic, ni, arg & 0xff,
    1608           0 :                             arg >> 8, arg >> 16);
    1609           0 :                         break;
    1610             :                 case IEEE80211_ACTION_DELBA:
    1611           0 :                         m = ieee80211_get_delba(ic, ni, arg & 0xff, arg >> 8,
    1612           0 :                             arg >> 16);
    1613           0 :                         break;
    1614             :                 }
    1615             :                 break;
    1616             :         case IEEE80211_CATEG_SA_QUERY:
    1617           0 :                 switch (action) {
    1618             : #ifndef IEEE80211_STA_ONLY
    1619             :                 case IEEE80211_ACTION_SA_QUERY_REQ:
    1620             : #endif
    1621             :                 case IEEE80211_ACTION_SA_QUERY_RESP:
    1622           0 :                         m = ieee80211_get_sa_query(ic, ni, action);
    1623           0 :                         break;
    1624             :                 }
    1625             :                 break;
    1626             :         }
    1627           0 :         return m;
    1628             : }
    1629             : 
    1630             : /*
    1631             :  * Send a management frame.  The node is for the destination (or ic_bss
    1632             :  * when in station mode).  Nodes other than ic_bss have their reference
    1633             :  * count bumped to reflect our use for an indeterminant time.
    1634             :  */
    1635             : int
    1636           0 : ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
    1637             :     int type, int arg1, int arg2)
    1638             : {
    1639             : #define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)
    1640           0 :         struct ifnet *ifp = &ic->ic_if;
    1641             :         struct mbuf *m;
    1642             :         int ret, timer;
    1643             : 
    1644           0 :         if (ni == NULL)
    1645           0 :                 panic("null node");
    1646             : 
    1647             :         /*
    1648             :          * Hold a reference on the node so it doesn't go away until after
    1649             :          * the xmit is complete all the way in the driver.  On error we
    1650             :          * will remove our reference.
    1651             :          */
    1652           0 :         ieee80211_ref_node(ni);
    1653             :         timer = 0;
    1654           0 :         switch (type) {
    1655             :         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
    1656           0 :                 if ((m = ieee80211_get_probe_req(ic, ni)) == NULL)
    1657           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1658             : 
    1659             :                 timer = IEEE80211_TRANS_WAIT;
    1660           0 :                 break;
    1661             : #ifndef IEEE80211_STA_ONLY
    1662             :         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
    1663           0 :                 if ((m = ieee80211_get_probe_resp(ic, ni)) == NULL)
    1664           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1665             :                 break;
    1666             : #endif
    1667             :         case IEEE80211_FC0_SUBTYPE_AUTH:
    1668           0 :                 m = ieee80211_get_auth(ic, ni, arg1 >> 16, arg1 & 0xffff);
    1669           0 :                 if (m == NULL)
    1670           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1671             : 
    1672           0 :                 if (ic->ic_opmode == IEEE80211_M_STA)
    1673           0 :                         timer = IEEE80211_TRANS_WAIT;
    1674             :                 break;
    1675             : 
    1676             :         case IEEE80211_FC0_SUBTYPE_DEAUTH:
    1677           0 :                 if ((m = ieee80211_get_deauth(ic, ni, arg1)) == NULL)
    1678           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1679             : #ifndef IEEE80211_STA_ONLY
    1680           0 :                 if ((ifp->if_flags & IFF_DEBUG) &&
    1681           0 :                     (ic->ic_opmode == IEEE80211_M_HOSTAP ||
    1682           0 :                     ic->ic_opmode == IEEE80211_M_IBSS))
    1683           0 :                         printf("%s: station %s deauthenticate (reason %d)\n",
    1684           0 :                             ifp->if_xname, ether_sprintf(ni->ni_macaddr),
    1685             :                             arg1);
    1686             : #endif
    1687             :                 break;
    1688             : 
    1689             :         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
    1690             :         case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
    1691           0 :                 if ((m = ieee80211_get_assoc_req(ic, ni, type)) == NULL)
    1692           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1693             : 
    1694             :                 timer = IEEE80211_TRANS_WAIT;
    1695           0 :                 break;
    1696             : #ifndef IEEE80211_STA_ONLY
    1697             :         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
    1698             :         case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
    1699           0 :                 if ((m = ieee80211_get_assoc_resp(ic, ni, arg1)) == NULL)
    1700           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1701             :                 break;
    1702             : #endif
    1703             :         case IEEE80211_FC0_SUBTYPE_DISASSOC:
    1704           0 :                 if ((m = ieee80211_get_disassoc(ic, ni, arg1)) == NULL)
    1705           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1706             : #ifndef IEEE80211_STA_ONLY
    1707           0 :                 if ((ifp->if_flags & IFF_DEBUG) &&
    1708           0 :                     (ic->ic_opmode == IEEE80211_M_HOSTAP ||
    1709           0 :                     ic->ic_opmode == IEEE80211_M_IBSS))
    1710           0 :                         printf("%s: station %s disassociate (reason %d)\n",
    1711           0 :                             ifp->if_xname, ether_sprintf(ni->ni_macaddr),
    1712             :                             arg1);
    1713             : #endif
    1714             :                 break;
    1715             : 
    1716             :         case IEEE80211_FC0_SUBTYPE_ACTION:
    1717           0 :                 m = ieee80211_get_action(ic, ni, arg1 >> 16, arg1 & 0xffff,
    1718             :                     arg2);
    1719           0 :                 if (m == NULL)
    1720           0 :                         senderr(ENOMEM, is_tx_nombuf);
    1721             :                 break;
    1722             : 
    1723             :         default:
    1724             :                 DPRINTF(("invalid mgmt frame type %u\n", type));
    1725           0 :                 senderr(EINVAL, is_tx_unknownmgt);
    1726             :                 /* NOTREACHED */
    1727             :         }
    1728             : 
    1729           0 :         ret = ieee80211_mgmt_output(ifp, ni, m, type);
    1730           0 :         if (ret == 0) {
    1731           0 :                 if (timer)
    1732           0 :                         ic->ic_mgt_timer = timer;
    1733             :         } else {
    1734             : bad:
    1735           0 :                 ieee80211_release_node(ic, ni);
    1736             :         }
    1737           0 :         return ret;
    1738             : #undef senderr
    1739             : }
    1740             : 
    1741             : /*
    1742             :  * Build a RTS (Request To Send) control frame (see 7.2.1.1).
    1743             :  */
    1744             : struct mbuf *
    1745           0 : ieee80211_get_rts(struct ieee80211com *ic, const struct ieee80211_frame *wh,
    1746             :     u_int16_t dur)
    1747             : {
    1748             :         struct ieee80211_frame_rts *rts;
    1749             :         struct mbuf *m;
    1750             : 
    1751           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    1752           0 :         if (m == NULL)
    1753           0 :                 return NULL;
    1754             : 
    1755           0 :         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_rts);
    1756             : 
    1757           0 :         rts = mtod(m, struct ieee80211_frame_rts *);
    1758           0 :         rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
    1759             :             IEEE80211_FC0_SUBTYPE_RTS;
    1760           0 :         rts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
    1761           0 :         *(u_int16_t *)rts->i_dur = htole16(dur);
    1762           0 :         IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1);
    1763           0 :         IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2);
    1764             : 
    1765           0 :         return m;
    1766           0 : }
    1767             : 
    1768             : /*
    1769             :  * Build a CTS-to-self (Clear To Send) control frame (see 7.2.1.2).
    1770             :  */
    1771             : struct mbuf *
    1772           0 : ieee80211_get_cts_to_self(struct ieee80211com *ic, u_int16_t dur)
    1773             : {
    1774             :         struct ieee80211_frame_cts *cts;
    1775             :         struct mbuf *m;
    1776             : 
    1777           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    1778           0 :         if (m == NULL)
    1779           0 :                 return NULL;
    1780             : 
    1781           0 :         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_cts);
    1782             : 
    1783           0 :         cts = mtod(m, struct ieee80211_frame_cts *);
    1784           0 :         cts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
    1785             :             IEEE80211_FC0_SUBTYPE_CTS;
    1786           0 :         cts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
    1787           0 :         *(u_int16_t *)cts->i_dur = htole16(dur);
    1788           0 :         IEEE80211_ADDR_COPY(cts->i_ra, ic->ic_myaddr);
    1789             : 
    1790           0 :         return m;
    1791           0 : }
    1792             : 
    1793             : #ifndef IEEE80211_STA_ONLY
    1794             : /*-
    1795             :  * Beacon frame format:
    1796             :  * [8]   Timestamp
    1797             :  * [2]   Beacon interval
    1798             :  * [2]   Capability
    1799             :  * [tlv] Service Set Identifier (SSID)
    1800             :  * [tlv] Supported rates
    1801             :  * [tlv] DS Parameter Set (802.11g)
    1802             :  * [tlv] IBSS Parameter Set
    1803             :  * [tlv] Traffic Indication Map (TIM)
    1804             :  * [tlv] ERP Information (802.11g)
    1805             :  * [tlv] Extended Supported Rates (802.11g)
    1806             :  * [tlv] RSN (802.11i)
    1807             :  * [tlv] EDCA Parameter Set (802.11e)
    1808             :  * [tlv] HT Capabilities (802.11n)
    1809             :  * [tlv] HT Operation (802.11n)
    1810             :  */
    1811             : struct mbuf *
    1812           0 : ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni)
    1813             : {
    1814           0 :         const struct ieee80211_rateset *rs = &ni->ni_rates;
    1815             :         struct ieee80211_frame *wh;
    1816             :         struct mbuf *m;
    1817             :         u_int8_t *frm;
    1818             : 
    1819           0 :         m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
    1820             :             8 + 2 + 2 +
    1821           0 :             2 + ((ic->ic_flags & IEEE80211_F_HIDENWID) ? 0 : ni->ni_esslen) +
    1822           0 :             2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
    1823           0 :             2 + 1 +
    1824           0 :             2 + ((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 254) +
    1825           0 :             ((ic->ic_curmode == IEEE80211_MODE_11G) ? 2 + 1 : 0) +
    1826           0 :             ((rs->rs_nrates > IEEE80211_RATE_SIZE) ?
    1827           0 :                 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) +
    1828           0 :             (((ic->ic_flags & IEEE80211_F_RSNON) &&
    1829           0 :               (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) ?
    1830           0 :                 2 + IEEE80211_RSNIE_MAXLEN : 0) +
    1831           0 :             ((ic->ic_flags & IEEE80211_F_QOS) ? 2 + 18 : 0) +
    1832           0 :             (((ic->ic_flags & IEEE80211_F_RSNON) &&
    1833           0 :               (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ?
    1834           0 :                 2 + IEEE80211_WPAIE_MAXLEN : 0) +
    1835           0 :             ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 + 26 : 0));
    1836           0 :         if (m == NULL)
    1837           0 :                 return NULL;
    1838             : 
    1839           0 :         M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
    1840           0 :         if (m == NULL)
    1841           0 :                 return NULL;
    1842           0 :         wh = mtod(m, struct ieee80211_frame *);
    1843           0 :         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
    1844             :             IEEE80211_FC0_SUBTYPE_BEACON;
    1845           0 :         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
    1846           0 :         *(u_int16_t *)wh->i_dur = 0;
    1847           0 :         IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
    1848           0 :         IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
    1849           0 :         IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
    1850           0 :         *(u_int16_t *)wh->i_seq = 0;
    1851             : 
    1852           0 :         frm = (u_int8_t *)&wh[1];
    1853           0 :         memset(frm, 0, 8); frm += 8;    /* timestamp is set by hardware */
    1854           0 :         LE_WRITE_2(frm, ni->ni_intval); frm += 2;
    1855           0 :         frm = ieee80211_add_capinfo(frm, ic, ni);
    1856           0 :         if (ic->ic_flags & IEEE80211_F_HIDENWID)
    1857           0 :                 frm = ieee80211_add_ssid(frm, NULL, 0);
    1858             :         else
    1859           0 :                 frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
    1860           0 :         frm = ieee80211_add_rates(frm, rs);
    1861           0 :         frm = ieee80211_add_ds_params(frm, ic, ni);
    1862           0 :         if (ic->ic_opmode == IEEE80211_M_IBSS)
    1863           0 :                 frm = ieee80211_add_ibss_params(frm, ni);
    1864             :         else
    1865           0 :                 frm = ieee80211_add_tim(frm, ic);
    1866           0 :         if (ic->ic_curmode == IEEE80211_MODE_11G)
    1867           0 :                 frm = ieee80211_add_erp(frm, ic);
    1868           0 :         if (rs->rs_nrates > IEEE80211_RATE_SIZE)
    1869           0 :                 frm = ieee80211_add_xrates(frm, rs);
    1870           0 :         if ((ic->ic_flags & IEEE80211_F_RSNON) &&
    1871           0 :             (ni->ni_rsnprotos & IEEE80211_PROTO_RSN))
    1872           0 :                 frm = ieee80211_add_rsn(frm, ic, ni);
    1873           0 :         if (ic->ic_flags & IEEE80211_F_QOS)
    1874           0 :                 frm = ieee80211_add_edca_params(frm, ic);
    1875           0 :         if ((ic->ic_flags & IEEE80211_F_RSNON) &&
    1876           0 :             (ni->ni_rsnprotos & IEEE80211_PROTO_WPA))
    1877           0 :                 frm = ieee80211_add_wpa(frm, ic, ni);
    1878           0 :         if (ic->ic_flags & IEEE80211_F_HTON) {
    1879           0 :                 frm = ieee80211_add_htcaps(frm, ic);
    1880           0 :                 frm = ieee80211_add_htop(frm, ic);
    1881           0 :                 frm = ieee80211_add_wme_param(frm, ic);
    1882           0 :         }
    1883             : 
    1884           0 :         m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
    1885           0 :         m->m_pkthdr.ph_cookie = ni;
    1886             : 
    1887           0 :         return m;
    1888           0 : }
    1889             : 
    1890             : /*
    1891             :  * Check if an outgoing MSDU or management frame should be buffered into
    1892             :  * the AP for power management.  Return 1 if the frame was buffered into
    1893             :  * the AP, or 0 if the frame shall be transmitted immediately.
    1894             :  */
    1895             : int
    1896           0 : ieee80211_pwrsave(struct ieee80211com *ic, struct mbuf *m,
    1897             :     struct ieee80211_node *ni)
    1898             : {
    1899             :         const struct ieee80211_frame *wh;
    1900           0 :         int pssta = 0;
    1901             : 
    1902           0 :         KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP);
    1903           0 :         if (!(ic->ic_caps & IEEE80211_C_APPMGT))
    1904           0 :                 return 0;
    1905             : 
    1906           0 :         wh = mtod(m, struct ieee80211_frame *);
    1907           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    1908             :                 /*
    1909             :                  * Buffer group addressed MSDUs with the Order bit clear
    1910             :                  * if any associated STAs are in PS mode.
    1911             :                  */
    1912           0 :                 ieee80211_iterate_nodes(ic, ieee80211_count_pssta, &pssta);
    1913           0 :                 if ((wh->i_fc[1] & IEEE80211_FC1_ORDER) || pssta == 0)
    1914           0 :                         return 0;
    1915           0 :                 ic->ic_tim_mcast_pending = 1;
    1916           0 :         } else {
    1917             :                 /*
    1918             :                  * Buffer MSDUs, A-MSDUs or management frames destined for
    1919             :                  * PS STAs.
    1920             :                  */
    1921           0 :                 if (ni->ni_pwrsave == IEEE80211_PS_AWAKE ||
    1922           0 :                     (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
    1923             :                     IEEE80211_FC0_TYPE_CTL)
    1924           0 :                         return 0;
    1925           0 :                 if (mq_empty(&ni->ni_savedq))
    1926           0 :                         (*ic->ic_set_tim)(ic, ni->ni_associd, 1);
    1927             :         }
    1928             :         /* NB: ni == ic->ic_bss for broadcast/multicast */
    1929             :         /*
    1930             :          * Similar to ieee80211_mgmt_output, store the node in a
    1931             :          * special pkthdr field.
    1932             :          */
    1933           0 :         m->m_pkthdr.ph_cookie = ni;
    1934           0 :         mq_enqueue(&ni->ni_savedq, m);
    1935           0 :         return 1;
    1936           0 : }
    1937             : #endif  /* IEEE80211_STA_ONLY */

Generated by: LCOV version 1.13