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

Cache object: dc27e0b3ecc07ebb396818c41054c7a8


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