The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_output.c

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

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

Cache object: 9b344918a2480515a7f404be6f8aa620


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


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