Commit 3491707a070c1183c709516b2f876f798c7a9a84
Committed by
John W. Linville
1 parent
ac9d1a7bef
Exists in
master
and in
7 other branches
mac80211: update meshconf IE
This updates the Mesh Configuration IE according to the latest draft (3.03). Notable changes include the simplified protocol IDs. Signed-off-by: Rui Paulo <rpaulo@gmail.com> Signed-off-by: Javier Cardona <javier@cozybit.com> Reviewed-by: Andrey Yurovsky <andrey@cozybit.com> Tested-by: Brian Cavagnolo <brian@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Showing 3 changed files with 35 additions and 46 deletions Inline Diff
include/linux/ieee80211.h
1 | /* | 1 | /* |
2 | * IEEE 802.11 defines | 2 | * IEEE 802.11 defines |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen | 4 | * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen |
5 | * <jkmaline@cc.hut.fi> | 5 | * <jkmaline@cc.hut.fi> |
6 | * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> | 6 | * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> |
7 | * Copyright (c) 2005, Devicescape Software, Inc. | 7 | * Copyright (c) 2005, Devicescape Software, Inc. |
8 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> | 8 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #ifndef LINUX_IEEE80211_H | 15 | #ifndef LINUX_IEEE80211_H |
16 | #define LINUX_IEEE80211_H | 16 | #define LINUX_IEEE80211_H |
17 | 17 | ||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <asm/byteorder.h> | 19 | #include <asm/byteorder.h> |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * DS bit usage | 22 | * DS bit usage |
23 | * | 23 | * |
24 | * TA = transmitter address | 24 | * TA = transmitter address |
25 | * RA = receiver address | 25 | * RA = receiver address |
26 | * DA = destination address | 26 | * DA = destination address |
27 | * SA = source address | 27 | * SA = source address |
28 | * | 28 | * |
29 | * ToDS FromDS A1(RA) A2(TA) A3 A4 Use | 29 | * ToDS FromDS A1(RA) A2(TA) A3 A4 Use |
30 | * ----------------------------------------------------------------- | 30 | * ----------------------------------------------------------------- |
31 | * 0 0 DA SA BSSID - IBSS/DLS | 31 | * 0 0 DA SA BSSID - IBSS/DLS |
32 | * 0 1 DA BSSID SA - AP -> STA | 32 | * 0 1 DA BSSID SA - AP -> STA |
33 | * 1 0 BSSID SA DA - AP <- STA | 33 | * 1 0 BSSID SA DA - AP <- STA |
34 | * 1 1 RA TA DA SA unspecified (WDS) | 34 | * 1 1 RA TA DA SA unspecified (WDS) |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #define FCS_LEN 4 | 37 | #define FCS_LEN 4 |
38 | 38 | ||
39 | #define IEEE80211_FCTL_VERS 0x0003 | 39 | #define IEEE80211_FCTL_VERS 0x0003 |
40 | #define IEEE80211_FCTL_FTYPE 0x000c | 40 | #define IEEE80211_FCTL_FTYPE 0x000c |
41 | #define IEEE80211_FCTL_STYPE 0x00f0 | 41 | #define IEEE80211_FCTL_STYPE 0x00f0 |
42 | #define IEEE80211_FCTL_TODS 0x0100 | 42 | #define IEEE80211_FCTL_TODS 0x0100 |
43 | #define IEEE80211_FCTL_FROMDS 0x0200 | 43 | #define IEEE80211_FCTL_FROMDS 0x0200 |
44 | #define IEEE80211_FCTL_MOREFRAGS 0x0400 | 44 | #define IEEE80211_FCTL_MOREFRAGS 0x0400 |
45 | #define IEEE80211_FCTL_RETRY 0x0800 | 45 | #define IEEE80211_FCTL_RETRY 0x0800 |
46 | #define IEEE80211_FCTL_PM 0x1000 | 46 | #define IEEE80211_FCTL_PM 0x1000 |
47 | #define IEEE80211_FCTL_MOREDATA 0x2000 | 47 | #define IEEE80211_FCTL_MOREDATA 0x2000 |
48 | #define IEEE80211_FCTL_PROTECTED 0x4000 | 48 | #define IEEE80211_FCTL_PROTECTED 0x4000 |
49 | #define IEEE80211_FCTL_ORDER 0x8000 | 49 | #define IEEE80211_FCTL_ORDER 0x8000 |
50 | 50 | ||
51 | #define IEEE80211_SCTL_FRAG 0x000F | 51 | #define IEEE80211_SCTL_FRAG 0x000F |
52 | #define IEEE80211_SCTL_SEQ 0xFFF0 | 52 | #define IEEE80211_SCTL_SEQ 0xFFF0 |
53 | 53 | ||
54 | #define IEEE80211_FTYPE_MGMT 0x0000 | 54 | #define IEEE80211_FTYPE_MGMT 0x0000 |
55 | #define IEEE80211_FTYPE_CTL 0x0004 | 55 | #define IEEE80211_FTYPE_CTL 0x0004 |
56 | #define IEEE80211_FTYPE_DATA 0x0008 | 56 | #define IEEE80211_FTYPE_DATA 0x0008 |
57 | 57 | ||
58 | /* management */ | 58 | /* management */ |
59 | #define IEEE80211_STYPE_ASSOC_REQ 0x0000 | 59 | #define IEEE80211_STYPE_ASSOC_REQ 0x0000 |
60 | #define IEEE80211_STYPE_ASSOC_RESP 0x0010 | 60 | #define IEEE80211_STYPE_ASSOC_RESP 0x0010 |
61 | #define IEEE80211_STYPE_REASSOC_REQ 0x0020 | 61 | #define IEEE80211_STYPE_REASSOC_REQ 0x0020 |
62 | #define IEEE80211_STYPE_REASSOC_RESP 0x0030 | 62 | #define IEEE80211_STYPE_REASSOC_RESP 0x0030 |
63 | #define IEEE80211_STYPE_PROBE_REQ 0x0040 | 63 | #define IEEE80211_STYPE_PROBE_REQ 0x0040 |
64 | #define IEEE80211_STYPE_PROBE_RESP 0x0050 | 64 | #define IEEE80211_STYPE_PROBE_RESP 0x0050 |
65 | #define IEEE80211_STYPE_BEACON 0x0080 | 65 | #define IEEE80211_STYPE_BEACON 0x0080 |
66 | #define IEEE80211_STYPE_ATIM 0x0090 | 66 | #define IEEE80211_STYPE_ATIM 0x0090 |
67 | #define IEEE80211_STYPE_DISASSOC 0x00A0 | 67 | #define IEEE80211_STYPE_DISASSOC 0x00A0 |
68 | #define IEEE80211_STYPE_AUTH 0x00B0 | 68 | #define IEEE80211_STYPE_AUTH 0x00B0 |
69 | #define IEEE80211_STYPE_DEAUTH 0x00C0 | 69 | #define IEEE80211_STYPE_DEAUTH 0x00C0 |
70 | #define IEEE80211_STYPE_ACTION 0x00D0 | 70 | #define IEEE80211_STYPE_ACTION 0x00D0 |
71 | 71 | ||
72 | /* control */ | 72 | /* control */ |
73 | #define IEEE80211_STYPE_BACK_REQ 0x0080 | 73 | #define IEEE80211_STYPE_BACK_REQ 0x0080 |
74 | #define IEEE80211_STYPE_BACK 0x0090 | 74 | #define IEEE80211_STYPE_BACK 0x0090 |
75 | #define IEEE80211_STYPE_PSPOLL 0x00A0 | 75 | #define IEEE80211_STYPE_PSPOLL 0x00A0 |
76 | #define IEEE80211_STYPE_RTS 0x00B0 | 76 | #define IEEE80211_STYPE_RTS 0x00B0 |
77 | #define IEEE80211_STYPE_CTS 0x00C0 | 77 | #define IEEE80211_STYPE_CTS 0x00C0 |
78 | #define IEEE80211_STYPE_ACK 0x00D0 | 78 | #define IEEE80211_STYPE_ACK 0x00D0 |
79 | #define IEEE80211_STYPE_CFEND 0x00E0 | 79 | #define IEEE80211_STYPE_CFEND 0x00E0 |
80 | #define IEEE80211_STYPE_CFENDACK 0x00F0 | 80 | #define IEEE80211_STYPE_CFENDACK 0x00F0 |
81 | 81 | ||
82 | /* data */ | 82 | /* data */ |
83 | #define IEEE80211_STYPE_DATA 0x0000 | 83 | #define IEEE80211_STYPE_DATA 0x0000 |
84 | #define IEEE80211_STYPE_DATA_CFACK 0x0010 | 84 | #define IEEE80211_STYPE_DATA_CFACK 0x0010 |
85 | #define IEEE80211_STYPE_DATA_CFPOLL 0x0020 | 85 | #define IEEE80211_STYPE_DATA_CFPOLL 0x0020 |
86 | #define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 | 86 | #define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 |
87 | #define IEEE80211_STYPE_NULLFUNC 0x0040 | 87 | #define IEEE80211_STYPE_NULLFUNC 0x0040 |
88 | #define IEEE80211_STYPE_CFACK 0x0050 | 88 | #define IEEE80211_STYPE_CFACK 0x0050 |
89 | #define IEEE80211_STYPE_CFPOLL 0x0060 | 89 | #define IEEE80211_STYPE_CFPOLL 0x0060 |
90 | #define IEEE80211_STYPE_CFACKPOLL 0x0070 | 90 | #define IEEE80211_STYPE_CFACKPOLL 0x0070 |
91 | #define IEEE80211_STYPE_QOS_DATA 0x0080 | 91 | #define IEEE80211_STYPE_QOS_DATA 0x0080 |
92 | #define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 | 92 | #define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 |
93 | #define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 | 93 | #define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 |
94 | #define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 | 94 | #define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 |
95 | #define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 | 95 | #define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 |
96 | #define IEEE80211_STYPE_QOS_CFACK 0x00D0 | 96 | #define IEEE80211_STYPE_QOS_CFACK 0x00D0 |
97 | #define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 | 97 | #define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 |
98 | #define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 | 98 | #define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 |
99 | 99 | ||
100 | 100 | ||
101 | /* miscellaneous IEEE 802.11 constants */ | 101 | /* miscellaneous IEEE 802.11 constants */ |
102 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 | 102 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 |
103 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 | 103 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 |
104 | #define IEEE80211_MAX_AID 2007 | 104 | #define IEEE80211_MAX_AID 2007 |
105 | #define IEEE80211_MAX_TIM_LEN 251 | 105 | #define IEEE80211_MAX_TIM_LEN 251 |
106 | /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section | 106 | /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section |
107 | 6.2.1.1.2. | 107 | 6.2.1.1.2. |
108 | 108 | ||
109 | 802.11e clarifies the figure in section 7.1.2. The frame body is | 109 | 802.11e clarifies the figure in section 7.1.2. The frame body is |
110 | up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ | 110 | up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ |
111 | #define IEEE80211_MAX_DATA_LEN 2304 | 111 | #define IEEE80211_MAX_DATA_LEN 2304 |
112 | /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ | 112 | /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ |
113 | #define IEEE80211_MAX_FRAME_LEN 2352 | 113 | #define IEEE80211_MAX_FRAME_LEN 2352 |
114 | 114 | ||
115 | #define IEEE80211_MAX_SSID_LEN 32 | 115 | #define IEEE80211_MAX_SSID_LEN 32 |
116 | 116 | ||
117 | #define IEEE80211_MAX_MESH_ID_LEN 32 | 117 | #define IEEE80211_MAX_MESH_ID_LEN 32 |
118 | #define IEEE80211_MESH_CONFIG_LEN 24 | 118 | #define IEEE80211_MESH_CONFIG_LEN 7 |
119 | 119 | ||
120 | #define IEEE80211_QOS_CTL_LEN 2 | 120 | #define IEEE80211_QOS_CTL_LEN 2 |
121 | #define IEEE80211_QOS_CTL_TID_MASK 0x000F | 121 | #define IEEE80211_QOS_CTL_TID_MASK 0x000F |
122 | #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 | 122 | #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 |
123 | 123 | ||
124 | struct ieee80211_hdr { | 124 | struct ieee80211_hdr { |
125 | __le16 frame_control; | 125 | __le16 frame_control; |
126 | __le16 duration_id; | 126 | __le16 duration_id; |
127 | u8 addr1[6]; | 127 | u8 addr1[6]; |
128 | u8 addr2[6]; | 128 | u8 addr2[6]; |
129 | u8 addr3[6]; | 129 | u8 addr3[6]; |
130 | __le16 seq_ctrl; | 130 | __le16 seq_ctrl; |
131 | u8 addr4[6]; | 131 | u8 addr4[6]; |
132 | } __attribute__ ((packed)); | 132 | } __attribute__ ((packed)); |
133 | 133 | ||
134 | /** | 134 | /** |
135 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set | 135 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set |
136 | * @fc: frame control bytes in little-endian byteorder | 136 | * @fc: frame control bytes in little-endian byteorder |
137 | */ | 137 | */ |
138 | static inline int ieee80211_has_tods(__le16 fc) | 138 | static inline int ieee80211_has_tods(__le16 fc) |
139 | { | 139 | { |
140 | return (fc & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0; | 140 | return (fc & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0; |
141 | } | 141 | } |
142 | 142 | ||
143 | /** | 143 | /** |
144 | * ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set | 144 | * ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set |
145 | * @fc: frame control bytes in little-endian byteorder | 145 | * @fc: frame control bytes in little-endian byteorder |
146 | */ | 146 | */ |
147 | static inline int ieee80211_has_fromds(__le16 fc) | 147 | static inline int ieee80211_has_fromds(__le16 fc) |
148 | { | 148 | { |
149 | return (fc & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0; | 149 | return (fc & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0; |
150 | } | 150 | } |
151 | 151 | ||
152 | /** | 152 | /** |
153 | * ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set | 153 | * ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set |
154 | * @fc: frame control bytes in little-endian byteorder | 154 | * @fc: frame control bytes in little-endian byteorder |
155 | */ | 155 | */ |
156 | static inline int ieee80211_has_a4(__le16 fc) | 156 | static inline int ieee80211_has_a4(__le16 fc) |
157 | { | 157 | { |
158 | __le16 tmp = cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); | 158 | __le16 tmp = cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); |
159 | return (fc & tmp) == tmp; | 159 | return (fc & tmp) == tmp; |
160 | } | 160 | } |
161 | 161 | ||
162 | /** | 162 | /** |
163 | * ieee80211_has_morefrags - check if IEEE80211_FCTL_MOREFRAGS is set | 163 | * ieee80211_has_morefrags - check if IEEE80211_FCTL_MOREFRAGS is set |
164 | * @fc: frame control bytes in little-endian byteorder | 164 | * @fc: frame control bytes in little-endian byteorder |
165 | */ | 165 | */ |
166 | static inline int ieee80211_has_morefrags(__le16 fc) | 166 | static inline int ieee80211_has_morefrags(__le16 fc) |
167 | { | 167 | { |
168 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0; | 168 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0; |
169 | } | 169 | } |
170 | 170 | ||
171 | /** | 171 | /** |
172 | * ieee80211_has_retry - check if IEEE80211_FCTL_RETRY is set | 172 | * ieee80211_has_retry - check if IEEE80211_FCTL_RETRY is set |
173 | * @fc: frame control bytes in little-endian byteorder | 173 | * @fc: frame control bytes in little-endian byteorder |
174 | */ | 174 | */ |
175 | static inline int ieee80211_has_retry(__le16 fc) | 175 | static inline int ieee80211_has_retry(__le16 fc) |
176 | { | 176 | { |
177 | return (fc & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0; | 177 | return (fc & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0; |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | 180 | /** |
181 | * ieee80211_has_pm - check if IEEE80211_FCTL_PM is set | 181 | * ieee80211_has_pm - check if IEEE80211_FCTL_PM is set |
182 | * @fc: frame control bytes in little-endian byteorder | 182 | * @fc: frame control bytes in little-endian byteorder |
183 | */ | 183 | */ |
184 | static inline int ieee80211_has_pm(__le16 fc) | 184 | static inline int ieee80211_has_pm(__le16 fc) |
185 | { | 185 | { |
186 | return (fc & cpu_to_le16(IEEE80211_FCTL_PM)) != 0; | 186 | return (fc & cpu_to_le16(IEEE80211_FCTL_PM)) != 0; |
187 | } | 187 | } |
188 | 188 | ||
189 | /** | 189 | /** |
190 | * ieee80211_has_moredata - check if IEEE80211_FCTL_MOREDATA is set | 190 | * ieee80211_has_moredata - check if IEEE80211_FCTL_MOREDATA is set |
191 | * @fc: frame control bytes in little-endian byteorder | 191 | * @fc: frame control bytes in little-endian byteorder |
192 | */ | 192 | */ |
193 | static inline int ieee80211_has_moredata(__le16 fc) | 193 | static inline int ieee80211_has_moredata(__le16 fc) |
194 | { | 194 | { |
195 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0; | 195 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0; |
196 | } | 196 | } |
197 | 197 | ||
198 | /** | 198 | /** |
199 | * ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set | 199 | * ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set |
200 | * @fc: frame control bytes in little-endian byteorder | 200 | * @fc: frame control bytes in little-endian byteorder |
201 | */ | 201 | */ |
202 | static inline int ieee80211_has_protected(__le16 fc) | 202 | static inline int ieee80211_has_protected(__le16 fc) |
203 | { | 203 | { |
204 | return (fc & cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0; | 204 | return (fc & cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0; |
205 | } | 205 | } |
206 | 206 | ||
207 | /** | 207 | /** |
208 | * ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set | 208 | * ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set |
209 | * @fc: frame control bytes in little-endian byteorder | 209 | * @fc: frame control bytes in little-endian byteorder |
210 | */ | 210 | */ |
211 | static inline int ieee80211_has_order(__le16 fc) | 211 | static inline int ieee80211_has_order(__le16 fc) |
212 | { | 212 | { |
213 | return (fc & cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0; | 213 | return (fc & cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0; |
214 | } | 214 | } |
215 | 215 | ||
216 | /** | 216 | /** |
217 | * ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT | 217 | * ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT |
218 | * @fc: frame control bytes in little-endian byteorder | 218 | * @fc: frame control bytes in little-endian byteorder |
219 | */ | 219 | */ |
220 | static inline int ieee80211_is_mgmt(__le16 fc) | 220 | static inline int ieee80211_is_mgmt(__le16 fc) |
221 | { | 221 | { |
222 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == | 222 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == |
223 | cpu_to_le16(IEEE80211_FTYPE_MGMT); | 223 | cpu_to_le16(IEEE80211_FTYPE_MGMT); |
224 | } | 224 | } |
225 | 225 | ||
226 | /** | 226 | /** |
227 | * ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL | 227 | * ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL |
228 | * @fc: frame control bytes in little-endian byteorder | 228 | * @fc: frame control bytes in little-endian byteorder |
229 | */ | 229 | */ |
230 | static inline int ieee80211_is_ctl(__le16 fc) | 230 | static inline int ieee80211_is_ctl(__le16 fc) |
231 | { | 231 | { |
232 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == | 232 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == |
233 | cpu_to_le16(IEEE80211_FTYPE_CTL); | 233 | cpu_to_le16(IEEE80211_FTYPE_CTL); |
234 | } | 234 | } |
235 | 235 | ||
236 | /** | 236 | /** |
237 | * ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA | 237 | * ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA |
238 | * @fc: frame control bytes in little-endian byteorder | 238 | * @fc: frame control bytes in little-endian byteorder |
239 | */ | 239 | */ |
240 | static inline int ieee80211_is_data(__le16 fc) | 240 | static inline int ieee80211_is_data(__le16 fc) |
241 | { | 241 | { |
242 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == | 242 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == |
243 | cpu_to_le16(IEEE80211_FTYPE_DATA); | 243 | cpu_to_le16(IEEE80211_FTYPE_DATA); |
244 | } | 244 | } |
245 | 245 | ||
246 | /** | 246 | /** |
247 | * ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set | 247 | * ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set |
248 | * @fc: frame control bytes in little-endian byteorder | 248 | * @fc: frame control bytes in little-endian byteorder |
249 | */ | 249 | */ |
250 | static inline int ieee80211_is_data_qos(__le16 fc) | 250 | static inline int ieee80211_is_data_qos(__le16 fc) |
251 | { | 251 | { |
252 | /* | 252 | /* |
253 | * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need | 253 | * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need |
254 | * to check the one bit | 254 | * to check the one bit |
255 | */ | 255 | */ |
256 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == | 256 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == |
257 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); | 257 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); |
258 | } | 258 | } |
259 | 259 | ||
260 | /** | 260 | /** |
261 | * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data | 261 | * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data |
262 | * @fc: frame control bytes in little-endian byteorder | 262 | * @fc: frame control bytes in little-endian byteorder |
263 | */ | 263 | */ |
264 | static inline int ieee80211_is_data_present(__le16 fc) | 264 | static inline int ieee80211_is_data_present(__le16 fc) |
265 | { | 265 | { |
266 | /* | 266 | /* |
267 | * mask with 0x40 and test that that bit is clear to only return true | 267 | * mask with 0x40 and test that that bit is clear to only return true |
268 | * for the data-containing substypes. | 268 | * for the data-containing substypes. |
269 | */ | 269 | */ |
270 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | 0x40)) == | 270 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | 0x40)) == |
271 | cpu_to_le16(IEEE80211_FTYPE_DATA); | 271 | cpu_to_le16(IEEE80211_FTYPE_DATA); |
272 | } | 272 | } |
273 | 273 | ||
274 | /** | 274 | /** |
275 | * ieee80211_is_assoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ | 275 | * ieee80211_is_assoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ |
276 | * @fc: frame control bytes in little-endian byteorder | 276 | * @fc: frame control bytes in little-endian byteorder |
277 | */ | 277 | */ |
278 | static inline int ieee80211_is_assoc_req(__le16 fc) | 278 | static inline int ieee80211_is_assoc_req(__le16 fc) |
279 | { | 279 | { |
280 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 280 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
281 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); | 281 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); |
282 | } | 282 | } |
283 | 283 | ||
284 | /** | 284 | /** |
285 | * ieee80211_is_assoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP | 285 | * ieee80211_is_assoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP |
286 | * @fc: frame control bytes in little-endian byteorder | 286 | * @fc: frame control bytes in little-endian byteorder |
287 | */ | 287 | */ |
288 | static inline int ieee80211_is_assoc_resp(__le16 fc) | 288 | static inline int ieee80211_is_assoc_resp(__le16 fc) |
289 | { | 289 | { |
290 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 290 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
291 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); | 291 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); |
292 | } | 292 | } |
293 | 293 | ||
294 | /** | 294 | /** |
295 | * ieee80211_is_reassoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ | 295 | * ieee80211_is_reassoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ |
296 | * @fc: frame control bytes in little-endian byteorder | 296 | * @fc: frame control bytes in little-endian byteorder |
297 | */ | 297 | */ |
298 | static inline int ieee80211_is_reassoc_req(__le16 fc) | 298 | static inline int ieee80211_is_reassoc_req(__le16 fc) |
299 | { | 299 | { |
300 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 300 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
301 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); | 301 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); |
302 | } | 302 | } |
303 | 303 | ||
304 | /** | 304 | /** |
305 | * ieee80211_is_reassoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP | 305 | * ieee80211_is_reassoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP |
306 | * @fc: frame control bytes in little-endian byteorder | 306 | * @fc: frame control bytes in little-endian byteorder |
307 | */ | 307 | */ |
308 | static inline int ieee80211_is_reassoc_resp(__le16 fc) | 308 | static inline int ieee80211_is_reassoc_resp(__le16 fc) |
309 | { | 309 | { |
310 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 310 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
311 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); | 311 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); |
312 | } | 312 | } |
313 | 313 | ||
314 | /** | 314 | /** |
315 | * ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ | 315 | * ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ |
316 | * @fc: frame control bytes in little-endian byteorder | 316 | * @fc: frame control bytes in little-endian byteorder |
317 | */ | 317 | */ |
318 | static inline int ieee80211_is_probe_req(__le16 fc) | 318 | static inline int ieee80211_is_probe_req(__le16 fc) |
319 | { | 319 | { |
320 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 320 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
321 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); | 321 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); |
322 | } | 322 | } |
323 | 323 | ||
324 | /** | 324 | /** |
325 | * ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP | 325 | * ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP |
326 | * @fc: frame control bytes in little-endian byteorder | 326 | * @fc: frame control bytes in little-endian byteorder |
327 | */ | 327 | */ |
328 | static inline int ieee80211_is_probe_resp(__le16 fc) | 328 | static inline int ieee80211_is_probe_resp(__le16 fc) |
329 | { | 329 | { |
330 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 330 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
331 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); | 331 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); |
332 | } | 332 | } |
333 | 333 | ||
334 | /** | 334 | /** |
335 | * ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON | 335 | * ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON |
336 | * @fc: frame control bytes in little-endian byteorder | 336 | * @fc: frame control bytes in little-endian byteorder |
337 | */ | 337 | */ |
338 | static inline int ieee80211_is_beacon(__le16 fc) | 338 | static inline int ieee80211_is_beacon(__le16 fc) |
339 | { | 339 | { |
340 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 340 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
341 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 341 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
342 | } | 342 | } |
343 | 343 | ||
344 | /** | 344 | /** |
345 | * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM | 345 | * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM |
346 | * @fc: frame control bytes in little-endian byteorder | 346 | * @fc: frame control bytes in little-endian byteorder |
347 | */ | 347 | */ |
348 | static inline int ieee80211_is_atim(__le16 fc) | 348 | static inline int ieee80211_is_atim(__le16 fc) |
349 | { | 349 | { |
350 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 350 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
351 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); | 351 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); |
352 | } | 352 | } |
353 | 353 | ||
354 | /** | 354 | /** |
355 | * ieee80211_is_disassoc - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC | 355 | * ieee80211_is_disassoc - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC |
356 | * @fc: frame control bytes in little-endian byteorder | 356 | * @fc: frame control bytes in little-endian byteorder |
357 | */ | 357 | */ |
358 | static inline int ieee80211_is_disassoc(__le16 fc) | 358 | static inline int ieee80211_is_disassoc(__le16 fc) |
359 | { | 359 | { |
360 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 360 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
361 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); | 361 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); |
362 | } | 362 | } |
363 | 363 | ||
364 | /** | 364 | /** |
365 | * ieee80211_is_auth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH | 365 | * ieee80211_is_auth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH |
366 | * @fc: frame control bytes in little-endian byteorder | 366 | * @fc: frame control bytes in little-endian byteorder |
367 | */ | 367 | */ |
368 | static inline int ieee80211_is_auth(__le16 fc) | 368 | static inline int ieee80211_is_auth(__le16 fc) |
369 | { | 369 | { |
370 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 370 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
371 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); | 371 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); |
372 | } | 372 | } |
373 | 373 | ||
374 | /** | 374 | /** |
375 | * ieee80211_is_deauth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH | 375 | * ieee80211_is_deauth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH |
376 | * @fc: frame control bytes in little-endian byteorder | 376 | * @fc: frame control bytes in little-endian byteorder |
377 | */ | 377 | */ |
378 | static inline int ieee80211_is_deauth(__le16 fc) | 378 | static inline int ieee80211_is_deauth(__le16 fc) |
379 | { | 379 | { |
380 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 380 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
381 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); | 381 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); |
382 | } | 382 | } |
383 | 383 | ||
384 | /** | 384 | /** |
385 | * ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION | 385 | * ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION |
386 | * @fc: frame control bytes in little-endian byteorder | 386 | * @fc: frame control bytes in little-endian byteorder |
387 | */ | 387 | */ |
388 | static inline int ieee80211_is_action(__le16 fc) | 388 | static inline int ieee80211_is_action(__le16 fc) |
389 | { | 389 | { |
390 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 390 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
391 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); | 391 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); |
392 | } | 392 | } |
393 | 393 | ||
394 | /** | 394 | /** |
395 | * ieee80211_is_back_req - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ | 395 | * ieee80211_is_back_req - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ |
396 | * @fc: frame control bytes in little-endian byteorder | 396 | * @fc: frame control bytes in little-endian byteorder |
397 | */ | 397 | */ |
398 | static inline int ieee80211_is_back_req(__le16 fc) | 398 | static inline int ieee80211_is_back_req(__le16 fc) |
399 | { | 399 | { |
400 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 400 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
401 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); | 401 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); |
402 | } | 402 | } |
403 | 403 | ||
404 | /** | 404 | /** |
405 | * ieee80211_is_back - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK | 405 | * ieee80211_is_back - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK |
406 | * @fc: frame control bytes in little-endian byteorder | 406 | * @fc: frame control bytes in little-endian byteorder |
407 | */ | 407 | */ |
408 | static inline int ieee80211_is_back(__le16 fc) | 408 | static inline int ieee80211_is_back(__le16 fc) |
409 | { | 409 | { |
410 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 410 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
411 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); | 411 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); |
412 | } | 412 | } |
413 | 413 | ||
414 | /** | 414 | /** |
415 | * ieee80211_is_pspoll - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL | 415 | * ieee80211_is_pspoll - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL |
416 | * @fc: frame control bytes in little-endian byteorder | 416 | * @fc: frame control bytes in little-endian byteorder |
417 | */ | 417 | */ |
418 | static inline int ieee80211_is_pspoll(__le16 fc) | 418 | static inline int ieee80211_is_pspoll(__le16 fc) |
419 | { | 419 | { |
420 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 420 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
421 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 421 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); |
422 | } | 422 | } |
423 | 423 | ||
424 | /** | 424 | /** |
425 | * ieee80211_is_rts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS | 425 | * ieee80211_is_rts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS |
426 | * @fc: frame control bytes in little-endian byteorder | 426 | * @fc: frame control bytes in little-endian byteorder |
427 | */ | 427 | */ |
428 | static inline int ieee80211_is_rts(__le16 fc) | 428 | static inline int ieee80211_is_rts(__le16 fc) |
429 | { | 429 | { |
430 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 430 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
431 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); | 431 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); |
432 | } | 432 | } |
433 | 433 | ||
434 | /** | 434 | /** |
435 | * ieee80211_is_cts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS | 435 | * ieee80211_is_cts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS |
436 | * @fc: frame control bytes in little-endian byteorder | 436 | * @fc: frame control bytes in little-endian byteorder |
437 | */ | 437 | */ |
438 | static inline int ieee80211_is_cts(__le16 fc) | 438 | static inline int ieee80211_is_cts(__le16 fc) |
439 | { | 439 | { |
440 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 440 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
441 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); | 441 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); |
442 | } | 442 | } |
443 | 443 | ||
444 | /** | 444 | /** |
445 | * ieee80211_is_ack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK | 445 | * ieee80211_is_ack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK |
446 | * @fc: frame control bytes in little-endian byteorder | 446 | * @fc: frame control bytes in little-endian byteorder |
447 | */ | 447 | */ |
448 | static inline int ieee80211_is_ack(__le16 fc) | 448 | static inline int ieee80211_is_ack(__le16 fc) |
449 | { | 449 | { |
450 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 450 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
451 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); | 451 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); |
452 | } | 452 | } |
453 | 453 | ||
454 | /** | 454 | /** |
455 | * ieee80211_is_cfend - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND | 455 | * ieee80211_is_cfend - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND |
456 | * @fc: frame control bytes in little-endian byteorder | 456 | * @fc: frame control bytes in little-endian byteorder |
457 | */ | 457 | */ |
458 | static inline int ieee80211_is_cfend(__le16 fc) | 458 | static inline int ieee80211_is_cfend(__le16 fc) |
459 | { | 459 | { |
460 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 460 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
461 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); | 461 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); |
462 | } | 462 | } |
463 | 463 | ||
464 | /** | 464 | /** |
465 | * ieee80211_is_cfendack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK | 465 | * ieee80211_is_cfendack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK |
466 | * @fc: frame control bytes in little-endian byteorder | 466 | * @fc: frame control bytes in little-endian byteorder |
467 | */ | 467 | */ |
468 | static inline int ieee80211_is_cfendack(__le16 fc) | 468 | static inline int ieee80211_is_cfendack(__le16 fc) |
469 | { | 469 | { |
470 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 470 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
471 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); | 471 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); |
472 | } | 472 | } |
473 | 473 | ||
474 | /** | 474 | /** |
475 | * ieee80211_is_nullfunc - check if frame is a regular (non-QoS) nullfunc frame | 475 | * ieee80211_is_nullfunc - check if frame is a regular (non-QoS) nullfunc frame |
476 | * @fc: frame control bytes in little-endian byteorder | 476 | * @fc: frame control bytes in little-endian byteorder |
477 | */ | 477 | */ |
478 | static inline int ieee80211_is_nullfunc(__le16 fc) | 478 | static inline int ieee80211_is_nullfunc(__le16 fc) |
479 | { | 479 | { |
480 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 480 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
481 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); | 481 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); |
482 | } | 482 | } |
483 | 483 | ||
484 | /** | 484 | /** |
485 | * ieee80211_is_qos_nullfunc - check if frame is a QoS nullfunc frame | 485 | * ieee80211_is_qos_nullfunc - check if frame is a QoS nullfunc frame |
486 | * @fc: frame control bytes in little-endian byteorder | 486 | * @fc: frame control bytes in little-endian byteorder |
487 | */ | 487 | */ |
488 | static inline int ieee80211_is_qos_nullfunc(__le16 fc) | 488 | static inline int ieee80211_is_qos_nullfunc(__le16 fc) |
489 | { | 489 | { |
490 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 490 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
491 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); | 491 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); |
492 | } | 492 | } |
493 | 493 | ||
494 | struct ieee80211s_hdr { | 494 | struct ieee80211s_hdr { |
495 | u8 flags; | 495 | u8 flags; |
496 | u8 ttl; | 496 | u8 ttl; |
497 | __le32 seqnum; | 497 | __le32 seqnum; |
498 | u8 eaddr1[6]; | 498 | u8 eaddr1[6]; |
499 | u8 eaddr2[6]; | 499 | u8 eaddr2[6]; |
500 | u8 eaddr3[6]; | 500 | u8 eaddr3[6]; |
501 | } __attribute__ ((packed)); | 501 | } __attribute__ ((packed)); |
502 | 502 | ||
503 | /* Mesh flags */ | 503 | /* Mesh flags */ |
504 | #define MESH_FLAGS_AE_A4 0x1 | 504 | #define MESH_FLAGS_AE_A4 0x1 |
505 | #define MESH_FLAGS_AE_A5_A6 0x2 | 505 | #define MESH_FLAGS_AE_A5_A6 0x2 |
506 | #define MESH_FLAGS_AE 0x3 | 506 | #define MESH_FLAGS_AE 0x3 |
507 | #define MESH_FLAGS_PS_DEEP 0x4 | 507 | #define MESH_FLAGS_PS_DEEP 0x4 |
508 | 508 | ||
509 | /** | 509 | /** |
510 | * struct ieee80211_quiet_ie | 510 | * struct ieee80211_quiet_ie |
511 | * | 511 | * |
512 | * This structure refers to "Quiet information element" | 512 | * This structure refers to "Quiet information element" |
513 | */ | 513 | */ |
514 | struct ieee80211_quiet_ie { | 514 | struct ieee80211_quiet_ie { |
515 | u8 count; | 515 | u8 count; |
516 | u8 period; | 516 | u8 period; |
517 | __le16 duration; | 517 | __le16 duration; |
518 | __le16 offset; | 518 | __le16 offset; |
519 | } __attribute__ ((packed)); | 519 | } __attribute__ ((packed)); |
520 | 520 | ||
521 | /** | 521 | /** |
522 | * struct ieee80211_msrment_ie | 522 | * struct ieee80211_msrment_ie |
523 | * | 523 | * |
524 | * This structure refers to "Measurement Request/Report information element" | 524 | * This structure refers to "Measurement Request/Report information element" |
525 | */ | 525 | */ |
526 | struct ieee80211_msrment_ie { | 526 | struct ieee80211_msrment_ie { |
527 | u8 token; | 527 | u8 token; |
528 | u8 mode; | 528 | u8 mode; |
529 | u8 type; | 529 | u8 type; |
530 | u8 request[0]; | 530 | u8 request[0]; |
531 | } __attribute__ ((packed)); | 531 | } __attribute__ ((packed)); |
532 | 532 | ||
533 | /** | 533 | /** |
534 | * struct ieee80211_channel_sw_ie | 534 | * struct ieee80211_channel_sw_ie |
535 | * | 535 | * |
536 | * This structure refers to "Channel Switch Announcement information element" | 536 | * This structure refers to "Channel Switch Announcement information element" |
537 | */ | 537 | */ |
538 | struct ieee80211_channel_sw_ie { | 538 | struct ieee80211_channel_sw_ie { |
539 | u8 mode; | 539 | u8 mode; |
540 | u8 new_ch_num; | 540 | u8 new_ch_num; |
541 | u8 count; | 541 | u8 count; |
542 | } __attribute__ ((packed)); | 542 | } __attribute__ ((packed)); |
543 | 543 | ||
544 | /** | 544 | /** |
545 | * struct ieee80211_tim | 545 | * struct ieee80211_tim |
546 | * | 546 | * |
547 | * This structure refers to "Traffic Indication Map information element" | 547 | * This structure refers to "Traffic Indication Map information element" |
548 | */ | 548 | */ |
549 | struct ieee80211_tim_ie { | 549 | struct ieee80211_tim_ie { |
550 | u8 dtim_count; | 550 | u8 dtim_count; |
551 | u8 dtim_period; | 551 | u8 dtim_period; |
552 | u8 bitmap_ctrl; | 552 | u8 bitmap_ctrl; |
553 | /* variable size: 1 - 251 bytes */ | 553 | /* variable size: 1 - 251 bytes */ |
554 | u8 virtual_map[1]; | 554 | u8 virtual_map[1]; |
555 | } __attribute__ ((packed)); | 555 | } __attribute__ ((packed)); |
556 | 556 | ||
557 | #define WLAN_SA_QUERY_TR_ID_LEN 2 | 557 | #define WLAN_SA_QUERY_TR_ID_LEN 2 |
558 | 558 | ||
559 | struct ieee80211_mgmt { | 559 | struct ieee80211_mgmt { |
560 | __le16 frame_control; | 560 | __le16 frame_control; |
561 | __le16 duration; | 561 | __le16 duration; |
562 | u8 da[6]; | 562 | u8 da[6]; |
563 | u8 sa[6]; | 563 | u8 sa[6]; |
564 | u8 bssid[6]; | 564 | u8 bssid[6]; |
565 | __le16 seq_ctrl; | 565 | __le16 seq_ctrl; |
566 | union { | 566 | union { |
567 | struct { | 567 | struct { |
568 | __le16 auth_alg; | 568 | __le16 auth_alg; |
569 | __le16 auth_transaction; | 569 | __le16 auth_transaction; |
570 | __le16 status_code; | 570 | __le16 status_code; |
571 | /* possibly followed by Challenge text */ | 571 | /* possibly followed by Challenge text */ |
572 | u8 variable[0]; | 572 | u8 variable[0]; |
573 | } __attribute__ ((packed)) auth; | 573 | } __attribute__ ((packed)) auth; |
574 | struct { | 574 | struct { |
575 | __le16 reason_code; | 575 | __le16 reason_code; |
576 | } __attribute__ ((packed)) deauth; | 576 | } __attribute__ ((packed)) deauth; |
577 | struct { | 577 | struct { |
578 | __le16 capab_info; | 578 | __le16 capab_info; |
579 | __le16 listen_interval; | 579 | __le16 listen_interval; |
580 | /* followed by SSID and Supported rates */ | 580 | /* followed by SSID and Supported rates */ |
581 | u8 variable[0]; | 581 | u8 variable[0]; |
582 | } __attribute__ ((packed)) assoc_req; | 582 | } __attribute__ ((packed)) assoc_req; |
583 | struct { | 583 | struct { |
584 | __le16 capab_info; | 584 | __le16 capab_info; |
585 | __le16 status_code; | 585 | __le16 status_code; |
586 | __le16 aid; | 586 | __le16 aid; |
587 | /* followed by Supported rates */ | 587 | /* followed by Supported rates */ |
588 | u8 variable[0]; | 588 | u8 variable[0]; |
589 | } __attribute__ ((packed)) assoc_resp, reassoc_resp; | 589 | } __attribute__ ((packed)) assoc_resp, reassoc_resp; |
590 | struct { | 590 | struct { |
591 | __le16 capab_info; | 591 | __le16 capab_info; |
592 | __le16 listen_interval; | 592 | __le16 listen_interval; |
593 | u8 current_ap[6]; | 593 | u8 current_ap[6]; |
594 | /* followed by SSID and Supported rates */ | 594 | /* followed by SSID and Supported rates */ |
595 | u8 variable[0]; | 595 | u8 variable[0]; |
596 | } __attribute__ ((packed)) reassoc_req; | 596 | } __attribute__ ((packed)) reassoc_req; |
597 | struct { | 597 | struct { |
598 | __le16 reason_code; | 598 | __le16 reason_code; |
599 | } __attribute__ ((packed)) disassoc; | 599 | } __attribute__ ((packed)) disassoc; |
600 | struct { | 600 | struct { |
601 | __le64 timestamp; | 601 | __le64 timestamp; |
602 | __le16 beacon_int; | 602 | __le16 beacon_int; |
603 | __le16 capab_info; | 603 | __le16 capab_info; |
604 | /* followed by some of SSID, Supported rates, | 604 | /* followed by some of SSID, Supported rates, |
605 | * FH Params, DS Params, CF Params, IBSS Params, TIM */ | 605 | * FH Params, DS Params, CF Params, IBSS Params, TIM */ |
606 | u8 variable[0]; | 606 | u8 variable[0]; |
607 | } __attribute__ ((packed)) beacon; | 607 | } __attribute__ ((packed)) beacon; |
608 | struct { | 608 | struct { |
609 | /* only variable items: SSID, Supported rates */ | 609 | /* only variable items: SSID, Supported rates */ |
610 | u8 variable[0]; | 610 | u8 variable[0]; |
611 | } __attribute__ ((packed)) probe_req; | 611 | } __attribute__ ((packed)) probe_req; |
612 | struct { | 612 | struct { |
613 | __le64 timestamp; | 613 | __le64 timestamp; |
614 | __le16 beacon_int; | 614 | __le16 beacon_int; |
615 | __le16 capab_info; | 615 | __le16 capab_info; |
616 | /* followed by some of SSID, Supported rates, | 616 | /* followed by some of SSID, Supported rates, |
617 | * FH Params, DS Params, CF Params, IBSS Params */ | 617 | * FH Params, DS Params, CF Params, IBSS Params */ |
618 | u8 variable[0]; | 618 | u8 variable[0]; |
619 | } __attribute__ ((packed)) probe_resp; | 619 | } __attribute__ ((packed)) probe_resp; |
620 | struct { | 620 | struct { |
621 | u8 category; | 621 | u8 category; |
622 | union { | 622 | union { |
623 | struct { | 623 | struct { |
624 | u8 action_code; | 624 | u8 action_code; |
625 | u8 dialog_token; | 625 | u8 dialog_token; |
626 | u8 status_code; | 626 | u8 status_code; |
627 | u8 variable[0]; | 627 | u8 variable[0]; |
628 | } __attribute__ ((packed)) wme_action; | 628 | } __attribute__ ((packed)) wme_action; |
629 | struct{ | 629 | struct{ |
630 | u8 action_code; | 630 | u8 action_code; |
631 | u8 element_id; | 631 | u8 element_id; |
632 | u8 length; | 632 | u8 length; |
633 | struct ieee80211_channel_sw_ie sw_elem; | 633 | struct ieee80211_channel_sw_ie sw_elem; |
634 | } __attribute__((packed)) chan_switch; | 634 | } __attribute__((packed)) chan_switch; |
635 | struct{ | 635 | struct{ |
636 | u8 action_code; | 636 | u8 action_code; |
637 | u8 dialog_token; | 637 | u8 dialog_token; |
638 | u8 element_id; | 638 | u8 element_id; |
639 | u8 length; | 639 | u8 length; |
640 | struct ieee80211_msrment_ie msr_elem; | 640 | struct ieee80211_msrment_ie msr_elem; |
641 | } __attribute__((packed)) measurement; | 641 | } __attribute__((packed)) measurement; |
642 | struct{ | 642 | struct{ |
643 | u8 action_code; | 643 | u8 action_code; |
644 | u8 dialog_token; | 644 | u8 dialog_token; |
645 | __le16 capab; | 645 | __le16 capab; |
646 | __le16 timeout; | 646 | __le16 timeout; |
647 | __le16 start_seq_num; | 647 | __le16 start_seq_num; |
648 | } __attribute__((packed)) addba_req; | 648 | } __attribute__((packed)) addba_req; |
649 | struct{ | 649 | struct{ |
650 | u8 action_code; | 650 | u8 action_code; |
651 | u8 dialog_token; | 651 | u8 dialog_token; |
652 | __le16 status; | 652 | __le16 status; |
653 | __le16 capab; | 653 | __le16 capab; |
654 | __le16 timeout; | 654 | __le16 timeout; |
655 | } __attribute__((packed)) addba_resp; | 655 | } __attribute__((packed)) addba_resp; |
656 | struct{ | 656 | struct{ |
657 | u8 action_code; | 657 | u8 action_code; |
658 | __le16 params; | 658 | __le16 params; |
659 | __le16 reason_code; | 659 | __le16 reason_code; |
660 | } __attribute__((packed)) delba; | 660 | } __attribute__((packed)) delba; |
661 | struct{ | 661 | struct{ |
662 | u8 action_code; | 662 | u8 action_code; |
663 | /* capab_info for open and confirm, | 663 | /* capab_info for open and confirm, |
664 | * reason for close | 664 | * reason for close |
665 | */ | 665 | */ |
666 | __le16 aux; | 666 | __le16 aux; |
667 | /* Followed in plink_confirm by status | 667 | /* Followed in plink_confirm by status |
668 | * code, AID and supported rates, | 668 | * code, AID and supported rates, |
669 | * and directly by supported rates in | 669 | * and directly by supported rates in |
670 | * plink_open and plink_close | 670 | * plink_open and plink_close |
671 | */ | 671 | */ |
672 | u8 variable[0]; | 672 | u8 variable[0]; |
673 | } __attribute__((packed)) plink_action; | 673 | } __attribute__((packed)) plink_action; |
674 | struct{ | 674 | struct{ |
675 | u8 action_code; | 675 | u8 action_code; |
676 | u8 variable[0]; | 676 | u8 variable[0]; |
677 | } __attribute__((packed)) mesh_action; | 677 | } __attribute__((packed)) mesh_action; |
678 | struct { | 678 | struct { |
679 | u8 action; | 679 | u8 action; |
680 | u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; | 680 | u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; |
681 | } __attribute__ ((packed)) sa_query; | 681 | } __attribute__ ((packed)) sa_query; |
682 | } u; | 682 | } u; |
683 | } __attribute__ ((packed)) action; | 683 | } __attribute__ ((packed)) action; |
684 | } u; | 684 | } u; |
685 | } __attribute__ ((packed)); | 685 | } __attribute__ ((packed)); |
686 | 686 | ||
687 | /* mgmt header + 1 byte category code */ | 687 | /* mgmt header + 1 byte category code */ |
688 | #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) | 688 | #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) |
689 | 689 | ||
690 | 690 | ||
691 | /* Management MIC information element (IEEE 802.11w) */ | 691 | /* Management MIC information element (IEEE 802.11w) */ |
692 | struct ieee80211_mmie { | 692 | struct ieee80211_mmie { |
693 | u8 element_id; | 693 | u8 element_id; |
694 | u8 length; | 694 | u8 length; |
695 | __le16 key_id; | 695 | __le16 key_id; |
696 | u8 sequence_number[6]; | 696 | u8 sequence_number[6]; |
697 | u8 mic[8]; | 697 | u8 mic[8]; |
698 | } __attribute__ ((packed)); | 698 | } __attribute__ ((packed)); |
699 | 699 | ||
700 | /* Control frames */ | 700 | /* Control frames */ |
701 | struct ieee80211_rts { | 701 | struct ieee80211_rts { |
702 | __le16 frame_control; | 702 | __le16 frame_control; |
703 | __le16 duration; | 703 | __le16 duration; |
704 | u8 ra[6]; | 704 | u8 ra[6]; |
705 | u8 ta[6]; | 705 | u8 ta[6]; |
706 | } __attribute__ ((packed)); | 706 | } __attribute__ ((packed)); |
707 | 707 | ||
708 | struct ieee80211_cts { | 708 | struct ieee80211_cts { |
709 | __le16 frame_control; | 709 | __le16 frame_control; |
710 | __le16 duration; | 710 | __le16 duration; |
711 | u8 ra[6]; | 711 | u8 ra[6]; |
712 | } __attribute__ ((packed)); | 712 | } __attribute__ ((packed)); |
713 | 713 | ||
714 | struct ieee80211_pspoll { | 714 | struct ieee80211_pspoll { |
715 | __le16 frame_control; | 715 | __le16 frame_control; |
716 | __le16 aid; | 716 | __le16 aid; |
717 | u8 bssid[6]; | 717 | u8 bssid[6]; |
718 | u8 ta[6]; | 718 | u8 ta[6]; |
719 | } __attribute__ ((packed)); | 719 | } __attribute__ ((packed)); |
720 | 720 | ||
721 | /** | 721 | /** |
722 | * struct ieee80211_bar - HT Block Ack Request | 722 | * struct ieee80211_bar - HT Block Ack Request |
723 | * | 723 | * |
724 | * This structure refers to "HT BlockAckReq" as | 724 | * This structure refers to "HT BlockAckReq" as |
725 | * described in 802.11n draft section 7.2.1.7.1 | 725 | * described in 802.11n draft section 7.2.1.7.1 |
726 | */ | 726 | */ |
727 | struct ieee80211_bar { | 727 | struct ieee80211_bar { |
728 | __le16 frame_control; | 728 | __le16 frame_control; |
729 | __le16 duration; | 729 | __le16 duration; |
730 | __u8 ra[6]; | 730 | __u8 ra[6]; |
731 | __u8 ta[6]; | 731 | __u8 ta[6]; |
732 | __le16 control; | 732 | __le16 control; |
733 | __le16 start_seq_num; | 733 | __le16 start_seq_num; |
734 | } __attribute__((packed)); | 734 | } __attribute__((packed)); |
735 | 735 | ||
736 | /* 802.11 BAR control masks */ | 736 | /* 802.11 BAR control masks */ |
737 | #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 | 737 | #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 |
738 | #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 | 738 | #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 |
739 | 739 | ||
740 | 740 | ||
741 | #define IEEE80211_HT_MCS_MASK_LEN 10 | 741 | #define IEEE80211_HT_MCS_MASK_LEN 10 |
742 | 742 | ||
743 | /** | 743 | /** |
744 | * struct ieee80211_mcs_info - MCS information | 744 | * struct ieee80211_mcs_info - MCS information |
745 | * @rx_mask: RX mask | 745 | * @rx_mask: RX mask |
746 | * @rx_highest: highest supported RX rate | 746 | * @rx_highest: highest supported RX rate |
747 | * @tx_params: TX parameters | 747 | * @tx_params: TX parameters |
748 | */ | 748 | */ |
749 | struct ieee80211_mcs_info { | 749 | struct ieee80211_mcs_info { |
750 | u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; | 750 | u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; |
751 | __le16 rx_highest; | 751 | __le16 rx_highest; |
752 | u8 tx_params; | 752 | u8 tx_params; |
753 | u8 reserved[3]; | 753 | u8 reserved[3]; |
754 | } __attribute__((packed)); | 754 | } __attribute__((packed)); |
755 | 755 | ||
756 | /* 802.11n HT capability MSC set */ | 756 | /* 802.11n HT capability MSC set */ |
757 | #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff | 757 | #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff |
758 | #define IEEE80211_HT_MCS_TX_DEFINED 0x01 | 758 | #define IEEE80211_HT_MCS_TX_DEFINED 0x01 |
759 | #define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 | 759 | #define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 |
760 | /* value 0 == 1 stream etc */ | 760 | /* value 0 == 1 stream etc */ |
761 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C | 761 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C |
762 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 | 762 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 |
763 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 | 763 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 |
764 | #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 | 764 | #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 |
765 | 765 | ||
766 | /* | 766 | /* |
767 | * 802.11n D5.0 20.3.5 / 20.6 says: | 767 | * 802.11n D5.0 20.3.5 / 20.6 says: |
768 | * - indices 0 to 7 and 32 are single spatial stream | 768 | * - indices 0 to 7 and 32 are single spatial stream |
769 | * - 8 to 31 are multiple spatial streams using equal modulation | 769 | * - 8 to 31 are multiple spatial streams using equal modulation |
770 | * [8..15 for two streams, 16..23 for three and 24..31 for four] | 770 | * [8..15 for two streams, 16..23 for three and 24..31 for four] |
771 | * - remainder are multiple spatial streams using unequal modulation | 771 | * - remainder are multiple spatial streams using unequal modulation |
772 | */ | 772 | */ |
773 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 | 773 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 |
774 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ | 774 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ |
775 | (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) | 775 | (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) |
776 | 776 | ||
777 | /** | 777 | /** |
778 | * struct ieee80211_ht_cap - HT capabilities | 778 | * struct ieee80211_ht_cap - HT capabilities |
779 | * | 779 | * |
780 | * This structure is the "HT capabilities element" as | 780 | * This structure is the "HT capabilities element" as |
781 | * described in 802.11n D5.0 7.3.2.57 | 781 | * described in 802.11n D5.0 7.3.2.57 |
782 | */ | 782 | */ |
783 | struct ieee80211_ht_cap { | 783 | struct ieee80211_ht_cap { |
784 | __le16 cap_info; | 784 | __le16 cap_info; |
785 | u8 ampdu_params_info; | 785 | u8 ampdu_params_info; |
786 | 786 | ||
787 | /* 16 bytes MCS information */ | 787 | /* 16 bytes MCS information */ |
788 | struct ieee80211_mcs_info mcs; | 788 | struct ieee80211_mcs_info mcs; |
789 | 789 | ||
790 | __le16 extended_ht_cap_info; | 790 | __le16 extended_ht_cap_info; |
791 | __le32 tx_BF_cap_info; | 791 | __le32 tx_BF_cap_info; |
792 | u8 antenna_selection_info; | 792 | u8 antenna_selection_info; |
793 | } __attribute__ ((packed)); | 793 | } __attribute__ ((packed)); |
794 | 794 | ||
795 | /* 802.11n HT capabilities masks (for cap_info) */ | 795 | /* 802.11n HT capabilities masks (for cap_info) */ |
796 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 | 796 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 |
797 | #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 | 797 | #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 |
798 | #define IEEE80211_HT_CAP_SM_PS 0x000C | 798 | #define IEEE80211_HT_CAP_SM_PS 0x000C |
799 | #define IEEE80211_HT_CAP_GRN_FLD 0x0010 | 799 | #define IEEE80211_HT_CAP_GRN_FLD 0x0010 |
800 | #define IEEE80211_HT_CAP_SGI_20 0x0020 | 800 | #define IEEE80211_HT_CAP_SGI_20 0x0020 |
801 | #define IEEE80211_HT_CAP_SGI_40 0x0040 | 801 | #define IEEE80211_HT_CAP_SGI_40 0x0040 |
802 | #define IEEE80211_HT_CAP_TX_STBC 0x0080 | 802 | #define IEEE80211_HT_CAP_TX_STBC 0x0080 |
803 | #define IEEE80211_HT_CAP_RX_STBC 0x0300 | 803 | #define IEEE80211_HT_CAP_RX_STBC 0x0300 |
804 | #define IEEE80211_HT_CAP_DELAY_BA 0x0400 | 804 | #define IEEE80211_HT_CAP_DELAY_BA 0x0400 |
805 | #define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 | 805 | #define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 |
806 | #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 | 806 | #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 |
807 | #define IEEE80211_HT_CAP_PSMP_SUPPORT 0x2000 | 807 | #define IEEE80211_HT_CAP_PSMP_SUPPORT 0x2000 |
808 | #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 | 808 | #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 |
809 | #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 | 809 | #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 |
810 | 810 | ||
811 | /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ | 811 | /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ |
812 | #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 | 812 | #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 |
813 | #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C | 813 | #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C |
814 | 814 | ||
815 | /* | 815 | /* |
816 | * Maximum length of AMPDU that the STA can receive. | 816 | * Maximum length of AMPDU that the STA can receive. |
817 | * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) | 817 | * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) |
818 | */ | 818 | */ |
819 | enum ieee80211_max_ampdu_length_exp { | 819 | enum ieee80211_max_ampdu_length_exp { |
820 | IEEE80211_HT_MAX_AMPDU_8K = 0, | 820 | IEEE80211_HT_MAX_AMPDU_8K = 0, |
821 | IEEE80211_HT_MAX_AMPDU_16K = 1, | 821 | IEEE80211_HT_MAX_AMPDU_16K = 1, |
822 | IEEE80211_HT_MAX_AMPDU_32K = 2, | 822 | IEEE80211_HT_MAX_AMPDU_32K = 2, |
823 | IEEE80211_HT_MAX_AMPDU_64K = 3 | 823 | IEEE80211_HT_MAX_AMPDU_64K = 3 |
824 | }; | 824 | }; |
825 | 825 | ||
826 | #define IEEE80211_HT_MAX_AMPDU_FACTOR 13 | 826 | #define IEEE80211_HT_MAX_AMPDU_FACTOR 13 |
827 | 827 | ||
828 | /* Minimum MPDU start spacing */ | 828 | /* Minimum MPDU start spacing */ |
829 | enum ieee80211_min_mpdu_spacing { | 829 | enum ieee80211_min_mpdu_spacing { |
830 | IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ | 830 | IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ |
831 | IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ | 831 | IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ |
832 | IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ | 832 | IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ |
833 | IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ | 833 | IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ |
834 | IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ | 834 | IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ |
835 | IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ | 835 | IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ |
836 | IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ | 836 | IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ |
837 | IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ | 837 | IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ |
838 | }; | 838 | }; |
839 | 839 | ||
840 | /** | 840 | /** |
841 | * struct ieee80211_ht_info - HT information | 841 | * struct ieee80211_ht_info - HT information |
842 | * | 842 | * |
843 | * This structure is the "HT information element" as | 843 | * This structure is the "HT information element" as |
844 | * described in 802.11n D5.0 7.3.2.58 | 844 | * described in 802.11n D5.0 7.3.2.58 |
845 | */ | 845 | */ |
846 | struct ieee80211_ht_info { | 846 | struct ieee80211_ht_info { |
847 | u8 control_chan; | 847 | u8 control_chan; |
848 | u8 ht_param; | 848 | u8 ht_param; |
849 | __le16 operation_mode; | 849 | __le16 operation_mode; |
850 | __le16 stbc_param; | 850 | __le16 stbc_param; |
851 | u8 basic_set[16]; | 851 | u8 basic_set[16]; |
852 | } __attribute__ ((packed)); | 852 | } __attribute__ ((packed)); |
853 | 853 | ||
854 | /* for ht_param */ | 854 | /* for ht_param */ |
855 | #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 | 855 | #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 |
856 | #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 | 856 | #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 |
857 | #define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 | 857 | #define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 |
858 | #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 | 858 | #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 |
859 | #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 | 859 | #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 |
860 | #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 | 860 | #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 |
861 | #define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 | 861 | #define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 |
862 | #define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 | 862 | #define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 |
863 | 863 | ||
864 | /* for operation_mode */ | 864 | /* for operation_mode */ |
865 | #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 | 865 | #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 |
866 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 | 866 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 |
867 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 | 867 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 |
868 | #define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 | 868 | #define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 |
869 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 | 869 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 |
870 | #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 | 870 | #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 |
871 | #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 | 871 | #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 |
872 | 872 | ||
873 | /* for stbc_param */ | 873 | /* for stbc_param */ |
874 | #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 | 874 | #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 |
875 | #define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 | 875 | #define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 |
876 | #define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 | 876 | #define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 |
877 | #define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 | 877 | #define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 |
878 | #define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 | 878 | #define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 |
879 | #define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 | 879 | #define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 |
880 | 880 | ||
881 | 881 | ||
882 | /* block-ack parameters */ | 882 | /* block-ack parameters */ |
883 | #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 | 883 | #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 |
884 | #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C | 884 | #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C |
885 | #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 | 885 | #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 |
886 | #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 | 886 | #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 |
887 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 | 887 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 |
888 | 888 | ||
889 | /* | 889 | /* |
890 | * A-PMDU buffer sizes | 890 | * A-PMDU buffer sizes |
891 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) | 891 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) |
892 | */ | 892 | */ |
893 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | 893 | #define IEEE80211_MIN_AMPDU_BUF 0x8 |
894 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | 894 | #define IEEE80211_MAX_AMPDU_BUF 0x40 |
895 | 895 | ||
896 | 896 | ||
897 | /* Spatial Multiplexing Power Save Modes */ | 897 | /* Spatial Multiplexing Power Save Modes */ |
898 | #define WLAN_HT_CAP_SM_PS_STATIC 0 | 898 | #define WLAN_HT_CAP_SM_PS_STATIC 0 |
899 | #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 | 899 | #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 |
900 | #define WLAN_HT_CAP_SM_PS_INVALID 2 | 900 | #define WLAN_HT_CAP_SM_PS_INVALID 2 |
901 | #define WLAN_HT_CAP_SM_PS_DISABLED 3 | 901 | #define WLAN_HT_CAP_SM_PS_DISABLED 3 |
902 | 902 | ||
903 | /* Authentication algorithms */ | 903 | /* Authentication algorithms */ |
904 | #define WLAN_AUTH_OPEN 0 | 904 | #define WLAN_AUTH_OPEN 0 |
905 | #define WLAN_AUTH_SHARED_KEY 1 | 905 | #define WLAN_AUTH_SHARED_KEY 1 |
906 | #define WLAN_AUTH_FT 2 | 906 | #define WLAN_AUTH_FT 2 |
907 | #define WLAN_AUTH_LEAP 128 | 907 | #define WLAN_AUTH_LEAP 128 |
908 | 908 | ||
909 | #define WLAN_AUTH_CHALLENGE_LEN 128 | 909 | #define WLAN_AUTH_CHALLENGE_LEN 128 |
910 | 910 | ||
911 | #define WLAN_CAPABILITY_ESS (1<<0) | 911 | #define WLAN_CAPABILITY_ESS (1<<0) |
912 | #define WLAN_CAPABILITY_IBSS (1<<1) | 912 | #define WLAN_CAPABILITY_IBSS (1<<1) |
913 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) | 913 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) |
914 | #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) | 914 | #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) |
915 | #define WLAN_CAPABILITY_PRIVACY (1<<4) | 915 | #define WLAN_CAPABILITY_PRIVACY (1<<4) |
916 | #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) | 916 | #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) |
917 | #define WLAN_CAPABILITY_PBCC (1<<6) | 917 | #define WLAN_CAPABILITY_PBCC (1<<6) |
918 | #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) | 918 | #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) |
919 | 919 | ||
920 | /* 802.11h */ | 920 | /* 802.11h */ |
921 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) | 921 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) |
922 | #define WLAN_CAPABILITY_QOS (1<<9) | 922 | #define WLAN_CAPABILITY_QOS (1<<9) |
923 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) | 923 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) |
924 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) | 924 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) |
925 | /* measurement */ | 925 | /* measurement */ |
926 | #define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) | 926 | #define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) |
927 | #define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) | 927 | #define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) |
928 | #define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) | 928 | #define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) |
929 | 929 | ||
930 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 | 930 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 |
931 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 | 931 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 |
932 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 | 932 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 |
933 | 933 | ||
934 | 934 | ||
935 | /* 802.11g ERP information element */ | 935 | /* 802.11g ERP information element */ |
936 | #define WLAN_ERP_NON_ERP_PRESENT (1<<0) | 936 | #define WLAN_ERP_NON_ERP_PRESENT (1<<0) |
937 | #define WLAN_ERP_USE_PROTECTION (1<<1) | 937 | #define WLAN_ERP_USE_PROTECTION (1<<1) |
938 | #define WLAN_ERP_BARKER_PREAMBLE (1<<2) | 938 | #define WLAN_ERP_BARKER_PREAMBLE (1<<2) |
939 | 939 | ||
940 | /* WLAN_ERP_BARKER_PREAMBLE values */ | 940 | /* WLAN_ERP_BARKER_PREAMBLE values */ |
941 | enum { | 941 | enum { |
942 | WLAN_ERP_PREAMBLE_SHORT = 0, | 942 | WLAN_ERP_PREAMBLE_SHORT = 0, |
943 | WLAN_ERP_PREAMBLE_LONG = 1, | 943 | WLAN_ERP_PREAMBLE_LONG = 1, |
944 | }; | 944 | }; |
945 | 945 | ||
946 | /* Status codes */ | 946 | /* Status codes */ |
947 | enum ieee80211_statuscode { | 947 | enum ieee80211_statuscode { |
948 | WLAN_STATUS_SUCCESS = 0, | 948 | WLAN_STATUS_SUCCESS = 0, |
949 | WLAN_STATUS_UNSPECIFIED_FAILURE = 1, | 949 | WLAN_STATUS_UNSPECIFIED_FAILURE = 1, |
950 | WLAN_STATUS_CAPS_UNSUPPORTED = 10, | 950 | WLAN_STATUS_CAPS_UNSUPPORTED = 10, |
951 | WLAN_STATUS_REASSOC_NO_ASSOC = 11, | 951 | WLAN_STATUS_REASSOC_NO_ASSOC = 11, |
952 | WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, | 952 | WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, |
953 | WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, | 953 | WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, |
954 | WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, | 954 | WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, |
955 | WLAN_STATUS_CHALLENGE_FAIL = 15, | 955 | WLAN_STATUS_CHALLENGE_FAIL = 15, |
956 | WLAN_STATUS_AUTH_TIMEOUT = 16, | 956 | WLAN_STATUS_AUTH_TIMEOUT = 16, |
957 | WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, | 957 | WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, |
958 | WLAN_STATUS_ASSOC_DENIED_RATES = 18, | 958 | WLAN_STATUS_ASSOC_DENIED_RATES = 18, |
959 | /* 802.11b */ | 959 | /* 802.11b */ |
960 | WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, | 960 | WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, |
961 | WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, | 961 | WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, |
962 | WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, | 962 | WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, |
963 | /* 802.11h */ | 963 | /* 802.11h */ |
964 | WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, | 964 | WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, |
965 | WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, | 965 | WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, |
966 | WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, | 966 | WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, |
967 | /* 802.11g */ | 967 | /* 802.11g */ |
968 | WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, | 968 | WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, |
969 | WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, | 969 | WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, |
970 | /* 802.11w */ | 970 | /* 802.11w */ |
971 | WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30, | 971 | WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30, |
972 | WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31, | 972 | WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31, |
973 | /* 802.11i */ | 973 | /* 802.11i */ |
974 | WLAN_STATUS_INVALID_IE = 40, | 974 | WLAN_STATUS_INVALID_IE = 40, |
975 | WLAN_STATUS_INVALID_GROUP_CIPHER = 41, | 975 | WLAN_STATUS_INVALID_GROUP_CIPHER = 41, |
976 | WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, | 976 | WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, |
977 | WLAN_STATUS_INVALID_AKMP = 43, | 977 | WLAN_STATUS_INVALID_AKMP = 43, |
978 | WLAN_STATUS_UNSUPP_RSN_VERSION = 44, | 978 | WLAN_STATUS_UNSUPP_RSN_VERSION = 44, |
979 | WLAN_STATUS_INVALID_RSN_IE_CAP = 45, | 979 | WLAN_STATUS_INVALID_RSN_IE_CAP = 45, |
980 | WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, | 980 | WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, |
981 | /* 802.11e */ | 981 | /* 802.11e */ |
982 | WLAN_STATUS_UNSPECIFIED_QOS = 32, | 982 | WLAN_STATUS_UNSPECIFIED_QOS = 32, |
983 | WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, | 983 | WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, |
984 | WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, | 984 | WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, |
985 | WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, | 985 | WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, |
986 | WLAN_STATUS_REQUEST_DECLINED = 37, | 986 | WLAN_STATUS_REQUEST_DECLINED = 37, |
987 | WLAN_STATUS_INVALID_QOS_PARAM = 38, | 987 | WLAN_STATUS_INVALID_QOS_PARAM = 38, |
988 | WLAN_STATUS_CHANGE_TSPEC = 39, | 988 | WLAN_STATUS_CHANGE_TSPEC = 39, |
989 | WLAN_STATUS_WAIT_TS_DELAY = 47, | 989 | WLAN_STATUS_WAIT_TS_DELAY = 47, |
990 | WLAN_STATUS_NO_DIRECT_LINK = 48, | 990 | WLAN_STATUS_NO_DIRECT_LINK = 48, |
991 | WLAN_STATUS_STA_NOT_PRESENT = 49, | 991 | WLAN_STATUS_STA_NOT_PRESENT = 49, |
992 | WLAN_STATUS_STA_NOT_QSTA = 50, | 992 | WLAN_STATUS_STA_NOT_QSTA = 50, |
993 | }; | 993 | }; |
994 | 994 | ||
995 | 995 | ||
996 | /* Reason codes */ | 996 | /* Reason codes */ |
997 | enum ieee80211_reasoncode { | 997 | enum ieee80211_reasoncode { |
998 | WLAN_REASON_UNSPECIFIED = 1, | 998 | WLAN_REASON_UNSPECIFIED = 1, |
999 | WLAN_REASON_PREV_AUTH_NOT_VALID = 2, | 999 | WLAN_REASON_PREV_AUTH_NOT_VALID = 2, |
1000 | WLAN_REASON_DEAUTH_LEAVING = 3, | 1000 | WLAN_REASON_DEAUTH_LEAVING = 3, |
1001 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, | 1001 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, |
1002 | WLAN_REASON_DISASSOC_AP_BUSY = 5, | 1002 | WLAN_REASON_DISASSOC_AP_BUSY = 5, |
1003 | WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, | 1003 | WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, |
1004 | WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, | 1004 | WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, |
1005 | WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, | 1005 | WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, |
1006 | WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, | 1006 | WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, |
1007 | /* 802.11h */ | 1007 | /* 802.11h */ |
1008 | WLAN_REASON_DISASSOC_BAD_POWER = 10, | 1008 | WLAN_REASON_DISASSOC_BAD_POWER = 10, |
1009 | WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, | 1009 | WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, |
1010 | /* 802.11i */ | 1010 | /* 802.11i */ |
1011 | WLAN_REASON_INVALID_IE = 13, | 1011 | WLAN_REASON_INVALID_IE = 13, |
1012 | WLAN_REASON_MIC_FAILURE = 14, | 1012 | WLAN_REASON_MIC_FAILURE = 14, |
1013 | WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, | 1013 | WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, |
1014 | WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, | 1014 | WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, |
1015 | WLAN_REASON_IE_DIFFERENT = 17, | 1015 | WLAN_REASON_IE_DIFFERENT = 17, |
1016 | WLAN_REASON_INVALID_GROUP_CIPHER = 18, | 1016 | WLAN_REASON_INVALID_GROUP_CIPHER = 18, |
1017 | WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, | 1017 | WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, |
1018 | WLAN_REASON_INVALID_AKMP = 20, | 1018 | WLAN_REASON_INVALID_AKMP = 20, |
1019 | WLAN_REASON_UNSUPP_RSN_VERSION = 21, | 1019 | WLAN_REASON_UNSUPP_RSN_VERSION = 21, |
1020 | WLAN_REASON_INVALID_RSN_IE_CAP = 22, | 1020 | WLAN_REASON_INVALID_RSN_IE_CAP = 22, |
1021 | WLAN_REASON_IEEE8021X_FAILED = 23, | 1021 | WLAN_REASON_IEEE8021X_FAILED = 23, |
1022 | WLAN_REASON_CIPHER_SUITE_REJECTED = 24, | 1022 | WLAN_REASON_CIPHER_SUITE_REJECTED = 24, |
1023 | /* 802.11e */ | 1023 | /* 802.11e */ |
1024 | WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, | 1024 | WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, |
1025 | WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, | 1025 | WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, |
1026 | WLAN_REASON_DISASSOC_LOW_ACK = 34, | 1026 | WLAN_REASON_DISASSOC_LOW_ACK = 34, |
1027 | WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, | 1027 | WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, |
1028 | WLAN_REASON_QSTA_LEAVE_QBSS = 36, | 1028 | WLAN_REASON_QSTA_LEAVE_QBSS = 36, |
1029 | WLAN_REASON_QSTA_NOT_USE = 37, | 1029 | WLAN_REASON_QSTA_NOT_USE = 37, |
1030 | WLAN_REASON_QSTA_REQUIRE_SETUP = 38, | 1030 | WLAN_REASON_QSTA_REQUIRE_SETUP = 38, |
1031 | WLAN_REASON_QSTA_TIMEOUT = 39, | 1031 | WLAN_REASON_QSTA_TIMEOUT = 39, |
1032 | WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, | 1032 | WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, |
1033 | }; | 1033 | }; |
1034 | 1034 | ||
1035 | 1035 | ||
1036 | /* Information Element IDs */ | 1036 | /* Information Element IDs */ |
1037 | enum ieee80211_eid { | 1037 | enum ieee80211_eid { |
1038 | WLAN_EID_SSID = 0, | 1038 | WLAN_EID_SSID = 0, |
1039 | WLAN_EID_SUPP_RATES = 1, | 1039 | WLAN_EID_SUPP_RATES = 1, |
1040 | WLAN_EID_FH_PARAMS = 2, | 1040 | WLAN_EID_FH_PARAMS = 2, |
1041 | WLAN_EID_DS_PARAMS = 3, | 1041 | WLAN_EID_DS_PARAMS = 3, |
1042 | WLAN_EID_CF_PARAMS = 4, | 1042 | WLAN_EID_CF_PARAMS = 4, |
1043 | WLAN_EID_TIM = 5, | 1043 | WLAN_EID_TIM = 5, |
1044 | WLAN_EID_IBSS_PARAMS = 6, | 1044 | WLAN_EID_IBSS_PARAMS = 6, |
1045 | WLAN_EID_CHALLENGE = 16, | 1045 | WLAN_EID_CHALLENGE = 16, |
1046 | /* 802.11d */ | 1046 | /* 802.11d */ |
1047 | WLAN_EID_COUNTRY = 7, | 1047 | WLAN_EID_COUNTRY = 7, |
1048 | WLAN_EID_HP_PARAMS = 8, | 1048 | WLAN_EID_HP_PARAMS = 8, |
1049 | WLAN_EID_HP_TABLE = 9, | 1049 | WLAN_EID_HP_TABLE = 9, |
1050 | WLAN_EID_REQUEST = 10, | 1050 | WLAN_EID_REQUEST = 10, |
1051 | /* 802.11e */ | 1051 | /* 802.11e */ |
1052 | WLAN_EID_QBSS_LOAD = 11, | 1052 | WLAN_EID_QBSS_LOAD = 11, |
1053 | WLAN_EID_EDCA_PARAM_SET = 12, | 1053 | WLAN_EID_EDCA_PARAM_SET = 12, |
1054 | WLAN_EID_TSPEC = 13, | 1054 | WLAN_EID_TSPEC = 13, |
1055 | WLAN_EID_TCLAS = 14, | 1055 | WLAN_EID_TCLAS = 14, |
1056 | WLAN_EID_SCHEDULE = 15, | 1056 | WLAN_EID_SCHEDULE = 15, |
1057 | WLAN_EID_TS_DELAY = 43, | 1057 | WLAN_EID_TS_DELAY = 43, |
1058 | WLAN_EID_TCLAS_PROCESSING = 44, | 1058 | WLAN_EID_TCLAS_PROCESSING = 44, |
1059 | WLAN_EID_QOS_CAPA = 46, | 1059 | WLAN_EID_QOS_CAPA = 46, |
1060 | /* 802.11s | 1060 | /* 802.11s |
1061 | * | 1061 | * |
1062 | * All mesh EID numbers are pending IEEE 802.11 ANA approval. | 1062 | * All mesh EID numbers are pending IEEE 802.11 ANA approval. |
1063 | * The numbers have been incremented from those suggested in | 1063 | * The numbers have been incremented from those suggested in |
1064 | * 802.11s/D2.0 so that MESH_CONFIG does not conflict with | 1064 | * 802.11s/D2.0 so that MESH_CONFIG does not conflict with |
1065 | * EXT_SUPP_RATES. | 1065 | * EXT_SUPP_RATES. |
1066 | */ | 1066 | */ |
1067 | WLAN_EID_MESH_CONFIG = 51, | 1067 | WLAN_EID_MESH_CONFIG = 51, |
1068 | WLAN_EID_MESH_ID = 52, | 1068 | WLAN_EID_MESH_ID = 52, |
1069 | WLAN_EID_PEER_LINK = 55, | 1069 | WLAN_EID_PEER_LINK = 55, |
1070 | WLAN_EID_PREQ = 68, | 1070 | WLAN_EID_PREQ = 68, |
1071 | WLAN_EID_PREP = 69, | 1071 | WLAN_EID_PREP = 69, |
1072 | WLAN_EID_PERR = 70, | 1072 | WLAN_EID_PERR = 70, |
1073 | /* 802.11h */ | 1073 | /* 802.11h */ |
1074 | WLAN_EID_PWR_CONSTRAINT = 32, | 1074 | WLAN_EID_PWR_CONSTRAINT = 32, |
1075 | WLAN_EID_PWR_CAPABILITY = 33, | 1075 | WLAN_EID_PWR_CAPABILITY = 33, |
1076 | WLAN_EID_TPC_REQUEST = 34, | 1076 | WLAN_EID_TPC_REQUEST = 34, |
1077 | WLAN_EID_TPC_REPORT = 35, | 1077 | WLAN_EID_TPC_REPORT = 35, |
1078 | WLAN_EID_SUPPORTED_CHANNELS = 36, | 1078 | WLAN_EID_SUPPORTED_CHANNELS = 36, |
1079 | WLAN_EID_CHANNEL_SWITCH = 37, | 1079 | WLAN_EID_CHANNEL_SWITCH = 37, |
1080 | WLAN_EID_MEASURE_REQUEST = 38, | 1080 | WLAN_EID_MEASURE_REQUEST = 38, |
1081 | WLAN_EID_MEASURE_REPORT = 39, | 1081 | WLAN_EID_MEASURE_REPORT = 39, |
1082 | WLAN_EID_QUIET = 40, | 1082 | WLAN_EID_QUIET = 40, |
1083 | WLAN_EID_IBSS_DFS = 41, | 1083 | WLAN_EID_IBSS_DFS = 41, |
1084 | /* 802.11g */ | 1084 | /* 802.11g */ |
1085 | WLAN_EID_ERP_INFO = 42, | 1085 | WLAN_EID_ERP_INFO = 42, |
1086 | WLAN_EID_EXT_SUPP_RATES = 50, | 1086 | WLAN_EID_EXT_SUPP_RATES = 50, |
1087 | /* 802.11n */ | 1087 | /* 802.11n */ |
1088 | WLAN_EID_HT_CAPABILITY = 45, | 1088 | WLAN_EID_HT_CAPABILITY = 45, |
1089 | WLAN_EID_HT_INFORMATION = 61, | 1089 | WLAN_EID_HT_INFORMATION = 61, |
1090 | /* 802.11i */ | 1090 | /* 802.11i */ |
1091 | WLAN_EID_RSN = 48, | 1091 | WLAN_EID_RSN = 48, |
1092 | WLAN_EID_TIMEOUT_INTERVAL = 56, | 1092 | WLAN_EID_TIMEOUT_INTERVAL = 56, |
1093 | WLAN_EID_MMIE = 76 /* 802.11w */, | 1093 | WLAN_EID_MMIE = 76 /* 802.11w */, |
1094 | WLAN_EID_WPA = 221, | 1094 | WLAN_EID_WPA = 221, |
1095 | WLAN_EID_GENERIC = 221, | 1095 | WLAN_EID_GENERIC = 221, |
1096 | WLAN_EID_VENDOR_SPECIFIC = 221, | 1096 | WLAN_EID_VENDOR_SPECIFIC = 221, |
1097 | WLAN_EID_QOS_PARAMETER = 222 | 1097 | WLAN_EID_QOS_PARAMETER = 222 |
1098 | }; | 1098 | }; |
1099 | 1099 | ||
1100 | /* Action category code */ | 1100 | /* Action category code */ |
1101 | enum ieee80211_category { | 1101 | enum ieee80211_category { |
1102 | WLAN_CATEGORY_SPECTRUM_MGMT = 0, | 1102 | WLAN_CATEGORY_SPECTRUM_MGMT = 0, |
1103 | WLAN_CATEGORY_QOS = 1, | 1103 | WLAN_CATEGORY_QOS = 1, |
1104 | WLAN_CATEGORY_DLS = 2, | 1104 | WLAN_CATEGORY_DLS = 2, |
1105 | WLAN_CATEGORY_BACK = 3, | 1105 | WLAN_CATEGORY_BACK = 3, |
1106 | WLAN_CATEGORY_PUBLIC = 4, | 1106 | WLAN_CATEGORY_PUBLIC = 4, |
1107 | WLAN_CATEGORY_HT = 7, | 1107 | WLAN_CATEGORY_HT = 7, |
1108 | WLAN_CATEGORY_SA_QUERY = 8, | 1108 | WLAN_CATEGORY_SA_QUERY = 8, |
1109 | WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, | 1109 | WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, |
1110 | WLAN_CATEGORY_WMM = 17, | 1110 | WLAN_CATEGORY_WMM = 17, |
1111 | WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, | 1111 | WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, |
1112 | WLAN_CATEGORY_VENDOR_SPECIFIC = 127, | 1112 | WLAN_CATEGORY_VENDOR_SPECIFIC = 127, |
1113 | }; | 1113 | }; |
1114 | 1114 | ||
1115 | /* SPECTRUM_MGMT action code */ | 1115 | /* SPECTRUM_MGMT action code */ |
1116 | enum ieee80211_spectrum_mgmt_actioncode { | 1116 | enum ieee80211_spectrum_mgmt_actioncode { |
1117 | WLAN_ACTION_SPCT_MSR_REQ = 0, | 1117 | WLAN_ACTION_SPCT_MSR_REQ = 0, |
1118 | WLAN_ACTION_SPCT_MSR_RPRT = 1, | 1118 | WLAN_ACTION_SPCT_MSR_RPRT = 1, |
1119 | WLAN_ACTION_SPCT_TPC_REQ = 2, | 1119 | WLAN_ACTION_SPCT_TPC_REQ = 2, |
1120 | WLAN_ACTION_SPCT_TPC_RPRT = 3, | 1120 | WLAN_ACTION_SPCT_TPC_RPRT = 3, |
1121 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, | 1121 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, |
1122 | }; | 1122 | }; |
1123 | 1123 | ||
1124 | /* Security key length */ | 1124 | /* Security key length */ |
1125 | enum ieee80211_key_len { | 1125 | enum ieee80211_key_len { |
1126 | WLAN_KEY_LEN_WEP40 = 5, | 1126 | WLAN_KEY_LEN_WEP40 = 5, |
1127 | WLAN_KEY_LEN_WEP104 = 13, | 1127 | WLAN_KEY_LEN_WEP104 = 13, |
1128 | WLAN_KEY_LEN_CCMP = 16, | 1128 | WLAN_KEY_LEN_CCMP = 16, |
1129 | WLAN_KEY_LEN_TKIP = 32, | 1129 | WLAN_KEY_LEN_TKIP = 32, |
1130 | WLAN_KEY_LEN_AES_CMAC = 16, | 1130 | WLAN_KEY_LEN_AES_CMAC = 16, |
1131 | }; | 1131 | }; |
1132 | 1132 | ||
1133 | /* | 1133 | /* |
1134 | * IEEE 802.11-2007 7.3.2.9 Country information element | 1134 | * IEEE 802.11-2007 7.3.2.9 Country information element |
1135 | * | 1135 | * |
1136 | * Minimum length is 8 octets, ie len must be evenly | 1136 | * Minimum length is 8 octets, ie len must be evenly |
1137 | * divisible by 2 | 1137 | * divisible by 2 |
1138 | */ | 1138 | */ |
1139 | 1139 | ||
1140 | /* Although the spec says 8 I'm seeing 6 in practice */ | 1140 | /* Although the spec says 8 I'm seeing 6 in practice */ |
1141 | #define IEEE80211_COUNTRY_IE_MIN_LEN 6 | 1141 | #define IEEE80211_COUNTRY_IE_MIN_LEN 6 |
1142 | 1142 | ||
1143 | /* | 1143 | /* |
1144 | * For regulatory extension stuff see IEEE 802.11-2007 | 1144 | * For regulatory extension stuff see IEEE 802.11-2007 |
1145 | * Annex I (page 1141) and Annex J (page 1147). Also | 1145 | * Annex I (page 1141) and Annex J (page 1147). Also |
1146 | * review 7.3.2.9. | 1146 | * review 7.3.2.9. |
1147 | * | 1147 | * |
1148 | * When dot11RegulatoryClassesRequired is true and the | 1148 | * When dot11RegulatoryClassesRequired is true and the |
1149 | * first_channel/reg_extension_id is >= 201 then the IE | 1149 | * first_channel/reg_extension_id is >= 201 then the IE |
1150 | * compromises of the 'ext' struct represented below: | 1150 | * compromises of the 'ext' struct represented below: |
1151 | * | 1151 | * |
1152 | * - Regulatory extension ID - when generating IE this just needs | 1152 | * - Regulatory extension ID - when generating IE this just needs |
1153 | * to be monotonically increasing for each triplet passed in | 1153 | * to be monotonically increasing for each triplet passed in |
1154 | * the IE | 1154 | * the IE |
1155 | * - Regulatory class - index into set of rules | 1155 | * - Regulatory class - index into set of rules |
1156 | * - Coverage class - index into air propagation time (Table 7-27), | 1156 | * - Coverage class - index into air propagation time (Table 7-27), |
1157 | * in microseconds, you can compute the air propagation time from | 1157 | * in microseconds, you can compute the air propagation time from |
1158 | * the index by multiplying by 3, so index 10 yields a propagation | 1158 | * the index by multiplying by 3, so index 10 yields a propagation |
1159 | * of 10 us. Valid values are 0-31, values 32-255 are not defined | 1159 | * of 10 us. Valid values are 0-31, values 32-255 are not defined |
1160 | * yet. A value of 0 inicates air propagation of <= 1 us. | 1160 | * yet. A value of 0 inicates air propagation of <= 1 us. |
1161 | * | 1161 | * |
1162 | * See also Table I.2 for Emission limit sets and table | 1162 | * See also Table I.2 for Emission limit sets and table |
1163 | * I.3 for Behavior limit sets. Table J.1 indicates how to map | 1163 | * I.3 for Behavior limit sets. Table J.1 indicates how to map |
1164 | * a reg_class to an emission limit set and behavior limit set. | 1164 | * a reg_class to an emission limit set and behavior limit set. |
1165 | */ | 1165 | */ |
1166 | #define IEEE80211_COUNTRY_EXTENSION_ID 201 | 1166 | #define IEEE80211_COUNTRY_EXTENSION_ID 201 |
1167 | 1167 | ||
1168 | /* | 1168 | /* |
1169 | * Channels numbers in the IE must be monotonically increasing | 1169 | * Channels numbers in the IE must be monotonically increasing |
1170 | * if dot11RegulatoryClassesRequired is not true. | 1170 | * if dot11RegulatoryClassesRequired is not true. |
1171 | * | 1171 | * |
1172 | * If dot11RegulatoryClassesRequired is true consecutive | 1172 | * If dot11RegulatoryClassesRequired is true consecutive |
1173 | * subband triplets following a regulatory triplet shall | 1173 | * subband triplets following a regulatory triplet shall |
1174 | * have monotonically increasing first_channel number fields. | 1174 | * have monotonically increasing first_channel number fields. |
1175 | * | 1175 | * |
1176 | * Channel numbers shall not overlap. | 1176 | * Channel numbers shall not overlap. |
1177 | * | 1177 | * |
1178 | * Note that max_power is signed. | 1178 | * Note that max_power is signed. |
1179 | */ | 1179 | */ |
1180 | struct ieee80211_country_ie_triplet { | 1180 | struct ieee80211_country_ie_triplet { |
1181 | union { | 1181 | union { |
1182 | struct { | 1182 | struct { |
1183 | u8 first_channel; | 1183 | u8 first_channel; |
1184 | u8 num_channels; | 1184 | u8 num_channels; |
1185 | s8 max_power; | 1185 | s8 max_power; |
1186 | } __attribute__ ((packed)) chans; | 1186 | } __attribute__ ((packed)) chans; |
1187 | struct { | 1187 | struct { |
1188 | u8 reg_extension_id; | 1188 | u8 reg_extension_id; |
1189 | u8 reg_class; | 1189 | u8 reg_class; |
1190 | u8 coverage_class; | 1190 | u8 coverage_class; |
1191 | } __attribute__ ((packed)) ext; | 1191 | } __attribute__ ((packed)) ext; |
1192 | }; | 1192 | }; |
1193 | } __attribute__ ((packed)); | 1193 | } __attribute__ ((packed)); |
1194 | 1194 | ||
1195 | enum ieee80211_timeout_interval_type { | 1195 | enum ieee80211_timeout_interval_type { |
1196 | WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */, | 1196 | WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */, |
1197 | WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */, | 1197 | WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */, |
1198 | WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */, | 1198 | WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */, |
1199 | }; | 1199 | }; |
1200 | 1200 | ||
1201 | /* BACK action code */ | 1201 | /* BACK action code */ |
1202 | enum ieee80211_back_actioncode { | 1202 | enum ieee80211_back_actioncode { |
1203 | WLAN_ACTION_ADDBA_REQ = 0, | 1203 | WLAN_ACTION_ADDBA_REQ = 0, |
1204 | WLAN_ACTION_ADDBA_RESP = 1, | 1204 | WLAN_ACTION_ADDBA_RESP = 1, |
1205 | WLAN_ACTION_DELBA = 2, | 1205 | WLAN_ACTION_DELBA = 2, |
1206 | }; | 1206 | }; |
1207 | 1207 | ||
1208 | /* BACK (block-ack) parties */ | 1208 | /* BACK (block-ack) parties */ |
1209 | enum ieee80211_back_parties { | 1209 | enum ieee80211_back_parties { |
1210 | WLAN_BACK_RECIPIENT = 0, | 1210 | WLAN_BACK_RECIPIENT = 0, |
1211 | WLAN_BACK_INITIATOR = 1, | 1211 | WLAN_BACK_INITIATOR = 1, |
1212 | WLAN_BACK_TIMER = 2, | 1212 | WLAN_BACK_TIMER = 2, |
1213 | }; | 1213 | }; |
1214 | 1214 | ||
1215 | /* SA Query action */ | 1215 | /* SA Query action */ |
1216 | enum ieee80211_sa_query_action { | 1216 | enum ieee80211_sa_query_action { |
1217 | WLAN_ACTION_SA_QUERY_REQUEST = 0, | 1217 | WLAN_ACTION_SA_QUERY_REQUEST = 0, |
1218 | WLAN_ACTION_SA_QUERY_RESPONSE = 1, | 1218 | WLAN_ACTION_SA_QUERY_RESPONSE = 1, |
1219 | }; | 1219 | }; |
1220 | 1220 | ||
1221 | 1221 | ||
1222 | /* A-MSDU 802.11n */ | 1222 | /* A-MSDU 802.11n */ |
1223 | #define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 | 1223 | #define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 |
1224 | 1224 | ||
1225 | /* cipher suite selectors */ | 1225 | /* cipher suite selectors */ |
1226 | #define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 | 1226 | #define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 |
1227 | #define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 | 1227 | #define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 |
1228 | #define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 | 1228 | #define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 |
1229 | /* reserved: 0x000FAC03 */ | 1229 | /* reserved: 0x000FAC03 */ |
1230 | #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 | 1230 | #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 |
1231 | #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 | 1231 | #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 |
1232 | #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 | 1232 | #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 |
1233 | 1233 | ||
1234 | /* AKM suite selectors */ | 1234 | /* AKM suite selectors */ |
1235 | #define WLAN_AKM_SUITE_8021X 0x000FAC01 | 1235 | #define WLAN_AKM_SUITE_8021X 0x000FAC01 |
1236 | #define WLAN_AKM_SUITE_PSK 0x000FAC02 | 1236 | #define WLAN_AKM_SUITE_PSK 0x000FAC02 |
1237 | 1237 | ||
1238 | #define WLAN_MAX_KEY_LEN 32 | 1238 | #define WLAN_MAX_KEY_LEN 32 |
1239 | 1239 | ||
1240 | /** | 1240 | /** |
1241 | * ieee80211_get_qos_ctl - get pointer to qos control bytes | 1241 | * ieee80211_get_qos_ctl - get pointer to qos control bytes |
1242 | * @hdr: the frame | 1242 | * @hdr: the frame |
1243 | * | 1243 | * |
1244 | * The qos ctrl bytes come after the frame_control, duration, seq_num | 1244 | * The qos ctrl bytes come after the frame_control, duration, seq_num |
1245 | * and 3 or 4 addresses of length ETH_ALEN. | 1245 | * and 3 or 4 addresses of length ETH_ALEN. |
1246 | * 3 addr: 2 + 2 + 2 + 3*6 = 24 | 1246 | * 3 addr: 2 + 2 + 2 + 3*6 = 24 |
1247 | * 4 addr: 2 + 2 + 2 + 4*6 = 30 | 1247 | * 4 addr: 2 + 2 + 2 + 4*6 = 30 |
1248 | */ | 1248 | */ |
1249 | static inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) | 1249 | static inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) |
1250 | { | 1250 | { |
1251 | if (ieee80211_has_a4(hdr->frame_control)) | 1251 | if (ieee80211_has_a4(hdr->frame_control)) |
1252 | return (u8 *)hdr + 30; | 1252 | return (u8 *)hdr + 30; |
1253 | else | 1253 | else |
1254 | return (u8 *)hdr + 24; | 1254 | return (u8 *)hdr + 24; |
1255 | } | 1255 | } |
1256 | 1256 | ||
1257 | /** | 1257 | /** |
1258 | * ieee80211_get_SA - get pointer to SA | 1258 | * ieee80211_get_SA - get pointer to SA |
1259 | * @hdr: the frame | 1259 | * @hdr: the frame |
1260 | * | 1260 | * |
1261 | * Given an 802.11 frame, this function returns the offset | 1261 | * Given an 802.11 frame, this function returns the offset |
1262 | * to the source address (SA). It does not verify that the | 1262 | * to the source address (SA). It does not verify that the |
1263 | * header is long enough to contain the address, and the | 1263 | * header is long enough to contain the address, and the |
1264 | * header must be long enough to contain the frame control | 1264 | * header must be long enough to contain the frame control |
1265 | * field. | 1265 | * field. |
1266 | */ | 1266 | */ |
1267 | static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) | 1267 | static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) |
1268 | { | 1268 | { |
1269 | if (ieee80211_has_a4(hdr->frame_control)) | 1269 | if (ieee80211_has_a4(hdr->frame_control)) |
1270 | return hdr->addr4; | 1270 | return hdr->addr4; |
1271 | if (ieee80211_has_fromds(hdr->frame_control)) | 1271 | if (ieee80211_has_fromds(hdr->frame_control)) |
1272 | return hdr->addr3; | 1272 | return hdr->addr3; |
1273 | return hdr->addr2; | 1273 | return hdr->addr2; |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | /** | 1276 | /** |
1277 | * ieee80211_get_DA - get pointer to DA | 1277 | * ieee80211_get_DA - get pointer to DA |
1278 | * @hdr: the frame | 1278 | * @hdr: the frame |
1279 | * | 1279 | * |
1280 | * Given an 802.11 frame, this function returns the offset | 1280 | * Given an 802.11 frame, this function returns the offset |
1281 | * to the destination address (DA). It does not verify that | 1281 | * to the destination address (DA). It does not verify that |
1282 | * the header is long enough to contain the address, and the | 1282 | * the header is long enough to contain the address, and the |
1283 | * header must be long enough to contain the frame control | 1283 | * header must be long enough to contain the frame control |
1284 | * field. | 1284 | * field. |
1285 | */ | 1285 | */ |
1286 | static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) | 1286 | static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) |
1287 | { | 1287 | { |
1288 | if (ieee80211_has_tods(hdr->frame_control)) | 1288 | if (ieee80211_has_tods(hdr->frame_control)) |
1289 | return hdr->addr3; | 1289 | return hdr->addr3; |
1290 | else | 1290 | else |
1291 | return hdr->addr1; | 1291 | return hdr->addr1; |
1292 | } | 1292 | } |
1293 | 1293 | ||
1294 | /** | 1294 | /** |
1295 | * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame | 1295 | * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame |
1296 | * @hdr: the frame (buffer must include at least the first octet of payload) | 1296 | * @hdr: the frame (buffer must include at least the first octet of payload) |
1297 | */ | 1297 | */ |
1298 | static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) | 1298 | static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) |
1299 | { | 1299 | { |
1300 | if (ieee80211_is_disassoc(hdr->frame_control) || | 1300 | if (ieee80211_is_disassoc(hdr->frame_control) || |
1301 | ieee80211_is_deauth(hdr->frame_control)) | 1301 | ieee80211_is_deauth(hdr->frame_control)) |
1302 | return true; | 1302 | return true; |
1303 | 1303 | ||
1304 | if (ieee80211_is_action(hdr->frame_control)) { | 1304 | if (ieee80211_is_action(hdr->frame_control)) { |
1305 | u8 *category; | 1305 | u8 *category; |
1306 | 1306 | ||
1307 | /* | 1307 | /* |
1308 | * Action frames, excluding Public Action frames, are Robust | 1308 | * Action frames, excluding Public Action frames, are Robust |
1309 | * Management Frames. However, if we are looking at a Protected | 1309 | * Management Frames. However, if we are looking at a Protected |
1310 | * frame, skip the check since the data may be encrypted and | 1310 | * frame, skip the check since the data may be encrypted and |
1311 | * the frame has already been found to be a Robust Management | 1311 | * the frame has already been found to be a Robust Management |
1312 | * Frame (by the other end). | 1312 | * Frame (by the other end). |
1313 | */ | 1313 | */ |
1314 | if (ieee80211_has_protected(hdr->frame_control)) | 1314 | if (ieee80211_has_protected(hdr->frame_control)) |
1315 | return true; | 1315 | return true; |
1316 | category = ((u8 *) hdr) + 24; | 1316 | category = ((u8 *) hdr) + 24; |
1317 | return *category != WLAN_CATEGORY_PUBLIC && | 1317 | return *category != WLAN_CATEGORY_PUBLIC && |
1318 | *category != WLAN_CATEGORY_HT && | 1318 | *category != WLAN_CATEGORY_HT && |
1319 | *category != WLAN_CATEGORY_VENDOR_SPECIFIC; | 1319 | *category != WLAN_CATEGORY_VENDOR_SPECIFIC; |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | return false; | 1322 | return false; |
1323 | } | 1323 | } |
1324 | 1324 | ||
1325 | /** | 1325 | /** |
1326 | * ieee80211_fhss_chan_to_freq - get channel frequency | 1326 | * ieee80211_fhss_chan_to_freq - get channel frequency |
1327 | * @channel: the FHSS channel | 1327 | * @channel: the FHSS channel |
1328 | * | 1328 | * |
1329 | * Convert IEEE802.11 FHSS channel to frequency (MHz) | 1329 | * Convert IEEE802.11 FHSS channel to frequency (MHz) |
1330 | * Ref IEEE 802.11-2007 section 14.6 | 1330 | * Ref IEEE 802.11-2007 section 14.6 |
1331 | */ | 1331 | */ |
1332 | static inline int ieee80211_fhss_chan_to_freq(int channel) | 1332 | static inline int ieee80211_fhss_chan_to_freq(int channel) |
1333 | { | 1333 | { |
1334 | if ((channel > 1) && (channel < 96)) | 1334 | if ((channel > 1) && (channel < 96)) |
1335 | return channel + 2400; | 1335 | return channel + 2400; |
1336 | else | 1336 | else |
1337 | return -1; | 1337 | return -1; |
1338 | } | 1338 | } |
1339 | 1339 | ||
1340 | /** | 1340 | /** |
1341 | * ieee80211_freq_to_fhss_chan - get channel | 1341 | * ieee80211_freq_to_fhss_chan - get channel |
1342 | * @freq: the channels frequency | 1342 | * @freq: the channels frequency |
1343 | * | 1343 | * |
1344 | * Convert frequency (MHz) to IEEE802.11 FHSS channel | 1344 | * Convert frequency (MHz) to IEEE802.11 FHSS channel |
1345 | * Ref IEEE 802.11-2007 section 14.6 | 1345 | * Ref IEEE 802.11-2007 section 14.6 |
1346 | */ | 1346 | */ |
1347 | static inline int ieee80211_freq_to_fhss_chan(int freq) | 1347 | static inline int ieee80211_freq_to_fhss_chan(int freq) |
1348 | { | 1348 | { |
1349 | if ((freq > 2401) && (freq < 2496)) | 1349 | if ((freq > 2401) && (freq < 2496)) |
1350 | return freq - 2400; | 1350 | return freq - 2400; |
1351 | else | 1351 | else |
1352 | return -1; | 1352 | return -1; |
1353 | } | 1353 | } |
1354 | 1354 | ||
1355 | /** | 1355 | /** |
1356 | * ieee80211_dsss_chan_to_freq - get channel center frequency | 1356 | * ieee80211_dsss_chan_to_freq - get channel center frequency |
1357 | * @channel: the DSSS channel | 1357 | * @channel: the DSSS channel |
1358 | * | 1358 | * |
1359 | * Convert IEEE802.11 DSSS channel to the center frequency (MHz). | 1359 | * Convert IEEE802.11 DSSS channel to the center frequency (MHz). |
1360 | * Ref IEEE 802.11-2007 section 15.6 | 1360 | * Ref IEEE 802.11-2007 section 15.6 |
1361 | */ | 1361 | */ |
1362 | static inline int ieee80211_dsss_chan_to_freq(int channel) | 1362 | static inline int ieee80211_dsss_chan_to_freq(int channel) |
1363 | { | 1363 | { |
1364 | if ((channel > 0) && (channel < 14)) | 1364 | if ((channel > 0) && (channel < 14)) |
1365 | return 2407 + (channel * 5); | 1365 | return 2407 + (channel * 5); |
1366 | else if (channel == 14) | 1366 | else if (channel == 14) |
1367 | return 2484; | 1367 | return 2484; |
1368 | else | 1368 | else |
1369 | return -1; | 1369 | return -1; |
1370 | } | 1370 | } |
1371 | 1371 | ||
1372 | /** | 1372 | /** |
1373 | * ieee80211_freq_to_dsss_chan - get channel | 1373 | * ieee80211_freq_to_dsss_chan - get channel |
1374 | * @freq: the frequency | 1374 | * @freq: the frequency |
1375 | * | 1375 | * |
1376 | * Convert frequency (MHz) to IEEE802.11 DSSS channel | 1376 | * Convert frequency (MHz) to IEEE802.11 DSSS channel |
1377 | * Ref IEEE 802.11-2007 section 15.6 | 1377 | * Ref IEEE 802.11-2007 section 15.6 |
1378 | * | 1378 | * |
1379 | * This routine selects the channel with the closest center frequency. | 1379 | * This routine selects the channel with the closest center frequency. |
1380 | */ | 1380 | */ |
1381 | static inline int ieee80211_freq_to_dsss_chan(int freq) | 1381 | static inline int ieee80211_freq_to_dsss_chan(int freq) |
1382 | { | 1382 | { |
1383 | if ((freq >= 2410) && (freq < 2475)) | 1383 | if ((freq >= 2410) && (freq < 2475)) |
1384 | return (freq - 2405) / 5; | 1384 | return (freq - 2405) / 5; |
1385 | else if ((freq >= 2482) && (freq < 2487)) | 1385 | else if ((freq >= 2482) && (freq < 2487)) |
1386 | return 14; | 1386 | return 14; |
1387 | else | 1387 | else |
1388 | return -1; | 1388 | return -1; |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | /* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back | 1391 | /* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back |
1392 | * Ref IEEE 802.11-2007 section 18.4.6.2 | 1392 | * Ref IEEE 802.11-2007 section 18.4.6.2 |
1393 | * | 1393 | * |
1394 | * The channels and frequencies are the same as those defined for DSSS | 1394 | * The channels and frequencies are the same as those defined for DSSS |
1395 | */ | 1395 | */ |
1396 | #define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) | 1396 | #define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) |
1397 | #define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) | 1397 | #define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) |
1398 | 1398 | ||
1399 | /* Convert IEEE802.11 ERP channel to frequency (MHz) and back | 1399 | /* Convert IEEE802.11 ERP channel to frequency (MHz) and back |
1400 | * Ref IEEE 802.11-2007 section 19.4.2 | 1400 | * Ref IEEE 802.11-2007 section 19.4.2 |
1401 | */ | 1401 | */ |
1402 | #define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) | 1402 | #define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) |
1403 | #define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) | 1403 | #define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) |
1404 | 1404 | ||
1405 | /** | 1405 | /** |
1406 | * ieee80211_ofdm_chan_to_freq - get channel center frequency | 1406 | * ieee80211_ofdm_chan_to_freq - get channel center frequency |
1407 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz | 1407 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz |
1408 | * @channel: the OFDM channel | 1408 | * @channel: the OFDM channel |
1409 | * | 1409 | * |
1410 | * Convert IEEE802.11 OFDM channel to center frequency (MHz) | 1410 | * Convert IEEE802.11 OFDM channel to center frequency (MHz) |
1411 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 | 1411 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 |
1412 | */ | 1412 | */ |
1413 | static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) | 1413 | static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) |
1414 | { | 1414 | { |
1415 | if ((channel > 0) && (channel <= 200) && | 1415 | if ((channel > 0) && (channel <= 200) && |
1416 | (s_freq >= 4000)) | 1416 | (s_freq >= 4000)) |
1417 | return s_freq + (channel * 5); | 1417 | return s_freq + (channel * 5); |
1418 | else | 1418 | else |
1419 | return -1; | 1419 | return -1; |
1420 | } | 1420 | } |
1421 | 1421 | ||
1422 | /** | 1422 | /** |
1423 | * ieee80211_freq_to_ofdm_channel - get channel | 1423 | * ieee80211_freq_to_ofdm_channel - get channel |
1424 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz | 1424 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz |
1425 | * @freq: the frequency | 1425 | * @freq: the frequency |
1426 | * | 1426 | * |
1427 | * Convert frequency (MHz) to IEEE802.11 OFDM channel | 1427 | * Convert frequency (MHz) to IEEE802.11 OFDM channel |
1428 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 | 1428 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 |
1429 | * | 1429 | * |
1430 | * This routine selects the channel with the closest center frequency. | 1430 | * This routine selects the channel with the closest center frequency. |
1431 | */ | 1431 | */ |
1432 | static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) | 1432 | static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) |
1433 | { | 1433 | { |
1434 | if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && | 1434 | if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && |
1435 | (s_freq >= 4000)) | 1435 | (s_freq >= 4000)) |
1436 | return (freq + 2 - s_freq) / 5; | 1436 | return (freq + 2 - s_freq) / 5; |
1437 | else | 1437 | else |
1438 | return -1; | 1438 | return -1; |
1439 | } | 1439 | } |
1440 | 1440 | ||
1441 | /** | 1441 | /** |
1442 | * ieee80211_tu_to_usec - convert time units (TU) to microseconds | 1442 | * ieee80211_tu_to_usec - convert time units (TU) to microseconds |
1443 | * @tu: the TUs | 1443 | * @tu: the TUs |
1444 | */ | 1444 | */ |
1445 | static inline unsigned long ieee80211_tu_to_usec(unsigned long tu) | 1445 | static inline unsigned long ieee80211_tu_to_usec(unsigned long tu) |
1446 | { | 1446 | { |
1447 | return 1024 * tu; | 1447 | return 1024 * tu; |
1448 | } | 1448 | } |
1449 | 1449 | ||
1450 | /** | 1450 | /** |
1451 | * ieee80211_check_tim - check if AID bit is set in TIM | 1451 | * ieee80211_check_tim - check if AID bit is set in TIM |
1452 | * @tim: the TIM IE | 1452 | * @tim: the TIM IE |
1453 | * @tim_len: length of the TIM IE | 1453 | * @tim_len: length of the TIM IE |
1454 | * @aid: the AID to look for | 1454 | * @aid: the AID to look for |
1455 | */ | 1455 | */ |
1456 | static inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, | 1456 | static inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, |
1457 | u8 tim_len, u16 aid) | 1457 | u8 tim_len, u16 aid) |
1458 | { | 1458 | { |
1459 | u8 mask; | 1459 | u8 mask; |
1460 | u8 index, indexn1, indexn2; | 1460 | u8 index, indexn1, indexn2; |
1461 | 1461 | ||
1462 | if (unlikely(!tim || tim_len < sizeof(*tim))) | 1462 | if (unlikely(!tim || tim_len < sizeof(*tim))) |
1463 | return false; | 1463 | return false; |
1464 | 1464 | ||
1465 | aid &= 0x3fff; | 1465 | aid &= 0x3fff; |
1466 | index = aid / 8; | 1466 | index = aid / 8; |
1467 | mask = 1 << (aid & 7); | 1467 | mask = 1 << (aid & 7); |
1468 | 1468 | ||
1469 | indexn1 = tim->bitmap_ctrl & 0xfe; | 1469 | indexn1 = tim->bitmap_ctrl & 0xfe; |
1470 | indexn2 = tim_len + indexn1 - 4; | 1470 | indexn2 = tim_len + indexn1 - 4; |
1471 | 1471 | ||
1472 | if (index < indexn1 || index > indexn2) | 1472 | if (index < indexn1 || index > indexn2) |
1473 | return false; | 1473 | return false; |
1474 | 1474 | ||
1475 | index -= indexn1; | 1475 | index -= indexn1; |
1476 | 1476 | ||
1477 | return !!(tim->virtual_map[index] & mask); | 1477 | return !!(tim->virtual_map[index] & mask); |
1478 | } | 1478 | } |
1479 | 1479 | ||
1480 | #endif /* LINUX_IEEE80211_H */ | 1480 | #endif /* LINUX_IEEE80211_H */ |
1481 | 1481 |
net/mac80211/ieee80211_i.h
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef IEEE80211_I_H | 12 | #ifndef IEEE80211_I_H |
13 | #define IEEE80211_I_H | 13 | #define IEEE80211_I_H |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/if_ether.h> | 17 | #include <linux/if_ether.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <net/cfg80211.h> | 26 | #include <net/cfg80211.h> |
27 | #include <net/mac80211.h> | 27 | #include <net/mac80211.h> |
28 | #include "key.h" | 28 | #include "key.h" |
29 | #include "sta_info.h" | 29 | #include "sta_info.h" |
30 | 30 | ||
31 | struct ieee80211_local; | 31 | struct ieee80211_local; |
32 | 32 | ||
33 | /* Maximum number of broadcast/multicast frames to buffer when some of the | 33 | /* Maximum number of broadcast/multicast frames to buffer when some of the |
34 | * associated stations are using power saving. */ | 34 | * associated stations are using power saving. */ |
35 | #define AP_MAX_BC_BUFFER 128 | 35 | #define AP_MAX_BC_BUFFER 128 |
36 | 36 | ||
37 | /* Maximum number of frames buffered to all STAs, including multicast frames. | 37 | /* Maximum number of frames buffered to all STAs, including multicast frames. |
38 | * Note: increasing this limit increases the potential memory requirement. Each | 38 | * Note: increasing this limit increases the potential memory requirement. Each |
39 | * frame can be up to about 2 kB long. */ | 39 | * frame can be up to about 2 kB long. */ |
40 | #define TOTAL_MAX_TX_BUFFER 512 | 40 | #define TOTAL_MAX_TX_BUFFER 512 |
41 | 41 | ||
42 | /* Required encryption head and tailroom */ | 42 | /* Required encryption head and tailroom */ |
43 | #define IEEE80211_ENCRYPT_HEADROOM 8 | 43 | #define IEEE80211_ENCRYPT_HEADROOM 8 |
44 | #define IEEE80211_ENCRYPT_TAILROOM 18 | 44 | #define IEEE80211_ENCRYPT_TAILROOM 18 |
45 | 45 | ||
46 | /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent | 46 | /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent |
47 | * reception of at least three fragmented frames. This limit can be increased | 47 | * reception of at least three fragmented frames. This limit can be increased |
48 | * by changing this define, at the cost of slower frame reassembly and | 48 | * by changing this define, at the cost of slower frame reassembly and |
49 | * increased memory use (about 2 kB of RAM per entry). */ | 49 | * increased memory use (about 2 kB of RAM per entry). */ |
50 | #define IEEE80211_FRAGMENT_MAX 4 | 50 | #define IEEE80211_FRAGMENT_MAX 4 |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Time after which we ignore scan results and no longer report/use | 53 | * Time after which we ignore scan results and no longer report/use |
54 | * them in any way. | 54 | * them in any way. |
55 | */ | 55 | */ |
56 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | 56 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) |
57 | 57 | ||
58 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) | 58 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) |
59 | 59 | ||
60 | struct ieee80211_fragment_entry { | 60 | struct ieee80211_fragment_entry { |
61 | unsigned long first_frag_time; | 61 | unsigned long first_frag_time; |
62 | unsigned int seq; | 62 | unsigned int seq; |
63 | unsigned int rx_queue; | 63 | unsigned int rx_queue; |
64 | unsigned int last_frag; | 64 | unsigned int last_frag; |
65 | unsigned int extra_len; | 65 | unsigned int extra_len; |
66 | struct sk_buff_head skb_list; | 66 | struct sk_buff_head skb_list; |
67 | int ccmp; /* Whether fragments were encrypted with CCMP */ | 67 | int ccmp; /* Whether fragments were encrypted with CCMP */ |
68 | u8 last_pn[6]; /* PN of the last fragment if CCMP was used */ | 68 | u8 last_pn[6]; /* PN of the last fragment if CCMP was used */ |
69 | }; | 69 | }; |
70 | 70 | ||
71 | 71 | ||
72 | struct ieee80211_bss { | 72 | struct ieee80211_bss { |
73 | /* Yes, this is a hack */ | 73 | /* Yes, this is a hack */ |
74 | struct cfg80211_bss cbss; | 74 | struct cfg80211_bss cbss; |
75 | 75 | ||
76 | /* don't want to look up all the time */ | 76 | /* don't want to look up all the time */ |
77 | size_t ssid_len; | 77 | size_t ssid_len; |
78 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 78 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
79 | 79 | ||
80 | u8 dtim_period; | 80 | u8 dtim_period; |
81 | 81 | ||
82 | bool wmm_used; | 82 | bool wmm_used; |
83 | 83 | ||
84 | unsigned long last_probe_resp; | 84 | unsigned long last_probe_resp; |
85 | 85 | ||
86 | #ifdef CONFIG_MAC80211_MESH | 86 | #ifdef CONFIG_MAC80211_MESH |
87 | u8 *mesh_id; | 87 | u8 *mesh_id; |
88 | size_t mesh_id_len; | 88 | size_t mesh_id_len; |
89 | u8 *mesh_cfg; | 89 | u8 *mesh_cfg; |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | #define IEEE80211_MAX_SUPP_RATES 32 | 92 | #define IEEE80211_MAX_SUPP_RATES 32 |
93 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 93 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
94 | size_t supp_rates_len; | 94 | size_t supp_rates_len; |
95 | 95 | ||
96 | /* | 96 | /* |
97 | * During assocation, we save an ERP value from a probe response so | 97 | * During assocation, we save an ERP value from a probe response so |
98 | * that we can feed ERP info to the driver when handling the | 98 | * that we can feed ERP info to the driver when handling the |
99 | * association completes. these fields probably won't be up-to-date | 99 | * association completes. these fields probably won't be up-to-date |
100 | * otherwise, you probably don't want to use them. | 100 | * otherwise, you probably don't want to use them. |
101 | */ | 101 | */ |
102 | bool has_erp_value; | 102 | bool has_erp_value; |
103 | u8 erp_value; | 103 | u8 erp_value; |
104 | }; | 104 | }; |
105 | 105 | ||
106 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) | 106 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) |
107 | { | 107 | { |
108 | #ifdef CONFIG_MAC80211_MESH | 108 | #ifdef CONFIG_MAC80211_MESH |
109 | return bss->mesh_cfg; | 109 | return bss->mesh_cfg; |
110 | #endif | 110 | #endif |
111 | return NULL; | 111 | return NULL; |
112 | } | 112 | } |
113 | 113 | ||
114 | static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) | 114 | static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) |
115 | { | 115 | { |
116 | #ifdef CONFIG_MAC80211_MESH | 116 | #ifdef CONFIG_MAC80211_MESH |
117 | return bss->mesh_id; | 117 | return bss->mesh_id; |
118 | #endif | 118 | #endif |
119 | return NULL; | 119 | return NULL; |
120 | } | 120 | } |
121 | 121 | ||
122 | static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) | 122 | static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) |
123 | { | 123 | { |
124 | #ifdef CONFIG_MAC80211_MESH | 124 | #ifdef CONFIG_MAC80211_MESH |
125 | return bss->mesh_id_len; | 125 | return bss->mesh_id_len; |
126 | #endif | 126 | #endif |
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | 130 | ||
131 | typedef unsigned __bitwise__ ieee80211_tx_result; | 131 | typedef unsigned __bitwise__ ieee80211_tx_result; |
132 | #define TX_CONTINUE ((__force ieee80211_tx_result) 0u) | 132 | #define TX_CONTINUE ((__force ieee80211_tx_result) 0u) |
133 | #define TX_DROP ((__force ieee80211_tx_result) 1u) | 133 | #define TX_DROP ((__force ieee80211_tx_result) 1u) |
134 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) | 134 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) |
135 | 135 | ||
136 | #define IEEE80211_TX_FRAGMENTED BIT(0) | 136 | #define IEEE80211_TX_FRAGMENTED BIT(0) |
137 | #define IEEE80211_TX_UNICAST BIT(1) | 137 | #define IEEE80211_TX_UNICAST BIT(1) |
138 | #define IEEE80211_TX_PS_BUFFERED BIT(2) | 138 | #define IEEE80211_TX_PS_BUFFERED BIT(2) |
139 | 139 | ||
140 | struct ieee80211_tx_data { | 140 | struct ieee80211_tx_data { |
141 | struct sk_buff *skb; | 141 | struct sk_buff *skb; |
142 | struct net_device *dev; | 142 | struct net_device *dev; |
143 | struct ieee80211_local *local; | 143 | struct ieee80211_local *local; |
144 | struct ieee80211_sub_if_data *sdata; | 144 | struct ieee80211_sub_if_data *sdata; |
145 | struct sta_info *sta; | 145 | struct sta_info *sta; |
146 | struct ieee80211_key *key; | 146 | struct ieee80211_key *key; |
147 | 147 | ||
148 | struct ieee80211_channel *channel; | 148 | struct ieee80211_channel *channel; |
149 | 149 | ||
150 | u16 ethertype; | 150 | u16 ethertype; |
151 | unsigned int flags; | 151 | unsigned int flags; |
152 | }; | 152 | }; |
153 | 153 | ||
154 | 154 | ||
155 | typedef unsigned __bitwise__ ieee80211_rx_result; | 155 | typedef unsigned __bitwise__ ieee80211_rx_result; |
156 | #define RX_CONTINUE ((__force ieee80211_rx_result) 0u) | 156 | #define RX_CONTINUE ((__force ieee80211_rx_result) 0u) |
157 | #define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u) | 157 | #define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u) |
158 | #define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u) | 158 | #define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u) |
159 | #define RX_QUEUED ((__force ieee80211_rx_result) 3u) | 159 | #define RX_QUEUED ((__force ieee80211_rx_result) 3u) |
160 | 160 | ||
161 | #define IEEE80211_RX_IN_SCAN BIT(0) | 161 | #define IEEE80211_RX_IN_SCAN BIT(0) |
162 | /* frame is destined to interface currently processed (incl. multicast frames) */ | 162 | /* frame is destined to interface currently processed (incl. multicast frames) */ |
163 | #define IEEE80211_RX_RA_MATCH BIT(1) | 163 | #define IEEE80211_RX_RA_MATCH BIT(1) |
164 | #define IEEE80211_RX_AMSDU BIT(2) | 164 | #define IEEE80211_RX_AMSDU BIT(2) |
165 | #define IEEE80211_RX_CMNTR_REPORTED BIT(3) | 165 | #define IEEE80211_RX_CMNTR_REPORTED BIT(3) |
166 | #define IEEE80211_RX_FRAGMENTED BIT(4) | 166 | #define IEEE80211_RX_FRAGMENTED BIT(4) |
167 | 167 | ||
168 | struct ieee80211_rx_data { | 168 | struct ieee80211_rx_data { |
169 | struct sk_buff *skb; | 169 | struct sk_buff *skb; |
170 | struct net_device *dev; | 170 | struct net_device *dev; |
171 | struct ieee80211_local *local; | 171 | struct ieee80211_local *local; |
172 | struct ieee80211_sub_if_data *sdata; | 172 | struct ieee80211_sub_if_data *sdata; |
173 | struct sta_info *sta; | 173 | struct sta_info *sta; |
174 | struct ieee80211_key *key; | 174 | struct ieee80211_key *key; |
175 | struct ieee80211_rx_status *status; | 175 | struct ieee80211_rx_status *status; |
176 | struct ieee80211_rate *rate; | 176 | struct ieee80211_rate *rate; |
177 | 177 | ||
178 | unsigned int flags; | 178 | unsigned int flags; |
179 | int queue; | 179 | int queue; |
180 | u32 tkip_iv32; | 180 | u32 tkip_iv32; |
181 | u16 tkip_iv16; | 181 | u16 tkip_iv16; |
182 | }; | 182 | }; |
183 | 183 | ||
184 | struct beacon_data { | 184 | struct beacon_data { |
185 | u8 *head, *tail; | 185 | u8 *head, *tail; |
186 | int head_len, tail_len; | 186 | int head_len, tail_len; |
187 | int dtim_period; | 187 | int dtim_period; |
188 | }; | 188 | }; |
189 | 189 | ||
190 | struct ieee80211_if_ap { | 190 | struct ieee80211_if_ap { |
191 | struct beacon_data *beacon; | 191 | struct beacon_data *beacon; |
192 | 192 | ||
193 | struct list_head vlans; | 193 | struct list_head vlans; |
194 | 194 | ||
195 | /* yes, this looks ugly, but guarantees that we can later use | 195 | /* yes, this looks ugly, but guarantees that we can later use |
196 | * bitmap_empty :) | 196 | * bitmap_empty :) |
197 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ | 197 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ |
198 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 198 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; |
199 | struct sk_buff_head ps_bc_buf; | 199 | struct sk_buff_head ps_bc_buf; |
200 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 200 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
201 | int dtim_count; | 201 | int dtim_count; |
202 | }; | 202 | }; |
203 | 203 | ||
204 | struct ieee80211_if_wds { | 204 | struct ieee80211_if_wds { |
205 | struct sta_info *sta; | 205 | struct sta_info *sta; |
206 | u8 remote_addr[ETH_ALEN]; | 206 | u8 remote_addr[ETH_ALEN]; |
207 | }; | 207 | }; |
208 | 208 | ||
209 | struct ieee80211_if_vlan { | 209 | struct ieee80211_if_vlan { |
210 | struct list_head list; | 210 | struct list_head list; |
211 | }; | 211 | }; |
212 | 212 | ||
213 | struct mesh_stats { | 213 | struct mesh_stats { |
214 | __u32 fwded_mcast; /* Mesh forwarded multicast frames */ | 214 | __u32 fwded_mcast; /* Mesh forwarded multicast frames */ |
215 | __u32 fwded_unicast; /* Mesh forwarded unicast frames */ | 215 | __u32 fwded_unicast; /* Mesh forwarded unicast frames */ |
216 | __u32 fwded_frames; /* Mesh total forwarded frames */ | 216 | __u32 fwded_frames; /* Mesh total forwarded frames */ |
217 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ | 217 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ |
218 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ | 218 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ |
219 | atomic_t estab_plinks; | 219 | atomic_t estab_plinks; |
220 | }; | 220 | }; |
221 | 221 | ||
222 | #define PREQ_Q_F_START 0x1 | 222 | #define PREQ_Q_F_START 0x1 |
223 | #define PREQ_Q_F_REFRESH 0x2 | 223 | #define PREQ_Q_F_REFRESH 0x2 |
224 | struct mesh_preq_queue { | 224 | struct mesh_preq_queue { |
225 | struct list_head list; | 225 | struct list_head list; |
226 | u8 dst[ETH_ALEN]; | 226 | u8 dst[ETH_ALEN]; |
227 | u8 flags; | 227 | u8 flags; |
228 | }; | 228 | }; |
229 | 229 | ||
230 | enum ieee80211_mgd_state { | 230 | enum ieee80211_mgd_state { |
231 | IEEE80211_MGD_STATE_IDLE, | 231 | IEEE80211_MGD_STATE_IDLE, |
232 | IEEE80211_MGD_STATE_PROBE, | 232 | IEEE80211_MGD_STATE_PROBE, |
233 | IEEE80211_MGD_STATE_AUTH, | 233 | IEEE80211_MGD_STATE_AUTH, |
234 | IEEE80211_MGD_STATE_ASSOC, | 234 | IEEE80211_MGD_STATE_ASSOC, |
235 | }; | 235 | }; |
236 | 236 | ||
237 | struct ieee80211_mgd_work { | 237 | struct ieee80211_mgd_work { |
238 | struct list_head list; | 238 | struct list_head list; |
239 | struct ieee80211_bss *bss; | 239 | struct ieee80211_bss *bss; |
240 | int ie_len; | 240 | int ie_len; |
241 | u8 prev_bssid[ETH_ALEN]; | 241 | u8 prev_bssid[ETH_ALEN]; |
242 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 242 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
243 | u8 ssid_len; | 243 | u8 ssid_len; |
244 | unsigned long timeout; | 244 | unsigned long timeout; |
245 | enum ieee80211_mgd_state state; | 245 | enum ieee80211_mgd_state state; |
246 | u16 auth_alg, auth_transaction; | 246 | u16 auth_alg, auth_transaction; |
247 | 247 | ||
248 | int tries; | 248 | int tries; |
249 | 249 | ||
250 | u8 key[WLAN_KEY_LEN_WEP104]; | 250 | u8 key[WLAN_KEY_LEN_WEP104]; |
251 | u8 key_len, key_idx; | 251 | u8 key_len, key_idx; |
252 | 252 | ||
253 | /* must be last */ | 253 | /* must be last */ |
254 | u8 ie[0]; /* for auth or assoc frame, not probe */ | 254 | u8 ie[0]; /* for auth or assoc frame, not probe */ |
255 | }; | 255 | }; |
256 | 256 | ||
257 | /* flags used in struct ieee80211_if_managed.flags */ | 257 | /* flags used in struct ieee80211_if_managed.flags */ |
258 | enum ieee80211_sta_flags { | 258 | enum ieee80211_sta_flags { |
259 | IEEE80211_STA_BEACON_POLL = BIT(0), | 259 | IEEE80211_STA_BEACON_POLL = BIT(0), |
260 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 260 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
261 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 261 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
262 | IEEE80211_STA_WMM_ENABLED = BIT(3), | 262 | IEEE80211_STA_WMM_ENABLED = BIT(3), |
263 | IEEE80211_STA_DISABLE_11N = BIT(4), | 263 | IEEE80211_STA_DISABLE_11N = BIT(4), |
264 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | 264 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
265 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 265 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
266 | }; | 266 | }; |
267 | 267 | ||
268 | /* flags for MLME request */ | 268 | /* flags for MLME request */ |
269 | enum ieee80211_sta_request { | 269 | enum ieee80211_sta_request { |
270 | IEEE80211_STA_REQ_SCAN, | 270 | IEEE80211_STA_REQ_SCAN, |
271 | }; | 271 | }; |
272 | 272 | ||
273 | struct ieee80211_if_managed { | 273 | struct ieee80211_if_managed { |
274 | struct timer_list timer; | 274 | struct timer_list timer; |
275 | struct timer_list conn_mon_timer; | 275 | struct timer_list conn_mon_timer; |
276 | struct timer_list bcn_mon_timer; | 276 | struct timer_list bcn_mon_timer; |
277 | struct timer_list chswitch_timer; | 277 | struct timer_list chswitch_timer; |
278 | struct work_struct work; | 278 | struct work_struct work; |
279 | struct work_struct monitor_work; | 279 | struct work_struct monitor_work; |
280 | struct work_struct chswitch_work; | 280 | struct work_struct chswitch_work; |
281 | struct work_struct beacon_loss_work; | 281 | struct work_struct beacon_loss_work; |
282 | 282 | ||
283 | unsigned long probe_timeout; | 283 | unsigned long probe_timeout; |
284 | int probe_send_count; | 284 | int probe_send_count; |
285 | 285 | ||
286 | struct mutex mtx; | 286 | struct mutex mtx; |
287 | struct ieee80211_bss *associated; | 287 | struct ieee80211_bss *associated; |
288 | struct ieee80211_mgd_work *old_associate_work; | 288 | struct ieee80211_mgd_work *old_associate_work; |
289 | struct list_head work_list; | 289 | struct list_head work_list; |
290 | 290 | ||
291 | u8 bssid[ETH_ALEN]; | 291 | u8 bssid[ETH_ALEN]; |
292 | 292 | ||
293 | u16 aid; | 293 | u16 aid; |
294 | u16 capab; | 294 | u16 capab; |
295 | 295 | ||
296 | struct sk_buff_head skb_queue; | 296 | struct sk_buff_head skb_queue; |
297 | 297 | ||
298 | unsigned long timers_running; /* used for quiesce/restart */ | 298 | unsigned long timers_running; /* used for quiesce/restart */ |
299 | bool powersave; /* powersave requested for this iface */ | 299 | bool powersave; /* powersave requested for this iface */ |
300 | 300 | ||
301 | unsigned long request; | 301 | unsigned long request; |
302 | 302 | ||
303 | unsigned int flags; | 303 | unsigned int flags; |
304 | 304 | ||
305 | u32 beacon_crc; | 305 | u32 beacon_crc; |
306 | 306 | ||
307 | enum { | 307 | enum { |
308 | IEEE80211_MFP_DISABLED, | 308 | IEEE80211_MFP_DISABLED, |
309 | IEEE80211_MFP_OPTIONAL, | 309 | IEEE80211_MFP_OPTIONAL, |
310 | IEEE80211_MFP_REQUIRED | 310 | IEEE80211_MFP_REQUIRED |
311 | } mfp; /* management frame protection */ | 311 | } mfp; /* management frame protection */ |
312 | 312 | ||
313 | int wmm_last_param_set; | 313 | int wmm_last_param_set; |
314 | }; | 314 | }; |
315 | 315 | ||
316 | enum ieee80211_ibss_request { | 316 | enum ieee80211_ibss_request { |
317 | IEEE80211_IBSS_REQ_RUN = 0, | 317 | IEEE80211_IBSS_REQ_RUN = 0, |
318 | }; | 318 | }; |
319 | 319 | ||
320 | struct ieee80211_if_ibss { | 320 | struct ieee80211_if_ibss { |
321 | struct timer_list timer; | 321 | struct timer_list timer; |
322 | struct work_struct work; | 322 | struct work_struct work; |
323 | 323 | ||
324 | struct sk_buff_head skb_queue; | 324 | struct sk_buff_head skb_queue; |
325 | 325 | ||
326 | unsigned long request; | 326 | unsigned long request; |
327 | unsigned long last_scan_completed; | 327 | unsigned long last_scan_completed; |
328 | 328 | ||
329 | bool timer_running; | 329 | bool timer_running; |
330 | 330 | ||
331 | bool fixed_bssid; | 331 | bool fixed_bssid; |
332 | bool fixed_channel; | 332 | bool fixed_channel; |
333 | bool privacy; | 333 | bool privacy; |
334 | 334 | ||
335 | u8 bssid[ETH_ALEN]; | 335 | u8 bssid[ETH_ALEN]; |
336 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 336 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
337 | u8 ssid_len, ie_len; | 337 | u8 ssid_len, ie_len; |
338 | u8 *ie; | 338 | u8 *ie; |
339 | struct ieee80211_channel *channel; | 339 | struct ieee80211_channel *channel; |
340 | 340 | ||
341 | unsigned long ibss_join_req; | 341 | unsigned long ibss_join_req; |
342 | /* probe response/beacon for IBSS */ | 342 | /* probe response/beacon for IBSS */ |
343 | struct sk_buff *presp, *skb; | 343 | struct sk_buff *presp, *skb; |
344 | 344 | ||
345 | enum { | 345 | enum { |
346 | IEEE80211_IBSS_MLME_SEARCH, | 346 | IEEE80211_IBSS_MLME_SEARCH, |
347 | IEEE80211_IBSS_MLME_JOINED, | 347 | IEEE80211_IBSS_MLME_JOINED, |
348 | } state; | 348 | } state; |
349 | }; | 349 | }; |
350 | 350 | ||
351 | struct ieee80211_if_mesh { | 351 | struct ieee80211_if_mesh { |
352 | struct work_struct work; | 352 | struct work_struct work; |
353 | struct timer_list housekeeping_timer; | 353 | struct timer_list housekeeping_timer; |
354 | struct timer_list mesh_path_timer; | 354 | struct timer_list mesh_path_timer; |
355 | struct sk_buff_head skb_queue; | 355 | struct sk_buff_head skb_queue; |
356 | 356 | ||
357 | unsigned long timers_running; | 357 | unsigned long timers_running; |
358 | 358 | ||
359 | unsigned long wrkq_flags; | 359 | unsigned long wrkq_flags; |
360 | 360 | ||
361 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | 361 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; |
362 | size_t mesh_id_len; | 362 | size_t mesh_id_len; |
363 | /* Active Path Selection Protocol Identifier */ | 363 | /* Active Path Selection Protocol Identifier */ |
364 | u8 mesh_pp_id[4]; | 364 | u8 mesh_pp_id; |
365 | /* Active Path Selection Metric Identifier */ | 365 | /* Active Path Selection Metric Identifier */ |
366 | u8 mesh_pm_id[4]; | 366 | u8 mesh_pm_id; |
367 | /* Congestion Control Mode Identifier */ | 367 | /* Congestion Control Mode Identifier */ |
368 | u8 mesh_cc_id[4]; | 368 | u8 mesh_cc_id; |
369 | /* Synchronization Protocol Identifier */ | 369 | /* Synchronization Protocol Identifier */ |
370 | u8 mesh_sp_id[4]; | 370 | u8 mesh_sp_id; |
371 | /* Authentication Protocol Identifier */ | 371 | /* Authentication Protocol Identifier */ |
372 | u8 mesh_auth_id[4]; | 372 | u8 mesh_auth_id; |
373 | /* Local mesh Destination Sequence Number */ | 373 | /* Local mesh Destination Sequence Number */ |
374 | u32 dsn; | 374 | u32 dsn; |
375 | /* Last used PREQ ID */ | 375 | /* Last used PREQ ID */ |
376 | u32 preq_id; | 376 | u32 preq_id; |
377 | atomic_t mpaths; | 377 | atomic_t mpaths; |
378 | /* Timestamp of last DSN update */ | 378 | /* Timestamp of last DSN update */ |
379 | unsigned long last_dsn_update; | 379 | unsigned long last_dsn_update; |
380 | /* Timestamp of last DSN sent */ | 380 | /* Timestamp of last DSN sent */ |
381 | unsigned long last_preq; | 381 | unsigned long last_preq; |
382 | struct mesh_rmc *rmc; | 382 | struct mesh_rmc *rmc; |
383 | spinlock_t mesh_preq_queue_lock; | 383 | spinlock_t mesh_preq_queue_lock; |
384 | struct mesh_preq_queue preq_queue; | 384 | struct mesh_preq_queue preq_queue; |
385 | int preq_queue_len; | 385 | int preq_queue_len; |
386 | struct mesh_stats mshstats; | 386 | struct mesh_stats mshstats; |
387 | struct mesh_config mshcfg; | 387 | struct mesh_config mshcfg; |
388 | u32 mesh_seqnum; | 388 | u32 mesh_seqnum; |
389 | bool accepting_plinks; | 389 | bool accepting_plinks; |
390 | }; | 390 | }; |
391 | 391 | ||
392 | #ifdef CONFIG_MAC80211_MESH | 392 | #ifdef CONFIG_MAC80211_MESH |
393 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ | 393 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
394 | do { (msh)->mshstats.name++; } while (0) | 394 | do { (msh)->mshstats.name++; } while (0) |
395 | #else | 395 | #else |
396 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ | 396 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
397 | do { } while (0) | 397 | do { } while (0) |
398 | #endif | 398 | #endif |
399 | 399 | ||
400 | /** | 400 | /** |
401 | * enum ieee80211_sub_if_data_flags - virtual interface flags | 401 | * enum ieee80211_sub_if_data_flags - virtual interface flags |
402 | * | 402 | * |
403 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets | 403 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets |
404 | * @IEEE80211_SDATA_PROMISC: interface is promisc | 404 | * @IEEE80211_SDATA_PROMISC: interface is promisc |
405 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode | 405 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode |
406 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between | 406 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between |
407 | * associated stations and deliver multicast frames both | 407 | * associated stations and deliver multicast frames both |
408 | * back to wireless media and to the local net stack. | 408 | * back to wireless media and to the local net stack. |
409 | */ | 409 | */ |
410 | enum ieee80211_sub_if_data_flags { | 410 | enum ieee80211_sub_if_data_flags { |
411 | IEEE80211_SDATA_ALLMULTI = BIT(0), | 411 | IEEE80211_SDATA_ALLMULTI = BIT(0), |
412 | IEEE80211_SDATA_PROMISC = BIT(1), | 412 | IEEE80211_SDATA_PROMISC = BIT(1), |
413 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), | 413 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), |
414 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), | 414 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), |
415 | }; | 415 | }; |
416 | 416 | ||
417 | struct ieee80211_sub_if_data { | 417 | struct ieee80211_sub_if_data { |
418 | struct list_head list; | 418 | struct list_head list; |
419 | 419 | ||
420 | struct wireless_dev wdev; | 420 | struct wireless_dev wdev; |
421 | 421 | ||
422 | /* keys */ | 422 | /* keys */ |
423 | struct list_head key_list; | 423 | struct list_head key_list; |
424 | 424 | ||
425 | struct net_device *dev; | 425 | struct net_device *dev; |
426 | struct ieee80211_local *local; | 426 | struct ieee80211_local *local; |
427 | 427 | ||
428 | unsigned int flags; | 428 | unsigned int flags; |
429 | 429 | ||
430 | int drop_unencrypted; | 430 | int drop_unencrypted; |
431 | 431 | ||
432 | /* | 432 | /* |
433 | * keep track of whether the HT opmode (stored in | 433 | * keep track of whether the HT opmode (stored in |
434 | * vif.bss_info.ht_operation_mode) is valid. | 434 | * vif.bss_info.ht_operation_mode) is valid. |
435 | */ | 435 | */ |
436 | bool ht_opmode_valid; | 436 | bool ht_opmode_valid; |
437 | 437 | ||
438 | /* Fragment table for host-based reassembly */ | 438 | /* Fragment table for host-based reassembly */ |
439 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 439 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
440 | unsigned int fragment_next; | 440 | unsigned int fragment_next; |
441 | 441 | ||
442 | #define NUM_DEFAULT_KEYS 4 | 442 | #define NUM_DEFAULT_KEYS 4 |
443 | #define NUM_DEFAULT_MGMT_KEYS 2 | 443 | #define NUM_DEFAULT_MGMT_KEYS 2 |
444 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 444 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
445 | struct ieee80211_key *default_key; | 445 | struct ieee80211_key *default_key; |
446 | struct ieee80211_key *default_mgmt_key; | 446 | struct ieee80211_key *default_mgmt_key; |
447 | 447 | ||
448 | u16 sequence_number; | 448 | u16 sequence_number; |
449 | 449 | ||
450 | /* | 450 | /* |
451 | * AP this belongs to: self in AP mode and | 451 | * AP this belongs to: self in AP mode and |
452 | * corresponding AP in VLAN mode, NULL for | 452 | * corresponding AP in VLAN mode, NULL for |
453 | * all others (might be needed later in IBSS) | 453 | * all others (might be needed later in IBSS) |
454 | */ | 454 | */ |
455 | struct ieee80211_if_ap *bss; | 455 | struct ieee80211_if_ap *bss; |
456 | 456 | ||
457 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | 457 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ |
458 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | 458 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ |
459 | 459 | ||
460 | union { | 460 | union { |
461 | struct ieee80211_if_ap ap; | 461 | struct ieee80211_if_ap ap; |
462 | struct ieee80211_if_wds wds; | 462 | struct ieee80211_if_wds wds; |
463 | struct ieee80211_if_vlan vlan; | 463 | struct ieee80211_if_vlan vlan; |
464 | struct ieee80211_if_managed mgd; | 464 | struct ieee80211_if_managed mgd; |
465 | struct ieee80211_if_ibss ibss; | 465 | struct ieee80211_if_ibss ibss; |
466 | #ifdef CONFIG_MAC80211_MESH | 466 | #ifdef CONFIG_MAC80211_MESH |
467 | struct ieee80211_if_mesh mesh; | 467 | struct ieee80211_if_mesh mesh; |
468 | #endif | 468 | #endif |
469 | u32 mntr_flags; | 469 | u32 mntr_flags; |
470 | } u; | 470 | } u; |
471 | 471 | ||
472 | #ifdef CONFIG_MAC80211_DEBUGFS | 472 | #ifdef CONFIG_MAC80211_DEBUGFS |
473 | struct { | 473 | struct { |
474 | struct dentry *dir; | 474 | struct dentry *dir; |
475 | struct dentry *default_key; | 475 | struct dentry *default_key; |
476 | struct dentry *default_mgmt_key; | 476 | struct dentry *default_mgmt_key; |
477 | } debugfs; | 477 | } debugfs; |
478 | #endif | 478 | #endif |
479 | /* must be last, dynamically sized area in this! */ | 479 | /* must be last, dynamically sized area in this! */ |
480 | struct ieee80211_vif vif; | 480 | struct ieee80211_vif vif; |
481 | }; | 481 | }; |
482 | 482 | ||
483 | static inline | 483 | static inline |
484 | struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | 484 | struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) |
485 | { | 485 | { |
486 | return container_of(p, struct ieee80211_sub_if_data, vif); | 486 | return container_of(p, struct ieee80211_sub_if_data, vif); |
487 | } | 487 | } |
488 | 488 | ||
489 | static inline void | 489 | static inline void |
490 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | 490 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, |
491 | u8 mesh_id_len, u8 *mesh_id) | 491 | u8 mesh_id_len, u8 *mesh_id) |
492 | { | 492 | { |
493 | #ifdef CONFIG_MAC80211_MESH | 493 | #ifdef CONFIG_MAC80211_MESH |
494 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 494 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
495 | ifmsh->mesh_id_len = mesh_id_len; | 495 | ifmsh->mesh_id_len = mesh_id_len; |
496 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); | 496 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); |
497 | #else | 497 | #else |
498 | WARN_ON(1); | 498 | WARN_ON(1); |
499 | #endif | 499 | #endif |
500 | } | 500 | } |
501 | 501 | ||
502 | enum { | 502 | enum { |
503 | IEEE80211_RX_MSG = 1, | 503 | IEEE80211_RX_MSG = 1, |
504 | IEEE80211_TX_STATUS_MSG = 2, | 504 | IEEE80211_TX_STATUS_MSG = 2, |
505 | IEEE80211_DELBA_MSG = 3, | 505 | IEEE80211_DELBA_MSG = 3, |
506 | IEEE80211_ADDBA_MSG = 4, | 506 | IEEE80211_ADDBA_MSG = 4, |
507 | }; | 507 | }; |
508 | 508 | ||
509 | enum queue_stop_reason { | 509 | enum queue_stop_reason { |
510 | IEEE80211_QUEUE_STOP_REASON_DRIVER, | 510 | IEEE80211_QUEUE_STOP_REASON_DRIVER, |
511 | IEEE80211_QUEUE_STOP_REASON_PS, | 511 | IEEE80211_QUEUE_STOP_REASON_PS, |
512 | IEEE80211_QUEUE_STOP_REASON_CSA, | 512 | IEEE80211_QUEUE_STOP_REASON_CSA, |
513 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 513 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
514 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 514 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
515 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 515 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
516 | }; | 516 | }; |
517 | 517 | ||
518 | /** | 518 | /** |
519 | * mac80211 scan flags - currently active scan mode | 519 | * mac80211 scan flags - currently active scan mode |
520 | * | 520 | * |
521 | * @SCAN_SW_SCANNING: We're currently in the process of scanning but may as | 521 | * @SCAN_SW_SCANNING: We're currently in the process of scanning but may as |
522 | * well be on the operating channel | 522 | * well be on the operating channel |
523 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to | 523 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to |
524 | * determine if we are on the operating channel or not | 524 | * determine if we are on the operating channel or not |
525 | * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, | 525 | * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, |
526 | * gets only set in conjunction with SCAN_SW_SCANNING | 526 | * gets only set in conjunction with SCAN_SW_SCANNING |
527 | */ | 527 | */ |
528 | enum { | 528 | enum { |
529 | SCAN_SW_SCANNING, | 529 | SCAN_SW_SCANNING, |
530 | SCAN_HW_SCANNING, | 530 | SCAN_HW_SCANNING, |
531 | SCAN_OFF_CHANNEL, | 531 | SCAN_OFF_CHANNEL, |
532 | }; | 532 | }; |
533 | 533 | ||
534 | /** | 534 | /** |
535 | * enum mac80211_scan_state - scan state machine states | 535 | * enum mac80211_scan_state - scan state machine states |
536 | * | 536 | * |
537 | * @SCAN_DECISION: Main entry point to the scan state machine, this state | 537 | * @SCAN_DECISION: Main entry point to the scan state machine, this state |
538 | * determines if we should keep on scanning or switch back to the | 538 | * determines if we should keep on scanning or switch back to the |
539 | * operating channel | 539 | * operating channel |
540 | * @SCAN_SET_CHANNEL: Set the next channel to be scanned | 540 | * @SCAN_SET_CHANNEL: Set the next channel to be scanned |
541 | * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses | 541 | * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses |
542 | * @SCAN_LEAVE_OPER_CHANNEL: Leave the operating channel, notify the AP | 542 | * @SCAN_LEAVE_OPER_CHANNEL: Leave the operating channel, notify the AP |
543 | * about us leaving the channel and stop all associated STA interfaces | 543 | * about us leaving the channel and stop all associated STA interfaces |
544 | * @SCAN_ENTER_OPER_CHANNEL: Enter the operating channel again, notify the | 544 | * @SCAN_ENTER_OPER_CHANNEL: Enter the operating channel again, notify the |
545 | * AP about us being back and restart all associated STA interfaces | 545 | * AP about us being back and restart all associated STA interfaces |
546 | */ | 546 | */ |
547 | enum mac80211_scan_state { | 547 | enum mac80211_scan_state { |
548 | SCAN_DECISION, | 548 | SCAN_DECISION, |
549 | SCAN_SET_CHANNEL, | 549 | SCAN_SET_CHANNEL, |
550 | SCAN_SEND_PROBE, | 550 | SCAN_SEND_PROBE, |
551 | SCAN_LEAVE_OPER_CHANNEL, | 551 | SCAN_LEAVE_OPER_CHANNEL, |
552 | SCAN_ENTER_OPER_CHANNEL, | 552 | SCAN_ENTER_OPER_CHANNEL, |
553 | }; | 553 | }; |
554 | 554 | ||
555 | struct ieee80211_local { | 555 | struct ieee80211_local { |
556 | /* embed the driver visible part. | 556 | /* embed the driver visible part. |
557 | * don't cast (use the static inlines below), but we keep | 557 | * don't cast (use the static inlines below), but we keep |
558 | * it first anyway so they become a no-op */ | 558 | * it first anyway so they become a no-op */ |
559 | struct ieee80211_hw hw; | 559 | struct ieee80211_hw hw; |
560 | 560 | ||
561 | const struct ieee80211_ops *ops; | 561 | const struct ieee80211_ops *ops; |
562 | 562 | ||
563 | /* | 563 | /* |
564 | * private workqueue to mac80211. mac80211 makes this accessible | 564 | * private workqueue to mac80211. mac80211 makes this accessible |
565 | * via ieee80211_queue_work() | 565 | * via ieee80211_queue_work() |
566 | */ | 566 | */ |
567 | struct workqueue_struct *workqueue; | 567 | struct workqueue_struct *workqueue; |
568 | 568 | ||
569 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | 569 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; |
570 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 570 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
571 | spinlock_t queue_stop_reason_lock; | 571 | spinlock_t queue_stop_reason_lock; |
572 | 572 | ||
573 | int open_count; | 573 | int open_count; |
574 | int monitors, cooked_mntrs; | 574 | int monitors, cooked_mntrs; |
575 | /* number of interfaces with corresponding FIF_ flags */ | 575 | /* number of interfaces with corresponding FIF_ flags */ |
576 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; | 576 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; |
577 | unsigned int filter_flags; /* FIF_* */ | 577 | unsigned int filter_flags; /* FIF_* */ |
578 | struct iw_statistics wstats; | 578 | struct iw_statistics wstats; |
579 | 579 | ||
580 | /* protects the aggregated multicast list and filter calls */ | 580 | /* protects the aggregated multicast list and filter calls */ |
581 | spinlock_t filter_lock; | 581 | spinlock_t filter_lock; |
582 | 582 | ||
583 | /* used for uploading changed mc list */ | 583 | /* used for uploading changed mc list */ |
584 | struct work_struct reconfig_filter; | 584 | struct work_struct reconfig_filter; |
585 | 585 | ||
586 | /* aggregated multicast list */ | 586 | /* aggregated multicast list */ |
587 | struct dev_addr_list *mc_list; | 587 | struct dev_addr_list *mc_list; |
588 | int mc_count; | 588 | int mc_count; |
589 | 589 | ||
590 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 590 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
591 | 591 | ||
592 | /* | 592 | /* |
593 | * suspended is true if we finished all the suspend _and_ we have | 593 | * suspended is true if we finished all the suspend _and_ we have |
594 | * not yet come up from resume. This is to be used by mac80211 | 594 | * not yet come up from resume. This is to be used by mac80211 |
595 | * to ensure driver sanity during suspend and mac80211's own | 595 | * to ensure driver sanity during suspend and mac80211's own |
596 | * sanity. It can eventually be used for WoW as well. | 596 | * sanity. It can eventually be used for WoW as well. |
597 | */ | 597 | */ |
598 | bool suspended; | 598 | bool suspended; |
599 | 599 | ||
600 | /* | 600 | /* |
601 | * quiescing is true during the suspend process _only_ to | 601 | * quiescing is true during the suspend process _only_ to |
602 | * ease timer cancelling etc. | 602 | * ease timer cancelling etc. |
603 | */ | 603 | */ |
604 | bool quiescing; | 604 | bool quiescing; |
605 | 605 | ||
606 | /* device is started */ | 606 | /* device is started */ |
607 | bool started; | 607 | bool started; |
608 | 608 | ||
609 | int tx_headroom; /* required headroom for hardware/radiotap */ | 609 | int tx_headroom; /* required headroom for hardware/radiotap */ |
610 | 610 | ||
611 | /* Tasklet and skb queue to process calls from IRQ mode. All frames | 611 | /* Tasklet and skb queue to process calls from IRQ mode. All frames |
612 | * added to skb_queue will be processed, but frames in | 612 | * added to skb_queue will be processed, but frames in |
613 | * skb_queue_unreliable may be dropped if the total length of these | 613 | * skb_queue_unreliable may be dropped if the total length of these |
614 | * queues increases over the limit. */ | 614 | * queues increases over the limit. */ |
615 | #define IEEE80211_IRQSAFE_QUEUE_LIMIT 128 | 615 | #define IEEE80211_IRQSAFE_QUEUE_LIMIT 128 |
616 | struct tasklet_struct tasklet; | 616 | struct tasklet_struct tasklet; |
617 | struct sk_buff_head skb_queue; | 617 | struct sk_buff_head skb_queue; |
618 | struct sk_buff_head skb_queue_unreliable; | 618 | struct sk_buff_head skb_queue_unreliable; |
619 | 619 | ||
620 | /* Station data */ | 620 | /* Station data */ |
621 | /* | 621 | /* |
622 | * The lock only protects the list, hash, timer and counter | 622 | * The lock only protects the list, hash, timer and counter |
623 | * against manipulation, reads are done in RCU. Additionally, | 623 | * against manipulation, reads are done in RCU. Additionally, |
624 | * the lock protects each BSS's TIM bitmap. | 624 | * the lock protects each BSS's TIM bitmap. |
625 | */ | 625 | */ |
626 | spinlock_t sta_lock; | 626 | spinlock_t sta_lock; |
627 | unsigned long num_sta; | 627 | unsigned long num_sta; |
628 | struct list_head sta_list; | 628 | struct list_head sta_list; |
629 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 629 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
630 | struct timer_list sta_cleanup; | 630 | struct timer_list sta_cleanup; |
631 | int sta_generation; | 631 | int sta_generation; |
632 | 632 | ||
633 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 633 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
634 | struct tasklet_struct tx_pending_tasklet; | 634 | struct tasklet_struct tx_pending_tasklet; |
635 | 635 | ||
636 | /* | 636 | /* |
637 | * This lock is used to prevent concurrent A-MPDU | 637 | * This lock is used to prevent concurrent A-MPDU |
638 | * session start/stop processing, this thus also | 638 | * session start/stop processing, this thus also |
639 | * synchronises the ->ampdu_action() callback to | 639 | * synchronises the ->ampdu_action() callback to |
640 | * drivers and limits it to one at a time. | 640 | * drivers and limits it to one at a time. |
641 | */ | 641 | */ |
642 | spinlock_t ampdu_lock; | 642 | spinlock_t ampdu_lock; |
643 | 643 | ||
644 | /* number of interfaces with corresponding IFF_ flags */ | 644 | /* number of interfaces with corresponding IFF_ flags */ |
645 | atomic_t iff_allmultis, iff_promiscs; | 645 | atomic_t iff_allmultis, iff_promiscs; |
646 | 646 | ||
647 | struct rate_control_ref *rate_ctrl; | 647 | struct rate_control_ref *rate_ctrl; |
648 | 648 | ||
649 | struct crypto_blkcipher *wep_tx_tfm; | 649 | struct crypto_blkcipher *wep_tx_tfm; |
650 | struct crypto_blkcipher *wep_rx_tfm; | 650 | struct crypto_blkcipher *wep_rx_tfm; |
651 | u32 wep_iv; | 651 | u32 wep_iv; |
652 | 652 | ||
653 | /* see iface.c */ | 653 | /* see iface.c */ |
654 | struct list_head interfaces; | 654 | struct list_head interfaces; |
655 | struct mutex iflist_mtx; | 655 | struct mutex iflist_mtx; |
656 | 656 | ||
657 | /* | 657 | /* |
658 | * Key lock, protects sdata's key_list and sta_info's | 658 | * Key lock, protects sdata's key_list and sta_info's |
659 | * key pointers (write access, they're RCU.) | 659 | * key pointers (write access, they're RCU.) |
660 | */ | 660 | */ |
661 | spinlock_t key_lock; | 661 | spinlock_t key_lock; |
662 | 662 | ||
663 | 663 | ||
664 | /* Scanning and BSS list */ | 664 | /* Scanning and BSS list */ |
665 | struct mutex scan_mtx; | 665 | struct mutex scan_mtx; |
666 | unsigned long scanning; | 666 | unsigned long scanning; |
667 | struct cfg80211_ssid scan_ssid; | 667 | struct cfg80211_ssid scan_ssid; |
668 | struct cfg80211_scan_request *int_scan_req; | 668 | struct cfg80211_scan_request *int_scan_req; |
669 | struct cfg80211_scan_request *scan_req, *hw_scan_req; | 669 | struct cfg80211_scan_request *scan_req, *hw_scan_req; |
670 | struct ieee80211_channel *scan_channel; | 670 | struct ieee80211_channel *scan_channel; |
671 | enum ieee80211_band hw_scan_band; | 671 | enum ieee80211_band hw_scan_band; |
672 | int scan_channel_idx; | 672 | int scan_channel_idx; |
673 | int scan_ies_len; | 673 | int scan_ies_len; |
674 | 674 | ||
675 | enum mac80211_scan_state next_scan_state; | 675 | enum mac80211_scan_state next_scan_state; |
676 | struct delayed_work scan_work; | 676 | struct delayed_work scan_work; |
677 | struct ieee80211_sub_if_data *scan_sdata; | 677 | struct ieee80211_sub_if_data *scan_sdata; |
678 | enum nl80211_channel_type oper_channel_type; | 678 | enum nl80211_channel_type oper_channel_type; |
679 | struct ieee80211_channel *oper_channel, *csa_channel; | 679 | struct ieee80211_channel *oper_channel, *csa_channel; |
680 | 680 | ||
681 | /* SNMP counters */ | 681 | /* SNMP counters */ |
682 | /* dot11CountersTable */ | 682 | /* dot11CountersTable */ |
683 | u32 dot11TransmittedFragmentCount; | 683 | u32 dot11TransmittedFragmentCount; |
684 | u32 dot11MulticastTransmittedFrameCount; | 684 | u32 dot11MulticastTransmittedFrameCount; |
685 | u32 dot11FailedCount; | 685 | u32 dot11FailedCount; |
686 | u32 dot11RetryCount; | 686 | u32 dot11RetryCount; |
687 | u32 dot11MultipleRetryCount; | 687 | u32 dot11MultipleRetryCount; |
688 | u32 dot11FrameDuplicateCount; | 688 | u32 dot11FrameDuplicateCount; |
689 | u32 dot11ReceivedFragmentCount; | 689 | u32 dot11ReceivedFragmentCount; |
690 | u32 dot11MulticastReceivedFrameCount; | 690 | u32 dot11MulticastReceivedFrameCount; |
691 | u32 dot11TransmittedFrameCount; | 691 | u32 dot11TransmittedFrameCount; |
692 | 692 | ||
693 | #ifdef CONFIG_MAC80211_LEDS | 693 | #ifdef CONFIG_MAC80211_LEDS |
694 | int tx_led_counter, rx_led_counter; | 694 | int tx_led_counter, rx_led_counter; |
695 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; | 695 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; |
696 | char tx_led_name[32], rx_led_name[32], | 696 | char tx_led_name[32], rx_led_name[32], |
697 | assoc_led_name[32], radio_led_name[32]; | 697 | assoc_led_name[32], radio_led_name[32]; |
698 | #endif | 698 | #endif |
699 | 699 | ||
700 | #ifdef CONFIG_MAC80211_DEBUGFS | 700 | #ifdef CONFIG_MAC80211_DEBUGFS |
701 | struct work_struct sta_debugfs_add; | 701 | struct work_struct sta_debugfs_add; |
702 | #endif | 702 | #endif |
703 | 703 | ||
704 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 704 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
705 | /* TX/RX handler statistics */ | 705 | /* TX/RX handler statistics */ |
706 | unsigned int tx_handlers_drop; | 706 | unsigned int tx_handlers_drop; |
707 | unsigned int tx_handlers_queued; | 707 | unsigned int tx_handlers_queued; |
708 | unsigned int tx_handlers_drop_unencrypted; | 708 | unsigned int tx_handlers_drop_unencrypted; |
709 | unsigned int tx_handlers_drop_fragment; | 709 | unsigned int tx_handlers_drop_fragment; |
710 | unsigned int tx_handlers_drop_wep; | 710 | unsigned int tx_handlers_drop_wep; |
711 | unsigned int tx_handlers_drop_not_assoc; | 711 | unsigned int tx_handlers_drop_not_assoc; |
712 | unsigned int tx_handlers_drop_unauth_port; | 712 | unsigned int tx_handlers_drop_unauth_port; |
713 | unsigned int rx_handlers_drop; | 713 | unsigned int rx_handlers_drop; |
714 | unsigned int rx_handlers_queued; | 714 | unsigned int rx_handlers_queued; |
715 | unsigned int rx_handlers_drop_nullfunc; | 715 | unsigned int rx_handlers_drop_nullfunc; |
716 | unsigned int rx_handlers_drop_defrag; | 716 | unsigned int rx_handlers_drop_defrag; |
717 | unsigned int rx_handlers_drop_short; | 717 | unsigned int rx_handlers_drop_short; |
718 | unsigned int rx_handlers_drop_passive_scan; | 718 | unsigned int rx_handlers_drop_passive_scan; |
719 | unsigned int tx_expand_skb_head; | 719 | unsigned int tx_expand_skb_head; |
720 | unsigned int tx_expand_skb_head_cloned; | 720 | unsigned int tx_expand_skb_head_cloned; |
721 | unsigned int rx_expand_skb_head; | 721 | unsigned int rx_expand_skb_head; |
722 | unsigned int rx_expand_skb_head2; | 722 | unsigned int rx_expand_skb_head2; |
723 | unsigned int rx_handlers_fragments; | 723 | unsigned int rx_handlers_fragments; |
724 | unsigned int tx_status_drop; | 724 | unsigned int tx_status_drop; |
725 | #define I802_DEBUG_INC(c) (c)++ | 725 | #define I802_DEBUG_INC(c) (c)++ |
726 | #else /* CONFIG_MAC80211_DEBUG_COUNTERS */ | 726 | #else /* CONFIG_MAC80211_DEBUG_COUNTERS */ |
727 | #define I802_DEBUG_INC(c) do { } while (0) | 727 | #define I802_DEBUG_INC(c) do { } while (0) |
728 | #endif /* CONFIG_MAC80211_DEBUG_COUNTERS */ | 728 | #endif /* CONFIG_MAC80211_DEBUG_COUNTERS */ |
729 | 729 | ||
730 | 730 | ||
731 | int total_ps_buffered; /* total number of all buffered unicast and | 731 | int total_ps_buffered; /* total number of all buffered unicast and |
732 | * multicast packets for power saving stations | 732 | * multicast packets for power saving stations |
733 | */ | 733 | */ |
734 | int wifi_wme_noack_test; | 734 | int wifi_wme_noack_test; |
735 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 735 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
736 | 736 | ||
737 | bool pspolling; | 737 | bool pspolling; |
738 | /* | 738 | /* |
739 | * PS can only be enabled when we have exactly one managed | 739 | * PS can only be enabled when we have exactly one managed |
740 | * interface (and monitors) in PS, this then points there. | 740 | * interface (and monitors) in PS, this then points there. |
741 | */ | 741 | */ |
742 | struct ieee80211_sub_if_data *ps_sdata; | 742 | struct ieee80211_sub_if_data *ps_sdata; |
743 | struct work_struct dynamic_ps_enable_work; | 743 | struct work_struct dynamic_ps_enable_work; |
744 | struct work_struct dynamic_ps_disable_work; | 744 | struct work_struct dynamic_ps_disable_work; |
745 | struct timer_list dynamic_ps_timer; | 745 | struct timer_list dynamic_ps_timer; |
746 | struct notifier_block network_latency_notifier; | 746 | struct notifier_block network_latency_notifier; |
747 | 747 | ||
748 | int user_power_level; /* in dBm */ | 748 | int user_power_level; /* in dBm */ |
749 | int power_constr_level; /* in dBm */ | 749 | int power_constr_level; /* in dBm */ |
750 | 750 | ||
751 | struct work_struct restart_work; | 751 | struct work_struct restart_work; |
752 | 752 | ||
753 | #ifdef CONFIG_MAC80211_DEBUGFS | 753 | #ifdef CONFIG_MAC80211_DEBUGFS |
754 | struct local_debugfsdentries { | 754 | struct local_debugfsdentries { |
755 | struct dentry *rcdir; | 755 | struct dentry *rcdir; |
756 | struct dentry *stations; | 756 | struct dentry *stations; |
757 | struct dentry *keys; | 757 | struct dentry *keys; |
758 | } debugfs; | 758 | } debugfs; |
759 | #endif | 759 | #endif |
760 | }; | 760 | }; |
761 | 761 | ||
762 | static inline struct ieee80211_sub_if_data * | 762 | static inline struct ieee80211_sub_if_data * |
763 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | 763 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) |
764 | { | 764 | { |
765 | return netdev_priv(dev); | 765 | return netdev_priv(dev); |
766 | } | 766 | } |
767 | 767 | ||
768 | /* this struct represents 802.11n's RA/TID combination */ | 768 | /* this struct represents 802.11n's RA/TID combination */ |
769 | struct ieee80211_ra_tid { | 769 | struct ieee80211_ra_tid { |
770 | u8 ra[ETH_ALEN]; | 770 | u8 ra[ETH_ALEN]; |
771 | u16 tid; | 771 | u16 tid; |
772 | }; | 772 | }; |
773 | 773 | ||
774 | /* Parsed Information Elements */ | 774 | /* Parsed Information Elements */ |
775 | struct ieee802_11_elems { | 775 | struct ieee802_11_elems { |
776 | u8 *ie_start; | 776 | u8 *ie_start; |
777 | size_t total_len; | 777 | size_t total_len; |
778 | 778 | ||
779 | /* pointers to IEs */ | 779 | /* pointers to IEs */ |
780 | u8 *ssid; | 780 | u8 *ssid; |
781 | u8 *supp_rates; | 781 | u8 *supp_rates; |
782 | u8 *fh_params; | 782 | u8 *fh_params; |
783 | u8 *ds_params; | 783 | u8 *ds_params; |
784 | u8 *cf_params; | 784 | u8 *cf_params; |
785 | struct ieee80211_tim_ie *tim; | 785 | struct ieee80211_tim_ie *tim; |
786 | u8 *ibss_params; | 786 | u8 *ibss_params; |
787 | u8 *challenge; | 787 | u8 *challenge; |
788 | u8 *wpa; | 788 | u8 *wpa; |
789 | u8 *rsn; | 789 | u8 *rsn; |
790 | u8 *erp_info; | 790 | u8 *erp_info; |
791 | u8 *ext_supp_rates; | 791 | u8 *ext_supp_rates; |
792 | u8 *wmm_info; | 792 | u8 *wmm_info; |
793 | u8 *wmm_param; | 793 | u8 *wmm_param; |
794 | struct ieee80211_ht_cap *ht_cap_elem; | 794 | struct ieee80211_ht_cap *ht_cap_elem; |
795 | struct ieee80211_ht_info *ht_info_elem; | 795 | struct ieee80211_ht_info *ht_info_elem; |
796 | u8 *mesh_config; | 796 | u8 *mesh_config; |
797 | u8 *mesh_id; | 797 | u8 *mesh_id; |
798 | u8 *peer_link; | 798 | u8 *peer_link; |
799 | u8 *preq; | 799 | u8 *preq; |
800 | u8 *prep; | 800 | u8 *prep; |
801 | u8 *perr; | 801 | u8 *perr; |
802 | u8 *ch_switch_elem; | 802 | u8 *ch_switch_elem; |
803 | u8 *country_elem; | 803 | u8 *country_elem; |
804 | u8 *pwr_constr_elem; | 804 | u8 *pwr_constr_elem; |
805 | u8 *quiet_elem; /* first quite element */ | 805 | u8 *quiet_elem; /* first quite element */ |
806 | u8 *timeout_int; | 806 | u8 *timeout_int; |
807 | 807 | ||
808 | /* length of them, respectively */ | 808 | /* length of them, respectively */ |
809 | u8 ssid_len; | 809 | u8 ssid_len; |
810 | u8 supp_rates_len; | 810 | u8 supp_rates_len; |
811 | u8 fh_params_len; | 811 | u8 fh_params_len; |
812 | u8 ds_params_len; | 812 | u8 ds_params_len; |
813 | u8 cf_params_len; | 813 | u8 cf_params_len; |
814 | u8 tim_len; | 814 | u8 tim_len; |
815 | u8 ibss_params_len; | 815 | u8 ibss_params_len; |
816 | u8 challenge_len; | 816 | u8 challenge_len; |
817 | u8 wpa_len; | 817 | u8 wpa_len; |
818 | u8 rsn_len; | 818 | u8 rsn_len; |
819 | u8 erp_info_len; | 819 | u8 erp_info_len; |
820 | u8 ext_supp_rates_len; | 820 | u8 ext_supp_rates_len; |
821 | u8 wmm_info_len; | 821 | u8 wmm_info_len; |
822 | u8 wmm_param_len; | 822 | u8 wmm_param_len; |
823 | u8 mesh_config_len; | 823 | u8 mesh_config_len; |
824 | u8 mesh_id_len; | 824 | u8 mesh_id_len; |
825 | u8 peer_link_len; | 825 | u8 peer_link_len; |
826 | u8 preq_len; | 826 | u8 preq_len; |
827 | u8 prep_len; | 827 | u8 prep_len; |
828 | u8 perr_len; | 828 | u8 perr_len; |
829 | u8 ch_switch_elem_len; | 829 | u8 ch_switch_elem_len; |
830 | u8 country_elem_len; | 830 | u8 country_elem_len; |
831 | u8 pwr_constr_elem_len; | 831 | u8 pwr_constr_elem_len; |
832 | u8 quiet_elem_len; | 832 | u8 quiet_elem_len; |
833 | u8 num_of_quiet_elem; /* can be more the one */ | 833 | u8 num_of_quiet_elem; /* can be more the one */ |
834 | u8 timeout_int_len; | 834 | u8 timeout_int_len; |
835 | }; | 835 | }; |
836 | 836 | ||
837 | static inline struct ieee80211_local *hw_to_local( | 837 | static inline struct ieee80211_local *hw_to_local( |
838 | struct ieee80211_hw *hw) | 838 | struct ieee80211_hw *hw) |
839 | { | 839 | { |
840 | return container_of(hw, struct ieee80211_local, hw); | 840 | return container_of(hw, struct ieee80211_local, hw); |
841 | } | 841 | } |
842 | 842 | ||
843 | static inline struct ieee80211_hw *local_to_hw( | 843 | static inline struct ieee80211_hw *local_to_hw( |
844 | struct ieee80211_local *local) | 844 | struct ieee80211_local *local) |
845 | { | 845 | { |
846 | return &local->hw; | 846 | return &local->hw; |
847 | } | 847 | } |
848 | 848 | ||
849 | 849 | ||
850 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | 850 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) |
851 | { | 851 | { |
852 | return compare_ether_addr(raddr, addr) == 0 || | 852 | return compare_ether_addr(raddr, addr) == 0 || |
853 | is_broadcast_ether_addr(raddr); | 853 | is_broadcast_ether_addr(raddr); |
854 | } | 854 | } |
855 | 855 | ||
856 | 856 | ||
857 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); | 857 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); |
858 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 858 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
859 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 859 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, |
860 | u32 changed); | 860 | u32 changed); |
861 | void ieee80211_configure_filter(struct ieee80211_local *local); | 861 | void ieee80211_configure_filter(struct ieee80211_local *local); |
862 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 862 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
863 | 863 | ||
864 | /* STA code */ | 864 | /* STA code */ |
865 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); | 865 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
866 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 866 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
867 | struct cfg80211_auth_request *req); | 867 | struct cfg80211_auth_request *req); |
868 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | 868 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
869 | struct cfg80211_assoc_request *req); | 869 | struct cfg80211_assoc_request *req); |
870 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | 870 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, |
871 | struct cfg80211_deauth_request *req, | 871 | struct cfg80211_deauth_request *req, |
872 | void *cookie); | 872 | void *cookie); |
873 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 873 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, |
874 | struct cfg80211_disassoc_request *req, | 874 | struct cfg80211_disassoc_request *req, |
875 | void *cookie); | 875 | void *cookie); |
876 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 876 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, |
877 | struct sk_buff *skb); | 877 | struct sk_buff *skb); |
878 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 878 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
879 | struct ieee80211_sub_if_data *sdata); | 879 | struct ieee80211_sub_if_data *sdata); |
880 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); | 880 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); |
881 | int ieee80211_max_network_latency(struct notifier_block *nb, | 881 | int ieee80211_max_network_latency(struct notifier_block *nb, |
882 | unsigned long data, void *dummy); | 882 | unsigned long data, void *dummy); |
883 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 883 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
884 | struct ieee80211_channel_sw_ie *sw_elem, | 884 | struct ieee80211_channel_sw_ie *sw_elem, |
885 | struct ieee80211_bss *bss); | 885 | struct ieee80211_bss *bss); |
886 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); | 886 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); |
887 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | 887 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); |
888 | 888 | ||
889 | /* IBSS code */ | 889 | /* IBSS code */ |
890 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 890 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
891 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | 891 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); |
892 | ieee80211_rx_result | 892 | ieee80211_rx_result |
893 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 893 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
894 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 894 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
895 | u8 *bssid, u8 *addr, u32 supp_rates); | 895 | u8 *bssid, u8 *addr, u32 supp_rates); |
896 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 896 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
897 | struct cfg80211_ibss_params *params); | 897 | struct cfg80211_ibss_params *params); |
898 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 898 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
899 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); | 899 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); |
900 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); | 900 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); |
901 | 901 | ||
902 | /* scan/BSS handling */ | 902 | /* scan/BSS handling */ |
903 | void ieee80211_scan_work(struct work_struct *work); | 903 | void ieee80211_scan_work(struct work_struct *work); |
904 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 904 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, |
905 | const u8 *ssid, u8 ssid_len); | 905 | const u8 *ssid, u8 ssid_len); |
906 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 906 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
907 | struct cfg80211_scan_request *req); | 907 | struct cfg80211_scan_request *req); |
908 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 908 | void ieee80211_scan_cancel(struct ieee80211_local *local); |
909 | ieee80211_rx_result | 909 | ieee80211_rx_result |
910 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 910 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
911 | 911 | ||
912 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | 912 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); |
913 | struct ieee80211_bss * | 913 | struct ieee80211_bss * |
914 | ieee80211_bss_info_update(struct ieee80211_local *local, | 914 | ieee80211_bss_info_update(struct ieee80211_local *local, |
915 | struct ieee80211_rx_status *rx_status, | 915 | struct ieee80211_rx_status *rx_status, |
916 | struct ieee80211_mgmt *mgmt, | 916 | struct ieee80211_mgmt *mgmt, |
917 | size_t len, | 917 | size_t len, |
918 | struct ieee802_11_elems *elems, | 918 | struct ieee802_11_elems *elems, |
919 | struct ieee80211_channel *channel, | 919 | struct ieee80211_channel *channel, |
920 | bool beacon); | 920 | bool beacon); |
921 | struct ieee80211_bss * | 921 | struct ieee80211_bss * |
922 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 922 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
923 | u8 *ssid, u8 ssid_len); | 923 | u8 *ssid, u8 ssid_len); |
924 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 924 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
925 | struct ieee80211_bss *bss); | 925 | struct ieee80211_bss *bss); |
926 | 926 | ||
927 | /* interface handling */ | 927 | /* interface handling */ |
928 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 928 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
929 | struct net_device **new_dev, enum nl80211_iftype type, | 929 | struct net_device **new_dev, enum nl80211_iftype type, |
930 | struct vif_params *params); | 930 | struct vif_params *params); |
931 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 931 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
932 | enum nl80211_iftype type); | 932 | enum nl80211_iftype type); |
933 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | 933 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
934 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 934 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
935 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); | 935 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); |
936 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 936 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
937 | 937 | ||
938 | /* tx handling */ | 938 | /* tx handling */ |
939 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 939 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
940 | void ieee80211_tx_pending(unsigned long data); | 940 | void ieee80211_tx_pending(unsigned long data); |
941 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | 941 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, |
942 | struct net_device *dev); | 942 | struct net_device *dev); |
943 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | 943 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, |
944 | struct net_device *dev); | 944 | struct net_device *dev); |
945 | 945 | ||
946 | /* HT */ | 946 | /* HT */ |
947 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 947 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, |
948 | struct ieee80211_ht_cap *ht_cap_ie, | 948 | struct ieee80211_ht_cap *ht_cap_ie, |
949 | struct ieee80211_sta_ht_cap *ht_cap); | 949 | struct ieee80211_sta_ht_cap *ht_cap); |
950 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); | 950 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); |
951 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 951 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
952 | const u8 *da, u16 tid, | 952 | const u8 *da, u16 tid, |
953 | u16 initiator, u16 reason_code); | 953 | u16 initiator, u16 reason_code); |
954 | 954 | ||
955 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | 955 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, |
956 | u16 tid, u16 initiator, u16 reason); | 956 | u16 tid, u16 initiator, u16 reason); |
957 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 957 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
958 | u16 initiator, u16 reason); | 958 | u16 initiator, u16 reason); |
959 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | 959 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); |
960 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 960 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
961 | struct sta_info *sta, | 961 | struct sta_info *sta, |
962 | struct ieee80211_mgmt *mgmt, size_t len); | 962 | struct ieee80211_mgmt *mgmt, size_t len); |
963 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | 963 | void ieee80211_process_addba_resp(struct ieee80211_local *local, |
964 | struct sta_info *sta, | 964 | struct sta_info *sta, |
965 | struct ieee80211_mgmt *mgmt, | 965 | struct ieee80211_mgmt *mgmt, |
966 | size_t len); | 966 | size_t len); |
967 | void ieee80211_process_addba_request(struct ieee80211_local *local, | 967 | void ieee80211_process_addba_request(struct ieee80211_local *local, |
968 | struct sta_info *sta, | 968 | struct sta_info *sta, |
969 | struct ieee80211_mgmt *mgmt, | 969 | struct ieee80211_mgmt *mgmt, |
970 | size_t len); | 970 | size_t len); |
971 | 971 | ||
972 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 972 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
973 | enum ieee80211_back_parties initiator); | 973 | enum ieee80211_back_parties initiator); |
974 | 974 | ||
975 | /* Spectrum management */ | 975 | /* Spectrum management */ |
976 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 976 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
977 | struct ieee80211_mgmt *mgmt, | 977 | struct ieee80211_mgmt *mgmt, |
978 | size_t len); | 978 | size_t len); |
979 | 979 | ||
980 | /* Suspend/resume and hw reconfiguration */ | 980 | /* Suspend/resume and hw reconfiguration */ |
981 | int ieee80211_reconfig(struct ieee80211_local *local); | 981 | int ieee80211_reconfig(struct ieee80211_local *local); |
982 | void ieee80211_stop_device(struct ieee80211_local *local); | 982 | void ieee80211_stop_device(struct ieee80211_local *local); |
983 | 983 | ||
984 | #ifdef CONFIG_PM | 984 | #ifdef CONFIG_PM |
985 | int __ieee80211_suspend(struct ieee80211_hw *hw); | 985 | int __ieee80211_suspend(struct ieee80211_hw *hw); |
986 | 986 | ||
987 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) | 987 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) |
988 | { | 988 | { |
989 | return ieee80211_reconfig(hw_to_local(hw)); | 989 | return ieee80211_reconfig(hw_to_local(hw)); |
990 | } | 990 | } |
991 | #else | 991 | #else |
992 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw) | 992 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw) |
993 | { | 993 | { |
994 | return 0; | 994 | return 0; |
995 | } | 995 | } |
996 | 996 | ||
997 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) | 997 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) |
998 | { | 998 | { |
999 | return 0; | 999 | return 0; |
1000 | } | 1000 | } |
1001 | #endif | 1001 | #endif |
1002 | 1002 | ||
1003 | /* utility functions/constants */ | 1003 | /* utility functions/constants */ |
1004 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1004 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
1005 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 1005 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
1006 | enum nl80211_iftype type); | 1006 | enum nl80211_iftype type); |
1007 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 1007 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, |
1008 | int rate, int erp, int short_preamble); | 1008 | int rate, int erp, int short_preamble); |
1009 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | 1009 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
1010 | struct ieee80211_hdr *hdr, const u8 *tsc, | 1010 | struct ieee80211_hdr *hdr, const u8 *tsc, |
1011 | gfp_t gfp); | 1011 | gfp_t gfp); |
1012 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 1012 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); |
1013 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 1013 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
1014 | int encrypt); | 1014 | int encrypt); |
1015 | void ieee802_11_parse_elems(u8 *start, size_t len, | 1015 | void ieee802_11_parse_elems(u8 *start, size_t len, |
1016 | struct ieee802_11_elems *elems); | 1016 | struct ieee802_11_elems *elems); |
1017 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | 1017 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
1018 | struct ieee802_11_elems *elems, | 1018 | struct ieee802_11_elems *elems, |
1019 | u64 filter, u32 crc); | 1019 | u64 filter, u32 crc); |
1020 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 1020 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
1021 | enum ieee80211_band band); | 1021 | enum ieee80211_band band); |
1022 | 1022 | ||
1023 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); | 1023 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); |
1024 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); | 1024 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); |
1025 | void ieee80211_dynamic_ps_timer(unsigned long data); | 1025 | void ieee80211_dynamic_ps_timer(unsigned long data); |
1026 | void ieee80211_send_nullfunc(struct ieee80211_local *local, | 1026 | void ieee80211_send_nullfunc(struct ieee80211_local *local, |
1027 | struct ieee80211_sub_if_data *sdata, | 1027 | struct ieee80211_sub_if_data *sdata, |
1028 | int powersave); | 1028 | int powersave); |
1029 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1029 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1030 | struct ieee80211_hdr *hdr); | 1030 | struct ieee80211_hdr *hdr); |
1031 | void ieee80211_beacon_loss_work(struct work_struct *work); | 1031 | void ieee80211_beacon_loss_work(struct work_struct *work); |
1032 | 1032 | ||
1033 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1033 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1034 | enum queue_stop_reason reason); | 1034 | enum queue_stop_reason reason); |
1035 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 1035 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
1036 | enum queue_stop_reason reason); | 1036 | enum queue_stop_reason reason); |
1037 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1037 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1038 | enum queue_stop_reason reason); | 1038 | enum queue_stop_reason reason); |
1039 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1039 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1040 | enum queue_stop_reason reason); | 1040 | enum queue_stop_reason reason); |
1041 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | 1041 | void ieee80211_add_pending_skb(struct ieee80211_local *local, |
1042 | struct sk_buff *skb); | 1042 | struct sk_buff *skb); |
1043 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | 1043 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, |
1044 | struct sk_buff_head *skbs); | 1044 | struct sk_buff_head *skbs); |
1045 | 1045 | ||
1046 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1046 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1047 | u16 transaction, u16 auth_alg, | 1047 | u16 transaction, u16 auth_alg, |
1048 | u8 *extra, size_t extra_len, const u8 *bssid, | 1048 | u8 *extra, size_t extra_len, const u8 *bssid, |
1049 | const u8 *key, u8 key_len, u8 key_idx); | 1049 | const u8 *key, u8 key_len, u8 key_idx); |
1050 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1050 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1051 | const u8 *ie, size_t ie_len, | 1051 | const u8 *ie, size_t ie_len, |
1052 | enum ieee80211_band band); | 1052 | enum ieee80211_band band); |
1053 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1053 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1054 | const u8 *ssid, size_t ssid_len, | 1054 | const u8 *ssid, size_t ssid_len, |
1055 | const u8 *ie, size_t ie_len); | 1055 | const u8 *ie, size_t ie_len); |
1056 | 1056 | ||
1057 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1057 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1058 | const size_t supp_rates_len, | 1058 | const size_t supp_rates_len, |
1059 | const u8 *supp_rates); | 1059 | const u8 *supp_rates); |
1060 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1060 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
1061 | struct ieee802_11_elems *elems, | 1061 | struct ieee802_11_elems *elems, |
1062 | enum ieee80211_band band); | 1062 | enum ieee80211_band band); |
1063 | 1063 | ||
1064 | #ifdef CONFIG_MAC80211_NOINLINE | 1064 | #ifdef CONFIG_MAC80211_NOINLINE |
1065 | #define debug_noinline noinline | 1065 | #define debug_noinline noinline |
1066 | #else | 1066 | #else |
1067 | #define debug_noinline | 1067 | #define debug_noinline |
1068 | #endif | 1068 | #endif |
1069 | 1069 | ||
1070 | #endif /* IEEE80211_I_H */ | 1070 | #endif /* IEEE80211_I_H */ |
1071 | 1071 |
net/mac80211/mesh.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 open80211s Ltd. | 2 | * Copyright (c) 2008 open80211s Ltd. |
3 | * Authors: Luis Carlos Cobo <luisca@cozybit.com> | 3 | * Authors: Luis Carlos Cobo <luisca@cozybit.com> |
4 | * Javier Cardona <javier@cozybit.com> | 4 | * Javier Cardona <javier@cozybit.com> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <asm/unaligned.h> | 11 | #include <asm/unaligned.h> |
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | #include "mesh.h" | 13 | #include "mesh.h" |
14 | 14 | ||
15 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | 15 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) |
16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | 16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) |
17 | 17 | ||
18 | #define PP_OFFSET 1 /* Path Selection Protocol */ | 18 | #define MESHCONF_PP_OFFSET 0 /* Path Selection Protocol */ |
19 | #define PM_OFFSET 5 /* Path Selection Metric */ | 19 | #define MESHCONF_PM_OFFSET 1 /* Path Selection Metric */ |
20 | #define CC_OFFSET 9 /* Congestion Control Mode */ | 20 | #define MESHCONF_CC_OFFSET 2 /* Congestion Control Mode */ |
21 | #define SP_OFFSET 13 /* Synchronization Protocol */ | 21 | #define MESHCONF_SP_OFFSET 3 /* Synchronization Protocol */ |
22 | #define AUTH_OFFSET 17 /* Authentication Protocol */ | 22 | #define MESHCONF_AUTH_OFFSET 4 /* Authentication Protocol */ |
23 | #define CAPAB_OFFSET 22 | 23 | #define MESHCONF_CAPAB_OFFSET 6 |
24 | #define CAPAB_ACCEPT_PLINKS 0x80 | 24 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 |
25 | #define CAPAB_FORWARDING 0x10 | 25 | #define MESHCONF_CAPAB_FORWARDING 0x08 |
26 | 26 | ||
27 | #define TMR_RUNNING_HK 0 | 27 | #define TMR_RUNNING_HK 0 |
28 | #define TMR_RUNNING_MP 1 | 28 | #define TMR_RUNNING_MP 1 |
29 | 29 | ||
30 | int mesh_allocated; | 30 | int mesh_allocated; |
31 | static struct kmem_cache *rm_cache; | 31 | static struct kmem_cache *rm_cache; |
32 | 32 | ||
33 | void ieee80211s_init(void) | 33 | void ieee80211s_init(void) |
34 | { | 34 | { |
35 | mesh_pathtbl_init(); | 35 | mesh_pathtbl_init(); |
36 | mesh_allocated = 1; | 36 | mesh_allocated = 1; |
37 | rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry), | 37 | rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry), |
38 | 0, 0, NULL); | 38 | 0, 0, NULL); |
39 | } | 39 | } |
40 | 40 | ||
41 | void ieee80211s_stop(void) | 41 | void ieee80211s_stop(void) |
42 | { | 42 | { |
43 | mesh_pathtbl_unregister(); | 43 | mesh_pathtbl_unregister(); |
44 | kmem_cache_destroy(rm_cache); | 44 | kmem_cache_destroy(rm_cache); |
45 | } | 45 | } |
46 | 46 | ||
47 | static void ieee80211_mesh_housekeeping_timer(unsigned long data) | 47 | static void ieee80211_mesh_housekeeping_timer(unsigned long data) |
48 | { | 48 | { |
49 | struct ieee80211_sub_if_data *sdata = (void *) data; | 49 | struct ieee80211_sub_if_data *sdata = (void *) data; |
50 | struct ieee80211_local *local = sdata->local; | 50 | struct ieee80211_local *local = sdata->local; |
51 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 51 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
52 | 52 | ||
53 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 53 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
54 | 54 | ||
55 | if (local->quiescing) { | 55 | if (local->quiescing) { |
56 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | 56 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); |
57 | return; | 57 | return; |
58 | } | 58 | } |
59 | 59 | ||
60 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 60 | ieee80211_queue_work(&local->hw, &ifmsh->work); |
61 | } | 61 | } |
62 | 62 | ||
63 | /** | 63 | /** |
64 | * mesh_matches_local - check if the config of a mesh point matches ours | 64 | * mesh_matches_local - check if the config of a mesh point matches ours |
65 | * | 65 | * |
66 | * @ie: information elements of a management frame from the mesh peer | 66 | * @ie: information elements of a management frame from the mesh peer |
67 | * @sdata: local mesh subif | 67 | * @sdata: local mesh subif |
68 | * | 68 | * |
69 | * This function checks if the mesh configuration of a mesh point matches the | 69 | * This function checks if the mesh configuration of a mesh point matches the |
70 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. | 70 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. |
71 | */ | 71 | */ |
72 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) | 72 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) |
73 | { | 73 | { |
74 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 74 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
75 | 75 | ||
76 | /* | 76 | /* |
77 | * As support for each feature is added, check for matching | 77 | * As support for each feature is added, check for matching |
78 | * - On mesh config capabilities | 78 | * - On mesh config capabilities |
79 | * - Power Save Support En | 79 | * - Power Save Support En |
80 | * - Sync support enabled | 80 | * - Sync support enabled |
81 | * - Sync support active | 81 | * - Sync support active |
82 | * - Sync support required from peer | 82 | * - Sync support required from peer |
83 | * - MDA enabled | 83 | * - MDA enabled |
84 | * - Power management control on fc | 84 | * - Power management control on fc |
85 | */ | 85 | */ |
86 | if (ifmsh->mesh_id_len == ie->mesh_id_len && | 86 | if (ifmsh->mesh_id_len == ie->mesh_id_len && |
87 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 87 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
88 | memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && | 88 | (ifmsh->mesh_pp_id == *(ie->mesh_config + MESHCONF_PP_OFFSET))&& |
89 | memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && | 89 | (ifmsh->mesh_pm_id == *(ie->mesh_config + MESHCONF_PM_OFFSET))&& |
90 | memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0 && | 90 | (ifmsh->mesh_cc_id == *(ie->mesh_config + MESHCONF_CC_OFFSET))&& |
91 | memcmp(ifmsh->mesh_sp_id, ie->mesh_config + SP_OFFSET, 4) == 0 && | 91 | (ifmsh->mesh_sp_id == *(ie->mesh_config + MESHCONF_SP_OFFSET))&& |
92 | memcmp(ifmsh->mesh_auth_id, ie->mesh_config + AUTH_OFFSET, 4) == 0) | 92 | (ifmsh->mesh_auth_id == *(ie->mesh_config + |
93 | MESHCONF_AUTH_OFFSET))) | ||
93 | return true; | 94 | return true; |
94 | 95 | ||
95 | return false; | 96 | return false; |
96 | } | 97 | } |
97 | 98 | ||
98 | /** | 99 | /** |
99 | * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links | 100 | * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links |
100 | * | 101 | * |
101 | * @ie: information elements of a management frame from the mesh peer | 102 | * @ie: information elements of a management frame from the mesh peer |
102 | */ | 103 | */ |
103 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | 104 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
104 | { | 105 | { |
105 | return (*(ie->mesh_config + CAPAB_OFFSET) & CAPAB_ACCEPT_PLINKS) != 0; | 106 | return (*(ie->mesh_config + MESHCONF_CAPAB_OFFSET) & |
107 | MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; | ||
106 | } | 108 | } |
107 | 109 | ||
108 | /** | 110 | /** |
109 | * mesh_accept_plinks_update: update accepting_plink in local mesh beacons | 111 | * mesh_accept_plinks_update: update accepting_plink in local mesh beacons |
110 | * | 112 | * |
111 | * @sdata: mesh interface in which mesh beacons are going to be updated | 113 | * @sdata: mesh interface in which mesh beacons are going to be updated |
112 | */ | 114 | */ |
113 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | 115 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) |
114 | { | 116 | { |
115 | bool free_plinks; | 117 | bool free_plinks; |
116 | 118 | ||
117 | /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, | 119 | /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, |
118 | * the mesh interface might be able to establish plinks with peers that | 120 | * the mesh interface might be able to establish plinks with peers that |
119 | * are already on the table but are not on PLINK_ESTAB state. However, | 121 | * are already on the table but are not on PLINK_ESTAB state. However, |
120 | * in general the mesh interface is not accepting peer link requests | 122 | * in general the mesh interface is not accepting peer link requests |
121 | * from new peers, and that must be reflected in the beacon | 123 | * from new peers, and that must be reflected in the beacon |
122 | */ | 124 | */ |
123 | free_plinks = mesh_plink_availables(sdata); | 125 | free_plinks = mesh_plink_availables(sdata); |
124 | 126 | ||
125 | if (free_plinks != sdata->u.mesh.accepting_plinks) | 127 | if (free_plinks != sdata->u.mesh.accepting_plinks) |
126 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); | 128 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
127 | } | 129 | } |
128 | 130 | ||
129 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) | 131 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) |
130 | { | 132 | { |
131 | u8 oui[3] = {0x00, 0x0F, 0xAC}; | 133 | sta->mesh_pp_id = 0; /* HWMP */ |
132 | 134 | sta->mesh_pm_id = 0; /* Airtime */ | |
133 | memcpy(sta->mesh_pp_id, oui, sizeof(oui)); | 135 | sta->mesh_cc_id = 0; /* Disabled */ |
134 | memcpy(sta->mesh_pm_id, oui, sizeof(oui)); | 136 | sta->mesh_sp_id = 0; /* Neighbor Offset */ |
135 | memcpy(sta->mesh_cc_id, oui, sizeof(oui)); | 137 | sta->mesh_auth_id = 0; /* Disabled */ |
136 | memcpy(sta->mesh_sp_id, oui, sizeof(oui)); | ||
137 | memcpy(sta->mesh_auth_id, oui, sizeof(oui)); | ||
138 | sta->mesh_pp_id[sizeof(oui)] = 0; | ||
139 | sta->mesh_pm_id[sizeof(oui)] = 0; | ||
140 | sta->mesh_cc_id[sizeof(oui)] = 0xff; | ||
141 | sta->mesh_sp_id[sizeof(oui)] = 0xff; | ||
142 | sta->mesh_auth_id[sizeof(oui)] = 0x0; | ||
143 | } | 138 | } |
144 | 139 | ||
145 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 140 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
146 | { | 141 | { |
147 | int i; | 142 | int i; |
148 | 143 | ||
149 | sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); | 144 | sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); |
150 | if (!sdata->u.mesh.rmc) | 145 | if (!sdata->u.mesh.rmc) |
151 | return -ENOMEM; | 146 | return -ENOMEM; |
152 | sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; | 147 | sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; |
153 | for (i = 0; i < RMC_BUCKETS; i++) | 148 | for (i = 0; i < RMC_BUCKETS; i++) |
154 | INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); | 149 | INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); |
155 | return 0; | 150 | return 0; |
156 | } | 151 | } |
157 | 152 | ||
158 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | 153 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) |
159 | { | 154 | { |
160 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; | 155 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
161 | struct rmc_entry *p, *n; | 156 | struct rmc_entry *p, *n; |
162 | int i; | 157 | int i; |
163 | 158 | ||
164 | if (!sdata->u.mesh.rmc) | 159 | if (!sdata->u.mesh.rmc) |
165 | return; | 160 | return; |
166 | 161 | ||
167 | for (i = 0; i < RMC_BUCKETS; i++) | 162 | for (i = 0; i < RMC_BUCKETS; i++) |
168 | list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { | 163 | list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { |
169 | list_del(&p->list); | 164 | list_del(&p->list); |
170 | kmem_cache_free(rm_cache, p); | 165 | kmem_cache_free(rm_cache, p); |
171 | } | 166 | } |
172 | 167 | ||
173 | kfree(rmc); | 168 | kfree(rmc); |
174 | sdata->u.mesh.rmc = NULL; | 169 | sdata->u.mesh.rmc = NULL; |
175 | } | 170 | } |
176 | 171 | ||
177 | /** | 172 | /** |
178 | * mesh_rmc_check - Check frame in recent multicast cache and add if absent. | 173 | * mesh_rmc_check - Check frame in recent multicast cache and add if absent. |
179 | * | 174 | * |
180 | * @sa: source address | 175 | * @sa: source address |
181 | * @mesh_hdr: mesh_header | 176 | * @mesh_hdr: mesh_header |
182 | * | 177 | * |
183 | * Returns: 0 if the frame is not in the cache, nonzero otherwise. | 178 | * Returns: 0 if the frame is not in the cache, nonzero otherwise. |
184 | * | 179 | * |
185 | * Checks using the source address and the mesh sequence number if we have | 180 | * Checks using the source address and the mesh sequence number if we have |
186 | * received this frame lately. If the frame is not in the cache, it is added to | 181 | * received this frame lately. If the frame is not in the cache, it is added to |
187 | * it. | 182 | * it. |
188 | */ | 183 | */ |
189 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | 184 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, |
190 | struct ieee80211_sub_if_data *sdata) | 185 | struct ieee80211_sub_if_data *sdata) |
191 | { | 186 | { |
192 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; | 187 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
193 | u32 seqnum = 0; | 188 | u32 seqnum = 0; |
194 | int entries = 0; | 189 | int entries = 0; |
195 | u8 idx; | 190 | u8 idx; |
196 | struct rmc_entry *p, *n; | 191 | struct rmc_entry *p, *n; |
197 | 192 | ||
198 | /* Don't care about endianness since only match matters */ | 193 | /* Don't care about endianness since only match matters */ |
199 | memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); | 194 | memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); |
200 | idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; | 195 | idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; |
201 | list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { | 196 | list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { |
202 | ++entries; | 197 | ++entries; |
203 | if (time_after(jiffies, p->exp_time) || | 198 | if (time_after(jiffies, p->exp_time) || |
204 | (entries == RMC_QUEUE_MAX_LEN)) { | 199 | (entries == RMC_QUEUE_MAX_LEN)) { |
205 | list_del(&p->list); | 200 | list_del(&p->list); |
206 | kmem_cache_free(rm_cache, p); | 201 | kmem_cache_free(rm_cache, p); |
207 | --entries; | 202 | --entries; |
208 | } else if ((seqnum == p->seqnum) | 203 | } else if ((seqnum == p->seqnum) |
209 | && (memcmp(sa, p->sa, ETH_ALEN) == 0)) | 204 | && (memcmp(sa, p->sa, ETH_ALEN) == 0)) |
210 | return -1; | 205 | return -1; |
211 | } | 206 | } |
212 | 207 | ||
213 | p = kmem_cache_alloc(rm_cache, GFP_ATOMIC); | 208 | p = kmem_cache_alloc(rm_cache, GFP_ATOMIC); |
214 | if (!p) { | 209 | if (!p) { |
215 | printk(KERN_DEBUG "o11s: could not allocate RMC entry\n"); | 210 | printk(KERN_DEBUG "o11s: could not allocate RMC entry\n"); |
216 | return 0; | 211 | return 0; |
217 | } | 212 | } |
218 | p->seqnum = seqnum; | 213 | p->seqnum = seqnum; |
219 | p->exp_time = jiffies + RMC_TIMEOUT; | 214 | p->exp_time = jiffies + RMC_TIMEOUT; |
220 | memcpy(p->sa, sa, ETH_ALEN); | 215 | memcpy(p->sa, sa, ETH_ALEN); |
221 | list_add(&p->list, &rmc->bucket[idx].list); | 216 | list_add(&p->list, &rmc->bucket[idx].list); |
222 | return 0; | 217 | return 0; |
223 | } | 218 | } |
224 | 219 | ||
225 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | 220 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) |
226 | { | 221 | { |
227 | struct ieee80211_local *local = sdata->local; | 222 | struct ieee80211_local *local = sdata->local; |
228 | struct ieee80211_supported_band *sband; | 223 | struct ieee80211_supported_band *sband; |
229 | u8 *pos; | 224 | u8 *pos; |
230 | int len, i, rate; | 225 | int len, i, rate; |
231 | 226 | ||
232 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 227 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
233 | len = sband->n_bitrates; | 228 | len = sband->n_bitrates; |
234 | if (len > 8) | 229 | if (len > 8) |
235 | len = 8; | 230 | len = 8; |
236 | pos = skb_put(skb, len + 2); | 231 | pos = skb_put(skb, len + 2); |
237 | *pos++ = WLAN_EID_SUPP_RATES; | 232 | *pos++ = WLAN_EID_SUPP_RATES; |
238 | *pos++ = len; | 233 | *pos++ = len; |
239 | for (i = 0; i < len; i++) { | 234 | for (i = 0; i < len; i++) { |
240 | rate = sband->bitrates[i].bitrate; | 235 | rate = sband->bitrates[i].bitrate; |
241 | *pos++ = (u8) (rate / 5); | 236 | *pos++ = (u8) (rate / 5); |
242 | } | 237 | } |
243 | 238 | ||
244 | if (sband->n_bitrates > len) { | 239 | if (sband->n_bitrates > len) { |
245 | pos = skb_put(skb, sband->n_bitrates - len + 2); | 240 | pos = skb_put(skb, sband->n_bitrates - len + 2); |
246 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 241 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
247 | *pos++ = sband->n_bitrates - len; | 242 | *pos++ = sband->n_bitrates - len; |
248 | for (i = len; i < sband->n_bitrates; i++) { | 243 | for (i = len; i < sband->n_bitrates; i++) { |
249 | rate = sband->bitrates[i].bitrate; | 244 | rate = sband->bitrates[i].bitrate; |
250 | *pos++ = (u8) (rate / 5); | 245 | *pos++ = (u8) (rate / 5); |
251 | } | 246 | } |
252 | } | 247 | } |
253 | 248 | ||
254 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); | 249 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); |
255 | *pos++ = WLAN_EID_MESH_ID; | 250 | *pos++ = WLAN_EID_MESH_ID; |
256 | *pos++ = sdata->u.mesh.mesh_id_len; | 251 | *pos++ = sdata->u.mesh.mesh_id_len; |
257 | if (sdata->u.mesh.mesh_id_len) | 252 | if (sdata->u.mesh.mesh_id_len) |
258 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); | 253 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); |
259 | 254 | ||
260 | pos = skb_put(skb, 2 + IEEE80211_MESH_CONFIG_LEN); | 255 | pos = skb_put(skb, 2 + IEEE80211_MESH_CONFIG_LEN); |
261 | *pos++ = WLAN_EID_MESH_CONFIG; | 256 | *pos++ = WLAN_EID_MESH_CONFIG; |
262 | *pos++ = IEEE80211_MESH_CONFIG_LEN; | 257 | *pos++ = IEEE80211_MESH_CONFIG_LEN; |
263 | /* Version */ | ||
264 | *pos++ = 1; | ||
265 | 258 | ||
266 | /* Active path selection protocol ID */ | 259 | /* Active path selection protocol ID */ |
267 | memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); | 260 | *pos++ = sdata->u.mesh.mesh_pp_id; |
268 | pos += 4; | ||
269 | 261 | ||
270 | /* Active path selection metric ID */ | 262 | /* Active path selection metric ID */ |
271 | memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); | 263 | *pos++ = sdata->u.mesh.mesh_pm_id; |
272 | pos += 4; | ||
273 | 264 | ||
274 | /* Congestion control mode identifier */ | 265 | /* Congestion control mode identifier */ |
275 | memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); | 266 | *pos++ = sdata->u.mesh.mesh_cc_id; |
276 | pos += 4; | ||
277 | 267 | ||
278 | /* Synchronization protocol identifier */ | 268 | /* Synchronization protocol identifier */ |
279 | memcpy(pos, sdata->u.mesh.mesh_sp_id, 4); | 269 | *pos++ = sdata->u.mesh.mesh_sp_id; |
280 | pos += 4; | ||
281 | 270 | ||
282 | /* Authentication Protocol identifier */ | 271 | /* Authentication Protocol identifier */ |
283 | memcpy(pos, sdata->u.mesh.mesh_auth_id, 4); | 272 | *pos++ = sdata->u.mesh.mesh_auth_id; |
284 | pos += 4; | ||
285 | 273 | ||
286 | /* Mesh Formation Info */ | 274 | /* Mesh Formation Info */ |
287 | memset(pos, 0x00, 1); | 275 | memset(pos, 0x00, 1); |
288 | pos += 1; | 276 | pos += 1; |
289 | 277 | ||
290 | /* Mesh capability */ | 278 | /* Mesh capability */ |
291 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); | 279 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); |
292 | *pos = CAPAB_FORWARDING; | 280 | *pos = MESHCONF_CAPAB_FORWARDING; |
293 | *pos++ |= sdata->u.mesh.accepting_plinks ? CAPAB_ACCEPT_PLINKS : 0x00; | 281 | *pos++ |= sdata->u.mesh.accepting_plinks ? |
282 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | ||
294 | *pos++ = 0x00; | 283 | *pos++ = 0x00; |
295 | 284 | ||
296 | return; | 285 | return; |
297 | } | 286 | } |
298 | 287 | ||
299 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) | 288 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) |
300 | { | 289 | { |
301 | /* Use last four bytes of hw addr and interface index as hash index */ | 290 | /* Use last four bytes of hw addr and interface index as hash index */ |
302 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) | 291 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) |
303 | & tbl->hash_mask; | 292 | & tbl->hash_mask; |
304 | } | 293 | } |
305 | 294 | ||
306 | struct mesh_table *mesh_table_alloc(int size_order) | 295 | struct mesh_table *mesh_table_alloc(int size_order) |
307 | { | 296 | { |
308 | int i; | 297 | int i; |
309 | struct mesh_table *newtbl; | 298 | struct mesh_table *newtbl; |
310 | 299 | ||
311 | newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); | 300 | newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); |
312 | if (!newtbl) | 301 | if (!newtbl) |
313 | return NULL; | 302 | return NULL; |
314 | 303 | ||
315 | newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * | 304 | newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * |
316 | (1 << size_order), GFP_KERNEL); | 305 | (1 << size_order), GFP_KERNEL); |
317 | 306 | ||
318 | if (!newtbl->hash_buckets) { | 307 | if (!newtbl->hash_buckets) { |
319 | kfree(newtbl); | 308 | kfree(newtbl); |
320 | return NULL; | 309 | return NULL; |
321 | } | 310 | } |
322 | 311 | ||
323 | newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * | 312 | newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * |
324 | (1 << size_order), GFP_KERNEL); | 313 | (1 << size_order), GFP_KERNEL); |
325 | if (!newtbl->hashwlock) { | 314 | if (!newtbl->hashwlock) { |
326 | kfree(newtbl->hash_buckets); | 315 | kfree(newtbl->hash_buckets); |
327 | kfree(newtbl); | 316 | kfree(newtbl); |
328 | return NULL; | 317 | return NULL; |
329 | } | 318 | } |
330 | 319 | ||
331 | newtbl->size_order = size_order; | 320 | newtbl->size_order = size_order; |
332 | newtbl->hash_mask = (1 << size_order) - 1; | 321 | newtbl->hash_mask = (1 << size_order) - 1; |
333 | atomic_set(&newtbl->entries, 0); | 322 | atomic_set(&newtbl->entries, 0); |
334 | get_random_bytes(&newtbl->hash_rnd, | 323 | get_random_bytes(&newtbl->hash_rnd, |
335 | sizeof(newtbl->hash_rnd)); | 324 | sizeof(newtbl->hash_rnd)); |
336 | for (i = 0; i <= newtbl->hash_mask; i++) | 325 | for (i = 0; i <= newtbl->hash_mask; i++) |
337 | spin_lock_init(&newtbl->hashwlock[i]); | 326 | spin_lock_init(&newtbl->hashwlock[i]); |
338 | 327 | ||
339 | return newtbl; | 328 | return newtbl; |
340 | } | 329 | } |
341 | 330 | ||
342 | 331 | ||
343 | static void ieee80211_mesh_path_timer(unsigned long data) | 332 | static void ieee80211_mesh_path_timer(unsigned long data) |
344 | { | 333 | { |
345 | struct ieee80211_sub_if_data *sdata = | 334 | struct ieee80211_sub_if_data *sdata = |
346 | (struct ieee80211_sub_if_data *) data; | 335 | (struct ieee80211_sub_if_data *) data; |
347 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 336 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
348 | struct ieee80211_local *local = sdata->local; | 337 | struct ieee80211_local *local = sdata->local; |
349 | 338 | ||
350 | if (local->quiescing) { | 339 | if (local->quiescing) { |
351 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | 340 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); |
352 | return; | 341 | return; |
353 | } | 342 | } |
354 | 343 | ||
355 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 344 | ieee80211_queue_work(&local->hw, &ifmsh->work); |
356 | } | 345 | } |
357 | 346 | ||
358 | /** | 347 | /** |
359 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame | 348 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame |
360 | * @hdr: 802.11 frame header | 349 | * @hdr: 802.11 frame header |
361 | * @fc: frame control field | 350 | * @fc: frame control field |
362 | * @meshda: destination address in the mesh | 351 | * @meshda: destination address in the mesh |
363 | * @meshsa: source address address in the mesh. Same as TA, as frame is | 352 | * @meshsa: source address address in the mesh. Same as TA, as frame is |
364 | * locally originated. | 353 | * locally originated. |
365 | * | 354 | * |
366 | * Return the length of the 802.11 (does not include a mesh control header) | 355 | * Return the length of the 802.11 (does not include a mesh control header) |
367 | */ | 356 | */ |
368 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char | 357 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char |
369 | *meshda, char *meshsa) { | 358 | *meshda, char *meshsa) { |
370 | if (is_multicast_ether_addr(meshda)) { | 359 | if (is_multicast_ether_addr(meshda)) { |
371 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 360 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
372 | /* DA TA SA */ | 361 | /* DA TA SA */ |
373 | memcpy(hdr->addr1, meshda, ETH_ALEN); | 362 | memcpy(hdr->addr1, meshda, ETH_ALEN); |
374 | memcpy(hdr->addr2, meshsa, ETH_ALEN); | 363 | memcpy(hdr->addr2, meshsa, ETH_ALEN); |
375 | memcpy(hdr->addr3, meshsa, ETH_ALEN); | 364 | memcpy(hdr->addr3, meshsa, ETH_ALEN); |
376 | return 24; | 365 | return 24; |
377 | } else { | 366 | } else { |
378 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | | 367 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | |
379 | IEEE80211_FCTL_TODS); | 368 | IEEE80211_FCTL_TODS); |
380 | /* RA TA DA SA */ | 369 | /* RA TA DA SA */ |
381 | memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */ | 370 | memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */ |
382 | memcpy(hdr->addr2, meshsa, ETH_ALEN); | 371 | memcpy(hdr->addr2, meshsa, ETH_ALEN); |
383 | memcpy(hdr->addr3, meshda, ETH_ALEN); | 372 | memcpy(hdr->addr3, meshda, ETH_ALEN); |
384 | memcpy(hdr->addr4, meshsa, ETH_ALEN); | 373 | memcpy(hdr->addr4, meshsa, ETH_ALEN); |
385 | return 30; | 374 | return 30; |
386 | } | 375 | } |
387 | } | 376 | } |
388 | 377 | ||
389 | /** | 378 | /** |
390 | * ieee80211_new_mesh_header - create a new mesh header | 379 | * ieee80211_new_mesh_header - create a new mesh header |
391 | * @meshhdr: uninitialized mesh header | 380 | * @meshhdr: uninitialized mesh header |
392 | * @sdata: mesh interface to be used | 381 | * @sdata: mesh interface to be used |
393 | * @addr4: addr4 of the mesh frame (1st in ae header) | 382 | * @addr4: addr4 of the mesh frame (1st in ae header) |
394 | * may be NULL | 383 | * may be NULL |
395 | * @addr5: addr5 of the mesh frame (1st or 2nd in ae header) | 384 | * @addr5: addr5 of the mesh frame (1st or 2nd in ae header) |
396 | * may be NULL unless addr6 is present | 385 | * may be NULL unless addr6 is present |
397 | * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header) | 386 | * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header) |
398 | * may be NULL unless addr5 is present | 387 | * may be NULL unless addr5 is present |
399 | * | 388 | * |
400 | * Return the header length. | 389 | * Return the header length. |
401 | */ | 390 | */ |
402 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 391 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
403 | struct ieee80211_sub_if_data *sdata, char *addr4, | 392 | struct ieee80211_sub_if_data *sdata, char *addr4, |
404 | char *addr5, char *addr6) | 393 | char *addr5, char *addr6) |
405 | { | 394 | { |
406 | int aelen = 0; | 395 | int aelen = 0; |
407 | memset(meshhdr, 0, sizeof(meshhdr)); | 396 | memset(meshhdr, 0, sizeof(meshhdr)); |
408 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 397 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
409 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); | 398 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
410 | sdata->u.mesh.mesh_seqnum++; | 399 | sdata->u.mesh.mesh_seqnum++; |
411 | if (addr4) { | 400 | if (addr4) { |
412 | meshhdr->flags |= MESH_FLAGS_AE_A4; | 401 | meshhdr->flags |= MESH_FLAGS_AE_A4; |
413 | aelen += ETH_ALEN; | 402 | aelen += ETH_ALEN; |
414 | memcpy(meshhdr->eaddr1, addr4, ETH_ALEN); | 403 | memcpy(meshhdr->eaddr1, addr4, ETH_ALEN); |
415 | } | 404 | } |
416 | if (addr5 && addr6) { | 405 | if (addr5 && addr6) { |
417 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; | 406 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; |
418 | aelen += 2 * ETH_ALEN; | 407 | aelen += 2 * ETH_ALEN; |
419 | if (!addr4) { | 408 | if (!addr4) { |
420 | memcpy(meshhdr->eaddr1, addr5, ETH_ALEN); | 409 | memcpy(meshhdr->eaddr1, addr5, ETH_ALEN); |
421 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); | 410 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); |
422 | } else { | 411 | } else { |
423 | memcpy(meshhdr->eaddr2, addr5, ETH_ALEN); | 412 | memcpy(meshhdr->eaddr2, addr5, ETH_ALEN); |
424 | memcpy(meshhdr->eaddr3, addr6, ETH_ALEN); | 413 | memcpy(meshhdr->eaddr3, addr6, ETH_ALEN); |
425 | } | 414 | } |
426 | } | 415 | } |
427 | return 6 + aelen; | 416 | return 6 + aelen; |
428 | } | 417 | } |
429 | 418 | ||
430 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | 419 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, |
431 | struct ieee80211_if_mesh *ifmsh) | 420 | struct ieee80211_if_mesh *ifmsh) |
432 | { | 421 | { |
433 | bool free_plinks; | 422 | bool free_plinks; |
434 | 423 | ||
435 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 424 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
436 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | 425 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", |
437 | sdata->dev->name); | 426 | sdata->dev->name); |
438 | #endif | 427 | #endif |
439 | 428 | ||
440 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 429 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
441 | mesh_path_expire(sdata); | 430 | mesh_path_expire(sdata); |
442 | 431 | ||
443 | free_plinks = mesh_plink_availables(sdata); | 432 | free_plinks = mesh_plink_availables(sdata); |
444 | if (free_plinks != sdata->u.mesh.accepting_plinks) | 433 | if (free_plinks != sdata->u.mesh.accepting_plinks) |
445 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 434 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
446 | 435 | ||
447 | mod_timer(&ifmsh->housekeeping_timer, | 436 | mod_timer(&ifmsh->housekeeping_timer, |
448 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | 437 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); |
449 | } | 438 | } |
450 | 439 | ||
451 | #ifdef CONFIG_PM | 440 | #ifdef CONFIG_PM |
452 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | 441 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) |
453 | { | 442 | { |
454 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 443 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
455 | 444 | ||
456 | /* might restart the timer but that doesn't matter */ | 445 | /* might restart the timer but that doesn't matter */ |
457 | cancel_work_sync(&ifmsh->work); | 446 | cancel_work_sync(&ifmsh->work); |
458 | 447 | ||
459 | /* use atomic bitops in case both timers fire at the same time */ | 448 | /* use atomic bitops in case both timers fire at the same time */ |
460 | 449 | ||
461 | if (del_timer_sync(&ifmsh->housekeeping_timer)) | 450 | if (del_timer_sync(&ifmsh->housekeeping_timer)) |
462 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | 451 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); |
463 | if (del_timer_sync(&ifmsh->mesh_path_timer)) | 452 | if (del_timer_sync(&ifmsh->mesh_path_timer)) |
464 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | 453 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); |
465 | } | 454 | } |
466 | 455 | ||
467 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | 456 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) |
468 | { | 457 | { |
469 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 458 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
470 | 459 | ||
471 | if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running)) | 460 | if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running)) |
472 | add_timer(&ifmsh->housekeeping_timer); | 461 | add_timer(&ifmsh->housekeeping_timer); |
473 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) | 462 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) |
474 | add_timer(&ifmsh->mesh_path_timer); | 463 | add_timer(&ifmsh->mesh_path_timer); |
475 | } | 464 | } |
476 | #endif | 465 | #endif |
477 | 466 | ||
478 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | 467 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) |
479 | { | 468 | { |
480 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 469 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
481 | struct ieee80211_local *local = sdata->local; | 470 | struct ieee80211_local *local = sdata->local; |
482 | 471 | ||
483 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 472 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
484 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 473 | ieee80211_queue_work(&local->hw, &ifmsh->work); |
485 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 474 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
486 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 475 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
487 | BSS_CHANGED_BEACON_ENABLED | | 476 | BSS_CHANGED_BEACON_ENABLED | |
488 | BSS_CHANGED_BEACON_INT); | 477 | BSS_CHANGED_BEACON_INT); |
489 | } | 478 | } |
490 | 479 | ||
491 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 480 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
492 | { | 481 | { |
493 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 482 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
494 | /* | 483 | /* |
495 | * If the timer fired while we waited for it, it will have | 484 | * If the timer fired while we waited for it, it will have |
496 | * requeued the work. Now the work will be running again | 485 | * requeued the work. Now the work will be running again |
497 | * but will not rearm the timer again because it checks | 486 | * but will not rearm the timer again because it checks |
498 | * whether the interface is running, which, at this point, | 487 | * whether the interface is running, which, at this point, |
499 | * it no longer is. | 488 | * it no longer is. |
500 | */ | 489 | */ |
501 | cancel_work_sync(&sdata->u.mesh.work); | 490 | cancel_work_sync(&sdata->u.mesh.work); |
502 | 491 | ||
503 | /* | 492 | /* |
504 | * When we get here, the interface is marked down. | 493 | * When we get here, the interface is marked down. |
505 | * Call synchronize_rcu() to wait for the RX path | 494 | * Call synchronize_rcu() to wait for the RX path |
506 | * should it be using the interface and enqueuing | 495 | * should it be using the interface and enqueuing |
507 | * frames at this very time on another CPU. | 496 | * frames at this very time on another CPU. |
508 | */ | 497 | */ |
509 | rcu_barrier(); /* Wait for RX path and call_rcu()'s */ | 498 | rcu_barrier(); /* Wait for RX path and call_rcu()'s */ |
510 | skb_queue_purge(&sdata->u.mesh.skb_queue); | 499 | skb_queue_purge(&sdata->u.mesh.skb_queue); |
511 | } | 500 | } |
512 | 501 | ||
513 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | 502 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, |
514 | u16 stype, | 503 | u16 stype, |
515 | struct ieee80211_mgmt *mgmt, | 504 | struct ieee80211_mgmt *mgmt, |
516 | size_t len, | 505 | size_t len, |
517 | struct ieee80211_rx_status *rx_status) | 506 | struct ieee80211_rx_status *rx_status) |
518 | { | 507 | { |
519 | struct ieee80211_local *local = sdata->local; | 508 | struct ieee80211_local *local = sdata->local; |
520 | struct ieee802_11_elems elems; | 509 | struct ieee802_11_elems elems; |
521 | struct ieee80211_channel *channel; | 510 | struct ieee80211_channel *channel; |
522 | u32 supp_rates = 0; | 511 | u32 supp_rates = 0; |
523 | size_t baselen; | 512 | size_t baselen; |
524 | int freq; | 513 | int freq; |
525 | enum ieee80211_band band = rx_status->band; | 514 | enum ieee80211_band band = rx_status->band; |
526 | 515 | ||
527 | /* ignore ProbeResp to foreign address */ | 516 | /* ignore ProbeResp to foreign address */ |
528 | if (stype == IEEE80211_STYPE_PROBE_RESP && | 517 | if (stype == IEEE80211_STYPE_PROBE_RESP && |
529 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) | 518 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) |
530 | return; | 519 | return; |
531 | 520 | ||
532 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 521 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
533 | if (baselen > len) | 522 | if (baselen > len) |
534 | return; | 523 | return; |
535 | 524 | ||
536 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | 525 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
537 | &elems); | 526 | &elems); |
538 | 527 | ||
539 | if (elems.ds_params && elems.ds_params_len == 1) | 528 | if (elems.ds_params && elems.ds_params_len == 1) |
540 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | 529 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); |
541 | else | 530 | else |
542 | freq = rx_status->freq; | 531 | freq = rx_status->freq; |
543 | 532 | ||
544 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | 533 | channel = ieee80211_get_channel(local->hw.wiphy, freq); |
545 | 534 | ||
546 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 535 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
547 | return; | 536 | return; |
548 | 537 | ||
549 | if (elems.mesh_id && elems.mesh_config && | 538 | if (elems.mesh_id && elems.mesh_config && |
550 | mesh_matches_local(&elems, sdata)) { | 539 | mesh_matches_local(&elems, sdata)) { |
551 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); | 540 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); |
552 | 541 | ||
553 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, | 542 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, |
554 | mesh_peer_accepts_plinks(&elems)); | 543 | mesh_peer_accepts_plinks(&elems)); |
555 | } | 544 | } |
556 | } | 545 | } |
557 | 546 | ||
558 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | 547 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, |
559 | struct ieee80211_mgmt *mgmt, | 548 | struct ieee80211_mgmt *mgmt, |
560 | size_t len, | 549 | size_t len, |
561 | struct ieee80211_rx_status *rx_status) | 550 | struct ieee80211_rx_status *rx_status) |
562 | { | 551 | { |
563 | switch (mgmt->u.action.category) { | 552 | switch (mgmt->u.action.category) { |
564 | case PLINK_CATEGORY: | 553 | case PLINK_CATEGORY: |
565 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | 554 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); |
566 | break; | 555 | break; |
567 | case MESH_PATH_SEL_CATEGORY: | 556 | case MESH_PATH_SEL_CATEGORY: |
568 | mesh_rx_path_sel_frame(sdata, mgmt, len); | 557 | mesh_rx_path_sel_frame(sdata, mgmt, len); |
569 | break; | 558 | break; |
570 | } | 559 | } |
571 | } | 560 | } |
572 | 561 | ||
573 | static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 562 | static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
574 | struct sk_buff *skb) | 563 | struct sk_buff *skb) |
575 | { | 564 | { |
576 | struct ieee80211_rx_status *rx_status; | 565 | struct ieee80211_rx_status *rx_status; |
577 | struct ieee80211_if_mesh *ifmsh; | 566 | struct ieee80211_if_mesh *ifmsh; |
578 | struct ieee80211_mgmt *mgmt; | 567 | struct ieee80211_mgmt *mgmt; |
579 | u16 stype; | 568 | u16 stype; |
580 | 569 | ||
581 | ifmsh = &sdata->u.mesh; | 570 | ifmsh = &sdata->u.mesh; |
582 | 571 | ||
583 | rx_status = IEEE80211_SKB_RXCB(skb); | 572 | rx_status = IEEE80211_SKB_RXCB(skb); |
584 | mgmt = (struct ieee80211_mgmt *) skb->data; | 573 | mgmt = (struct ieee80211_mgmt *) skb->data; |
585 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; | 574 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; |
586 | 575 | ||
587 | switch (stype) { | 576 | switch (stype) { |
588 | case IEEE80211_STYPE_PROBE_RESP: | 577 | case IEEE80211_STYPE_PROBE_RESP: |
589 | case IEEE80211_STYPE_BEACON: | 578 | case IEEE80211_STYPE_BEACON: |
590 | ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, | 579 | ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, |
591 | rx_status); | 580 | rx_status); |
592 | break; | 581 | break; |
593 | case IEEE80211_STYPE_ACTION: | 582 | case IEEE80211_STYPE_ACTION: |
594 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); | 583 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); |
595 | break; | 584 | break; |
596 | } | 585 | } |
597 | 586 | ||
598 | kfree_skb(skb); | 587 | kfree_skb(skb); |
599 | } | 588 | } |
600 | 589 | ||
601 | static void ieee80211_mesh_work(struct work_struct *work) | 590 | static void ieee80211_mesh_work(struct work_struct *work) |
602 | { | 591 | { |
603 | struct ieee80211_sub_if_data *sdata = | 592 | struct ieee80211_sub_if_data *sdata = |
604 | container_of(work, struct ieee80211_sub_if_data, u.mesh.work); | 593 | container_of(work, struct ieee80211_sub_if_data, u.mesh.work); |
605 | struct ieee80211_local *local = sdata->local; | 594 | struct ieee80211_local *local = sdata->local; |
606 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 595 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
607 | struct sk_buff *skb; | 596 | struct sk_buff *skb; |
608 | 597 | ||
609 | if (!netif_running(sdata->dev)) | 598 | if (!netif_running(sdata->dev)) |
610 | return; | 599 | return; |
611 | 600 | ||
612 | if (local->scanning) | 601 | if (local->scanning) |
613 | return; | 602 | return; |
614 | 603 | ||
615 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) | 604 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) |
616 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); | 605 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); |
617 | 606 | ||
618 | if (ifmsh->preq_queue_len && | 607 | if (ifmsh->preq_queue_len && |
619 | time_after(jiffies, | 608 | time_after(jiffies, |
620 | ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) | 609 | ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) |
621 | mesh_path_start_discovery(sdata); | 610 | mesh_path_start_discovery(sdata); |
622 | 611 | ||
623 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) | 612 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) |
624 | mesh_mpath_table_grow(); | 613 | mesh_mpath_table_grow(); |
625 | 614 | ||
626 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) | 615 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) |
627 | mesh_mpp_table_grow(); | 616 | mesh_mpp_table_grow(); |
628 | 617 | ||
629 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) | 618 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
630 | ieee80211_mesh_housekeeping(sdata, ifmsh); | 619 | ieee80211_mesh_housekeeping(sdata, ifmsh); |
631 | } | 620 | } |
632 | 621 | ||
633 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | 622 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) |
634 | { | 623 | { |
635 | struct ieee80211_sub_if_data *sdata; | 624 | struct ieee80211_sub_if_data *sdata; |
636 | 625 | ||
637 | rcu_read_lock(); | 626 | rcu_read_lock(); |
638 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 627 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
639 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 628 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
640 | ieee80211_queue_work(&local->hw, &sdata->u.mesh.work); | 629 | ieee80211_queue_work(&local->hw, &sdata->u.mesh.work); |
641 | rcu_read_unlock(); | 630 | rcu_read_unlock(); |
642 | } | 631 | } |
643 | 632 | ||
644 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | 633 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) |
645 | { | 634 | { |
646 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 635 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
647 | 636 | ||
648 | INIT_WORK(&ifmsh->work, ieee80211_mesh_work); | 637 | INIT_WORK(&ifmsh->work, ieee80211_mesh_work); |
649 | setup_timer(&ifmsh->housekeeping_timer, | 638 | setup_timer(&ifmsh->housekeeping_timer, |
650 | ieee80211_mesh_housekeeping_timer, | 639 | ieee80211_mesh_housekeeping_timer, |
651 | (unsigned long) sdata); | 640 | (unsigned long) sdata); |
652 | skb_queue_head_init(&sdata->u.mesh.skb_queue); | 641 | skb_queue_head_init(&sdata->u.mesh.skb_queue); |
653 | 642 | ||
654 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; | 643 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; |
655 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | 644 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; |
656 | ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | 645 | ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; |
657 | ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | 646 | ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; |
658 | ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; | 647 | ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; |
659 | ifmsh->mshcfg.auto_open_plinks = true; | 648 | ifmsh->mshcfg.auto_open_plinks = true; |
660 | ifmsh->mshcfg.dot11MeshMaxPeerLinks = | 649 | ifmsh->mshcfg.dot11MeshMaxPeerLinks = |
661 | MESH_MAX_ESTAB_PLINKS; | 650 | MESH_MAX_ESTAB_PLINKS; |
662 | ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = | 651 | ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = |
663 | MESH_PATH_TIMEOUT; | 652 | MESH_PATH_TIMEOUT; |
664 | ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = | 653 | ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = |
665 | MESH_PREQ_MIN_INT; | 654 | MESH_PREQ_MIN_INT; |
666 | ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = | 655 | ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = |
667 | MESH_DIAM_TRAVERSAL_TIME; | 656 | MESH_DIAM_TRAVERSAL_TIME; |
668 | ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = | 657 | ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = |
669 | MESH_MAX_PREQ_RETRIES; | 658 | MESH_MAX_PREQ_RETRIES; |
670 | ifmsh->mshcfg.path_refresh_time = | 659 | ifmsh->mshcfg.path_refresh_time = |
671 | MESH_PATH_REFRESH_TIME; | 660 | MESH_PATH_REFRESH_TIME; |
672 | ifmsh->mshcfg.min_discovery_timeout = | 661 | ifmsh->mshcfg.min_discovery_timeout = |
673 | MESH_MIN_DISCOVERY_TIMEOUT; | 662 | MESH_MIN_DISCOVERY_TIMEOUT; |
674 | ifmsh->accepting_plinks = true; | 663 | ifmsh->accepting_plinks = true; |
675 | ifmsh->preq_id = 0; | 664 | ifmsh->preq_id = 0; |
676 | ifmsh->dsn = 0; | 665 | ifmsh->dsn = 0; |
677 | atomic_set(&ifmsh->mpaths, 0); | 666 | atomic_set(&ifmsh->mpaths, 0); |
678 | mesh_rmc_init(sdata); | 667 | mesh_rmc_init(sdata); |
679 | ifmsh->last_preq = jiffies; | 668 | ifmsh->last_preq = jiffies; |
680 | /* Allocate all mesh structures when creating the first mesh interface. */ | 669 | /* Allocate all mesh structures when creating the first mesh interface. */ |
681 | if (!mesh_allocated) | 670 | if (!mesh_allocated) |
682 | ieee80211s_init(); | 671 | ieee80211s_init(); |
683 | mesh_ids_set_default(ifmsh); | 672 | mesh_ids_set_default(ifmsh); |
684 | setup_timer(&ifmsh->mesh_path_timer, | 673 | setup_timer(&ifmsh->mesh_path_timer, |
685 | ieee80211_mesh_path_timer, | 674 | ieee80211_mesh_path_timer, |
686 | (unsigned long) sdata); | 675 | (unsigned long) sdata); |
687 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); | 676 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
688 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); | 677 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
689 | } | 678 | } |
690 | 679 | ||
691 | ieee80211_rx_result | 680 | ieee80211_rx_result |
692 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | 681 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
693 | { | 682 | { |
694 | struct ieee80211_local *local = sdata->local; | 683 | struct ieee80211_local *local = sdata->local; |
695 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 684 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
696 | struct ieee80211_mgmt *mgmt; | 685 | struct ieee80211_mgmt *mgmt; |
697 | u16 fc; | 686 | u16 fc; |
698 | 687 | ||
699 | if (skb->len < 24) | 688 | if (skb->len < 24) |
700 | return RX_DROP_MONITOR; | 689 | return RX_DROP_MONITOR; |
701 | 690 | ||
702 | mgmt = (struct ieee80211_mgmt *) skb->data; | 691 | mgmt = (struct ieee80211_mgmt *) skb->data; |
703 | fc = le16_to_cpu(mgmt->frame_control); | 692 | fc = le16_to_cpu(mgmt->frame_control); |
704 | 693 | ||
705 | switch (fc & IEEE80211_FCTL_STYPE) { | 694 | switch (fc & IEEE80211_FCTL_STYPE) { |
706 | case IEEE80211_STYPE_ACTION: | 695 | case IEEE80211_STYPE_ACTION: |
707 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | 696 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) |
708 | return RX_DROP_MONITOR; | 697 | return RX_DROP_MONITOR; |
709 | /* fall through */ | 698 | /* fall through */ |
710 | case IEEE80211_STYPE_PROBE_RESP: | 699 | case IEEE80211_STYPE_PROBE_RESP: |
711 | case IEEE80211_STYPE_BEACON: | 700 | case IEEE80211_STYPE_BEACON: |
712 | skb_queue_tail(&ifmsh->skb_queue, skb); | 701 | skb_queue_tail(&ifmsh->skb_queue, skb); |
713 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 702 | ieee80211_queue_work(&local->hw, &ifmsh->work); |
714 | return RX_QUEUED; | 703 | return RX_QUEUED; |
715 | } | 704 | } |
716 | 705 |