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