1b032f27cSSam Leffler /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3fe267a55SPedro F. Giffuni * 410ad9a77SSam Leffler * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting 5b032f27cSSam Leffler * All rights reserved. 6b032f27cSSam Leffler * 7b032f27cSSam Leffler * Redistribution and use in source and binary forms, with or without 8b032f27cSSam Leffler * modification, are permitted provided that the following conditions 9b032f27cSSam Leffler * are met: 10b032f27cSSam Leffler * 1. Redistributions of source code must retain the above copyright 11b032f27cSSam Leffler * notice, this list of conditions and the following disclaimer. 12b032f27cSSam Leffler * 2. Redistributions in binary form must reproduce the above copyright 13b032f27cSSam Leffler * notice, this list of conditions and the following disclaimer in the 14b032f27cSSam Leffler * documentation and/or other materials provided with the distribution. 15b032f27cSSam Leffler * 16b032f27cSSam Leffler * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17b032f27cSSam Leffler * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18b032f27cSSam Leffler * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19b032f27cSSam Leffler * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20b032f27cSSam Leffler * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21b032f27cSSam Leffler * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22b032f27cSSam Leffler * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23b032f27cSSam Leffler * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24b032f27cSSam Leffler * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25b032f27cSSam Leffler * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26b032f27cSSam Leffler * 27b032f27cSSam Leffler * $FreeBSD$ 28b032f27cSSam Leffler */ 29b032f27cSSam Leffler #ifndef _NET80211_IEEE80211_INPUT_H_ 30b032f27cSSam Leffler #define _NET80211_IEEE80211_INPUT_H_ 31b032f27cSSam Leffler 32b032f27cSSam Leffler /* Verify the existence and length of __elem or get out. */ 33b032f27cSSam Leffler #define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen, _action) do { \ 34b032f27cSSam Leffler if ((__elem) == NULL) { \ 35b032f27cSSam Leffler IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID, \ 36b032f27cSSam Leffler wh, NULL, "%s", "no " #__elem ); \ 37b032f27cSSam Leffler vap->iv_stats.is_rx_elem_missing++; \ 38b032f27cSSam Leffler _action; \ 39b032f27cSSam Leffler } else if ((__elem)[1] > (__maxlen)) { \ 40b032f27cSSam Leffler IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID, \ 41b032f27cSSam Leffler wh, NULL, "bad " #__elem " len %d", (__elem)[1]); \ 42b032f27cSSam Leffler vap->iv_stats.is_rx_elem_toobig++; \ 43b032f27cSSam Leffler _action; \ 44b032f27cSSam Leffler } \ 45b032f27cSSam Leffler } while (0) 46b032f27cSSam Leffler 47b032f27cSSam Leffler #define IEEE80211_VERIFY_LENGTH(_len, _minlen, _action) do { \ 48b032f27cSSam Leffler if ((_len) < (_minlen)) { \ 49b032f27cSSam Leffler IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID, \ 50b032f27cSSam Leffler wh, NULL, "ie too short, got %d, expected %d", \ 51b032f27cSSam Leffler (_len), (_minlen)); \ 52b032f27cSSam Leffler vap->iv_stats.is_rx_elem_toosmall++; \ 53b032f27cSSam Leffler _action; \ 54b032f27cSSam Leffler } \ 55b032f27cSSam Leffler } while (0) 56b032f27cSSam Leffler 57b032f27cSSam Leffler #ifdef IEEE80211_DEBUG 58b032f27cSSam Leffler void ieee80211_ssid_mismatch(struct ieee80211vap *, const char *tag, 59b032f27cSSam Leffler uint8_t mac[IEEE80211_ADDR_LEN], uint8_t *ssid); 60b032f27cSSam Leffler 61b032f27cSSam Leffler #define IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do { \ 62b032f27cSSam Leffler if ((_ssid)[1] != 0 && \ 63b032f27cSSam Leffler ((_ssid)[1] != (_ni)->ni_esslen || \ 64b032f27cSSam Leffler memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \ 65b032f27cSSam Leffler if (ieee80211_msg_input(vap)) \ 66b032f27cSSam Leffler ieee80211_ssid_mismatch(vap, \ 674357a5d1SAndriy Voskoboinyk ieee80211_mgt_subtype_name(subtype), \ 68b032f27cSSam Leffler wh->i_addr2, _ssid); \ 69b032f27cSSam Leffler vap->iv_stats.is_rx_ssidmismatch++; \ 70b032f27cSSam Leffler _action; \ 71b032f27cSSam Leffler } \ 72b032f27cSSam Leffler } while (0) 73b032f27cSSam Leffler #else /* !IEEE80211_DEBUG */ 74b032f27cSSam Leffler #define IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do { \ 75b032f27cSSam Leffler if ((_ssid)[1] != 0 && \ 76b032f27cSSam Leffler ((_ssid)[1] != (_ni)->ni_esslen || \ 77b032f27cSSam Leffler memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \ 78b032f27cSSam Leffler vap->iv_stats.is_rx_ssidmismatch++; \ 79b032f27cSSam Leffler _action; \ 80b032f27cSSam Leffler } \ 81b032f27cSSam Leffler } while (0) 82b032f27cSSam Leffler #endif /* !IEEE80211_DEBUG */ 83b032f27cSSam Leffler 8431021a2bSAndriy Voskoboinyk #include <sys/endian.h> /* For le16toh() / le32dec() */ 85b032f27cSSam Leffler 86b032f27cSSam Leffler static __inline int 87b032f27cSSam Leffler iswpaoui(const uint8_t *frm) 88b032f27cSSam Leffler { 8931021a2bSAndriy Voskoboinyk return frm[1] > 3 && le32dec(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); 90b032f27cSSam Leffler } 91b032f27cSSam Leffler 92b032f27cSSam Leffler static __inline int 93b032f27cSSam Leffler iswmeoui(const uint8_t *frm) 94b032f27cSSam Leffler { 9531021a2bSAndriy Voskoboinyk return frm[1] > 3 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI); 96b032f27cSSam Leffler } 97b032f27cSSam Leffler 98b032f27cSSam Leffler static __inline int 99b032f27cSSam Leffler iswmeparam(const uint8_t *frm) 100b032f27cSSam Leffler { 10131021a2bSAndriy Voskoboinyk return frm[1] > 5 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) && 102b032f27cSSam Leffler frm[6] == WME_PARAM_OUI_SUBTYPE; 103b032f27cSSam Leffler } 104b032f27cSSam Leffler 105b032f27cSSam Leffler static __inline int 106b032f27cSSam Leffler iswmeinfo(const uint8_t *frm) 107b032f27cSSam Leffler { 10831021a2bSAndriy Voskoboinyk return frm[1] > 5 && le32dec(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) && 109b032f27cSSam Leffler frm[6] == WME_INFO_OUI_SUBTYPE; 110b032f27cSSam Leffler } 111b032f27cSSam Leffler 112b032f27cSSam Leffler static __inline int 113b032f27cSSam Leffler isatherosoui(const uint8_t *frm) 114b032f27cSSam Leffler { 11531021a2bSAndriy Voskoboinyk return frm[1] > 3 && le32dec(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI); 116b032f27cSSam Leffler } 117b032f27cSSam Leffler 118b032f27cSSam Leffler static __inline int 11910ad9a77SSam Leffler istdmaoui(const uint8_t *frm) 12010ad9a77SSam Leffler { 12131021a2bSAndriy Voskoboinyk return frm[1] > 3 && le32dec(frm+2) == ((TDMA_OUI_TYPE<<24)|TDMA_OUI); 12210ad9a77SSam Leffler } 12310ad9a77SSam Leffler 12410ad9a77SSam Leffler static __inline int 125b032f27cSSam Leffler ishtcapoui(const uint8_t *frm) 126b032f27cSSam Leffler { 12731021a2bSAndriy Voskoboinyk return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTCAP<<24)|BCM_OUI); 128b032f27cSSam Leffler } 129b032f27cSSam Leffler 130b032f27cSSam Leffler static __inline int 131b032f27cSSam Leffler ishtinfooui(const uint8_t *frm) 132b032f27cSSam Leffler { 13331021a2bSAndriy Voskoboinyk return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI); 134b032f27cSSam Leffler } 135b032f27cSSam Leffler 13648f95a36SAdrian Chadd static __inline int 13748f95a36SAdrian Chadd ieee80211_check_rxseq_amsdu(const struct ieee80211_rx_stats *rxs) 13848f95a36SAdrian Chadd { 139e9efad4fSAdrian Chadd if (rxs == NULL) 140e9efad4fSAdrian Chadd return 0; 14148f95a36SAdrian Chadd return (!! (rxs->c_pktflags & IEEE80211_RX_F_AMSDU)); 14248f95a36SAdrian Chadd } 14348f95a36SAdrian Chadd 14448f95a36SAdrian Chadd /* 14548f95a36SAdrian Chadd * Return 1 if the rxseq check should increment the sequence 14648f95a36SAdrian Chadd * number. Return 0 if it's part of an AMSDU batch and it isn't 14748f95a36SAdrian Chadd * the final frame in the decap'ed burst. 14848f95a36SAdrian Chadd */ 14948f95a36SAdrian Chadd static __inline int 15048f95a36SAdrian Chadd ieee80211_check_rxseq_amsdu_more(const struct ieee80211_rx_stats *rxs) 15148f95a36SAdrian Chadd { 15248f95a36SAdrian Chadd /* No state? ok */ 15348f95a36SAdrian Chadd if (rxs == NULL) 15448f95a36SAdrian Chadd return (1); 15548f95a36SAdrian Chadd 15648f95a36SAdrian Chadd /* State but no AMSDU set? ok */ 15748f95a36SAdrian Chadd if ((rxs->c_pktflags & IEEE80211_RX_F_AMSDU) == 0) 15848f95a36SAdrian Chadd return (1); 15948f95a36SAdrian Chadd 16048f95a36SAdrian Chadd /* State, AMSDU set, then _MORE means "don't inc yet" */ 16148f95a36SAdrian Chadd if (rxs->c_pktflags & IEEE80211_RX_F_AMSDU_MORE) { 16248f95a36SAdrian Chadd return (0); 16348f95a36SAdrian Chadd } 16448f95a36SAdrian Chadd 16548f95a36SAdrian Chadd /* Both are set, so return ok */ 16648f95a36SAdrian Chadd return (1); 16748f95a36SAdrian Chadd } 16848f95a36SAdrian Chadd 169cd0b8f2dSAdrian Chadd /* 170cd0b8f2dSAdrian Chadd * Check the current frame sequence number against the current TID 171cd0b8f2dSAdrian Chadd * state and return whether it's in sequence or should be dropped. 172cd0b8f2dSAdrian Chadd * 173cd0b8f2dSAdrian Chadd * Since out of order packet and duplicate packet eliminations should 174cd0b8f2dSAdrian Chadd * be done by the AMPDU RX code, this routine blindly accepts all 175cd0b8f2dSAdrian Chadd * frames from a HT station w/ a TID that is currently doing AMPDU-RX. 176cd0b8f2dSAdrian Chadd * HT stations without WME or where the TID is not doing AMPDU-RX 177cd0b8f2dSAdrian Chadd * are checked like non-HT stations. 178cd0b8f2dSAdrian Chadd * 179cd0b8f2dSAdrian Chadd * The routine only eliminates packets whose sequence/fragment 180cd0b8f2dSAdrian Chadd * match or are less than the last seen sequence/fragment number 18149c220b0SBjoern A. Zeeb * AND are retransmits. It doesn't try to eliminate out of order packets. 182cd0b8f2dSAdrian Chadd * 183cd0b8f2dSAdrian Chadd * Since all frames after sequence number 4095 will be less than 4095 184cd0b8f2dSAdrian Chadd * (as the seqnum wraps), handle that special case so packets aren't 185cd0b8f2dSAdrian Chadd * incorrectly dropped - ie, if the next packet is sequence number 0 186cd0b8f2dSAdrian Chadd * but a retransmit since the initial packet didn't make it. 1879764ef21SAdrian Chadd * 1889764ef21SAdrian Chadd * XXX TODO: handle sequence number space wrapping with dropped frames; 1899764ef21SAdrian Chadd * especially in high interference conditions under high traffic load 1909764ef21SAdrian Chadd * The RX AMPDU reorder code also needs it. 1919764ef21SAdrian Chadd * 1929764ef21SAdrian Chadd * XXX TODO: update for 802.11-2012 9.3.2.10 Duplicate Detection and Recovery. 193cd0b8f2dSAdrian Chadd */ 194cd0b8f2dSAdrian Chadd static __inline int 1951ffa8d7eSAndriy Voskoboinyk ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh, 19685c4e670SAdrian Chadd uint8_t *bssid, const struct ieee80211_rx_stats *rxs) 197cd0b8f2dSAdrian Chadd { 198cd0b8f2dSAdrian Chadd #define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) 199cd0b8f2dSAdrian Chadd #define SEQ_EQ(a,b) ((int)((a)-(b)) == 0) 200cd0b8f2dSAdrian Chadd #define SEQNO(a) ((a) >> IEEE80211_SEQ_SEQ_SHIFT) 201cd0b8f2dSAdrian Chadd #define FRAGNO(a) ((a) & IEEE80211_SEQ_FRAG_MASK) 2021ffa8d7eSAndriy Voskoboinyk struct ieee80211vap *vap = ni->ni_vap; 203cd0b8f2dSAdrian Chadd uint16_t rxseq; 204c3ebe019SAdrian Chadd uint8_t type, subtype; 205cd0b8f2dSAdrian Chadd uint8_t tid; 206cd0b8f2dSAdrian Chadd struct ieee80211_rx_ampdu *rap; 207cd0b8f2dSAdrian Chadd 208cd0b8f2dSAdrian Chadd rxseq = le16toh(*(uint16_t *)wh->i_seq); 209cd0b8f2dSAdrian Chadd type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 210c3ebe019SAdrian Chadd subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 211cd0b8f2dSAdrian Chadd 212c3ebe019SAdrian Chadd /* 213c3ebe019SAdrian Chadd * Types with no sequence number (or QoS (+)Null frames) 214c3ebe019SAdrian Chadd * are always treated valid. 215c3ebe019SAdrian Chadd */ 216c3ebe019SAdrian Chadd if (! IEEE80211_HAS_SEQ(type, subtype)) 217cd0b8f2dSAdrian Chadd return 1; 218cd0b8f2dSAdrian Chadd 2199764ef21SAdrian Chadd /* 2209764ef21SAdrian Chadd * Always allow multicast frames for now - QoS (any TID) 2219764ef21SAdrian Chadd * or not. 2229764ef21SAdrian Chadd */ 2239764ef21SAdrian Chadd if (IEEE80211_IS_MULTICAST(wh->i_addr1)) 2249764ef21SAdrian Chadd return 1; 2259764ef21SAdrian Chadd 226cd0b8f2dSAdrian Chadd tid = ieee80211_gettid(wh); 227cd0b8f2dSAdrian Chadd 228cd0b8f2dSAdrian Chadd /* 229cd0b8f2dSAdrian Chadd * Only do the HT AMPDU check for WME stations; non-WME HT stations 230cd0b8f2dSAdrian Chadd * shouldn't exist outside of debugging. We should at least 231cd0b8f2dSAdrian Chadd * handle that. 232cd0b8f2dSAdrian Chadd */ 233cd0b8f2dSAdrian Chadd if (tid < WME_NUM_TID) { 234cd0b8f2dSAdrian Chadd rap = &ni->ni_rx_ampdu[tid]; 235cd0b8f2dSAdrian Chadd /* HT nodes currently doing RX AMPDU are always valid */ 236cd0b8f2dSAdrian Chadd if ((ni->ni_flags & IEEE80211_NODE_HT) && 237cd0b8f2dSAdrian Chadd (rap->rxa_flags & IEEE80211_AGGR_RUNNING)) 2381ffa8d7eSAndriy Voskoboinyk goto ok; 239cd0b8f2dSAdrian Chadd } 240cd0b8f2dSAdrian Chadd 241cd0b8f2dSAdrian Chadd /* 242cd0b8f2dSAdrian Chadd * Otherwise, retries for packets below or equal to the last 243cd0b8f2dSAdrian Chadd * seen sequence number should be dropped. 244cd0b8f2dSAdrian Chadd */ 245cd0b8f2dSAdrian Chadd 246cd0b8f2dSAdrian Chadd /* 247cd0b8f2dSAdrian Chadd * Treat frame seqnum 4095 as special due to boundary 248cd0b8f2dSAdrian Chadd * wrapping conditions. 249cd0b8f2dSAdrian Chadd */ 250cd0b8f2dSAdrian Chadd if (SEQNO(ni->ni_rxseqs[tid]) == 4095) { 251cd0b8f2dSAdrian Chadd /* 252cd0b8f2dSAdrian Chadd * Drop retransmits on seqnum 4095/current fragment for itself. 253cd0b8f2dSAdrian Chadd */ 254cd0b8f2dSAdrian Chadd if (SEQ_EQ(rxseq, ni->ni_rxseqs[tid]) && 255cd0b8f2dSAdrian Chadd (wh->i_fc[1] & IEEE80211_FC1_RETRY)) 2561ffa8d7eSAndriy Voskoboinyk goto fail; 257cd0b8f2dSAdrian Chadd /* 258cd0b8f2dSAdrian Chadd * Treat any subsequent frame as fine if the last seen frame 259cd0b8f2dSAdrian Chadd * is 4095 and it's not a retransmit for the same sequence 260cd0b8f2dSAdrian Chadd * number. However, this doesn't capture incorrectly ordered 261cd0b8f2dSAdrian Chadd * fragments w/ sequence number 4095. It shouldn't be seen 262cd0b8f2dSAdrian Chadd * in practice, but see the comment above for further info. 263cd0b8f2dSAdrian Chadd */ 2641ffa8d7eSAndriy Voskoboinyk goto ok; 265cd0b8f2dSAdrian Chadd } 266cd0b8f2dSAdrian Chadd 267cd0b8f2dSAdrian Chadd /* 268cd0b8f2dSAdrian Chadd * At this point we assume that retransmitted seq/frag numbers below 269cd0b8f2dSAdrian Chadd * the current can simply be eliminated. 270cd0b8f2dSAdrian Chadd */ 271cd0b8f2dSAdrian Chadd if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) && 272cd0b8f2dSAdrian Chadd SEQ_LEQ(rxseq, ni->ni_rxseqs[tid])) 2731ffa8d7eSAndriy Voskoboinyk goto fail; 2741ffa8d7eSAndriy Voskoboinyk 2751ffa8d7eSAndriy Voskoboinyk ok: 27648f95a36SAdrian Chadd /* 27748f95a36SAdrian Chadd * Only bump the sequence number if it's the last frame 27848f95a36SAdrian Chadd * in a batch. That way frames in the rest of the batch 27948f95a36SAdrian Chadd * get included, and the last frame in the batch kicks 28048f95a36SAdrian Chadd * it next. 28148f95a36SAdrian Chadd */ 28248f95a36SAdrian Chadd if (ieee80211_check_rxseq_amsdu_more(rxs)) { 2831ffa8d7eSAndriy Voskoboinyk ni->ni_rxseqs[tid] = rxseq; 28479caf56eSAdrian Chadd if ((rxs != NULL) && ieee80211_check_rxseq_amsdu(rxs)) 28548f95a36SAdrian Chadd IEEE80211_NODE_STAT(ni, rx_amsdu_more_end); 28648f95a36SAdrian Chadd } else { 28748f95a36SAdrian Chadd /* .. still waiting */ 28848f95a36SAdrian Chadd IEEE80211_NODE_STAT(ni, rx_amsdu_more); 28948f95a36SAdrian Chadd } 290cd0b8f2dSAdrian Chadd 291cd0b8f2dSAdrian Chadd return 1; 2921ffa8d7eSAndriy Voskoboinyk 2931ffa8d7eSAndriy Voskoboinyk fail: 2941ffa8d7eSAndriy Voskoboinyk /* duplicate, discard */ 2951ffa8d7eSAndriy Voskoboinyk IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, bssid, "duplicate", 2961ffa8d7eSAndriy Voskoboinyk "seqno <%u,%u> fragno <%u,%u> tid %u", 2971ffa8d7eSAndriy Voskoboinyk SEQNO(rxseq), SEQNO(ni->ni_rxseqs[tid]), 2981ffa8d7eSAndriy Voskoboinyk FRAGNO(rxseq), FRAGNO(ni->ni_rxseqs[tid]), tid); 2991ffa8d7eSAndriy Voskoboinyk vap->iv_stats.is_rx_dup++; 3001ffa8d7eSAndriy Voskoboinyk IEEE80211_NODE_STAT(ni, rx_dup); 3011ffa8d7eSAndriy Voskoboinyk 3021ffa8d7eSAndriy Voskoboinyk return 0; 303cd0b8f2dSAdrian Chadd #undef SEQ_LEQ 304cd0b8f2dSAdrian Chadd #undef SEQ_EQ 305cd0b8f2dSAdrian Chadd #undef SEQNO 306cd0b8f2dSAdrian Chadd #undef FRAGNO 307cd0b8f2dSAdrian Chadd } 308cd0b8f2dSAdrian Chadd 309b032f27cSSam Leffler void ieee80211_deliver_data(struct ieee80211vap *, 310b032f27cSSam Leffler struct ieee80211_node *, struct mbuf *); 311b032f27cSSam Leffler struct mbuf *ieee80211_defrag(struct ieee80211_node *, 31211572d7dSMathy Vanhoef struct mbuf *, int, int); 313519f677aSSam Leffler struct mbuf *ieee80211_realign(struct ieee80211vap *, struct mbuf *, size_t); 314f024bdf1SMathy Vanhoef struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int, 315f024bdf1SMathy Vanhoef uint8_t); 316b032f27cSSam Leffler struct mbuf *ieee80211_decap1(struct mbuf *, int *); 317b032f27cSSam Leffler int ieee80211_setup_rates(struct ieee80211_node *ni, 318b032f27cSSam Leffler const uint8_t *rates, const uint8_t *xrates, int flags); 319b032f27cSSam Leffler void ieee80211_send_error(struct ieee80211_node *, 320b032f27cSSam Leffler const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg); 321b032f27cSSam Leffler int ieee80211_alloc_challenge(struct ieee80211_node *); 322b032f27cSSam Leffler int ieee80211_parse_beacon(struct ieee80211_node *, struct mbuf *, 323c79f192cSAdrian Chadd struct ieee80211_channel *, 324b032f27cSSam Leffler struct ieee80211_scanparams *); 325b032f27cSSam Leffler int ieee80211_parse_action(struct ieee80211_node *, struct mbuf *); 326b032f27cSSam Leffler #endif /* _NET80211_IEEE80211_INPUT_H_ */ 327