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_input.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  *
   27  * $FreeBSD$
   28  */
   29 #ifndef _NET80211_IEEE80211_INPUT_H_
   30 #define _NET80211_IEEE80211_INPUT_H_
   31 
   32 /* Verify the existence and length of __elem or get out. */
   33 #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen, _action) do {        \
   34         if ((__elem) == NULL) {                                         \
   35                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,            \
   36                     wh, NULL, "%s", "no " #__elem );                    \
   37                 vap->iv_stats.is_rx_elem_missing++;                     \
   38                 _action;                                                \
   39         } else if ((__elem)[1] > (__maxlen)) {                          \
   40                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,            \
   41                     wh, NULL, "bad " #__elem " len %d", (__elem)[1]);   \
   42                 vap->iv_stats.is_rx_elem_toobig++;                      \
   43                 _action;                                                \
   44         }                                                               \
   45 } while (0)
   46 
   47 #define IEEE80211_VERIFY_LENGTH(_len, _minlen, _action) do {            \
   48         if ((_len) < (_minlen)) {                                       \
   49                 IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,            \
   50                     wh, NULL, "ie too short, got %d, expected %d",      \
   51                     (_len), (_minlen));                                 \
   52                 vap->iv_stats.is_rx_elem_toosmall++;                    \
   53                 _action;                                                \
   54         }                                                               \
   55 } while (0)
   56 
   57 #ifdef IEEE80211_DEBUG
   58 void    ieee80211_ssid_mismatch(struct ieee80211vap *, const char *tag,
   59         uint8_t mac[IEEE80211_ADDR_LEN], uint8_t *ssid);
   60 
   61 #define IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do {                 \
   62         if ((_ssid)[1] != 0 &&                                          \
   63             ((_ssid)[1] != (_ni)->ni_esslen ||                          \
   64             memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
   65                 if (ieee80211_msg_input(vap))                           \
   66                         ieee80211_ssid_mismatch(vap,                    \
   67                             ieee80211_mgt_subtype_name(subtype),        \
   68                                 wh->i_addr2, _ssid);                    \
   69                 vap->iv_stats.is_rx_ssidmismatch++;                     \
   70                 _action;                                                \
   71         }                                                               \
   72 } while (0)
   73 #else /* !IEEE80211_DEBUG */
   74 #define IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do {                 \
   75         if ((_ssid)[1] != 0 &&                                          \
   76             ((_ssid)[1] != (_ni)->ni_esslen ||                          \
   77             memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {   \
   78                 vap->iv_stats.is_rx_ssidmismatch++;                     \
   79                 _action;                                                \
   80         }                                                               \
   81 } while (0)
   82 #endif /* !IEEE80211_DEBUG */
   83 
   84 #include <sys/endian.h>         /* For le16toh() / le32dec() */
   85 
   86 static __inline int
   87 iswpaoui(const uint8_t *frm)
   88 {
   89         return frm[1] > 3 && le32dec(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
   90 }
   91 
   92 static __inline int
   93 iswmeoui(const uint8_t *frm)
   94 {
   95         return frm[1] > 3 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);
   96 }
   97 
   98 static __inline int
   99 iswmeparam(const uint8_t *frm)
  100 {
  101         return frm[1] > 5 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
  102                 frm[6] == WME_PARAM_OUI_SUBTYPE;
  103 }
  104 
  105 static __inline int
  106 iswmeinfo(const uint8_t *frm)
  107 {
  108         return frm[1] > 5 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
  109                 frm[6] == WME_INFO_OUI_SUBTYPE;
  110 }
  111 
  112 static __inline int
  113 isatherosoui(const uint8_t *frm)
  114 {
  115         return frm[1] > 3 && le32dec(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
  116 }
  117 
  118 static __inline int
  119 istdmaoui(const uint8_t *frm)
  120 {
  121         return frm[1] > 3 && le32dec(frm+2) == ((TDMA_OUI_TYPE<<24)|TDMA_OUI);
  122 }
  123 
  124 static __inline int
  125 ishtcapoui(const uint8_t *frm)
  126 {
  127         return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTCAP<<24)|BCM_OUI);
  128 }
  129 
  130 static __inline int
  131 ishtinfooui(const uint8_t *frm)
  132 {
  133         return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI);
  134 }
  135 
  136 static __inline int
  137 ieee80211_check_rxseq_amsdu(const struct ieee80211_rx_stats *rxs)
  138 {
  139         if (rxs == NULL)
  140                 return 0;
  141         return (!! (rxs->c_pktflags & IEEE80211_RX_F_AMSDU));
  142 }
  143 
  144 /*
  145  * Return 1 if the rxseq check should increment the sequence
  146  * number. Return 0 if it's part of an AMSDU batch and it isn't
  147  * the final frame in the decap'ed burst.
  148  */
  149 static __inline int
  150 ieee80211_check_rxseq_amsdu_more(const struct ieee80211_rx_stats *rxs)
  151 {
  152         /* No state? ok */
  153         if (rxs == NULL)
  154                 return (1);
  155 
  156         /* State but no AMSDU set? ok */
  157         if ((rxs->c_pktflags & IEEE80211_RX_F_AMSDU) == 0)
  158                 return (1);
  159 
  160         /* State, AMSDU set, then _MORE means "don't inc yet" */
  161         if (rxs->c_pktflags & IEEE80211_RX_F_AMSDU_MORE) {
  162                 return (0);
  163         }
  164 
  165         /* Both are set, so return ok */
  166         return (1);
  167 }
  168 
  169 /*
  170  * Check the current frame sequence number against the current TID
  171  * state and return whether it's in sequence or should be dropped.
  172  *
  173  * Since out of order packet and duplicate packet eliminations should
  174  * be done by the AMPDU RX code, this routine blindly accepts all
  175  * frames from a HT station w/ a TID that is currently doing AMPDU-RX.
  176  * HT stations without WME or where the TID is not doing AMPDU-RX
  177  * are checked like non-HT stations.
  178  *
  179  * The routine only eliminates packets whose sequence/fragment
  180  * match or are less than the last seen sequence/fragment number
  181  * AND are retransmits It doesn't try to eliminate out of order packets.
  182  *
  183  * Since all frames after sequence number 4095 will be less than 4095
  184  * (as the seqnum wraps), handle that special case so packets aren't
  185  * incorrectly dropped - ie, if the next packet is sequence number 0
  186  * but a retransmit since the initial packet didn't make it.
  187  *
  188  * XXX TODO: handle sequence number space wrapping with dropped frames;
  189  * especially in high interference conditions under high traffic load
  190  * The RX AMPDU reorder code also needs it.
  191  *
  192  * XXX TODO: update for 802.11-2012 9.3.2.10 Duplicate Detection and Recovery.
  193  */
  194 static __inline int
  195 ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh,
  196     uint8_t *bssid, const struct ieee80211_rx_stats *rxs)
  197 {
  198 #define SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
  199 #define SEQ_EQ(a,b)     ((int)((a)-(b)) == 0)
  200 #define SEQNO(a)        ((a) >> IEEE80211_SEQ_SEQ_SHIFT)
  201 #define FRAGNO(a)       ((a) & IEEE80211_SEQ_FRAG_MASK)
  202         struct ieee80211vap *vap = ni->ni_vap;
  203         uint16_t rxseq;
  204         uint8_t type, subtype;
  205         uint8_t tid;
  206         struct ieee80211_rx_ampdu *rap;
  207 
  208         rxseq = le16toh(*(uint16_t *)wh->i_seq);
  209         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
  210         subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
  211 
  212         /*
  213          * Types with no sequence number (or QoS (+)Null frames)
  214          * are always treated valid.
  215          */
  216         if (! IEEE80211_HAS_SEQ(type, subtype))
  217                 return 1;
  218 
  219         /*
  220          * Always allow multicast frames for now - QoS (any TID)
  221          * or not.
  222          */
  223         if (IEEE80211_IS_MULTICAST(wh->i_addr1))
  224                 return 1;
  225 
  226         tid = ieee80211_gettid(wh);
  227 
  228         /*
  229          * Only do the HT AMPDU check for WME stations; non-WME HT stations
  230          * shouldn't exist outside of debugging. We should at least
  231          * handle that.
  232          */
  233         if (tid < WME_NUM_TID) {
  234                 rap = &ni->ni_rx_ampdu[tid];
  235                 /* HT nodes currently doing RX AMPDU are always valid */
  236                 if ((ni->ni_flags & IEEE80211_NODE_HT) &&
  237                     (rap->rxa_flags & IEEE80211_AGGR_RUNNING))
  238                         goto ok;
  239         }
  240 
  241         /*      
  242          * Otherwise, retries for packets below or equal to the last
  243          * seen sequence number should be dropped.
  244          */
  245 
  246         /*
  247          * Treat frame seqnum 4095 as special due to boundary
  248          * wrapping conditions.
  249          */
  250         if (SEQNO(ni->ni_rxseqs[tid]) == 4095) {
  251                 /*
  252                  * Drop retransmits on seqnum 4095/current fragment for itself.
  253                  */
  254                 if (SEQ_EQ(rxseq, ni->ni_rxseqs[tid]) &&
  255                     (wh->i_fc[1] & IEEE80211_FC1_RETRY))
  256                         goto fail;
  257                 /*
  258                  * Treat any subsequent frame as fine if the last seen frame
  259                  * is 4095 and it's not a retransmit for the same sequence
  260                  * number. However, this doesn't capture incorrectly ordered
  261                  * fragments w/ sequence number 4095. It shouldn't be seen
  262                  * in practice, but see the comment above for further info.
  263                  */
  264                 goto ok;
  265         }
  266 
  267         /*
  268          * At this point we assume that retransmitted seq/frag numbers below
  269          * the current can simply be eliminated.
  270          */
  271         if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
  272             SEQ_LEQ(rxseq, ni->ni_rxseqs[tid]))
  273                 goto fail;
  274 
  275 ok:
  276         /*
  277          * Only bump the sequence number if it's the last frame
  278          * in a batch.  That way frames in the rest of the batch
  279          * get included, and the last frame in the batch kicks
  280          * it next.
  281          */
  282         if (ieee80211_check_rxseq_amsdu_more(rxs)) {
  283                 ni->ni_rxseqs[tid] = rxseq;
  284                 if ((rxs != NULL) && ieee80211_check_rxseq_amsdu(rxs))
  285                         IEEE80211_NODE_STAT(ni, rx_amsdu_more_end);
  286         } else {
  287                 /* .. still waiting */
  288                 IEEE80211_NODE_STAT(ni, rx_amsdu_more);
  289         }
  290 
  291         return 1;
  292 
  293 fail:
  294         /* duplicate, discard */
  295         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, bssid, "duplicate",
  296             "seqno <%u,%u> fragno <%u,%u> tid %u",
  297              SEQNO(rxseq),  SEQNO(ni->ni_rxseqs[tid]),
  298             FRAGNO(rxseq), FRAGNO(ni->ni_rxseqs[tid]), tid);
  299         vap->iv_stats.is_rx_dup++;
  300         IEEE80211_NODE_STAT(ni, rx_dup);
  301 
  302         return 0;
  303 #undef  SEQ_LEQ
  304 #undef  SEQ_EQ
  305 #undef  SEQNO
  306 #undef  FRAGNO
  307 }
  308 
  309 void    ieee80211_deliver_data(struct ieee80211vap *,
  310                 struct ieee80211_node *, struct mbuf *);
  311 struct mbuf *ieee80211_defrag(struct ieee80211_node *,
  312                 struct mbuf *, int, int);
  313 struct mbuf *ieee80211_realign(struct ieee80211vap *, struct mbuf *, size_t);
  314 struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int,
  315                 uint8_t);
  316 struct mbuf *ieee80211_decap1(struct mbuf *, int *);
  317 int     ieee80211_setup_rates(struct ieee80211_node *ni,
  318                 const uint8_t *rates, const uint8_t *xrates, int flags);
  319 void ieee80211_send_error(struct ieee80211_node *,
  320                 const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg);
  321 int     ieee80211_alloc_challenge(struct ieee80211_node *);
  322 int     ieee80211_parse_beacon(struct ieee80211_node *, struct mbuf *,
  323                 struct ieee80211_channel *,
  324                 struct ieee80211_scanparams *);
  325 int     ieee80211_parse_action(struct ieee80211_node *, struct mbuf *);
  326 #endif /* _NET80211_IEEE80211_INPUT_H_ */

Cache object: fb9c4f8d3711305d6886c535a8befb84


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