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: releng/12.0/sys/net80211/ieee80211_input.h 326272 2017-11-27 15:23:17Z pfg $
   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 
  140         return (!! (rxs->c_pktflags & IEEE80211_RX_F_AMSDU));
  141 }
  142 
  143 /*
  144  * Return 1 if the rxseq check should increment the sequence
  145  * number. Return 0 if it's part of an AMSDU batch and it isn't
  146  * the final frame in the decap'ed burst.
  147  */
  148 static __inline int
  149 ieee80211_check_rxseq_amsdu_more(const struct ieee80211_rx_stats *rxs)
  150 {
  151         /* No state? ok */
  152         if (rxs == NULL)
  153                 return (1);
  154 
  155         /* State but no AMSDU set? ok */
  156         if ((rxs->c_pktflags & IEEE80211_RX_F_AMSDU) == 0)
  157                 return (1);
  158 
  159         /* State, AMSDU set, then _MORE means "don't inc yet" */
  160         if (rxs->c_pktflags & IEEE80211_RX_F_AMSDU_MORE) {
  161                 return (0);
  162         }
  163 
  164         /* Both are set, so return ok */
  165         return (1);
  166 }
  167 
  168 /*
  169  * Check the current frame sequence number against the current TID
  170  * state and return whether it's in sequence or should be dropped.
  171  *
  172  * Since out of order packet and duplicate packet eliminations should
  173  * be done by the AMPDU RX code, this routine blindly accepts all
  174  * frames from a HT station w/ a TID that is currently doing AMPDU-RX.
  175  * HT stations without WME or where the TID is not doing AMPDU-RX
  176  * are checked like non-HT stations.
  177  *
  178  * The routine only eliminates packets whose sequence/fragment
  179  * match or are less than the last seen sequence/fragment number
  180  * AND are retransmits It doesn't try to eliminate out of order packets.
  181  *
  182  * Since all frames after sequence number 4095 will be less than 4095
  183  * (as the seqnum wraps), handle that special case so packets aren't
  184  * incorrectly dropped - ie, if the next packet is sequence number 0
  185  * but a retransmit since the initial packet didn't make it.
  186  *
  187  * XXX TODO: handle sequence number space wrapping with dropped frames;
  188  * especially in high interference conditions under high traffic load
  189  * The RX AMPDU reorder code also needs it.
  190  *
  191  * XXX TODO: update for 802.11-2012 9.3.2.10 Duplicate Detection and Recovery.
  192  */
  193 static __inline int
  194 ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh,
  195     uint8_t *bssid, const struct ieee80211_rx_stats *rxs)
  196 {
  197 #define SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
  198 #define SEQ_EQ(a,b)     ((int)((a)-(b)) == 0)
  199 #define SEQNO(a)        ((a) >> IEEE80211_SEQ_SEQ_SHIFT)
  200 #define FRAGNO(a)       ((a) & IEEE80211_SEQ_FRAG_MASK)
  201         struct ieee80211vap *vap = ni->ni_vap;
  202         uint16_t rxseq;
  203         uint8_t type, subtype;
  204         uint8_t tid;
  205         struct ieee80211_rx_ampdu *rap;
  206 
  207         rxseq = le16toh(*(uint16_t *)wh->i_seq);
  208         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
  209         subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
  210 
  211         /*
  212          * Types with no sequence number (or QoS (+)Null frames)
  213          * are always treated valid.
  214          */
  215         if (! IEEE80211_HAS_SEQ(type, subtype))
  216                 return 1;
  217 
  218         /*
  219          * Always allow multicast frames for now - QoS (any TID)
  220          * or not.
  221          */
  222         if (IEEE80211_IS_MULTICAST(wh->i_addr1))
  223                 return 1;
  224 
  225         tid = ieee80211_gettid(wh);
  226 
  227         /*
  228          * Only do the HT AMPDU check for WME stations; non-WME HT stations
  229          * shouldn't exist outside of debugging. We should at least
  230          * handle that.
  231          */
  232         if (tid < WME_NUM_TID) {
  233                 rap = &ni->ni_rx_ampdu[tid];
  234                 /* HT nodes currently doing RX AMPDU are always valid */
  235                 if ((ni->ni_flags & IEEE80211_NODE_HT) &&
  236                     (rap->rxa_flags & IEEE80211_AGGR_RUNNING))
  237                         goto ok;
  238         }
  239 
  240         /*      
  241          * Otherwise, retries for packets below or equal to the last
  242          * seen sequence number should be dropped.
  243          */
  244 
  245         /*
  246          * Treat frame seqnum 4095 as special due to boundary
  247          * wrapping conditions.
  248          */
  249         if (SEQNO(ni->ni_rxseqs[tid]) == 4095) {
  250                 /*
  251                  * Drop retransmits on seqnum 4095/current fragment for itself.
  252                  */
  253                 if (SEQ_EQ(rxseq, ni->ni_rxseqs[tid]) &&
  254                     (wh->i_fc[1] & IEEE80211_FC1_RETRY))
  255                         goto fail;
  256                 /*
  257                  * Treat any subsequent frame as fine if the last seen frame
  258                  * is 4095 and it's not a retransmit for the same sequence
  259                  * number. However, this doesn't capture incorrectly ordered
  260                  * fragments w/ sequence number 4095. It shouldn't be seen
  261                  * in practice, but see the comment above for further info.
  262                  */
  263                 goto ok;
  264         }
  265 
  266         /*
  267          * At this point we assume that retransmitted seq/frag numbers below
  268          * the current can simply be eliminated.
  269          */
  270         if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
  271             SEQ_LEQ(rxseq, ni->ni_rxseqs[tid]))
  272                 goto fail;
  273 
  274 ok:
  275         /*
  276          * Only bump the sequence number if it's the last frame
  277          * in a batch.  That way frames in the rest of the batch
  278          * get included, and the last frame in the batch kicks
  279          * it next.
  280          */
  281         if (ieee80211_check_rxseq_amsdu_more(rxs)) {
  282                 ni->ni_rxseqs[tid] = rxseq;
  283                 if ((rxs != NULL) && ieee80211_check_rxseq_amsdu(rxs))
  284                         IEEE80211_NODE_STAT(ni, rx_amsdu_more_end);
  285         } else {
  286                 /* .. still waiting */
  287                 IEEE80211_NODE_STAT(ni, rx_amsdu_more);
  288         }
  289 
  290         return 1;
  291 
  292 fail:
  293         /* duplicate, discard */
  294         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, bssid, "duplicate",
  295             "seqno <%u,%u> fragno <%u,%u> tid %u",
  296              SEQNO(rxseq),  SEQNO(ni->ni_rxseqs[tid]),
  297             FRAGNO(rxseq), FRAGNO(ni->ni_rxseqs[tid]), tid);
  298         vap->iv_stats.is_rx_dup++;
  299         IEEE80211_NODE_STAT(ni, rx_dup);
  300 
  301         return 0;
  302 #undef  SEQ_LEQ
  303 #undef  SEQ_EQ
  304 #undef  SEQNO
  305 #undef  FRAGNO
  306 }
  307 
  308 void    ieee80211_deliver_data(struct ieee80211vap *,
  309                 struct ieee80211_node *, struct mbuf *);
  310 struct mbuf *ieee80211_defrag(struct ieee80211_node *,
  311                 struct mbuf *, int);
  312 struct mbuf *ieee80211_realign(struct ieee80211vap *, struct mbuf *, size_t);
  313 struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int);
  314 struct mbuf *ieee80211_decap1(struct mbuf *, int *);
  315 int     ieee80211_setup_rates(struct ieee80211_node *ni,
  316                 const uint8_t *rates, const uint8_t *xrates, int flags);
  317 void ieee80211_send_error(struct ieee80211_node *,
  318                 const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg);
  319 int     ieee80211_alloc_challenge(struct ieee80211_node *);
  320 int     ieee80211_parse_beacon(struct ieee80211_node *, struct mbuf *,
  321                 struct ieee80211_channel *,
  322                 struct ieee80211_scanparams *);
  323 int     ieee80211_parse_action(struct ieee80211_node *, struct mbuf *);
  324 #endif /* _NET80211_IEEE80211_INPUT_H_ */

Cache object: fa9637ee942070a6594a486b6ce95bba


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