ieee80211_input.h revision 186904
1178354Ssam/*-
2186904Ssam * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
3178354Ssam * All rights reserved.
4178354Ssam *
5178354Ssam * Redistribution and use in source and binary forms, with or without
6178354Ssam * modification, are permitted provided that the following conditions
7178354Ssam * are met:
8178354Ssam * 1. Redistributions of source code must retain the above copyright
9178354Ssam *    notice, this list of conditions and the following disclaimer.
10178354Ssam * 2. Redistributions in binary form must reproduce the above copyright
11178354Ssam *    notice, this list of conditions and the following disclaimer in the
12178354Ssam *    documentation and/or other materials provided with the distribution.
13178354Ssam *
14178354Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15178354Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16178354Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17178354Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18178354Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19178354Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20178354Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21178354Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22178354Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23178354Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24178354Ssam *
25178354Ssam * $FreeBSD: head/sys/net80211/ieee80211_input.h 186904 2009-01-08 17:12:47Z sam $
26178354Ssam */
27178354Ssam#ifndef _NET80211_IEEE80211_INPUT_H_
28178354Ssam#define _NET80211_IEEE80211_INPUT_H_
29178354Ssam
30178354Ssam/* Verify the existence and length of __elem or get out. */
31178354Ssam#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen, _action) do {	\
32178354Ssam	if ((__elem) == NULL) {						\
33178354Ssam		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\
34178354Ssam		    wh, NULL, "%s", "no " #__elem );			\
35178354Ssam		vap->iv_stats.is_rx_elem_missing++;			\
36178354Ssam		_action;						\
37178354Ssam	} else if ((__elem)[1] > (__maxlen)) {				\
38178354Ssam		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\
39178354Ssam		    wh, NULL, "bad " #__elem " len %d", (__elem)[1]);	\
40178354Ssam		vap->iv_stats.is_rx_elem_toobig++;			\
41178354Ssam		_action;						\
42178354Ssam	}								\
43178354Ssam} while (0)
44178354Ssam
45178354Ssam#define	IEEE80211_VERIFY_LENGTH(_len, _minlen, _action) do {		\
46178354Ssam	if ((_len) < (_minlen)) {					\
47178354Ssam		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\
48178354Ssam		    wh, NULL, "ie too short, got %d, expected %d",	\
49178354Ssam		    (_len), (_minlen));					\
50178354Ssam		vap->iv_stats.is_rx_elem_toosmall++;			\
51178354Ssam		_action;						\
52178354Ssam	}								\
53178354Ssam} while (0)
54178354Ssam
55178354Ssam#ifdef IEEE80211_DEBUG
56178354Ssamvoid	ieee80211_ssid_mismatch(struct ieee80211vap *, const char *tag,
57178354Ssam	uint8_t mac[IEEE80211_ADDR_LEN], uint8_t *ssid);
58178354Ssam
59178354Ssam#define	IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do {			\
60178354Ssam	if ((_ssid)[1] != 0 &&						\
61178354Ssam	    ((_ssid)[1] != (_ni)->ni_esslen ||				\
62178354Ssam	    memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {	\
63178354Ssam		if (ieee80211_msg_input(vap))				\
64178354Ssam			ieee80211_ssid_mismatch(vap, 			\
65178354Ssam			    ieee80211_mgt_subtype_name[subtype >>	\
66178354Ssam				IEEE80211_FC0_SUBTYPE_SHIFT],		\
67178354Ssam				wh->i_addr2, _ssid);			\
68178354Ssam		vap->iv_stats.is_rx_ssidmismatch++;			\
69178354Ssam		_action;						\
70178354Ssam	}								\
71178354Ssam} while (0)
72178354Ssam#else /* !IEEE80211_DEBUG */
73178354Ssam#define	IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do {			\
74178354Ssam	if ((_ssid)[1] != 0 &&						\
75178354Ssam	    ((_ssid)[1] != (_ni)->ni_esslen ||				\
76178354Ssam	    memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {	\
77178354Ssam		vap->iv_stats.is_rx_ssidmismatch++;			\
78178354Ssam		_action;						\
79178354Ssam	}								\
80178354Ssam} while (0)
81178354Ssam#endif /* !IEEE80211_DEBUG */
82178354Ssam
83178354Ssam/* unalligned little endian access */
84178354Ssam#define LE_READ_2(p)					\
85178354Ssam	((uint16_t)					\
86178354Ssam	 ((((const uint8_t *)(p))[0]      ) |		\
87178354Ssam	  (((const uint8_t *)(p))[1] <<  8)))
88178354Ssam#define LE_READ_4(p)					\
89178354Ssam	((uint32_t)					\
90178354Ssam	 ((((const uint8_t *)(p))[0]      ) |		\
91178354Ssam	  (((const uint8_t *)(p))[1] <<  8) |		\
92178354Ssam	  (((const uint8_t *)(p))[2] << 16) |		\
93178354Ssam	  (((const uint8_t *)(p))[3] << 24)))
94178354Ssam
95178354Ssamstatic __inline int
96178354Ssamiswpaoui(const uint8_t *frm)
97178354Ssam{
98178354Ssam	return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
99178354Ssam}
100178354Ssam
101178354Ssamstatic __inline int
102178354Ssamiswmeoui(const uint8_t *frm)
103178354Ssam{
104178354Ssam	return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);
105178354Ssam}
106178354Ssam
107178354Ssamstatic __inline int
108178354Ssamiswmeparam(const uint8_t *frm)
109178354Ssam{
110178354Ssam	return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
111178354Ssam		frm[6] == WME_PARAM_OUI_SUBTYPE;
112178354Ssam}
113178354Ssam
114178354Ssamstatic __inline int
115178354Ssamiswmeinfo(const uint8_t *frm)
116178354Ssam{
117178354Ssam	return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
118178354Ssam		frm[6] == WME_INFO_OUI_SUBTYPE;
119178354Ssam}
120178354Ssam
121178354Ssamstatic __inline int
122178354Ssamisatherosoui(const uint8_t *frm)
123178354Ssam{
124178354Ssam	return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
125178354Ssam}
126178354Ssam
127178354Ssamstatic __inline int
128186904Ssamistdmaoui(const uint8_t *frm)
129186904Ssam{
130186904Ssam	return frm[1] > 3 && LE_READ_4(frm+2) == ((TDMA_OUI_TYPE<<24)|TDMA_OUI);
131186904Ssam}
132186904Ssam
133186904Ssamstatic __inline int
134178354Ssamishtcapoui(const uint8_t *frm)
135178354Ssam{
136178354Ssam	return frm[1] > 3 && LE_READ_4(frm+2) == ((BCM_OUI_HTCAP<<24)|BCM_OUI);
137178354Ssam}
138178354Ssam
139178354Ssamstatic __inline int
140178354Ssamishtinfooui(const uint8_t *frm)
141178354Ssam{
142178354Ssam	return frm[1] > 3 && LE_READ_4(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI);
143178354Ssam}
144178354Ssam
145178354Ssamvoid	ieee80211_deliver_data(struct ieee80211vap *,
146178354Ssam		struct ieee80211_node *, struct mbuf *);
147178354Ssamstruct mbuf *ieee80211_defrag(struct ieee80211_node *,
148178354Ssam		struct mbuf *, int);
149178354Ssamstruct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int);
150178354Ssamstruct mbuf *ieee80211_decap1(struct mbuf *, int *);
151178354Ssamstruct mbuf *ieee80211_decap_fastframe(struct ieee80211_node *,
152178354Ssam		struct mbuf *);
153178354Ssamint	ieee80211_setup_rates(struct ieee80211_node *ni,
154178354Ssam		const uint8_t *rates, const uint8_t *xrates, int flags);
155178354Ssamvoid ieee80211_send_error(struct ieee80211_node *,
156178354Ssam		const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg);
157178354Ssamint	ieee80211_alloc_challenge(struct ieee80211_node *);
158178354Ssamvoid	ieee80211_parse_ath(struct ieee80211_node *, uint8_t *);
159178354Ssamint	ieee80211_parse_beacon(struct ieee80211_node *, struct mbuf *,
160178354Ssam		struct ieee80211_scanparams *);
161178354Ssamint	ieee80211_parse_action(struct ieee80211_node *, struct mbuf *);
162178354Ssam#endif /* _NET80211_IEEE80211_INPUT_H_ */
163