Commit 3cfcf6ac6d69dc290e96416731eea5c88ac7d426
Committed by
John W. Linville
1 parent
765cb46a3f
Exists in
master
and in
7 other branches
mac80211: 802.11w - Use BIP (AES-128-CMAC)
Add mechanism for managing BIP keys (IGTK) and integrate BIP into the TX/RX paths. Signed-off-by: Jouni Malinen <j@w1.fi> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Showing 14 changed files with 317 additions and 21 deletions Inline Diff
- drivers/net/wireless/ath5k/pcu.c
- include/linux/ieee80211.h
- include/linux/nl80211.h
- include/net/cfg80211.h
- include/net/mac80211.h
- net/mac80211/cfg.c
- net/mac80211/debugfs_key.c
- net/mac80211/debugfs_key.h
- net/mac80211/ieee80211_i.h
- net/mac80211/key.c
- net/mac80211/key.h
- net/mac80211/rx.c
- net/mac80211/tx.c
- net/wireless/nl80211.c
drivers/net/wireless/ath5k/pcu.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | 2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> |
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | 3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> |
4 | * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org> | 4 | * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org> |
5 | * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | 5 | * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu> |
6 | * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org> | 6 | * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org> |
7 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> | 7 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> |
8 | * | 8 | * |
9 | * Permission to use, copy, modify, and distribute this software for any | 9 | * Permission to use, copy, modify, and distribute this software for any |
10 | * purpose with or without fee is hereby granted, provided that the above | 10 | * purpose with or without fee is hereby granted, provided that the above |
11 | * copyright notice and this permission notice appear in all copies. | 11 | * copyright notice and this permission notice appear in all copies. |
12 | * | 12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /*********************************\ | 23 | /*********************************\ |
24 | * Protocol Control Unit Functions * | 24 | * Protocol Control Unit Functions * |
25 | \*********************************/ | 25 | \*********************************/ |
26 | 26 | ||
27 | #include "ath5k.h" | 27 | #include "ath5k.h" |
28 | #include "reg.h" | 28 | #include "reg.h" |
29 | #include "debug.h" | 29 | #include "debug.h" |
30 | #include "base.h" | 30 | #include "base.h" |
31 | 31 | ||
32 | /*******************\ | 32 | /*******************\ |
33 | * Generic functions * | 33 | * Generic functions * |
34 | \*******************/ | 34 | \*******************/ |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * ath5k_hw_set_opmode - Set PCU operating mode | 37 | * ath5k_hw_set_opmode - Set PCU operating mode |
38 | * | 38 | * |
39 | * @ah: The &struct ath5k_hw | 39 | * @ah: The &struct ath5k_hw |
40 | * | 40 | * |
41 | * Initialize PCU for the various operating modes (AP/STA etc) | 41 | * Initialize PCU for the various operating modes (AP/STA etc) |
42 | * | 42 | * |
43 | * NOTE: ah->ah_op_mode must be set before calling this. | 43 | * NOTE: ah->ah_op_mode must be set before calling this. |
44 | */ | 44 | */ |
45 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | 45 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) |
46 | { | 46 | { |
47 | u32 pcu_reg, beacon_reg, low_id, high_id; | 47 | u32 pcu_reg, beacon_reg, low_id, high_id; |
48 | 48 | ||
49 | 49 | ||
50 | /* Preserve rest settings */ | 50 | /* Preserve rest settings */ |
51 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 51 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
52 | pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP | 52 | pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP |
53 | | AR5K_STA_ID1_KEYSRCH_MODE | 53 | | AR5K_STA_ID1_KEYSRCH_MODE |
54 | | (ah->ah_version == AR5K_AR5210 ? | 54 | | (ah->ah_version == AR5K_AR5210 ? |
55 | (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); | 55 | (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); |
56 | 56 | ||
57 | beacon_reg = 0; | 57 | beacon_reg = 0; |
58 | 58 | ||
59 | ATH5K_TRACE(ah->ah_sc); | 59 | ATH5K_TRACE(ah->ah_sc); |
60 | 60 | ||
61 | switch (ah->ah_op_mode) { | 61 | switch (ah->ah_op_mode) { |
62 | case NL80211_IFTYPE_ADHOC: | 62 | case NL80211_IFTYPE_ADHOC: |
63 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | 63 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; |
64 | beacon_reg |= AR5K_BCR_ADHOC; | 64 | beacon_reg |= AR5K_BCR_ADHOC; |
65 | if (ah->ah_version == AR5K_AR5210) | 65 | if (ah->ah_version == AR5K_AR5210) |
66 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | 66 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; |
67 | else | 67 | else |
68 | AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | 68 | AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); |
69 | break; | 69 | break; |
70 | 70 | ||
71 | case NL80211_IFTYPE_AP: | 71 | case NL80211_IFTYPE_AP: |
72 | case NL80211_IFTYPE_MESH_POINT: | 72 | case NL80211_IFTYPE_MESH_POINT: |
73 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; | 73 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; |
74 | beacon_reg |= AR5K_BCR_AP; | 74 | beacon_reg |= AR5K_BCR_AP; |
75 | if (ah->ah_version == AR5K_AR5210) | 75 | if (ah->ah_version == AR5K_AR5210) |
76 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | 76 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; |
77 | else | 77 | else |
78 | AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | 78 | AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); |
79 | break; | 79 | break; |
80 | 80 | ||
81 | case NL80211_IFTYPE_STATION: | 81 | case NL80211_IFTYPE_STATION: |
82 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | 82 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
83 | | (ah->ah_version == AR5K_AR5210 ? | 83 | | (ah->ah_version == AR5K_AR5210 ? |
84 | AR5K_STA_ID1_PWR_SV : 0); | 84 | AR5K_STA_ID1_PWR_SV : 0); |
85 | case NL80211_IFTYPE_MONITOR: | 85 | case NL80211_IFTYPE_MONITOR: |
86 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | 86 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
87 | | (ah->ah_version == AR5K_AR5210 ? | 87 | | (ah->ah_version == AR5K_AR5210 ? |
88 | AR5K_STA_ID1_NO_PSPOLL : 0); | 88 | AR5K_STA_ID1_NO_PSPOLL : 0); |
89 | break; | 89 | break; |
90 | 90 | ||
91 | default: | 91 | default: |
92 | return -EINVAL; | 92 | return -EINVAL; |
93 | } | 93 | } |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * Set PCU registers | 96 | * Set PCU registers |
97 | */ | 97 | */ |
98 | low_id = AR5K_LOW_ID(ah->ah_sta_id); | 98 | low_id = AR5K_LOW_ID(ah->ah_sta_id); |
99 | high_id = AR5K_HIGH_ID(ah->ah_sta_id); | 99 | high_id = AR5K_HIGH_ID(ah->ah_sta_id); |
100 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | 100 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); |
101 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | 101 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Set Beacon Control Register on 5210 | 104 | * Set Beacon Control Register on 5210 |
105 | */ | 105 | */ |
106 | if (ah->ah_version == AR5K_AR5210) | 106 | if (ah->ah_version == AR5K_AR5210) |
107 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); | 107 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); |
108 | 108 | ||
109 | return 0; | 109 | return 0; |
110 | } | 110 | } |
111 | 111 | ||
112 | /** | 112 | /** |
113 | * ath5k_hw_update - Update mib counters (mac layer statistics) | 113 | * ath5k_hw_update - Update mib counters (mac layer statistics) |
114 | * | 114 | * |
115 | * @ah: The &struct ath5k_hw | 115 | * @ah: The &struct ath5k_hw |
116 | * @stats: The &struct ieee80211_low_level_stats we use to track | 116 | * @stats: The &struct ieee80211_low_level_stats we use to track |
117 | * statistics on the driver | 117 | * statistics on the driver |
118 | * | 118 | * |
119 | * Reads MIB counters from PCU and updates sw statistics. Must be | 119 | * Reads MIB counters from PCU and updates sw statistics. Must be |
120 | * called after a MIB interrupt. | 120 | * called after a MIB interrupt. |
121 | */ | 121 | */ |
122 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | 122 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, |
123 | struct ieee80211_low_level_stats *stats) | 123 | struct ieee80211_low_level_stats *stats) |
124 | { | 124 | { |
125 | ATH5K_TRACE(ah->ah_sc); | 125 | ATH5K_TRACE(ah->ah_sc); |
126 | 126 | ||
127 | /* Read-And-Clear */ | 127 | /* Read-And-Clear */ |
128 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | 128 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); |
129 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | 129 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); |
130 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | 130 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); |
131 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | 131 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); |
132 | 132 | ||
133 | /* XXX: Should we use this to track beacon count ? | 133 | /* XXX: Should we use this to track beacon count ? |
134 | * -we read it anyway to clear the register */ | 134 | * -we read it anyway to clear the register */ |
135 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | 135 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); |
136 | 136 | ||
137 | /* Reset profile count registers on 5212*/ | 137 | /* Reset profile count registers on 5212*/ |
138 | if (ah->ah_version == AR5K_AR5212) { | 138 | if (ah->ah_version == AR5K_AR5212) { |
139 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | 139 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); |
140 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | 140 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); |
141 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | 141 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); |
142 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | 142 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); |
143 | } | 143 | } |
144 | 144 | ||
145 | /* TODO: Handle ANI stats */ | 145 | /* TODO: Handle ANI stats */ |
146 | } | 146 | } |
147 | 147 | ||
148 | /** | 148 | /** |
149 | * ath5k_hw_set_ack_bitrate - set bitrate for ACKs | 149 | * ath5k_hw_set_ack_bitrate - set bitrate for ACKs |
150 | * | 150 | * |
151 | * @ah: The &struct ath5k_hw | 151 | * @ah: The &struct ath5k_hw |
152 | * @high: Flag to determine if we want to use high transmition rate | 152 | * @high: Flag to determine if we want to use high transmition rate |
153 | * for ACKs or not | 153 | * for ACKs or not |
154 | * | 154 | * |
155 | * If high flag is set, we tell hw to use a set of control rates based on | 155 | * If high flag is set, we tell hw to use a set of control rates based on |
156 | * the current transmition rate (check out control_rates array inside reset.c). | 156 | * the current transmition rate (check out control_rates array inside reset.c). |
157 | * If not hw just uses the lowest rate available for the current modulation | 157 | * If not hw just uses the lowest rate available for the current modulation |
158 | * scheme being used (1Mbit for CCK and 6Mbits for OFDM). | 158 | * scheme being used (1Mbit for CCK and 6Mbits for OFDM). |
159 | */ | 159 | */ |
160 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | 160 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) |
161 | { | 161 | { |
162 | if (ah->ah_version != AR5K_AR5212) | 162 | if (ah->ah_version != AR5K_AR5212) |
163 | return; | 163 | return; |
164 | else { | 164 | else { |
165 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | 165 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; |
166 | if (high) | 166 | if (high) |
167 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | 167 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); |
168 | else | 168 | else |
169 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | 169 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); |
170 | } | 170 | } |
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | /******************\ | 174 | /******************\ |
175 | * ACK/CTS Timeouts * | 175 | * ACK/CTS Timeouts * |
176 | \******************/ | 176 | \******************/ |
177 | 177 | ||
178 | /** | 178 | /** |
179 | * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec | 179 | * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec |
180 | * | 180 | * |
181 | * @ah: The &struct ath5k_hw | 181 | * @ah: The &struct ath5k_hw |
182 | */ | 182 | */ |
183 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | 183 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) |
184 | { | 184 | { |
185 | ATH5K_TRACE(ah->ah_sc); | 185 | ATH5K_TRACE(ah->ah_sc); |
186 | 186 | ||
187 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 187 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, |
188 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); | 188 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); |
189 | } | 189 | } |
190 | 190 | ||
191 | /** | 191 | /** |
192 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | 192 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU |
193 | * | 193 | * |
194 | * @ah: The &struct ath5k_hw | 194 | * @ah: The &struct ath5k_hw |
195 | * @timeout: Timeout in usec | 195 | * @timeout: Timeout in usec |
196 | */ | 196 | */ |
197 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 197 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
198 | { | 198 | { |
199 | ATH5K_TRACE(ah->ah_sc); | 199 | ATH5K_TRACE(ah->ah_sc); |
200 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), | 200 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), |
201 | ah->ah_turbo) <= timeout) | 201 | ah->ah_turbo) <= timeout) |
202 | return -EINVAL; | 202 | return -EINVAL; |
203 | 203 | ||
204 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, | 204 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, |
205 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 205 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); |
206 | 206 | ||
207 | return 0; | 207 | return 0; |
208 | } | 208 | } |
209 | 209 | ||
210 | /** | 210 | /** |
211 | * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec | 211 | * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec |
212 | * | 212 | * |
213 | * @ah: The &struct ath5k_hw | 213 | * @ah: The &struct ath5k_hw |
214 | */ | 214 | */ |
215 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | 215 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) |
216 | { | 216 | { |
217 | ATH5K_TRACE(ah->ah_sc); | 217 | ATH5K_TRACE(ah->ah_sc); |
218 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 218 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, |
219 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); | 219 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); |
220 | } | 220 | } |
221 | 221 | ||
222 | /** | 222 | /** |
223 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU | 223 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU |
224 | * | 224 | * |
225 | * @ah: The &struct ath5k_hw | 225 | * @ah: The &struct ath5k_hw |
226 | * @timeout: Timeout in usec | 226 | * @timeout: Timeout in usec |
227 | */ | 227 | */ |
228 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 228 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
229 | { | 229 | { |
230 | ATH5K_TRACE(ah->ah_sc); | 230 | ATH5K_TRACE(ah->ah_sc); |
231 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), | 231 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), |
232 | ah->ah_turbo) <= timeout) | 232 | ah->ah_turbo) <= timeout) |
233 | return -EINVAL; | 233 | return -EINVAL; |
234 | 234 | ||
235 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, | 235 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, |
236 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 236 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); |
237 | 237 | ||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | 241 | ||
242 | /****************\ | 242 | /****************\ |
243 | * BSSID handling * | 243 | * BSSID handling * |
244 | \****************/ | 244 | \****************/ |
245 | 245 | ||
246 | /** | 246 | /** |
247 | * ath5k_hw_get_lladdr - Get station id | 247 | * ath5k_hw_get_lladdr - Get station id |
248 | * | 248 | * |
249 | * @ah: The &struct ath5k_hw | 249 | * @ah: The &struct ath5k_hw |
250 | * @mac: The card's mac address | 250 | * @mac: The card's mac address |
251 | * | 251 | * |
252 | * Initialize ah->ah_sta_id using the mac address provided | 252 | * Initialize ah->ah_sta_id using the mac address provided |
253 | * (just a memcpy). | 253 | * (just a memcpy). |
254 | * | 254 | * |
255 | * TODO: Remove it once we merge ath5k_softc and ath5k_hw | 255 | * TODO: Remove it once we merge ath5k_softc and ath5k_hw |
256 | */ | 256 | */ |
257 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | 257 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) |
258 | { | 258 | { |
259 | ATH5K_TRACE(ah->ah_sc); | 259 | ATH5K_TRACE(ah->ah_sc); |
260 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); | 260 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); |
261 | } | 261 | } |
262 | 262 | ||
263 | /** | 263 | /** |
264 | * ath5k_hw_set_lladdr - Set station id | 264 | * ath5k_hw_set_lladdr - Set station id |
265 | * | 265 | * |
266 | * @ah: The &struct ath5k_hw | 266 | * @ah: The &struct ath5k_hw |
267 | * @mac: The card's mac address | 267 | * @mac: The card's mac address |
268 | * | 268 | * |
269 | * Set station id on hw using the provided mac address | 269 | * Set station id on hw using the provided mac address |
270 | */ | 270 | */ |
271 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | 271 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) |
272 | { | 272 | { |
273 | u32 low_id, high_id; | 273 | u32 low_id, high_id; |
274 | u32 pcu_reg; | 274 | u32 pcu_reg; |
275 | 275 | ||
276 | ATH5K_TRACE(ah->ah_sc); | 276 | ATH5K_TRACE(ah->ah_sc); |
277 | /* Set new station ID */ | 277 | /* Set new station ID */ |
278 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); | 278 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); |
279 | 279 | ||
280 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 280 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
281 | 281 | ||
282 | low_id = AR5K_LOW_ID(mac); | 282 | low_id = AR5K_LOW_ID(mac); |
283 | high_id = AR5K_HIGH_ID(mac); | 283 | high_id = AR5K_HIGH_ID(mac); |
284 | 284 | ||
285 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | 285 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); |
286 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | 286 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
287 | 287 | ||
288 | return 0; | 288 | return 0; |
289 | } | 289 | } |
290 | 290 | ||
291 | /** | 291 | /** |
292 | * ath5k_hw_set_associd - Set BSSID for association | 292 | * ath5k_hw_set_associd - Set BSSID for association |
293 | * | 293 | * |
294 | * @ah: The &struct ath5k_hw | 294 | * @ah: The &struct ath5k_hw |
295 | * @bssid: BSSID | 295 | * @bssid: BSSID |
296 | * @assoc_id: Assoc id | 296 | * @assoc_id: Assoc id |
297 | * | 297 | * |
298 | * Sets the BSSID which trigers the "SME Join" operation | 298 | * Sets the BSSID which trigers the "SME Join" operation |
299 | */ | 299 | */ |
300 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | 300 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) |
301 | { | 301 | { |
302 | u32 low_id, high_id; | 302 | u32 low_id, high_id; |
303 | u16 tim_offset = 0; | 303 | u16 tim_offset = 0; |
304 | 304 | ||
305 | /* | 305 | /* |
306 | * Set simple BSSID mask on 5212 | 306 | * Set simple BSSID mask on 5212 |
307 | */ | 307 | */ |
308 | if (ah->ah_version == AR5K_AR5212) { | 308 | if (ah->ah_version == AR5K_AR5212) { |
309 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), | 309 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), |
310 | AR5K_BSS_IDM0); | 310 | AR5K_BSS_IDM0); |
311 | ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), | 311 | ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), |
312 | AR5K_BSS_IDM1); | 312 | AR5K_BSS_IDM1); |
313 | } | 313 | } |
314 | 314 | ||
315 | /* | 315 | /* |
316 | * Set BSSID which triggers the "SME Join" operation | 316 | * Set BSSID which triggers the "SME Join" operation |
317 | */ | 317 | */ |
318 | low_id = AR5K_LOW_ID(bssid); | 318 | low_id = AR5K_LOW_ID(bssid); |
319 | high_id = AR5K_HIGH_ID(bssid); | 319 | high_id = AR5K_HIGH_ID(bssid); |
320 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); | 320 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); |
321 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << | 321 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << |
322 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); | 322 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); |
323 | 323 | ||
324 | if (assoc_id == 0) { | 324 | if (assoc_id == 0) { |
325 | ath5k_hw_disable_pspoll(ah); | 325 | ath5k_hw_disable_pspoll(ah); |
326 | return; | 326 | return; |
327 | } | 327 | } |
328 | 328 | ||
329 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, | 329 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, |
330 | tim_offset ? tim_offset + 4 : 0); | 330 | tim_offset ? tim_offset + 4 : 0); |
331 | 331 | ||
332 | ath5k_hw_enable_pspoll(ah, NULL, 0); | 332 | ath5k_hw_enable_pspoll(ah, NULL, 0); |
333 | } | 333 | } |
334 | 334 | ||
335 | /** | 335 | /** |
336 | * ath5k_hw_set_bssid_mask - filter out bssids we listen | 336 | * ath5k_hw_set_bssid_mask - filter out bssids we listen |
337 | * | 337 | * |
338 | * @ah: the &struct ath5k_hw | 338 | * @ah: the &struct ath5k_hw |
339 | * @mask: the bssid_mask, a u8 array of size ETH_ALEN | 339 | * @mask: the bssid_mask, a u8 array of size ETH_ALEN |
340 | * | 340 | * |
341 | * BSSID masking is a method used by AR5212 and newer hardware to inform PCU | 341 | * BSSID masking is a method used by AR5212 and newer hardware to inform PCU |
342 | * which bits of the interface's MAC address should be looked at when trying | 342 | * which bits of the interface's MAC address should be looked at when trying |
343 | * to decide which packets to ACK. In station mode and AP mode with a single | 343 | * to decide which packets to ACK. In station mode and AP mode with a single |
344 | * BSS every bit matters since we lock to only one BSS. In AP mode with | 344 | * BSS every bit matters since we lock to only one BSS. In AP mode with |
345 | * multiple BSSes (virtual interfaces) not every bit matters because hw must | 345 | * multiple BSSes (virtual interfaces) not every bit matters because hw must |
346 | * accept frames for all BSSes and so we tweak some bits of our mac address | 346 | * accept frames for all BSSes and so we tweak some bits of our mac address |
347 | * in order to have multiple BSSes. | 347 | * in order to have multiple BSSes. |
348 | * | 348 | * |
349 | * NOTE: This is a simple filter and does *not* filter out all | 349 | * NOTE: This is a simple filter and does *not* filter out all |
350 | * relevant frames. Some frames that are not for us might get ACKed from us | 350 | * relevant frames. Some frames that are not for us might get ACKed from us |
351 | * by PCU because they just match the mask. | 351 | * by PCU because they just match the mask. |
352 | * | 352 | * |
353 | * When handling multiple BSSes you can get the BSSID mask by computing the | 353 | * When handling multiple BSSes you can get the BSSID mask by computing the |
354 | * set of ~ ( MAC XOR BSSID ) for all bssids we handle. | 354 | * set of ~ ( MAC XOR BSSID ) for all bssids we handle. |
355 | * | 355 | * |
356 | * When you do this you are essentially computing the common bits of all your | 356 | * When you do this you are essentially computing the common bits of all your |
357 | * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with | 357 | * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with |
358 | * the MAC address to obtain the relevant bits and compare the result with | 358 | * the MAC address to obtain the relevant bits and compare the result with |
359 | * (frame's BSSID & mask) to see if they match. | 359 | * (frame's BSSID & mask) to see if they match. |
360 | */ | 360 | */ |
361 | /* | 361 | /* |
362 | * Simple example: on your card you have have two BSSes you have created with | 362 | * Simple example: on your card you have have two BSSes you have created with |
363 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. | 363 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. |
364 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, | 364 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, |
365 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: | 365 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: |
366 | * | 366 | * |
367 | * \ | 367 | * \ |
368 | * MAC: 0001 | | 368 | * MAC: 0001 | |
369 | * BSSID-01: 0100 | --> Belongs to us | 369 | * BSSID-01: 0100 | --> Belongs to us |
370 | * BSSID-02: 1001 | | 370 | * BSSID-02: 1001 | |
371 | * / | 371 | * / |
372 | * ------------------- | 372 | * ------------------- |
373 | * BSSID-03: 0110 | --> External | 373 | * BSSID-03: 0110 | --> External |
374 | * ------------------- | 374 | * ------------------- |
375 | * | 375 | * |
376 | * Our bssid_mask would then be: | 376 | * Our bssid_mask would then be: |
377 | * | 377 | * |
378 | * On loop iteration for BSSID-01: | 378 | * On loop iteration for BSSID-01: |
379 | * ~(0001 ^ 0100) -> ~(0101) | 379 | * ~(0001 ^ 0100) -> ~(0101) |
380 | * -> 1010 | 380 | * -> 1010 |
381 | * bssid_mask = 1010 | 381 | * bssid_mask = 1010 |
382 | * | 382 | * |
383 | * On loop iteration for BSSID-02: | 383 | * On loop iteration for BSSID-02: |
384 | * bssid_mask &= ~(0001 ^ 1001) | 384 | * bssid_mask &= ~(0001 ^ 1001) |
385 | * bssid_mask = (1010) & ~(0001 ^ 1001) | 385 | * bssid_mask = (1010) & ~(0001 ^ 1001) |
386 | * bssid_mask = (1010) & ~(1001) | 386 | * bssid_mask = (1010) & ~(1001) |
387 | * bssid_mask = (1010) & (0110) | 387 | * bssid_mask = (1010) & (0110) |
388 | * bssid_mask = 0010 | 388 | * bssid_mask = 0010 |
389 | * | 389 | * |
390 | * A bssid_mask of 0010 means "only pay attention to the second least | 390 | * A bssid_mask of 0010 means "only pay attention to the second least |
391 | * significant bit". This is because its the only bit common | 391 | * significant bit". This is because its the only bit common |
392 | * amongst the MAC and all BSSIDs we support. To findout what the real | 392 | * amongst the MAC and all BSSIDs we support. To findout what the real |
393 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have | 393 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have |
394 | * or our MAC address (we assume the hardware uses the MAC address). | 394 | * or our MAC address (we assume the hardware uses the MAC address). |
395 | * | 395 | * |
396 | * Now, suppose there's an incoming frame for BSSID-03: | 396 | * Now, suppose there's an incoming frame for BSSID-03: |
397 | * | 397 | * |
398 | * IFRAME-01: 0110 | 398 | * IFRAME-01: 0110 |
399 | * | 399 | * |
400 | * An easy eye-inspeciton of this already should tell you that this frame | 400 | * An easy eye-inspeciton of this already should tell you that this frame |
401 | * will not pass our check. This is beacuse the bssid_mask tells the | 401 | * will not pass our check. This is beacuse the bssid_mask tells the |
402 | * hardware to only look at the second least significant bit and the | 402 | * hardware to only look at the second least significant bit and the |
403 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB | 403 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB |
404 | * as 1, which does not match 0. | 404 | * as 1, which does not match 0. |
405 | * | 405 | * |
406 | * So with IFRAME-01 we *assume* the hardware will do: | 406 | * So with IFRAME-01 we *assume* the hardware will do: |
407 | * | 407 | * |
408 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | 408 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; |
409 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; | 409 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; |
410 | * --> allow = (0010) == 0000 ? 1 : 0; | 410 | * --> allow = (0010) == 0000 ? 1 : 0; |
411 | * --> allow = 0 | 411 | * --> allow = 0 |
412 | * | 412 | * |
413 | * Lets now test a frame that should work: | 413 | * Lets now test a frame that should work: |
414 | * | 414 | * |
415 | * IFRAME-02: 0001 (we should allow) | 415 | * IFRAME-02: 0001 (we should allow) |
416 | * | 416 | * |
417 | * allow = (0001 & 1010) == 1010 | 417 | * allow = (0001 & 1010) == 1010 |
418 | * | 418 | * |
419 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | 419 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; |
420 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; | 420 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; |
421 | * --> allow = (0010) == (0010) | 421 | * --> allow = (0010) == (0010) |
422 | * --> allow = 1 | 422 | * --> allow = 1 |
423 | * | 423 | * |
424 | * Other examples: | 424 | * Other examples: |
425 | * | 425 | * |
426 | * IFRAME-03: 0100 --> allowed | 426 | * IFRAME-03: 0100 --> allowed |
427 | * IFRAME-04: 1001 --> allowed | 427 | * IFRAME-04: 1001 --> allowed |
428 | * IFRAME-05: 1101 --> allowed but its not for us!!! | 428 | * IFRAME-05: 1101 --> allowed but its not for us!!! |
429 | * | 429 | * |
430 | */ | 430 | */ |
431 | int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | 431 | int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) |
432 | { | 432 | { |
433 | u32 low_id, high_id; | 433 | u32 low_id, high_id; |
434 | ATH5K_TRACE(ah->ah_sc); | 434 | ATH5K_TRACE(ah->ah_sc); |
435 | 435 | ||
436 | /* Cache bssid mask so that we can restore it | 436 | /* Cache bssid mask so that we can restore it |
437 | * on reset */ | 437 | * on reset */ |
438 | memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); | 438 | memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); |
439 | if (ah->ah_version == AR5K_AR5212) { | 439 | if (ah->ah_version == AR5K_AR5212) { |
440 | low_id = AR5K_LOW_ID(mask); | 440 | low_id = AR5K_LOW_ID(mask); |
441 | high_id = AR5K_HIGH_ID(mask); | 441 | high_id = AR5K_HIGH_ID(mask); |
442 | 442 | ||
443 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); | 443 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); |
444 | ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); | 444 | ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); |
445 | 445 | ||
446 | return 0; | 446 | return 0; |
447 | } | 447 | } |
448 | 448 | ||
449 | return -EIO; | 449 | return -EIO; |
450 | } | 450 | } |
451 | 451 | ||
452 | 452 | ||
453 | /************\ | 453 | /************\ |
454 | * RX Control * | 454 | * RX Control * |
455 | \************/ | 455 | \************/ |
456 | 456 | ||
457 | /** | 457 | /** |
458 | * ath5k_hw_start_rx_pcu - Start RX engine | 458 | * ath5k_hw_start_rx_pcu - Start RX engine |
459 | * | 459 | * |
460 | * @ah: The &struct ath5k_hw | 460 | * @ah: The &struct ath5k_hw |
461 | * | 461 | * |
462 | * Starts RX engine on PCU so that hw can process RXed frames | 462 | * Starts RX engine on PCU so that hw can process RXed frames |
463 | * (ACK etc). | 463 | * (ACK etc). |
464 | * | 464 | * |
465 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | 465 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma |
466 | * TODO: Init ANI here | 466 | * TODO: Init ANI here |
467 | */ | 467 | */ |
468 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | 468 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) |
469 | { | 469 | { |
470 | ATH5K_TRACE(ah->ah_sc); | 470 | ATH5K_TRACE(ah->ah_sc); |
471 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 471 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
472 | } | 472 | } |
473 | 473 | ||
474 | /** | 474 | /** |
475 | * at5k_hw_stop_rx_pcu - Stop RX engine | 475 | * at5k_hw_stop_rx_pcu - Stop RX engine |
476 | * | 476 | * |
477 | * @ah: The &struct ath5k_hw | 477 | * @ah: The &struct ath5k_hw |
478 | * | 478 | * |
479 | * Stops RX engine on PCU | 479 | * Stops RX engine on PCU |
480 | * | 480 | * |
481 | * TODO: Detach ANI here | 481 | * TODO: Detach ANI here |
482 | */ | 482 | */ |
483 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | 483 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) |
484 | { | 484 | { |
485 | ATH5K_TRACE(ah->ah_sc); | 485 | ATH5K_TRACE(ah->ah_sc); |
486 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 486 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
487 | } | 487 | } |
488 | 488 | ||
489 | /* | 489 | /* |
490 | * Set multicast filter | 490 | * Set multicast filter |
491 | */ | 491 | */ |
492 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | 492 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) |
493 | { | 493 | { |
494 | ATH5K_TRACE(ah->ah_sc); | 494 | ATH5K_TRACE(ah->ah_sc); |
495 | /* Set the multicat filter */ | 495 | /* Set the multicat filter */ |
496 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); | 496 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); |
497 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | 497 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); |
498 | } | 498 | } |
499 | 499 | ||
500 | /* | 500 | /* |
501 | * Set multicast filter by index | 501 | * Set multicast filter by index |
502 | */ | 502 | */ |
503 | int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | 503 | int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) |
504 | { | 504 | { |
505 | 505 | ||
506 | ATH5K_TRACE(ah->ah_sc); | 506 | ATH5K_TRACE(ah->ah_sc); |
507 | if (index >= 64) | 507 | if (index >= 64) |
508 | return -EINVAL; | 508 | return -EINVAL; |
509 | else if (index >= 32) | 509 | else if (index >= 32) |
510 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, | 510 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, |
511 | (1 << (index - 32))); | 511 | (1 << (index - 32))); |
512 | else | 512 | else |
513 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | 513 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); |
514 | 514 | ||
515 | return 0; | 515 | return 0; |
516 | } | 516 | } |
517 | 517 | ||
518 | /* | 518 | /* |
519 | * Clear Multicast filter by index | 519 | * Clear Multicast filter by index |
520 | */ | 520 | */ |
521 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | 521 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) |
522 | { | 522 | { |
523 | 523 | ||
524 | ATH5K_TRACE(ah->ah_sc); | 524 | ATH5K_TRACE(ah->ah_sc); |
525 | if (index >= 64) | 525 | if (index >= 64) |
526 | return -EINVAL; | 526 | return -EINVAL; |
527 | else if (index >= 32) | 527 | else if (index >= 32) |
528 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, | 528 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, |
529 | (1 << (index - 32))); | 529 | (1 << (index - 32))); |
530 | else | 530 | else |
531 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | 531 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); |
532 | 532 | ||
533 | return 0; | 533 | return 0; |
534 | } | 534 | } |
535 | 535 | ||
536 | /** | 536 | /** |
537 | * ath5k_hw_get_rx_filter - Get current rx filter | 537 | * ath5k_hw_get_rx_filter - Get current rx filter |
538 | * | 538 | * |
539 | * @ah: The &struct ath5k_hw | 539 | * @ah: The &struct ath5k_hw |
540 | * | 540 | * |
541 | * Returns the RX filter by reading rx filter and | 541 | * Returns the RX filter by reading rx filter and |
542 | * phy error filter registers. RX filter is used | 542 | * phy error filter registers. RX filter is used |
543 | * to set the allowed frame types that PCU will accept | 543 | * to set the allowed frame types that PCU will accept |
544 | * and pass to the driver. For a list of frame types | 544 | * and pass to the driver. For a list of frame types |
545 | * check out reg.h. | 545 | * check out reg.h. |
546 | */ | 546 | */ |
547 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | 547 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) |
548 | { | 548 | { |
549 | u32 data, filter = 0; | 549 | u32 data, filter = 0; |
550 | 550 | ||
551 | ATH5K_TRACE(ah->ah_sc); | 551 | ATH5K_TRACE(ah->ah_sc); |
552 | filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); | 552 | filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); |
553 | 553 | ||
554 | /*Radar detection for 5212*/ | 554 | /*Radar detection for 5212*/ |
555 | if (ah->ah_version == AR5K_AR5212) { | 555 | if (ah->ah_version == AR5K_AR5212) { |
556 | data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); | 556 | data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); |
557 | 557 | ||
558 | if (data & AR5K_PHY_ERR_FIL_RADAR) | 558 | if (data & AR5K_PHY_ERR_FIL_RADAR) |
559 | filter |= AR5K_RX_FILTER_RADARERR; | 559 | filter |= AR5K_RX_FILTER_RADARERR; |
560 | if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) | 560 | if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) |
561 | filter |= AR5K_RX_FILTER_PHYERR; | 561 | filter |= AR5K_RX_FILTER_PHYERR; |
562 | } | 562 | } |
563 | 563 | ||
564 | return filter; | 564 | return filter; |
565 | } | 565 | } |
566 | 566 | ||
567 | /** | 567 | /** |
568 | * ath5k_hw_set_rx_filter - Set rx filter | 568 | * ath5k_hw_set_rx_filter - Set rx filter |
569 | * | 569 | * |
570 | * @ah: The &struct ath5k_hw | 570 | * @ah: The &struct ath5k_hw |
571 | * @filter: RX filter mask (see reg.h) | 571 | * @filter: RX filter mask (see reg.h) |
572 | * | 572 | * |
573 | * Sets RX filter register and also handles PHY error filter | 573 | * Sets RX filter register and also handles PHY error filter |
574 | * register on 5212 and newer chips so that we have proper PHY | 574 | * register on 5212 and newer chips so that we have proper PHY |
575 | * error reporting. | 575 | * error reporting. |
576 | */ | 576 | */ |
577 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | 577 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) |
578 | { | 578 | { |
579 | u32 data = 0; | 579 | u32 data = 0; |
580 | 580 | ||
581 | ATH5K_TRACE(ah->ah_sc); | 581 | ATH5K_TRACE(ah->ah_sc); |
582 | 582 | ||
583 | /* Set PHY error filter register on 5212*/ | 583 | /* Set PHY error filter register on 5212*/ |
584 | if (ah->ah_version == AR5K_AR5212) { | 584 | if (ah->ah_version == AR5K_AR5212) { |
585 | if (filter & AR5K_RX_FILTER_RADARERR) | 585 | if (filter & AR5K_RX_FILTER_RADARERR) |
586 | data |= AR5K_PHY_ERR_FIL_RADAR; | 586 | data |= AR5K_PHY_ERR_FIL_RADAR; |
587 | if (filter & AR5K_RX_FILTER_PHYERR) | 587 | if (filter & AR5K_RX_FILTER_PHYERR) |
588 | data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; | 588 | data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; |
589 | } | 589 | } |
590 | 590 | ||
591 | /* | 591 | /* |
592 | * The AR5210 uses promiscous mode to detect radar activity | 592 | * The AR5210 uses promiscous mode to detect radar activity |
593 | */ | 593 | */ |
594 | if (ah->ah_version == AR5K_AR5210 && | 594 | if (ah->ah_version == AR5K_AR5210 && |
595 | (filter & AR5K_RX_FILTER_RADARERR)) { | 595 | (filter & AR5K_RX_FILTER_RADARERR)) { |
596 | filter &= ~AR5K_RX_FILTER_RADARERR; | 596 | filter &= ~AR5K_RX_FILTER_RADARERR; |
597 | filter |= AR5K_RX_FILTER_PROM; | 597 | filter |= AR5K_RX_FILTER_PROM; |
598 | } | 598 | } |
599 | 599 | ||
600 | /*Zero length DMA (phy error reporting) */ | 600 | /*Zero length DMA (phy error reporting) */ |
601 | if (data) | 601 | if (data) |
602 | AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | 602 | AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); |
603 | else | 603 | else |
604 | AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | 604 | AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); |
605 | 605 | ||
606 | /*Write RX Filter register*/ | 606 | /*Write RX Filter register*/ |
607 | ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); | 607 | ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); |
608 | 608 | ||
609 | /*Write PHY error filter register on 5212*/ | 609 | /*Write PHY error filter register on 5212*/ |
610 | if (ah->ah_version == AR5K_AR5212) | 610 | if (ah->ah_version == AR5K_AR5212) |
611 | ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); | 611 | ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); |
612 | 612 | ||
613 | } | 613 | } |
614 | 614 | ||
615 | 615 | ||
616 | /****************\ | 616 | /****************\ |
617 | * Beacon control * | 617 | * Beacon control * |
618 | \****************/ | 618 | \****************/ |
619 | 619 | ||
620 | /** | 620 | /** |
621 | * ath5k_hw_get_tsf32 - Get a 32bit TSF | 621 | * ath5k_hw_get_tsf32 - Get a 32bit TSF |
622 | * | 622 | * |
623 | * @ah: The &struct ath5k_hw | 623 | * @ah: The &struct ath5k_hw |
624 | * | 624 | * |
625 | * Returns lower 32 bits of current TSF | 625 | * Returns lower 32 bits of current TSF |
626 | */ | 626 | */ |
627 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | 627 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) |
628 | { | 628 | { |
629 | ATH5K_TRACE(ah->ah_sc); | 629 | ATH5K_TRACE(ah->ah_sc); |
630 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); | 630 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); |
631 | } | 631 | } |
632 | 632 | ||
633 | /** | 633 | /** |
634 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF | 634 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF |
635 | * | 635 | * |
636 | * @ah: The &struct ath5k_hw | 636 | * @ah: The &struct ath5k_hw |
637 | * | 637 | * |
638 | * Returns the current TSF | 638 | * Returns the current TSF |
639 | */ | 639 | */ |
640 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | 640 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) |
641 | { | 641 | { |
642 | u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | 642 | u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); |
643 | ATH5K_TRACE(ah->ah_sc); | 643 | ATH5K_TRACE(ah->ah_sc); |
644 | 644 | ||
645 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); | 645 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); |
646 | } | 646 | } |
647 | 647 | ||
648 | /** | 648 | /** |
649 | * ath5k_hw_reset_tsf - Force a TSF reset | 649 | * ath5k_hw_reset_tsf - Force a TSF reset |
650 | * | 650 | * |
651 | * @ah: The &struct ath5k_hw | 651 | * @ah: The &struct ath5k_hw |
652 | * | 652 | * |
653 | * Forces a TSF reset on PCU | 653 | * Forces a TSF reset on PCU |
654 | */ | 654 | */ |
655 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah) | 655 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah) |
656 | { | 656 | { |
657 | u32 val; | 657 | u32 val; |
658 | 658 | ||
659 | ATH5K_TRACE(ah->ah_sc); | 659 | ATH5K_TRACE(ah->ah_sc); |
660 | 660 | ||
661 | val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; | 661 | val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; |
662 | 662 | ||
663 | /* | 663 | /* |
664 | * Each write to the RESET_TSF bit toggles a hardware internal | 664 | * Each write to the RESET_TSF bit toggles a hardware internal |
665 | * signal to reset TSF, but if left high it will cause a TSF reset | 665 | * signal to reset TSF, but if left high it will cause a TSF reset |
666 | * on the next chip reset as well. Thus we always write the value | 666 | * on the next chip reset as well. Thus we always write the value |
667 | * twice to clear the signal. | 667 | * twice to clear the signal. |
668 | */ | 668 | */ |
669 | ath5k_hw_reg_write(ah, val, AR5K_BEACON); | 669 | ath5k_hw_reg_write(ah, val, AR5K_BEACON); |
670 | ath5k_hw_reg_write(ah, val, AR5K_BEACON); | 670 | ath5k_hw_reg_write(ah, val, AR5K_BEACON); |
671 | } | 671 | } |
672 | 672 | ||
673 | /* | 673 | /* |
674 | * Initialize beacon timers | 674 | * Initialize beacon timers |
675 | */ | 675 | */ |
676 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | 676 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) |
677 | { | 677 | { |
678 | u32 timer1, timer2, timer3; | 678 | u32 timer1, timer2, timer3; |
679 | 679 | ||
680 | ATH5K_TRACE(ah->ah_sc); | 680 | ATH5K_TRACE(ah->ah_sc); |
681 | /* | 681 | /* |
682 | * Set the additional timers by mode | 682 | * Set the additional timers by mode |
683 | */ | 683 | */ |
684 | switch (ah->ah_op_mode) { | 684 | switch (ah->ah_op_mode) { |
685 | case NL80211_IFTYPE_MONITOR: | 685 | case NL80211_IFTYPE_MONITOR: |
686 | case NL80211_IFTYPE_STATION: | 686 | case NL80211_IFTYPE_STATION: |
687 | /* In STA mode timer1 is used as next wakeup | 687 | /* In STA mode timer1 is used as next wakeup |
688 | * timer and timer2 as next CFP duration start | 688 | * timer and timer2 as next CFP duration start |
689 | * timer. Both in 1/8TUs. */ | 689 | * timer. Both in 1/8TUs. */ |
690 | /* TODO: PCF handling */ | 690 | /* TODO: PCF handling */ |
691 | if (ah->ah_version == AR5K_AR5210) { | 691 | if (ah->ah_version == AR5K_AR5210) { |
692 | timer1 = 0xffffffff; | 692 | timer1 = 0xffffffff; |
693 | timer2 = 0xffffffff; | 693 | timer2 = 0xffffffff; |
694 | } else { | 694 | } else { |
695 | timer1 = 0x0000ffff; | 695 | timer1 = 0x0000ffff; |
696 | timer2 = 0x0007ffff; | 696 | timer2 = 0x0007ffff; |
697 | } | 697 | } |
698 | /* Mark associated AP as PCF incapable for now */ | 698 | /* Mark associated AP as PCF incapable for now */ |
699 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF); | 699 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF); |
700 | break; | 700 | break; |
701 | case NL80211_IFTYPE_ADHOC: | 701 | case NL80211_IFTYPE_ADHOC: |
702 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); | 702 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); |
703 | default: | 703 | default: |
704 | /* On non-STA modes timer1 is used as next DMA | 704 | /* On non-STA modes timer1 is used as next DMA |
705 | * beacon alert (DBA) timer and timer2 as next | 705 | * beacon alert (DBA) timer and timer2 as next |
706 | * software beacon alert. Both in 1/8TUs. */ | 706 | * software beacon alert. Both in 1/8TUs. */ |
707 | timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; | 707 | timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; |
708 | timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; | 708 | timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; |
709 | break; | 709 | break; |
710 | } | 710 | } |
711 | 711 | ||
712 | /* Timer3 marks the end of our ATIM window | 712 | /* Timer3 marks the end of our ATIM window |
713 | * a zero length window is not allowed because | 713 | * a zero length window is not allowed because |
714 | * we 'll get no beacons */ | 714 | * we 'll get no beacons */ |
715 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); | 715 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); |
716 | 716 | ||
717 | /* | 717 | /* |
718 | * Set the beacon register and enable all timers. | 718 | * Set the beacon register and enable all timers. |
719 | */ | 719 | */ |
720 | /* When in AP mode zero timer0 to start TSF */ | 720 | /* When in AP mode zero timer0 to start TSF */ |
721 | if (ah->ah_op_mode == NL80211_IFTYPE_AP) | 721 | if (ah->ah_op_mode == NL80211_IFTYPE_AP) |
722 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | 722 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); |
723 | else | 723 | else |
724 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | 724 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); |
725 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); | 725 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); |
726 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); | 726 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); |
727 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); | 727 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); |
728 | 728 | ||
729 | /* Force a TSF reset if requested and enable beacons */ | 729 | /* Force a TSF reset if requested and enable beacons */ |
730 | if (interval & AR5K_BEACON_RESET_TSF) | 730 | if (interval & AR5K_BEACON_RESET_TSF) |
731 | ath5k_hw_reset_tsf(ah); | 731 | ath5k_hw_reset_tsf(ah); |
732 | 732 | ||
733 | ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | | 733 | ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | |
734 | AR5K_BEACON_ENABLE), | 734 | AR5K_BEACON_ENABLE), |
735 | AR5K_BEACON); | 735 | AR5K_BEACON); |
736 | 736 | ||
737 | /* Flush any pending BMISS interrupts on ISR by | 737 | /* Flush any pending BMISS interrupts on ISR by |
738 | * performing a clear-on-write operation on PISR | 738 | * performing a clear-on-write operation on PISR |
739 | * register for the BMISS bit (writing a bit on | 739 | * register for the BMISS bit (writing a bit on |
740 | * ISR togles a reset for that bit and leaves | 740 | * ISR togles a reset for that bit and leaves |
741 | * the rest bits intact) */ | 741 | * the rest bits intact) */ |
742 | if (ah->ah_version == AR5K_AR5210) | 742 | if (ah->ah_version == AR5K_AR5210) |
743 | ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR); | 743 | ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR); |
744 | else | 744 | else |
745 | ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); | 745 | ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); |
746 | 746 | ||
747 | /* TODO: Set enchanced sleep registers on AR5212 | 747 | /* TODO: Set enchanced sleep registers on AR5212 |
748 | * based on vif->bss_conf params, until then | 748 | * based on vif->bss_conf params, until then |
749 | * disable power save reporting.*/ | 749 | * disable power save reporting.*/ |
750 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); | 750 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); |
751 | 751 | ||
752 | } | 752 | } |
753 | 753 | ||
754 | #if 0 | 754 | #if 0 |
755 | /* | 755 | /* |
756 | * Set beacon timers | 756 | * Set beacon timers |
757 | */ | 757 | */ |
758 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, | 758 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, |
759 | const struct ath5k_beacon_state *state) | 759 | const struct ath5k_beacon_state *state) |
760 | { | 760 | { |
761 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; | 761 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; |
762 | 762 | ||
763 | /* | 763 | /* |
764 | * TODO: should be changed through *state | 764 | * TODO: should be changed through *state |
765 | * review struct ath5k_beacon_state struct | 765 | * review struct ath5k_beacon_state struct |
766 | * | 766 | * |
767 | * XXX: These are used for cfp period bellow, are they | 767 | * XXX: These are used for cfp period bellow, are they |
768 | * ok ? Is it O.K. for tsf here to be 0 or should we use | 768 | * ok ? Is it O.K. for tsf here to be 0 or should we use |
769 | * get_tsf ? | 769 | * get_tsf ? |
770 | */ | 770 | */ |
771 | u32 dtim_count = 0; /* XXX */ | 771 | u32 dtim_count = 0; /* XXX */ |
772 | u32 cfp_count = 0; /* XXX */ | 772 | u32 cfp_count = 0; /* XXX */ |
773 | u32 tsf = 0; /* XXX */ | 773 | u32 tsf = 0; /* XXX */ |
774 | 774 | ||
775 | ATH5K_TRACE(ah->ah_sc); | 775 | ATH5K_TRACE(ah->ah_sc); |
776 | /* Return on an invalid beacon state */ | 776 | /* Return on an invalid beacon state */ |
777 | if (state->bs_interval < 1) | 777 | if (state->bs_interval < 1) |
778 | return -EINVAL; | 778 | return -EINVAL; |
779 | 779 | ||
780 | interval = state->bs_interval; | 780 | interval = state->bs_interval; |
781 | dtim = state->bs_dtim_period; | 781 | dtim = state->bs_dtim_period; |
782 | 782 | ||
783 | /* | 783 | /* |
784 | * PCF support? | 784 | * PCF support? |
785 | */ | 785 | */ |
786 | if (state->bs_cfp_period > 0) { | 786 | if (state->bs_cfp_period > 0) { |
787 | /* | 787 | /* |
788 | * Enable PCF mode and set the CFP | 788 | * Enable PCF mode and set the CFP |
789 | * (Contention Free Period) and timer registers | 789 | * (Contention Free Period) and timer registers |
790 | */ | 790 | */ |
791 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * | 791 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * |
792 | state->bs_interval; | 792 | state->bs_interval; |
793 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * | 793 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * |
794 | state->bs_interval; | 794 | state->bs_interval; |
795 | 795 | ||
796 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | 796 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, |
797 | AR5K_STA_ID1_DEFAULT_ANTENNA | | 797 | AR5K_STA_ID1_DEFAULT_ANTENNA | |
798 | AR5K_STA_ID1_PCF); | 798 | AR5K_STA_ID1_PCF); |
799 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); | 799 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); |
800 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, | 800 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, |
801 | AR5K_CFP_DUR); | 801 | AR5K_CFP_DUR); |
802 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : | 802 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : |
803 | next_cfp)) << 3, AR5K_TIMER2); | 803 | next_cfp)) << 3, AR5K_TIMER2); |
804 | } else { | 804 | } else { |
805 | /* Disable PCF mode */ | 805 | /* Disable PCF mode */ |
806 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | 806 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, |
807 | AR5K_STA_ID1_DEFAULT_ANTENNA | | 807 | AR5K_STA_ID1_DEFAULT_ANTENNA | |
808 | AR5K_STA_ID1_PCF); | 808 | AR5K_STA_ID1_PCF); |
809 | } | 809 | } |
810 | 810 | ||
811 | /* | 811 | /* |
812 | * Enable the beacon timer register | 812 | * Enable the beacon timer register |
813 | */ | 813 | */ |
814 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); | 814 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); |
815 | 815 | ||
816 | /* | 816 | /* |
817 | * Start the beacon timers | 817 | * Start the beacon timers |
818 | */ | 818 | */ |
819 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & | 819 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & |
820 | ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | | 820 | ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | |
821 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, | 821 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, |
822 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, | 822 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, |
823 | AR5K_BEACON_PERIOD), AR5K_BEACON); | 823 | AR5K_BEACON_PERIOD), AR5K_BEACON); |
824 | 824 | ||
825 | /* | 825 | /* |
826 | * Write new beacon miss threshold, if it appears to be valid | 826 | * Write new beacon miss threshold, if it appears to be valid |
827 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max | 827 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max |
828 | * and return if its not in range. We can test this by reading value and | 828 | * and return if its not in range. We can test this by reading value and |
829 | * setting value to a largest value and seeing which values register. | 829 | * setting value to a largest value and seeing which values register. |
830 | */ | 830 | */ |
831 | 831 | ||
832 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, | 832 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, |
833 | state->bs_bmiss_threshold); | 833 | state->bs_bmiss_threshold); |
834 | 834 | ||
835 | /* | 835 | /* |
836 | * Set sleep control register | 836 | * Set sleep control register |
837 | * XXX: Didn't find this in 5210 code but since this register | 837 | * XXX: Didn't find this in 5210 code but since this register |
838 | * exists also in ar5k's 5210 headers i leave it as common code. | 838 | * exists also in ar5k's 5210 headers i leave it as common code. |
839 | */ | 839 | */ |
840 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, | 840 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, |
841 | (state->bs_sleep_duration - 3) << 3); | 841 | (state->bs_sleep_duration - 3) << 3); |
842 | 842 | ||
843 | /* | 843 | /* |
844 | * Set enhanced sleep registers on 5212 | 844 | * Set enhanced sleep registers on 5212 |
845 | */ | 845 | */ |
846 | if (ah->ah_version == AR5K_AR5212) { | 846 | if (ah->ah_version == AR5K_AR5212) { |
847 | if (state->bs_sleep_duration > state->bs_interval && | 847 | if (state->bs_sleep_duration > state->bs_interval && |
848 | roundup(state->bs_sleep_duration, interval) == | 848 | roundup(state->bs_sleep_duration, interval) == |
849 | state->bs_sleep_duration) | 849 | state->bs_sleep_duration) |
850 | interval = state->bs_sleep_duration; | 850 | interval = state->bs_sleep_duration; |
851 | 851 | ||
852 | if (state->bs_sleep_duration > dtim && (dtim == 0 || | 852 | if (state->bs_sleep_duration > dtim && (dtim == 0 || |
853 | roundup(state->bs_sleep_duration, dtim) == | 853 | roundup(state->bs_sleep_duration, dtim) == |
854 | state->bs_sleep_duration)) | 854 | state->bs_sleep_duration)) |
855 | dtim = state->bs_sleep_duration; | 855 | dtim = state->bs_sleep_duration; |
856 | 856 | ||
857 | if (interval > dtim) | 857 | if (interval > dtim) |
858 | return -EINVAL; | 858 | return -EINVAL; |
859 | 859 | ||
860 | next_beacon = interval == dtim ? state->bs_next_dtim : | 860 | next_beacon = interval == dtim ? state->bs_next_dtim : |
861 | state->bs_next_beacon; | 861 | state->bs_next_beacon; |
862 | 862 | ||
863 | ath5k_hw_reg_write(ah, | 863 | ath5k_hw_reg_write(ah, |
864 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, | 864 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, |
865 | AR5K_SLEEP0_NEXT_DTIM) | | 865 | AR5K_SLEEP0_NEXT_DTIM) | |
866 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | | 866 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | |
867 | AR5K_SLEEP0_ENH_SLEEP_EN | | 867 | AR5K_SLEEP0_ENH_SLEEP_EN | |
868 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); | 868 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); |
869 | 869 | ||
870 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, | 870 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, |
871 | AR5K_SLEEP1_NEXT_TIM) | | 871 | AR5K_SLEEP1_NEXT_TIM) | |
872 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); | 872 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); |
873 | 873 | ||
874 | ath5k_hw_reg_write(ah, | 874 | ath5k_hw_reg_write(ah, |
875 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | | 875 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | |
876 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); | 876 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); |
877 | } | 877 | } |
878 | 878 | ||
879 | return 0; | 879 | return 0; |
880 | } | 880 | } |
881 | 881 | ||
882 | /* | 882 | /* |
883 | * Reset beacon timers | 883 | * Reset beacon timers |
884 | */ | 884 | */ |
885 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) | 885 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) |
886 | { | 886 | { |
887 | ATH5K_TRACE(ah->ah_sc); | 887 | ATH5K_TRACE(ah->ah_sc); |
888 | /* | 888 | /* |
889 | * Disable beacon timer | 889 | * Disable beacon timer |
890 | */ | 890 | */ |
891 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | 891 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); |
892 | 892 | ||
893 | /* | 893 | /* |
894 | * Disable some beacon register values | 894 | * Disable some beacon register values |
895 | */ | 895 | */ |
896 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | 896 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, |
897 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); | 897 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); |
898 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); | 898 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); |
899 | } | 899 | } |
900 | 900 | ||
901 | /* | 901 | /* |
902 | * Wait for beacon queue to finish | 902 | * Wait for beacon queue to finish |
903 | */ | 903 | */ |
904 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | 904 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) |
905 | { | 905 | { |
906 | unsigned int i; | 906 | unsigned int i; |
907 | int ret; | 907 | int ret; |
908 | 908 | ||
909 | ATH5K_TRACE(ah->ah_sc); | 909 | ATH5K_TRACE(ah->ah_sc); |
910 | 910 | ||
911 | /* 5210 doesn't have QCU*/ | 911 | /* 5210 doesn't have QCU*/ |
912 | if (ah->ah_version == AR5K_AR5210) { | 912 | if (ah->ah_version == AR5K_AR5210) { |
913 | /* | 913 | /* |
914 | * Wait for beaconn queue to finish by checking | 914 | * Wait for beaconn queue to finish by checking |
915 | * Control Register and Beacon Status Register. | 915 | * Control Register and Beacon Status Register. |
916 | */ | 916 | */ |
917 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { | 917 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { |
918 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) | 918 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) |
919 | || | 919 | || |
920 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) | 920 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) |
921 | break; | 921 | break; |
922 | udelay(10); | 922 | udelay(10); |
923 | } | 923 | } |
924 | 924 | ||
925 | /* Timeout... */ | 925 | /* Timeout... */ |
926 | if (i <= 0) { | 926 | if (i <= 0) { |
927 | /* | 927 | /* |
928 | * Re-schedule the beacon queue | 928 | * Re-schedule the beacon queue |
929 | */ | 929 | */ |
930 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); | 930 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); |
931 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | 931 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, |
932 | AR5K_BCR); | 932 | AR5K_BCR); |
933 | 933 | ||
934 | return -EIO; | 934 | return -EIO; |
935 | } | 935 | } |
936 | ret = 0; | 936 | ret = 0; |
937 | } else { | 937 | } else { |
938 | /*5211/5212*/ | 938 | /*5211/5212*/ |
939 | ret = ath5k_hw_register_timeout(ah, | 939 | ret = ath5k_hw_register_timeout(ah, |
940 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), | 940 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), |
941 | AR5K_QCU_STS_FRMPENDCNT, 0, false); | 941 | AR5K_QCU_STS_FRMPENDCNT, 0, false); |
942 | 942 | ||
943 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) | 943 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) |
944 | return -EIO; | 944 | return -EIO; |
945 | } | 945 | } |
946 | 946 | ||
947 | return ret; | 947 | return ret; |
948 | } | 948 | } |
949 | #endif | 949 | #endif |
950 | 950 | ||
951 | 951 | ||
952 | /*********************\ | 952 | /*********************\ |
953 | * Key table functions * | 953 | * Key table functions * |
954 | \*********************/ | 954 | \*********************/ |
955 | 955 | ||
956 | /* | 956 | /* |
957 | * Reset a key entry on the table | 957 | * Reset a key entry on the table |
958 | */ | 958 | */ |
959 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | 959 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) |
960 | { | 960 | { |
961 | unsigned int i, type; | 961 | unsigned int i, type; |
962 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | 962 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; |
963 | 963 | ||
964 | ATH5K_TRACE(ah->ah_sc); | 964 | ATH5K_TRACE(ah->ah_sc); |
965 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 965 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
966 | 966 | ||
967 | type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); | 967 | type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); |
968 | 968 | ||
969 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | 969 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) |
970 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | 970 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); |
971 | 971 | ||
972 | /* Reset associated MIC entry if TKIP | 972 | /* Reset associated MIC entry if TKIP |
973 | * is enabled located at offset (entry + 64) */ | 973 | * is enabled located at offset (entry + 64) */ |
974 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { | 974 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { |
975 | AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); | 975 | AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); |
976 | for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) | 976 | for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) |
977 | ath5k_hw_reg_write(ah, 0, | 977 | ath5k_hw_reg_write(ah, 0, |
978 | AR5K_KEYTABLE_OFF(micentry, i)); | 978 | AR5K_KEYTABLE_OFF(micentry, i)); |
979 | } | 979 | } |
980 | 980 | ||
981 | /* | 981 | /* |
982 | * Set NULL encryption on AR5212+ | 982 | * Set NULL encryption on AR5212+ |
983 | * | 983 | * |
984 | * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) | 984 | * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) |
985 | * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 | 985 | * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 |
986 | * | 986 | * |
987 | * Note2: Windows driver (ndiswrapper) sets this to | 987 | * Note2: Windows driver (ndiswrapper) sets this to |
988 | * 0x00000714 instead of 0x00000007 | 988 | * 0x00000714 instead of 0x00000007 |
989 | */ | 989 | */ |
990 | if (ah->ah_version > AR5K_AR5211) { | 990 | if (ah->ah_version > AR5K_AR5211) { |
991 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | 991 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, |
992 | AR5K_KEYTABLE_TYPE(entry)); | 992 | AR5K_KEYTABLE_TYPE(entry)); |
993 | 993 | ||
994 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { | 994 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { |
995 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | 995 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, |
996 | AR5K_KEYTABLE_TYPE(micentry)); | 996 | AR5K_KEYTABLE_TYPE(micentry)); |
997 | } | 997 | } |
998 | } | 998 | } |
999 | 999 | ||
1000 | return 0; | 1000 | return 0; |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | /* | 1003 | /* |
1004 | * Check if a table entry is valid | 1004 | * Check if a table entry is valid |
1005 | */ | 1005 | */ |
1006 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | 1006 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) |
1007 | { | 1007 | { |
1008 | ATH5K_TRACE(ah->ah_sc); | 1008 | ATH5K_TRACE(ah->ah_sc); |
1009 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 1009 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
1010 | 1010 | ||
1011 | /* Check the validation flag at the end of the entry */ | 1011 | /* Check the validation flag at the end of the entry */ |
1012 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & | 1012 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & |
1013 | AR5K_KEYTABLE_VALID; | 1013 | AR5K_KEYTABLE_VALID; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static | 1016 | static |
1017 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | 1017 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) |
1018 | { | 1018 | { |
1019 | switch (key->alg) { | 1019 | switch (key->alg) { |
1020 | case ALG_TKIP: | 1020 | case ALG_TKIP: |
1021 | return AR5K_KEYTABLE_TYPE_TKIP; | 1021 | return AR5K_KEYTABLE_TYPE_TKIP; |
1022 | case ALG_CCMP: | 1022 | case ALG_CCMP: |
1023 | return AR5K_KEYTABLE_TYPE_CCM; | 1023 | return AR5K_KEYTABLE_TYPE_CCM; |
1024 | case ALG_WEP: | 1024 | case ALG_WEP: |
1025 | if (key->keylen == LEN_WEP40) | 1025 | if (key->keylen == LEN_WEP40) |
1026 | return AR5K_KEYTABLE_TYPE_40; | 1026 | return AR5K_KEYTABLE_TYPE_40; |
1027 | else if (key->keylen == LEN_WEP104) | 1027 | else if (key->keylen == LEN_WEP104) |
1028 | return AR5K_KEYTABLE_TYPE_104; | 1028 | return AR5K_KEYTABLE_TYPE_104; |
1029 | return -EINVAL; | ||
1030 | default: | ||
1031 | return -EINVAL; | ||
1029 | } | 1032 | } |
1030 | return -EINVAL; | 1033 | return -EINVAL; |
1031 | } | 1034 | } |
1032 | 1035 | ||
1033 | /* | 1036 | /* |
1034 | * Set a key entry on the table | 1037 | * Set a key entry on the table |
1035 | */ | 1038 | */ |
1036 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | 1039 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, |
1037 | const struct ieee80211_key_conf *key, const u8 *mac) | 1040 | const struct ieee80211_key_conf *key, const u8 *mac) |
1038 | { | 1041 | { |
1039 | unsigned int i; | 1042 | unsigned int i; |
1040 | int keylen; | 1043 | int keylen; |
1041 | __le32 key_v[5] = {}; | 1044 | __le32 key_v[5] = {}; |
1042 | __le32 key0 = 0, key1 = 0; | 1045 | __le32 key0 = 0, key1 = 0; |
1043 | __le32 *rxmic, *txmic; | 1046 | __le32 *rxmic, *txmic; |
1044 | u32 keytype; | 1047 | u32 keytype; |
1045 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | 1048 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; |
1046 | bool is_tkip; | 1049 | bool is_tkip; |
1047 | const u8 *key_ptr; | 1050 | const u8 *key_ptr; |
1048 | 1051 | ||
1049 | ATH5K_TRACE(ah->ah_sc); | 1052 | ATH5K_TRACE(ah->ah_sc); |
1050 | 1053 | ||
1051 | is_tkip = (key->alg == ALG_TKIP); | 1054 | is_tkip = (key->alg == ALG_TKIP); |
1052 | 1055 | ||
1053 | /* | 1056 | /* |
1054 | * key->keylen comes in from mac80211 in bytes. | 1057 | * key->keylen comes in from mac80211 in bytes. |
1055 | * TKIP is 128 bit + 128 bit mic | 1058 | * TKIP is 128 bit + 128 bit mic |
1056 | */ | 1059 | */ |
1057 | keylen = (is_tkip) ? (128 / 8) : key->keylen; | 1060 | keylen = (is_tkip) ? (128 / 8) : key->keylen; |
1058 | 1061 | ||
1059 | if (entry > AR5K_KEYTABLE_SIZE || | 1062 | if (entry > AR5K_KEYTABLE_SIZE || |
1060 | (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) | 1063 | (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) |
1061 | return -EOPNOTSUPP; | 1064 | return -EOPNOTSUPP; |
1062 | 1065 | ||
1063 | if (unlikely(keylen > 16)) | 1066 | if (unlikely(keylen > 16)) |
1064 | return -EOPNOTSUPP; | 1067 | return -EOPNOTSUPP; |
1065 | 1068 | ||
1066 | keytype = ath5k_keycache_type(key); | 1069 | keytype = ath5k_keycache_type(key); |
1067 | if (keytype < 0) | 1070 | if (keytype < 0) |
1068 | return keytype; | 1071 | return keytype; |
1069 | 1072 | ||
1070 | /* | 1073 | /* |
1071 | * each key block is 6 bytes wide, written as pairs of | 1074 | * each key block is 6 bytes wide, written as pairs of |
1072 | * alternating 32 and 16 bit le values. | 1075 | * alternating 32 and 16 bit le values. |
1073 | */ | 1076 | */ |
1074 | key_ptr = key->key; | 1077 | key_ptr = key->key; |
1075 | for (i = 0; keylen >= 6; keylen -= 6) { | 1078 | for (i = 0; keylen >= 6; keylen -= 6) { |
1076 | memcpy(&key_v[i], key_ptr, 6); | 1079 | memcpy(&key_v[i], key_ptr, 6); |
1077 | i += 2; | 1080 | i += 2; |
1078 | key_ptr += 6; | 1081 | key_ptr += 6; |
1079 | } | 1082 | } |
1080 | if (keylen) | 1083 | if (keylen) |
1081 | memcpy(&key_v[i], key_ptr, keylen); | 1084 | memcpy(&key_v[i], key_ptr, keylen); |
1082 | 1085 | ||
1083 | /* intentionally corrupt key until mic is installed */ | 1086 | /* intentionally corrupt key until mic is installed */ |
1084 | if (is_tkip) { | 1087 | if (is_tkip) { |
1085 | key0 = key_v[0] = ~key_v[0]; | 1088 | key0 = key_v[0] = ~key_v[0]; |
1086 | key1 = key_v[1] = ~key_v[1]; | 1089 | key1 = key_v[1] = ~key_v[1]; |
1087 | } | 1090 | } |
1088 | 1091 | ||
1089 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | 1092 | for (i = 0; i < ARRAY_SIZE(key_v); i++) |
1090 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | 1093 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), |
1091 | AR5K_KEYTABLE_OFF(entry, i)); | 1094 | AR5K_KEYTABLE_OFF(entry, i)); |
1092 | 1095 | ||
1093 | ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); | 1096 | ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); |
1094 | 1097 | ||
1095 | if (is_tkip) { | 1098 | if (is_tkip) { |
1096 | /* Install rx/tx MIC */ | 1099 | /* Install rx/tx MIC */ |
1097 | rxmic = (__le32 *) &key->key[16]; | 1100 | rxmic = (__le32 *) &key->key[16]; |
1098 | txmic = (__le32 *) &key->key[24]; | 1101 | txmic = (__le32 *) &key->key[24]; |
1099 | 1102 | ||
1100 | if (ah->ah_combined_mic) { | 1103 | if (ah->ah_combined_mic) { |
1101 | key_v[0] = rxmic[0]; | 1104 | key_v[0] = rxmic[0]; |
1102 | key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); | 1105 | key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); |
1103 | key_v[2] = rxmic[1]; | 1106 | key_v[2] = rxmic[1]; |
1104 | key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); | 1107 | key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); |
1105 | key_v[4] = txmic[1]; | 1108 | key_v[4] = txmic[1]; |
1106 | } else { | 1109 | } else { |
1107 | key_v[0] = rxmic[0]; | 1110 | key_v[0] = rxmic[0]; |
1108 | key_v[1] = 0; | 1111 | key_v[1] = 0; |
1109 | key_v[2] = rxmic[1]; | 1112 | key_v[2] = rxmic[1]; |
1110 | key_v[3] = 0; | 1113 | key_v[3] = 0; |
1111 | key_v[4] = 0; | 1114 | key_v[4] = 0; |
1112 | } | 1115 | } |
1113 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | 1116 | for (i = 0; i < ARRAY_SIZE(key_v); i++) |
1114 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | 1117 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), |
1115 | AR5K_KEYTABLE_OFF(micentry, i)); | 1118 | AR5K_KEYTABLE_OFF(micentry, i)); |
1116 | 1119 | ||
1117 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | 1120 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, |
1118 | AR5K_KEYTABLE_TYPE(micentry)); | 1121 | AR5K_KEYTABLE_TYPE(micentry)); |
1119 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry)); | 1122 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry)); |
1120 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry)); | 1123 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry)); |
1121 | 1124 | ||
1122 | /* restore first 2 words of key */ | 1125 | /* restore first 2 words of key */ |
1123 | ath5k_hw_reg_write(ah, le32_to_cpu(~key0), | 1126 | ath5k_hw_reg_write(ah, le32_to_cpu(~key0), |
1124 | AR5K_KEYTABLE_OFF(entry, 0)); | 1127 | AR5K_KEYTABLE_OFF(entry, 0)); |
1125 | ath5k_hw_reg_write(ah, le32_to_cpu(~key1), | 1128 | ath5k_hw_reg_write(ah, le32_to_cpu(~key1), |
1126 | AR5K_KEYTABLE_OFF(entry, 1)); | 1129 | AR5K_KEYTABLE_OFF(entry, 1)); |
1127 | } | 1130 | } |
1128 | 1131 | ||
1129 | return ath5k_hw_set_key_lladdr(ah, entry, mac); | 1132 | return ath5k_hw_set_key_lladdr(ah, entry, mac); |
1130 | } | 1133 | } |
1131 | 1134 | ||
1132 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | 1135 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) |
1133 | { | 1136 | { |
1134 | u32 low_id, high_id; | 1137 | u32 low_id, high_id; |
1135 | 1138 | ||
1136 | ATH5K_TRACE(ah->ah_sc); | 1139 | ATH5K_TRACE(ah->ah_sc); |
1137 | /* Invalid entry (key table overflow) */ | 1140 | /* Invalid entry (key table overflow) */ |
1138 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 1141 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
1139 | 1142 | ||
1140 | /* MAC may be NULL if it's a broadcast key. In this case no need to | 1143 | /* MAC may be NULL if it's a broadcast key. In this case no need to |
1141 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | 1144 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ |
1142 | if (!mac) { | 1145 | if (!mac) { |
1143 | low_id = 0xffffffff; | 1146 | low_id = 0xffffffff; |
1144 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | 1147 | high_id = 0xffff | AR5K_KEYTABLE_VALID; |
1145 | } else { | 1148 | } else { |
1146 | low_id = AR5K_LOW_ID(mac); | 1149 | low_id = AR5K_LOW_ID(mac); |
1147 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; | 1150 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; |
1148 | } | 1151 | } |
1149 | 1152 | ||
1150 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | 1153 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); |
1151 | ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); | 1154 | ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); |
1152 | 1155 | ||
1153 | return 0; | 1156 | return 0; |
1154 | } | 1157 | } |
1155 | 1158 | ||
1156 | 1159 |
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 | #define FCS_LEN 4 | 21 | #define FCS_LEN 4 |
22 | 22 | ||
23 | #define IEEE80211_FCTL_VERS 0x0003 | 23 | #define IEEE80211_FCTL_VERS 0x0003 |
24 | #define IEEE80211_FCTL_FTYPE 0x000c | 24 | #define IEEE80211_FCTL_FTYPE 0x000c |
25 | #define IEEE80211_FCTL_STYPE 0x00f0 | 25 | #define IEEE80211_FCTL_STYPE 0x00f0 |
26 | #define IEEE80211_FCTL_TODS 0x0100 | 26 | #define IEEE80211_FCTL_TODS 0x0100 |
27 | #define IEEE80211_FCTL_FROMDS 0x0200 | 27 | #define IEEE80211_FCTL_FROMDS 0x0200 |
28 | #define IEEE80211_FCTL_MOREFRAGS 0x0400 | 28 | #define IEEE80211_FCTL_MOREFRAGS 0x0400 |
29 | #define IEEE80211_FCTL_RETRY 0x0800 | 29 | #define IEEE80211_FCTL_RETRY 0x0800 |
30 | #define IEEE80211_FCTL_PM 0x1000 | 30 | #define IEEE80211_FCTL_PM 0x1000 |
31 | #define IEEE80211_FCTL_MOREDATA 0x2000 | 31 | #define IEEE80211_FCTL_MOREDATA 0x2000 |
32 | #define IEEE80211_FCTL_PROTECTED 0x4000 | 32 | #define IEEE80211_FCTL_PROTECTED 0x4000 |
33 | #define IEEE80211_FCTL_ORDER 0x8000 | 33 | #define IEEE80211_FCTL_ORDER 0x8000 |
34 | 34 | ||
35 | #define IEEE80211_SCTL_FRAG 0x000F | 35 | #define IEEE80211_SCTL_FRAG 0x000F |
36 | #define IEEE80211_SCTL_SEQ 0xFFF0 | 36 | #define IEEE80211_SCTL_SEQ 0xFFF0 |
37 | 37 | ||
38 | #define IEEE80211_FTYPE_MGMT 0x0000 | 38 | #define IEEE80211_FTYPE_MGMT 0x0000 |
39 | #define IEEE80211_FTYPE_CTL 0x0004 | 39 | #define IEEE80211_FTYPE_CTL 0x0004 |
40 | #define IEEE80211_FTYPE_DATA 0x0008 | 40 | #define IEEE80211_FTYPE_DATA 0x0008 |
41 | 41 | ||
42 | /* management */ | 42 | /* management */ |
43 | #define IEEE80211_STYPE_ASSOC_REQ 0x0000 | 43 | #define IEEE80211_STYPE_ASSOC_REQ 0x0000 |
44 | #define IEEE80211_STYPE_ASSOC_RESP 0x0010 | 44 | #define IEEE80211_STYPE_ASSOC_RESP 0x0010 |
45 | #define IEEE80211_STYPE_REASSOC_REQ 0x0020 | 45 | #define IEEE80211_STYPE_REASSOC_REQ 0x0020 |
46 | #define IEEE80211_STYPE_REASSOC_RESP 0x0030 | 46 | #define IEEE80211_STYPE_REASSOC_RESP 0x0030 |
47 | #define IEEE80211_STYPE_PROBE_REQ 0x0040 | 47 | #define IEEE80211_STYPE_PROBE_REQ 0x0040 |
48 | #define IEEE80211_STYPE_PROBE_RESP 0x0050 | 48 | #define IEEE80211_STYPE_PROBE_RESP 0x0050 |
49 | #define IEEE80211_STYPE_BEACON 0x0080 | 49 | #define IEEE80211_STYPE_BEACON 0x0080 |
50 | #define IEEE80211_STYPE_ATIM 0x0090 | 50 | #define IEEE80211_STYPE_ATIM 0x0090 |
51 | #define IEEE80211_STYPE_DISASSOC 0x00A0 | 51 | #define IEEE80211_STYPE_DISASSOC 0x00A0 |
52 | #define IEEE80211_STYPE_AUTH 0x00B0 | 52 | #define IEEE80211_STYPE_AUTH 0x00B0 |
53 | #define IEEE80211_STYPE_DEAUTH 0x00C0 | 53 | #define IEEE80211_STYPE_DEAUTH 0x00C0 |
54 | #define IEEE80211_STYPE_ACTION 0x00D0 | 54 | #define IEEE80211_STYPE_ACTION 0x00D0 |
55 | 55 | ||
56 | /* control */ | 56 | /* control */ |
57 | #define IEEE80211_STYPE_BACK_REQ 0x0080 | 57 | #define IEEE80211_STYPE_BACK_REQ 0x0080 |
58 | #define IEEE80211_STYPE_BACK 0x0090 | 58 | #define IEEE80211_STYPE_BACK 0x0090 |
59 | #define IEEE80211_STYPE_PSPOLL 0x00A0 | 59 | #define IEEE80211_STYPE_PSPOLL 0x00A0 |
60 | #define IEEE80211_STYPE_RTS 0x00B0 | 60 | #define IEEE80211_STYPE_RTS 0x00B0 |
61 | #define IEEE80211_STYPE_CTS 0x00C0 | 61 | #define IEEE80211_STYPE_CTS 0x00C0 |
62 | #define IEEE80211_STYPE_ACK 0x00D0 | 62 | #define IEEE80211_STYPE_ACK 0x00D0 |
63 | #define IEEE80211_STYPE_CFEND 0x00E0 | 63 | #define IEEE80211_STYPE_CFEND 0x00E0 |
64 | #define IEEE80211_STYPE_CFENDACK 0x00F0 | 64 | #define IEEE80211_STYPE_CFENDACK 0x00F0 |
65 | 65 | ||
66 | /* data */ | 66 | /* data */ |
67 | #define IEEE80211_STYPE_DATA 0x0000 | 67 | #define IEEE80211_STYPE_DATA 0x0000 |
68 | #define IEEE80211_STYPE_DATA_CFACK 0x0010 | 68 | #define IEEE80211_STYPE_DATA_CFACK 0x0010 |
69 | #define IEEE80211_STYPE_DATA_CFPOLL 0x0020 | 69 | #define IEEE80211_STYPE_DATA_CFPOLL 0x0020 |
70 | #define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 | 70 | #define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 |
71 | #define IEEE80211_STYPE_NULLFUNC 0x0040 | 71 | #define IEEE80211_STYPE_NULLFUNC 0x0040 |
72 | #define IEEE80211_STYPE_CFACK 0x0050 | 72 | #define IEEE80211_STYPE_CFACK 0x0050 |
73 | #define IEEE80211_STYPE_CFPOLL 0x0060 | 73 | #define IEEE80211_STYPE_CFPOLL 0x0060 |
74 | #define IEEE80211_STYPE_CFACKPOLL 0x0070 | 74 | #define IEEE80211_STYPE_CFACKPOLL 0x0070 |
75 | #define IEEE80211_STYPE_QOS_DATA 0x0080 | 75 | #define IEEE80211_STYPE_QOS_DATA 0x0080 |
76 | #define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 | 76 | #define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 |
77 | #define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 | 77 | #define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 |
78 | #define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 | 78 | #define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 |
79 | #define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 | 79 | #define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 |
80 | #define IEEE80211_STYPE_QOS_CFACK 0x00D0 | 80 | #define IEEE80211_STYPE_QOS_CFACK 0x00D0 |
81 | #define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 | 81 | #define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 |
82 | #define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 | 82 | #define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 |
83 | 83 | ||
84 | 84 | ||
85 | /* miscellaneous IEEE 802.11 constants */ | 85 | /* miscellaneous IEEE 802.11 constants */ |
86 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 | 86 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 |
87 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 | 87 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 |
88 | #define IEEE80211_MAX_AID 2007 | 88 | #define IEEE80211_MAX_AID 2007 |
89 | #define IEEE80211_MAX_TIM_LEN 251 | 89 | #define IEEE80211_MAX_TIM_LEN 251 |
90 | /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section | 90 | /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section |
91 | 6.2.1.1.2. | 91 | 6.2.1.1.2. |
92 | 92 | ||
93 | 802.11e clarifies the figure in section 7.1.2. The frame body is | 93 | 802.11e clarifies the figure in section 7.1.2. The frame body is |
94 | up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ | 94 | up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ |
95 | #define IEEE80211_MAX_DATA_LEN 2304 | 95 | #define IEEE80211_MAX_DATA_LEN 2304 |
96 | /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ | 96 | /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ |
97 | #define IEEE80211_MAX_FRAME_LEN 2352 | 97 | #define IEEE80211_MAX_FRAME_LEN 2352 |
98 | 98 | ||
99 | #define IEEE80211_MAX_SSID_LEN 32 | 99 | #define IEEE80211_MAX_SSID_LEN 32 |
100 | 100 | ||
101 | #define IEEE80211_MAX_MESH_ID_LEN 32 | 101 | #define IEEE80211_MAX_MESH_ID_LEN 32 |
102 | #define IEEE80211_MESH_CONFIG_LEN 19 | 102 | #define IEEE80211_MESH_CONFIG_LEN 19 |
103 | 103 | ||
104 | #define IEEE80211_QOS_CTL_LEN 2 | 104 | #define IEEE80211_QOS_CTL_LEN 2 |
105 | #define IEEE80211_QOS_CTL_TID_MASK 0x000F | 105 | #define IEEE80211_QOS_CTL_TID_MASK 0x000F |
106 | #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 | 106 | #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 |
107 | 107 | ||
108 | struct ieee80211_hdr { | 108 | struct ieee80211_hdr { |
109 | __le16 frame_control; | 109 | __le16 frame_control; |
110 | __le16 duration_id; | 110 | __le16 duration_id; |
111 | u8 addr1[6]; | 111 | u8 addr1[6]; |
112 | u8 addr2[6]; | 112 | u8 addr2[6]; |
113 | u8 addr3[6]; | 113 | u8 addr3[6]; |
114 | __le16 seq_ctrl; | 114 | __le16 seq_ctrl; |
115 | u8 addr4[6]; | 115 | u8 addr4[6]; |
116 | } __attribute__ ((packed)); | 116 | } __attribute__ ((packed)); |
117 | 117 | ||
118 | /** | 118 | /** |
119 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set | 119 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set |
120 | * @fc: frame control bytes in little-endian byteorder | 120 | * @fc: frame control bytes in little-endian byteorder |
121 | */ | 121 | */ |
122 | static inline int ieee80211_has_tods(__le16 fc) | 122 | static inline int ieee80211_has_tods(__le16 fc) |
123 | { | 123 | { |
124 | return (fc & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0; | 124 | return (fc & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0; |
125 | } | 125 | } |
126 | 126 | ||
127 | /** | 127 | /** |
128 | * ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set | 128 | * ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set |
129 | * @fc: frame control bytes in little-endian byteorder | 129 | * @fc: frame control bytes in little-endian byteorder |
130 | */ | 130 | */ |
131 | static inline int ieee80211_has_fromds(__le16 fc) | 131 | static inline int ieee80211_has_fromds(__le16 fc) |
132 | { | 132 | { |
133 | return (fc & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0; | 133 | return (fc & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0; |
134 | } | 134 | } |
135 | 135 | ||
136 | /** | 136 | /** |
137 | * ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set | 137 | * ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set |
138 | * @fc: frame control bytes in little-endian byteorder | 138 | * @fc: frame control bytes in little-endian byteorder |
139 | */ | 139 | */ |
140 | static inline int ieee80211_has_a4(__le16 fc) | 140 | static inline int ieee80211_has_a4(__le16 fc) |
141 | { | 141 | { |
142 | __le16 tmp = cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); | 142 | __le16 tmp = cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); |
143 | return (fc & tmp) == tmp; | 143 | return (fc & tmp) == tmp; |
144 | } | 144 | } |
145 | 145 | ||
146 | /** | 146 | /** |
147 | * ieee80211_has_morefrags - check if IEEE80211_FCTL_MOREFRAGS is set | 147 | * ieee80211_has_morefrags - check if IEEE80211_FCTL_MOREFRAGS is set |
148 | * @fc: frame control bytes in little-endian byteorder | 148 | * @fc: frame control bytes in little-endian byteorder |
149 | */ | 149 | */ |
150 | static inline int ieee80211_has_morefrags(__le16 fc) | 150 | static inline int ieee80211_has_morefrags(__le16 fc) |
151 | { | 151 | { |
152 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0; | 152 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0; |
153 | } | 153 | } |
154 | 154 | ||
155 | /** | 155 | /** |
156 | * ieee80211_has_retry - check if IEEE80211_FCTL_RETRY is set | 156 | * ieee80211_has_retry - check if IEEE80211_FCTL_RETRY is set |
157 | * @fc: frame control bytes in little-endian byteorder | 157 | * @fc: frame control bytes in little-endian byteorder |
158 | */ | 158 | */ |
159 | static inline int ieee80211_has_retry(__le16 fc) | 159 | static inline int ieee80211_has_retry(__le16 fc) |
160 | { | 160 | { |
161 | return (fc & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0; | 161 | return (fc & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * ieee80211_has_pm - check if IEEE80211_FCTL_PM is set | 165 | * ieee80211_has_pm - check if IEEE80211_FCTL_PM is set |
166 | * @fc: frame control bytes in little-endian byteorder | 166 | * @fc: frame control bytes in little-endian byteorder |
167 | */ | 167 | */ |
168 | static inline int ieee80211_has_pm(__le16 fc) | 168 | static inline int ieee80211_has_pm(__le16 fc) |
169 | { | 169 | { |
170 | return (fc & cpu_to_le16(IEEE80211_FCTL_PM)) != 0; | 170 | return (fc & cpu_to_le16(IEEE80211_FCTL_PM)) != 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | /** | 173 | /** |
174 | * ieee80211_has_moredata - check if IEEE80211_FCTL_MOREDATA is set | 174 | * ieee80211_has_moredata - check if IEEE80211_FCTL_MOREDATA is set |
175 | * @fc: frame control bytes in little-endian byteorder | 175 | * @fc: frame control bytes in little-endian byteorder |
176 | */ | 176 | */ |
177 | static inline int ieee80211_has_moredata(__le16 fc) | 177 | static inline int ieee80211_has_moredata(__le16 fc) |
178 | { | 178 | { |
179 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0; | 179 | return (fc & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | /** | 182 | /** |
183 | * ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set | 183 | * ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set |
184 | * @fc: frame control bytes in little-endian byteorder | 184 | * @fc: frame control bytes in little-endian byteorder |
185 | */ | 185 | */ |
186 | static inline int ieee80211_has_protected(__le16 fc) | 186 | static inline int ieee80211_has_protected(__le16 fc) |
187 | { | 187 | { |
188 | return (fc & cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0; | 188 | return (fc & cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | /** | 191 | /** |
192 | * ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set | 192 | * ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set |
193 | * @fc: frame control bytes in little-endian byteorder | 193 | * @fc: frame control bytes in little-endian byteorder |
194 | */ | 194 | */ |
195 | static inline int ieee80211_has_order(__le16 fc) | 195 | static inline int ieee80211_has_order(__le16 fc) |
196 | { | 196 | { |
197 | return (fc & cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0; | 197 | return (fc & cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | /** | 200 | /** |
201 | * ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT | 201 | * ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT |
202 | * @fc: frame control bytes in little-endian byteorder | 202 | * @fc: frame control bytes in little-endian byteorder |
203 | */ | 203 | */ |
204 | static inline int ieee80211_is_mgmt(__le16 fc) | 204 | static inline int ieee80211_is_mgmt(__le16 fc) |
205 | { | 205 | { |
206 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == | 206 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == |
207 | cpu_to_le16(IEEE80211_FTYPE_MGMT); | 207 | cpu_to_le16(IEEE80211_FTYPE_MGMT); |
208 | } | 208 | } |
209 | 209 | ||
210 | /** | 210 | /** |
211 | * ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL | 211 | * ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL |
212 | * @fc: frame control bytes in little-endian byteorder | 212 | * @fc: frame control bytes in little-endian byteorder |
213 | */ | 213 | */ |
214 | static inline int ieee80211_is_ctl(__le16 fc) | 214 | static inline int ieee80211_is_ctl(__le16 fc) |
215 | { | 215 | { |
216 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == | 216 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == |
217 | cpu_to_le16(IEEE80211_FTYPE_CTL); | 217 | cpu_to_le16(IEEE80211_FTYPE_CTL); |
218 | } | 218 | } |
219 | 219 | ||
220 | /** | 220 | /** |
221 | * ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA | 221 | * ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA |
222 | * @fc: frame control bytes in little-endian byteorder | 222 | * @fc: frame control bytes in little-endian byteorder |
223 | */ | 223 | */ |
224 | static inline int ieee80211_is_data(__le16 fc) | 224 | static inline int ieee80211_is_data(__le16 fc) |
225 | { | 225 | { |
226 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == | 226 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == |
227 | cpu_to_le16(IEEE80211_FTYPE_DATA); | 227 | cpu_to_le16(IEEE80211_FTYPE_DATA); |
228 | } | 228 | } |
229 | 229 | ||
230 | /** | 230 | /** |
231 | * ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set | 231 | * ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set |
232 | * @fc: frame control bytes in little-endian byteorder | 232 | * @fc: frame control bytes in little-endian byteorder |
233 | */ | 233 | */ |
234 | static inline int ieee80211_is_data_qos(__le16 fc) | 234 | static inline int ieee80211_is_data_qos(__le16 fc) |
235 | { | 235 | { |
236 | /* | 236 | /* |
237 | * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need | 237 | * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need |
238 | * to check the one bit | 238 | * to check the one bit |
239 | */ | 239 | */ |
240 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == | 240 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == |
241 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); | 241 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); |
242 | } | 242 | } |
243 | 243 | ||
244 | /** | 244 | /** |
245 | * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data | 245 | * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data |
246 | * @fc: frame control bytes in little-endian byteorder | 246 | * @fc: frame control bytes in little-endian byteorder |
247 | */ | 247 | */ |
248 | static inline int ieee80211_is_data_present(__le16 fc) | 248 | static inline int ieee80211_is_data_present(__le16 fc) |
249 | { | 249 | { |
250 | /* | 250 | /* |
251 | * mask with 0x40 and test that that bit is clear to only return true | 251 | * mask with 0x40 and test that that bit is clear to only return true |
252 | * for the data-containing substypes. | 252 | * for the data-containing substypes. |
253 | */ | 253 | */ |
254 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | 0x40)) == | 254 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | 0x40)) == |
255 | cpu_to_le16(IEEE80211_FTYPE_DATA); | 255 | cpu_to_le16(IEEE80211_FTYPE_DATA); |
256 | } | 256 | } |
257 | 257 | ||
258 | /** | 258 | /** |
259 | * ieee80211_is_assoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ | 259 | * ieee80211_is_assoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ |
260 | * @fc: frame control bytes in little-endian byteorder | 260 | * @fc: frame control bytes in little-endian byteorder |
261 | */ | 261 | */ |
262 | static inline int ieee80211_is_assoc_req(__le16 fc) | 262 | static inline int ieee80211_is_assoc_req(__le16 fc) |
263 | { | 263 | { |
264 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 264 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
265 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); | 265 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); |
266 | } | 266 | } |
267 | 267 | ||
268 | /** | 268 | /** |
269 | * ieee80211_is_assoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP | 269 | * ieee80211_is_assoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP |
270 | * @fc: frame control bytes in little-endian byteorder | 270 | * @fc: frame control bytes in little-endian byteorder |
271 | */ | 271 | */ |
272 | static inline int ieee80211_is_assoc_resp(__le16 fc) | 272 | static inline int ieee80211_is_assoc_resp(__le16 fc) |
273 | { | 273 | { |
274 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 274 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
275 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); | 275 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); |
276 | } | 276 | } |
277 | 277 | ||
278 | /** | 278 | /** |
279 | * ieee80211_is_reassoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ | 279 | * ieee80211_is_reassoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ |
280 | * @fc: frame control bytes in little-endian byteorder | 280 | * @fc: frame control bytes in little-endian byteorder |
281 | */ | 281 | */ |
282 | static inline int ieee80211_is_reassoc_req(__le16 fc) | 282 | static inline int ieee80211_is_reassoc_req(__le16 fc) |
283 | { | 283 | { |
284 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 284 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
285 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); | 285 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); |
286 | } | 286 | } |
287 | 287 | ||
288 | /** | 288 | /** |
289 | * ieee80211_is_reassoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP | 289 | * ieee80211_is_reassoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP |
290 | * @fc: frame control bytes in little-endian byteorder | 290 | * @fc: frame control bytes in little-endian byteorder |
291 | */ | 291 | */ |
292 | static inline int ieee80211_is_reassoc_resp(__le16 fc) | 292 | static inline int ieee80211_is_reassoc_resp(__le16 fc) |
293 | { | 293 | { |
294 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 294 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
295 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); | 295 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); |
296 | } | 296 | } |
297 | 297 | ||
298 | /** | 298 | /** |
299 | * ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ | 299 | * ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ |
300 | * @fc: frame control bytes in little-endian byteorder | 300 | * @fc: frame control bytes in little-endian byteorder |
301 | */ | 301 | */ |
302 | static inline int ieee80211_is_probe_req(__le16 fc) | 302 | static inline int ieee80211_is_probe_req(__le16 fc) |
303 | { | 303 | { |
304 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 304 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
305 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); | 305 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); |
306 | } | 306 | } |
307 | 307 | ||
308 | /** | 308 | /** |
309 | * ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP | 309 | * ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP |
310 | * @fc: frame control bytes in little-endian byteorder | 310 | * @fc: frame control bytes in little-endian byteorder |
311 | */ | 311 | */ |
312 | static inline int ieee80211_is_probe_resp(__le16 fc) | 312 | static inline int ieee80211_is_probe_resp(__le16 fc) |
313 | { | 313 | { |
314 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 314 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
315 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); | 315 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); |
316 | } | 316 | } |
317 | 317 | ||
318 | /** | 318 | /** |
319 | * ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON | 319 | * ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON |
320 | * @fc: frame control bytes in little-endian byteorder | 320 | * @fc: frame control bytes in little-endian byteorder |
321 | */ | 321 | */ |
322 | static inline int ieee80211_is_beacon(__le16 fc) | 322 | static inline int ieee80211_is_beacon(__le16 fc) |
323 | { | 323 | { |
324 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 324 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
325 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 325 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
326 | } | 326 | } |
327 | 327 | ||
328 | /** | 328 | /** |
329 | * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM | 329 | * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM |
330 | * @fc: frame control bytes in little-endian byteorder | 330 | * @fc: frame control bytes in little-endian byteorder |
331 | */ | 331 | */ |
332 | static inline int ieee80211_is_atim(__le16 fc) | 332 | static inline int ieee80211_is_atim(__le16 fc) |
333 | { | 333 | { |
334 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 334 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
335 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); | 335 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); |
336 | } | 336 | } |
337 | 337 | ||
338 | /** | 338 | /** |
339 | * ieee80211_is_disassoc - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC | 339 | * ieee80211_is_disassoc - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC |
340 | * @fc: frame control bytes in little-endian byteorder | 340 | * @fc: frame control bytes in little-endian byteorder |
341 | */ | 341 | */ |
342 | static inline int ieee80211_is_disassoc(__le16 fc) | 342 | static inline int ieee80211_is_disassoc(__le16 fc) |
343 | { | 343 | { |
344 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 344 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
345 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); | 345 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); |
346 | } | 346 | } |
347 | 347 | ||
348 | /** | 348 | /** |
349 | * ieee80211_is_auth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH | 349 | * ieee80211_is_auth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH |
350 | * @fc: frame control bytes in little-endian byteorder | 350 | * @fc: frame control bytes in little-endian byteorder |
351 | */ | 351 | */ |
352 | static inline int ieee80211_is_auth(__le16 fc) | 352 | static inline int ieee80211_is_auth(__le16 fc) |
353 | { | 353 | { |
354 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 354 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
355 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); | 355 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); |
356 | } | 356 | } |
357 | 357 | ||
358 | /** | 358 | /** |
359 | * ieee80211_is_deauth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH | 359 | * ieee80211_is_deauth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH |
360 | * @fc: frame control bytes in little-endian byteorder | 360 | * @fc: frame control bytes in little-endian byteorder |
361 | */ | 361 | */ |
362 | static inline int ieee80211_is_deauth(__le16 fc) | 362 | static inline int ieee80211_is_deauth(__le16 fc) |
363 | { | 363 | { |
364 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 364 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
365 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); | 365 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); |
366 | } | 366 | } |
367 | 367 | ||
368 | /** | 368 | /** |
369 | * ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION | 369 | * ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION |
370 | * @fc: frame control bytes in little-endian byteorder | 370 | * @fc: frame control bytes in little-endian byteorder |
371 | */ | 371 | */ |
372 | static inline int ieee80211_is_action(__le16 fc) | 372 | static inline int ieee80211_is_action(__le16 fc) |
373 | { | 373 | { |
374 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 374 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
375 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); | 375 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); |
376 | } | 376 | } |
377 | 377 | ||
378 | /** | 378 | /** |
379 | * ieee80211_is_back_req - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ | 379 | * ieee80211_is_back_req - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ |
380 | * @fc: frame control bytes in little-endian byteorder | 380 | * @fc: frame control bytes in little-endian byteorder |
381 | */ | 381 | */ |
382 | static inline int ieee80211_is_back_req(__le16 fc) | 382 | static inline int ieee80211_is_back_req(__le16 fc) |
383 | { | 383 | { |
384 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 384 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
385 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); | 385 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); |
386 | } | 386 | } |
387 | 387 | ||
388 | /** | 388 | /** |
389 | * ieee80211_is_back - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK | 389 | * ieee80211_is_back - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK |
390 | * @fc: frame control bytes in little-endian byteorder | 390 | * @fc: frame control bytes in little-endian byteorder |
391 | */ | 391 | */ |
392 | static inline int ieee80211_is_back(__le16 fc) | 392 | static inline int ieee80211_is_back(__le16 fc) |
393 | { | 393 | { |
394 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 394 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
395 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); | 395 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); |
396 | } | 396 | } |
397 | 397 | ||
398 | /** | 398 | /** |
399 | * ieee80211_is_pspoll - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL | 399 | * ieee80211_is_pspoll - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL |
400 | * @fc: frame control bytes in little-endian byteorder | 400 | * @fc: frame control bytes in little-endian byteorder |
401 | */ | 401 | */ |
402 | static inline int ieee80211_is_pspoll(__le16 fc) | 402 | static inline int ieee80211_is_pspoll(__le16 fc) |
403 | { | 403 | { |
404 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 404 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
405 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 405 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); |
406 | } | 406 | } |
407 | 407 | ||
408 | /** | 408 | /** |
409 | * ieee80211_is_rts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS | 409 | * ieee80211_is_rts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS |
410 | * @fc: frame control bytes in little-endian byteorder | 410 | * @fc: frame control bytes in little-endian byteorder |
411 | */ | 411 | */ |
412 | static inline int ieee80211_is_rts(__le16 fc) | 412 | static inline int ieee80211_is_rts(__le16 fc) |
413 | { | 413 | { |
414 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 414 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
415 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); | 415 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); |
416 | } | 416 | } |
417 | 417 | ||
418 | /** | 418 | /** |
419 | * ieee80211_is_cts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS | 419 | * ieee80211_is_cts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS |
420 | * @fc: frame control bytes in little-endian byteorder | 420 | * @fc: frame control bytes in little-endian byteorder |
421 | */ | 421 | */ |
422 | static inline int ieee80211_is_cts(__le16 fc) | 422 | static inline int ieee80211_is_cts(__le16 fc) |
423 | { | 423 | { |
424 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 424 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
425 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); | 425 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); |
426 | } | 426 | } |
427 | 427 | ||
428 | /** | 428 | /** |
429 | * ieee80211_is_ack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK | 429 | * ieee80211_is_ack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK |
430 | * @fc: frame control bytes in little-endian byteorder | 430 | * @fc: frame control bytes in little-endian byteorder |
431 | */ | 431 | */ |
432 | static inline int ieee80211_is_ack(__le16 fc) | 432 | static inline int ieee80211_is_ack(__le16 fc) |
433 | { | 433 | { |
434 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 434 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
435 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); | 435 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); |
436 | } | 436 | } |
437 | 437 | ||
438 | /** | 438 | /** |
439 | * ieee80211_is_cfend - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND | 439 | * ieee80211_is_cfend - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND |
440 | * @fc: frame control bytes in little-endian byteorder | 440 | * @fc: frame control bytes in little-endian byteorder |
441 | */ | 441 | */ |
442 | static inline int ieee80211_is_cfend(__le16 fc) | 442 | static inline int ieee80211_is_cfend(__le16 fc) |
443 | { | 443 | { |
444 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 444 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
445 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); | 445 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); |
446 | } | 446 | } |
447 | 447 | ||
448 | /** | 448 | /** |
449 | * ieee80211_is_cfendack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK | 449 | * ieee80211_is_cfendack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK |
450 | * @fc: frame control bytes in little-endian byteorder | 450 | * @fc: frame control bytes in little-endian byteorder |
451 | */ | 451 | */ |
452 | static inline int ieee80211_is_cfendack(__le16 fc) | 452 | static inline int ieee80211_is_cfendack(__le16 fc) |
453 | { | 453 | { |
454 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 454 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
455 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); | 455 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); |
456 | } | 456 | } |
457 | 457 | ||
458 | /** | 458 | /** |
459 | * ieee80211_is_nullfunc - check if FTYPE=IEEE80211_FTYPE_DATA and STYPE=IEEE80211_STYPE_NULLFUNC | 459 | * ieee80211_is_nullfunc - check if FTYPE=IEEE80211_FTYPE_DATA and STYPE=IEEE80211_STYPE_NULLFUNC |
460 | * @fc: frame control bytes in little-endian byteorder | 460 | * @fc: frame control bytes in little-endian byteorder |
461 | */ | 461 | */ |
462 | static inline int ieee80211_is_nullfunc(__le16 fc) | 462 | static inline int ieee80211_is_nullfunc(__le16 fc) |
463 | { | 463 | { |
464 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == | 464 | return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == |
465 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); | 465 | cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); |
466 | } | 466 | } |
467 | 467 | ||
468 | struct ieee80211s_hdr { | 468 | struct ieee80211s_hdr { |
469 | u8 flags; | 469 | u8 flags; |
470 | u8 ttl; | 470 | u8 ttl; |
471 | __le32 seqnum; | 471 | __le32 seqnum; |
472 | u8 eaddr1[6]; | 472 | u8 eaddr1[6]; |
473 | u8 eaddr2[6]; | 473 | u8 eaddr2[6]; |
474 | u8 eaddr3[6]; | 474 | u8 eaddr3[6]; |
475 | } __attribute__ ((packed)); | 475 | } __attribute__ ((packed)); |
476 | 476 | ||
477 | /* Mesh flags */ | 477 | /* Mesh flags */ |
478 | #define MESH_FLAGS_AE_A4 0x1 | 478 | #define MESH_FLAGS_AE_A4 0x1 |
479 | #define MESH_FLAGS_AE_A5_A6 0x2 | 479 | #define MESH_FLAGS_AE_A5_A6 0x2 |
480 | #define MESH_FLAGS_PS_DEEP 0x4 | 480 | #define MESH_FLAGS_PS_DEEP 0x4 |
481 | 481 | ||
482 | /** | 482 | /** |
483 | * struct ieee80211_quiet_ie | 483 | * struct ieee80211_quiet_ie |
484 | * | 484 | * |
485 | * This structure refers to "Quiet information element" | 485 | * This structure refers to "Quiet information element" |
486 | */ | 486 | */ |
487 | struct ieee80211_quiet_ie { | 487 | struct ieee80211_quiet_ie { |
488 | u8 count; | 488 | u8 count; |
489 | u8 period; | 489 | u8 period; |
490 | __le16 duration; | 490 | __le16 duration; |
491 | __le16 offset; | 491 | __le16 offset; |
492 | } __attribute__ ((packed)); | 492 | } __attribute__ ((packed)); |
493 | 493 | ||
494 | /** | 494 | /** |
495 | * struct ieee80211_msrment_ie | 495 | * struct ieee80211_msrment_ie |
496 | * | 496 | * |
497 | * This structure refers to "Measurement Request/Report information element" | 497 | * This structure refers to "Measurement Request/Report information element" |
498 | */ | 498 | */ |
499 | struct ieee80211_msrment_ie { | 499 | struct ieee80211_msrment_ie { |
500 | u8 token; | 500 | u8 token; |
501 | u8 mode; | 501 | u8 mode; |
502 | u8 type; | 502 | u8 type; |
503 | u8 request[0]; | 503 | u8 request[0]; |
504 | } __attribute__ ((packed)); | 504 | } __attribute__ ((packed)); |
505 | 505 | ||
506 | /** | 506 | /** |
507 | * struct ieee80211_channel_sw_ie | 507 | * struct ieee80211_channel_sw_ie |
508 | * | 508 | * |
509 | * This structure refers to "Channel Switch Announcement information element" | 509 | * This structure refers to "Channel Switch Announcement information element" |
510 | */ | 510 | */ |
511 | struct ieee80211_channel_sw_ie { | 511 | struct ieee80211_channel_sw_ie { |
512 | u8 mode; | 512 | u8 mode; |
513 | u8 new_ch_num; | 513 | u8 new_ch_num; |
514 | u8 count; | 514 | u8 count; |
515 | } __attribute__ ((packed)); | 515 | } __attribute__ ((packed)); |
516 | 516 | ||
517 | /** | 517 | /** |
518 | * struct ieee80211_tim | 518 | * struct ieee80211_tim |
519 | * | 519 | * |
520 | * This structure refers to "Traffic Indication Map information element" | 520 | * This structure refers to "Traffic Indication Map information element" |
521 | */ | 521 | */ |
522 | struct ieee80211_tim_ie { | 522 | struct ieee80211_tim_ie { |
523 | u8 dtim_count; | 523 | u8 dtim_count; |
524 | u8 dtim_period; | 524 | u8 dtim_period; |
525 | u8 bitmap_ctrl; | 525 | u8 bitmap_ctrl; |
526 | /* variable size: 1 - 251 bytes */ | 526 | /* variable size: 1 - 251 bytes */ |
527 | u8 virtual_map[0]; | 527 | u8 virtual_map[0]; |
528 | } __attribute__ ((packed)); | 528 | } __attribute__ ((packed)); |
529 | 529 | ||
530 | struct ieee80211_mgmt { | 530 | struct ieee80211_mgmt { |
531 | __le16 frame_control; | 531 | __le16 frame_control; |
532 | __le16 duration; | 532 | __le16 duration; |
533 | u8 da[6]; | 533 | u8 da[6]; |
534 | u8 sa[6]; | 534 | u8 sa[6]; |
535 | u8 bssid[6]; | 535 | u8 bssid[6]; |
536 | __le16 seq_ctrl; | 536 | __le16 seq_ctrl; |
537 | union { | 537 | union { |
538 | struct { | 538 | struct { |
539 | __le16 auth_alg; | 539 | __le16 auth_alg; |
540 | __le16 auth_transaction; | 540 | __le16 auth_transaction; |
541 | __le16 status_code; | 541 | __le16 status_code; |
542 | /* possibly followed by Challenge text */ | 542 | /* possibly followed by Challenge text */ |
543 | u8 variable[0]; | 543 | u8 variable[0]; |
544 | } __attribute__ ((packed)) auth; | 544 | } __attribute__ ((packed)) auth; |
545 | struct { | 545 | struct { |
546 | __le16 reason_code; | 546 | __le16 reason_code; |
547 | } __attribute__ ((packed)) deauth; | 547 | } __attribute__ ((packed)) deauth; |
548 | struct { | 548 | struct { |
549 | __le16 capab_info; | 549 | __le16 capab_info; |
550 | __le16 listen_interval; | 550 | __le16 listen_interval; |
551 | /* followed by SSID and Supported rates */ | 551 | /* followed by SSID and Supported rates */ |
552 | u8 variable[0]; | 552 | u8 variable[0]; |
553 | } __attribute__ ((packed)) assoc_req; | 553 | } __attribute__ ((packed)) assoc_req; |
554 | struct { | 554 | struct { |
555 | __le16 capab_info; | 555 | __le16 capab_info; |
556 | __le16 status_code; | 556 | __le16 status_code; |
557 | __le16 aid; | 557 | __le16 aid; |
558 | /* followed by Supported rates */ | 558 | /* followed by Supported rates */ |
559 | u8 variable[0]; | 559 | u8 variable[0]; |
560 | } __attribute__ ((packed)) assoc_resp, reassoc_resp; | 560 | } __attribute__ ((packed)) assoc_resp, reassoc_resp; |
561 | struct { | 561 | struct { |
562 | __le16 capab_info; | 562 | __le16 capab_info; |
563 | __le16 listen_interval; | 563 | __le16 listen_interval; |
564 | u8 current_ap[6]; | 564 | u8 current_ap[6]; |
565 | /* followed by SSID and Supported rates */ | 565 | /* followed by SSID and Supported rates */ |
566 | u8 variable[0]; | 566 | u8 variable[0]; |
567 | } __attribute__ ((packed)) reassoc_req; | 567 | } __attribute__ ((packed)) reassoc_req; |
568 | struct { | 568 | struct { |
569 | __le16 reason_code; | 569 | __le16 reason_code; |
570 | } __attribute__ ((packed)) disassoc; | 570 | } __attribute__ ((packed)) disassoc; |
571 | struct { | 571 | struct { |
572 | __le64 timestamp; | 572 | __le64 timestamp; |
573 | __le16 beacon_int; | 573 | __le16 beacon_int; |
574 | __le16 capab_info; | 574 | __le16 capab_info; |
575 | /* followed by some of SSID, Supported rates, | 575 | /* followed by some of SSID, Supported rates, |
576 | * FH Params, DS Params, CF Params, IBSS Params, TIM */ | 576 | * FH Params, DS Params, CF Params, IBSS Params, TIM */ |
577 | u8 variable[0]; | 577 | u8 variable[0]; |
578 | } __attribute__ ((packed)) beacon; | 578 | } __attribute__ ((packed)) beacon; |
579 | struct { | 579 | struct { |
580 | /* only variable items: SSID, Supported rates */ | 580 | /* only variable items: SSID, Supported rates */ |
581 | u8 variable[0]; | 581 | u8 variable[0]; |
582 | } __attribute__ ((packed)) probe_req; | 582 | } __attribute__ ((packed)) probe_req; |
583 | struct { | 583 | struct { |
584 | __le64 timestamp; | 584 | __le64 timestamp; |
585 | __le16 beacon_int; | 585 | __le16 beacon_int; |
586 | __le16 capab_info; | 586 | __le16 capab_info; |
587 | /* followed by some of SSID, Supported rates, | 587 | /* followed by some of SSID, Supported rates, |
588 | * FH Params, DS Params, CF Params, IBSS Params */ | 588 | * FH Params, DS Params, CF Params, IBSS Params */ |
589 | u8 variable[0]; | 589 | u8 variable[0]; |
590 | } __attribute__ ((packed)) probe_resp; | 590 | } __attribute__ ((packed)) probe_resp; |
591 | struct { | 591 | struct { |
592 | u8 category; | 592 | u8 category; |
593 | union { | 593 | union { |
594 | struct { | 594 | struct { |
595 | u8 action_code; | 595 | u8 action_code; |
596 | u8 dialog_token; | 596 | u8 dialog_token; |
597 | u8 status_code; | 597 | u8 status_code; |
598 | u8 variable[0]; | 598 | u8 variable[0]; |
599 | } __attribute__ ((packed)) wme_action; | 599 | } __attribute__ ((packed)) wme_action; |
600 | struct{ | 600 | struct{ |
601 | u8 action_code; | 601 | u8 action_code; |
602 | u8 element_id; | 602 | u8 element_id; |
603 | u8 length; | 603 | u8 length; |
604 | struct ieee80211_channel_sw_ie sw_elem; | 604 | struct ieee80211_channel_sw_ie sw_elem; |
605 | } __attribute__((packed)) chan_switch; | 605 | } __attribute__((packed)) chan_switch; |
606 | struct{ | 606 | struct{ |
607 | u8 action_code; | 607 | u8 action_code; |
608 | u8 dialog_token; | 608 | u8 dialog_token; |
609 | u8 element_id; | 609 | u8 element_id; |
610 | u8 length; | 610 | u8 length; |
611 | struct ieee80211_msrment_ie msr_elem; | 611 | struct ieee80211_msrment_ie msr_elem; |
612 | } __attribute__((packed)) measurement; | 612 | } __attribute__((packed)) measurement; |
613 | struct{ | 613 | struct{ |
614 | u8 action_code; | 614 | u8 action_code; |
615 | u8 dialog_token; | 615 | u8 dialog_token; |
616 | __le16 capab; | 616 | __le16 capab; |
617 | __le16 timeout; | 617 | __le16 timeout; |
618 | __le16 start_seq_num; | 618 | __le16 start_seq_num; |
619 | } __attribute__((packed)) addba_req; | 619 | } __attribute__((packed)) addba_req; |
620 | struct{ | 620 | struct{ |
621 | u8 action_code; | 621 | u8 action_code; |
622 | u8 dialog_token; | 622 | u8 dialog_token; |
623 | __le16 status; | 623 | __le16 status; |
624 | __le16 capab; | 624 | __le16 capab; |
625 | __le16 timeout; | 625 | __le16 timeout; |
626 | } __attribute__((packed)) addba_resp; | 626 | } __attribute__((packed)) addba_resp; |
627 | struct{ | 627 | struct{ |
628 | u8 action_code; | 628 | u8 action_code; |
629 | __le16 params; | 629 | __le16 params; |
630 | __le16 reason_code; | 630 | __le16 reason_code; |
631 | } __attribute__((packed)) delba; | 631 | } __attribute__((packed)) delba; |
632 | struct{ | 632 | struct{ |
633 | u8 action_code; | 633 | u8 action_code; |
634 | /* capab_info for open and confirm, | 634 | /* capab_info for open and confirm, |
635 | * reason for close | 635 | * reason for close |
636 | */ | 636 | */ |
637 | __le16 aux; | 637 | __le16 aux; |
638 | /* Followed in plink_confirm by status | 638 | /* Followed in plink_confirm by status |
639 | * code, AID and supported rates, | 639 | * code, AID and supported rates, |
640 | * and directly by supported rates in | 640 | * and directly by supported rates in |
641 | * plink_open and plink_close | 641 | * plink_open and plink_close |
642 | */ | 642 | */ |
643 | u8 variable[0]; | 643 | u8 variable[0]; |
644 | } __attribute__((packed)) plink_action; | 644 | } __attribute__((packed)) plink_action; |
645 | struct{ | 645 | struct{ |
646 | u8 action_code; | 646 | u8 action_code; |
647 | u8 variable[0]; | 647 | u8 variable[0]; |
648 | } __attribute__((packed)) mesh_action; | 648 | } __attribute__((packed)) mesh_action; |
649 | } u; | 649 | } u; |
650 | } __attribute__ ((packed)) action; | 650 | } __attribute__ ((packed)) action; |
651 | } u; | 651 | } u; |
652 | } __attribute__ ((packed)); | 652 | } __attribute__ ((packed)); |
653 | 653 | ||
654 | /* mgmt header + 1 byte category code */ | 654 | /* mgmt header + 1 byte category code */ |
655 | #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) | 655 | #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) |
656 | 656 | ||
657 | 657 | ||
658 | /* Management MIC information element (IEEE 802.11w) */ | 658 | /* Management MIC information element (IEEE 802.11w) */ |
659 | struct ieee80211_mmie { | 659 | struct ieee80211_mmie { |
660 | u8 element_id; | 660 | u8 element_id; |
661 | u8 length; | 661 | u8 length; |
662 | __le16 key_id; | 662 | __le16 key_id; |
663 | u8 sequence_number[6]; | 663 | u8 sequence_number[6]; |
664 | u8 mic[8]; | 664 | u8 mic[8]; |
665 | } __attribute__ ((packed)); | 665 | } __attribute__ ((packed)); |
666 | 666 | ||
667 | /* Control frames */ | 667 | /* Control frames */ |
668 | struct ieee80211_rts { | 668 | struct ieee80211_rts { |
669 | __le16 frame_control; | 669 | __le16 frame_control; |
670 | __le16 duration; | 670 | __le16 duration; |
671 | u8 ra[6]; | 671 | u8 ra[6]; |
672 | u8 ta[6]; | 672 | u8 ta[6]; |
673 | } __attribute__ ((packed)); | 673 | } __attribute__ ((packed)); |
674 | 674 | ||
675 | struct ieee80211_cts { | 675 | struct ieee80211_cts { |
676 | __le16 frame_control; | 676 | __le16 frame_control; |
677 | __le16 duration; | 677 | __le16 duration; |
678 | u8 ra[6]; | 678 | u8 ra[6]; |
679 | } __attribute__ ((packed)); | 679 | } __attribute__ ((packed)); |
680 | 680 | ||
681 | struct ieee80211_pspoll { | 681 | struct ieee80211_pspoll { |
682 | __le16 frame_control; | 682 | __le16 frame_control; |
683 | __le16 aid; | 683 | __le16 aid; |
684 | u8 bssid[6]; | 684 | u8 bssid[6]; |
685 | u8 ta[6]; | 685 | u8 ta[6]; |
686 | } __attribute__ ((packed)); | 686 | } __attribute__ ((packed)); |
687 | 687 | ||
688 | /** | 688 | /** |
689 | * struct ieee80211_bar - HT Block Ack Request | 689 | * struct ieee80211_bar - HT Block Ack Request |
690 | * | 690 | * |
691 | * This structure refers to "HT BlockAckReq" as | 691 | * This structure refers to "HT BlockAckReq" as |
692 | * described in 802.11n draft section 7.2.1.7.1 | 692 | * described in 802.11n draft section 7.2.1.7.1 |
693 | */ | 693 | */ |
694 | struct ieee80211_bar { | 694 | struct ieee80211_bar { |
695 | __le16 frame_control; | 695 | __le16 frame_control; |
696 | __le16 duration; | 696 | __le16 duration; |
697 | __u8 ra[6]; | 697 | __u8 ra[6]; |
698 | __u8 ta[6]; | 698 | __u8 ta[6]; |
699 | __le16 control; | 699 | __le16 control; |
700 | __le16 start_seq_num; | 700 | __le16 start_seq_num; |
701 | } __attribute__((packed)); | 701 | } __attribute__((packed)); |
702 | 702 | ||
703 | /* 802.11 BAR control masks */ | 703 | /* 802.11 BAR control masks */ |
704 | #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 | 704 | #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 |
705 | #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 | 705 | #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 |
706 | 706 | ||
707 | 707 | ||
708 | #define IEEE80211_HT_MCS_MASK_LEN 10 | 708 | #define IEEE80211_HT_MCS_MASK_LEN 10 |
709 | 709 | ||
710 | /** | 710 | /** |
711 | * struct ieee80211_mcs_info - MCS information | 711 | * struct ieee80211_mcs_info - MCS information |
712 | * @rx_mask: RX mask | 712 | * @rx_mask: RX mask |
713 | * @rx_highest: highest supported RX rate | 713 | * @rx_highest: highest supported RX rate |
714 | * @tx_params: TX parameters | 714 | * @tx_params: TX parameters |
715 | */ | 715 | */ |
716 | struct ieee80211_mcs_info { | 716 | struct ieee80211_mcs_info { |
717 | u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; | 717 | u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; |
718 | __le16 rx_highest; | 718 | __le16 rx_highest; |
719 | u8 tx_params; | 719 | u8 tx_params; |
720 | u8 reserved[3]; | 720 | u8 reserved[3]; |
721 | } __attribute__((packed)); | 721 | } __attribute__((packed)); |
722 | 722 | ||
723 | /* 802.11n HT capability MSC set */ | 723 | /* 802.11n HT capability MSC set */ |
724 | #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff | 724 | #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff |
725 | #define IEEE80211_HT_MCS_TX_DEFINED 0x01 | 725 | #define IEEE80211_HT_MCS_TX_DEFINED 0x01 |
726 | #define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 | 726 | #define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 |
727 | /* value 0 == 1 stream etc */ | 727 | /* value 0 == 1 stream etc */ |
728 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C | 728 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C |
729 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 | 729 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 |
730 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 | 730 | #define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 |
731 | #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 | 731 | #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 |
732 | 732 | ||
733 | /* | 733 | /* |
734 | * 802.11n D5.0 20.3.5 / 20.6 says: | 734 | * 802.11n D5.0 20.3.5 / 20.6 says: |
735 | * - indices 0 to 7 and 32 are single spatial stream | 735 | * - indices 0 to 7 and 32 are single spatial stream |
736 | * - 8 to 31 are multiple spatial streams using equal modulation | 736 | * - 8 to 31 are multiple spatial streams using equal modulation |
737 | * [8..15 for two streams, 16..23 for three and 24..31 for four] | 737 | * [8..15 for two streams, 16..23 for three and 24..31 for four] |
738 | * - remainder are multiple spatial streams using unequal modulation | 738 | * - remainder are multiple spatial streams using unequal modulation |
739 | */ | 739 | */ |
740 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 | 740 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 |
741 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ | 741 | #define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ |
742 | (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) | 742 | (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) |
743 | 743 | ||
744 | /** | 744 | /** |
745 | * struct ieee80211_ht_cap - HT capabilities | 745 | * struct ieee80211_ht_cap - HT capabilities |
746 | * | 746 | * |
747 | * This structure is the "HT capabilities element" as | 747 | * This structure is the "HT capabilities element" as |
748 | * described in 802.11n D5.0 7.3.2.57 | 748 | * described in 802.11n D5.0 7.3.2.57 |
749 | */ | 749 | */ |
750 | struct ieee80211_ht_cap { | 750 | struct ieee80211_ht_cap { |
751 | __le16 cap_info; | 751 | __le16 cap_info; |
752 | u8 ampdu_params_info; | 752 | u8 ampdu_params_info; |
753 | 753 | ||
754 | /* 16 bytes MCS information */ | 754 | /* 16 bytes MCS information */ |
755 | struct ieee80211_mcs_info mcs; | 755 | struct ieee80211_mcs_info mcs; |
756 | 756 | ||
757 | __le16 extended_ht_cap_info; | 757 | __le16 extended_ht_cap_info; |
758 | __le32 tx_BF_cap_info; | 758 | __le32 tx_BF_cap_info; |
759 | u8 antenna_selection_info; | 759 | u8 antenna_selection_info; |
760 | } __attribute__ ((packed)); | 760 | } __attribute__ ((packed)); |
761 | 761 | ||
762 | /* 802.11n HT capabilities masks (for cap_info) */ | 762 | /* 802.11n HT capabilities masks (for cap_info) */ |
763 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 | 763 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 |
764 | #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 | 764 | #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 |
765 | #define IEEE80211_HT_CAP_SM_PS 0x000C | 765 | #define IEEE80211_HT_CAP_SM_PS 0x000C |
766 | #define IEEE80211_HT_CAP_GRN_FLD 0x0010 | 766 | #define IEEE80211_HT_CAP_GRN_FLD 0x0010 |
767 | #define IEEE80211_HT_CAP_SGI_20 0x0020 | 767 | #define IEEE80211_HT_CAP_SGI_20 0x0020 |
768 | #define IEEE80211_HT_CAP_SGI_40 0x0040 | 768 | #define IEEE80211_HT_CAP_SGI_40 0x0040 |
769 | #define IEEE80211_HT_CAP_TX_STBC 0x0080 | 769 | #define IEEE80211_HT_CAP_TX_STBC 0x0080 |
770 | #define IEEE80211_HT_CAP_RX_STBC 0x0300 | 770 | #define IEEE80211_HT_CAP_RX_STBC 0x0300 |
771 | #define IEEE80211_HT_CAP_DELAY_BA 0x0400 | 771 | #define IEEE80211_HT_CAP_DELAY_BA 0x0400 |
772 | #define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 | 772 | #define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 |
773 | #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 | 773 | #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 |
774 | #define IEEE80211_HT_CAP_PSMP_SUPPORT 0x2000 | 774 | #define IEEE80211_HT_CAP_PSMP_SUPPORT 0x2000 |
775 | #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 | 775 | #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 |
776 | #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 | 776 | #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 |
777 | 777 | ||
778 | /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ | 778 | /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ |
779 | #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 | 779 | #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 |
780 | #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C | 780 | #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C |
781 | 781 | ||
782 | /** | 782 | /** |
783 | * struct ieee80211_ht_info - HT information | 783 | * struct ieee80211_ht_info - HT information |
784 | * | 784 | * |
785 | * This structure is the "HT information element" as | 785 | * This structure is the "HT information element" as |
786 | * described in 802.11n D5.0 7.3.2.58 | 786 | * described in 802.11n D5.0 7.3.2.58 |
787 | */ | 787 | */ |
788 | struct ieee80211_ht_info { | 788 | struct ieee80211_ht_info { |
789 | u8 control_chan; | 789 | u8 control_chan; |
790 | u8 ht_param; | 790 | u8 ht_param; |
791 | __le16 operation_mode; | 791 | __le16 operation_mode; |
792 | __le16 stbc_param; | 792 | __le16 stbc_param; |
793 | u8 basic_set[16]; | 793 | u8 basic_set[16]; |
794 | } __attribute__ ((packed)); | 794 | } __attribute__ ((packed)); |
795 | 795 | ||
796 | /* for ht_param */ | 796 | /* for ht_param */ |
797 | #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 | 797 | #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 |
798 | #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 | 798 | #define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 |
799 | #define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 | 799 | #define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 |
800 | #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 | 800 | #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 |
801 | #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 | 801 | #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 |
802 | #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 | 802 | #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 |
803 | #define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 | 803 | #define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 |
804 | #define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 | 804 | #define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 |
805 | 805 | ||
806 | /* for operation_mode */ | 806 | /* for operation_mode */ |
807 | #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 | 807 | #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 |
808 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 | 808 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 |
809 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 | 809 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 |
810 | #define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 | 810 | #define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 |
811 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 | 811 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 |
812 | #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 | 812 | #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 |
813 | #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 | 813 | #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 |
814 | 814 | ||
815 | /* for stbc_param */ | 815 | /* for stbc_param */ |
816 | #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 | 816 | #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 |
817 | #define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 | 817 | #define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 |
818 | #define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 | 818 | #define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 |
819 | #define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 | 819 | #define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 |
820 | #define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 | 820 | #define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 |
821 | #define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 | 821 | #define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 |
822 | 822 | ||
823 | 823 | ||
824 | /* block-ack parameters */ | 824 | /* block-ack parameters */ |
825 | #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 | 825 | #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 |
826 | #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C | 826 | #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C |
827 | #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 | 827 | #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 |
828 | #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 | 828 | #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 |
829 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 | 829 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 |
830 | 830 | ||
831 | /* | 831 | /* |
832 | * A-PMDU buffer sizes | 832 | * A-PMDU buffer sizes |
833 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) | 833 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) |
834 | */ | 834 | */ |
835 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | 835 | #define IEEE80211_MIN_AMPDU_BUF 0x8 |
836 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | 836 | #define IEEE80211_MAX_AMPDU_BUF 0x40 |
837 | 837 | ||
838 | 838 | ||
839 | /* Spatial Multiplexing Power Save Modes */ | 839 | /* Spatial Multiplexing Power Save Modes */ |
840 | #define WLAN_HT_CAP_SM_PS_STATIC 0 | 840 | #define WLAN_HT_CAP_SM_PS_STATIC 0 |
841 | #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 | 841 | #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 |
842 | #define WLAN_HT_CAP_SM_PS_INVALID 2 | 842 | #define WLAN_HT_CAP_SM_PS_INVALID 2 |
843 | #define WLAN_HT_CAP_SM_PS_DISABLED 3 | 843 | #define WLAN_HT_CAP_SM_PS_DISABLED 3 |
844 | 844 | ||
845 | /* Authentication algorithms */ | 845 | /* Authentication algorithms */ |
846 | #define WLAN_AUTH_OPEN 0 | 846 | #define WLAN_AUTH_OPEN 0 |
847 | #define WLAN_AUTH_SHARED_KEY 1 | 847 | #define WLAN_AUTH_SHARED_KEY 1 |
848 | #define WLAN_AUTH_LEAP 128 | 848 | #define WLAN_AUTH_LEAP 128 |
849 | 849 | ||
850 | #define WLAN_AUTH_CHALLENGE_LEN 128 | 850 | #define WLAN_AUTH_CHALLENGE_LEN 128 |
851 | 851 | ||
852 | #define WLAN_CAPABILITY_ESS (1<<0) | 852 | #define WLAN_CAPABILITY_ESS (1<<0) |
853 | #define WLAN_CAPABILITY_IBSS (1<<1) | 853 | #define WLAN_CAPABILITY_IBSS (1<<1) |
854 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) | 854 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) |
855 | #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) | 855 | #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) |
856 | #define WLAN_CAPABILITY_PRIVACY (1<<4) | 856 | #define WLAN_CAPABILITY_PRIVACY (1<<4) |
857 | #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) | 857 | #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) |
858 | #define WLAN_CAPABILITY_PBCC (1<<6) | 858 | #define WLAN_CAPABILITY_PBCC (1<<6) |
859 | #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) | 859 | #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) |
860 | 860 | ||
861 | /* 802.11h */ | 861 | /* 802.11h */ |
862 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) | 862 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) |
863 | #define WLAN_CAPABILITY_QOS (1<<9) | 863 | #define WLAN_CAPABILITY_QOS (1<<9) |
864 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) | 864 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) |
865 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) | 865 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) |
866 | /* measurement */ | 866 | /* measurement */ |
867 | #define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) | 867 | #define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) |
868 | #define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) | 868 | #define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) |
869 | #define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) | 869 | #define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) |
870 | 870 | ||
871 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 | 871 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 |
872 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 | 872 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 |
873 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 | 873 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 |
874 | 874 | ||
875 | 875 | ||
876 | /* 802.11g ERP information element */ | 876 | /* 802.11g ERP information element */ |
877 | #define WLAN_ERP_NON_ERP_PRESENT (1<<0) | 877 | #define WLAN_ERP_NON_ERP_PRESENT (1<<0) |
878 | #define WLAN_ERP_USE_PROTECTION (1<<1) | 878 | #define WLAN_ERP_USE_PROTECTION (1<<1) |
879 | #define WLAN_ERP_BARKER_PREAMBLE (1<<2) | 879 | #define WLAN_ERP_BARKER_PREAMBLE (1<<2) |
880 | 880 | ||
881 | /* WLAN_ERP_BARKER_PREAMBLE values */ | 881 | /* WLAN_ERP_BARKER_PREAMBLE values */ |
882 | enum { | 882 | enum { |
883 | WLAN_ERP_PREAMBLE_SHORT = 0, | 883 | WLAN_ERP_PREAMBLE_SHORT = 0, |
884 | WLAN_ERP_PREAMBLE_LONG = 1, | 884 | WLAN_ERP_PREAMBLE_LONG = 1, |
885 | }; | 885 | }; |
886 | 886 | ||
887 | /* Status codes */ | 887 | /* Status codes */ |
888 | enum ieee80211_statuscode { | 888 | enum ieee80211_statuscode { |
889 | WLAN_STATUS_SUCCESS = 0, | 889 | WLAN_STATUS_SUCCESS = 0, |
890 | WLAN_STATUS_UNSPECIFIED_FAILURE = 1, | 890 | WLAN_STATUS_UNSPECIFIED_FAILURE = 1, |
891 | WLAN_STATUS_CAPS_UNSUPPORTED = 10, | 891 | WLAN_STATUS_CAPS_UNSUPPORTED = 10, |
892 | WLAN_STATUS_REASSOC_NO_ASSOC = 11, | 892 | WLAN_STATUS_REASSOC_NO_ASSOC = 11, |
893 | WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, | 893 | WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, |
894 | WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, | 894 | WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, |
895 | WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, | 895 | WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, |
896 | WLAN_STATUS_CHALLENGE_FAIL = 15, | 896 | WLAN_STATUS_CHALLENGE_FAIL = 15, |
897 | WLAN_STATUS_AUTH_TIMEOUT = 16, | 897 | WLAN_STATUS_AUTH_TIMEOUT = 16, |
898 | WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, | 898 | WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, |
899 | WLAN_STATUS_ASSOC_DENIED_RATES = 18, | 899 | WLAN_STATUS_ASSOC_DENIED_RATES = 18, |
900 | /* 802.11b */ | 900 | /* 802.11b */ |
901 | WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, | 901 | WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, |
902 | WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, | 902 | WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, |
903 | WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, | 903 | WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, |
904 | /* 802.11h */ | 904 | /* 802.11h */ |
905 | WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, | 905 | WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, |
906 | WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, | 906 | WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, |
907 | WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, | 907 | WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, |
908 | /* 802.11g */ | 908 | /* 802.11g */ |
909 | WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, | 909 | WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, |
910 | WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, | 910 | WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, |
911 | /* 802.11i */ | 911 | /* 802.11i */ |
912 | WLAN_STATUS_INVALID_IE = 40, | 912 | WLAN_STATUS_INVALID_IE = 40, |
913 | WLAN_STATUS_INVALID_GROUP_CIPHER = 41, | 913 | WLAN_STATUS_INVALID_GROUP_CIPHER = 41, |
914 | WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, | 914 | WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, |
915 | WLAN_STATUS_INVALID_AKMP = 43, | 915 | WLAN_STATUS_INVALID_AKMP = 43, |
916 | WLAN_STATUS_UNSUPP_RSN_VERSION = 44, | 916 | WLAN_STATUS_UNSUPP_RSN_VERSION = 44, |
917 | WLAN_STATUS_INVALID_RSN_IE_CAP = 45, | 917 | WLAN_STATUS_INVALID_RSN_IE_CAP = 45, |
918 | WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, | 918 | WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, |
919 | /* 802.11e */ | 919 | /* 802.11e */ |
920 | WLAN_STATUS_UNSPECIFIED_QOS = 32, | 920 | WLAN_STATUS_UNSPECIFIED_QOS = 32, |
921 | WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, | 921 | WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, |
922 | WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, | 922 | WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, |
923 | WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, | 923 | WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, |
924 | WLAN_STATUS_REQUEST_DECLINED = 37, | 924 | WLAN_STATUS_REQUEST_DECLINED = 37, |
925 | WLAN_STATUS_INVALID_QOS_PARAM = 38, | 925 | WLAN_STATUS_INVALID_QOS_PARAM = 38, |
926 | WLAN_STATUS_CHANGE_TSPEC = 39, | 926 | WLAN_STATUS_CHANGE_TSPEC = 39, |
927 | WLAN_STATUS_WAIT_TS_DELAY = 47, | 927 | WLAN_STATUS_WAIT_TS_DELAY = 47, |
928 | WLAN_STATUS_NO_DIRECT_LINK = 48, | 928 | WLAN_STATUS_NO_DIRECT_LINK = 48, |
929 | WLAN_STATUS_STA_NOT_PRESENT = 49, | 929 | WLAN_STATUS_STA_NOT_PRESENT = 49, |
930 | WLAN_STATUS_STA_NOT_QSTA = 50, | 930 | WLAN_STATUS_STA_NOT_QSTA = 50, |
931 | }; | 931 | }; |
932 | 932 | ||
933 | 933 | ||
934 | /* Reason codes */ | 934 | /* Reason codes */ |
935 | enum ieee80211_reasoncode { | 935 | enum ieee80211_reasoncode { |
936 | WLAN_REASON_UNSPECIFIED = 1, | 936 | WLAN_REASON_UNSPECIFIED = 1, |
937 | WLAN_REASON_PREV_AUTH_NOT_VALID = 2, | 937 | WLAN_REASON_PREV_AUTH_NOT_VALID = 2, |
938 | WLAN_REASON_DEAUTH_LEAVING = 3, | 938 | WLAN_REASON_DEAUTH_LEAVING = 3, |
939 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, | 939 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, |
940 | WLAN_REASON_DISASSOC_AP_BUSY = 5, | 940 | WLAN_REASON_DISASSOC_AP_BUSY = 5, |
941 | WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, | 941 | WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, |
942 | WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, | 942 | WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, |
943 | WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, | 943 | WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, |
944 | WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, | 944 | WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, |
945 | /* 802.11h */ | 945 | /* 802.11h */ |
946 | WLAN_REASON_DISASSOC_BAD_POWER = 10, | 946 | WLAN_REASON_DISASSOC_BAD_POWER = 10, |
947 | WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, | 947 | WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, |
948 | /* 802.11i */ | 948 | /* 802.11i */ |
949 | WLAN_REASON_INVALID_IE = 13, | 949 | WLAN_REASON_INVALID_IE = 13, |
950 | WLAN_REASON_MIC_FAILURE = 14, | 950 | WLAN_REASON_MIC_FAILURE = 14, |
951 | WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, | 951 | WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, |
952 | WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, | 952 | WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, |
953 | WLAN_REASON_IE_DIFFERENT = 17, | 953 | WLAN_REASON_IE_DIFFERENT = 17, |
954 | WLAN_REASON_INVALID_GROUP_CIPHER = 18, | 954 | WLAN_REASON_INVALID_GROUP_CIPHER = 18, |
955 | WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, | 955 | WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, |
956 | WLAN_REASON_INVALID_AKMP = 20, | 956 | WLAN_REASON_INVALID_AKMP = 20, |
957 | WLAN_REASON_UNSUPP_RSN_VERSION = 21, | 957 | WLAN_REASON_UNSUPP_RSN_VERSION = 21, |
958 | WLAN_REASON_INVALID_RSN_IE_CAP = 22, | 958 | WLAN_REASON_INVALID_RSN_IE_CAP = 22, |
959 | WLAN_REASON_IEEE8021X_FAILED = 23, | 959 | WLAN_REASON_IEEE8021X_FAILED = 23, |
960 | WLAN_REASON_CIPHER_SUITE_REJECTED = 24, | 960 | WLAN_REASON_CIPHER_SUITE_REJECTED = 24, |
961 | /* 802.11e */ | 961 | /* 802.11e */ |
962 | WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, | 962 | WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, |
963 | WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, | 963 | WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, |
964 | WLAN_REASON_DISASSOC_LOW_ACK = 34, | 964 | WLAN_REASON_DISASSOC_LOW_ACK = 34, |
965 | WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, | 965 | WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, |
966 | WLAN_REASON_QSTA_LEAVE_QBSS = 36, | 966 | WLAN_REASON_QSTA_LEAVE_QBSS = 36, |
967 | WLAN_REASON_QSTA_NOT_USE = 37, | 967 | WLAN_REASON_QSTA_NOT_USE = 37, |
968 | WLAN_REASON_QSTA_REQUIRE_SETUP = 38, | 968 | WLAN_REASON_QSTA_REQUIRE_SETUP = 38, |
969 | WLAN_REASON_QSTA_TIMEOUT = 39, | 969 | WLAN_REASON_QSTA_TIMEOUT = 39, |
970 | WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, | 970 | WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, |
971 | }; | 971 | }; |
972 | 972 | ||
973 | 973 | ||
974 | /* Information Element IDs */ | 974 | /* Information Element IDs */ |
975 | enum ieee80211_eid { | 975 | enum ieee80211_eid { |
976 | WLAN_EID_SSID = 0, | 976 | WLAN_EID_SSID = 0, |
977 | WLAN_EID_SUPP_RATES = 1, | 977 | WLAN_EID_SUPP_RATES = 1, |
978 | WLAN_EID_FH_PARAMS = 2, | 978 | WLAN_EID_FH_PARAMS = 2, |
979 | WLAN_EID_DS_PARAMS = 3, | 979 | WLAN_EID_DS_PARAMS = 3, |
980 | WLAN_EID_CF_PARAMS = 4, | 980 | WLAN_EID_CF_PARAMS = 4, |
981 | WLAN_EID_TIM = 5, | 981 | WLAN_EID_TIM = 5, |
982 | WLAN_EID_IBSS_PARAMS = 6, | 982 | WLAN_EID_IBSS_PARAMS = 6, |
983 | WLAN_EID_CHALLENGE = 16, | 983 | WLAN_EID_CHALLENGE = 16, |
984 | /* 802.11d */ | 984 | /* 802.11d */ |
985 | WLAN_EID_COUNTRY = 7, | 985 | WLAN_EID_COUNTRY = 7, |
986 | WLAN_EID_HP_PARAMS = 8, | 986 | WLAN_EID_HP_PARAMS = 8, |
987 | WLAN_EID_HP_TABLE = 9, | 987 | WLAN_EID_HP_TABLE = 9, |
988 | WLAN_EID_REQUEST = 10, | 988 | WLAN_EID_REQUEST = 10, |
989 | /* 802.11e */ | 989 | /* 802.11e */ |
990 | WLAN_EID_QBSS_LOAD = 11, | 990 | WLAN_EID_QBSS_LOAD = 11, |
991 | WLAN_EID_EDCA_PARAM_SET = 12, | 991 | WLAN_EID_EDCA_PARAM_SET = 12, |
992 | WLAN_EID_TSPEC = 13, | 992 | WLAN_EID_TSPEC = 13, |
993 | WLAN_EID_TCLAS = 14, | 993 | WLAN_EID_TCLAS = 14, |
994 | WLAN_EID_SCHEDULE = 15, | 994 | WLAN_EID_SCHEDULE = 15, |
995 | WLAN_EID_TS_DELAY = 43, | 995 | WLAN_EID_TS_DELAY = 43, |
996 | WLAN_EID_TCLAS_PROCESSING = 44, | 996 | WLAN_EID_TCLAS_PROCESSING = 44, |
997 | WLAN_EID_QOS_CAPA = 46, | 997 | WLAN_EID_QOS_CAPA = 46, |
998 | /* 802.11s | 998 | /* 802.11s |
999 | * | 999 | * |
1000 | * All mesh EID numbers are pending IEEE 802.11 ANA approval. | 1000 | * All mesh EID numbers are pending IEEE 802.11 ANA approval. |
1001 | * The numbers have been incremented from those suggested in | 1001 | * The numbers have been incremented from those suggested in |
1002 | * 802.11s/D2.0 so that MESH_CONFIG does not conflict with | 1002 | * 802.11s/D2.0 so that MESH_CONFIG does not conflict with |
1003 | * EXT_SUPP_RATES. | 1003 | * EXT_SUPP_RATES. |
1004 | */ | 1004 | */ |
1005 | WLAN_EID_MESH_CONFIG = 51, | 1005 | WLAN_EID_MESH_CONFIG = 51, |
1006 | WLAN_EID_MESH_ID = 52, | 1006 | WLAN_EID_MESH_ID = 52, |
1007 | WLAN_EID_PEER_LINK = 55, | 1007 | WLAN_EID_PEER_LINK = 55, |
1008 | WLAN_EID_PREQ = 68, | 1008 | WLAN_EID_PREQ = 68, |
1009 | WLAN_EID_PREP = 69, | 1009 | WLAN_EID_PREP = 69, |
1010 | WLAN_EID_PERR = 70, | 1010 | WLAN_EID_PERR = 70, |
1011 | /* 802.11h */ | 1011 | /* 802.11h */ |
1012 | WLAN_EID_PWR_CONSTRAINT = 32, | 1012 | WLAN_EID_PWR_CONSTRAINT = 32, |
1013 | WLAN_EID_PWR_CAPABILITY = 33, | 1013 | WLAN_EID_PWR_CAPABILITY = 33, |
1014 | WLAN_EID_TPC_REQUEST = 34, | 1014 | WLAN_EID_TPC_REQUEST = 34, |
1015 | WLAN_EID_TPC_REPORT = 35, | 1015 | WLAN_EID_TPC_REPORT = 35, |
1016 | WLAN_EID_SUPPORTED_CHANNELS = 36, | 1016 | WLAN_EID_SUPPORTED_CHANNELS = 36, |
1017 | WLAN_EID_CHANNEL_SWITCH = 37, | 1017 | WLAN_EID_CHANNEL_SWITCH = 37, |
1018 | WLAN_EID_MEASURE_REQUEST = 38, | 1018 | WLAN_EID_MEASURE_REQUEST = 38, |
1019 | WLAN_EID_MEASURE_REPORT = 39, | 1019 | WLAN_EID_MEASURE_REPORT = 39, |
1020 | WLAN_EID_QUIET = 40, | 1020 | WLAN_EID_QUIET = 40, |
1021 | WLAN_EID_IBSS_DFS = 41, | 1021 | WLAN_EID_IBSS_DFS = 41, |
1022 | /* 802.11g */ | 1022 | /* 802.11g */ |
1023 | WLAN_EID_ERP_INFO = 42, | 1023 | WLAN_EID_ERP_INFO = 42, |
1024 | WLAN_EID_EXT_SUPP_RATES = 50, | 1024 | WLAN_EID_EXT_SUPP_RATES = 50, |
1025 | /* 802.11n */ | 1025 | /* 802.11n */ |
1026 | WLAN_EID_HT_CAPABILITY = 45, | 1026 | WLAN_EID_HT_CAPABILITY = 45, |
1027 | WLAN_EID_HT_INFORMATION = 61, | 1027 | WLAN_EID_HT_INFORMATION = 61, |
1028 | /* 802.11i */ | 1028 | /* 802.11i */ |
1029 | WLAN_EID_RSN = 48, | 1029 | WLAN_EID_RSN = 48, |
1030 | WLAN_EID_MMIE = 76 /* 802.11w */, | 1030 | WLAN_EID_MMIE = 76 /* 802.11w */, |
1031 | WLAN_EID_WPA = 221, | 1031 | WLAN_EID_WPA = 221, |
1032 | WLAN_EID_GENERIC = 221, | 1032 | WLAN_EID_GENERIC = 221, |
1033 | WLAN_EID_VENDOR_SPECIFIC = 221, | 1033 | WLAN_EID_VENDOR_SPECIFIC = 221, |
1034 | WLAN_EID_QOS_PARAMETER = 222 | 1034 | WLAN_EID_QOS_PARAMETER = 222 |
1035 | }; | 1035 | }; |
1036 | 1036 | ||
1037 | /* Action category code */ | 1037 | /* Action category code */ |
1038 | enum ieee80211_category { | 1038 | enum ieee80211_category { |
1039 | WLAN_CATEGORY_SPECTRUM_MGMT = 0, | 1039 | WLAN_CATEGORY_SPECTRUM_MGMT = 0, |
1040 | WLAN_CATEGORY_QOS = 1, | 1040 | WLAN_CATEGORY_QOS = 1, |
1041 | WLAN_CATEGORY_DLS = 2, | 1041 | WLAN_CATEGORY_DLS = 2, |
1042 | WLAN_CATEGORY_BACK = 3, | 1042 | WLAN_CATEGORY_BACK = 3, |
1043 | WLAN_CATEGORY_PUBLIC = 4, | 1043 | WLAN_CATEGORY_PUBLIC = 4, |
1044 | WLAN_CATEGORY_WMM = 17, | 1044 | WLAN_CATEGORY_WMM = 17, |
1045 | }; | 1045 | }; |
1046 | 1046 | ||
1047 | /* SPECTRUM_MGMT action code */ | 1047 | /* SPECTRUM_MGMT action code */ |
1048 | enum ieee80211_spectrum_mgmt_actioncode { | 1048 | enum ieee80211_spectrum_mgmt_actioncode { |
1049 | WLAN_ACTION_SPCT_MSR_REQ = 0, | 1049 | WLAN_ACTION_SPCT_MSR_REQ = 0, |
1050 | WLAN_ACTION_SPCT_MSR_RPRT = 1, | 1050 | WLAN_ACTION_SPCT_MSR_RPRT = 1, |
1051 | WLAN_ACTION_SPCT_TPC_REQ = 2, | 1051 | WLAN_ACTION_SPCT_TPC_REQ = 2, |
1052 | WLAN_ACTION_SPCT_TPC_RPRT = 3, | 1052 | WLAN_ACTION_SPCT_TPC_RPRT = 3, |
1053 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, | 1053 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, |
1054 | }; | 1054 | }; |
1055 | 1055 | ||
1056 | /* | 1056 | /* |
1057 | * IEEE 802.11-2007 7.3.2.9 Country information element | 1057 | * IEEE 802.11-2007 7.3.2.9 Country information element |
1058 | * | 1058 | * |
1059 | * Minimum length is 8 octets, ie len must be evenly | 1059 | * Minimum length is 8 octets, ie len must be evenly |
1060 | * divisible by 2 | 1060 | * divisible by 2 |
1061 | */ | 1061 | */ |
1062 | 1062 | ||
1063 | /* Although the spec says 8 I'm seeing 6 in practice */ | 1063 | /* Although the spec says 8 I'm seeing 6 in practice */ |
1064 | #define IEEE80211_COUNTRY_IE_MIN_LEN 6 | 1064 | #define IEEE80211_COUNTRY_IE_MIN_LEN 6 |
1065 | 1065 | ||
1066 | /* | 1066 | /* |
1067 | * For regulatory extension stuff see IEEE 802.11-2007 | 1067 | * For regulatory extension stuff see IEEE 802.11-2007 |
1068 | * Annex I (page 1141) and Annex J (page 1147). Also | 1068 | * Annex I (page 1141) and Annex J (page 1147). Also |
1069 | * review 7.3.2.9. | 1069 | * review 7.3.2.9. |
1070 | * | 1070 | * |
1071 | * When dot11RegulatoryClassesRequired is true and the | 1071 | * When dot11RegulatoryClassesRequired is true and the |
1072 | * first_channel/reg_extension_id is >= 201 then the IE | 1072 | * first_channel/reg_extension_id is >= 201 then the IE |
1073 | * compromises of the 'ext' struct represented below: | 1073 | * compromises of the 'ext' struct represented below: |
1074 | * | 1074 | * |
1075 | * - Regulatory extension ID - when generating IE this just needs | 1075 | * - Regulatory extension ID - when generating IE this just needs |
1076 | * to be monotonically increasing for each triplet passed in | 1076 | * to be monotonically increasing for each triplet passed in |
1077 | * the IE | 1077 | * the IE |
1078 | * - Regulatory class - index into set of rules | 1078 | * - Regulatory class - index into set of rules |
1079 | * - Coverage class - index into air propagation time (Table 7-27), | 1079 | * - Coverage class - index into air propagation time (Table 7-27), |
1080 | * in microseconds, you can compute the air propagation time from | 1080 | * in microseconds, you can compute the air propagation time from |
1081 | * the index by multiplying by 3, so index 10 yields a propagation | 1081 | * the index by multiplying by 3, so index 10 yields a propagation |
1082 | * of 10 us. Valid values are 0-31, values 32-255 are not defined | 1082 | * of 10 us. Valid values are 0-31, values 32-255 are not defined |
1083 | * yet. A value of 0 inicates air propagation of <= 1 us. | 1083 | * yet. A value of 0 inicates air propagation of <= 1 us. |
1084 | * | 1084 | * |
1085 | * See also Table I.2 for Emission limit sets and table | 1085 | * See also Table I.2 for Emission limit sets and table |
1086 | * I.3 for Behavior limit sets. Table J.1 indicates how to map | 1086 | * I.3 for Behavior limit sets. Table J.1 indicates how to map |
1087 | * a reg_class to an emission limit set and behavior limit set. | 1087 | * a reg_class to an emission limit set and behavior limit set. |
1088 | */ | 1088 | */ |
1089 | #define IEEE80211_COUNTRY_EXTENSION_ID 201 | 1089 | #define IEEE80211_COUNTRY_EXTENSION_ID 201 |
1090 | 1090 | ||
1091 | /* | 1091 | /* |
1092 | * Channels numbers in the IE must be monotonically increasing | 1092 | * Channels numbers in the IE must be monotonically increasing |
1093 | * if dot11RegulatoryClassesRequired is not true. | 1093 | * if dot11RegulatoryClassesRequired is not true. |
1094 | * | 1094 | * |
1095 | * If dot11RegulatoryClassesRequired is true consecutive | 1095 | * If dot11RegulatoryClassesRequired is true consecutive |
1096 | * subband triplets following a regulatory triplet shall | 1096 | * subband triplets following a regulatory triplet shall |
1097 | * have monotonically increasing first_channel number fields. | 1097 | * have monotonically increasing first_channel number fields. |
1098 | * | 1098 | * |
1099 | * Channel numbers shall not overlap. | 1099 | * Channel numbers shall not overlap. |
1100 | * | 1100 | * |
1101 | * Note that max_power is signed. | 1101 | * Note that max_power is signed. |
1102 | */ | 1102 | */ |
1103 | struct ieee80211_country_ie_triplet { | 1103 | struct ieee80211_country_ie_triplet { |
1104 | union { | 1104 | union { |
1105 | struct { | 1105 | struct { |
1106 | u8 first_channel; | 1106 | u8 first_channel; |
1107 | u8 num_channels; | 1107 | u8 num_channels; |
1108 | s8 max_power; | 1108 | s8 max_power; |
1109 | } __attribute__ ((packed)) chans; | 1109 | } __attribute__ ((packed)) chans; |
1110 | struct { | 1110 | struct { |
1111 | u8 reg_extension_id; | 1111 | u8 reg_extension_id; |
1112 | u8 reg_class; | 1112 | u8 reg_class; |
1113 | u8 coverage_class; | 1113 | u8 coverage_class; |
1114 | } __attribute__ ((packed)) ext; | 1114 | } __attribute__ ((packed)) ext; |
1115 | }; | 1115 | }; |
1116 | } __attribute__ ((packed)); | 1116 | } __attribute__ ((packed)); |
1117 | 1117 | ||
1118 | /* BACK action code */ | 1118 | /* BACK action code */ |
1119 | enum ieee80211_back_actioncode { | 1119 | enum ieee80211_back_actioncode { |
1120 | WLAN_ACTION_ADDBA_REQ = 0, | 1120 | WLAN_ACTION_ADDBA_REQ = 0, |
1121 | WLAN_ACTION_ADDBA_RESP = 1, | 1121 | WLAN_ACTION_ADDBA_RESP = 1, |
1122 | WLAN_ACTION_DELBA = 2, | 1122 | WLAN_ACTION_DELBA = 2, |
1123 | }; | 1123 | }; |
1124 | 1124 | ||
1125 | /* BACK (block-ack) parties */ | 1125 | /* BACK (block-ack) parties */ |
1126 | enum ieee80211_back_parties { | 1126 | enum ieee80211_back_parties { |
1127 | WLAN_BACK_RECIPIENT = 0, | 1127 | WLAN_BACK_RECIPIENT = 0, |
1128 | WLAN_BACK_INITIATOR = 1, | 1128 | WLAN_BACK_INITIATOR = 1, |
1129 | WLAN_BACK_TIMER = 2, | 1129 | WLAN_BACK_TIMER = 2, |
1130 | }; | 1130 | }; |
1131 | 1131 | ||
1132 | /* A-MSDU 802.11n */ | 1132 | /* A-MSDU 802.11n */ |
1133 | #define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 | 1133 | #define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 |
1134 | 1134 | ||
1135 | /* cipher suite selectors */ | 1135 | /* cipher suite selectors */ |
1136 | #define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 | 1136 | #define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 |
1137 | #define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 | 1137 | #define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 |
1138 | #define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 | 1138 | #define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 |
1139 | /* reserved: 0x000FAC03 */ | 1139 | /* reserved: 0x000FAC03 */ |
1140 | #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 | 1140 | #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 |
1141 | #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 | 1141 | #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 |
1142 | #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 | ||
1142 | 1143 | ||
1143 | #define WLAN_MAX_KEY_LEN 32 | 1144 | #define WLAN_MAX_KEY_LEN 32 |
1144 | 1145 | ||
1145 | /** | 1146 | /** |
1146 | * ieee80211_get_qos_ctl - get pointer to qos control bytes | 1147 | * ieee80211_get_qos_ctl - get pointer to qos control bytes |
1147 | * @hdr: the frame | 1148 | * @hdr: the frame |
1148 | * | 1149 | * |
1149 | * The qos ctrl bytes come after the frame_control, duration, seq_num | 1150 | * The qos ctrl bytes come after the frame_control, duration, seq_num |
1150 | * and 3 or 4 addresses of length ETH_ALEN. | 1151 | * and 3 or 4 addresses of length ETH_ALEN. |
1151 | * 3 addr: 2 + 2 + 2 + 3*6 = 24 | 1152 | * 3 addr: 2 + 2 + 2 + 3*6 = 24 |
1152 | * 4 addr: 2 + 2 + 2 + 4*6 = 30 | 1153 | * 4 addr: 2 + 2 + 2 + 4*6 = 30 |
1153 | */ | 1154 | */ |
1154 | static inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) | 1155 | static inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) |
1155 | { | 1156 | { |
1156 | if (ieee80211_has_a4(hdr->frame_control)) | 1157 | if (ieee80211_has_a4(hdr->frame_control)) |
1157 | return (u8 *)hdr + 30; | 1158 | return (u8 *)hdr + 30; |
1158 | else | 1159 | else |
1159 | return (u8 *)hdr + 24; | 1160 | return (u8 *)hdr + 24; |
1160 | } | 1161 | } |
1161 | 1162 | ||
1162 | /** | 1163 | /** |
1163 | * ieee80211_get_SA - get pointer to SA | 1164 | * ieee80211_get_SA - get pointer to SA |
1164 | * @hdr: the frame | 1165 | * @hdr: the frame |
1165 | * | 1166 | * |
1166 | * Given an 802.11 frame, this function returns the offset | 1167 | * Given an 802.11 frame, this function returns the offset |
1167 | * to the source address (SA). It does not verify that the | 1168 | * to the source address (SA). It does not verify that the |
1168 | * header is long enough to contain the address, and the | 1169 | * header is long enough to contain the address, and the |
1169 | * header must be long enough to contain the frame control | 1170 | * header must be long enough to contain the frame control |
1170 | * field. | 1171 | * field. |
1171 | */ | 1172 | */ |
1172 | static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) | 1173 | static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) |
1173 | { | 1174 | { |
1174 | if (ieee80211_has_a4(hdr->frame_control)) | 1175 | if (ieee80211_has_a4(hdr->frame_control)) |
1175 | return hdr->addr4; | 1176 | return hdr->addr4; |
1176 | if (ieee80211_has_fromds(hdr->frame_control)) | 1177 | if (ieee80211_has_fromds(hdr->frame_control)) |
1177 | return hdr->addr3; | 1178 | return hdr->addr3; |
1178 | return hdr->addr2; | 1179 | return hdr->addr2; |
1179 | } | 1180 | } |
1180 | 1181 | ||
1181 | /** | 1182 | /** |
1182 | * ieee80211_get_DA - get pointer to DA | 1183 | * ieee80211_get_DA - get pointer to DA |
1183 | * @hdr: the frame | 1184 | * @hdr: the frame |
1184 | * | 1185 | * |
1185 | * Given an 802.11 frame, this function returns the offset | 1186 | * Given an 802.11 frame, this function returns the offset |
1186 | * to the destination address (DA). It does not verify that | 1187 | * to the destination address (DA). It does not verify that |
1187 | * the header is long enough to contain the address, and the | 1188 | * the header is long enough to contain the address, and the |
1188 | * header must be long enough to contain the frame control | 1189 | * header must be long enough to contain the frame control |
1189 | * field. | 1190 | * field. |
1190 | */ | 1191 | */ |
1191 | static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) | 1192 | static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) |
1192 | { | 1193 | { |
1193 | if (ieee80211_has_tods(hdr->frame_control)) | 1194 | if (ieee80211_has_tods(hdr->frame_control)) |
1194 | return hdr->addr3; | 1195 | return hdr->addr3; |
1195 | else | 1196 | else |
1196 | return hdr->addr1; | 1197 | return hdr->addr1; |
1197 | } | 1198 | } |
1198 | 1199 | ||
1199 | /** | 1200 | /** |
1200 | * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame | 1201 | * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame |
1201 | * @hdr: the frame (buffer must include at least the first octet of payload) | 1202 | * @hdr: the frame (buffer must include at least the first octet of payload) |
1202 | */ | 1203 | */ |
1203 | static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) | 1204 | static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) |
1204 | { | 1205 | { |
1205 | if (ieee80211_is_disassoc(hdr->frame_control) || | 1206 | if (ieee80211_is_disassoc(hdr->frame_control) || |
1206 | ieee80211_is_deauth(hdr->frame_control)) | 1207 | ieee80211_is_deauth(hdr->frame_control)) |
1207 | return true; | 1208 | return true; |
1208 | 1209 | ||
1209 | if (ieee80211_is_action(hdr->frame_control)) { | 1210 | if (ieee80211_is_action(hdr->frame_control)) { |
1210 | u8 *category; | 1211 | u8 *category; |
1211 | 1212 | ||
1212 | /* | 1213 | /* |
1213 | * Action frames, excluding Public Action frames, are Robust | 1214 | * Action frames, excluding Public Action frames, are Robust |
1214 | * Management Frames. However, if we are looking at a Protected | 1215 | * Management Frames. However, if we are looking at a Protected |
1215 | * frame, skip the check since the data may be encrypted and | 1216 | * frame, skip the check since the data may be encrypted and |
1216 | * the frame has already been found to be a Robust Management | 1217 | * the frame has already been found to be a Robust Management |
1217 | * Frame (by the other end). | 1218 | * Frame (by the other end). |
1218 | */ | 1219 | */ |
1219 | if (ieee80211_has_protected(hdr->frame_control)) | 1220 | if (ieee80211_has_protected(hdr->frame_control)) |
1220 | return true; | 1221 | return true; |
1221 | category = ((u8 *) hdr) + 24; | 1222 | category = ((u8 *) hdr) + 24; |
1222 | return *category != WLAN_CATEGORY_PUBLIC; | 1223 | return *category != WLAN_CATEGORY_PUBLIC; |
1223 | } | 1224 | } |
1224 | 1225 | ||
1225 | return false; | 1226 | return false; |
1226 | } | 1227 | } |
1227 | 1228 | ||
1228 | /** | 1229 | /** |
1229 | * ieee80211_fhss_chan_to_freq - get channel frequency | 1230 | * ieee80211_fhss_chan_to_freq - get channel frequency |
1230 | * @channel: the FHSS channel | 1231 | * @channel: the FHSS channel |
1231 | * | 1232 | * |
1232 | * Convert IEEE802.11 FHSS channel to frequency (MHz) | 1233 | * Convert IEEE802.11 FHSS channel to frequency (MHz) |
1233 | * Ref IEEE 802.11-2007 section 14.6 | 1234 | * Ref IEEE 802.11-2007 section 14.6 |
1234 | */ | 1235 | */ |
1235 | static inline int ieee80211_fhss_chan_to_freq(int channel) | 1236 | static inline int ieee80211_fhss_chan_to_freq(int channel) |
1236 | { | 1237 | { |
1237 | if ((channel > 1) && (channel < 96)) | 1238 | if ((channel > 1) && (channel < 96)) |
1238 | return channel + 2400; | 1239 | return channel + 2400; |
1239 | else | 1240 | else |
1240 | return -1; | 1241 | return -1; |
1241 | } | 1242 | } |
1242 | 1243 | ||
1243 | /** | 1244 | /** |
1244 | * ieee80211_freq_to_fhss_chan - get channel | 1245 | * ieee80211_freq_to_fhss_chan - get channel |
1245 | * @freq: the channels frequency | 1246 | * @freq: the channels frequency |
1246 | * | 1247 | * |
1247 | * Convert frequency (MHz) to IEEE802.11 FHSS channel | 1248 | * Convert frequency (MHz) to IEEE802.11 FHSS channel |
1248 | * Ref IEEE 802.11-2007 section 14.6 | 1249 | * Ref IEEE 802.11-2007 section 14.6 |
1249 | */ | 1250 | */ |
1250 | static inline int ieee80211_freq_to_fhss_chan(int freq) | 1251 | static inline int ieee80211_freq_to_fhss_chan(int freq) |
1251 | { | 1252 | { |
1252 | if ((freq > 2401) && (freq < 2496)) | 1253 | if ((freq > 2401) && (freq < 2496)) |
1253 | return freq - 2400; | 1254 | return freq - 2400; |
1254 | else | 1255 | else |
1255 | return -1; | 1256 | return -1; |
1256 | } | 1257 | } |
1257 | 1258 | ||
1258 | /** | 1259 | /** |
1259 | * ieee80211_dsss_chan_to_freq - get channel center frequency | 1260 | * ieee80211_dsss_chan_to_freq - get channel center frequency |
1260 | * @channel: the DSSS channel | 1261 | * @channel: the DSSS channel |
1261 | * | 1262 | * |
1262 | * Convert IEEE802.11 DSSS channel to the center frequency (MHz). | 1263 | * Convert IEEE802.11 DSSS channel to the center frequency (MHz). |
1263 | * Ref IEEE 802.11-2007 section 15.6 | 1264 | * Ref IEEE 802.11-2007 section 15.6 |
1264 | */ | 1265 | */ |
1265 | static inline int ieee80211_dsss_chan_to_freq(int channel) | 1266 | static inline int ieee80211_dsss_chan_to_freq(int channel) |
1266 | { | 1267 | { |
1267 | if ((channel > 0) && (channel < 14)) | 1268 | if ((channel > 0) && (channel < 14)) |
1268 | return 2407 + (channel * 5); | 1269 | return 2407 + (channel * 5); |
1269 | else if (channel == 14) | 1270 | else if (channel == 14) |
1270 | return 2484; | 1271 | return 2484; |
1271 | else | 1272 | else |
1272 | return -1; | 1273 | return -1; |
1273 | } | 1274 | } |
1274 | 1275 | ||
1275 | /** | 1276 | /** |
1276 | * ieee80211_freq_to_dsss_chan - get channel | 1277 | * ieee80211_freq_to_dsss_chan - get channel |
1277 | * @freq: the frequency | 1278 | * @freq: the frequency |
1278 | * | 1279 | * |
1279 | * Convert frequency (MHz) to IEEE802.11 DSSS channel | 1280 | * Convert frequency (MHz) to IEEE802.11 DSSS channel |
1280 | * Ref IEEE 802.11-2007 section 15.6 | 1281 | * Ref IEEE 802.11-2007 section 15.6 |
1281 | * | 1282 | * |
1282 | * This routine selects the channel with the closest center frequency. | 1283 | * This routine selects the channel with the closest center frequency. |
1283 | */ | 1284 | */ |
1284 | static inline int ieee80211_freq_to_dsss_chan(int freq) | 1285 | static inline int ieee80211_freq_to_dsss_chan(int freq) |
1285 | { | 1286 | { |
1286 | if ((freq >= 2410) && (freq < 2475)) | 1287 | if ((freq >= 2410) && (freq < 2475)) |
1287 | return (freq - 2405) / 5; | 1288 | return (freq - 2405) / 5; |
1288 | else if ((freq >= 2482) && (freq < 2487)) | 1289 | else if ((freq >= 2482) && (freq < 2487)) |
1289 | return 14; | 1290 | return 14; |
1290 | else | 1291 | else |
1291 | return -1; | 1292 | return -1; |
1292 | } | 1293 | } |
1293 | 1294 | ||
1294 | /* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back | 1295 | /* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back |
1295 | * Ref IEEE 802.11-2007 section 18.4.6.2 | 1296 | * Ref IEEE 802.11-2007 section 18.4.6.2 |
1296 | * | 1297 | * |
1297 | * The channels and frequencies are the same as those defined for DSSS | 1298 | * The channels and frequencies are the same as those defined for DSSS |
1298 | */ | 1299 | */ |
1299 | #define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) | 1300 | #define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) |
1300 | #define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) | 1301 | #define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) |
1301 | 1302 | ||
1302 | /* Convert IEEE802.11 ERP channel to frequency (MHz) and back | 1303 | /* Convert IEEE802.11 ERP channel to frequency (MHz) and back |
1303 | * Ref IEEE 802.11-2007 section 19.4.2 | 1304 | * Ref IEEE 802.11-2007 section 19.4.2 |
1304 | */ | 1305 | */ |
1305 | #define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) | 1306 | #define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) |
1306 | #define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) | 1307 | #define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) |
1307 | 1308 | ||
1308 | /** | 1309 | /** |
1309 | * ieee80211_ofdm_chan_to_freq - get channel center frequency | 1310 | * ieee80211_ofdm_chan_to_freq - get channel center frequency |
1310 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz | 1311 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz |
1311 | * @channel: the OFDM channel | 1312 | * @channel: the OFDM channel |
1312 | * | 1313 | * |
1313 | * Convert IEEE802.11 OFDM channel to center frequency (MHz) | 1314 | * Convert IEEE802.11 OFDM channel to center frequency (MHz) |
1314 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 | 1315 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 |
1315 | */ | 1316 | */ |
1316 | static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) | 1317 | static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) |
1317 | { | 1318 | { |
1318 | if ((channel > 0) && (channel <= 200) && | 1319 | if ((channel > 0) && (channel <= 200) && |
1319 | (s_freq >= 4000)) | 1320 | (s_freq >= 4000)) |
1320 | return s_freq + (channel * 5); | 1321 | return s_freq + (channel * 5); |
1321 | else | 1322 | else |
1322 | return -1; | 1323 | return -1; |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | /** | 1326 | /** |
1326 | * ieee80211_freq_to_ofdm_channel - get channel | 1327 | * ieee80211_freq_to_ofdm_channel - get channel |
1327 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz | 1328 | * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz |
1328 | * @freq: the frequency | 1329 | * @freq: the frequency |
1329 | * | 1330 | * |
1330 | * Convert frequency (MHz) to IEEE802.11 OFDM channel | 1331 | * Convert frequency (MHz) to IEEE802.11 OFDM channel |
1331 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 | 1332 | * Ref IEEE 802.11-2007 section 17.3.8.3.2 |
1332 | * | 1333 | * |
1333 | * This routine selects the channel with the closest center frequency. | 1334 | * This routine selects the channel with the closest center frequency. |
1334 | */ | 1335 | */ |
1335 | static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) | 1336 | static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) |
1336 | { | 1337 | { |
1337 | if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && | 1338 | if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && |
1338 | (s_freq >= 4000)) | 1339 | (s_freq >= 4000)) |
1339 | return (freq + 2 - s_freq) / 5; | 1340 | return (freq + 2 - s_freq) / 5; |
1340 | else | 1341 | else |
1341 | return -1; | 1342 | return -1; |
1342 | } | 1343 | } |
1343 | 1344 | ||
1344 | #endif /* LINUX_IEEE80211_H */ | 1345 | #endif /* LINUX_IEEE80211_H */ |
1345 | 1346 |
include/linux/nl80211.h
1 | #ifndef __LINUX_NL80211_H | 1 | #ifndef __LINUX_NL80211_H |
2 | #define __LINUX_NL80211_H | 2 | #define __LINUX_NL80211_H |
3 | /* | 3 | /* |
4 | * 802.11 netlink interface public header | 4 | * 802.11 netlink interface public header |
5 | * | 5 | * |
6 | * Copyright 2006, 2007, 2008 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2006, 2007, 2008 Johannes Berg <johannes@sipsolutions.net> |
7 | * Copyright 2008 Michael Wu <flamingice@sourmilk.net> | 7 | * Copyright 2008 Michael Wu <flamingice@sourmilk.net> |
8 | * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com> | 8 | * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com> |
9 | * Copyright 2008 Michael Buesch <mb@bu3sch.de> | 9 | * Copyright 2008 Michael Buesch <mb@bu3sch.de> |
10 | * Copyright 2008 Luis R. Rodriguez <lrodriguez@atheros.com> | 10 | * Copyright 2008 Luis R. Rodriguez <lrodriguez@atheros.com> |
11 | * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> | 11 | * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> |
12 | * Copyright 2008 Colin McCabe <colin@cozybit.com> | 12 | * Copyright 2008 Colin McCabe <colin@cozybit.com> |
13 | * | 13 | * |
14 | * Permission to use, copy, modify, and/or distribute this software for any | 14 | * Permission to use, copy, modify, and/or distribute this software for any |
15 | * purpose with or without fee is hereby granted, provided that the above | 15 | * purpose with or without fee is hereby granted, provided that the above |
16 | * copyright notice and this permission notice appear in all copies. | 16 | * copyright notice and this permission notice appear in all copies. |
17 | * | 17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 18 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
19 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 19 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
20 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 20 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
21 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 21 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
22 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 22 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
23 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 23 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
24 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 24 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * DOC: Station handling | 29 | * DOC: Station handling |
30 | * | 30 | * |
31 | * Stations are added per interface, but a special case exists with VLAN | 31 | * Stations are added per interface, but a special case exists with VLAN |
32 | * interfaces. When a station is bound to an AP interface, it may be moved | 32 | * interfaces. When a station is bound to an AP interface, it may be moved |
33 | * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). | 33 | * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). |
34 | * The station is still assumed to belong to the AP interface it was added | 34 | * The station is still assumed to belong to the AP interface it was added |
35 | * to. | 35 | * to. |
36 | * | 36 | * |
37 | * TODO: need more info? | 37 | * TODO: need more info? |
38 | */ | 38 | */ |
39 | 39 | ||
40 | /** | 40 | /** |
41 | * enum nl80211_commands - supported nl80211 commands | 41 | * enum nl80211_commands - supported nl80211 commands |
42 | * | 42 | * |
43 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors | 43 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors |
44 | * | 44 | * |
45 | * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request | 45 | * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request |
46 | * to get a list of all present wiphys. | 46 | * to get a list of all present wiphys. |
47 | * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or | 47 | * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or |
48 | * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, | 48 | * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, |
49 | * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or | 49 | * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or |
50 | * %NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET. | 50 | * %NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET. |
51 | * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request | 51 | * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request |
52 | * or rename notification. Has attributes %NL80211_ATTR_WIPHY and | 52 | * or rename notification. Has attributes %NL80211_ATTR_WIPHY and |
53 | * %NL80211_ATTR_WIPHY_NAME. | 53 | * %NL80211_ATTR_WIPHY_NAME. |
54 | * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes | 54 | * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes |
55 | * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. | 55 | * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. |
56 | * | 56 | * |
57 | * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; | 57 | * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; |
58 | * either a dump request on a %NL80211_ATTR_WIPHY or a specific get | 58 | * either a dump request on a %NL80211_ATTR_WIPHY or a specific get |
59 | * on an %NL80211_ATTR_IFINDEX is supported. | 59 | * on an %NL80211_ATTR_IFINDEX is supported. |
60 | * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires | 60 | * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires |
61 | * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. | 61 | * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. |
62 | * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response | 62 | * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response |
63 | * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, | 63 | * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, |
64 | * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also | 64 | * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also |
65 | * be sent from userspace to request creation of a new virtual interface, | 65 | * be sent from userspace to request creation of a new virtual interface, |
66 | * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and | 66 | * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and |
67 | * %NL80211_ATTR_IFNAME. | 67 | * %NL80211_ATTR_IFNAME. |
68 | * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes | 68 | * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes |
69 | * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from | 69 | * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from |
70 | * userspace to request deletion of a virtual interface, then requires | 70 | * userspace to request deletion of a virtual interface, then requires |
71 | * attribute %NL80211_ATTR_IFINDEX. | 71 | * attribute %NL80211_ATTR_IFINDEX. |
72 | * | 72 | * |
73 | * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified | 73 | * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified |
74 | * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. | 74 | * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. |
75 | * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT or | 75 | * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, |
76 | * %NL80211_ATTR_KEY_THRESHOLD. | 76 | * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. |
77 | * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, | 77 | * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, |
78 | * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER | 78 | * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER |
79 | * attributes. | 79 | * attributes. |
80 | * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX | 80 | * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX |
81 | * or %NL80211_ATTR_MAC. | 81 | * or %NL80211_ATTR_MAC. |
82 | * | 82 | * |
83 | * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a | 83 | * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a |
84 | * %NL80222_CMD_NEW_BEACON message) | 84 | * %NL80222_CMD_NEW_BEACON message) |
85 | * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface | 85 | * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface |
86 | * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, | 86 | * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, |
87 | * %NL80211_BEACON_HEAD and %NL80211_BEACON_TAIL attributes. | 87 | * %NL80211_BEACON_HEAD and %NL80211_BEACON_TAIL attributes. |
88 | * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, | 88 | * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, |
89 | * parameters are like for %NL80211_CMD_SET_BEACON. | 89 | * parameters are like for %NL80211_CMD_SET_BEACON. |
90 | * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it | 90 | * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it |
91 | * | 91 | * |
92 | * @NL80211_CMD_GET_STATION: Get station attributes for station identified by | 92 | * @NL80211_CMD_GET_STATION: Get station attributes for station identified by |
93 | * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. | 93 | * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. |
94 | * @NL80211_CMD_SET_STATION: Set station attributes for station identified by | 94 | * @NL80211_CMD_SET_STATION: Set station attributes for station identified by |
95 | * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. | 95 | * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. |
96 | * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the | 96 | * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the |
97 | * the interface identified by %NL80211_ATTR_IFINDEX. | 97 | * the interface identified by %NL80211_ATTR_IFINDEX. |
98 | * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC | 98 | * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC |
99 | * or, if no MAC address given, all stations, on the interface identified | 99 | * or, if no MAC address given, all stations, on the interface identified |
100 | * by %NL80211_ATTR_IFINDEX. | 100 | * by %NL80211_ATTR_IFINDEX. |
101 | * | 101 | * |
102 | * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to | 102 | * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to |
103 | * destination %NL80211_ATTR_MAC on the interface identified by | 103 | * destination %NL80211_ATTR_MAC on the interface identified by |
104 | * %NL80211_ATTR_IFINDEX. | 104 | * %NL80211_ATTR_IFINDEX. |
105 | * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to | 105 | * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to |
106 | * destination %NL80211_ATTR_MAC on the interface identified by | 106 | * destination %NL80211_ATTR_MAC on the interface identified by |
107 | * %NL80211_ATTR_IFINDEX. | 107 | * %NL80211_ATTR_IFINDEX. |
108 | * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the | 108 | * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the |
109 | * the interface identified by %NL80211_ATTR_IFINDEX. | 109 | * the interface identified by %NL80211_ATTR_IFINDEX. |
110 | * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC | 110 | * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC |
111 | * or, if no MAC address given, all mesh paths, on the interface identified | 111 | * or, if no MAC address given, all mesh paths, on the interface identified |
112 | * by %NL80211_ATTR_IFINDEX. | 112 | * by %NL80211_ATTR_IFINDEX. |
113 | * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by | 113 | * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by |
114 | * %NL80211_ATTR_IFINDEX. | 114 | * %NL80211_ATTR_IFINDEX. |
115 | * | 115 | * |
116 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command | 116 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command |
117 | * after being queried by the kernel. CRDA replies by sending a regulatory | 117 | * after being queried by the kernel. CRDA replies by sending a regulatory |
118 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our | 118 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our |
119 | * current alpha2 if it found a match. It also provides | 119 | * current alpha2 if it found a match. It also provides |
120 | * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each | 120 | * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each |
121 | * regulatory rule is a nested set of attributes given by | 121 | * regulatory rule is a nested set of attributes given by |
122 | * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and | 122 | * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and |
123 | * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by | 123 | * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by |
124 | * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and | 124 | * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and |
125 | * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. | 125 | * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. |
126 | * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain | 126 | * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain |
127 | * to the the specified ISO/IEC 3166-1 alpha2 country code. The core will | 127 | * to the the specified ISO/IEC 3166-1 alpha2 country code. The core will |
128 | * store this as a valid request and then query userspace for it. | 128 | * store this as a valid request and then query userspace for it. |
129 | * | 129 | * |
130 | * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the | 130 | * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the |
131 | * interface identified by %NL80211_ATTR_IFINDEX | 131 | * interface identified by %NL80211_ATTR_IFINDEX |
132 | * | 132 | * |
133 | * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the | 133 | * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the |
134 | * interface identified by %NL80211_ATTR_IFINDEX | 134 | * interface identified by %NL80211_ATTR_IFINDEX |
135 | * | 135 | * |
136 | * @NL80211_CMD_MAX: highest used command number | 136 | * @NL80211_CMD_MAX: highest used command number |
137 | * @__NL80211_CMD_AFTER_LAST: internal use | 137 | * @__NL80211_CMD_AFTER_LAST: internal use |
138 | */ | 138 | */ |
139 | enum nl80211_commands { | 139 | enum nl80211_commands { |
140 | /* don't change the order or add anything inbetween, this is ABI! */ | 140 | /* don't change the order or add anything inbetween, this is ABI! */ |
141 | NL80211_CMD_UNSPEC, | 141 | NL80211_CMD_UNSPEC, |
142 | 142 | ||
143 | NL80211_CMD_GET_WIPHY, /* can dump */ | 143 | NL80211_CMD_GET_WIPHY, /* can dump */ |
144 | NL80211_CMD_SET_WIPHY, | 144 | NL80211_CMD_SET_WIPHY, |
145 | NL80211_CMD_NEW_WIPHY, | 145 | NL80211_CMD_NEW_WIPHY, |
146 | NL80211_CMD_DEL_WIPHY, | 146 | NL80211_CMD_DEL_WIPHY, |
147 | 147 | ||
148 | NL80211_CMD_GET_INTERFACE, /* can dump */ | 148 | NL80211_CMD_GET_INTERFACE, /* can dump */ |
149 | NL80211_CMD_SET_INTERFACE, | 149 | NL80211_CMD_SET_INTERFACE, |
150 | NL80211_CMD_NEW_INTERFACE, | 150 | NL80211_CMD_NEW_INTERFACE, |
151 | NL80211_CMD_DEL_INTERFACE, | 151 | NL80211_CMD_DEL_INTERFACE, |
152 | 152 | ||
153 | NL80211_CMD_GET_KEY, | 153 | NL80211_CMD_GET_KEY, |
154 | NL80211_CMD_SET_KEY, | 154 | NL80211_CMD_SET_KEY, |
155 | NL80211_CMD_NEW_KEY, | 155 | NL80211_CMD_NEW_KEY, |
156 | NL80211_CMD_DEL_KEY, | 156 | NL80211_CMD_DEL_KEY, |
157 | 157 | ||
158 | NL80211_CMD_GET_BEACON, | 158 | NL80211_CMD_GET_BEACON, |
159 | NL80211_CMD_SET_BEACON, | 159 | NL80211_CMD_SET_BEACON, |
160 | NL80211_CMD_NEW_BEACON, | 160 | NL80211_CMD_NEW_BEACON, |
161 | NL80211_CMD_DEL_BEACON, | 161 | NL80211_CMD_DEL_BEACON, |
162 | 162 | ||
163 | NL80211_CMD_GET_STATION, | 163 | NL80211_CMD_GET_STATION, |
164 | NL80211_CMD_SET_STATION, | 164 | NL80211_CMD_SET_STATION, |
165 | NL80211_CMD_NEW_STATION, | 165 | NL80211_CMD_NEW_STATION, |
166 | NL80211_CMD_DEL_STATION, | 166 | NL80211_CMD_DEL_STATION, |
167 | 167 | ||
168 | NL80211_CMD_GET_MPATH, | 168 | NL80211_CMD_GET_MPATH, |
169 | NL80211_CMD_SET_MPATH, | 169 | NL80211_CMD_SET_MPATH, |
170 | NL80211_CMD_NEW_MPATH, | 170 | NL80211_CMD_NEW_MPATH, |
171 | NL80211_CMD_DEL_MPATH, | 171 | NL80211_CMD_DEL_MPATH, |
172 | 172 | ||
173 | NL80211_CMD_SET_BSS, | 173 | NL80211_CMD_SET_BSS, |
174 | 174 | ||
175 | NL80211_CMD_SET_REG, | 175 | NL80211_CMD_SET_REG, |
176 | NL80211_CMD_REQ_SET_REG, | 176 | NL80211_CMD_REQ_SET_REG, |
177 | 177 | ||
178 | NL80211_CMD_GET_MESH_PARAMS, | 178 | NL80211_CMD_GET_MESH_PARAMS, |
179 | NL80211_CMD_SET_MESH_PARAMS, | 179 | NL80211_CMD_SET_MESH_PARAMS, |
180 | 180 | ||
181 | /* add new commands above here */ | 181 | /* add new commands above here */ |
182 | 182 | ||
183 | /* used to define NL80211_CMD_MAX below */ | 183 | /* used to define NL80211_CMD_MAX below */ |
184 | __NL80211_CMD_AFTER_LAST, | 184 | __NL80211_CMD_AFTER_LAST, |
185 | NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 | 185 | NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 |
186 | }; | 186 | }; |
187 | 187 | ||
188 | /* | 188 | /* |
189 | * Allow user space programs to use #ifdef on new commands by defining them | 189 | * Allow user space programs to use #ifdef on new commands by defining them |
190 | * here | 190 | * here |
191 | */ | 191 | */ |
192 | #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS | 192 | #define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS |
193 | 193 | ||
194 | /** | 194 | /** |
195 | * enum nl80211_attrs - nl80211 netlink attributes | 195 | * enum nl80211_attrs - nl80211 netlink attributes |
196 | * | 196 | * |
197 | * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors | 197 | * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors |
198 | * | 198 | * |
199 | * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. | 199 | * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. |
200 | * /sys/class/ieee80211/<phyname>/index | 200 | * /sys/class/ieee80211/<phyname>/index |
201 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) | 201 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) |
202 | * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters | 202 | * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters |
203 | * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz | 203 | * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz |
204 | * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ | 204 | * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ |
205 | * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): | 205 | * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): |
206 | * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including | 206 | * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including |
207 | * this attribute) | 207 | * this attribute) |
208 | * NL80211_CHAN_HT20 = HT20 only | 208 | * NL80211_CHAN_HT20 = HT20 only |
209 | * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel | 209 | * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel |
210 | * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel | 210 | * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel |
211 | * | 211 | * |
212 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on | 212 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on |
213 | * @NL80211_ATTR_IFNAME: network interface name | 213 | * @NL80211_ATTR_IFNAME: network interface name |
214 | * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype | 214 | * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype |
215 | * | 215 | * |
216 | * @NL80211_ATTR_MAC: MAC address (various uses) | 216 | * @NL80211_ATTR_MAC: MAC address (various uses) |
217 | * | 217 | * |
218 | * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of | 218 | * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of |
219 | * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC | 219 | * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC |
220 | * keys | 220 | * keys |
221 | * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) | 221 | * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) |
222 | * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 | 222 | * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 |
223 | * section 7.3.2.25.1, e.g. 0x000FAC04) | 223 | * section 7.3.2.25.1, e.g. 0x000FAC04) |
224 | * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and | 224 | * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and |
225 | * CCMP keys, each six bytes in little endian | 225 | * CCMP keys, each six bytes in little endian |
226 | * | 226 | * |
227 | * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU | 227 | * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU |
228 | * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing | 228 | * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing |
229 | * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE | 229 | * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE |
230 | * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE | 230 | * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE |
231 | * | 231 | * |
232 | * @NL80211_ATTR_STA_AID: Association ID for the station (u16) | 232 | * @NL80211_ATTR_STA_AID: Association ID for the station (u16) |
233 | * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of | 233 | * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of |
234 | * &enum nl80211_sta_flags. | 234 | * &enum nl80211_sta_flags. |
235 | * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by | 235 | * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by |
236 | * IEEE 802.11 7.3.1.6 (u16). | 236 | * IEEE 802.11 7.3.1.6 (u16). |
237 | * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported | 237 | * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported |
238 | * rates as defined by IEEE 802.11 7.3.2.2 but without the length | 238 | * rates as defined by IEEE 802.11 7.3.2.2 but without the length |
239 | * restriction (at most %NL80211_MAX_SUPP_RATES). | 239 | * restriction (at most %NL80211_MAX_SUPP_RATES). |
240 | * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station | 240 | * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station |
241 | * to, or the AP interface the station was originally added to to. | 241 | * to, or the AP interface the station was originally added to to. |
242 | * @NL80211_ATTR_STA_INFO: information about a station, part of station info | 242 | * @NL80211_ATTR_STA_INFO: information about a station, part of station info |
243 | * given for %NL80211_CMD_GET_STATION, nested attribute containing | 243 | * given for %NL80211_CMD_GET_STATION, nested attribute containing |
244 | * info as possible, see &enum nl80211_sta_info. | 244 | * info as possible, see &enum nl80211_sta_info. |
245 | * | 245 | * |
246 | * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, | 246 | * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, |
247 | * consisting of a nested array. | 247 | * consisting of a nested array. |
248 | * | 248 | * |
249 | * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). | 249 | * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). |
250 | * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link. | 250 | * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link. |
251 | * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. | 251 | * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. |
252 | * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path | 252 | * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path |
253 | * info given for %NL80211_CMD_GET_MPATH, nested attribute described at | 253 | * info given for %NL80211_CMD_GET_MPATH, nested attribute described at |
254 | * &enum nl80211_mpath_info. | 254 | * &enum nl80211_mpath_info. |
255 | * | 255 | * |
256 | * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of | 256 | * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of |
257 | * &enum nl80211_mntr_flags. | 257 | * &enum nl80211_mntr_flags. |
258 | * | 258 | * |
259 | * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the | 259 | * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the |
260 | * current regulatory domain should be set to or is already set to. | 260 | * current regulatory domain should be set to or is already set to. |
261 | * For example, 'CR', for Costa Rica. This attribute is used by the kernel | 261 | * For example, 'CR', for Costa Rica. This attribute is used by the kernel |
262 | * to query the CRDA to retrieve one regulatory domain. This attribute can | 262 | * to query the CRDA to retrieve one regulatory domain. This attribute can |
263 | * also be used by userspace to query the kernel for the currently set | 263 | * also be used by userspace to query the kernel for the currently set |
264 | * regulatory domain. We chose an alpha2 as that is also used by the | 264 | * regulatory domain. We chose an alpha2 as that is also used by the |
265 | * IEEE-802.11d country information element to identify a country. | 265 | * IEEE-802.11d country information element to identify a country. |
266 | * Users can also simply ask the wireless core to set regulatory domain | 266 | * Users can also simply ask the wireless core to set regulatory domain |
267 | * to a specific alpha2. | 267 | * to a specific alpha2. |
268 | * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory | 268 | * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory |
269 | * rules. | 269 | * rules. |
270 | * | 270 | * |
271 | * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) | 271 | * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) |
272 | * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled | 272 | * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled |
273 | * (u8, 0 or 1) | 273 | * (u8, 0 or 1) |
274 | * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled | 274 | * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled |
275 | * (u8, 0 or 1) | 275 | * (u8, 0 or 1) |
276 | * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic | 276 | * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic |
277 | * rates in format defined by IEEE 802.11 7.3.2.2 but without the length | 277 | * rates in format defined by IEEE 802.11 7.3.2.2 but without the length |
278 | * restriction (at most %NL80211_MAX_SUPP_RATES). | 278 | * restriction (at most %NL80211_MAX_SUPP_RATES). |
279 | * | 279 | * |
280 | * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from | 280 | * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from |
281 | * association request when used with NL80211_CMD_NEW_STATION) | 281 | * association request when used with NL80211_CMD_NEW_STATION) |
282 | * | 282 | * |
283 | * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all | 283 | * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all |
284 | * supported interface types, each a flag attribute with the number | 284 | * supported interface types, each a flag attribute with the number |
285 | * of the interface mode. | 285 | * of the interface mode. |
286 | * | 286 | * |
287 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 287 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
288 | * @__NL80211_ATTR_AFTER_LAST: internal use | 288 | * @__NL80211_ATTR_AFTER_LAST: internal use |
289 | */ | 289 | */ |
290 | enum nl80211_attrs { | 290 | enum nl80211_attrs { |
291 | /* don't change the order or add anything inbetween, this is ABI! */ | 291 | /* don't change the order or add anything inbetween, this is ABI! */ |
292 | NL80211_ATTR_UNSPEC, | 292 | NL80211_ATTR_UNSPEC, |
293 | 293 | ||
294 | NL80211_ATTR_WIPHY, | 294 | NL80211_ATTR_WIPHY, |
295 | NL80211_ATTR_WIPHY_NAME, | 295 | NL80211_ATTR_WIPHY_NAME, |
296 | 296 | ||
297 | NL80211_ATTR_IFINDEX, | 297 | NL80211_ATTR_IFINDEX, |
298 | NL80211_ATTR_IFNAME, | 298 | NL80211_ATTR_IFNAME, |
299 | NL80211_ATTR_IFTYPE, | 299 | NL80211_ATTR_IFTYPE, |
300 | 300 | ||
301 | NL80211_ATTR_MAC, | 301 | NL80211_ATTR_MAC, |
302 | 302 | ||
303 | NL80211_ATTR_KEY_DATA, | 303 | NL80211_ATTR_KEY_DATA, |
304 | NL80211_ATTR_KEY_IDX, | 304 | NL80211_ATTR_KEY_IDX, |
305 | NL80211_ATTR_KEY_CIPHER, | 305 | NL80211_ATTR_KEY_CIPHER, |
306 | NL80211_ATTR_KEY_SEQ, | 306 | NL80211_ATTR_KEY_SEQ, |
307 | NL80211_ATTR_KEY_DEFAULT, | 307 | NL80211_ATTR_KEY_DEFAULT, |
308 | 308 | ||
309 | NL80211_ATTR_BEACON_INTERVAL, | 309 | NL80211_ATTR_BEACON_INTERVAL, |
310 | NL80211_ATTR_DTIM_PERIOD, | 310 | NL80211_ATTR_DTIM_PERIOD, |
311 | NL80211_ATTR_BEACON_HEAD, | 311 | NL80211_ATTR_BEACON_HEAD, |
312 | NL80211_ATTR_BEACON_TAIL, | 312 | NL80211_ATTR_BEACON_TAIL, |
313 | 313 | ||
314 | NL80211_ATTR_STA_AID, | 314 | NL80211_ATTR_STA_AID, |
315 | NL80211_ATTR_STA_FLAGS, | 315 | NL80211_ATTR_STA_FLAGS, |
316 | NL80211_ATTR_STA_LISTEN_INTERVAL, | 316 | NL80211_ATTR_STA_LISTEN_INTERVAL, |
317 | NL80211_ATTR_STA_SUPPORTED_RATES, | 317 | NL80211_ATTR_STA_SUPPORTED_RATES, |
318 | NL80211_ATTR_STA_VLAN, | 318 | NL80211_ATTR_STA_VLAN, |
319 | NL80211_ATTR_STA_INFO, | 319 | NL80211_ATTR_STA_INFO, |
320 | 320 | ||
321 | NL80211_ATTR_WIPHY_BANDS, | 321 | NL80211_ATTR_WIPHY_BANDS, |
322 | 322 | ||
323 | NL80211_ATTR_MNTR_FLAGS, | 323 | NL80211_ATTR_MNTR_FLAGS, |
324 | 324 | ||
325 | NL80211_ATTR_MESH_ID, | 325 | NL80211_ATTR_MESH_ID, |
326 | NL80211_ATTR_STA_PLINK_ACTION, | 326 | NL80211_ATTR_STA_PLINK_ACTION, |
327 | NL80211_ATTR_MPATH_NEXT_HOP, | 327 | NL80211_ATTR_MPATH_NEXT_HOP, |
328 | NL80211_ATTR_MPATH_INFO, | 328 | NL80211_ATTR_MPATH_INFO, |
329 | 329 | ||
330 | NL80211_ATTR_BSS_CTS_PROT, | 330 | NL80211_ATTR_BSS_CTS_PROT, |
331 | NL80211_ATTR_BSS_SHORT_PREAMBLE, | 331 | NL80211_ATTR_BSS_SHORT_PREAMBLE, |
332 | NL80211_ATTR_BSS_SHORT_SLOT_TIME, | 332 | NL80211_ATTR_BSS_SHORT_SLOT_TIME, |
333 | 333 | ||
334 | NL80211_ATTR_HT_CAPABILITY, | 334 | NL80211_ATTR_HT_CAPABILITY, |
335 | 335 | ||
336 | NL80211_ATTR_SUPPORTED_IFTYPES, | 336 | NL80211_ATTR_SUPPORTED_IFTYPES, |
337 | 337 | ||
338 | NL80211_ATTR_REG_ALPHA2, | 338 | NL80211_ATTR_REG_ALPHA2, |
339 | NL80211_ATTR_REG_RULES, | 339 | NL80211_ATTR_REG_RULES, |
340 | 340 | ||
341 | NL80211_ATTR_MESH_PARAMS, | 341 | NL80211_ATTR_MESH_PARAMS, |
342 | 342 | ||
343 | NL80211_ATTR_BSS_BASIC_RATES, | 343 | NL80211_ATTR_BSS_BASIC_RATES, |
344 | 344 | ||
345 | NL80211_ATTR_WIPHY_TXQ_PARAMS, | 345 | NL80211_ATTR_WIPHY_TXQ_PARAMS, |
346 | NL80211_ATTR_WIPHY_FREQ, | 346 | NL80211_ATTR_WIPHY_FREQ, |
347 | NL80211_ATTR_WIPHY_CHANNEL_TYPE, | 347 | NL80211_ATTR_WIPHY_CHANNEL_TYPE, |
348 | |||
349 | NL80211_ATTR_KEY_DEFAULT_MGMT, | ||
348 | 350 | ||
349 | /* add attributes here, update the policy in nl80211.c */ | 351 | /* add attributes here, update the policy in nl80211.c */ |
350 | 352 | ||
351 | __NL80211_ATTR_AFTER_LAST, | 353 | __NL80211_ATTR_AFTER_LAST, |
352 | NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 | 354 | NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 |
353 | }; | 355 | }; |
354 | 356 | ||
355 | /* | 357 | /* |
356 | * Allow user space programs to use #ifdef on new attributes by defining them | 358 | * Allow user space programs to use #ifdef on new attributes by defining them |
357 | * here | 359 | * here |
358 | */ | 360 | */ |
359 | #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY | 361 | #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY |
360 | #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES | 362 | #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES |
361 | #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS | 363 | #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS |
362 | #define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ | 364 | #define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ |
363 | #define NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET | 365 | #define NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET |
364 | 366 | ||
365 | #define NL80211_MAX_SUPP_RATES 32 | 367 | #define NL80211_MAX_SUPP_RATES 32 |
366 | #define NL80211_MAX_SUPP_REG_RULES 32 | 368 | #define NL80211_MAX_SUPP_REG_RULES 32 |
367 | #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 | 369 | #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 |
368 | #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 | 370 | #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 |
369 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 | 371 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 |
370 | #define NL80211_HT_CAPABILITY_LEN 26 | 372 | #define NL80211_HT_CAPABILITY_LEN 26 |
371 | 373 | ||
372 | /** | 374 | /** |
373 | * enum nl80211_iftype - (virtual) interface types | 375 | * enum nl80211_iftype - (virtual) interface types |
374 | * | 376 | * |
375 | * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides | 377 | * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides |
376 | * @NL80211_IFTYPE_ADHOC: independent BSS member | 378 | * @NL80211_IFTYPE_ADHOC: independent BSS member |
377 | * @NL80211_IFTYPE_STATION: managed BSS member | 379 | * @NL80211_IFTYPE_STATION: managed BSS member |
378 | * @NL80211_IFTYPE_AP: access point | 380 | * @NL80211_IFTYPE_AP: access point |
379 | * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points | 381 | * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points |
380 | * @NL80211_IFTYPE_WDS: wireless distribution interface | 382 | * @NL80211_IFTYPE_WDS: wireless distribution interface |
381 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames | 383 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames |
382 | * @NL80211_IFTYPE_MESH_POINT: mesh point | 384 | * @NL80211_IFTYPE_MESH_POINT: mesh point |
383 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined | 385 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined |
384 | * @__NL80211_IFTYPE_AFTER_LAST: internal use | 386 | * @__NL80211_IFTYPE_AFTER_LAST: internal use |
385 | * | 387 | * |
386 | * These values are used with the %NL80211_ATTR_IFTYPE | 388 | * These values are used with the %NL80211_ATTR_IFTYPE |
387 | * to set the type of an interface. | 389 | * to set the type of an interface. |
388 | * | 390 | * |
389 | */ | 391 | */ |
390 | enum nl80211_iftype { | 392 | enum nl80211_iftype { |
391 | NL80211_IFTYPE_UNSPECIFIED, | 393 | NL80211_IFTYPE_UNSPECIFIED, |
392 | NL80211_IFTYPE_ADHOC, | 394 | NL80211_IFTYPE_ADHOC, |
393 | NL80211_IFTYPE_STATION, | 395 | NL80211_IFTYPE_STATION, |
394 | NL80211_IFTYPE_AP, | 396 | NL80211_IFTYPE_AP, |
395 | NL80211_IFTYPE_AP_VLAN, | 397 | NL80211_IFTYPE_AP_VLAN, |
396 | NL80211_IFTYPE_WDS, | 398 | NL80211_IFTYPE_WDS, |
397 | NL80211_IFTYPE_MONITOR, | 399 | NL80211_IFTYPE_MONITOR, |
398 | NL80211_IFTYPE_MESH_POINT, | 400 | NL80211_IFTYPE_MESH_POINT, |
399 | 401 | ||
400 | /* keep last */ | 402 | /* keep last */ |
401 | __NL80211_IFTYPE_AFTER_LAST, | 403 | __NL80211_IFTYPE_AFTER_LAST, |
402 | NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 | 404 | NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 |
403 | }; | 405 | }; |
404 | 406 | ||
405 | /** | 407 | /** |
406 | * enum nl80211_sta_flags - station flags | 408 | * enum nl80211_sta_flags - station flags |
407 | * | 409 | * |
408 | * Station flags. When a station is added to an AP interface, it is | 410 | * Station flags. When a station is added to an AP interface, it is |
409 | * assumed to be already associated (and hence authenticated.) | 411 | * assumed to be already associated (and hence authenticated.) |
410 | * | 412 | * |
411 | * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) | 413 | * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) |
412 | * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames | 414 | * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames |
413 | * with short barker preamble | 415 | * with short barker preamble |
414 | * @NL80211_STA_FLAG_WME: station is WME/QoS capable | 416 | * @NL80211_STA_FLAG_WME: station is WME/QoS capable |
415 | * @NL80211_STA_FLAG_MFP: station uses management frame protection | 417 | * @NL80211_STA_FLAG_MFP: station uses management frame protection |
416 | */ | 418 | */ |
417 | enum nl80211_sta_flags { | 419 | enum nl80211_sta_flags { |
418 | __NL80211_STA_FLAG_INVALID, | 420 | __NL80211_STA_FLAG_INVALID, |
419 | NL80211_STA_FLAG_AUTHORIZED, | 421 | NL80211_STA_FLAG_AUTHORIZED, |
420 | NL80211_STA_FLAG_SHORT_PREAMBLE, | 422 | NL80211_STA_FLAG_SHORT_PREAMBLE, |
421 | NL80211_STA_FLAG_WME, | 423 | NL80211_STA_FLAG_WME, |
422 | NL80211_STA_FLAG_MFP, | 424 | NL80211_STA_FLAG_MFP, |
423 | 425 | ||
424 | /* keep last */ | 426 | /* keep last */ |
425 | __NL80211_STA_FLAG_AFTER_LAST, | 427 | __NL80211_STA_FLAG_AFTER_LAST, |
426 | NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 | 428 | NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 |
427 | }; | 429 | }; |
428 | 430 | ||
429 | /** | 431 | /** |
430 | * enum nl80211_rate_info - bitrate information | 432 | * enum nl80211_rate_info - bitrate information |
431 | * | 433 | * |
432 | * These attribute types are used with %NL80211_STA_INFO_TXRATE | 434 | * These attribute types are used with %NL80211_STA_INFO_TXRATE |
433 | * when getting information about the bitrate of a station. | 435 | * when getting information about the bitrate of a station. |
434 | * | 436 | * |
435 | * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved | 437 | * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved |
436 | * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) | 438 | * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) |
437 | * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) | 439 | * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) |
438 | * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate | 440 | * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate |
439 | * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval | 441 | * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval |
440 | * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined | 442 | * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined |
441 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use | 443 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use |
442 | */ | 444 | */ |
443 | enum nl80211_rate_info { | 445 | enum nl80211_rate_info { |
444 | __NL80211_RATE_INFO_INVALID, | 446 | __NL80211_RATE_INFO_INVALID, |
445 | NL80211_RATE_INFO_BITRATE, | 447 | NL80211_RATE_INFO_BITRATE, |
446 | NL80211_RATE_INFO_MCS, | 448 | NL80211_RATE_INFO_MCS, |
447 | NL80211_RATE_INFO_40_MHZ_WIDTH, | 449 | NL80211_RATE_INFO_40_MHZ_WIDTH, |
448 | NL80211_RATE_INFO_SHORT_GI, | 450 | NL80211_RATE_INFO_SHORT_GI, |
449 | 451 | ||
450 | /* keep last */ | 452 | /* keep last */ |
451 | __NL80211_RATE_INFO_AFTER_LAST, | 453 | __NL80211_RATE_INFO_AFTER_LAST, |
452 | NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 | 454 | NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 |
453 | }; | 455 | }; |
454 | 456 | ||
455 | /** | 457 | /** |
456 | * enum nl80211_sta_info - station information | 458 | * enum nl80211_sta_info - station information |
457 | * | 459 | * |
458 | * These attribute types are used with %NL80211_ATTR_STA_INFO | 460 | * These attribute types are used with %NL80211_ATTR_STA_INFO |
459 | * when getting information about a station. | 461 | * when getting information about a station. |
460 | * | 462 | * |
461 | * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved | 463 | * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved |
462 | * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) | 464 | * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) |
463 | * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) | 465 | * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) |
464 | * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) | 466 | * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) |
465 | * @__NL80211_STA_INFO_AFTER_LAST: internal | 467 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
466 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 468 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
467 | * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) | 469 | * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) |
468 | * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute | 470 | * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute |
469 | * containing info as possible, see &enum nl80211_sta_info_txrate. | 471 | * containing info as possible, see &enum nl80211_sta_info_txrate. |
470 | */ | 472 | */ |
471 | enum nl80211_sta_info { | 473 | enum nl80211_sta_info { |
472 | __NL80211_STA_INFO_INVALID, | 474 | __NL80211_STA_INFO_INVALID, |
473 | NL80211_STA_INFO_INACTIVE_TIME, | 475 | NL80211_STA_INFO_INACTIVE_TIME, |
474 | NL80211_STA_INFO_RX_BYTES, | 476 | NL80211_STA_INFO_RX_BYTES, |
475 | NL80211_STA_INFO_TX_BYTES, | 477 | NL80211_STA_INFO_TX_BYTES, |
476 | NL80211_STA_INFO_LLID, | 478 | NL80211_STA_INFO_LLID, |
477 | NL80211_STA_INFO_PLID, | 479 | NL80211_STA_INFO_PLID, |
478 | NL80211_STA_INFO_PLINK_STATE, | 480 | NL80211_STA_INFO_PLINK_STATE, |
479 | NL80211_STA_INFO_SIGNAL, | 481 | NL80211_STA_INFO_SIGNAL, |
480 | NL80211_STA_INFO_TX_BITRATE, | 482 | NL80211_STA_INFO_TX_BITRATE, |
481 | 483 | ||
482 | /* keep last */ | 484 | /* keep last */ |
483 | __NL80211_STA_INFO_AFTER_LAST, | 485 | __NL80211_STA_INFO_AFTER_LAST, |
484 | NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 | 486 | NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 |
485 | }; | 487 | }; |
486 | 488 | ||
487 | /** | 489 | /** |
488 | * enum nl80211_mpath_flags - nl80211 mesh path flags | 490 | * enum nl80211_mpath_flags - nl80211 mesh path flags |
489 | * | 491 | * |
490 | * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active | 492 | * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active |
491 | * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running | 493 | * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running |
492 | * @NL80211_MPATH_FLAG_DSN_VALID: the mesh path contains a valid DSN | 494 | * @NL80211_MPATH_FLAG_DSN_VALID: the mesh path contains a valid DSN |
493 | * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set | 495 | * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set |
494 | * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded | 496 | * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded |
495 | */ | 497 | */ |
496 | enum nl80211_mpath_flags { | 498 | enum nl80211_mpath_flags { |
497 | NL80211_MPATH_FLAG_ACTIVE = 1<<0, | 499 | NL80211_MPATH_FLAG_ACTIVE = 1<<0, |
498 | NL80211_MPATH_FLAG_RESOLVING = 1<<1, | 500 | NL80211_MPATH_FLAG_RESOLVING = 1<<1, |
499 | NL80211_MPATH_FLAG_DSN_VALID = 1<<2, | 501 | NL80211_MPATH_FLAG_DSN_VALID = 1<<2, |
500 | NL80211_MPATH_FLAG_FIXED = 1<<3, | 502 | NL80211_MPATH_FLAG_FIXED = 1<<3, |
501 | NL80211_MPATH_FLAG_RESOLVED = 1<<4, | 503 | NL80211_MPATH_FLAG_RESOLVED = 1<<4, |
502 | }; | 504 | }; |
503 | 505 | ||
504 | /** | 506 | /** |
505 | * enum nl80211_mpath_info - mesh path information | 507 | * enum nl80211_mpath_info - mesh path information |
506 | * | 508 | * |
507 | * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting | 509 | * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting |
508 | * information about a mesh path. | 510 | * information about a mesh path. |
509 | * | 511 | * |
510 | * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved | 512 | * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved |
511 | * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination | 513 | * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination |
512 | * @NL80211_ATTR_MPATH_DSN: destination sequence number | 514 | * @NL80211_ATTR_MPATH_DSN: destination sequence number |
513 | * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path | 515 | * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path |
514 | * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now | 516 | * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now |
515 | * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in | 517 | * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in |
516 | * &enum nl80211_mpath_flags; | 518 | * &enum nl80211_mpath_flags; |
517 | * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec | 519 | * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec |
518 | * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries | 520 | * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries |
519 | */ | 521 | */ |
520 | enum nl80211_mpath_info { | 522 | enum nl80211_mpath_info { |
521 | __NL80211_MPATH_INFO_INVALID, | 523 | __NL80211_MPATH_INFO_INVALID, |
522 | NL80211_MPATH_INFO_FRAME_QLEN, | 524 | NL80211_MPATH_INFO_FRAME_QLEN, |
523 | NL80211_MPATH_INFO_DSN, | 525 | NL80211_MPATH_INFO_DSN, |
524 | NL80211_MPATH_INFO_METRIC, | 526 | NL80211_MPATH_INFO_METRIC, |
525 | NL80211_MPATH_INFO_EXPTIME, | 527 | NL80211_MPATH_INFO_EXPTIME, |
526 | NL80211_MPATH_INFO_FLAGS, | 528 | NL80211_MPATH_INFO_FLAGS, |
527 | NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, | 529 | NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, |
528 | NL80211_MPATH_INFO_DISCOVERY_RETRIES, | 530 | NL80211_MPATH_INFO_DISCOVERY_RETRIES, |
529 | 531 | ||
530 | /* keep last */ | 532 | /* keep last */ |
531 | __NL80211_MPATH_INFO_AFTER_LAST, | 533 | __NL80211_MPATH_INFO_AFTER_LAST, |
532 | NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 | 534 | NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 |
533 | }; | 535 | }; |
534 | 536 | ||
535 | /** | 537 | /** |
536 | * enum nl80211_band_attr - band attributes | 538 | * enum nl80211_band_attr - band attributes |
537 | * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved | 539 | * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved |
538 | * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, | 540 | * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, |
539 | * an array of nested frequency attributes | 541 | * an array of nested frequency attributes |
540 | * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, | 542 | * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, |
541 | * an array of nested bitrate attributes | 543 | * an array of nested bitrate attributes |
542 | * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as | 544 | * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as |
543 | * defined in 802.11n | 545 | * defined in 802.11n |
544 | * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE | 546 | * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE |
545 | * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n | 547 | * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n |
546 | * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n | 548 | * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n |
547 | */ | 549 | */ |
548 | enum nl80211_band_attr { | 550 | enum nl80211_band_attr { |
549 | __NL80211_BAND_ATTR_INVALID, | 551 | __NL80211_BAND_ATTR_INVALID, |
550 | NL80211_BAND_ATTR_FREQS, | 552 | NL80211_BAND_ATTR_FREQS, |
551 | NL80211_BAND_ATTR_RATES, | 553 | NL80211_BAND_ATTR_RATES, |
552 | 554 | ||
553 | NL80211_BAND_ATTR_HT_MCS_SET, | 555 | NL80211_BAND_ATTR_HT_MCS_SET, |
554 | NL80211_BAND_ATTR_HT_CAPA, | 556 | NL80211_BAND_ATTR_HT_CAPA, |
555 | NL80211_BAND_ATTR_HT_AMPDU_FACTOR, | 557 | NL80211_BAND_ATTR_HT_AMPDU_FACTOR, |
556 | NL80211_BAND_ATTR_HT_AMPDU_DENSITY, | 558 | NL80211_BAND_ATTR_HT_AMPDU_DENSITY, |
557 | 559 | ||
558 | /* keep last */ | 560 | /* keep last */ |
559 | __NL80211_BAND_ATTR_AFTER_LAST, | 561 | __NL80211_BAND_ATTR_AFTER_LAST, |
560 | NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 | 562 | NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 |
561 | }; | 563 | }; |
562 | 564 | ||
563 | #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA | 565 | #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA |
564 | 566 | ||
565 | /** | 567 | /** |
566 | * enum nl80211_frequency_attr - frequency attributes | 568 | * enum nl80211_frequency_attr - frequency attributes |
567 | * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz | 569 | * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz |
568 | * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current | 570 | * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current |
569 | * regulatory domain. | 571 | * regulatory domain. |
570 | * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is | 572 | * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is |
571 | * permitted on this channel in current regulatory domain. | 573 | * permitted on this channel in current regulatory domain. |
572 | * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted | 574 | * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted |
573 | * on this channel in current regulatory domain. | 575 | * on this channel in current regulatory domain. |
574 | * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory | 576 | * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory |
575 | * on this channel in current regulatory domain. | 577 | * on this channel in current regulatory domain. |
576 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm | 578 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm |
577 | * (100 * dBm). | 579 | * (100 * dBm). |
578 | */ | 580 | */ |
579 | enum nl80211_frequency_attr { | 581 | enum nl80211_frequency_attr { |
580 | __NL80211_FREQUENCY_ATTR_INVALID, | 582 | __NL80211_FREQUENCY_ATTR_INVALID, |
581 | NL80211_FREQUENCY_ATTR_FREQ, | 583 | NL80211_FREQUENCY_ATTR_FREQ, |
582 | NL80211_FREQUENCY_ATTR_DISABLED, | 584 | NL80211_FREQUENCY_ATTR_DISABLED, |
583 | NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, | 585 | NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, |
584 | NL80211_FREQUENCY_ATTR_NO_IBSS, | 586 | NL80211_FREQUENCY_ATTR_NO_IBSS, |
585 | NL80211_FREQUENCY_ATTR_RADAR, | 587 | NL80211_FREQUENCY_ATTR_RADAR, |
586 | NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | 588 | NL80211_FREQUENCY_ATTR_MAX_TX_POWER, |
587 | 589 | ||
588 | /* keep last */ | 590 | /* keep last */ |
589 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, | 591 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, |
590 | NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 | 592 | NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 |
591 | }; | 593 | }; |
592 | 594 | ||
593 | #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER | 595 | #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER |
594 | 596 | ||
595 | /** | 597 | /** |
596 | * enum nl80211_bitrate_attr - bitrate attributes | 598 | * enum nl80211_bitrate_attr - bitrate attributes |
597 | * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps | 599 | * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps |
598 | * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported | 600 | * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported |
599 | * in 2.4 GHz band. | 601 | * in 2.4 GHz band. |
600 | */ | 602 | */ |
601 | enum nl80211_bitrate_attr { | 603 | enum nl80211_bitrate_attr { |
602 | __NL80211_BITRATE_ATTR_INVALID, | 604 | __NL80211_BITRATE_ATTR_INVALID, |
603 | NL80211_BITRATE_ATTR_RATE, | 605 | NL80211_BITRATE_ATTR_RATE, |
604 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, | 606 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, |
605 | 607 | ||
606 | /* keep last */ | 608 | /* keep last */ |
607 | __NL80211_BITRATE_ATTR_AFTER_LAST, | 609 | __NL80211_BITRATE_ATTR_AFTER_LAST, |
608 | NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 | 610 | NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 |
609 | }; | 611 | }; |
610 | 612 | ||
611 | /** | 613 | /** |
612 | * enum nl80211_reg_rule_attr - regulatory rule attributes | 614 | * enum nl80211_reg_rule_attr - regulatory rule attributes |
613 | * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional | 615 | * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional |
614 | * considerations for a given frequency range. These are the | 616 | * considerations for a given frequency range. These are the |
615 | * &enum nl80211_reg_rule_flags. | 617 | * &enum nl80211_reg_rule_flags. |
616 | * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory | 618 | * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory |
617 | * rule in KHz. This is not a center of frequency but an actual regulatory | 619 | * rule in KHz. This is not a center of frequency but an actual regulatory |
618 | * band edge. | 620 | * band edge. |
619 | * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule | 621 | * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule |
620 | * in KHz. This is not a center a frequency but an actual regulatory | 622 | * in KHz. This is not a center a frequency but an actual regulatory |
621 | * band edge. | 623 | * band edge. |
622 | * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this | 624 | * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this |
623 | * frequency range, in KHz. | 625 | * frequency range, in KHz. |
624 | * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain | 626 | * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain |
625 | * for a given frequency range. The value is in mBi (100 * dBi). | 627 | * for a given frequency range. The value is in mBi (100 * dBi). |
626 | * If you don't have one then don't send this. | 628 | * If you don't have one then don't send this. |
627 | * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for | 629 | * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for |
628 | * a given frequency range. The value is in mBm (100 * dBm). | 630 | * a given frequency range. The value is in mBm (100 * dBm). |
629 | */ | 631 | */ |
630 | enum nl80211_reg_rule_attr { | 632 | enum nl80211_reg_rule_attr { |
631 | __NL80211_REG_RULE_ATTR_INVALID, | 633 | __NL80211_REG_RULE_ATTR_INVALID, |
632 | NL80211_ATTR_REG_RULE_FLAGS, | 634 | NL80211_ATTR_REG_RULE_FLAGS, |
633 | 635 | ||
634 | NL80211_ATTR_FREQ_RANGE_START, | 636 | NL80211_ATTR_FREQ_RANGE_START, |
635 | NL80211_ATTR_FREQ_RANGE_END, | 637 | NL80211_ATTR_FREQ_RANGE_END, |
636 | NL80211_ATTR_FREQ_RANGE_MAX_BW, | 638 | NL80211_ATTR_FREQ_RANGE_MAX_BW, |
637 | 639 | ||
638 | NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | 640 | NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, |
639 | NL80211_ATTR_POWER_RULE_MAX_EIRP, | 641 | NL80211_ATTR_POWER_RULE_MAX_EIRP, |
640 | 642 | ||
641 | /* keep last */ | 643 | /* keep last */ |
642 | __NL80211_REG_RULE_ATTR_AFTER_LAST, | 644 | __NL80211_REG_RULE_ATTR_AFTER_LAST, |
643 | NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 | 645 | NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 |
644 | }; | 646 | }; |
645 | 647 | ||
646 | /** | 648 | /** |
647 | * enum nl80211_reg_rule_flags - regulatory rule flags | 649 | * enum nl80211_reg_rule_flags - regulatory rule flags |
648 | * | 650 | * |
649 | * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed | 651 | * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed |
650 | * @NL80211_RRF_NO_CCK: CCK modulation not allowed | 652 | * @NL80211_RRF_NO_CCK: CCK modulation not allowed |
651 | * @NL80211_RRF_NO_INDOOR: indoor operation not allowed | 653 | * @NL80211_RRF_NO_INDOOR: indoor operation not allowed |
652 | * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed | 654 | * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed |
653 | * @NL80211_RRF_DFS: DFS support is required to be used | 655 | * @NL80211_RRF_DFS: DFS support is required to be used |
654 | * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links | 656 | * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links |
655 | * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links | 657 | * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links |
656 | * @NL80211_RRF_PASSIVE_SCAN: passive scan is required | 658 | * @NL80211_RRF_PASSIVE_SCAN: passive scan is required |
657 | * @NL80211_RRF_NO_IBSS: no IBSS is allowed | 659 | * @NL80211_RRF_NO_IBSS: no IBSS is allowed |
658 | */ | 660 | */ |
659 | enum nl80211_reg_rule_flags { | 661 | enum nl80211_reg_rule_flags { |
660 | NL80211_RRF_NO_OFDM = 1<<0, | 662 | NL80211_RRF_NO_OFDM = 1<<0, |
661 | NL80211_RRF_NO_CCK = 1<<1, | 663 | NL80211_RRF_NO_CCK = 1<<1, |
662 | NL80211_RRF_NO_INDOOR = 1<<2, | 664 | NL80211_RRF_NO_INDOOR = 1<<2, |
663 | NL80211_RRF_NO_OUTDOOR = 1<<3, | 665 | NL80211_RRF_NO_OUTDOOR = 1<<3, |
664 | NL80211_RRF_DFS = 1<<4, | 666 | NL80211_RRF_DFS = 1<<4, |
665 | NL80211_RRF_PTP_ONLY = 1<<5, | 667 | NL80211_RRF_PTP_ONLY = 1<<5, |
666 | NL80211_RRF_PTMP_ONLY = 1<<6, | 668 | NL80211_RRF_PTMP_ONLY = 1<<6, |
667 | NL80211_RRF_PASSIVE_SCAN = 1<<7, | 669 | NL80211_RRF_PASSIVE_SCAN = 1<<7, |
668 | NL80211_RRF_NO_IBSS = 1<<8, | 670 | NL80211_RRF_NO_IBSS = 1<<8, |
669 | }; | 671 | }; |
670 | 672 | ||
671 | /** | 673 | /** |
672 | * enum nl80211_mntr_flags - monitor configuration flags | 674 | * enum nl80211_mntr_flags - monitor configuration flags |
673 | * | 675 | * |
674 | * Monitor configuration flags. | 676 | * Monitor configuration flags. |
675 | * | 677 | * |
676 | * @__NL80211_MNTR_FLAG_INVALID: reserved | 678 | * @__NL80211_MNTR_FLAG_INVALID: reserved |
677 | * | 679 | * |
678 | * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS | 680 | * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS |
679 | * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP | 681 | * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP |
680 | * @NL80211_MNTR_FLAG_CONTROL: pass control frames | 682 | * @NL80211_MNTR_FLAG_CONTROL: pass control frames |
681 | * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering | 683 | * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering |
682 | * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. | 684 | * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. |
683 | * overrides all other flags. | 685 | * overrides all other flags. |
684 | * | 686 | * |
685 | * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use | 687 | * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use |
686 | * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag | 688 | * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag |
687 | */ | 689 | */ |
688 | enum nl80211_mntr_flags { | 690 | enum nl80211_mntr_flags { |
689 | __NL80211_MNTR_FLAG_INVALID, | 691 | __NL80211_MNTR_FLAG_INVALID, |
690 | NL80211_MNTR_FLAG_FCSFAIL, | 692 | NL80211_MNTR_FLAG_FCSFAIL, |
691 | NL80211_MNTR_FLAG_PLCPFAIL, | 693 | NL80211_MNTR_FLAG_PLCPFAIL, |
692 | NL80211_MNTR_FLAG_CONTROL, | 694 | NL80211_MNTR_FLAG_CONTROL, |
693 | NL80211_MNTR_FLAG_OTHER_BSS, | 695 | NL80211_MNTR_FLAG_OTHER_BSS, |
694 | NL80211_MNTR_FLAG_COOK_FRAMES, | 696 | NL80211_MNTR_FLAG_COOK_FRAMES, |
695 | 697 | ||
696 | /* keep last */ | 698 | /* keep last */ |
697 | __NL80211_MNTR_FLAG_AFTER_LAST, | 699 | __NL80211_MNTR_FLAG_AFTER_LAST, |
698 | NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 | 700 | NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 |
699 | }; | 701 | }; |
700 | 702 | ||
701 | /** | 703 | /** |
702 | * enum nl80211_meshconf_params - mesh configuration parameters | 704 | * enum nl80211_meshconf_params - mesh configuration parameters |
703 | * | 705 | * |
704 | * Mesh configuration parameters | 706 | * Mesh configuration parameters |
705 | * | 707 | * |
706 | * @__NL80211_MESHCONF_INVALID: internal use | 708 | * @__NL80211_MESHCONF_INVALID: internal use |
707 | * | 709 | * |
708 | * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in | 710 | * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in |
709 | * millisecond units, used by the Peer Link Open message | 711 | * millisecond units, used by the Peer Link Open message |
710 | * | 712 | * |
711 | * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in | 713 | * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in |
712 | * millisecond units, used by the peer link management to close a peer link | 714 | * millisecond units, used by the peer link management to close a peer link |
713 | * | 715 | * |
714 | * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in | 716 | * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in |
715 | * millisecond units | 717 | * millisecond units |
716 | * | 718 | * |
717 | * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed | 719 | * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed |
718 | * on this mesh interface | 720 | * on this mesh interface |
719 | * | 721 | * |
720 | * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link | 722 | * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link |
721 | * open retries that can be sent to establish a new peer link instance in a | 723 | * open retries that can be sent to establish a new peer link instance in a |
722 | * mesh | 724 | * mesh |
723 | * | 725 | * |
724 | * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh | 726 | * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh |
725 | * point. | 727 | * point. |
726 | * | 728 | * |
727 | * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically | 729 | * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically |
728 | * open peer links when we detect compatible mesh peers. | 730 | * open peer links when we detect compatible mesh peers. |
729 | * | 731 | * |
730 | * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames | 732 | * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames |
731 | * containing a PREQ that an MP can send to a particular destination (path | 733 | * containing a PREQ that an MP can send to a particular destination (path |
732 | * target) | 734 | * target) |
733 | * | 735 | * |
734 | * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths | 736 | * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths |
735 | * (in milliseconds) | 737 | * (in milliseconds) |
736 | * | 738 | * |
737 | * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait | 739 | * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait |
738 | * until giving up on a path discovery (in milliseconds) | 740 | * until giving up on a path discovery (in milliseconds) |
739 | * | 741 | * |
740 | * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh | 742 | * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh |
741 | * points receiving a PREQ shall consider the forwarding information from the | 743 | * points receiving a PREQ shall consider the forwarding information from the |
742 | * root to be valid. (TU = time unit) | 744 | * root to be valid. (TU = time unit) |
743 | * | 745 | * |
744 | * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in | 746 | * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in |
745 | * TUs) during which an MP can send only one action frame containing a PREQ | 747 | * TUs) during which an MP can send only one action frame containing a PREQ |
746 | * reference element | 748 | * reference element |
747 | * | 749 | * |
748 | * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) | 750 | * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) |
749 | * that it takes for an HWMP information element to propagate across the mesh | 751 | * that it takes for an HWMP information element to propagate across the mesh |
750 | * | 752 | * |
751 | * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute | 753 | * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute |
752 | * | 754 | * |
753 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use | 755 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use |
754 | */ | 756 | */ |
755 | enum nl80211_meshconf_params { | 757 | enum nl80211_meshconf_params { |
756 | __NL80211_MESHCONF_INVALID, | 758 | __NL80211_MESHCONF_INVALID, |
757 | NL80211_MESHCONF_RETRY_TIMEOUT, | 759 | NL80211_MESHCONF_RETRY_TIMEOUT, |
758 | NL80211_MESHCONF_CONFIRM_TIMEOUT, | 760 | NL80211_MESHCONF_CONFIRM_TIMEOUT, |
759 | NL80211_MESHCONF_HOLDING_TIMEOUT, | 761 | NL80211_MESHCONF_HOLDING_TIMEOUT, |
760 | NL80211_MESHCONF_MAX_PEER_LINKS, | 762 | NL80211_MESHCONF_MAX_PEER_LINKS, |
761 | NL80211_MESHCONF_MAX_RETRIES, | 763 | NL80211_MESHCONF_MAX_RETRIES, |
762 | NL80211_MESHCONF_TTL, | 764 | NL80211_MESHCONF_TTL, |
763 | NL80211_MESHCONF_AUTO_OPEN_PLINKS, | 765 | NL80211_MESHCONF_AUTO_OPEN_PLINKS, |
764 | NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 766 | NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
765 | NL80211_MESHCONF_PATH_REFRESH_TIME, | 767 | NL80211_MESHCONF_PATH_REFRESH_TIME, |
766 | NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | 768 | NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, |
767 | NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | 769 | NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, |
768 | NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | 770 | NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, |
769 | NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | 771 | NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
770 | 772 | ||
771 | /* keep last */ | 773 | /* keep last */ |
772 | __NL80211_MESHCONF_ATTR_AFTER_LAST, | 774 | __NL80211_MESHCONF_ATTR_AFTER_LAST, |
773 | NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 | 775 | NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 |
774 | }; | 776 | }; |
775 | 777 | ||
776 | /** | 778 | /** |
777 | * enum nl80211_txq_attr - TX queue parameter attributes | 779 | * enum nl80211_txq_attr - TX queue parameter attributes |
778 | * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved | 780 | * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved |
779 | * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*) | 781 | * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*) |
780 | * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning | 782 | * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning |
781 | * disabled | 783 | * disabled |
782 | * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form | 784 | * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form |
783 | * 2^n-1 in the range 1..32767] | 785 | * 2^n-1 in the range 1..32767] |
784 | * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form | 786 | * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form |
785 | * 2^n-1 in the range 1..32767] | 787 | * 2^n-1 in the range 1..32767] |
786 | * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] | 788 | * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] |
787 | * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal | 789 | * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal |
788 | * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number | 790 | * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number |
789 | */ | 791 | */ |
790 | enum nl80211_txq_attr { | 792 | enum nl80211_txq_attr { |
791 | __NL80211_TXQ_ATTR_INVALID, | 793 | __NL80211_TXQ_ATTR_INVALID, |
792 | NL80211_TXQ_ATTR_QUEUE, | 794 | NL80211_TXQ_ATTR_QUEUE, |
793 | NL80211_TXQ_ATTR_TXOP, | 795 | NL80211_TXQ_ATTR_TXOP, |
794 | NL80211_TXQ_ATTR_CWMIN, | 796 | NL80211_TXQ_ATTR_CWMIN, |
795 | NL80211_TXQ_ATTR_CWMAX, | 797 | NL80211_TXQ_ATTR_CWMAX, |
796 | NL80211_TXQ_ATTR_AIFS, | 798 | NL80211_TXQ_ATTR_AIFS, |
797 | 799 | ||
798 | /* keep last */ | 800 | /* keep last */ |
799 | __NL80211_TXQ_ATTR_AFTER_LAST, | 801 | __NL80211_TXQ_ATTR_AFTER_LAST, |
800 | NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 | 802 | NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 |
801 | }; | 803 | }; |
802 | 804 | ||
803 | enum nl80211_txq_q { | 805 | enum nl80211_txq_q { |
804 | NL80211_TXQ_Q_VO, | 806 | NL80211_TXQ_Q_VO, |
805 | NL80211_TXQ_Q_VI, | 807 | NL80211_TXQ_Q_VI, |
806 | NL80211_TXQ_Q_BE, | 808 | NL80211_TXQ_Q_BE, |
807 | NL80211_TXQ_Q_BK | 809 | NL80211_TXQ_Q_BK |
808 | }; | 810 | }; |
809 | 811 | ||
810 | enum nl80211_channel_type { | 812 | enum nl80211_channel_type { |
811 | NL80211_CHAN_NO_HT, | 813 | NL80211_CHAN_NO_HT, |
812 | NL80211_CHAN_HT20, | 814 | NL80211_CHAN_HT20, |
813 | NL80211_CHAN_HT40MINUS, | 815 | NL80211_CHAN_HT40MINUS, |
814 | NL80211_CHAN_HT40PLUS | 816 | NL80211_CHAN_HT40PLUS |
815 | }; | 817 | }; |
816 | #endif /* __LINUX_NL80211_H */ | 818 | #endif /* __LINUX_NL80211_H */ |
817 | 819 |
include/net/cfg80211.h
1 | #ifndef __NET_CFG80211_H | 1 | #ifndef __NET_CFG80211_H |
2 | #define __NET_CFG80211_H | 2 | #define __NET_CFG80211_H |
3 | 3 | ||
4 | #include <linux/netlink.h> | 4 | #include <linux/netlink.h> |
5 | #include <linux/skbuff.h> | 5 | #include <linux/skbuff.h> |
6 | #include <linux/nl80211.h> | 6 | #include <linux/nl80211.h> |
7 | #include <net/genetlink.h> | 7 | #include <net/genetlink.h> |
8 | /* remove once we remove the wext stuff */ | 8 | /* remove once we remove the wext stuff */ |
9 | #include <net/iw_handler.h> | 9 | #include <net/iw_handler.h> |
10 | 10 | ||
11 | /* | 11 | /* |
12 | * 802.11 configuration in-kernel interface | 12 | * 802.11 configuration in-kernel interface |
13 | * | 13 | * |
14 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 14 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /** | 17 | /** |
18 | * struct vif_params - describes virtual interface parameters | 18 | * struct vif_params - describes virtual interface parameters |
19 | * @mesh_id: mesh ID to use | 19 | * @mesh_id: mesh ID to use |
20 | * @mesh_id_len: length of the mesh ID | 20 | * @mesh_id_len: length of the mesh ID |
21 | */ | 21 | */ |
22 | struct vif_params { | 22 | struct vif_params { |
23 | u8 *mesh_id; | 23 | u8 *mesh_id; |
24 | int mesh_id_len; | 24 | int mesh_id_len; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | /* Radiotap header iteration | 27 | /* Radiotap header iteration |
28 | * implemented in net/wireless/radiotap.c | 28 | * implemented in net/wireless/radiotap.c |
29 | * docs in Documentation/networking/radiotap-headers.txt | 29 | * docs in Documentation/networking/radiotap-headers.txt |
30 | */ | 30 | */ |
31 | /** | 31 | /** |
32 | * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args | 32 | * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args |
33 | * @rtheader: pointer to the radiotap header we are walking through | 33 | * @rtheader: pointer to the radiotap header we are walking through |
34 | * @max_length: length of radiotap header in cpu byte ordering | 34 | * @max_length: length of radiotap header in cpu byte ordering |
35 | * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg | 35 | * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg |
36 | * @this_arg: pointer to current radiotap arg | 36 | * @this_arg: pointer to current radiotap arg |
37 | * @arg_index: internal next argument index | 37 | * @arg_index: internal next argument index |
38 | * @arg: internal next argument pointer | 38 | * @arg: internal next argument pointer |
39 | * @next_bitmap: internal pointer to next present u32 | 39 | * @next_bitmap: internal pointer to next present u32 |
40 | * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present | 40 | * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present |
41 | */ | 41 | */ |
42 | 42 | ||
43 | struct ieee80211_radiotap_iterator { | 43 | struct ieee80211_radiotap_iterator { |
44 | struct ieee80211_radiotap_header *rtheader; | 44 | struct ieee80211_radiotap_header *rtheader; |
45 | int max_length; | 45 | int max_length; |
46 | int this_arg_index; | 46 | int this_arg_index; |
47 | u8 *this_arg; | 47 | u8 *this_arg; |
48 | 48 | ||
49 | int arg_index; | 49 | int arg_index; |
50 | u8 *arg; | 50 | u8 *arg; |
51 | __le32 *next_bitmap; | 51 | __le32 *next_bitmap; |
52 | u32 bitmap_shifter; | 52 | u32 bitmap_shifter; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | extern int ieee80211_radiotap_iterator_init( | 55 | extern int ieee80211_radiotap_iterator_init( |
56 | struct ieee80211_radiotap_iterator *iterator, | 56 | struct ieee80211_radiotap_iterator *iterator, |
57 | struct ieee80211_radiotap_header *radiotap_header, | 57 | struct ieee80211_radiotap_header *radiotap_header, |
58 | int max_length); | 58 | int max_length); |
59 | 59 | ||
60 | extern int ieee80211_radiotap_iterator_next( | 60 | extern int ieee80211_radiotap_iterator_next( |
61 | struct ieee80211_radiotap_iterator *iterator); | 61 | struct ieee80211_radiotap_iterator *iterator); |
62 | 62 | ||
63 | 63 | ||
64 | /** | 64 | /** |
65 | * struct key_params - key information | 65 | * struct key_params - key information |
66 | * | 66 | * |
67 | * Information about a key | 67 | * Information about a key |
68 | * | 68 | * |
69 | * @key: key material | 69 | * @key: key material |
70 | * @key_len: length of key material | 70 | * @key_len: length of key material |
71 | * @cipher: cipher suite selector | 71 | * @cipher: cipher suite selector |
72 | * @seq: sequence counter (IV/PN) for TKIP and CCMP keys, only used | 72 | * @seq: sequence counter (IV/PN) for TKIP and CCMP keys, only used |
73 | * with the get_key() callback, must be in little endian, | 73 | * with the get_key() callback, must be in little endian, |
74 | * length given by @seq_len. | 74 | * length given by @seq_len. |
75 | */ | 75 | */ |
76 | struct key_params { | 76 | struct key_params { |
77 | u8 *key; | 77 | u8 *key; |
78 | u8 *seq; | 78 | u8 *seq; |
79 | int key_len; | 79 | int key_len; |
80 | int seq_len; | 80 | int seq_len; |
81 | u32 cipher; | 81 | u32 cipher; |
82 | }; | 82 | }; |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * struct beacon_parameters - beacon parameters | 85 | * struct beacon_parameters - beacon parameters |
86 | * | 86 | * |
87 | * Used to configure the beacon for an interface. | 87 | * Used to configure the beacon for an interface. |
88 | * | 88 | * |
89 | * @head: head portion of beacon (before TIM IE) | 89 | * @head: head portion of beacon (before TIM IE) |
90 | * or %NULL if not changed | 90 | * or %NULL if not changed |
91 | * @tail: tail portion of beacon (after TIM IE) | 91 | * @tail: tail portion of beacon (after TIM IE) |
92 | * or %NULL if not changed | 92 | * or %NULL if not changed |
93 | * @interval: beacon interval or zero if not changed | 93 | * @interval: beacon interval or zero if not changed |
94 | * @dtim_period: DTIM period or zero if not changed | 94 | * @dtim_period: DTIM period or zero if not changed |
95 | * @head_len: length of @head | 95 | * @head_len: length of @head |
96 | * @tail_len: length of @tail | 96 | * @tail_len: length of @tail |
97 | */ | 97 | */ |
98 | struct beacon_parameters { | 98 | struct beacon_parameters { |
99 | u8 *head, *tail; | 99 | u8 *head, *tail; |
100 | int interval, dtim_period; | 100 | int interval, dtim_period; |
101 | int head_len, tail_len; | 101 | int head_len, tail_len; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | /** | 104 | /** |
105 | * enum station_flags - station flags | 105 | * enum station_flags - station flags |
106 | * | 106 | * |
107 | * Station capability flags. Note that these must be the bits | 107 | * Station capability flags. Note that these must be the bits |
108 | * according to the nl80211 flags. | 108 | * according to the nl80211 flags. |
109 | * | 109 | * |
110 | * @STATION_FLAG_CHANGED: station flags were changed | 110 | * @STATION_FLAG_CHANGED: station flags were changed |
111 | * @STATION_FLAG_AUTHORIZED: station is authorized to send frames (802.1X) | 111 | * @STATION_FLAG_AUTHORIZED: station is authorized to send frames (802.1X) |
112 | * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames | 112 | * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames |
113 | * with short preambles | 113 | * with short preambles |
114 | * @STATION_FLAG_WME: station is WME/QoS capable | 114 | * @STATION_FLAG_WME: station is WME/QoS capable |
115 | * @STATION_FLAG_MFP: station uses management frame protection | 115 | * @STATION_FLAG_MFP: station uses management frame protection |
116 | */ | 116 | */ |
117 | enum station_flags { | 117 | enum station_flags { |
118 | STATION_FLAG_CHANGED = 1<<0, | 118 | STATION_FLAG_CHANGED = 1<<0, |
119 | STATION_FLAG_AUTHORIZED = 1<<NL80211_STA_FLAG_AUTHORIZED, | 119 | STATION_FLAG_AUTHORIZED = 1<<NL80211_STA_FLAG_AUTHORIZED, |
120 | STATION_FLAG_SHORT_PREAMBLE = 1<<NL80211_STA_FLAG_SHORT_PREAMBLE, | 120 | STATION_FLAG_SHORT_PREAMBLE = 1<<NL80211_STA_FLAG_SHORT_PREAMBLE, |
121 | STATION_FLAG_WME = 1<<NL80211_STA_FLAG_WME, | 121 | STATION_FLAG_WME = 1<<NL80211_STA_FLAG_WME, |
122 | STATION_FLAG_MFP = 1<<NL80211_STA_FLAG_MFP, | 122 | STATION_FLAG_MFP = 1<<NL80211_STA_FLAG_MFP, |
123 | }; | 123 | }; |
124 | 124 | ||
125 | /** | 125 | /** |
126 | * enum plink_action - actions to perform in mesh peers | 126 | * enum plink_action - actions to perform in mesh peers |
127 | * | 127 | * |
128 | * @PLINK_ACTION_INVALID: action 0 is reserved | 128 | * @PLINK_ACTION_INVALID: action 0 is reserved |
129 | * @PLINK_ACTION_OPEN: start mesh peer link establishment | 129 | * @PLINK_ACTION_OPEN: start mesh peer link establishment |
130 | * @PLINK_ACTION_BLOCL: block traffic from this mesh peer | 130 | * @PLINK_ACTION_BLOCL: block traffic from this mesh peer |
131 | */ | 131 | */ |
132 | enum plink_actions { | 132 | enum plink_actions { |
133 | PLINK_ACTION_INVALID, | 133 | PLINK_ACTION_INVALID, |
134 | PLINK_ACTION_OPEN, | 134 | PLINK_ACTION_OPEN, |
135 | PLINK_ACTION_BLOCK, | 135 | PLINK_ACTION_BLOCK, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | /** | 138 | /** |
139 | * struct station_parameters - station parameters | 139 | * struct station_parameters - station parameters |
140 | * | 140 | * |
141 | * Used to change and create a new station. | 141 | * Used to change and create a new station. |
142 | * | 142 | * |
143 | * @vlan: vlan interface station should belong to | 143 | * @vlan: vlan interface station should belong to |
144 | * @supported_rates: supported rates in IEEE 802.11 format | 144 | * @supported_rates: supported rates in IEEE 802.11 format |
145 | * (or NULL for no change) | 145 | * (or NULL for no change) |
146 | * @supported_rates_len: number of supported rates | 146 | * @supported_rates_len: number of supported rates |
147 | * @station_flags: station flags (see &enum station_flags) | 147 | * @station_flags: station flags (see &enum station_flags) |
148 | * @listen_interval: listen interval or -1 for no change | 148 | * @listen_interval: listen interval or -1 for no change |
149 | * @aid: AID or zero for no change | 149 | * @aid: AID or zero for no change |
150 | */ | 150 | */ |
151 | struct station_parameters { | 151 | struct station_parameters { |
152 | u8 *supported_rates; | 152 | u8 *supported_rates; |
153 | struct net_device *vlan; | 153 | struct net_device *vlan; |
154 | u32 station_flags; | 154 | u32 station_flags; |
155 | int listen_interval; | 155 | int listen_interval; |
156 | u16 aid; | 156 | u16 aid; |
157 | u8 supported_rates_len; | 157 | u8 supported_rates_len; |
158 | u8 plink_action; | 158 | u8 plink_action; |
159 | struct ieee80211_ht_cap *ht_capa; | 159 | struct ieee80211_ht_cap *ht_capa; |
160 | }; | 160 | }; |
161 | 161 | ||
162 | /** | 162 | /** |
163 | * enum station_info_flags - station information flags | 163 | * enum station_info_flags - station information flags |
164 | * | 164 | * |
165 | * Used by the driver to indicate which info in &struct station_info | 165 | * Used by the driver to indicate which info in &struct station_info |
166 | * it has filled in during get_station() or dump_station(). | 166 | * it has filled in during get_station() or dump_station(). |
167 | * | 167 | * |
168 | * @STATION_INFO_INACTIVE_TIME: @inactive_time filled | 168 | * @STATION_INFO_INACTIVE_TIME: @inactive_time filled |
169 | * @STATION_INFO_RX_BYTES: @rx_bytes filled | 169 | * @STATION_INFO_RX_BYTES: @rx_bytes filled |
170 | * @STATION_INFO_TX_BYTES: @tx_bytes filled | 170 | * @STATION_INFO_TX_BYTES: @tx_bytes filled |
171 | * @STATION_INFO_LLID: @llid filled | 171 | * @STATION_INFO_LLID: @llid filled |
172 | * @STATION_INFO_PLID: @plid filled | 172 | * @STATION_INFO_PLID: @plid filled |
173 | * @STATION_INFO_PLINK_STATE: @plink_state filled | 173 | * @STATION_INFO_PLINK_STATE: @plink_state filled |
174 | * @STATION_INFO_SIGNAL: @signal filled | 174 | * @STATION_INFO_SIGNAL: @signal filled |
175 | * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled | 175 | * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled |
176 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) | 176 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) |
177 | */ | 177 | */ |
178 | enum station_info_flags { | 178 | enum station_info_flags { |
179 | STATION_INFO_INACTIVE_TIME = 1<<0, | 179 | STATION_INFO_INACTIVE_TIME = 1<<0, |
180 | STATION_INFO_RX_BYTES = 1<<1, | 180 | STATION_INFO_RX_BYTES = 1<<1, |
181 | STATION_INFO_TX_BYTES = 1<<2, | 181 | STATION_INFO_TX_BYTES = 1<<2, |
182 | STATION_INFO_LLID = 1<<3, | 182 | STATION_INFO_LLID = 1<<3, |
183 | STATION_INFO_PLID = 1<<4, | 183 | STATION_INFO_PLID = 1<<4, |
184 | STATION_INFO_PLINK_STATE = 1<<5, | 184 | STATION_INFO_PLINK_STATE = 1<<5, |
185 | STATION_INFO_SIGNAL = 1<<6, | 185 | STATION_INFO_SIGNAL = 1<<6, |
186 | STATION_INFO_TX_BITRATE = 1<<7, | 186 | STATION_INFO_TX_BITRATE = 1<<7, |
187 | }; | 187 | }; |
188 | 188 | ||
189 | /** | 189 | /** |
190 | * enum station_info_rate_flags - bitrate info flags | 190 | * enum station_info_rate_flags - bitrate info flags |
191 | * | 191 | * |
192 | * Used by the driver to indicate the specific rate transmission | 192 | * Used by the driver to indicate the specific rate transmission |
193 | * type for 802.11n transmissions. | 193 | * type for 802.11n transmissions. |
194 | * | 194 | * |
195 | * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled | 195 | * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled |
196 | * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission | 196 | * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission |
197 | * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval | 197 | * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval |
198 | */ | 198 | */ |
199 | enum rate_info_flags { | 199 | enum rate_info_flags { |
200 | RATE_INFO_FLAGS_MCS = 1<<0, | 200 | RATE_INFO_FLAGS_MCS = 1<<0, |
201 | RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, | 201 | RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, |
202 | RATE_INFO_FLAGS_SHORT_GI = 1<<2, | 202 | RATE_INFO_FLAGS_SHORT_GI = 1<<2, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | /** | 205 | /** |
206 | * struct rate_info - bitrate information | 206 | * struct rate_info - bitrate information |
207 | * | 207 | * |
208 | * Information about a receiving or transmitting bitrate | 208 | * Information about a receiving or transmitting bitrate |
209 | * | 209 | * |
210 | * @flags: bitflag of flags from &enum rate_info_flags | 210 | * @flags: bitflag of flags from &enum rate_info_flags |
211 | * @mcs: mcs index if struct describes a 802.11n bitrate | 211 | * @mcs: mcs index if struct describes a 802.11n bitrate |
212 | * @legacy: bitrate in 100kbit/s for 802.11abg | 212 | * @legacy: bitrate in 100kbit/s for 802.11abg |
213 | */ | 213 | */ |
214 | struct rate_info { | 214 | struct rate_info { |
215 | u8 flags; | 215 | u8 flags; |
216 | u8 mcs; | 216 | u8 mcs; |
217 | u16 legacy; | 217 | u16 legacy; |
218 | }; | 218 | }; |
219 | 219 | ||
220 | /** | 220 | /** |
221 | * struct station_info - station information | 221 | * struct station_info - station information |
222 | * | 222 | * |
223 | * Station information filled by driver for get_station() and dump_station. | 223 | * Station information filled by driver for get_station() and dump_station. |
224 | * | 224 | * |
225 | * @filled: bitflag of flags from &enum station_info_flags | 225 | * @filled: bitflag of flags from &enum station_info_flags |
226 | * @inactive_time: time since last station activity (tx/rx) in milliseconds | 226 | * @inactive_time: time since last station activity (tx/rx) in milliseconds |
227 | * @rx_bytes: bytes received from this station | 227 | * @rx_bytes: bytes received from this station |
228 | * @tx_bytes: bytes transmitted to this station | 228 | * @tx_bytes: bytes transmitted to this station |
229 | * @llid: mesh local link id | 229 | * @llid: mesh local link id |
230 | * @plid: mesh peer link id | 230 | * @plid: mesh peer link id |
231 | * @plink_state: mesh peer link state | 231 | * @plink_state: mesh peer link state |
232 | * @signal: signal strength of last received packet in dBm | 232 | * @signal: signal strength of last received packet in dBm |
233 | * @txrate: current unicast bitrate to this station | 233 | * @txrate: current unicast bitrate to this station |
234 | */ | 234 | */ |
235 | struct station_info { | 235 | struct station_info { |
236 | u32 filled; | 236 | u32 filled; |
237 | u32 inactive_time; | 237 | u32 inactive_time; |
238 | u32 rx_bytes; | 238 | u32 rx_bytes; |
239 | u32 tx_bytes; | 239 | u32 tx_bytes; |
240 | u16 llid; | 240 | u16 llid; |
241 | u16 plid; | 241 | u16 plid; |
242 | u8 plink_state; | 242 | u8 plink_state; |
243 | s8 signal; | 243 | s8 signal; |
244 | struct rate_info txrate; | 244 | struct rate_info txrate; |
245 | }; | 245 | }; |
246 | 246 | ||
247 | /** | 247 | /** |
248 | * enum monitor_flags - monitor flags | 248 | * enum monitor_flags - monitor flags |
249 | * | 249 | * |
250 | * Monitor interface configuration flags. Note that these must be the bits | 250 | * Monitor interface configuration flags. Note that these must be the bits |
251 | * according to the nl80211 flags. | 251 | * according to the nl80211 flags. |
252 | * | 252 | * |
253 | * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS | 253 | * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS |
254 | * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP | 254 | * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP |
255 | * @MONITOR_FLAG_CONTROL: pass control frames | 255 | * @MONITOR_FLAG_CONTROL: pass control frames |
256 | * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering | 256 | * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering |
257 | * @MONITOR_FLAG_COOK_FRAMES: report frames after processing | 257 | * @MONITOR_FLAG_COOK_FRAMES: report frames after processing |
258 | */ | 258 | */ |
259 | enum monitor_flags { | 259 | enum monitor_flags { |
260 | MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL, | 260 | MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL, |
261 | MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL, | 261 | MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL, |
262 | MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL, | 262 | MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL, |
263 | MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS, | 263 | MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS, |
264 | MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES, | 264 | MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES, |
265 | }; | 265 | }; |
266 | 266 | ||
267 | /** | 267 | /** |
268 | * enum mpath_info_flags - mesh path information flags | 268 | * enum mpath_info_flags - mesh path information flags |
269 | * | 269 | * |
270 | * Used by the driver to indicate which info in &struct mpath_info it has filled | 270 | * Used by the driver to indicate which info in &struct mpath_info it has filled |
271 | * in during get_station() or dump_station(). | 271 | * in during get_station() or dump_station(). |
272 | * | 272 | * |
273 | * MPATH_INFO_FRAME_QLEN: @frame_qlen filled | 273 | * MPATH_INFO_FRAME_QLEN: @frame_qlen filled |
274 | * MPATH_INFO_DSN: @dsn filled | 274 | * MPATH_INFO_DSN: @dsn filled |
275 | * MPATH_INFO_METRIC: @metric filled | 275 | * MPATH_INFO_METRIC: @metric filled |
276 | * MPATH_INFO_EXPTIME: @exptime filled | 276 | * MPATH_INFO_EXPTIME: @exptime filled |
277 | * MPATH_INFO_DISCOVERY_TIMEOUT: @discovery_timeout filled | 277 | * MPATH_INFO_DISCOVERY_TIMEOUT: @discovery_timeout filled |
278 | * MPATH_INFO_DISCOVERY_RETRIES: @discovery_retries filled | 278 | * MPATH_INFO_DISCOVERY_RETRIES: @discovery_retries filled |
279 | * MPATH_INFO_FLAGS: @flags filled | 279 | * MPATH_INFO_FLAGS: @flags filled |
280 | */ | 280 | */ |
281 | enum mpath_info_flags { | 281 | enum mpath_info_flags { |
282 | MPATH_INFO_FRAME_QLEN = BIT(0), | 282 | MPATH_INFO_FRAME_QLEN = BIT(0), |
283 | MPATH_INFO_DSN = BIT(1), | 283 | MPATH_INFO_DSN = BIT(1), |
284 | MPATH_INFO_METRIC = BIT(2), | 284 | MPATH_INFO_METRIC = BIT(2), |
285 | MPATH_INFO_EXPTIME = BIT(3), | 285 | MPATH_INFO_EXPTIME = BIT(3), |
286 | MPATH_INFO_DISCOVERY_TIMEOUT = BIT(4), | 286 | MPATH_INFO_DISCOVERY_TIMEOUT = BIT(4), |
287 | MPATH_INFO_DISCOVERY_RETRIES = BIT(5), | 287 | MPATH_INFO_DISCOVERY_RETRIES = BIT(5), |
288 | MPATH_INFO_FLAGS = BIT(6), | 288 | MPATH_INFO_FLAGS = BIT(6), |
289 | }; | 289 | }; |
290 | 290 | ||
291 | /** | 291 | /** |
292 | * struct mpath_info - mesh path information | 292 | * struct mpath_info - mesh path information |
293 | * | 293 | * |
294 | * Mesh path information filled by driver for get_mpath() and dump_mpath(). | 294 | * Mesh path information filled by driver for get_mpath() and dump_mpath(). |
295 | * | 295 | * |
296 | * @filled: bitfield of flags from &enum mpath_info_flags | 296 | * @filled: bitfield of flags from &enum mpath_info_flags |
297 | * @frame_qlen: number of queued frames for this destination | 297 | * @frame_qlen: number of queued frames for this destination |
298 | * @dsn: destination sequence number | 298 | * @dsn: destination sequence number |
299 | * @metric: metric (cost) of this mesh path | 299 | * @metric: metric (cost) of this mesh path |
300 | * @exptime: expiration time for the mesh path from now, in msecs | 300 | * @exptime: expiration time for the mesh path from now, in msecs |
301 | * @flags: mesh path flags | 301 | * @flags: mesh path flags |
302 | * @discovery_timeout: total mesh path discovery timeout, in msecs | 302 | * @discovery_timeout: total mesh path discovery timeout, in msecs |
303 | * @discovery_retries: mesh path discovery retries | 303 | * @discovery_retries: mesh path discovery retries |
304 | */ | 304 | */ |
305 | struct mpath_info { | 305 | struct mpath_info { |
306 | u32 filled; | 306 | u32 filled; |
307 | u32 frame_qlen; | 307 | u32 frame_qlen; |
308 | u32 dsn; | 308 | u32 dsn; |
309 | u32 metric; | 309 | u32 metric; |
310 | u32 exptime; | 310 | u32 exptime; |
311 | u32 discovery_timeout; | 311 | u32 discovery_timeout; |
312 | u8 discovery_retries; | 312 | u8 discovery_retries; |
313 | u8 flags; | 313 | u8 flags; |
314 | }; | 314 | }; |
315 | 315 | ||
316 | /** | 316 | /** |
317 | * struct bss_parameters - BSS parameters | 317 | * struct bss_parameters - BSS parameters |
318 | * | 318 | * |
319 | * Used to change BSS parameters (mainly for AP mode). | 319 | * Used to change BSS parameters (mainly for AP mode). |
320 | * | 320 | * |
321 | * @use_cts_prot: Whether to use CTS protection | 321 | * @use_cts_prot: Whether to use CTS protection |
322 | * (0 = no, 1 = yes, -1 = do not change) | 322 | * (0 = no, 1 = yes, -1 = do not change) |
323 | * @use_short_preamble: Whether the use of short preambles is allowed | 323 | * @use_short_preamble: Whether the use of short preambles is allowed |
324 | * (0 = no, 1 = yes, -1 = do not change) | 324 | * (0 = no, 1 = yes, -1 = do not change) |
325 | * @use_short_slot_time: Whether the use of short slot time is allowed | 325 | * @use_short_slot_time: Whether the use of short slot time is allowed |
326 | * (0 = no, 1 = yes, -1 = do not change) | 326 | * (0 = no, 1 = yes, -1 = do not change) |
327 | * @basic_rates: basic rates in IEEE 802.11 format | 327 | * @basic_rates: basic rates in IEEE 802.11 format |
328 | * (or NULL for no change) | 328 | * (or NULL for no change) |
329 | * @basic_rates_len: number of basic rates | 329 | * @basic_rates_len: number of basic rates |
330 | */ | 330 | */ |
331 | struct bss_parameters { | 331 | struct bss_parameters { |
332 | int use_cts_prot; | 332 | int use_cts_prot; |
333 | int use_short_preamble; | 333 | int use_short_preamble; |
334 | int use_short_slot_time; | 334 | int use_short_slot_time; |
335 | u8 *basic_rates; | 335 | u8 *basic_rates; |
336 | u8 basic_rates_len; | 336 | u8 basic_rates_len; |
337 | }; | 337 | }; |
338 | 338 | ||
339 | /** | 339 | /** |
340 | * enum reg_set_by - Indicates who is trying to set the regulatory domain | 340 | * enum reg_set_by - Indicates who is trying to set the regulatory domain |
341 | * @REGDOM_SET_BY_INIT: regulatory domain was set by initialization. We will be | 341 | * @REGDOM_SET_BY_INIT: regulatory domain was set by initialization. We will be |
342 | * using a static world regulatory domain by default. | 342 | * using a static world regulatory domain by default. |
343 | * @REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world regulatory domain. | 343 | * @REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world regulatory domain. |
344 | * @REGDOM_SET_BY_USER: User asked the wireless core to set the | 344 | * @REGDOM_SET_BY_USER: User asked the wireless core to set the |
345 | * regulatory domain. | 345 | * regulatory domain. |
346 | * @REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the wireless core | 346 | * @REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the wireless core |
347 | * it thinks its knows the regulatory domain we should be in. | 347 | * it thinks its knows the regulatory domain we should be in. |
348 | * @REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an 802.11 country | 348 | * @REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an 802.11 country |
349 | * information element with regulatory information it thinks we | 349 | * information element with regulatory information it thinks we |
350 | * should consider. | 350 | * should consider. |
351 | */ | 351 | */ |
352 | enum reg_set_by { | 352 | enum reg_set_by { |
353 | REGDOM_SET_BY_INIT, | 353 | REGDOM_SET_BY_INIT, |
354 | REGDOM_SET_BY_CORE, | 354 | REGDOM_SET_BY_CORE, |
355 | REGDOM_SET_BY_USER, | 355 | REGDOM_SET_BY_USER, |
356 | REGDOM_SET_BY_DRIVER, | 356 | REGDOM_SET_BY_DRIVER, |
357 | REGDOM_SET_BY_COUNTRY_IE, | 357 | REGDOM_SET_BY_COUNTRY_IE, |
358 | }; | 358 | }; |
359 | 359 | ||
360 | struct ieee80211_freq_range { | 360 | struct ieee80211_freq_range { |
361 | u32 start_freq_khz; | 361 | u32 start_freq_khz; |
362 | u32 end_freq_khz; | 362 | u32 end_freq_khz; |
363 | u32 max_bandwidth_khz; | 363 | u32 max_bandwidth_khz; |
364 | }; | 364 | }; |
365 | 365 | ||
366 | struct ieee80211_power_rule { | 366 | struct ieee80211_power_rule { |
367 | u32 max_antenna_gain; | 367 | u32 max_antenna_gain; |
368 | u32 max_eirp; | 368 | u32 max_eirp; |
369 | }; | 369 | }; |
370 | 370 | ||
371 | struct ieee80211_reg_rule { | 371 | struct ieee80211_reg_rule { |
372 | struct ieee80211_freq_range freq_range; | 372 | struct ieee80211_freq_range freq_range; |
373 | struct ieee80211_power_rule power_rule; | 373 | struct ieee80211_power_rule power_rule; |
374 | u32 flags; | 374 | u32 flags; |
375 | }; | 375 | }; |
376 | 376 | ||
377 | struct ieee80211_regdomain { | 377 | struct ieee80211_regdomain { |
378 | u32 n_reg_rules; | 378 | u32 n_reg_rules; |
379 | char alpha2[2]; | 379 | char alpha2[2]; |
380 | struct ieee80211_reg_rule reg_rules[]; | 380 | struct ieee80211_reg_rule reg_rules[]; |
381 | }; | 381 | }; |
382 | 382 | ||
383 | #define MHZ_TO_KHZ(freq) ((freq) * 1000) | 383 | #define MHZ_TO_KHZ(freq) ((freq) * 1000) |
384 | #define KHZ_TO_MHZ(freq) ((freq) / 1000) | 384 | #define KHZ_TO_MHZ(freq) ((freq) / 1000) |
385 | #define DBI_TO_MBI(gain) ((gain) * 100) | 385 | #define DBI_TO_MBI(gain) ((gain) * 100) |
386 | #define MBI_TO_DBI(gain) ((gain) / 100) | 386 | #define MBI_TO_DBI(gain) ((gain) / 100) |
387 | #define DBM_TO_MBM(gain) ((gain) * 100) | 387 | #define DBM_TO_MBM(gain) ((gain) * 100) |
388 | #define MBM_TO_DBM(gain) ((gain) / 100) | 388 | #define MBM_TO_DBM(gain) ((gain) / 100) |
389 | 389 | ||
390 | #define REG_RULE(start, end, bw, gain, eirp, reg_flags) { \ | 390 | #define REG_RULE(start, end, bw, gain, eirp, reg_flags) { \ |
391 | .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ | 391 | .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ |
392 | .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ | 392 | .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ |
393 | .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ | 393 | .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ |
394 | .power_rule.max_antenna_gain = DBI_TO_MBI(gain), \ | 394 | .power_rule.max_antenna_gain = DBI_TO_MBI(gain), \ |
395 | .power_rule.max_eirp = DBM_TO_MBM(eirp), \ | 395 | .power_rule.max_eirp = DBM_TO_MBM(eirp), \ |
396 | .flags = reg_flags, \ | 396 | .flags = reg_flags, \ |
397 | } | 397 | } |
398 | 398 | ||
399 | struct mesh_config { | 399 | struct mesh_config { |
400 | /* Timeouts in ms */ | 400 | /* Timeouts in ms */ |
401 | /* Mesh plink management parameters */ | 401 | /* Mesh plink management parameters */ |
402 | u16 dot11MeshRetryTimeout; | 402 | u16 dot11MeshRetryTimeout; |
403 | u16 dot11MeshConfirmTimeout; | 403 | u16 dot11MeshConfirmTimeout; |
404 | u16 dot11MeshHoldingTimeout; | 404 | u16 dot11MeshHoldingTimeout; |
405 | u16 dot11MeshMaxPeerLinks; | 405 | u16 dot11MeshMaxPeerLinks; |
406 | u8 dot11MeshMaxRetries; | 406 | u8 dot11MeshMaxRetries; |
407 | u8 dot11MeshTTL; | 407 | u8 dot11MeshTTL; |
408 | bool auto_open_plinks; | 408 | bool auto_open_plinks; |
409 | /* HWMP parameters */ | 409 | /* HWMP parameters */ |
410 | u8 dot11MeshHWMPmaxPREQretries; | 410 | u8 dot11MeshHWMPmaxPREQretries; |
411 | u32 path_refresh_time; | 411 | u32 path_refresh_time; |
412 | u16 min_discovery_timeout; | 412 | u16 min_discovery_timeout; |
413 | u32 dot11MeshHWMPactivePathTimeout; | 413 | u32 dot11MeshHWMPactivePathTimeout; |
414 | u16 dot11MeshHWMPpreqMinInterval; | 414 | u16 dot11MeshHWMPpreqMinInterval; |
415 | u16 dot11MeshHWMPnetDiameterTraversalTime; | 415 | u16 dot11MeshHWMPnetDiameterTraversalTime; |
416 | }; | 416 | }; |
417 | 417 | ||
418 | /** | 418 | /** |
419 | * struct ieee80211_txq_params - TX queue parameters | 419 | * struct ieee80211_txq_params - TX queue parameters |
420 | * @queue: TX queue identifier (NL80211_TXQ_Q_*) | 420 | * @queue: TX queue identifier (NL80211_TXQ_Q_*) |
421 | * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled | 421 | * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled |
422 | * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range | 422 | * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range |
423 | * 1..32767] | 423 | * 1..32767] |
424 | * @cwmax: Maximum contention window [a value of the form 2^n-1 in the range | 424 | * @cwmax: Maximum contention window [a value of the form 2^n-1 in the range |
425 | * 1..32767] | 425 | * 1..32767] |
426 | * @aifs: Arbitration interframe space [0..255] | 426 | * @aifs: Arbitration interframe space [0..255] |
427 | */ | 427 | */ |
428 | struct ieee80211_txq_params { | 428 | struct ieee80211_txq_params { |
429 | enum nl80211_txq_q queue; | 429 | enum nl80211_txq_q queue; |
430 | u16 txop; | 430 | u16 txop; |
431 | u16 cwmin; | 431 | u16 cwmin; |
432 | u16 cwmax; | 432 | u16 cwmax; |
433 | u8 aifs; | 433 | u8 aifs; |
434 | }; | 434 | }; |
435 | 435 | ||
436 | /* from net/wireless.h */ | 436 | /* from net/wireless.h */ |
437 | struct wiphy; | 437 | struct wiphy; |
438 | 438 | ||
439 | /* from net/ieee80211.h */ | 439 | /* from net/ieee80211.h */ |
440 | struct ieee80211_channel; | 440 | struct ieee80211_channel; |
441 | 441 | ||
442 | /** | 442 | /** |
443 | * struct cfg80211_ops - backend description for wireless configuration | 443 | * struct cfg80211_ops - backend description for wireless configuration |
444 | * | 444 | * |
445 | * This struct is registered by fullmac card drivers and/or wireless stacks | 445 | * This struct is registered by fullmac card drivers and/or wireless stacks |
446 | * in order to handle configuration requests on their interfaces. | 446 | * in order to handle configuration requests on their interfaces. |
447 | * | 447 | * |
448 | * All callbacks except where otherwise noted should return 0 | 448 | * All callbacks except where otherwise noted should return 0 |
449 | * on success or a negative error code. | 449 | * on success or a negative error code. |
450 | * | 450 | * |
451 | * All operations are currently invoked under rtnl for consistency with the | 451 | * All operations are currently invoked under rtnl for consistency with the |
452 | * wireless extensions but this is subject to reevaluation as soon as this | 452 | * wireless extensions but this is subject to reevaluation as soon as this |
453 | * code is used more widely and we have a first user without wext. | 453 | * code is used more widely and we have a first user without wext. |
454 | * | 454 | * |
455 | * @add_virtual_intf: create a new virtual interface with the given name, | 455 | * @add_virtual_intf: create a new virtual interface with the given name, |
456 | * must set the struct wireless_dev's iftype. | 456 | * must set the struct wireless_dev's iftype. |
457 | * | 457 | * |
458 | * @del_virtual_intf: remove the virtual interface determined by ifindex. | 458 | * @del_virtual_intf: remove the virtual interface determined by ifindex. |
459 | * | 459 | * |
460 | * @change_virtual_intf: change type/configuration of virtual interface, | 460 | * @change_virtual_intf: change type/configuration of virtual interface, |
461 | * keep the struct wireless_dev's iftype updated. | 461 | * keep the struct wireless_dev's iftype updated. |
462 | * | 462 | * |
463 | * @add_key: add a key with the given parameters. @mac_addr will be %NULL | 463 | * @add_key: add a key with the given parameters. @mac_addr will be %NULL |
464 | * when adding a group key. | 464 | * when adding a group key. |
465 | * | 465 | * |
466 | * @get_key: get information about the key with the given parameters. | 466 | * @get_key: get information about the key with the given parameters. |
467 | * @mac_addr will be %NULL when requesting information for a group | 467 | * @mac_addr will be %NULL when requesting information for a group |
468 | * key. All pointers given to the @callback function need not be valid | 468 | * key. All pointers given to the @callback function need not be valid |
469 | * after it returns. | 469 | * after it returns. |
470 | * | 470 | * |
471 | * @del_key: remove a key given the @mac_addr (%NULL for a group key) | 471 | * @del_key: remove a key given the @mac_addr (%NULL for a group key) |
472 | * and @key_index | 472 | * and @key_index |
473 | * | 473 | * |
474 | * @set_default_key: set the default key on an interface | 474 | * @set_default_key: set the default key on an interface |
475 | * | 475 | * |
476 | * @set_default_mgmt_key: set the default management frame key on an interface | ||
477 | * | ||
476 | * @add_beacon: Add a beacon with given parameters, @head, @interval | 478 | * @add_beacon: Add a beacon with given parameters, @head, @interval |
477 | * and @dtim_period will be valid, @tail is optional. | 479 | * and @dtim_period will be valid, @tail is optional. |
478 | * @set_beacon: Change the beacon parameters for an access point mode | 480 | * @set_beacon: Change the beacon parameters for an access point mode |
479 | * interface. This should reject the call when no beacon has been | 481 | * interface. This should reject the call when no beacon has been |
480 | * configured. | 482 | * configured. |
481 | * @del_beacon: Remove beacon configuration and stop sending the beacon. | 483 | * @del_beacon: Remove beacon configuration and stop sending the beacon. |
482 | * | 484 | * |
483 | * @add_station: Add a new station. | 485 | * @add_station: Add a new station. |
484 | * | 486 | * |
485 | * @del_station: Remove a station; @mac may be NULL to remove all stations. | 487 | * @del_station: Remove a station; @mac may be NULL to remove all stations. |
486 | * | 488 | * |
487 | * @change_station: Modify a given station. | 489 | * @change_station: Modify a given station. |
488 | * | 490 | * |
489 | * @get_mesh_params: Put the current mesh parameters into *params | 491 | * @get_mesh_params: Put the current mesh parameters into *params |
490 | * | 492 | * |
491 | * @set_mesh_params: Set mesh parameters. | 493 | * @set_mesh_params: Set mesh parameters. |
492 | * The mask is a bitfield which tells us which parameters to | 494 | * The mask is a bitfield which tells us which parameters to |
493 | * set, and which to leave alone. | 495 | * set, and which to leave alone. |
494 | * | 496 | * |
495 | * @set_mesh_cfg: set mesh parameters (by now, just mesh id) | 497 | * @set_mesh_cfg: set mesh parameters (by now, just mesh id) |
496 | * | 498 | * |
497 | * @change_bss: Modify parameters for a given BSS. | 499 | * @change_bss: Modify parameters for a given BSS. |
498 | * | 500 | * |
499 | * @set_txq_params: Set TX queue parameters | 501 | * @set_txq_params: Set TX queue parameters |
500 | * | 502 | * |
501 | * @set_channel: Set channel | 503 | * @set_channel: Set channel |
502 | */ | 504 | */ |
503 | struct cfg80211_ops { | 505 | struct cfg80211_ops { |
504 | int (*add_virtual_intf)(struct wiphy *wiphy, char *name, | 506 | int (*add_virtual_intf)(struct wiphy *wiphy, char *name, |
505 | enum nl80211_iftype type, u32 *flags, | 507 | enum nl80211_iftype type, u32 *flags, |
506 | struct vif_params *params); | 508 | struct vif_params *params); |
507 | int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex); | 509 | int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex); |
508 | int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex, | 510 | int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex, |
509 | enum nl80211_iftype type, u32 *flags, | 511 | enum nl80211_iftype type, u32 *flags, |
510 | struct vif_params *params); | 512 | struct vif_params *params); |
511 | 513 | ||
512 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, | 514 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, |
513 | u8 key_index, u8 *mac_addr, | 515 | u8 key_index, u8 *mac_addr, |
514 | struct key_params *params); | 516 | struct key_params *params); |
515 | int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, | 517 | int (*get_key)(struct wiphy *wiphy, struct net_device *netdev, |
516 | u8 key_index, u8 *mac_addr, void *cookie, | 518 | u8 key_index, u8 *mac_addr, void *cookie, |
517 | void (*callback)(void *cookie, struct key_params*)); | 519 | void (*callback)(void *cookie, struct key_params*)); |
518 | int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, | 520 | int (*del_key)(struct wiphy *wiphy, struct net_device *netdev, |
519 | u8 key_index, u8 *mac_addr); | 521 | u8 key_index, u8 *mac_addr); |
520 | int (*set_default_key)(struct wiphy *wiphy, | 522 | int (*set_default_key)(struct wiphy *wiphy, |
521 | struct net_device *netdev, | 523 | struct net_device *netdev, |
522 | u8 key_index); | 524 | u8 key_index); |
525 | int (*set_default_mgmt_key)(struct wiphy *wiphy, | ||
526 | struct net_device *netdev, | ||
527 | u8 key_index); | ||
523 | 528 | ||
524 | int (*add_beacon)(struct wiphy *wiphy, struct net_device *dev, | 529 | int (*add_beacon)(struct wiphy *wiphy, struct net_device *dev, |
525 | struct beacon_parameters *info); | 530 | struct beacon_parameters *info); |
526 | int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev, | 531 | int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev, |
527 | struct beacon_parameters *info); | 532 | struct beacon_parameters *info); |
528 | int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev); | 533 | int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev); |
529 | 534 | ||
530 | 535 | ||
531 | int (*add_station)(struct wiphy *wiphy, struct net_device *dev, | 536 | int (*add_station)(struct wiphy *wiphy, struct net_device *dev, |
532 | u8 *mac, struct station_parameters *params); | 537 | u8 *mac, struct station_parameters *params); |
533 | int (*del_station)(struct wiphy *wiphy, struct net_device *dev, | 538 | int (*del_station)(struct wiphy *wiphy, struct net_device *dev, |
534 | u8 *mac); | 539 | u8 *mac); |
535 | int (*change_station)(struct wiphy *wiphy, struct net_device *dev, | 540 | int (*change_station)(struct wiphy *wiphy, struct net_device *dev, |
536 | u8 *mac, struct station_parameters *params); | 541 | u8 *mac, struct station_parameters *params); |
537 | int (*get_station)(struct wiphy *wiphy, struct net_device *dev, | 542 | int (*get_station)(struct wiphy *wiphy, struct net_device *dev, |
538 | u8 *mac, struct station_info *sinfo); | 543 | u8 *mac, struct station_info *sinfo); |
539 | int (*dump_station)(struct wiphy *wiphy, struct net_device *dev, | 544 | int (*dump_station)(struct wiphy *wiphy, struct net_device *dev, |
540 | int idx, u8 *mac, struct station_info *sinfo); | 545 | int idx, u8 *mac, struct station_info *sinfo); |
541 | 546 | ||
542 | int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev, | 547 | int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev, |
543 | u8 *dst, u8 *next_hop); | 548 | u8 *dst, u8 *next_hop); |
544 | int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev, | 549 | int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev, |
545 | u8 *dst); | 550 | u8 *dst); |
546 | int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev, | 551 | int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev, |
547 | u8 *dst, u8 *next_hop); | 552 | u8 *dst, u8 *next_hop); |
548 | int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev, | 553 | int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev, |
549 | u8 *dst, u8 *next_hop, | 554 | u8 *dst, u8 *next_hop, |
550 | struct mpath_info *pinfo); | 555 | struct mpath_info *pinfo); |
551 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, | 556 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, |
552 | int idx, u8 *dst, u8 *next_hop, | 557 | int idx, u8 *dst, u8 *next_hop, |
553 | struct mpath_info *pinfo); | 558 | struct mpath_info *pinfo); |
554 | int (*get_mesh_params)(struct wiphy *wiphy, | 559 | int (*get_mesh_params)(struct wiphy *wiphy, |
555 | struct net_device *dev, | 560 | struct net_device *dev, |
556 | struct mesh_config *conf); | 561 | struct mesh_config *conf); |
557 | int (*set_mesh_params)(struct wiphy *wiphy, | 562 | int (*set_mesh_params)(struct wiphy *wiphy, |
558 | struct net_device *dev, | 563 | struct net_device *dev, |
559 | const struct mesh_config *nconf, u32 mask); | 564 | const struct mesh_config *nconf, u32 mask); |
560 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, | 565 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, |
561 | struct bss_parameters *params); | 566 | struct bss_parameters *params); |
562 | 567 | ||
563 | int (*set_txq_params)(struct wiphy *wiphy, | 568 | int (*set_txq_params)(struct wiphy *wiphy, |
564 | struct ieee80211_txq_params *params); | 569 | struct ieee80211_txq_params *params); |
565 | 570 | ||
566 | int (*set_channel)(struct wiphy *wiphy, | 571 | int (*set_channel)(struct wiphy *wiphy, |
567 | struct ieee80211_channel *chan, | 572 | struct ieee80211_channel *chan, |
568 | enum nl80211_channel_type channel_type); | 573 | enum nl80211_channel_type channel_type); |
569 | }; | 574 | }; |
570 | 575 | ||
571 | /* temporary wext handlers */ | 576 | /* temporary wext handlers */ |
572 | int cfg80211_wext_giwname(struct net_device *dev, | 577 | int cfg80211_wext_giwname(struct net_device *dev, |
573 | struct iw_request_info *info, | 578 | struct iw_request_info *info, |
574 | char *name, char *extra); | 579 | char *name, char *extra); |
575 | int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, | 580 | int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, |
576 | u32 *mode, char *extra); | 581 | u32 *mode, char *extra); |
577 | int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, | 582 | int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, |
578 | u32 *mode, char *extra); | 583 | u32 *mode, char *extra); |
579 | 584 | ||
580 | #endif /* __NET_CFG80211_H */ | 585 | #endif /* __NET_CFG80211_H */ |
581 | 586 |
include/net/mac80211.h
1 | /* | 1 | /* |
2 | * mac80211 <-> driver interface | 2 | * mac80211 <-> driver interface |
3 | * | 3 | * |
4 | * Copyright 2002-2005, Devicescape Software, Inc. | 4 | * Copyright 2002-2005, Devicescape Software, Inc. |
5 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 5 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
6 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef MAC80211_H | 13 | #ifndef MAC80211_H |
14 | #define MAC80211_H | 14 | #define MAC80211_H |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/if_ether.h> | 17 | #include <linux/if_ether.h> |
18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
19 | #include <linux/wireless.h> | 19 | #include <linux/wireless.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/ieee80211.h> | 21 | #include <linux/ieee80211.h> |
22 | #include <net/wireless.h> | 22 | #include <net/wireless.h> |
23 | #include <net/cfg80211.h> | 23 | #include <net/cfg80211.h> |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * DOC: Introduction | 26 | * DOC: Introduction |
27 | * | 27 | * |
28 | * mac80211 is the Linux stack for 802.11 hardware that implements | 28 | * mac80211 is the Linux stack for 802.11 hardware that implements |
29 | * only partial functionality in hard- or firmware. This document | 29 | * only partial functionality in hard- or firmware. This document |
30 | * defines the interface between mac80211 and low-level hardware | 30 | * defines the interface between mac80211 and low-level hardware |
31 | * drivers. | 31 | * drivers. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | /** | 34 | /** |
35 | * DOC: Calling mac80211 from interrupts | 35 | * DOC: Calling mac80211 from interrupts |
36 | * | 36 | * |
37 | * Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be | 37 | * Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be |
38 | * called in hardware interrupt context. The low-level driver must not call any | 38 | * called in hardware interrupt context. The low-level driver must not call any |
39 | * other functions in hardware interrupt context. If there is a need for such | 39 | * other functions in hardware interrupt context. If there is a need for such |
40 | * call, the low-level driver should first ACK the interrupt and perform the | 40 | * call, the low-level driver should first ACK the interrupt and perform the |
41 | * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even | 41 | * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even |
42 | * tasklet function. | 42 | * tasklet function. |
43 | * | 43 | * |
44 | * NOTE: If the driver opts to use the _irqsafe() functions, it may not also | 44 | * NOTE: If the driver opts to use the _irqsafe() functions, it may not also |
45 | * use the non-IRQ-safe functions! | 45 | * use the non-IRQ-safe functions! |
46 | */ | 46 | */ |
47 | 47 | ||
48 | /** | 48 | /** |
49 | * DOC: Warning | 49 | * DOC: Warning |
50 | * | 50 | * |
51 | * If you're reading this document and not the header file itself, it will | 51 | * If you're reading this document and not the header file itself, it will |
52 | * be incomplete because not all documentation has been converted yet. | 52 | * be incomplete because not all documentation has been converted yet. |
53 | */ | 53 | */ |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * DOC: Frame format | 56 | * DOC: Frame format |
57 | * | 57 | * |
58 | * As a general rule, when frames are passed between mac80211 and the driver, | 58 | * As a general rule, when frames are passed between mac80211 and the driver, |
59 | * they start with the IEEE 802.11 header and include the same octets that are | 59 | * they start with the IEEE 802.11 header and include the same octets that are |
60 | * sent over the air except for the FCS which should be calculated by the | 60 | * sent over the air except for the FCS which should be calculated by the |
61 | * hardware. | 61 | * hardware. |
62 | * | 62 | * |
63 | * There are, however, various exceptions to this rule for advanced features: | 63 | * There are, however, various exceptions to this rule for advanced features: |
64 | * | 64 | * |
65 | * The first exception is for hardware encryption and decryption offload | 65 | * The first exception is for hardware encryption and decryption offload |
66 | * where the IV/ICV may or may not be generated in hardware. | 66 | * where the IV/ICV may or may not be generated in hardware. |
67 | * | 67 | * |
68 | * Secondly, when the hardware handles fragmentation, the frame handed to | 68 | * Secondly, when the hardware handles fragmentation, the frame handed to |
69 | * the driver from mac80211 is the MSDU, not the MPDU. | 69 | * the driver from mac80211 is the MSDU, not the MPDU. |
70 | * | 70 | * |
71 | * Finally, for received frames, the driver is able to indicate that it has | 71 | * Finally, for received frames, the driver is able to indicate that it has |
72 | * filled a radiotap header and put that in front of the frame; if it does | 72 | * filled a radiotap header and put that in front of the frame; if it does |
73 | * not do so then mac80211 may add this under certain circumstances. | 73 | * not do so then mac80211 may add this under certain circumstances. |
74 | */ | 74 | */ |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * struct ieee80211_ht_bss_info - describing BSS's HT characteristics | 77 | * struct ieee80211_ht_bss_info - describing BSS's HT characteristics |
78 | * | 78 | * |
79 | * This structure describes most essential parameters needed | 79 | * This structure describes most essential parameters needed |
80 | * to describe 802.11n HT characteristics in a BSS. | 80 | * to describe 802.11n HT characteristics in a BSS. |
81 | * | 81 | * |
82 | * @primary_channel: channel number of primery channel | 82 | * @primary_channel: channel number of primery channel |
83 | * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width) | 83 | * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width) |
84 | * @bss_op_mode: 802.11n's BSS operation modes (e.g. HT protection) | 84 | * @bss_op_mode: 802.11n's BSS operation modes (e.g. HT protection) |
85 | */ | 85 | */ |
86 | struct ieee80211_ht_bss_info { | 86 | struct ieee80211_ht_bss_info { |
87 | u8 primary_channel; | 87 | u8 primary_channel; |
88 | u8 bss_cap; /* use IEEE80211_HT_IE_CHA_ */ | 88 | u8 bss_cap; /* use IEEE80211_HT_IE_CHA_ */ |
89 | u8 bss_op_mode; /* use IEEE80211_HT_IE_ */ | 89 | u8 bss_op_mode; /* use IEEE80211_HT_IE_ */ |
90 | }; | 90 | }; |
91 | 91 | ||
92 | /** | 92 | /** |
93 | * enum ieee80211_max_queues - maximum number of queues | 93 | * enum ieee80211_max_queues - maximum number of queues |
94 | * | 94 | * |
95 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. | 95 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. |
96 | * @IEEE80211_MAX_AMPDU_QUEUES: Maximum number of queues usable | 96 | * @IEEE80211_MAX_AMPDU_QUEUES: Maximum number of queues usable |
97 | * for A-MPDU operation. | 97 | * for A-MPDU operation. |
98 | */ | 98 | */ |
99 | enum ieee80211_max_queues { | 99 | enum ieee80211_max_queues { |
100 | IEEE80211_MAX_QUEUES = 16, | 100 | IEEE80211_MAX_QUEUES = 16, |
101 | IEEE80211_MAX_AMPDU_QUEUES = 16, | 101 | IEEE80211_MAX_AMPDU_QUEUES = 16, |
102 | }; | 102 | }; |
103 | 103 | ||
104 | /** | 104 | /** |
105 | * struct ieee80211_tx_queue_params - transmit queue configuration | 105 | * struct ieee80211_tx_queue_params - transmit queue configuration |
106 | * | 106 | * |
107 | * The information provided in this structure is required for QoS | 107 | * The information provided in this structure is required for QoS |
108 | * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29. | 108 | * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29. |
109 | * | 109 | * |
110 | * @aifs: arbitration interframe space [0..255] | 110 | * @aifs: arbitration interframe space [0..255] |
111 | * @cw_min: minimum contention window [a value of the form | 111 | * @cw_min: minimum contention window [a value of the form |
112 | * 2^n-1 in the range 1..32767] | 112 | * 2^n-1 in the range 1..32767] |
113 | * @cw_max: maximum contention window [like @cw_min] | 113 | * @cw_max: maximum contention window [like @cw_min] |
114 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled | 114 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled |
115 | */ | 115 | */ |
116 | struct ieee80211_tx_queue_params { | 116 | struct ieee80211_tx_queue_params { |
117 | u16 txop; | 117 | u16 txop; |
118 | u16 cw_min; | 118 | u16 cw_min; |
119 | u16 cw_max; | 119 | u16 cw_max; |
120 | u8 aifs; | 120 | u8 aifs; |
121 | }; | 121 | }; |
122 | 122 | ||
123 | /** | 123 | /** |
124 | * struct ieee80211_tx_queue_stats - transmit queue statistics | 124 | * struct ieee80211_tx_queue_stats - transmit queue statistics |
125 | * | 125 | * |
126 | * @len: number of packets in queue | 126 | * @len: number of packets in queue |
127 | * @limit: queue length limit | 127 | * @limit: queue length limit |
128 | * @count: number of frames sent | 128 | * @count: number of frames sent |
129 | */ | 129 | */ |
130 | struct ieee80211_tx_queue_stats { | 130 | struct ieee80211_tx_queue_stats { |
131 | unsigned int len; | 131 | unsigned int len; |
132 | unsigned int limit; | 132 | unsigned int limit; |
133 | unsigned int count; | 133 | unsigned int count; |
134 | }; | 134 | }; |
135 | 135 | ||
136 | struct ieee80211_low_level_stats { | 136 | struct ieee80211_low_level_stats { |
137 | unsigned int dot11ACKFailureCount; | 137 | unsigned int dot11ACKFailureCount; |
138 | unsigned int dot11RTSFailureCount; | 138 | unsigned int dot11RTSFailureCount; |
139 | unsigned int dot11FCSErrorCount; | 139 | unsigned int dot11FCSErrorCount; |
140 | unsigned int dot11RTSSuccessCount; | 140 | unsigned int dot11RTSSuccessCount; |
141 | }; | 141 | }; |
142 | 142 | ||
143 | /** | 143 | /** |
144 | * enum ieee80211_bss_change - BSS change notification flags | 144 | * enum ieee80211_bss_change - BSS change notification flags |
145 | * | 145 | * |
146 | * These flags are used with the bss_info_changed() callback | 146 | * These flags are used with the bss_info_changed() callback |
147 | * to indicate which BSS parameter changed. | 147 | * to indicate which BSS parameter changed. |
148 | * | 148 | * |
149 | * @BSS_CHANGED_ASSOC: association status changed (associated/disassociated), | 149 | * @BSS_CHANGED_ASSOC: association status changed (associated/disassociated), |
150 | * also implies a change in the AID. | 150 | * also implies a change in the AID. |
151 | * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed | 151 | * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed |
152 | * @BSS_CHANGED_ERP_PREAMBLE: preamble changed | 152 | * @BSS_CHANGED_ERP_PREAMBLE: preamble changed |
153 | * @BSS_CHANGED_ERP_SLOT: slot timing changed | 153 | * @BSS_CHANGED_ERP_SLOT: slot timing changed |
154 | * @BSS_CHANGED_HT: 802.11n parameters changed | 154 | * @BSS_CHANGED_HT: 802.11n parameters changed |
155 | * @BSS_CHANGED_BASIC_RATES: Basic rateset changed | 155 | * @BSS_CHANGED_BASIC_RATES: Basic rateset changed |
156 | */ | 156 | */ |
157 | enum ieee80211_bss_change { | 157 | enum ieee80211_bss_change { |
158 | BSS_CHANGED_ASSOC = 1<<0, | 158 | BSS_CHANGED_ASSOC = 1<<0, |
159 | BSS_CHANGED_ERP_CTS_PROT = 1<<1, | 159 | BSS_CHANGED_ERP_CTS_PROT = 1<<1, |
160 | BSS_CHANGED_ERP_PREAMBLE = 1<<2, | 160 | BSS_CHANGED_ERP_PREAMBLE = 1<<2, |
161 | BSS_CHANGED_ERP_SLOT = 1<<3, | 161 | BSS_CHANGED_ERP_SLOT = 1<<3, |
162 | BSS_CHANGED_HT = 1<<4, | 162 | BSS_CHANGED_HT = 1<<4, |
163 | BSS_CHANGED_BASIC_RATES = 1<<5, | 163 | BSS_CHANGED_BASIC_RATES = 1<<5, |
164 | }; | 164 | }; |
165 | 165 | ||
166 | /** | 166 | /** |
167 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration | 167 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration |
168 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) | 168 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) |
169 | */ | 169 | */ |
170 | struct ieee80211_bss_ht_conf { | 170 | struct ieee80211_bss_ht_conf { |
171 | u16 operation_mode; | 171 | u16 operation_mode; |
172 | }; | 172 | }; |
173 | 173 | ||
174 | /** | 174 | /** |
175 | * struct ieee80211_bss_conf - holds the BSS's changing parameters | 175 | * struct ieee80211_bss_conf - holds the BSS's changing parameters |
176 | * | 176 | * |
177 | * This structure keeps information about a BSS (and an association | 177 | * This structure keeps information about a BSS (and an association |
178 | * to that BSS) that can change during the lifetime of the BSS. | 178 | * to that BSS) that can change during the lifetime of the BSS. |
179 | * | 179 | * |
180 | * @assoc: association status | 180 | * @assoc: association status |
181 | * @aid: association ID number, valid only when @assoc is true | 181 | * @aid: association ID number, valid only when @assoc is true |
182 | * @use_cts_prot: use CTS protection | 182 | * @use_cts_prot: use CTS protection |
183 | * @use_short_preamble: use 802.11b short preamble; | 183 | * @use_short_preamble: use 802.11b short preamble; |
184 | * if the hardware cannot handle this it must set the | 184 | * if the hardware cannot handle this it must set the |
185 | * IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag | 185 | * IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag |
186 | * @use_short_slot: use short slot time (only relevant for ERP); | 186 | * @use_short_slot: use short slot time (only relevant for ERP); |
187 | * if the hardware cannot handle this it must set the | 187 | * if the hardware cannot handle this it must set the |
188 | * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag | 188 | * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag |
189 | * @dtim_period: num of beacons before the next DTIM, for PSM | 189 | * @dtim_period: num of beacons before the next DTIM, for PSM |
190 | * @timestamp: beacon timestamp | 190 | * @timestamp: beacon timestamp |
191 | * @beacon_int: beacon interval | 191 | * @beacon_int: beacon interval |
192 | * @assoc_capability: capabilities taken from assoc resp | 192 | * @assoc_capability: capabilities taken from assoc resp |
193 | * @ht: BSS's HT configuration | 193 | * @ht: BSS's HT configuration |
194 | * @basic_rates: bitmap of basic rates, each bit stands for an | 194 | * @basic_rates: bitmap of basic rates, each bit stands for an |
195 | * index into the rate table configured by the driver in | 195 | * index into the rate table configured by the driver in |
196 | * the current band. | 196 | * the current band. |
197 | */ | 197 | */ |
198 | struct ieee80211_bss_conf { | 198 | struct ieee80211_bss_conf { |
199 | /* association related data */ | 199 | /* association related data */ |
200 | bool assoc; | 200 | bool assoc; |
201 | u16 aid; | 201 | u16 aid; |
202 | /* erp related data */ | 202 | /* erp related data */ |
203 | bool use_cts_prot; | 203 | bool use_cts_prot; |
204 | bool use_short_preamble; | 204 | bool use_short_preamble; |
205 | bool use_short_slot; | 205 | bool use_short_slot; |
206 | u8 dtim_period; | 206 | u8 dtim_period; |
207 | u16 beacon_int; | 207 | u16 beacon_int; |
208 | u16 assoc_capability; | 208 | u16 assoc_capability; |
209 | u64 timestamp; | 209 | u64 timestamp; |
210 | u64 basic_rates; | 210 | u64 basic_rates; |
211 | struct ieee80211_bss_ht_conf ht; | 211 | struct ieee80211_bss_ht_conf ht; |
212 | }; | 212 | }; |
213 | 213 | ||
214 | /** | 214 | /** |
215 | * enum mac80211_tx_control_flags - flags to describe transmission information/status | 215 | * enum mac80211_tx_control_flags - flags to describe transmission information/status |
216 | * | 216 | * |
217 | * These flags are used with the @flags member of &ieee80211_tx_info. | 217 | * These flags are used with the @flags member of &ieee80211_tx_info. |
218 | * | 218 | * |
219 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. | 219 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. |
220 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence | 220 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence |
221 | * number to this frame, taking care of not overwriting the fragment | 221 | * number to this frame, taking care of not overwriting the fragment |
222 | * number and increasing the sequence number only when the | 222 | * number and increasing the sequence number only when the |
223 | * IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly | 223 | * IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly |
224 | * assign sequence numbers to QoS-data frames but cannot do so correctly | 224 | * assign sequence numbers to QoS-data frames but cannot do so correctly |
225 | * for non-QoS-data and management frames because beacons need them from | 225 | * for non-QoS-data and management frames because beacons need them from |
226 | * that counter as well and mac80211 cannot guarantee proper sequencing. | 226 | * that counter as well and mac80211 cannot guarantee proper sequencing. |
227 | * If this flag is set, the driver should instruct the hardware to | 227 | * If this flag is set, the driver should instruct the hardware to |
228 | * assign a sequence number to the frame or assign one itself. Cf. IEEE | 228 | * assign a sequence number to the frame or assign one itself. Cf. IEEE |
229 | * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for | 229 | * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for |
230 | * beacons and always be clear for frames without a sequence number field. | 230 | * beacons and always be clear for frames without a sequence number field. |
231 | * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack | 231 | * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack |
232 | * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination | 232 | * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination |
233 | * station | 233 | * station |
234 | * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame | 234 | * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame |
235 | * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon | 235 | * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon |
236 | * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU | 236 | * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU |
237 | * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. | 237 | * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. |
238 | * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted | 238 | * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted |
239 | * because the destination STA was in powersave mode. | 239 | * because the destination STA was in powersave mode. |
240 | * @IEEE80211_TX_STAT_ACK: Frame was acknowledged | 240 | * @IEEE80211_TX_STAT_ACK: Frame was acknowledged |
241 | * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status | 241 | * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status |
242 | * is for the whole aggregation. | 242 | * is for the whole aggregation. |
243 | * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, | 243 | * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, |
244 | * so consider using block ack request (BAR). | 244 | * so consider using block ack request (BAR). |
245 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be | 245 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be |
246 | * set by rate control algorithms to indicate probe rate, will | 246 | * set by rate control algorithms to indicate probe rate, will |
247 | * be cleared for fragmented frames (except on the last fragment) | 247 | * be cleared for fragmented frames (except on the last fragment) |
248 | */ | 248 | */ |
249 | enum mac80211_tx_control_flags { | 249 | enum mac80211_tx_control_flags { |
250 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 250 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
251 | IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), | 251 | IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), |
252 | IEEE80211_TX_CTL_NO_ACK = BIT(2), | 252 | IEEE80211_TX_CTL_NO_ACK = BIT(2), |
253 | IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3), | 253 | IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3), |
254 | IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4), | 254 | IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4), |
255 | IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5), | 255 | IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5), |
256 | IEEE80211_TX_CTL_AMPDU = BIT(6), | 256 | IEEE80211_TX_CTL_AMPDU = BIT(6), |
257 | IEEE80211_TX_CTL_INJECTED = BIT(7), | 257 | IEEE80211_TX_CTL_INJECTED = BIT(7), |
258 | IEEE80211_TX_STAT_TX_FILTERED = BIT(8), | 258 | IEEE80211_TX_STAT_TX_FILTERED = BIT(8), |
259 | IEEE80211_TX_STAT_ACK = BIT(9), | 259 | IEEE80211_TX_STAT_ACK = BIT(9), |
260 | IEEE80211_TX_STAT_AMPDU = BIT(10), | 260 | IEEE80211_TX_STAT_AMPDU = BIT(10), |
261 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), | 261 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), |
262 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), | 262 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), |
263 | }; | 263 | }; |
264 | 264 | ||
265 | enum mac80211_rate_control_flags { | 265 | enum mac80211_rate_control_flags { |
266 | IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), | 266 | IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), |
267 | IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), | 267 | IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), |
268 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), | 268 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), |
269 | 269 | ||
270 | /* rate index is an MCS rate number instead of an index */ | 270 | /* rate index is an MCS rate number instead of an index */ |
271 | IEEE80211_TX_RC_MCS = BIT(3), | 271 | IEEE80211_TX_RC_MCS = BIT(3), |
272 | IEEE80211_TX_RC_GREEN_FIELD = BIT(4), | 272 | IEEE80211_TX_RC_GREEN_FIELD = BIT(4), |
273 | IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), | 273 | IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), |
274 | IEEE80211_TX_RC_DUP_DATA = BIT(6), | 274 | IEEE80211_TX_RC_DUP_DATA = BIT(6), |
275 | IEEE80211_TX_RC_SHORT_GI = BIT(7), | 275 | IEEE80211_TX_RC_SHORT_GI = BIT(7), |
276 | }; | 276 | }; |
277 | 277 | ||
278 | 278 | ||
279 | /* there are 40 bytes if you don't need the rateset to be kept */ | 279 | /* there are 40 bytes if you don't need the rateset to be kept */ |
280 | #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40 | 280 | #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40 |
281 | 281 | ||
282 | /* if you do need the rateset, then you have less space */ | 282 | /* if you do need the rateset, then you have less space */ |
283 | #define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 | 283 | #define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 |
284 | 284 | ||
285 | /* maximum number of rate stages */ | 285 | /* maximum number of rate stages */ |
286 | #define IEEE80211_TX_MAX_RATES 5 | 286 | #define IEEE80211_TX_MAX_RATES 5 |
287 | 287 | ||
288 | /** | 288 | /** |
289 | * struct ieee80211_tx_rate - rate selection/status | 289 | * struct ieee80211_tx_rate - rate selection/status |
290 | * | 290 | * |
291 | * @idx: rate index to attempt to send with | 291 | * @idx: rate index to attempt to send with |
292 | * @flags: rate control flags (&enum mac80211_rate_control_flags) | 292 | * @flags: rate control flags (&enum mac80211_rate_control_flags) |
293 | * @count: number of tries in this rate before going to the next rate | 293 | * @count: number of tries in this rate before going to the next rate |
294 | * | 294 | * |
295 | * A value of -1 for @idx indicates an invalid rate and, if used | 295 | * A value of -1 for @idx indicates an invalid rate and, if used |
296 | * in an array of retry rates, that no more rates should be tried. | 296 | * in an array of retry rates, that no more rates should be tried. |
297 | * | 297 | * |
298 | * When used for transmit status reporting, the driver should | 298 | * When used for transmit status reporting, the driver should |
299 | * always report the rate along with the flags it used. | 299 | * always report the rate along with the flags it used. |
300 | */ | 300 | */ |
301 | struct ieee80211_tx_rate { | 301 | struct ieee80211_tx_rate { |
302 | s8 idx; | 302 | s8 idx; |
303 | u8 count; | 303 | u8 count; |
304 | u8 flags; | 304 | u8 flags; |
305 | } __attribute__((packed)); | 305 | } __attribute__((packed)); |
306 | 306 | ||
307 | /** | 307 | /** |
308 | * struct ieee80211_tx_info - skb transmit information | 308 | * struct ieee80211_tx_info - skb transmit information |
309 | * | 309 | * |
310 | * This structure is placed in skb->cb for three uses: | 310 | * This structure is placed in skb->cb for three uses: |
311 | * (1) mac80211 TX control - mac80211 tells the driver what to do | 311 | * (1) mac80211 TX control - mac80211 tells the driver what to do |
312 | * (2) driver internal use (if applicable) | 312 | * (2) driver internal use (if applicable) |
313 | * (3) TX status information - driver tells mac80211 what happened | 313 | * (3) TX status information - driver tells mac80211 what happened |
314 | * | 314 | * |
315 | * The TX control's sta pointer is only valid during the ->tx call, | 315 | * The TX control's sta pointer is only valid during the ->tx call, |
316 | * it may be NULL. | 316 | * it may be NULL. |
317 | * | 317 | * |
318 | * @flags: transmit info flags, defined above | 318 | * @flags: transmit info flags, defined above |
319 | * @band: the band to transmit on (use for checking for races) | 319 | * @band: the band to transmit on (use for checking for races) |
320 | * @antenna_sel_tx: antenna to use, 0 for automatic diversity | 320 | * @antenna_sel_tx: antenna to use, 0 for automatic diversity |
321 | * @pad: padding, ignore | 321 | * @pad: padding, ignore |
322 | * @control: union for control data | 322 | * @control: union for control data |
323 | * @status: union for status data | 323 | * @status: union for status data |
324 | * @driver_data: array of driver_data pointers | 324 | * @driver_data: array of driver_data pointers |
325 | * @ampdu_ack_len: number of aggregated frames. | 325 | * @ampdu_ack_len: number of aggregated frames. |
326 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. | 326 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. |
327 | * @ampdu_ack_map: block ack bit map for the aggregation. | 327 | * @ampdu_ack_map: block ack bit map for the aggregation. |
328 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. | 328 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. |
329 | * @ack_signal: signal strength of the ACK frame | 329 | * @ack_signal: signal strength of the ACK frame |
330 | */ | 330 | */ |
331 | struct ieee80211_tx_info { | 331 | struct ieee80211_tx_info { |
332 | /* common information */ | 332 | /* common information */ |
333 | u32 flags; | 333 | u32 flags; |
334 | u8 band; | 334 | u8 band; |
335 | 335 | ||
336 | u8 antenna_sel_tx; | 336 | u8 antenna_sel_tx; |
337 | 337 | ||
338 | /* 2 byte hole */ | 338 | /* 2 byte hole */ |
339 | u8 pad[2]; | 339 | u8 pad[2]; |
340 | 340 | ||
341 | union { | 341 | union { |
342 | struct { | 342 | struct { |
343 | union { | 343 | union { |
344 | /* rate control */ | 344 | /* rate control */ |
345 | struct { | 345 | struct { |
346 | struct ieee80211_tx_rate rates[ | 346 | struct ieee80211_tx_rate rates[ |
347 | IEEE80211_TX_MAX_RATES]; | 347 | IEEE80211_TX_MAX_RATES]; |
348 | s8 rts_cts_rate_idx; | 348 | s8 rts_cts_rate_idx; |
349 | }; | 349 | }; |
350 | /* only needed before rate control */ | 350 | /* only needed before rate control */ |
351 | unsigned long jiffies; | 351 | unsigned long jiffies; |
352 | }; | 352 | }; |
353 | /* NB: vif can be NULL for injected frames */ | 353 | /* NB: vif can be NULL for injected frames */ |
354 | struct ieee80211_vif *vif; | 354 | struct ieee80211_vif *vif; |
355 | struct ieee80211_key_conf *hw_key; | 355 | struct ieee80211_key_conf *hw_key; |
356 | struct ieee80211_sta *sta; | 356 | struct ieee80211_sta *sta; |
357 | } control; | 357 | } control; |
358 | struct { | 358 | struct { |
359 | struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; | 359 | struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; |
360 | u8 ampdu_ack_len; | 360 | u8 ampdu_ack_len; |
361 | u64 ampdu_ack_map; | 361 | u64 ampdu_ack_map; |
362 | int ack_signal; | 362 | int ack_signal; |
363 | /* 8 bytes free */ | 363 | /* 8 bytes free */ |
364 | } status; | 364 | } status; |
365 | struct { | 365 | struct { |
366 | struct ieee80211_tx_rate driver_rates[ | 366 | struct ieee80211_tx_rate driver_rates[ |
367 | IEEE80211_TX_MAX_RATES]; | 367 | IEEE80211_TX_MAX_RATES]; |
368 | void *rate_driver_data[ | 368 | void *rate_driver_data[ |
369 | IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)]; | 369 | IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)]; |
370 | }; | 370 | }; |
371 | void *driver_data[ | 371 | void *driver_data[ |
372 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)]; | 372 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)]; |
373 | }; | 373 | }; |
374 | }; | 374 | }; |
375 | 375 | ||
376 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) | 376 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) |
377 | { | 377 | { |
378 | return (struct ieee80211_tx_info *)skb->cb; | 378 | return (struct ieee80211_tx_info *)skb->cb; |
379 | } | 379 | } |
380 | 380 | ||
381 | /** | 381 | /** |
382 | * ieee80211_tx_info_clear_status - clear TX status | 382 | * ieee80211_tx_info_clear_status - clear TX status |
383 | * | 383 | * |
384 | * @info: The &struct ieee80211_tx_info to be cleared. | 384 | * @info: The &struct ieee80211_tx_info to be cleared. |
385 | * | 385 | * |
386 | * When the driver passes an skb back to mac80211, it must report | 386 | * When the driver passes an skb back to mac80211, it must report |
387 | * a number of things in TX status. This function clears everything | 387 | * a number of things in TX status. This function clears everything |
388 | * in the TX status but the rate control information (it does clear | 388 | * in the TX status but the rate control information (it does clear |
389 | * the count since you need to fill that in anyway). | 389 | * the count since you need to fill that in anyway). |
390 | * | 390 | * |
391 | * NOTE: You can only use this function if you do NOT use | 391 | * NOTE: You can only use this function if you do NOT use |
392 | * info->driver_data! Use info->rate_driver_data | 392 | * info->driver_data! Use info->rate_driver_data |
393 | * instead if you need only the less space that allows. | 393 | * instead if you need only the less space that allows. |
394 | */ | 394 | */ |
395 | static inline void | 395 | static inline void |
396 | ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | 396 | ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) |
397 | { | 397 | { |
398 | int i; | 398 | int i; |
399 | 399 | ||
400 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != | 400 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != |
401 | offsetof(struct ieee80211_tx_info, control.rates)); | 401 | offsetof(struct ieee80211_tx_info, control.rates)); |
402 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != | 402 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != |
403 | offsetof(struct ieee80211_tx_info, driver_rates)); | 403 | offsetof(struct ieee80211_tx_info, driver_rates)); |
404 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != 8); | 404 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != 8); |
405 | /* clear the rate counts */ | 405 | /* clear the rate counts */ |
406 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) | 406 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) |
407 | info->status.rates[i].count = 0; | 407 | info->status.rates[i].count = 0; |
408 | 408 | ||
409 | BUILD_BUG_ON( | 409 | BUILD_BUG_ON( |
410 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); | 410 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); |
411 | memset(&info->status.ampdu_ack_len, 0, | 411 | memset(&info->status.ampdu_ack_len, 0, |
412 | sizeof(struct ieee80211_tx_info) - | 412 | sizeof(struct ieee80211_tx_info) - |
413 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); | 413 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); |
414 | } | 414 | } |
415 | 415 | ||
416 | 416 | ||
417 | /** | 417 | /** |
418 | * enum mac80211_rx_flags - receive flags | 418 | * enum mac80211_rx_flags - receive flags |
419 | * | 419 | * |
420 | * These flags are used with the @flag member of &struct ieee80211_rx_status. | 420 | * These flags are used with the @flag member of &struct ieee80211_rx_status. |
421 | * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame. | 421 | * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame. |
422 | * Use together with %RX_FLAG_MMIC_STRIPPED. | 422 | * Use together with %RX_FLAG_MMIC_STRIPPED. |
423 | * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware. | 423 | * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware. |
424 | * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header. | 424 | * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header. |
425 | * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame, | 425 | * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame, |
426 | * verification has been done by the hardware. | 426 | * verification has been done by the hardware. |
427 | * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. | 427 | * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. |
428 | * If this flag is set, the stack cannot do any replay detection | 428 | * If this flag is set, the stack cannot do any replay detection |
429 | * hence the driver or hardware will have to do that. | 429 | * hence the driver or hardware will have to do that. |
430 | * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on | 430 | * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on |
431 | * the frame. | 431 | * the frame. |
432 | * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on | 432 | * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on |
433 | * the frame. | 433 | * the frame. |
434 | * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field) | 434 | * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field) |
435 | * is valid. This is useful in monitor mode and necessary for beacon frames | 435 | * is valid. This is useful in monitor mode and necessary for beacon frames |
436 | * to enable IBSS merging. | 436 | * to enable IBSS merging. |
437 | * @RX_FLAG_SHORTPRE: Short preamble was used for this frame | 437 | * @RX_FLAG_SHORTPRE: Short preamble was used for this frame |
438 | * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index | 438 | * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index |
439 | * @RX_FLAG_40MHZ: HT40 (40 MHz) was used | 439 | * @RX_FLAG_40MHZ: HT40 (40 MHz) was used |
440 | * @RX_FLAG_SHORT_GI: Short guard interval was used | 440 | * @RX_FLAG_SHORT_GI: Short guard interval was used |
441 | */ | 441 | */ |
442 | enum mac80211_rx_flags { | 442 | enum mac80211_rx_flags { |
443 | RX_FLAG_MMIC_ERROR = 1<<0, | 443 | RX_FLAG_MMIC_ERROR = 1<<0, |
444 | RX_FLAG_DECRYPTED = 1<<1, | 444 | RX_FLAG_DECRYPTED = 1<<1, |
445 | RX_FLAG_RADIOTAP = 1<<2, | 445 | RX_FLAG_RADIOTAP = 1<<2, |
446 | RX_FLAG_MMIC_STRIPPED = 1<<3, | 446 | RX_FLAG_MMIC_STRIPPED = 1<<3, |
447 | RX_FLAG_IV_STRIPPED = 1<<4, | 447 | RX_FLAG_IV_STRIPPED = 1<<4, |
448 | RX_FLAG_FAILED_FCS_CRC = 1<<5, | 448 | RX_FLAG_FAILED_FCS_CRC = 1<<5, |
449 | RX_FLAG_FAILED_PLCP_CRC = 1<<6, | 449 | RX_FLAG_FAILED_PLCP_CRC = 1<<6, |
450 | RX_FLAG_TSFT = 1<<7, | 450 | RX_FLAG_TSFT = 1<<7, |
451 | RX_FLAG_SHORTPRE = 1<<8, | 451 | RX_FLAG_SHORTPRE = 1<<8, |
452 | RX_FLAG_HT = 1<<9, | 452 | RX_FLAG_HT = 1<<9, |
453 | RX_FLAG_40MHZ = 1<<10, | 453 | RX_FLAG_40MHZ = 1<<10, |
454 | RX_FLAG_SHORT_GI = 1<<11, | 454 | RX_FLAG_SHORT_GI = 1<<11, |
455 | }; | 455 | }; |
456 | 456 | ||
457 | /** | 457 | /** |
458 | * struct ieee80211_rx_status - receive status | 458 | * struct ieee80211_rx_status - receive status |
459 | * | 459 | * |
460 | * The low-level driver should provide this information (the subset | 460 | * The low-level driver should provide this information (the subset |
461 | * supported by hardware) to the 802.11 code with each received | 461 | * supported by hardware) to the 802.11 code with each received |
462 | * frame. | 462 | * frame. |
463 | * | 463 | * |
464 | * @mactime: value in microseconds of the 64-bit Time Synchronization Function | 464 | * @mactime: value in microseconds of the 64-bit Time Synchronization Function |
465 | * (TSF) timer when the first data symbol (MPDU) arrived at the hardware. | 465 | * (TSF) timer when the first data symbol (MPDU) arrived at the hardware. |
466 | * @band: the active band when this frame was received | 466 | * @band: the active band when this frame was received |
467 | * @freq: frequency the radio was tuned to when receiving this frame, in MHz | 467 | * @freq: frequency the radio was tuned to when receiving this frame, in MHz |
468 | * @signal: signal strength when receiving this frame, either in dBm, in dB or | 468 | * @signal: signal strength when receiving this frame, either in dBm, in dB or |
469 | * unspecified depending on the hardware capabilities flags | 469 | * unspecified depending on the hardware capabilities flags |
470 | * @IEEE80211_HW_SIGNAL_* | 470 | * @IEEE80211_HW_SIGNAL_* |
471 | * @noise: noise when receiving this frame, in dBm. | 471 | * @noise: noise when receiving this frame, in dBm. |
472 | * @qual: overall signal quality indication, in percent (0-100). | 472 | * @qual: overall signal quality indication, in percent (0-100). |
473 | * @antenna: antenna used | 473 | * @antenna: antenna used |
474 | * @rate_idx: index of data rate into band's supported rates or MCS index if | 474 | * @rate_idx: index of data rate into band's supported rates or MCS index if |
475 | * HT rates are use (RX_FLAG_HT) | 475 | * HT rates are use (RX_FLAG_HT) |
476 | * @flag: %RX_FLAG_* | 476 | * @flag: %RX_FLAG_* |
477 | */ | 477 | */ |
478 | struct ieee80211_rx_status { | 478 | struct ieee80211_rx_status { |
479 | u64 mactime; | 479 | u64 mactime; |
480 | enum ieee80211_band band; | 480 | enum ieee80211_band band; |
481 | int freq; | 481 | int freq; |
482 | int signal; | 482 | int signal; |
483 | int noise; | 483 | int noise; |
484 | int qual; | 484 | int qual; |
485 | int antenna; | 485 | int antenna; |
486 | int rate_idx; | 486 | int rate_idx; |
487 | int flag; | 487 | int flag; |
488 | }; | 488 | }; |
489 | 489 | ||
490 | /** | 490 | /** |
491 | * enum ieee80211_conf_flags - configuration flags | 491 | * enum ieee80211_conf_flags - configuration flags |
492 | * | 492 | * |
493 | * Flags to define PHY configuration options | 493 | * Flags to define PHY configuration options |
494 | * | 494 | * |
495 | * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) | 495 | * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) |
496 | * @IEEE80211_CONF_PS: Enable 802.11 power save mode | 496 | * @IEEE80211_CONF_PS: Enable 802.11 power save mode |
497 | */ | 497 | */ |
498 | enum ieee80211_conf_flags { | 498 | enum ieee80211_conf_flags { |
499 | IEEE80211_CONF_RADIOTAP = (1<<0), | 499 | IEEE80211_CONF_RADIOTAP = (1<<0), |
500 | IEEE80211_CONF_PS = (1<<1), | 500 | IEEE80211_CONF_PS = (1<<1), |
501 | }; | 501 | }; |
502 | 502 | ||
503 | /* XXX: remove all this once drivers stop trying to use it */ | 503 | /* XXX: remove all this once drivers stop trying to use it */ |
504 | static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) | 504 | static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) |
505 | { | 505 | { |
506 | return 0; | 506 | return 0; |
507 | } | 507 | } |
508 | #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) | 508 | #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) |
509 | 509 | ||
510 | /** | 510 | /** |
511 | * enum ieee80211_conf_changed - denotes which configuration changed | 511 | * enum ieee80211_conf_changed - denotes which configuration changed |
512 | * | 512 | * |
513 | * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed | 513 | * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed |
514 | * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed | 514 | * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed |
515 | * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed | 515 | * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed |
516 | * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed | 516 | * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed |
517 | * @IEEE80211_CONF_CHANGE_PS: the PS flag changed | 517 | * @IEEE80211_CONF_CHANGE_PS: the PS flag changed |
518 | * @IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT: the dynamic PS timeout changed | 518 | * @IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT: the dynamic PS timeout changed |
519 | * @IEEE80211_CONF_CHANGE_POWER: the TX power changed | 519 | * @IEEE80211_CONF_CHANGE_POWER: the TX power changed |
520 | * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed | 520 | * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed |
521 | * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed | 521 | * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed |
522 | */ | 522 | */ |
523 | enum ieee80211_conf_changed { | 523 | enum ieee80211_conf_changed { |
524 | IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), | 524 | IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), |
525 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), | 525 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), |
526 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), | 526 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), |
527 | IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), | 527 | IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), |
528 | IEEE80211_CONF_CHANGE_PS = BIT(4), | 528 | IEEE80211_CONF_CHANGE_PS = BIT(4), |
529 | IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT = BIT(5), | 529 | IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT = BIT(5), |
530 | IEEE80211_CONF_CHANGE_POWER = BIT(6), | 530 | IEEE80211_CONF_CHANGE_POWER = BIT(6), |
531 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(7), | 531 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(7), |
532 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(8), | 532 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(8), |
533 | }; | 533 | }; |
534 | 534 | ||
535 | /** | 535 | /** |
536 | * struct ieee80211_conf - configuration of the device | 536 | * struct ieee80211_conf - configuration of the device |
537 | * | 537 | * |
538 | * This struct indicates how the driver shall configure the hardware. | 538 | * This struct indicates how the driver shall configure the hardware. |
539 | * | 539 | * |
540 | * @radio_enabled: when zero, driver is required to switch off the radio. | 540 | * @radio_enabled: when zero, driver is required to switch off the radio. |
541 | * @beacon_int: beacon interval (TODO make interface config) | 541 | * @beacon_int: beacon interval (TODO make interface config) |
542 | * @listen_interval: listen interval in units of beacon interval | 542 | * @listen_interval: listen interval in units of beacon interval |
543 | * @flags: configuration flags defined above | 543 | * @flags: configuration flags defined above |
544 | * @power_level: requested transmit power (in dBm) | 544 | * @power_level: requested transmit power (in dBm) |
545 | * @dynamic_ps_timeout: dynamic powersave timeout (in ms) | 545 | * @dynamic_ps_timeout: dynamic powersave timeout (in ms) |
546 | * @channel: the channel to tune to | 546 | * @channel: the channel to tune to |
547 | * @channel_type: the channel (HT) type | 547 | * @channel_type: the channel (HT) type |
548 | * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame | 548 | * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame |
549 | * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, | 549 | * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, |
550 | * but actually means the number of transmissions not the number of retries | 550 | * but actually means the number of transmissions not the number of retries |
551 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" | 551 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" |
552 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the | 552 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the |
553 | * number of transmissions not the number of retries | 553 | * number of transmissions not the number of retries |
554 | */ | 554 | */ |
555 | struct ieee80211_conf { | 555 | struct ieee80211_conf { |
556 | int beacon_int; | 556 | int beacon_int; |
557 | u32 flags; | 557 | u32 flags; |
558 | int power_level, dynamic_ps_timeout; | 558 | int power_level, dynamic_ps_timeout; |
559 | 559 | ||
560 | u16 listen_interval; | 560 | u16 listen_interval; |
561 | bool radio_enabled; | 561 | bool radio_enabled; |
562 | 562 | ||
563 | u8 long_frame_max_tx_count, short_frame_max_tx_count; | 563 | u8 long_frame_max_tx_count, short_frame_max_tx_count; |
564 | 564 | ||
565 | struct ieee80211_channel *channel; | 565 | struct ieee80211_channel *channel; |
566 | enum nl80211_channel_type channel_type; | 566 | enum nl80211_channel_type channel_type; |
567 | }; | 567 | }; |
568 | 568 | ||
569 | /** | 569 | /** |
570 | * struct ieee80211_vif - per-interface data | 570 | * struct ieee80211_vif - per-interface data |
571 | * | 571 | * |
572 | * Data in this structure is continually present for driver | 572 | * Data in this structure is continually present for driver |
573 | * use during the life of a virtual interface. | 573 | * use during the life of a virtual interface. |
574 | * | 574 | * |
575 | * @type: type of this virtual interface | 575 | * @type: type of this virtual interface |
576 | * @bss_conf: BSS configuration for this interface, either our own | 576 | * @bss_conf: BSS configuration for this interface, either our own |
577 | * or the BSS we're associated to | 577 | * or the BSS we're associated to |
578 | * @drv_priv: data area for driver use, will always be aligned to | 578 | * @drv_priv: data area for driver use, will always be aligned to |
579 | * sizeof(void *). | 579 | * sizeof(void *). |
580 | */ | 580 | */ |
581 | struct ieee80211_vif { | 581 | struct ieee80211_vif { |
582 | enum nl80211_iftype type; | 582 | enum nl80211_iftype type; |
583 | struct ieee80211_bss_conf bss_conf; | 583 | struct ieee80211_bss_conf bss_conf; |
584 | /* must be last */ | 584 | /* must be last */ |
585 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 585 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
586 | }; | 586 | }; |
587 | 587 | ||
588 | static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | 588 | static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) |
589 | { | 589 | { |
590 | #ifdef CONFIG_MAC80211_MESH | 590 | #ifdef CONFIG_MAC80211_MESH |
591 | return vif->type == NL80211_IFTYPE_MESH_POINT; | 591 | return vif->type == NL80211_IFTYPE_MESH_POINT; |
592 | #endif | 592 | #endif |
593 | return false; | 593 | return false; |
594 | } | 594 | } |
595 | 595 | ||
596 | /** | 596 | /** |
597 | * struct ieee80211_if_init_conf - initial configuration of an interface | 597 | * struct ieee80211_if_init_conf - initial configuration of an interface |
598 | * | 598 | * |
599 | * @vif: pointer to a driver-use per-interface structure. The pointer | 599 | * @vif: pointer to a driver-use per-interface structure. The pointer |
600 | * itself is also used for various functions including | 600 | * itself is also used for various functions including |
601 | * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). | 601 | * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). |
602 | * @type: one of &enum nl80211_iftype constants. Determines the type of | 602 | * @type: one of &enum nl80211_iftype constants. Determines the type of |
603 | * added/removed interface. | 603 | * added/removed interface. |
604 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid | 604 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid |
605 | * until the interface is removed (i.e. it cannot be used after | 605 | * until the interface is removed (i.e. it cannot be used after |
606 | * remove_interface() callback was called for this interface). | 606 | * remove_interface() callback was called for this interface). |
607 | * | 607 | * |
608 | * This structure is used in add_interface() and remove_interface() | 608 | * This structure is used in add_interface() and remove_interface() |
609 | * callbacks of &struct ieee80211_hw. | 609 | * callbacks of &struct ieee80211_hw. |
610 | * | 610 | * |
611 | * When you allow multiple interfaces to be added to your PHY, take care | 611 | * When you allow multiple interfaces to be added to your PHY, take care |
612 | * that the hardware can actually handle multiple MAC addresses. However, | 612 | * that the hardware can actually handle multiple MAC addresses. However, |
613 | * also take care that when there's no interface left with mac_addr != %NULL | 613 | * also take care that when there's no interface left with mac_addr != %NULL |
614 | * you remove the MAC address from the device to avoid acknowledging packets | 614 | * you remove the MAC address from the device to avoid acknowledging packets |
615 | * in pure monitor mode. | 615 | * in pure monitor mode. |
616 | */ | 616 | */ |
617 | struct ieee80211_if_init_conf { | 617 | struct ieee80211_if_init_conf { |
618 | enum nl80211_iftype type; | 618 | enum nl80211_iftype type; |
619 | struct ieee80211_vif *vif; | 619 | struct ieee80211_vif *vif; |
620 | void *mac_addr; | 620 | void *mac_addr; |
621 | }; | 621 | }; |
622 | 622 | ||
623 | /** | 623 | /** |
624 | * enum ieee80211_if_conf_change - interface config change flags | 624 | * enum ieee80211_if_conf_change - interface config change flags |
625 | * | 625 | * |
626 | * @IEEE80211_IFCC_BSSID: The BSSID changed. | 626 | * @IEEE80211_IFCC_BSSID: The BSSID changed. |
627 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed | 627 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed |
628 | * (currently AP and MESH only), use ieee80211_beacon_get(). | 628 | * (currently AP and MESH only), use ieee80211_beacon_get(). |
629 | */ | 629 | */ |
630 | enum ieee80211_if_conf_change { | 630 | enum ieee80211_if_conf_change { |
631 | IEEE80211_IFCC_BSSID = BIT(0), | 631 | IEEE80211_IFCC_BSSID = BIT(0), |
632 | IEEE80211_IFCC_BEACON = BIT(1), | 632 | IEEE80211_IFCC_BEACON = BIT(1), |
633 | }; | 633 | }; |
634 | 634 | ||
635 | /** | 635 | /** |
636 | * struct ieee80211_if_conf - configuration of an interface | 636 | * struct ieee80211_if_conf - configuration of an interface |
637 | * | 637 | * |
638 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. | 638 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. |
639 | * @bssid: BSSID of the network we are associated to/creating. | 639 | * @bssid: BSSID of the network we are associated to/creating. |
640 | * | 640 | * |
641 | * This structure is passed to the config_interface() callback of | 641 | * This structure is passed to the config_interface() callback of |
642 | * &struct ieee80211_hw. | 642 | * &struct ieee80211_hw. |
643 | */ | 643 | */ |
644 | struct ieee80211_if_conf { | 644 | struct ieee80211_if_conf { |
645 | u32 changed; | 645 | u32 changed; |
646 | u8 *bssid; | 646 | u8 *bssid; |
647 | }; | 647 | }; |
648 | 648 | ||
649 | /** | 649 | /** |
650 | * enum ieee80211_key_alg - key algorithm | 650 | * enum ieee80211_key_alg - key algorithm |
651 | * @ALG_WEP: WEP40 or WEP104 | 651 | * @ALG_WEP: WEP40 or WEP104 |
652 | * @ALG_TKIP: TKIP | 652 | * @ALG_TKIP: TKIP |
653 | * @ALG_CCMP: CCMP (AES) | 653 | * @ALG_CCMP: CCMP (AES) |
654 | * @ALG_AES_CMAC: AES-128-CMAC | ||
654 | */ | 655 | */ |
655 | enum ieee80211_key_alg { | 656 | enum ieee80211_key_alg { |
656 | ALG_WEP, | 657 | ALG_WEP, |
657 | ALG_TKIP, | 658 | ALG_TKIP, |
658 | ALG_CCMP, | 659 | ALG_CCMP, |
660 | ALG_AES_CMAC, | ||
659 | }; | 661 | }; |
660 | 662 | ||
661 | /** | 663 | /** |
662 | * enum ieee80211_key_len - key length | 664 | * enum ieee80211_key_len - key length |
663 | * @LEN_WEP40: WEP 5-byte long key | 665 | * @LEN_WEP40: WEP 5-byte long key |
664 | * @LEN_WEP104: WEP 13-byte long key | 666 | * @LEN_WEP104: WEP 13-byte long key |
665 | */ | 667 | */ |
666 | enum ieee80211_key_len { | 668 | enum ieee80211_key_len { |
667 | LEN_WEP40 = 5, | 669 | LEN_WEP40 = 5, |
668 | LEN_WEP104 = 13, | 670 | LEN_WEP104 = 13, |
669 | }; | 671 | }; |
670 | 672 | ||
671 | /** | 673 | /** |
672 | * enum ieee80211_key_flags - key flags | 674 | * enum ieee80211_key_flags - key flags |
673 | * | 675 | * |
674 | * These flags are used for communication about keys between the driver | 676 | * These flags are used for communication about keys between the driver |
675 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. | 677 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. |
676 | * | 678 | * |
677 | * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates | 679 | * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates |
678 | * that the STA this key will be used with could be using QoS. | 680 | * that the STA this key will be used with could be using QoS. |
679 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the | 681 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the |
680 | * driver to indicate that it requires IV generation for this | 682 | * driver to indicate that it requires IV generation for this |
681 | * particular key. | 683 | * particular key. |
682 | * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by | 684 | * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by |
683 | * the driver for a TKIP key if it requires Michael MIC | 685 | * the driver for a TKIP key if it requires Michael MIC |
684 | * generation in software. | 686 | * generation in software. |
685 | * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates | 687 | * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates |
686 | * that the key is pairwise rather then a shared key. | 688 | * that the key is pairwise rather then a shared key. |
687 | */ | 689 | */ |
688 | enum ieee80211_key_flags { | 690 | enum ieee80211_key_flags { |
689 | IEEE80211_KEY_FLAG_WMM_STA = 1<<0, | 691 | IEEE80211_KEY_FLAG_WMM_STA = 1<<0, |
690 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, | 692 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, |
691 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, | 693 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, |
692 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, | 694 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, |
693 | }; | 695 | }; |
694 | 696 | ||
695 | /** | 697 | /** |
696 | * struct ieee80211_key_conf - key information | 698 | * struct ieee80211_key_conf - key information |
697 | * | 699 | * |
698 | * This key information is given by mac80211 to the driver by | 700 | * This key information is given by mac80211 to the driver by |
699 | * the set_key() callback in &struct ieee80211_ops. | 701 | * the set_key() callback in &struct ieee80211_ops. |
700 | * | 702 | * |
701 | * @hw_key_idx: To be set by the driver, this is the key index the driver | 703 | * @hw_key_idx: To be set by the driver, this is the key index the driver |
702 | * wants to be given when a frame is transmitted and needs to be | 704 | * wants to be given when a frame is transmitted and needs to be |
703 | * encrypted in hardware. | 705 | * encrypted in hardware. |
704 | * @alg: The key algorithm. | 706 | * @alg: The key algorithm. |
705 | * @flags: key flags, see &enum ieee80211_key_flags. | 707 | * @flags: key flags, see &enum ieee80211_key_flags. |
706 | * @keyidx: the key index (0-3) | 708 | * @keyidx: the key index (0-3) |
707 | * @keylen: key material length | 709 | * @keylen: key material length |
708 | * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) | 710 | * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) |
709 | * data block: | 711 | * data block: |
710 | * - Temporal Encryption Key (128 bits) | 712 | * - Temporal Encryption Key (128 bits) |
711 | * - Temporal Authenticator Tx MIC Key (64 bits) | 713 | * - Temporal Authenticator Tx MIC Key (64 bits) |
712 | * - Temporal Authenticator Rx MIC Key (64 bits) | 714 | * - Temporal Authenticator Rx MIC Key (64 bits) |
713 | * @icv_len: The ICV length for this key type | 715 | * @icv_len: The ICV length for this key type |
714 | * @iv_len: The IV length for this key type | 716 | * @iv_len: The IV length for this key type |
715 | */ | 717 | */ |
716 | struct ieee80211_key_conf { | 718 | struct ieee80211_key_conf { |
717 | enum ieee80211_key_alg alg; | 719 | enum ieee80211_key_alg alg; |
718 | u8 icv_len; | 720 | u8 icv_len; |
719 | u8 iv_len; | 721 | u8 iv_len; |
720 | u8 hw_key_idx; | 722 | u8 hw_key_idx; |
721 | u8 flags; | 723 | u8 flags; |
722 | s8 keyidx; | 724 | s8 keyidx; |
723 | u8 keylen; | 725 | u8 keylen; |
724 | u8 key[0]; | 726 | u8 key[0]; |
725 | }; | 727 | }; |
726 | 728 | ||
727 | /** | 729 | /** |
728 | * enum set_key_cmd - key command | 730 | * enum set_key_cmd - key command |
729 | * | 731 | * |
730 | * Used with the set_key() callback in &struct ieee80211_ops, this | 732 | * Used with the set_key() callback in &struct ieee80211_ops, this |
731 | * indicates whether a key is being removed or added. | 733 | * indicates whether a key is being removed or added. |
732 | * | 734 | * |
733 | * @SET_KEY: a key is set | 735 | * @SET_KEY: a key is set |
734 | * @DISABLE_KEY: a key must be disabled | 736 | * @DISABLE_KEY: a key must be disabled |
735 | */ | 737 | */ |
736 | enum set_key_cmd { | 738 | enum set_key_cmd { |
737 | SET_KEY, DISABLE_KEY, | 739 | SET_KEY, DISABLE_KEY, |
738 | }; | 740 | }; |
739 | 741 | ||
740 | /** | 742 | /** |
741 | * struct ieee80211_sta - station table entry | 743 | * struct ieee80211_sta - station table entry |
742 | * | 744 | * |
743 | * A station table entry represents a station we are possibly | 745 | * A station table entry represents a station we are possibly |
744 | * communicating with. Since stations are RCU-managed in | 746 | * communicating with. Since stations are RCU-managed in |
745 | * mac80211, any ieee80211_sta pointer you get access to must | 747 | * mac80211, any ieee80211_sta pointer you get access to must |
746 | * either be protected by rcu_read_lock() explicitly or implicitly, | 748 | * either be protected by rcu_read_lock() explicitly or implicitly, |
747 | * or you must take good care to not use such a pointer after a | 749 | * or you must take good care to not use such a pointer after a |
748 | * call to your sta_notify callback that removed it. | 750 | * call to your sta_notify callback that removed it. |
749 | * | 751 | * |
750 | * @addr: MAC address | 752 | * @addr: MAC address |
751 | * @aid: AID we assigned to the station if we're an AP | 753 | * @aid: AID we assigned to the station if we're an AP |
752 | * @supp_rates: Bitmap of supported rates (per band) | 754 | * @supp_rates: Bitmap of supported rates (per band) |
753 | * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities | 755 | * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities |
754 | * @drv_priv: data area for driver use, will always be aligned to | 756 | * @drv_priv: data area for driver use, will always be aligned to |
755 | * sizeof(void *), size is determined in hw information. | 757 | * sizeof(void *), size is determined in hw information. |
756 | */ | 758 | */ |
757 | struct ieee80211_sta { | 759 | struct ieee80211_sta { |
758 | u64 supp_rates[IEEE80211_NUM_BANDS]; | 760 | u64 supp_rates[IEEE80211_NUM_BANDS]; |
759 | u8 addr[ETH_ALEN]; | 761 | u8 addr[ETH_ALEN]; |
760 | u16 aid; | 762 | u16 aid; |
761 | struct ieee80211_sta_ht_cap ht_cap; | 763 | struct ieee80211_sta_ht_cap ht_cap; |
762 | 764 | ||
763 | /* must be last */ | 765 | /* must be last */ |
764 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 766 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
765 | }; | 767 | }; |
766 | 768 | ||
767 | /** | 769 | /** |
768 | * enum sta_notify_cmd - sta notify command | 770 | * enum sta_notify_cmd - sta notify command |
769 | * | 771 | * |
770 | * Used with the sta_notify() callback in &struct ieee80211_ops, this | 772 | * Used with the sta_notify() callback in &struct ieee80211_ops, this |
771 | * indicates addition and removal of a station to station table, | 773 | * indicates addition and removal of a station to station table, |
772 | * or if a associated station made a power state transition. | 774 | * or if a associated station made a power state transition. |
773 | * | 775 | * |
774 | * @STA_NOTIFY_ADD: a station was added to the station table | 776 | * @STA_NOTIFY_ADD: a station was added to the station table |
775 | * @STA_NOTIFY_REMOVE: a station being removed from the station table | 777 | * @STA_NOTIFY_REMOVE: a station being removed from the station table |
776 | * @STA_NOTIFY_SLEEP: a station is now sleeping | 778 | * @STA_NOTIFY_SLEEP: a station is now sleeping |
777 | * @STA_NOTIFY_AWAKE: a sleeping station woke up | 779 | * @STA_NOTIFY_AWAKE: a sleeping station woke up |
778 | */ | 780 | */ |
779 | enum sta_notify_cmd { | 781 | enum sta_notify_cmd { |
780 | STA_NOTIFY_ADD, STA_NOTIFY_REMOVE, | 782 | STA_NOTIFY_ADD, STA_NOTIFY_REMOVE, |
781 | STA_NOTIFY_SLEEP, STA_NOTIFY_AWAKE, | 783 | STA_NOTIFY_SLEEP, STA_NOTIFY_AWAKE, |
782 | }; | 784 | }; |
783 | 785 | ||
784 | /** | 786 | /** |
785 | * enum ieee80211_tkip_key_type - get tkip key | 787 | * enum ieee80211_tkip_key_type - get tkip key |
786 | * | 788 | * |
787 | * Used by drivers which need to get a tkip key for skb. Some drivers need a | 789 | * Used by drivers which need to get a tkip key for skb. Some drivers need a |
788 | * phase 1 key, others need a phase 2 key. A single function allows the driver | 790 | * phase 1 key, others need a phase 2 key. A single function allows the driver |
789 | * to get the key, this enum indicates what type of key is required. | 791 | * to get the key, this enum indicates what type of key is required. |
790 | * | 792 | * |
791 | * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key | 793 | * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key |
792 | * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key | 794 | * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key |
793 | */ | 795 | */ |
794 | enum ieee80211_tkip_key_type { | 796 | enum ieee80211_tkip_key_type { |
795 | IEEE80211_TKIP_P1_KEY, | 797 | IEEE80211_TKIP_P1_KEY, |
796 | IEEE80211_TKIP_P2_KEY, | 798 | IEEE80211_TKIP_P2_KEY, |
797 | }; | 799 | }; |
798 | 800 | ||
799 | /** | 801 | /** |
800 | * enum ieee80211_hw_flags - hardware flags | 802 | * enum ieee80211_hw_flags - hardware flags |
801 | * | 803 | * |
802 | * These flags are used to indicate hardware capabilities to | 804 | * These flags are used to indicate hardware capabilities to |
803 | * the stack. Generally, flags here should have their meaning | 805 | * the stack. Generally, flags here should have their meaning |
804 | * done in a way that the simplest hardware doesn't need setting | 806 | * done in a way that the simplest hardware doesn't need setting |
805 | * any particular flags. There are some exceptions to this rule, | 807 | * any particular flags. There are some exceptions to this rule, |
806 | * however, so you are advised to review these flags carefully. | 808 | * however, so you are advised to review these flags carefully. |
807 | * | 809 | * |
808 | * @IEEE80211_HW_RX_INCLUDES_FCS: | 810 | * @IEEE80211_HW_RX_INCLUDES_FCS: |
809 | * Indicates that received frames passed to the stack include | 811 | * Indicates that received frames passed to the stack include |
810 | * the FCS at the end. | 812 | * the FCS at the end. |
811 | * | 813 | * |
812 | * @IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING: | 814 | * @IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING: |
813 | * Some wireless LAN chipsets buffer broadcast/multicast frames | 815 | * Some wireless LAN chipsets buffer broadcast/multicast frames |
814 | * for power saving stations in the hardware/firmware and others | 816 | * for power saving stations in the hardware/firmware and others |
815 | * rely on the host system for such buffering. This option is used | 817 | * rely on the host system for such buffering. This option is used |
816 | * to configure the IEEE 802.11 upper layer to buffer broadcast and | 818 | * to configure the IEEE 802.11 upper layer to buffer broadcast and |
817 | * multicast frames when there are power saving stations so that | 819 | * multicast frames when there are power saving stations so that |
818 | * the driver can fetch them with ieee80211_get_buffered_bc(). | 820 | * the driver can fetch them with ieee80211_get_buffered_bc(). |
819 | * | 821 | * |
820 | * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE: | 822 | * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE: |
821 | * Hardware is not capable of short slot operation on the 2.4 GHz band. | 823 | * Hardware is not capable of short slot operation on the 2.4 GHz band. |
822 | * | 824 | * |
823 | * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE: | 825 | * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE: |
824 | * Hardware is not capable of receiving frames with short preamble on | 826 | * Hardware is not capable of receiving frames with short preamble on |
825 | * the 2.4 GHz band. | 827 | * the 2.4 GHz band. |
826 | * | 828 | * |
827 | * @IEEE80211_HW_SIGNAL_UNSPEC: | 829 | * @IEEE80211_HW_SIGNAL_UNSPEC: |
828 | * Hardware can provide signal values but we don't know its units. We | 830 | * Hardware can provide signal values but we don't know its units. We |
829 | * expect values between 0 and @max_signal. | 831 | * expect values between 0 and @max_signal. |
830 | * If possible please provide dB or dBm instead. | 832 | * If possible please provide dB or dBm instead. |
831 | * | 833 | * |
832 | * @IEEE80211_HW_SIGNAL_DB: | 834 | * @IEEE80211_HW_SIGNAL_DB: |
833 | * Hardware gives signal values in dB, decibel difference from an | 835 | * Hardware gives signal values in dB, decibel difference from an |
834 | * arbitrary, fixed reference. We expect values between 0 and @max_signal. | 836 | * arbitrary, fixed reference. We expect values between 0 and @max_signal. |
835 | * If possible please provide dBm instead. | 837 | * If possible please provide dBm instead. |
836 | * | 838 | * |
837 | * @IEEE80211_HW_SIGNAL_DBM: | 839 | * @IEEE80211_HW_SIGNAL_DBM: |
838 | * Hardware gives signal values in dBm, decibel difference from | 840 | * Hardware gives signal values in dBm, decibel difference from |
839 | * one milliwatt. This is the preferred method since it is standardized | 841 | * one milliwatt. This is the preferred method since it is standardized |
840 | * between different devices. @max_signal does not need to be set. | 842 | * between different devices. @max_signal does not need to be set. |
841 | * | 843 | * |
842 | * @IEEE80211_HW_NOISE_DBM: | 844 | * @IEEE80211_HW_NOISE_DBM: |
843 | * Hardware can provide noise (radio interference) values in units dBm, | 845 | * Hardware can provide noise (radio interference) values in units dBm, |
844 | * decibel difference from one milliwatt. | 846 | * decibel difference from one milliwatt. |
845 | * | 847 | * |
846 | * @IEEE80211_HW_SPECTRUM_MGMT: | 848 | * @IEEE80211_HW_SPECTRUM_MGMT: |
847 | * Hardware supports spectrum management defined in 802.11h | 849 | * Hardware supports spectrum management defined in 802.11h |
848 | * Measurement, Channel Switch, Quieting, TPC | 850 | * Measurement, Channel Switch, Quieting, TPC |
849 | * | 851 | * |
850 | * @IEEE80211_HW_AMPDU_AGGREGATION: | 852 | * @IEEE80211_HW_AMPDU_AGGREGATION: |
851 | * Hardware supports 11n A-MPDU aggregation. | 853 | * Hardware supports 11n A-MPDU aggregation. |
852 | * | 854 | * |
853 | * @IEEE80211_HW_SUPPORTS_PS: | 855 | * @IEEE80211_HW_SUPPORTS_PS: |
854 | * Hardware has power save support (i.e. can go to sleep). | 856 | * Hardware has power save support (i.e. can go to sleep). |
855 | * | 857 | * |
856 | * @IEEE80211_HW_PS_NULLFUNC_STACK: | 858 | * @IEEE80211_HW_PS_NULLFUNC_STACK: |
857 | * Hardware requires nullfunc frame handling in stack, implies | 859 | * Hardware requires nullfunc frame handling in stack, implies |
858 | * stack support for dynamic PS. | 860 | * stack support for dynamic PS. |
859 | * | 861 | * |
860 | * @IEEE80211_HW_SUPPORTS_DYNAMIC_PS: | 862 | * @IEEE80211_HW_SUPPORTS_DYNAMIC_PS: |
861 | * Hardware has support for dynamic PS. | 863 | * Hardware has support for dynamic PS. |
862 | */ | 864 | */ |
863 | enum ieee80211_hw_flags { | 865 | enum ieee80211_hw_flags { |
864 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, | 866 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, |
865 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, | 867 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, |
866 | IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, | 868 | IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, |
867 | IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, | 869 | IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, |
868 | IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, | 870 | IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, |
869 | IEEE80211_HW_SIGNAL_DB = 1<<6, | 871 | IEEE80211_HW_SIGNAL_DB = 1<<6, |
870 | IEEE80211_HW_SIGNAL_DBM = 1<<7, | 872 | IEEE80211_HW_SIGNAL_DBM = 1<<7, |
871 | IEEE80211_HW_NOISE_DBM = 1<<8, | 873 | IEEE80211_HW_NOISE_DBM = 1<<8, |
872 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, | 874 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, |
873 | IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, | 875 | IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, |
874 | IEEE80211_HW_SUPPORTS_PS = 1<<11, | 876 | IEEE80211_HW_SUPPORTS_PS = 1<<11, |
875 | IEEE80211_HW_PS_NULLFUNC_STACK = 1<<12, | 877 | IEEE80211_HW_PS_NULLFUNC_STACK = 1<<12, |
876 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<13, | 878 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<13, |
877 | }; | 879 | }; |
878 | 880 | ||
879 | /** | 881 | /** |
880 | * struct ieee80211_hw - hardware information and state | 882 | * struct ieee80211_hw - hardware information and state |
881 | * | 883 | * |
882 | * This structure contains the configuration and hardware | 884 | * This structure contains the configuration and hardware |
883 | * information for an 802.11 PHY. | 885 | * information for an 802.11 PHY. |
884 | * | 886 | * |
885 | * @wiphy: This points to the &struct wiphy allocated for this | 887 | * @wiphy: This points to the &struct wiphy allocated for this |
886 | * 802.11 PHY. You must fill in the @perm_addr and @dev | 888 | * 802.11 PHY. You must fill in the @perm_addr and @dev |
887 | * members of this structure using SET_IEEE80211_DEV() | 889 | * members of this structure using SET_IEEE80211_DEV() |
888 | * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported | 890 | * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported |
889 | * bands (with channels, bitrates) are registered here. | 891 | * bands (with channels, bitrates) are registered here. |
890 | * | 892 | * |
891 | * @conf: &struct ieee80211_conf, device configuration, don't use. | 893 | * @conf: &struct ieee80211_conf, device configuration, don't use. |
892 | * | 894 | * |
893 | * @workqueue: single threaded workqueue available for driver use, | 895 | * @workqueue: single threaded workqueue available for driver use, |
894 | * allocated by mac80211 on registration and flushed when an | 896 | * allocated by mac80211 on registration and flushed when an |
895 | * interface is removed. | 897 | * interface is removed. |
896 | * NOTICE: All work performed on this workqueue should NEVER | 898 | * NOTICE: All work performed on this workqueue should NEVER |
897 | * acquire the RTNL lock (i.e. Don't use the function | 899 | * acquire the RTNL lock (i.e. Don't use the function |
898 | * ieee80211_iterate_active_interfaces()) | 900 | * ieee80211_iterate_active_interfaces()) |
899 | * | 901 | * |
900 | * @priv: pointer to private area that was allocated for driver use | 902 | * @priv: pointer to private area that was allocated for driver use |
901 | * along with this structure. | 903 | * along with this structure. |
902 | * | 904 | * |
903 | * @flags: hardware flags, see &enum ieee80211_hw_flags. | 905 | * @flags: hardware flags, see &enum ieee80211_hw_flags. |
904 | * | 906 | * |
905 | * @extra_tx_headroom: headroom to reserve in each transmit skb | 907 | * @extra_tx_headroom: headroom to reserve in each transmit skb |
906 | * for use by the driver (e.g. for transmit headers.) | 908 | * for use by the driver (e.g. for transmit headers.) |
907 | * | 909 | * |
908 | * @channel_change_time: time (in microseconds) it takes to change channels. | 910 | * @channel_change_time: time (in microseconds) it takes to change channels. |
909 | * | 911 | * |
910 | * @max_signal: Maximum value for signal (rssi) in RX information, used | 912 | * @max_signal: Maximum value for signal (rssi) in RX information, used |
911 | * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB | 913 | * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB |
912 | * | 914 | * |
913 | * @max_listen_interval: max listen interval in units of beacon interval | 915 | * @max_listen_interval: max listen interval in units of beacon interval |
914 | * that HW supports | 916 | * that HW supports |
915 | * | 917 | * |
916 | * @queues: number of available hardware transmit queues for | 918 | * @queues: number of available hardware transmit queues for |
917 | * data packets. WMM/QoS requires at least four, these | 919 | * data packets. WMM/QoS requires at least four, these |
918 | * queues need to have configurable access parameters. | 920 | * queues need to have configurable access parameters. |
919 | * | 921 | * |
920 | * @ampdu_queues: number of available hardware transmit queues | 922 | * @ampdu_queues: number of available hardware transmit queues |
921 | * for A-MPDU packets, these have no access parameters | 923 | * for A-MPDU packets, these have no access parameters |
922 | * because they're used only for A-MPDU frames. Note that | 924 | * because they're used only for A-MPDU frames. Note that |
923 | * mac80211 will not currently use any of the regular queues | 925 | * mac80211 will not currently use any of the regular queues |
924 | * for aggregation. | 926 | * for aggregation. |
925 | * | 927 | * |
926 | * @rate_control_algorithm: rate control algorithm for this hardware. | 928 | * @rate_control_algorithm: rate control algorithm for this hardware. |
927 | * If unset (NULL), the default algorithm will be used. Must be | 929 | * If unset (NULL), the default algorithm will be used. Must be |
928 | * set before calling ieee80211_register_hw(). | 930 | * set before calling ieee80211_register_hw(). |
929 | * | 931 | * |
930 | * @vif_data_size: size (in bytes) of the drv_priv data area | 932 | * @vif_data_size: size (in bytes) of the drv_priv data area |
931 | * within &struct ieee80211_vif. | 933 | * within &struct ieee80211_vif. |
932 | * @sta_data_size: size (in bytes) of the drv_priv data area | 934 | * @sta_data_size: size (in bytes) of the drv_priv data area |
933 | * within &struct ieee80211_sta. | 935 | * within &struct ieee80211_sta. |
934 | * | 936 | * |
935 | * @max_rates: maximum number of alternate rate retry stages | 937 | * @max_rates: maximum number of alternate rate retry stages |
936 | * @max_rate_tries: maximum number of tries for each stage | 938 | * @max_rate_tries: maximum number of tries for each stage |
937 | */ | 939 | */ |
938 | struct ieee80211_hw { | 940 | struct ieee80211_hw { |
939 | struct ieee80211_conf conf; | 941 | struct ieee80211_conf conf; |
940 | struct wiphy *wiphy; | 942 | struct wiphy *wiphy; |
941 | struct workqueue_struct *workqueue; | 943 | struct workqueue_struct *workqueue; |
942 | const char *rate_control_algorithm; | 944 | const char *rate_control_algorithm; |
943 | void *priv; | 945 | void *priv; |
944 | u32 flags; | 946 | u32 flags; |
945 | unsigned int extra_tx_headroom; | 947 | unsigned int extra_tx_headroom; |
946 | int channel_change_time; | 948 | int channel_change_time; |
947 | int vif_data_size; | 949 | int vif_data_size; |
948 | int sta_data_size; | 950 | int sta_data_size; |
949 | u16 queues; | 951 | u16 queues; |
950 | u16 ampdu_queues; | 952 | u16 ampdu_queues; |
951 | u16 max_listen_interval; | 953 | u16 max_listen_interval; |
952 | s8 max_signal; | 954 | s8 max_signal; |
953 | u8 max_rates; | 955 | u8 max_rates; |
954 | u8 max_rate_tries; | 956 | u8 max_rate_tries; |
955 | }; | 957 | }; |
956 | 958 | ||
957 | /** | 959 | /** |
958 | * SET_IEEE80211_DEV - set device for 802.11 hardware | 960 | * SET_IEEE80211_DEV - set device for 802.11 hardware |
959 | * | 961 | * |
960 | * @hw: the &struct ieee80211_hw to set the device for | 962 | * @hw: the &struct ieee80211_hw to set the device for |
961 | * @dev: the &struct device of this 802.11 device | 963 | * @dev: the &struct device of this 802.11 device |
962 | */ | 964 | */ |
963 | static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev) | 965 | static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev) |
964 | { | 966 | { |
965 | set_wiphy_dev(hw->wiphy, dev); | 967 | set_wiphy_dev(hw->wiphy, dev); |
966 | } | 968 | } |
967 | 969 | ||
968 | /** | 970 | /** |
969 | * SET_IEEE80211_PERM_ADDR - set the permanent MAC address for 802.11 hardware | 971 | * SET_IEEE80211_PERM_ADDR - set the permanent MAC address for 802.11 hardware |
970 | * | 972 | * |
971 | * @hw: the &struct ieee80211_hw to set the MAC address for | 973 | * @hw: the &struct ieee80211_hw to set the MAC address for |
972 | * @addr: the address to set | 974 | * @addr: the address to set |
973 | */ | 975 | */ |
974 | static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr) | 976 | static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr) |
975 | { | 977 | { |
976 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); | 978 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); |
977 | } | 979 | } |
978 | 980 | ||
979 | static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw) | 981 | static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw) |
980 | { | 982 | { |
981 | return hw->queues; | 983 | return hw->queues; |
982 | } | 984 | } |
983 | 985 | ||
984 | static inline int ieee80211_num_queues(struct ieee80211_hw *hw) | 986 | static inline int ieee80211_num_queues(struct ieee80211_hw *hw) |
985 | { | 987 | { |
986 | return hw->queues + hw->ampdu_queues; | 988 | return hw->queues + hw->ampdu_queues; |
987 | } | 989 | } |
988 | 990 | ||
989 | static inline struct ieee80211_rate * | 991 | static inline struct ieee80211_rate * |
990 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, | 992 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, |
991 | const struct ieee80211_tx_info *c) | 993 | const struct ieee80211_tx_info *c) |
992 | { | 994 | { |
993 | if (WARN_ON(c->control.rates[0].idx < 0)) | 995 | if (WARN_ON(c->control.rates[0].idx < 0)) |
994 | return NULL; | 996 | return NULL; |
995 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; | 997 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; |
996 | } | 998 | } |
997 | 999 | ||
998 | static inline struct ieee80211_rate * | 1000 | static inline struct ieee80211_rate * |
999 | ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw, | 1001 | ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw, |
1000 | const struct ieee80211_tx_info *c) | 1002 | const struct ieee80211_tx_info *c) |
1001 | { | 1003 | { |
1002 | if (c->control.rts_cts_rate_idx < 0) | 1004 | if (c->control.rts_cts_rate_idx < 0) |
1003 | return NULL; | 1005 | return NULL; |
1004 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rts_cts_rate_idx]; | 1006 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rts_cts_rate_idx]; |
1005 | } | 1007 | } |
1006 | 1008 | ||
1007 | static inline struct ieee80211_rate * | 1009 | static inline struct ieee80211_rate * |
1008 | ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, | 1010 | ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, |
1009 | const struct ieee80211_tx_info *c, int idx) | 1011 | const struct ieee80211_tx_info *c, int idx) |
1010 | { | 1012 | { |
1011 | if (c->control.rates[idx + 1].idx < 0) | 1013 | if (c->control.rates[idx + 1].idx < 0) |
1012 | return NULL; | 1014 | return NULL; |
1013 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx]; | 1015 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx]; |
1014 | } | 1016 | } |
1015 | 1017 | ||
1016 | /** | 1018 | /** |
1017 | * DOC: Hardware crypto acceleration | 1019 | * DOC: Hardware crypto acceleration |
1018 | * | 1020 | * |
1019 | * mac80211 is capable of taking advantage of many hardware | 1021 | * mac80211 is capable of taking advantage of many hardware |
1020 | * acceleration designs for encryption and decryption operations. | 1022 | * acceleration designs for encryption and decryption operations. |
1021 | * | 1023 | * |
1022 | * The set_key() callback in the &struct ieee80211_ops for a given | 1024 | * The set_key() callback in the &struct ieee80211_ops for a given |
1023 | * device is called to enable hardware acceleration of encryption and | 1025 | * device is called to enable hardware acceleration of encryption and |
1024 | * decryption. The callback takes a @sta parameter that will be NULL | 1026 | * decryption. The callback takes a @sta parameter that will be NULL |
1025 | * for default keys or keys used for transmission only, or point to | 1027 | * for default keys or keys used for transmission only, or point to |
1026 | * the station information for the peer for individual keys. | 1028 | * the station information for the peer for individual keys. |
1027 | * Multiple transmission keys with the same key index may be used when | 1029 | * Multiple transmission keys with the same key index may be used when |
1028 | * VLANs are configured for an access point. | 1030 | * VLANs are configured for an access point. |
1029 | * | 1031 | * |
1030 | * When transmitting, the TX control data will use the @hw_key_idx | 1032 | * When transmitting, the TX control data will use the @hw_key_idx |
1031 | * selected by the driver by modifying the &struct ieee80211_key_conf | 1033 | * selected by the driver by modifying the &struct ieee80211_key_conf |
1032 | * pointed to by the @key parameter to the set_key() function. | 1034 | * pointed to by the @key parameter to the set_key() function. |
1033 | * | 1035 | * |
1034 | * The set_key() call for the %SET_KEY command should return 0 if | 1036 | * The set_key() call for the %SET_KEY command should return 0 if |
1035 | * the key is now in use, -%EOPNOTSUPP or -%ENOSPC if it couldn't be | 1037 | * the key is now in use, -%EOPNOTSUPP or -%ENOSPC if it couldn't be |
1036 | * added; if you return 0 then hw_key_idx must be assigned to the | 1038 | * added; if you return 0 then hw_key_idx must be assigned to the |
1037 | * hardware key index, you are free to use the full u8 range. | 1039 | * hardware key index, you are free to use the full u8 range. |
1038 | * | 1040 | * |
1039 | * When the cmd is %DISABLE_KEY then it must succeed. | 1041 | * When the cmd is %DISABLE_KEY then it must succeed. |
1040 | * | 1042 | * |
1041 | * Note that it is permissible to not decrypt a frame even if a key | 1043 | * Note that it is permissible to not decrypt a frame even if a key |
1042 | * for it has been uploaded to hardware, the stack will not make any | 1044 | * for it has been uploaded to hardware, the stack will not make any |
1043 | * decision based on whether a key has been uploaded or not but rather | 1045 | * decision based on whether a key has been uploaded or not but rather |
1044 | * based on the receive flags. | 1046 | * based on the receive flags. |
1045 | * | 1047 | * |
1046 | * The &struct ieee80211_key_conf structure pointed to by the @key | 1048 | * The &struct ieee80211_key_conf structure pointed to by the @key |
1047 | * parameter is guaranteed to be valid until another call to set_key() | 1049 | * parameter is guaranteed to be valid until another call to set_key() |
1048 | * removes it, but it can only be used as a cookie to differentiate | 1050 | * removes it, but it can only be used as a cookie to differentiate |
1049 | * keys. | 1051 | * keys. |
1050 | * | 1052 | * |
1051 | * In TKIP some HW need to be provided a phase 1 key, for RX decryption | 1053 | * In TKIP some HW need to be provided a phase 1 key, for RX decryption |
1052 | * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key | 1054 | * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key |
1053 | * handler. | 1055 | * handler. |
1054 | * The update_tkip_key() call updates the driver with the new phase 1 key. | 1056 | * The update_tkip_key() call updates the driver with the new phase 1 key. |
1055 | * This happens everytime the iv16 wraps around (every 65536 packets). The | 1057 | * This happens everytime the iv16 wraps around (every 65536 packets). The |
1056 | * set_key() call will happen only once for each key (unless the AP did | 1058 | * set_key() call will happen only once for each key (unless the AP did |
1057 | * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is | 1059 | * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is |
1058 | * provided by update_tkip_key only. The trigger that makes mac80211 call this | 1060 | * provided by update_tkip_key only. The trigger that makes mac80211 call this |
1059 | * handler is software decryption with wrap around of iv16. | 1061 | * handler is software decryption with wrap around of iv16. |
1060 | */ | 1062 | */ |
1061 | 1063 | ||
1062 | /** | 1064 | /** |
1063 | * DOC: Powersave support | 1065 | * DOC: Powersave support |
1064 | * | 1066 | * |
1065 | * mac80211 has support for various powersave implementations. | 1067 | * mac80211 has support for various powersave implementations. |
1066 | * | 1068 | * |
1067 | * First, it can support hardware that handles all powersaving by | 1069 | * First, it can support hardware that handles all powersaving by |
1068 | * itself, such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS | 1070 | * itself, such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS |
1069 | * hardware flag. In that case, it will be told about the desired | 1071 | * hardware flag. In that case, it will be told about the desired |
1070 | * powersave mode depending on the association status, and the driver | 1072 | * powersave mode depending on the association status, and the driver |
1071 | * must take care of sending nullfunc frames when necessary, i.e. when | 1073 | * must take care of sending nullfunc frames when necessary, i.e. when |
1072 | * entering and leaving powersave mode. The driver is required to look at | 1074 | * entering and leaving powersave mode. The driver is required to look at |
1073 | * the AID in beacons and signal to the AP that it woke up when it finds | 1075 | * the AID in beacons and signal to the AP that it woke up when it finds |
1074 | * traffic directed to it. This mode supports dynamic PS by simply | 1076 | * traffic directed to it. This mode supports dynamic PS by simply |
1075 | * enabling/disabling PS. | 1077 | * enabling/disabling PS. |
1076 | * | 1078 | * |
1077 | * Additionally, such hardware may set the %IEEE80211_HW_SUPPORTS_DYNAMIC_PS | 1079 | * Additionally, such hardware may set the %IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
1078 | * flag to indicate that it can support dynamic PS mode itself (see below). | 1080 | * flag to indicate that it can support dynamic PS mode itself (see below). |
1079 | * | 1081 | * |
1080 | * Other hardware designs cannot send nullfunc frames by themselves and also | 1082 | * Other hardware designs cannot send nullfunc frames by themselves and also |
1081 | * need software support for parsing the TIM bitmap. This is also supported | 1083 | * need software support for parsing the TIM bitmap. This is also supported |
1082 | * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and | 1084 | * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and |
1083 | * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still | 1085 | * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still |
1084 | * required to pass up beacons. Additionally, in this case, mac80211 will | 1086 | * required to pass up beacons. Additionally, in this case, mac80211 will |
1085 | * wake up the hardware when multicast traffic is announced in the beacon. | 1087 | * wake up the hardware when multicast traffic is announced in the beacon. |
1086 | * | 1088 | * |
1087 | * FIXME: I don't think we can be fast enough in software when we want to | 1089 | * FIXME: I don't think we can be fast enough in software when we want to |
1088 | * receive multicast traffic? | 1090 | * receive multicast traffic? |
1089 | * | 1091 | * |
1090 | * Dynamic powersave mode is an extension to normal powersave mode in which | 1092 | * Dynamic powersave mode is an extension to normal powersave mode in which |
1091 | * the hardware stays awake for a user-specified period of time after sending | 1093 | * the hardware stays awake for a user-specified period of time after sending |
1092 | * a frame so that reply frames need not be buffered and therefore delayed | 1094 | * a frame so that reply frames need not be buffered and therefore delayed |
1093 | * to the next wakeup. This can either be supported by hardware, in which case | 1095 | * to the next wakeup. This can either be supported by hardware, in which case |
1094 | * the driver needs to look at the @dynamic_ps_timeout hardware configuration | 1096 | * the driver needs to look at the @dynamic_ps_timeout hardware configuration |
1095 | * value, or by the stack if all nullfunc handling is in the stack. | 1097 | * value, or by the stack if all nullfunc handling is in the stack. |
1096 | */ | 1098 | */ |
1097 | 1099 | ||
1098 | /** | 1100 | /** |
1099 | * DOC: Frame filtering | 1101 | * DOC: Frame filtering |
1100 | * | 1102 | * |
1101 | * mac80211 requires to see many management frames for proper | 1103 | * mac80211 requires to see many management frames for proper |
1102 | * operation, and users may want to see many more frames when | 1104 | * operation, and users may want to see many more frames when |
1103 | * in monitor mode. However, for best CPU usage and power consumption, | 1105 | * in monitor mode. However, for best CPU usage and power consumption, |
1104 | * having as few frames as possible percolate through the stack is | 1106 | * having as few frames as possible percolate through the stack is |
1105 | * desirable. Hence, the hardware should filter as much as possible. | 1107 | * desirable. Hence, the hardware should filter as much as possible. |
1106 | * | 1108 | * |
1107 | * To achieve this, mac80211 uses filter flags (see below) to tell | 1109 | * To achieve this, mac80211 uses filter flags (see below) to tell |
1108 | * the driver's configure_filter() function which frames should be | 1110 | * the driver's configure_filter() function which frames should be |
1109 | * passed to mac80211 and which should be filtered out. | 1111 | * passed to mac80211 and which should be filtered out. |
1110 | * | 1112 | * |
1111 | * The configure_filter() callback is invoked with the parameters | 1113 | * The configure_filter() callback is invoked with the parameters |
1112 | * @mc_count and @mc_list for the combined multicast address list | 1114 | * @mc_count and @mc_list for the combined multicast address list |
1113 | * of all virtual interfaces, @changed_flags telling which flags | 1115 | * of all virtual interfaces, @changed_flags telling which flags |
1114 | * were changed and @total_flags with the new flag states. | 1116 | * were changed and @total_flags with the new flag states. |
1115 | * | 1117 | * |
1116 | * If your device has no multicast address filters your driver will | 1118 | * If your device has no multicast address filters your driver will |
1117 | * need to check both the %FIF_ALLMULTI flag and the @mc_count | 1119 | * need to check both the %FIF_ALLMULTI flag and the @mc_count |
1118 | * parameter to see whether multicast frames should be accepted | 1120 | * parameter to see whether multicast frames should be accepted |
1119 | * or dropped. | 1121 | * or dropped. |
1120 | * | 1122 | * |
1121 | * All unsupported flags in @total_flags must be cleared. | 1123 | * All unsupported flags in @total_flags must be cleared. |
1122 | * Hardware does not support a flag if it is incapable of _passing_ | 1124 | * Hardware does not support a flag if it is incapable of _passing_ |
1123 | * the frame to the stack. Otherwise the driver must ignore | 1125 | * the frame to the stack. Otherwise the driver must ignore |
1124 | * the flag, but not clear it. | 1126 | * the flag, but not clear it. |
1125 | * You must _only_ clear the flag (announce no support for the | 1127 | * You must _only_ clear the flag (announce no support for the |
1126 | * flag to mac80211) if you are not able to pass the packet type | 1128 | * flag to mac80211) if you are not able to pass the packet type |
1127 | * to the stack (so the hardware always filters it). | 1129 | * to the stack (so the hardware always filters it). |
1128 | * So for example, you should clear @FIF_CONTROL, if your hardware | 1130 | * So for example, you should clear @FIF_CONTROL, if your hardware |
1129 | * always filters control frames. If your hardware always passes | 1131 | * always filters control frames. If your hardware always passes |
1130 | * control frames to the kernel and is incapable of filtering them, | 1132 | * control frames to the kernel and is incapable of filtering them, |
1131 | * you do _not_ clear the @FIF_CONTROL flag. | 1133 | * you do _not_ clear the @FIF_CONTROL flag. |
1132 | * This rule applies to all other FIF flags as well. | 1134 | * This rule applies to all other FIF flags as well. |
1133 | */ | 1135 | */ |
1134 | 1136 | ||
1135 | /** | 1137 | /** |
1136 | * enum ieee80211_filter_flags - hardware filter flags | 1138 | * enum ieee80211_filter_flags - hardware filter flags |
1137 | * | 1139 | * |
1138 | * These flags determine what the filter in hardware should be | 1140 | * These flags determine what the filter in hardware should be |
1139 | * programmed to let through and what should not be passed to the | 1141 | * programmed to let through and what should not be passed to the |
1140 | * stack. It is always safe to pass more frames than requested, | 1142 | * stack. It is always safe to pass more frames than requested, |
1141 | * but this has negative impact on power consumption. | 1143 | * but this has negative impact on power consumption. |
1142 | * | 1144 | * |
1143 | * @FIF_PROMISC_IN_BSS: promiscuous mode within your BSS, | 1145 | * @FIF_PROMISC_IN_BSS: promiscuous mode within your BSS, |
1144 | * think of the BSS as your network segment and then this corresponds | 1146 | * think of the BSS as your network segment and then this corresponds |
1145 | * to the regular ethernet device promiscuous mode. | 1147 | * to the regular ethernet device promiscuous mode. |
1146 | * | 1148 | * |
1147 | * @FIF_ALLMULTI: pass all multicast frames, this is used if requested | 1149 | * @FIF_ALLMULTI: pass all multicast frames, this is used if requested |
1148 | * by the user or if the hardware is not capable of filtering by | 1150 | * by the user or if the hardware is not capable of filtering by |
1149 | * multicast address. | 1151 | * multicast address. |
1150 | * | 1152 | * |
1151 | * @FIF_FCSFAIL: pass frames with failed FCS (but you need to set the | 1153 | * @FIF_FCSFAIL: pass frames with failed FCS (but you need to set the |
1152 | * %RX_FLAG_FAILED_FCS_CRC for them) | 1154 | * %RX_FLAG_FAILED_FCS_CRC for them) |
1153 | * | 1155 | * |
1154 | * @FIF_PLCPFAIL: pass frames with failed PLCP CRC (but you need to set | 1156 | * @FIF_PLCPFAIL: pass frames with failed PLCP CRC (but you need to set |
1155 | * the %RX_FLAG_FAILED_PLCP_CRC for them | 1157 | * the %RX_FLAG_FAILED_PLCP_CRC for them |
1156 | * | 1158 | * |
1157 | * @FIF_BCN_PRBRESP_PROMISC: This flag is set during scanning to indicate | 1159 | * @FIF_BCN_PRBRESP_PROMISC: This flag is set during scanning to indicate |
1158 | * to the hardware that it should not filter beacons or probe responses | 1160 | * to the hardware that it should not filter beacons or probe responses |
1159 | * by BSSID. Filtering them can greatly reduce the amount of processing | 1161 | * by BSSID. Filtering them can greatly reduce the amount of processing |
1160 | * mac80211 needs to do and the amount of CPU wakeups, so you should | 1162 | * mac80211 needs to do and the amount of CPU wakeups, so you should |
1161 | * honour this flag if possible. | 1163 | * honour this flag if possible. |
1162 | * | 1164 | * |
1163 | * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then | 1165 | * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then |
1164 | * only those addressed to this station | 1166 | * only those addressed to this station |
1165 | * | 1167 | * |
1166 | * @FIF_OTHER_BSS: pass frames destined to other BSSes | 1168 | * @FIF_OTHER_BSS: pass frames destined to other BSSes |
1167 | */ | 1169 | */ |
1168 | enum ieee80211_filter_flags { | 1170 | enum ieee80211_filter_flags { |
1169 | FIF_PROMISC_IN_BSS = 1<<0, | 1171 | FIF_PROMISC_IN_BSS = 1<<0, |
1170 | FIF_ALLMULTI = 1<<1, | 1172 | FIF_ALLMULTI = 1<<1, |
1171 | FIF_FCSFAIL = 1<<2, | 1173 | FIF_FCSFAIL = 1<<2, |
1172 | FIF_PLCPFAIL = 1<<3, | 1174 | FIF_PLCPFAIL = 1<<3, |
1173 | FIF_BCN_PRBRESP_PROMISC = 1<<4, | 1175 | FIF_BCN_PRBRESP_PROMISC = 1<<4, |
1174 | FIF_CONTROL = 1<<5, | 1176 | FIF_CONTROL = 1<<5, |
1175 | FIF_OTHER_BSS = 1<<6, | 1177 | FIF_OTHER_BSS = 1<<6, |
1176 | }; | 1178 | }; |
1177 | 1179 | ||
1178 | /** | 1180 | /** |
1179 | * enum ieee80211_ampdu_mlme_action - A-MPDU actions | 1181 | * enum ieee80211_ampdu_mlme_action - A-MPDU actions |
1180 | * | 1182 | * |
1181 | * These flags are used with the ampdu_action() callback in | 1183 | * These flags are used with the ampdu_action() callback in |
1182 | * &struct ieee80211_ops to indicate which action is needed. | 1184 | * &struct ieee80211_ops to indicate which action is needed. |
1183 | * @IEEE80211_AMPDU_RX_START: start Rx aggregation | 1185 | * @IEEE80211_AMPDU_RX_START: start Rx aggregation |
1184 | * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation | 1186 | * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation |
1185 | * @IEEE80211_AMPDU_TX_START: start Tx aggregation | 1187 | * @IEEE80211_AMPDU_TX_START: start Tx aggregation |
1186 | * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation | 1188 | * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation |
1187 | * @IEEE80211_AMPDU_TX_RESUME: resume TX aggregation | 1189 | * @IEEE80211_AMPDU_TX_RESUME: resume TX aggregation |
1188 | */ | 1190 | */ |
1189 | enum ieee80211_ampdu_mlme_action { | 1191 | enum ieee80211_ampdu_mlme_action { |
1190 | IEEE80211_AMPDU_RX_START, | 1192 | IEEE80211_AMPDU_RX_START, |
1191 | IEEE80211_AMPDU_RX_STOP, | 1193 | IEEE80211_AMPDU_RX_STOP, |
1192 | IEEE80211_AMPDU_TX_START, | 1194 | IEEE80211_AMPDU_TX_START, |
1193 | IEEE80211_AMPDU_TX_STOP, | 1195 | IEEE80211_AMPDU_TX_STOP, |
1194 | IEEE80211_AMPDU_TX_RESUME, | 1196 | IEEE80211_AMPDU_TX_RESUME, |
1195 | }; | 1197 | }; |
1196 | 1198 | ||
1197 | /** | 1199 | /** |
1198 | * struct ieee80211_ops - callbacks from mac80211 to the driver | 1200 | * struct ieee80211_ops - callbacks from mac80211 to the driver |
1199 | * | 1201 | * |
1200 | * This structure contains various callbacks that the driver may | 1202 | * This structure contains various callbacks that the driver may |
1201 | * handle or, in some cases, must handle, for example to configure | 1203 | * handle or, in some cases, must handle, for example to configure |
1202 | * the hardware to a new channel or to transmit a frame. | 1204 | * the hardware to a new channel or to transmit a frame. |
1203 | * | 1205 | * |
1204 | * @tx: Handler that 802.11 module calls for each transmitted frame. | 1206 | * @tx: Handler that 802.11 module calls for each transmitted frame. |
1205 | * skb contains the buffer starting from the IEEE 802.11 header. | 1207 | * skb contains the buffer starting from the IEEE 802.11 header. |
1206 | * The low-level driver should send the frame out based on | 1208 | * The low-level driver should send the frame out based on |
1207 | * configuration in the TX control data. This handler should, | 1209 | * configuration in the TX control data. This handler should, |
1208 | * preferably, never fail and stop queues appropriately, more | 1210 | * preferably, never fail and stop queues appropriately, more |
1209 | * importantly, however, it must never fail for A-MPDU-queues. | 1211 | * importantly, however, it must never fail for A-MPDU-queues. |
1210 | * Must be implemented and atomic. | 1212 | * Must be implemented and atomic. |
1211 | * | 1213 | * |
1212 | * @start: Called before the first netdevice attached to the hardware | 1214 | * @start: Called before the first netdevice attached to the hardware |
1213 | * is enabled. This should turn on the hardware and must turn on | 1215 | * is enabled. This should turn on the hardware and must turn on |
1214 | * frame reception (for possibly enabled monitor interfaces.) | 1216 | * frame reception (for possibly enabled monitor interfaces.) |
1215 | * Returns negative error codes, these may be seen in userspace, | 1217 | * Returns negative error codes, these may be seen in userspace, |
1216 | * or zero. | 1218 | * or zero. |
1217 | * When the device is started it should not have a MAC address | 1219 | * When the device is started it should not have a MAC address |
1218 | * to avoid acknowledging frames before a non-monitor device | 1220 | * to avoid acknowledging frames before a non-monitor device |
1219 | * is added. | 1221 | * is added. |
1220 | * Must be implemented. | 1222 | * Must be implemented. |
1221 | * | 1223 | * |
1222 | * @stop: Called after last netdevice attached to the hardware | 1224 | * @stop: Called after last netdevice attached to the hardware |
1223 | * is disabled. This should turn off the hardware (at least | 1225 | * is disabled. This should turn off the hardware (at least |
1224 | * it must turn off frame reception.) | 1226 | * it must turn off frame reception.) |
1225 | * May be called right after add_interface if that rejects | 1227 | * May be called right after add_interface if that rejects |
1226 | * an interface. | 1228 | * an interface. |
1227 | * Must be implemented. | 1229 | * Must be implemented. |
1228 | * | 1230 | * |
1229 | * @add_interface: Called when a netdevice attached to the hardware is | 1231 | * @add_interface: Called when a netdevice attached to the hardware is |
1230 | * enabled. Because it is not called for monitor mode devices, @start | 1232 | * enabled. Because it is not called for monitor mode devices, @start |
1231 | * and @stop must be implemented. | 1233 | * and @stop must be implemented. |
1232 | * The driver should perform any initialization it needs before | 1234 | * The driver should perform any initialization it needs before |
1233 | * the device can be enabled. The initial configuration for the | 1235 | * the device can be enabled. The initial configuration for the |
1234 | * interface is given in the conf parameter. | 1236 | * interface is given in the conf parameter. |
1235 | * The callback may refuse to add an interface by returning a | 1237 | * The callback may refuse to add an interface by returning a |
1236 | * negative error code (which will be seen in userspace.) | 1238 | * negative error code (which will be seen in userspace.) |
1237 | * Must be implemented. | 1239 | * Must be implemented. |
1238 | * | 1240 | * |
1239 | * @remove_interface: Notifies a driver that an interface is going down. | 1241 | * @remove_interface: Notifies a driver that an interface is going down. |
1240 | * The @stop callback is called after this if it is the last interface | 1242 | * The @stop callback is called after this if it is the last interface |
1241 | * and no monitor interfaces are present. | 1243 | * and no monitor interfaces are present. |
1242 | * When all interfaces are removed, the MAC address in the hardware | 1244 | * When all interfaces are removed, the MAC address in the hardware |
1243 | * must be cleared so the device no longer acknowledges packets, | 1245 | * must be cleared so the device no longer acknowledges packets, |
1244 | * the mac_addr member of the conf structure is, however, set to the | 1246 | * the mac_addr member of the conf structure is, however, set to the |
1245 | * MAC address of the device going away. | 1247 | * MAC address of the device going away. |
1246 | * Hence, this callback must be implemented. | 1248 | * Hence, this callback must be implemented. |
1247 | * | 1249 | * |
1248 | * @config: Handler for configuration requests. IEEE 802.11 code calls this | 1250 | * @config: Handler for configuration requests. IEEE 802.11 code calls this |
1249 | * function to change hardware configuration, e.g., channel. | 1251 | * function to change hardware configuration, e.g., channel. |
1250 | * | 1252 | * |
1251 | * @config_interface: Handler for configuration requests related to interfaces | 1253 | * @config_interface: Handler for configuration requests related to interfaces |
1252 | * (e.g. BSSID changes.) | 1254 | * (e.g. BSSID changes.) |
1253 | * | 1255 | * |
1254 | * @bss_info_changed: Handler for configuration requests related to BSS | 1256 | * @bss_info_changed: Handler for configuration requests related to BSS |
1255 | * parameters that may vary during BSS's lifespan, and may affect low | 1257 | * parameters that may vary during BSS's lifespan, and may affect low |
1256 | * level driver (e.g. assoc/disassoc status, erp parameters). | 1258 | * level driver (e.g. assoc/disassoc status, erp parameters). |
1257 | * This function should not be used if no BSS has been set, unless | 1259 | * This function should not be used if no BSS has been set, unless |
1258 | * for association indication. The @changed parameter indicates which | 1260 | * for association indication. The @changed parameter indicates which |
1259 | * of the bss parameters has changed when a call is made. | 1261 | * of the bss parameters has changed when a call is made. |
1260 | * | 1262 | * |
1261 | * @configure_filter: Configure the device's RX filter. | 1263 | * @configure_filter: Configure the device's RX filter. |
1262 | * See the section "Frame filtering" for more information. | 1264 | * See the section "Frame filtering" for more information. |
1263 | * This callback must be implemented and atomic. | 1265 | * This callback must be implemented and atomic. |
1264 | * | 1266 | * |
1265 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit | 1267 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit |
1266 | * must be set or cleared for a given STA. Must be atomic. | 1268 | * must be set or cleared for a given STA. Must be atomic. |
1267 | * | 1269 | * |
1268 | * @set_key: See the section "Hardware crypto acceleration" | 1270 | * @set_key: See the section "Hardware crypto acceleration" |
1269 | * This callback can sleep, and is only called between add_interface | 1271 | * This callback can sleep, and is only called between add_interface |
1270 | * and remove_interface calls, i.e. while the given virtual interface | 1272 | * and remove_interface calls, i.e. while the given virtual interface |
1271 | * is enabled. | 1273 | * is enabled. |
1272 | * | 1274 | * |
1273 | * @update_tkip_key: See the section "Hardware crypto acceleration" | 1275 | * @update_tkip_key: See the section "Hardware crypto acceleration" |
1274 | * This callback will be called in the context of Rx. Called for drivers | 1276 | * This callback will be called in the context of Rx. Called for drivers |
1275 | * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. | 1277 | * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. |
1276 | * | 1278 | * |
1277 | * @hw_scan: Ask the hardware to service the scan request, no need to start | 1279 | * @hw_scan: Ask the hardware to service the scan request, no need to start |
1278 | * the scan state machine in stack. The scan must honour the channel | 1280 | * the scan state machine in stack. The scan must honour the channel |
1279 | * configuration done by the regulatory agent in the wiphy's registered | 1281 | * configuration done by the regulatory agent in the wiphy's registered |
1280 | * bands. When the scan finishes, ieee80211_scan_completed() must be | 1282 | * bands. When the scan finishes, ieee80211_scan_completed() must be |
1281 | * called; note that it also must be called when the scan cannot finish | 1283 | * called; note that it also must be called when the scan cannot finish |
1282 | * because the hardware is turned off! Anything else is a bug! | 1284 | * because the hardware is turned off! Anything else is a bug! |
1283 | * | 1285 | * |
1284 | * @get_stats: return low-level statistics | 1286 | * @get_stats: return low-level statistics |
1285 | * | 1287 | * |
1286 | * @get_tkip_seq: If your device implements TKIP encryption in hardware this | 1288 | * @get_tkip_seq: If your device implements TKIP encryption in hardware this |
1287 | * callback should be provided to read the TKIP transmit IVs (both IV32 | 1289 | * callback should be provided to read the TKIP transmit IVs (both IV32 |
1288 | * and IV16) for the given key from hardware. | 1290 | * and IV16) for the given key from hardware. |
1289 | * | 1291 | * |
1290 | * @set_rts_threshold: Configuration of RTS threshold (if device needs it) | 1292 | * @set_rts_threshold: Configuration of RTS threshold (if device needs it) |
1291 | * | 1293 | * |
1292 | * @sta_notify: Notifies low level driver about addition, removal or power | 1294 | * @sta_notify: Notifies low level driver about addition, removal or power |
1293 | * state transition of an associated station, AP, IBSS/WDS/mesh peer etc. | 1295 | * state transition of an associated station, AP, IBSS/WDS/mesh peer etc. |
1294 | * Must be atomic. | 1296 | * Must be atomic. |
1295 | * | 1297 | * |
1296 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), | 1298 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), |
1297 | * bursting) for a hardware TX queue. | 1299 | * bursting) for a hardware TX queue. |
1298 | * | 1300 | * |
1299 | * @get_tx_stats: Get statistics of the current TX queue status. This is used | 1301 | * @get_tx_stats: Get statistics of the current TX queue status. This is used |
1300 | * to get number of currently queued packets (queue length), maximum queue | 1302 | * to get number of currently queued packets (queue length), maximum queue |
1301 | * size (limit), and total number of packets sent using each TX queue | 1303 | * size (limit), and total number of packets sent using each TX queue |
1302 | * (count). The 'stats' pointer points to an array that has hw->queues + | 1304 | * (count). The 'stats' pointer points to an array that has hw->queues + |
1303 | * hw->ampdu_queues items. | 1305 | * hw->ampdu_queues items. |
1304 | * | 1306 | * |
1305 | * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, | 1307 | * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, |
1306 | * this is only used for IBSS mode debugging and, as such, is not a | 1308 | * this is only used for IBSS mode debugging and, as such, is not a |
1307 | * required function. Must be atomic. | 1309 | * required function. Must be atomic. |
1308 | * | 1310 | * |
1309 | * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize | 1311 | * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize |
1310 | * with other STAs in the IBSS. This is only used in IBSS mode. This | 1312 | * with other STAs in the IBSS. This is only used in IBSS mode. This |
1311 | * function is optional if the firmware/hardware takes full care of | 1313 | * function is optional if the firmware/hardware takes full care of |
1312 | * TSF synchronization. | 1314 | * TSF synchronization. |
1313 | * | 1315 | * |
1314 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. | 1316 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. |
1315 | * This is needed only for IBSS mode and the result of this function is | 1317 | * This is needed only for IBSS mode and the result of this function is |
1316 | * used to determine whether to reply to Probe Requests. | 1318 | * used to determine whether to reply to Probe Requests. |
1317 | * | 1319 | * |
1318 | * @ampdu_action: Perform a certain A-MPDU action | 1320 | * @ampdu_action: Perform a certain A-MPDU action |
1319 | * The RA/TID combination determines the destination and TID we want | 1321 | * The RA/TID combination determines the destination and TID we want |
1320 | * the ampdu action to be performed for. The action is defined through | 1322 | * the ampdu action to be performed for. The action is defined through |
1321 | * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) | 1323 | * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) |
1322 | * is the first frame we expect to perform the action on. notice | 1324 | * is the first frame we expect to perform the action on. notice |
1323 | * that TX/RX_STOP can pass NULL for this parameter. | 1325 | * that TX/RX_STOP can pass NULL for this parameter. |
1324 | */ | 1326 | */ |
1325 | struct ieee80211_ops { | 1327 | struct ieee80211_ops { |
1326 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); | 1328 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); |
1327 | int (*start)(struct ieee80211_hw *hw); | 1329 | int (*start)(struct ieee80211_hw *hw); |
1328 | void (*stop)(struct ieee80211_hw *hw); | 1330 | void (*stop)(struct ieee80211_hw *hw); |
1329 | int (*add_interface)(struct ieee80211_hw *hw, | 1331 | int (*add_interface)(struct ieee80211_hw *hw, |
1330 | struct ieee80211_if_init_conf *conf); | 1332 | struct ieee80211_if_init_conf *conf); |
1331 | void (*remove_interface)(struct ieee80211_hw *hw, | 1333 | void (*remove_interface)(struct ieee80211_hw *hw, |
1332 | struct ieee80211_if_init_conf *conf); | 1334 | struct ieee80211_if_init_conf *conf); |
1333 | int (*config)(struct ieee80211_hw *hw, u32 changed); | 1335 | int (*config)(struct ieee80211_hw *hw, u32 changed); |
1334 | int (*config_interface)(struct ieee80211_hw *hw, | 1336 | int (*config_interface)(struct ieee80211_hw *hw, |
1335 | struct ieee80211_vif *vif, | 1337 | struct ieee80211_vif *vif, |
1336 | struct ieee80211_if_conf *conf); | 1338 | struct ieee80211_if_conf *conf); |
1337 | void (*bss_info_changed)(struct ieee80211_hw *hw, | 1339 | void (*bss_info_changed)(struct ieee80211_hw *hw, |
1338 | struct ieee80211_vif *vif, | 1340 | struct ieee80211_vif *vif, |
1339 | struct ieee80211_bss_conf *info, | 1341 | struct ieee80211_bss_conf *info, |
1340 | u32 changed); | 1342 | u32 changed); |
1341 | void (*configure_filter)(struct ieee80211_hw *hw, | 1343 | void (*configure_filter)(struct ieee80211_hw *hw, |
1342 | unsigned int changed_flags, | 1344 | unsigned int changed_flags, |
1343 | unsigned int *total_flags, | 1345 | unsigned int *total_flags, |
1344 | int mc_count, struct dev_addr_list *mc_list); | 1346 | int mc_count, struct dev_addr_list *mc_list); |
1345 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 1347 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
1346 | bool set); | 1348 | bool set); |
1347 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1349 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
1348 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | 1350 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
1349 | struct ieee80211_key_conf *key); | 1351 | struct ieee80211_key_conf *key); |
1350 | void (*update_tkip_key)(struct ieee80211_hw *hw, | 1352 | void (*update_tkip_key)(struct ieee80211_hw *hw, |
1351 | struct ieee80211_key_conf *conf, const u8 *address, | 1353 | struct ieee80211_key_conf *conf, const u8 *address, |
1352 | u32 iv32, u16 *phase1key); | 1354 | u32 iv32, u16 *phase1key); |
1353 | int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len); | 1355 | int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len); |
1354 | int (*get_stats)(struct ieee80211_hw *hw, | 1356 | int (*get_stats)(struct ieee80211_hw *hw, |
1355 | struct ieee80211_low_level_stats *stats); | 1357 | struct ieee80211_low_level_stats *stats); |
1356 | void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, | 1358 | void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, |
1357 | u32 *iv32, u16 *iv16); | 1359 | u32 *iv32, u16 *iv16); |
1358 | int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); | 1360 | int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); |
1359 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1361 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1360 | enum sta_notify_cmd, struct ieee80211_sta *sta); | 1362 | enum sta_notify_cmd, struct ieee80211_sta *sta); |
1361 | int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, | 1363 | int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, |
1362 | const struct ieee80211_tx_queue_params *params); | 1364 | const struct ieee80211_tx_queue_params *params); |
1363 | int (*get_tx_stats)(struct ieee80211_hw *hw, | 1365 | int (*get_tx_stats)(struct ieee80211_hw *hw, |
1364 | struct ieee80211_tx_queue_stats *stats); | 1366 | struct ieee80211_tx_queue_stats *stats); |
1365 | u64 (*get_tsf)(struct ieee80211_hw *hw); | 1367 | u64 (*get_tsf)(struct ieee80211_hw *hw); |
1366 | void (*reset_tsf)(struct ieee80211_hw *hw); | 1368 | void (*reset_tsf)(struct ieee80211_hw *hw); |
1367 | int (*tx_last_beacon)(struct ieee80211_hw *hw); | 1369 | int (*tx_last_beacon)(struct ieee80211_hw *hw); |
1368 | int (*ampdu_action)(struct ieee80211_hw *hw, | 1370 | int (*ampdu_action)(struct ieee80211_hw *hw, |
1369 | enum ieee80211_ampdu_mlme_action action, | 1371 | enum ieee80211_ampdu_mlme_action action, |
1370 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 1372 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); |
1371 | }; | 1373 | }; |
1372 | 1374 | ||
1373 | /** | 1375 | /** |
1374 | * ieee80211_alloc_hw - Allocate a new hardware device | 1376 | * ieee80211_alloc_hw - Allocate a new hardware device |
1375 | * | 1377 | * |
1376 | * This must be called once for each hardware device. The returned pointer | 1378 | * This must be called once for each hardware device. The returned pointer |
1377 | * must be used to refer to this device when calling other functions. | 1379 | * must be used to refer to this device when calling other functions. |
1378 | * mac80211 allocates a private data area for the driver pointed to by | 1380 | * mac80211 allocates a private data area for the driver pointed to by |
1379 | * @priv in &struct ieee80211_hw, the size of this area is given as | 1381 | * @priv in &struct ieee80211_hw, the size of this area is given as |
1380 | * @priv_data_len. | 1382 | * @priv_data_len. |
1381 | * | 1383 | * |
1382 | * @priv_data_len: length of private data | 1384 | * @priv_data_len: length of private data |
1383 | * @ops: callbacks for this device | 1385 | * @ops: callbacks for this device |
1384 | */ | 1386 | */ |
1385 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 1387 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
1386 | const struct ieee80211_ops *ops); | 1388 | const struct ieee80211_ops *ops); |
1387 | 1389 | ||
1388 | /** | 1390 | /** |
1389 | * ieee80211_register_hw - Register hardware device | 1391 | * ieee80211_register_hw - Register hardware device |
1390 | * | 1392 | * |
1391 | * You must call this function before any other functions in | 1393 | * You must call this function before any other functions in |
1392 | * mac80211. Note that before a hardware can be registered, you | 1394 | * mac80211. Note that before a hardware can be registered, you |
1393 | * need to fill the contained wiphy's information. | 1395 | * need to fill the contained wiphy's information. |
1394 | * | 1396 | * |
1395 | * @hw: the device to register as returned by ieee80211_alloc_hw() | 1397 | * @hw: the device to register as returned by ieee80211_alloc_hw() |
1396 | */ | 1398 | */ |
1397 | int ieee80211_register_hw(struct ieee80211_hw *hw); | 1399 | int ieee80211_register_hw(struct ieee80211_hw *hw); |
1398 | 1400 | ||
1399 | #ifdef CONFIG_MAC80211_LEDS | 1401 | #ifdef CONFIG_MAC80211_LEDS |
1400 | extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw); | 1402 | extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw); |
1401 | extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw); | 1403 | extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw); |
1402 | extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw); | 1404 | extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw); |
1403 | extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw); | 1405 | extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw); |
1404 | #endif | 1406 | #endif |
1405 | /** | 1407 | /** |
1406 | * ieee80211_get_tx_led_name - get name of TX LED | 1408 | * ieee80211_get_tx_led_name - get name of TX LED |
1407 | * | 1409 | * |
1408 | * mac80211 creates a transmit LED trigger for each wireless hardware | 1410 | * mac80211 creates a transmit LED trigger for each wireless hardware |
1409 | * that can be used to drive LEDs if your driver registers a LED device. | 1411 | * that can be used to drive LEDs if your driver registers a LED device. |
1410 | * This function returns the name (or %NULL if not configured for LEDs) | 1412 | * This function returns the name (or %NULL if not configured for LEDs) |
1411 | * of the trigger so you can automatically link the LED device. | 1413 | * of the trigger so you can automatically link the LED device. |
1412 | * | 1414 | * |
1413 | * @hw: the hardware to get the LED trigger name for | 1415 | * @hw: the hardware to get the LED trigger name for |
1414 | */ | 1416 | */ |
1415 | static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw) | 1417 | static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw) |
1416 | { | 1418 | { |
1417 | #ifdef CONFIG_MAC80211_LEDS | 1419 | #ifdef CONFIG_MAC80211_LEDS |
1418 | return __ieee80211_get_tx_led_name(hw); | 1420 | return __ieee80211_get_tx_led_name(hw); |
1419 | #else | 1421 | #else |
1420 | return NULL; | 1422 | return NULL; |
1421 | #endif | 1423 | #endif |
1422 | } | 1424 | } |
1423 | 1425 | ||
1424 | /** | 1426 | /** |
1425 | * ieee80211_get_rx_led_name - get name of RX LED | 1427 | * ieee80211_get_rx_led_name - get name of RX LED |
1426 | * | 1428 | * |
1427 | * mac80211 creates a receive LED trigger for each wireless hardware | 1429 | * mac80211 creates a receive LED trigger for each wireless hardware |
1428 | * that can be used to drive LEDs if your driver registers a LED device. | 1430 | * that can be used to drive LEDs if your driver registers a LED device. |
1429 | * This function returns the name (or %NULL if not configured for LEDs) | 1431 | * This function returns the name (or %NULL if not configured for LEDs) |
1430 | * of the trigger so you can automatically link the LED device. | 1432 | * of the trigger so you can automatically link the LED device. |
1431 | * | 1433 | * |
1432 | * @hw: the hardware to get the LED trigger name for | 1434 | * @hw: the hardware to get the LED trigger name for |
1433 | */ | 1435 | */ |
1434 | static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw) | 1436 | static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw) |
1435 | { | 1437 | { |
1436 | #ifdef CONFIG_MAC80211_LEDS | 1438 | #ifdef CONFIG_MAC80211_LEDS |
1437 | return __ieee80211_get_rx_led_name(hw); | 1439 | return __ieee80211_get_rx_led_name(hw); |
1438 | #else | 1440 | #else |
1439 | return NULL; | 1441 | return NULL; |
1440 | #endif | 1442 | #endif |
1441 | } | 1443 | } |
1442 | 1444 | ||
1443 | /** | 1445 | /** |
1444 | * ieee80211_get_assoc_led_name - get name of association LED | 1446 | * ieee80211_get_assoc_led_name - get name of association LED |
1445 | * | 1447 | * |
1446 | * mac80211 creates a association LED trigger for each wireless hardware | 1448 | * mac80211 creates a association LED trigger for each wireless hardware |
1447 | * that can be used to drive LEDs if your driver registers a LED device. | 1449 | * that can be used to drive LEDs if your driver registers a LED device. |
1448 | * This function returns the name (or %NULL if not configured for LEDs) | 1450 | * This function returns the name (or %NULL if not configured for LEDs) |
1449 | * of the trigger so you can automatically link the LED device. | 1451 | * of the trigger so you can automatically link the LED device. |
1450 | * | 1452 | * |
1451 | * @hw: the hardware to get the LED trigger name for | 1453 | * @hw: the hardware to get the LED trigger name for |
1452 | */ | 1454 | */ |
1453 | static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) | 1455 | static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) |
1454 | { | 1456 | { |
1455 | #ifdef CONFIG_MAC80211_LEDS | 1457 | #ifdef CONFIG_MAC80211_LEDS |
1456 | return __ieee80211_get_assoc_led_name(hw); | 1458 | return __ieee80211_get_assoc_led_name(hw); |
1457 | #else | 1459 | #else |
1458 | return NULL; | 1460 | return NULL; |
1459 | #endif | 1461 | #endif |
1460 | } | 1462 | } |
1461 | 1463 | ||
1462 | /** | 1464 | /** |
1463 | * ieee80211_get_radio_led_name - get name of radio LED | 1465 | * ieee80211_get_radio_led_name - get name of radio LED |
1464 | * | 1466 | * |
1465 | * mac80211 creates a radio change LED trigger for each wireless hardware | 1467 | * mac80211 creates a radio change LED trigger for each wireless hardware |
1466 | * that can be used to drive LEDs if your driver registers a LED device. | 1468 | * that can be used to drive LEDs if your driver registers a LED device. |
1467 | * This function returns the name (or %NULL if not configured for LEDs) | 1469 | * This function returns the name (or %NULL if not configured for LEDs) |
1468 | * of the trigger so you can automatically link the LED device. | 1470 | * of the trigger so you can automatically link the LED device. |
1469 | * | 1471 | * |
1470 | * @hw: the hardware to get the LED trigger name for | 1472 | * @hw: the hardware to get the LED trigger name for |
1471 | */ | 1473 | */ |
1472 | static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) | 1474 | static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) |
1473 | { | 1475 | { |
1474 | #ifdef CONFIG_MAC80211_LEDS | 1476 | #ifdef CONFIG_MAC80211_LEDS |
1475 | return __ieee80211_get_radio_led_name(hw); | 1477 | return __ieee80211_get_radio_led_name(hw); |
1476 | #else | 1478 | #else |
1477 | return NULL; | 1479 | return NULL; |
1478 | #endif | 1480 | #endif |
1479 | } | 1481 | } |
1480 | 1482 | ||
1481 | /** | 1483 | /** |
1482 | * ieee80211_unregister_hw - Unregister a hardware device | 1484 | * ieee80211_unregister_hw - Unregister a hardware device |
1483 | * | 1485 | * |
1484 | * This function instructs mac80211 to free allocated resources | 1486 | * This function instructs mac80211 to free allocated resources |
1485 | * and unregister netdevices from the networking subsystem. | 1487 | * and unregister netdevices from the networking subsystem. |
1486 | * | 1488 | * |
1487 | * @hw: the hardware to unregister | 1489 | * @hw: the hardware to unregister |
1488 | */ | 1490 | */ |
1489 | void ieee80211_unregister_hw(struct ieee80211_hw *hw); | 1491 | void ieee80211_unregister_hw(struct ieee80211_hw *hw); |
1490 | 1492 | ||
1491 | /** | 1493 | /** |
1492 | * ieee80211_free_hw - free hardware descriptor | 1494 | * ieee80211_free_hw - free hardware descriptor |
1493 | * | 1495 | * |
1494 | * This function frees everything that was allocated, including the | 1496 | * This function frees everything that was allocated, including the |
1495 | * private data for the driver. You must call ieee80211_unregister_hw() | 1497 | * private data for the driver. You must call ieee80211_unregister_hw() |
1496 | * before calling this function. | 1498 | * before calling this function. |
1497 | * | 1499 | * |
1498 | * @hw: the hardware to free | 1500 | * @hw: the hardware to free |
1499 | */ | 1501 | */ |
1500 | void ieee80211_free_hw(struct ieee80211_hw *hw); | 1502 | void ieee80211_free_hw(struct ieee80211_hw *hw); |
1501 | 1503 | ||
1502 | /* trick to avoid symbol clashes with the ieee80211 subsystem */ | 1504 | /* trick to avoid symbol clashes with the ieee80211 subsystem */ |
1503 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | 1505 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, |
1504 | struct ieee80211_rx_status *status); | 1506 | struct ieee80211_rx_status *status); |
1505 | 1507 | ||
1506 | /** | 1508 | /** |
1507 | * ieee80211_rx - receive frame | 1509 | * ieee80211_rx - receive frame |
1508 | * | 1510 | * |
1509 | * Use this function to hand received frames to mac80211. The receive | 1511 | * Use this function to hand received frames to mac80211. The receive |
1510 | * buffer in @skb must start with an IEEE 802.11 header or a radiotap | 1512 | * buffer in @skb must start with an IEEE 802.11 header or a radiotap |
1511 | * header if %RX_FLAG_RADIOTAP is set in the @status flags. | 1513 | * header if %RX_FLAG_RADIOTAP is set in the @status flags. |
1512 | * | 1514 | * |
1513 | * This function may not be called in IRQ context. Calls to this function | 1515 | * This function may not be called in IRQ context. Calls to this function |
1514 | * for a single hardware must be synchronized against each other. Calls | 1516 | * for a single hardware must be synchronized against each other. Calls |
1515 | * to this function and ieee80211_rx_irqsafe() may not be mixed for a | 1517 | * to this function and ieee80211_rx_irqsafe() may not be mixed for a |
1516 | * single hardware. | 1518 | * single hardware. |
1517 | * | 1519 | * |
1518 | * @hw: the hardware this frame came in on | 1520 | * @hw: the hardware this frame came in on |
1519 | * @skb: the buffer to receive, owned by mac80211 after this call | 1521 | * @skb: the buffer to receive, owned by mac80211 after this call |
1520 | * @status: status of this frame; the status pointer need not be valid | 1522 | * @status: status of this frame; the status pointer need not be valid |
1521 | * after this function returns | 1523 | * after this function returns |
1522 | */ | 1524 | */ |
1523 | static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | 1525 | static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, |
1524 | struct ieee80211_rx_status *status) | 1526 | struct ieee80211_rx_status *status) |
1525 | { | 1527 | { |
1526 | __ieee80211_rx(hw, skb, status); | 1528 | __ieee80211_rx(hw, skb, status); |
1527 | } | 1529 | } |
1528 | 1530 | ||
1529 | /** | 1531 | /** |
1530 | * ieee80211_rx_irqsafe - receive frame | 1532 | * ieee80211_rx_irqsafe - receive frame |
1531 | * | 1533 | * |
1532 | * Like ieee80211_rx() but can be called in IRQ context | 1534 | * Like ieee80211_rx() but can be called in IRQ context |
1533 | * (internally defers to a tasklet.) | 1535 | * (internally defers to a tasklet.) |
1534 | * | 1536 | * |
1535 | * Calls to this function and ieee80211_rx() may not be mixed for a | 1537 | * Calls to this function and ieee80211_rx() may not be mixed for a |
1536 | * single hardware. | 1538 | * single hardware. |
1537 | * | 1539 | * |
1538 | * @hw: the hardware this frame came in on | 1540 | * @hw: the hardware this frame came in on |
1539 | * @skb: the buffer to receive, owned by mac80211 after this call | 1541 | * @skb: the buffer to receive, owned by mac80211 after this call |
1540 | * @status: status of this frame; the status pointer need not be valid | 1542 | * @status: status of this frame; the status pointer need not be valid |
1541 | * after this function returns and is not freed by mac80211, | 1543 | * after this function returns and is not freed by mac80211, |
1542 | * it is recommended that it points to a stack area | 1544 | * it is recommended that it points to a stack area |
1543 | */ | 1545 | */ |
1544 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, | 1546 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, |
1545 | struct sk_buff *skb, | 1547 | struct sk_buff *skb, |
1546 | struct ieee80211_rx_status *status); | 1548 | struct ieee80211_rx_status *status); |
1547 | 1549 | ||
1548 | /** | 1550 | /** |
1549 | * ieee80211_tx_status - transmit status callback | 1551 | * ieee80211_tx_status - transmit status callback |
1550 | * | 1552 | * |
1551 | * Call this function for all transmitted frames after they have been | 1553 | * Call this function for all transmitted frames after they have been |
1552 | * transmitted. It is permissible to not call this function for | 1554 | * transmitted. It is permissible to not call this function for |
1553 | * multicast frames but this can affect statistics. | 1555 | * multicast frames but this can affect statistics. |
1554 | * | 1556 | * |
1555 | * This function may not be called in IRQ context. Calls to this function | 1557 | * This function may not be called in IRQ context. Calls to this function |
1556 | * for a single hardware must be synchronized against each other. Calls | 1558 | * for a single hardware must be synchronized against each other. Calls |
1557 | * to this function and ieee80211_tx_status_irqsafe() may not be mixed | 1559 | * to this function and ieee80211_tx_status_irqsafe() may not be mixed |
1558 | * for a single hardware. | 1560 | * for a single hardware. |
1559 | * | 1561 | * |
1560 | * @hw: the hardware the frame was transmitted by | 1562 | * @hw: the hardware the frame was transmitted by |
1561 | * @skb: the frame that was transmitted, owned by mac80211 after this call | 1563 | * @skb: the frame that was transmitted, owned by mac80211 after this call |
1562 | */ | 1564 | */ |
1563 | void ieee80211_tx_status(struct ieee80211_hw *hw, | 1565 | void ieee80211_tx_status(struct ieee80211_hw *hw, |
1564 | struct sk_buff *skb); | 1566 | struct sk_buff *skb); |
1565 | 1567 | ||
1566 | /** | 1568 | /** |
1567 | * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback | 1569 | * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback |
1568 | * | 1570 | * |
1569 | * Like ieee80211_tx_status() but can be called in IRQ context | 1571 | * Like ieee80211_tx_status() but can be called in IRQ context |
1570 | * (internally defers to a tasklet.) | 1572 | * (internally defers to a tasklet.) |
1571 | * | 1573 | * |
1572 | * Calls to this function and ieee80211_tx_status() may not be mixed for a | 1574 | * Calls to this function and ieee80211_tx_status() may not be mixed for a |
1573 | * single hardware. | 1575 | * single hardware. |
1574 | * | 1576 | * |
1575 | * @hw: the hardware the frame was transmitted by | 1577 | * @hw: the hardware the frame was transmitted by |
1576 | * @skb: the frame that was transmitted, owned by mac80211 after this call | 1578 | * @skb: the frame that was transmitted, owned by mac80211 after this call |
1577 | */ | 1579 | */ |
1578 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 1580 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
1579 | struct sk_buff *skb); | 1581 | struct sk_buff *skb); |
1580 | 1582 | ||
1581 | /** | 1583 | /** |
1582 | * ieee80211_beacon_get - beacon generation function | 1584 | * ieee80211_beacon_get - beacon generation function |
1583 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1585 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1584 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1586 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1585 | * | 1587 | * |
1586 | * If the beacon frames are generated by the host system (i.e., not in | 1588 | * If the beacon frames are generated by the host system (i.e., not in |
1587 | * hardware/firmware), the low-level driver uses this function to receive | 1589 | * hardware/firmware), the low-level driver uses this function to receive |
1588 | * the next beacon frame from the 802.11 code. The low-level is responsible | 1590 | * the next beacon frame from the 802.11 code. The low-level is responsible |
1589 | * for calling this function before beacon data is needed (e.g., based on | 1591 | * for calling this function before beacon data is needed (e.g., based on |
1590 | * hardware interrupt). Returned skb is used only once and low-level driver | 1592 | * hardware interrupt). Returned skb is used only once and low-level driver |
1591 | * is responsible for freeing it. | 1593 | * is responsible for freeing it. |
1592 | */ | 1594 | */ |
1593 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | 1595 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, |
1594 | struct ieee80211_vif *vif); | 1596 | struct ieee80211_vif *vif); |
1595 | 1597 | ||
1596 | /** | 1598 | /** |
1597 | * ieee80211_rts_get - RTS frame generation function | 1599 | * ieee80211_rts_get - RTS frame generation function |
1598 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1600 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1599 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1601 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1600 | * @frame: pointer to the frame that is going to be protected by the RTS. | 1602 | * @frame: pointer to the frame that is going to be protected by the RTS. |
1601 | * @frame_len: the frame length (in octets). | 1603 | * @frame_len: the frame length (in octets). |
1602 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1604 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1603 | * @rts: The buffer where to store the RTS frame. | 1605 | * @rts: The buffer where to store the RTS frame. |
1604 | * | 1606 | * |
1605 | * If the RTS frames are generated by the host system (i.e., not in | 1607 | * If the RTS frames are generated by the host system (i.e., not in |
1606 | * hardware/firmware), the low-level driver uses this function to receive | 1608 | * hardware/firmware), the low-level driver uses this function to receive |
1607 | * the next RTS frame from the 802.11 code. The low-level is responsible | 1609 | * the next RTS frame from the 802.11 code. The low-level is responsible |
1608 | * for calling this function before and RTS frame is needed. | 1610 | * for calling this function before and RTS frame is needed. |
1609 | */ | 1611 | */ |
1610 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1612 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1611 | const void *frame, size_t frame_len, | 1613 | const void *frame, size_t frame_len, |
1612 | const struct ieee80211_tx_info *frame_txctl, | 1614 | const struct ieee80211_tx_info *frame_txctl, |
1613 | struct ieee80211_rts *rts); | 1615 | struct ieee80211_rts *rts); |
1614 | 1616 | ||
1615 | /** | 1617 | /** |
1616 | * ieee80211_rts_duration - Get the duration field for an RTS frame | 1618 | * ieee80211_rts_duration - Get the duration field for an RTS frame |
1617 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1619 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1618 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1620 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1619 | * @frame_len: the length of the frame that is going to be protected by the RTS. | 1621 | * @frame_len: the length of the frame that is going to be protected by the RTS. |
1620 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1622 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1621 | * | 1623 | * |
1622 | * If the RTS is generated in firmware, but the host system must provide | 1624 | * If the RTS is generated in firmware, but the host system must provide |
1623 | * the duration field, the low-level driver uses this function to receive | 1625 | * the duration field, the low-level driver uses this function to receive |
1624 | * the duration field value in little-endian byteorder. | 1626 | * the duration field value in little-endian byteorder. |
1625 | */ | 1627 | */ |
1626 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | 1628 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, |
1627 | struct ieee80211_vif *vif, size_t frame_len, | 1629 | struct ieee80211_vif *vif, size_t frame_len, |
1628 | const struct ieee80211_tx_info *frame_txctl); | 1630 | const struct ieee80211_tx_info *frame_txctl); |
1629 | 1631 | ||
1630 | /** | 1632 | /** |
1631 | * ieee80211_ctstoself_get - CTS-to-self frame generation function | 1633 | * ieee80211_ctstoself_get - CTS-to-self frame generation function |
1632 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1634 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1633 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1635 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1634 | * @frame: pointer to the frame that is going to be protected by the CTS-to-self. | 1636 | * @frame: pointer to the frame that is going to be protected by the CTS-to-self. |
1635 | * @frame_len: the frame length (in octets). | 1637 | * @frame_len: the frame length (in octets). |
1636 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1638 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1637 | * @cts: The buffer where to store the CTS-to-self frame. | 1639 | * @cts: The buffer where to store the CTS-to-self frame. |
1638 | * | 1640 | * |
1639 | * If the CTS-to-self frames are generated by the host system (i.e., not in | 1641 | * If the CTS-to-self frames are generated by the host system (i.e., not in |
1640 | * hardware/firmware), the low-level driver uses this function to receive | 1642 | * hardware/firmware), the low-level driver uses this function to receive |
1641 | * the next CTS-to-self frame from the 802.11 code. The low-level is responsible | 1643 | * the next CTS-to-self frame from the 802.11 code. The low-level is responsible |
1642 | * for calling this function before and CTS-to-self frame is needed. | 1644 | * for calling this function before and CTS-to-self frame is needed. |
1643 | */ | 1645 | */ |
1644 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, | 1646 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, |
1645 | struct ieee80211_vif *vif, | 1647 | struct ieee80211_vif *vif, |
1646 | const void *frame, size_t frame_len, | 1648 | const void *frame, size_t frame_len, |
1647 | const struct ieee80211_tx_info *frame_txctl, | 1649 | const struct ieee80211_tx_info *frame_txctl, |
1648 | struct ieee80211_cts *cts); | 1650 | struct ieee80211_cts *cts); |
1649 | 1651 | ||
1650 | /** | 1652 | /** |
1651 | * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame | 1653 | * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame |
1652 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1654 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1653 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1655 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1654 | * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. | 1656 | * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. |
1655 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1657 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1656 | * | 1658 | * |
1657 | * If the CTS-to-self is generated in firmware, but the host system must provide | 1659 | * If the CTS-to-self is generated in firmware, but the host system must provide |
1658 | * the duration field, the low-level driver uses this function to receive | 1660 | * the duration field, the low-level driver uses this function to receive |
1659 | * the duration field value in little-endian byteorder. | 1661 | * the duration field value in little-endian byteorder. |
1660 | */ | 1662 | */ |
1661 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | 1663 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, |
1662 | struct ieee80211_vif *vif, | 1664 | struct ieee80211_vif *vif, |
1663 | size_t frame_len, | 1665 | size_t frame_len, |
1664 | const struct ieee80211_tx_info *frame_txctl); | 1666 | const struct ieee80211_tx_info *frame_txctl); |
1665 | 1667 | ||
1666 | /** | 1668 | /** |
1667 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame | 1669 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame |
1668 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1670 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1669 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1671 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1670 | * @frame_len: the length of the frame. | 1672 | * @frame_len: the length of the frame. |
1671 | * @rate: the rate at which the frame is going to be transmitted. | 1673 | * @rate: the rate at which the frame is going to be transmitted. |
1672 | * | 1674 | * |
1673 | * Calculate the duration field of some generic frame, given its | 1675 | * Calculate the duration field of some generic frame, given its |
1674 | * length and transmission rate (in 100kbps). | 1676 | * length and transmission rate (in 100kbps). |
1675 | */ | 1677 | */ |
1676 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | 1678 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, |
1677 | struct ieee80211_vif *vif, | 1679 | struct ieee80211_vif *vif, |
1678 | size_t frame_len, | 1680 | size_t frame_len, |
1679 | struct ieee80211_rate *rate); | 1681 | struct ieee80211_rate *rate); |
1680 | 1682 | ||
1681 | /** | 1683 | /** |
1682 | * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames | 1684 | * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames |
1683 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1685 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1684 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1686 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1685 | * | 1687 | * |
1686 | * Function for accessing buffered broadcast and multicast frames. If | 1688 | * Function for accessing buffered broadcast and multicast frames. If |
1687 | * hardware/firmware does not implement buffering of broadcast/multicast | 1689 | * hardware/firmware does not implement buffering of broadcast/multicast |
1688 | * frames when power saving is used, 802.11 code buffers them in the host | 1690 | * frames when power saving is used, 802.11 code buffers them in the host |
1689 | * memory. The low-level driver uses this function to fetch next buffered | 1691 | * memory. The low-level driver uses this function to fetch next buffered |
1690 | * frame. In most cases, this is used when generating beacon frame. This | 1692 | * frame. In most cases, this is used when generating beacon frame. This |
1691 | * function returns a pointer to the next buffered skb or NULL if no more | 1693 | * function returns a pointer to the next buffered skb or NULL if no more |
1692 | * buffered frames are available. | 1694 | * buffered frames are available. |
1693 | * | 1695 | * |
1694 | * Note: buffered frames are returned only after DTIM beacon frame was | 1696 | * Note: buffered frames are returned only after DTIM beacon frame was |
1695 | * generated with ieee80211_beacon_get() and the low-level driver must thus | 1697 | * generated with ieee80211_beacon_get() and the low-level driver must thus |
1696 | * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns | 1698 | * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns |
1697 | * NULL if the previous generated beacon was not DTIM, so the low-level driver | 1699 | * NULL if the previous generated beacon was not DTIM, so the low-level driver |
1698 | * does not need to check for DTIM beacons separately and should be able to | 1700 | * does not need to check for DTIM beacons separately and should be able to |
1699 | * use common code for all beacons. | 1701 | * use common code for all beacons. |
1700 | */ | 1702 | */ |
1701 | struct sk_buff * | 1703 | struct sk_buff * |
1702 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 1704 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
1703 | 1705 | ||
1704 | /** | 1706 | /** |
1705 | * ieee80211_get_hdrlen_from_skb - get header length from data | 1707 | * ieee80211_get_hdrlen_from_skb - get header length from data |
1706 | * | 1708 | * |
1707 | * Given an skb with a raw 802.11 header at the data pointer this function | 1709 | * Given an skb with a raw 802.11 header at the data pointer this function |
1708 | * returns the 802.11 header length in bytes (not including encryption | 1710 | * returns the 802.11 header length in bytes (not including encryption |
1709 | * headers). If the data in the sk_buff is too short to contain a valid 802.11 | 1711 | * headers). If the data in the sk_buff is too short to contain a valid 802.11 |
1710 | * header the function returns 0. | 1712 | * header the function returns 0. |
1711 | * | 1713 | * |
1712 | * @skb: the frame | 1714 | * @skb: the frame |
1713 | */ | 1715 | */ |
1714 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); | 1716 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); |
1715 | 1717 | ||
1716 | /** | 1718 | /** |
1717 | * ieee80211_hdrlen - get header length in bytes from frame control | 1719 | * ieee80211_hdrlen - get header length in bytes from frame control |
1718 | * @fc: frame control field in little-endian format | 1720 | * @fc: frame control field in little-endian format |
1719 | */ | 1721 | */ |
1720 | unsigned int ieee80211_hdrlen(__le16 fc); | 1722 | unsigned int ieee80211_hdrlen(__le16 fc); |
1721 | 1723 | ||
1722 | /** | 1724 | /** |
1723 | * ieee80211_get_tkip_key - get a TKIP rc4 for skb | 1725 | * ieee80211_get_tkip_key - get a TKIP rc4 for skb |
1724 | * | 1726 | * |
1725 | * This function computes a TKIP rc4 key for an skb. It computes | 1727 | * This function computes a TKIP rc4 key for an skb. It computes |
1726 | * a phase 1 key if needed (iv16 wraps around). This function is to | 1728 | * a phase 1 key if needed (iv16 wraps around). This function is to |
1727 | * be used by drivers which can do HW encryption but need to compute | 1729 | * be used by drivers which can do HW encryption but need to compute |
1728 | * to phase 1/2 key in SW. | 1730 | * to phase 1/2 key in SW. |
1729 | * | 1731 | * |
1730 | * @keyconf: the parameter passed with the set key | 1732 | * @keyconf: the parameter passed with the set key |
1731 | * @skb: the skb for which the key is needed | 1733 | * @skb: the skb for which the key is needed |
1732 | * @type: TBD | 1734 | * @type: TBD |
1733 | * @key: a buffer to which the key will be written | 1735 | * @key: a buffer to which the key will be written |
1734 | */ | 1736 | */ |
1735 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | 1737 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, |
1736 | struct sk_buff *skb, | 1738 | struct sk_buff *skb, |
1737 | enum ieee80211_tkip_key_type type, u8 *key); | 1739 | enum ieee80211_tkip_key_type type, u8 *key); |
1738 | /** | 1740 | /** |
1739 | * ieee80211_wake_queue - wake specific queue | 1741 | * ieee80211_wake_queue - wake specific queue |
1740 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1742 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1741 | * @queue: queue number (counted from zero). | 1743 | * @queue: queue number (counted from zero). |
1742 | * | 1744 | * |
1743 | * Drivers should use this function instead of netif_wake_queue. | 1745 | * Drivers should use this function instead of netif_wake_queue. |
1744 | */ | 1746 | */ |
1745 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue); | 1747 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue); |
1746 | 1748 | ||
1747 | /** | 1749 | /** |
1748 | * ieee80211_stop_queue - stop specific queue | 1750 | * ieee80211_stop_queue - stop specific queue |
1749 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1751 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1750 | * @queue: queue number (counted from zero). | 1752 | * @queue: queue number (counted from zero). |
1751 | * | 1753 | * |
1752 | * Drivers should use this function instead of netif_stop_queue. | 1754 | * Drivers should use this function instead of netif_stop_queue. |
1753 | */ | 1755 | */ |
1754 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue); | 1756 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue); |
1755 | 1757 | ||
1756 | /** | 1758 | /** |
1757 | * ieee80211_queue_stopped - test status of the queue | 1759 | * ieee80211_queue_stopped - test status of the queue |
1758 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1760 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1759 | * @queue: queue number (counted from zero). | 1761 | * @queue: queue number (counted from zero). |
1760 | * | 1762 | * |
1761 | * Drivers should use this function instead of netif_stop_queue. | 1763 | * Drivers should use this function instead of netif_stop_queue. |
1762 | */ | 1764 | */ |
1763 | 1765 | ||
1764 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue); | 1766 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue); |
1765 | 1767 | ||
1766 | /** | 1768 | /** |
1767 | * ieee80211_stop_queues - stop all queues | 1769 | * ieee80211_stop_queues - stop all queues |
1768 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1770 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1769 | * | 1771 | * |
1770 | * Drivers should use this function instead of netif_stop_queue. | 1772 | * Drivers should use this function instead of netif_stop_queue. |
1771 | */ | 1773 | */ |
1772 | void ieee80211_stop_queues(struct ieee80211_hw *hw); | 1774 | void ieee80211_stop_queues(struct ieee80211_hw *hw); |
1773 | 1775 | ||
1774 | /** | 1776 | /** |
1775 | * ieee80211_wake_queues - wake all queues | 1777 | * ieee80211_wake_queues - wake all queues |
1776 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1778 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1777 | * | 1779 | * |
1778 | * Drivers should use this function instead of netif_wake_queue. | 1780 | * Drivers should use this function instead of netif_wake_queue. |
1779 | */ | 1781 | */ |
1780 | void ieee80211_wake_queues(struct ieee80211_hw *hw); | 1782 | void ieee80211_wake_queues(struct ieee80211_hw *hw); |
1781 | 1783 | ||
1782 | /** | 1784 | /** |
1783 | * ieee80211_scan_completed - completed hardware scan | 1785 | * ieee80211_scan_completed - completed hardware scan |
1784 | * | 1786 | * |
1785 | * When hardware scan offload is used (i.e. the hw_scan() callback is | 1787 | * When hardware scan offload is used (i.e. the hw_scan() callback is |
1786 | * assigned) this function needs to be called by the driver to notify | 1788 | * assigned) this function needs to be called by the driver to notify |
1787 | * mac80211 that the scan finished. | 1789 | * mac80211 that the scan finished. |
1788 | * | 1790 | * |
1789 | * @hw: the hardware that finished the scan | 1791 | * @hw: the hardware that finished the scan |
1790 | */ | 1792 | */ |
1791 | void ieee80211_scan_completed(struct ieee80211_hw *hw); | 1793 | void ieee80211_scan_completed(struct ieee80211_hw *hw); |
1792 | 1794 | ||
1793 | /** | 1795 | /** |
1794 | * ieee80211_iterate_active_interfaces - iterate active interfaces | 1796 | * ieee80211_iterate_active_interfaces - iterate active interfaces |
1795 | * | 1797 | * |
1796 | * This function iterates over the interfaces associated with a given | 1798 | * This function iterates over the interfaces associated with a given |
1797 | * hardware that are currently active and calls the callback for them. | 1799 | * hardware that are currently active and calls the callback for them. |
1798 | * This function allows the iterator function to sleep, when the iterator | 1800 | * This function allows the iterator function to sleep, when the iterator |
1799 | * function is atomic @ieee80211_iterate_active_interfaces_atomic can | 1801 | * function is atomic @ieee80211_iterate_active_interfaces_atomic can |
1800 | * be used. | 1802 | * be used. |
1801 | * | 1803 | * |
1802 | * @hw: the hardware struct of which the interfaces should be iterated over | 1804 | * @hw: the hardware struct of which the interfaces should be iterated over |
1803 | * @iterator: the iterator function to call | 1805 | * @iterator: the iterator function to call |
1804 | * @data: first argument of the iterator function | 1806 | * @data: first argument of the iterator function |
1805 | */ | 1807 | */ |
1806 | void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, | 1808 | void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, |
1807 | void (*iterator)(void *data, u8 *mac, | 1809 | void (*iterator)(void *data, u8 *mac, |
1808 | struct ieee80211_vif *vif), | 1810 | struct ieee80211_vif *vif), |
1809 | void *data); | 1811 | void *data); |
1810 | 1812 | ||
1811 | /** | 1813 | /** |
1812 | * ieee80211_iterate_active_interfaces_atomic - iterate active interfaces | 1814 | * ieee80211_iterate_active_interfaces_atomic - iterate active interfaces |
1813 | * | 1815 | * |
1814 | * This function iterates over the interfaces associated with a given | 1816 | * This function iterates over the interfaces associated with a given |
1815 | * hardware that are currently active and calls the callback for them. | 1817 | * hardware that are currently active and calls the callback for them. |
1816 | * This function requires the iterator callback function to be atomic, | 1818 | * This function requires the iterator callback function to be atomic, |
1817 | * if that is not desired, use @ieee80211_iterate_active_interfaces instead. | 1819 | * if that is not desired, use @ieee80211_iterate_active_interfaces instead. |
1818 | * | 1820 | * |
1819 | * @hw: the hardware struct of which the interfaces should be iterated over | 1821 | * @hw: the hardware struct of which the interfaces should be iterated over |
1820 | * @iterator: the iterator function to call, cannot sleep | 1822 | * @iterator: the iterator function to call, cannot sleep |
1821 | * @data: first argument of the iterator function | 1823 | * @data: first argument of the iterator function |
1822 | */ | 1824 | */ |
1823 | void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, | 1825 | void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, |
1824 | void (*iterator)(void *data, | 1826 | void (*iterator)(void *data, |
1825 | u8 *mac, | 1827 | u8 *mac, |
1826 | struct ieee80211_vif *vif), | 1828 | struct ieee80211_vif *vif), |
1827 | void *data); | 1829 | void *data); |
1828 | 1830 | ||
1829 | /** | 1831 | /** |
1830 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. | 1832 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. |
1831 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1833 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1832 | * @ra: receiver address of the BA session recipient | 1834 | * @ra: receiver address of the BA session recipient |
1833 | * @tid: the TID to BA on. | 1835 | * @tid: the TID to BA on. |
1834 | * | 1836 | * |
1835 | * Return: success if addBA request was sent, failure otherwise | 1837 | * Return: success if addBA request was sent, failure otherwise |
1836 | * | 1838 | * |
1837 | * Although mac80211/low level driver/user space application can estimate | 1839 | * Although mac80211/low level driver/user space application can estimate |
1838 | * the need to start aggregation on a certain RA/TID, the session level | 1840 | * the need to start aggregation on a certain RA/TID, the session level |
1839 | * will be managed by the mac80211. | 1841 | * will be managed by the mac80211. |
1840 | */ | 1842 | */ |
1841 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid); | 1843 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid); |
1842 | 1844 | ||
1843 | /** | 1845 | /** |
1844 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. | 1846 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. |
1845 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1847 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1846 | * @ra: receiver address of the BA session recipient. | 1848 | * @ra: receiver address of the BA session recipient. |
1847 | * @tid: the TID to BA on. | 1849 | * @tid: the TID to BA on. |
1848 | * | 1850 | * |
1849 | * This function must be called by low level driver once it has | 1851 | * This function must be called by low level driver once it has |
1850 | * finished with preparations for the BA session. | 1852 | * finished with preparations for the BA session. |
1851 | */ | 1853 | */ |
1852 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); | 1854 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); |
1853 | 1855 | ||
1854 | /** | 1856 | /** |
1855 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. | 1857 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. |
1856 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1858 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1857 | * @ra: receiver address of the BA session recipient. | 1859 | * @ra: receiver address of the BA session recipient. |
1858 | * @tid: the TID to BA on. | 1860 | * @tid: the TID to BA on. |
1859 | * | 1861 | * |
1860 | * This function must be called by low level driver once it has | 1862 | * This function must be called by low level driver once it has |
1861 | * finished with preparations for the BA session. | 1863 | * finished with preparations for the BA session. |
1862 | * This version of the function is IRQ-safe. | 1864 | * This version of the function is IRQ-safe. |
1863 | */ | 1865 | */ |
1864 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 1866 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, |
1865 | u16 tid); | 1867 | u16 tid); |
1866 | 1868 | ||
1867 | /** | 1869 | /** |
1868 | * ieee80211_stop_tx_ba_session - Stop a Block Ack session. | 1870 | * ieee80211_stop_tx_ba_session - Stop a Block Ack session. |
1869 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1871 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1870 | * @ra: receiver address of the BA session recipient | 1872 | * @ra: receiver address of the BA session recipient |
1871 | * @tid: the TID to stop BA. | 1873 | * @tid: the TID to stop BA. |
1872 | * @initiator: if indicates initiator DELBA frame will be sent. | 1874 | * @initiator: if indicates initiator DELBA frame will be sent. |
1873 | * | 1875 | * |
1874 | * Return: error if no sta with matching da found, success otherwise | 1876 | * Return: error if no sta with matching da found, success otherwise |
1875 | * | 1877 | * |
1876 | * Although mac80211/low level driver/user space application can estimate | 1878 | * Although mac80211/low level driver/user space application can estimate |
1877 | * the need to stop aggregation on a certain RA/TID, the session level | 1879 | * the need to stop aggregation on a certain RA/TID, the session level |
1878 | * will be managed by the mac80211. | 1880 | * will be managed by the mac80211. |
1879 | */ | 1881 | */ |
1880 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | 1882 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, |
1881 | u8 *ra, u16 tid, | 1883 | u8 *ra, u16 tid, |
1882 | enum ieee80211_back_parties initiator); | 1884 | enum ieee80211_back_parties initiator); |
1883 | 1885 | ||
1884 | /** | 1886 | /** |
1885 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. | 1887 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. |
1886 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1888 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1887 | * @ra: receiver address of the BA session recipient. | 1889 | * @ra: receiver address of the BA session recipient. |
1888 | * @tid: the desired TID to BA on. | 1890 | * @tid: the desired TID to BA on. |
1889 | * | 1891 | * |
1890 | * This function must be called by low level driver once it has | 1892 | * This function must be called by low level driver once it has |
1891 | * finished with preparations for the BA session tear down. | 1893 | * finished with preparations for the BA session tear down. |
1892 | */ | 1894 | */ |
1893 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); | 1895 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); |
1894 | 1896 | ||
1895 | /** | 1897 | /** |
1896 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. | 1898 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. |
1897 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1899 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1898 | * @ra: receiver address of the BA session recipient. | 1900 | * @ra: receiver address of the BA session recipient. |
1899 | * @tid: the desired TID to BA on. | 1901 | * @tid: the desired TID to BA on. |
1900 | * | 1902 | * |
1901 | * This function must be called by low level driver once it has | 1903 | * This function must be called by low level driver once it has |
1902 | * finished with preparations for the BA session tear down. | 1904 | * finished with preparations for the BA session tear down. |
1903 | * This version of the function is IRQ-safe. | 1905 | * This version of the function is IRQ-safe. |
1904 | */ | 1906 | */ |
1905 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 1907 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, |
1906 | u16 tid); | 1908 | u16 tid); |
1907 | 1909 | ||
1908 | /** | 1910 | /** |
1909 | * ieee80211_find_sta - find a station | 1911 | * ieee80211_find_sta - find a station |
1910 | * | 1912 | * |
1911 | * @hw: pointer as obtained from ieee80211_alloc_hw() | 1913 | * @hw: pointer as obtained from ieee80211_alloc_hw() |
1912 | * @addr: station's address | 1914 | * @addr: station's address |
1913 | * | 1915 | * |
1914 | * This function must be called under RCU lock and the | 1916 | * This function must be called under RCU lock and the |
1915 | * resulting pointer is only valid under RCU lock as well. | 1917 | * resulting pointer is only valid under RCU lock as well. |
1916 | */ | 1918 | */ |
1917 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | 1919 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, |
1918 | const u8 *addr); | 1920 | const u8 *addr); |
1919 | 1921 | ||
1920 | 1922 | ||
1921 | /* Rate control API */ | 1923 | /* Rate control API */ |
1922 | 1924 | ||
1923 | /** | 1925 | /** |
1924 | * struct ieee80211_tx_rate_control - rate control information for/from RC algo | 1926 | * struct ieee80211_tx_rate_control - rate control information for/from RC algo |
1925 | * | 1927 | * |
1926 | * @hw: The hardware the algorithm is invoked for. | 1928 | * @hw: The hardware the algorithm is invoked for. |
1927 | * @sband: The band this frame is being transmitted on. | 1929 | * @sband: The band this frame is being transmitted on. |
1928 | * @bss_conf: the current BSS configuration | 1930 | * @bss_conf: the current BSS configuration |
1929 | * @reported_rate: The rate control algorithm can fill this in to indicate | 1931 | * @reported_rate: The rate control algorithm can fill this in to indicate |
1930 | * which rate should be reported to userspace as the current rate and | 1932 | * which rate should be reported to userspace as the current rate and |
1931 | * used for rate calculations in the mesh network. | 1933 | * used for rate calculations in the mesh network. |
1932 | * @rts: whether RTS will be used for this frame because it is longer than the | 1934 | * @rts: whether RTS will be used for this frame because it is longer than the |
1933 | * RTS threshold | 1935 | * RTS threshold |
1934 | * @short_preamble: whether mac80211 will request short-preamble transmission | 1936 | * @short_preamble: whether mac80211 will request short-preamble transmission |
1935 | * if the selected rate supports it | 1937 | * if the selected rate supports it |
1936 | * @max_rate_idx: user-requested maximum rate (not MCS for now) | 1938 | * @max_rate_idx: user-requested maximum rate (not MCS for now) |
1937 | * @skb: the skb that will be transmitted, the control information in it needs | 1939 | * @skb: the skb that will be transmitted, the control information in it needs |
1938 | * to be filled in | 1940 | * to be filled in |
1939 | */ | 1941 | */ |
1940 | struct ieee80211_tx_rate_control { | 1942 | struct ieee80211_tx_rate_control { |
1941 | struct ieee80211_hw *hw; | 1943 | struct ieee80211_hw *hw; |
1942 | struct ieee80211_supported_band *sband; | 1944 | struct ieee80211_supported_band *sband; |
1943 | struct ieee80211_bss_conf *bss_conf; | 1945 | struct ieee80211_bss_conf *bss_conf; |
1944 | struct sk_buff *skb; | 1946 | struct sk_buff *skb; |
1945 | struct ieee80211_tx_rate reported_rate; | 1947 | struct ieee80211_tx_rate reported_rate; |
1946 | bool rts, short_preamble; | 1948 | bool rts, short_preamble; |
1947 | u8 max_rate_idx; | 1949 | u8 max_rate_idx; |
1948 | }; | 1950 | }; |
1949 | 1951 | ||
1950 | struct rate_control_ops { | 1952 | struct rate_control_ops { |
1951 | struct module *module; | 1953 | struct module *module; |
1952 | const char *name; | 1954 | const char *name; |
1953 | void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); | 1955 | void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); |
1954 | void (*free)(void *priv); | 1956 | void (*free)(void *priv); |
1955 | 1957 | ||
1956 | void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); | 1958 | void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); |
1957 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, | 1959 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, |
1958 | struct ieee80211_sta *sta, void *priv_sta); | 1960 | struct ieee80211_sta *sta, void *priv_sta); |
1959 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, | 1961 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, |
1960 | void *priv_sta); | 1962 | void *priv_sta); |
1961 | 1963 | ||
1962 | void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, | 1964 | void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, |
1963 | struct ieee80211_sta *sta, void *priv_sta, | 1965 | struct ieee80211_sta *sta, void *priv_sta, |
1964 | struct sk_buff *skb); | 1966 | struct sk_buff *skb); |
1965 | void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta, | 1967 | void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta, |
1966 | struct ieee80211_tx_rate_control *txrc); | 1968 | struct ieee80211_tx_rate_control *txrc); |
1967 | 1969 | ||
1968 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | 1970 | void (*add_sta_debugfs)(void *priv, void *priv_sta, |
1969 | struct dentry *dir); | 1971 | struct dentry *dir); |
1970 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | 1972 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); |
1971 | }; | 1973 | }; |
1972 | 1974 | ||
1973 | static inline int rate_supported(struct ieee80211_sta *sta, | 1975 | static inline int rate_supported(struct ieee80211_sta *sta, |
1974 | enum ieee80211_band band, | 1976 | enum ieee80211_band band, |
1975 | int index) | 1977 | int index) |
1976 | { | 1978 | { |
1977 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); | 1979 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); |
1978 | } | 1980 | } |
1979 | 1981 | ||
1980 | static inline s8 | 1982 | static inline s8 |
1981 | rate_lowest_index(struct ieee80211_supported_band *sband, | 1983 | rate_lowest_index(struct ieee80211_supported_band *sband, |
1982 | struct ieee80211_sta *sta) | 1984 | struct ieee80211_sta *sta) |
1983 | { | 1985 | { |
1984 | int i; | 1986 | int i; |
1985 | 1987 | ||
1986 | for (i = 0; i < sband->n_bitrates; i++) | 1988 | for (i = 0; i < sband->n_bitrates; i++) |
1987 | if (rate_supported(sta, sband->band, i)) | 1989 | if (rate_supported(sta, sband->band, i)) |
1988 | return i; | 1990 | return i; |
1989 | 1991 | ||
1990 | /* warn when we cannot find a rate. */ | 1992 | /* warn when we cannot find a rate. */ |
1991 | WARN_ON(1); | 1993 | WARN_ON(1); |
1992 | 1994 | ||
1993 | return 0; | 1995 | return 0; |
1994 | } | 1996 | } |
1995 | 1997 | ||
1996 | 1998 | ||
1997 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | 1999 | int ieee80211_rate_control_register(struct rate_control_ops *ops); |
1998 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | 2000 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); |
1999 | 2001 | ||
2000 | static inline bool | 2002 | static inline bool |
2001 | conf_is_ht20(struct ieee80211_conf *conf) | 2003 | conf_is_ht20(struct ieee80211_conf *conf) |
2002 | { | 2004 | { |
2003 | return conf->channel_type == NL80211_CHAN_HT20; | 2005 | return conf->channel_type == NL80211_CHAN_HT20; |
2004 | } | 2006 | } |
2005 | 2007 | ||
2006 | static inline bool | 2008 | static inline bool |
2007 | conf_is_ht40_minus(struct ieee80211_conf *conf) | 2009 | conf_is_ht40_minus(struct ieee80211_conf *conf) |
2008 | { | 2010 | { |
2009 | return conf->channel_type == NL80211_CHAN_HT40MINUS; | 2011 | return conf->channel_type == NL80211_CHAN_HT40MINUS; |
2010 | } | 2012 | } |
2011 | 2013 | ||
2012 | static inline bool | 2014 | static inline bool |
2013 | conf_is_ht40_plus(struct ieee80211_conf *conf) | 2015 | conf_is_ht40_plus(struct ieee80211_conf *conf) |
2014 | { | 2016 | { |
2015 | return conf->channel_type == NL80211_CHAN_HT40PLUS; | 2017 | return conf->channel_type == NL80211_CHAN_HT40PLUS; |
2016 | } | 2018 | } |
2017 | 2019 | ||
2018 | static inline bool | 2020 | static inline bool |
2019 | conf_is_ht40(struct ieee80211_conf *conf) | 2021 | conf_is_ht40(struct ieee80211_conf *conf) |
2020 | { | 2022 | { |
2021 | return conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf); | 2023 | return conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf); |
2022 | } | 2024 | } |
2023 | 2025 | ||
2024 | static inline bool | 2026 | static inline bool |
2025 | conf_is_ht(struct ieee80211_conf *conf) | 2027 | conf_is_ht(struct ieee80211_conf *conf) |
2026 | { | 2028 | { |
2027 | return conf->channel_type != NL80211_CHAN_NO_HT; | 2029 | return conf->channel_type != NL80211_CHAN_NO_HT; |
2028 | } | 2030 | } |
2029 | 2031 | ||
2030 | #endif /* MAC80211_H */ | 2032 | #endif /* MAC80211_H */ |
2031 | 2033 |
net/mac80211/cfg.c
1 | /* | 1 | /* |
2 | * mac80211 configuration hooks for cfg80211 | 2 | * mac80211 configuration hooks for cfg80211 |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> |
5 | * | 5 | * |
6 | * This file is GPLv2 as found in COPYING. | 6 | * This file is GPLv2 as found in COPYING. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/ieee80211.h> | 9 | #include <linux/ieee80211.h> |
10 | #include <linux/nl80211.h> | 10 | #include <linux/nl80211.h> |
11 | #include <linux/rtnetlink.h> | 11 | #include <linux/rtnetlink.h> |
12 | #include <net/net_namespace.h> | 12 | #include <net/net_namespace.h> |
13 | #include <linux/rcupdate.h> | 13 | #include <linux/rcupdate.h> |
14 | #include <net/cfg80211.h> | 14 | #include <net/cfg80211.h> |
15 | #include "ieee80211_i.h" | 15 | #include "ieee80211_i.h" |
16 | #include "cfg.h" | 16 | #include "cfg.h" |
17 | #include "rate.h" | 17 | #include "rate.h" |
18 | #include "mesh.h" | 18 | #include "mesh.h" |
19 | 19 | ||
20 | static bool nl80211_type_check(enum nl80211_iftype type) | 20 | static bool nl80211_type_check(enum nl80211_iftype type) |
21 | { | 21 | { |
22 | switch (type) { | 22 | switch (type) { |
23 | case NL80211_IFTYPE_ADHOC: | 23 | case NL80211_IFTYPE_ADHOC: |
24 | case NL80211_IFTYPE_STATION: | 24 | case NL80211_IFTYPE_STATION: |
25 | case NL80211_IFTYPE_MONITOR: | 25 | case NL80211_IFTYPE_MONITOR: |
26 | #ifdef CONFIG_MAC80211_MESH | 26 | #ifdef CONFIG_MAC80211_MESH |
27 | case NL80211_IFTYPE_MESH_POINT: | 27 | case NL80211_IFTYPE_MESH_POINT: |
28 | #endif | 28 | #endif |
29 | case NL80211_IFTYPE_AP: | 29 | case NL80211_IFTYPE_AP: |
30 | case NL80211_IFTYPE_AP_VLAN: | 30 | case NL80211_IFTYPE_AP_VLAN: |
31 | case NL80211_IFTYPE_WDS: | 31 | case NL80211_IFTYPE_WDS: |
32 | return true; | 32 | return true; |
33 | default: | 33 | default: |
34 | return false; | 34 | return false; |
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
38 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | 38 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, |
39 | enum nl80211_iftype type, u32 *flags, | 39 | enum nl80211_iftype type, u32 *flags, |
40 | struct vif_params *params) | 40 | struct vif_params *params) |
41 | { | 41 | { |
42 | struct ieee80211_local *local = wiphy_priv(wiphy); | 42 | struct ieee80211_local *local = wiphy_priv(wiphy); |
43 | struct net_device *dev; | 43 | struct net_device *dev; |
44 | struct ieee80211_sub_if_data *sdata; | 44 | struct ieee80211_sub_if_data *sdata; |
45 | int err; | 45 | int err; |
46 | 46 | ||
47 | if (!nl80211_type_check(type)) | 47 | if (!nl80211_type_check(type)) |
48 | return -EINVAL; | 48 | return -EINVAL; |
49 | 49 | ||
50 | err = ieee80211_if_add(local, name, &dev, type, params); | 50 | err = ieee80211_if_add(local, name, &dev, type, params); |
51 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) | 51 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) |
52 | return err; | 52 | return err; |
53 | 53 | ||
54 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 54 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
55 | sdata->u.mntr_flags = *flags; | 55 | sdata->u.mntr_flags = *flags; |
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
59 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | 59 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) |
60 | { | 60 | { |
61 | struct net_device *dev; | 61 | struct net_device *dev; |
62 | struct ieee80211_sub_if_data *sdata; | 62 | struct ieee80211_sub_if_data *sdata; |
63 | 63 | ||
64 | /* we're under RTNL */ | 64 | /* we're under RTNL */ |
65 | dev = __dev_get_by_index(&init_net, ifindex); | 65 | dev = __dev_get_by_index(&init_net, ifindex); |
66 | if (!dev) | 66 | if (!dev) |
67 | return -ENODEV; | 67 | return -ENODEV; |
68 | 68 | ||
69 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 69 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
70 | 70 | ||
71 | ieee80211_if_remove(sdata); | 71 | ieee80211_if_remove(sdata); |
72 | 72 | ||
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | 76 | static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, |
77 | enum nl80211_iftype type, u32 *flags, | 77 | enum nl80211_iftype type, u32 *flags, |
78 | struct vif_params *params) | 78 | struct vif_params *params) |
79 | { | 79 | { |
80 | struct net_device *dev; | 80 | struct net_device *dev; |
81 | struct ieee80211_sub_if_data *sdata; | 81 | struct ieee80211_sub_if_data *sdata; |
82 | int ret; | 82 | int ret; |
83 | 83 | ||
84 | /* we're under RTNL */ | 84 | /* we're under RTNL */ |
85 | dev = __dev_get_by_index(&init_net, ifindex); | 85 | dev = __dev_get_by_index(&init_net, ifindex); |
86 | if (!dev) | 86 | if (!dev) |
87 | return -ENODEV; | 87 | return -ENODEV; |
88 | 88 | ||
89 | if (!nl80211_type_check(type)) | 89 | if (!nl80211_type_check(type)) |
90 | return -EINVAL; | 90 | return -EINVAL; |
91 | 91 | ||
92 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 92 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
93 | 93 | ||
94 | ret = ieee80211_if_change_type(sdata, type); | 94 | ret = ieee80211_if_change_type(sdata, type); |
95 | if (ret) | 95 | if (ret) |
96 | return ret; | 96 | return ret; |
97 | 97 | ||
98 | if (netif_running(sdata->dev)) | 98 | if (netif_running(sdata->dev)) |
99 | return -EBUSY; | 99 | return -EBUSY; |
100 | 100 | ||
101 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 101 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
102 | ieee80211_sdata_set_mesh_id(sdata, | 102 | ieee80211_sdata_set_mesh_id(sdata, |
103 | params->mesh_id_len, | 103 | params->mesh_id_len, |
104 | params->mesh_id); | 104 | params->mesh_id); |
105 | 105 | ||
106 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) | 106 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) |
107 | return 0; | 107 | return 0; |
108 | 108 | ||
109 | sdata->u.mntr_flags = *flags; | 109 | sdata->u.mntr_flags = *flags; |
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | 112 | ||
113 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | 113 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
114 | u8 key_idx, u8 *mac_addr, | 114 | u8 key_idx, u8 *mac_addr, |
115 | struct key_params *params) | 115 | struct key_params *params) |
116 | { | 116 | { |
117 | struct ieee80211_sub_if_data *sdata; | 117 | struct ieee80211_sub_if_data *sdata; |
118 | struct sta_info *sta = NULL; | 118 | struct sta_info *sta = NULL; |
119 | enum ieee80211_key_alg alg; | 119 | enum ieee80211_key_alg alg; |
120 | struct ieee80211_key *key; | 120 | struct ieee80211_key *key; |
121 | int err; | 121 | int err; |
122 | 122 | ||
123 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 123 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
124 | 124 | ||
125 | switch (params->cipher) { | 125 | switch (params->cipher) { |
126 | case WLAN_CIPHER_SUITE_WEP40: | 126 | case WLAN_CIPHER_SUITE_WEP40: |
127 | case WLAN_CIPHER_SUITE_WEP104: | 127 | case WLAN_CIPHER_SUITE_WEP104: |
128 | alg = ALG_WEP; | 128 | alg = ALG_WEP; |
129 | break; | 129 | break; |
130 | case WLAN_CIPHER_SUITE_TKIP: | 130 | case WLAN_CIPHER_SUITE_TKIP: |
131 | alg = ALG_TKIP; | 131 | alg = ALG_TKIP; |
132 | break; | 132 | break; |
133 | case WLAN_CIPHER_SUITE_CCMP: | 133 | case WLAN_CIPHER_SUITE_CCMP: |
134 | alg = ALG_CCMP; | 134 | alg = ALG_CCMP; |
135 | break; | 135 | break; |
136 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
137 | alg = ALG_AES_CMAC; | ||
138 | break; | ||
136 | default: | 139 | default: |
137 | return -EINVAL; | 140 | return -EINVAL; |
138 | } | 141 | } |
139 | 142 | ||
140 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key); | 143 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key); |
141 | if (!key) | 144 | if (!key) |
142 | return -ENOMEM; | 145 | return -ENOMEM; |
143 | 146 | ||
144 | rcu_read_lock(); | 147 | rcu_read_lock(); |
145 | 148 | ||
146 | if (mac_addr) { | 149 | if (mac_addr) { |
147 | sta = sta_info_get(sdata->local, mac_addr); | 150 | sta = sta_info_get(sdata->local, mac_addr); |
148 | if (!sta) { | 151 | if (!sta) { |
149 | ieee80211_key_free(key); | 152 | ieee80211_key_free(key); |
150 | err = -ENOENT; | 153 | err = -ENOENT; |
151 | goto out_unlock; | 154 | goto out_unlock; |
152 | } | 155 | } |
153 | } | 156 | } |
154 | 157 | ||
155 | ieee80211_key_link(key, sdata, sta); | 158 | ieee80211_key_link(key, sdata, sta); |
156 | 159 | ||
157 | err = 0; | 160 | err = 0; |
158 | out_unlock: | 161 | out_unlock: |
159 | rcu_read_unlock(); | 162 | rcu_read_unlock(); |
160 | 163 | ||
161 | return err; | 164 | return err; |
162 | } | 165 | } |
163 | 166 | ||
164 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 167 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
165 | u8 key_idx, u8 *mac_addr) | 168 | u8 key_idx, u8 *mac_addr) |
166 | { | 169 | { |
167 | struct ieee80211_sub_if_data *sdata; | 170 | struct ieee80211_sub_if_data *sdata; |
168 | struct sta_info *sta; | 171 | struct sta_info *sta; |
169 | int ret; | 172 | int ret; |
170 | 173 | ||
171 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 174 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
172 | 175 | ||
173 | rcu_read_lock(); | 176 | rcu_read_lock(); |
174 | 177 | ||
175 | if (mac_addr) { | 178 | if (mac_addr) { |
176 | ret = -ENOENT; | 179 | ret = -ENOENT; |
177 | 180 | ||
178 | sta = sta_info_get(sdata->local, mac_addr); | 181 | sta = sta_info_get(sdata->local, mac_addr); |
179 | if (!sta) | 182 | if (!sta) |
180 | goto out_unlock; | 183 | goto out_unlock; |
181 | 184 | ||
182 | if (sta->key) { | 185 | if (sta->key) { |
183 | ieee80211_key_free(sta->key); | 186 | ieee80211_key_free(sta->key); |
184 | WARN_ON(sta->key); | 187 | WARN_ON(sta->key); |
185 | ret = 0; | 188 | ret = 0; |
186 | } | 189 | } |
187 | 190 | ||
188 | goto out_unlock; | 191 | goto out_unlock; |
189 | } | 192 | } |
190 | 193 | ||
191 | if (!sdata->keys[key_idx]) { | 194 | if (!sdata->keys[key_idx]) { |
192 | ret = -ENOENT; | 195 | ret = -ENOENT; |
193 | goto out_unlock; | 196 | goto out_unlock; |
194 | } | 197 | } |
195 | 198 | ||
196 | ieee80211_key_free(sdata->keys[key_idx]); | 199 | ieee80211_key_free(sdata->keys[key_idx]); |
197 | WARN_ON(sdata->keys[key_idx]); | 200 | WARN_ON(sdata->keys[key_idx]); |
198 | 201 | ||
199 | ret = 0; | 202 | ret = 0; |
200 | out_unlock: | 203 | out_unlock: |
201 | rcu_read_unlock(); | 204 | rcu_read_unlock(); |
202 | 205 | ||
203 | return ret; | 206 | return ret; |
204 | } | 207 | } |
205 | 208 | ||
206 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | 209 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, |
207 | u8 key_idx, u8 *mac_addr, void *cookie, | 210 | u8 key_idx, u8 *mac_addr, void *cookie, |
208 | void (*callback)(void *cookie, | 211 | void (*callback)(void *cookie, |
209 | struct key_params *params)) | 212 | struct key_params *params)) |
210 | { | 213 | { |
211 | struct ieee80211_sub_if_data *sdata; | 214 | struct ieee80211_sub_if_data *sdata; |
212 | struct sta_info *sta = NULL; | 215 | struct sta_info *sta = NULL; |
213 | u8 seq[6] = {0}; | 216 | u8 seq[6] = {0}; |
214 | struct key_params params; | 217 | struct key_params params; |
215 | struct ieee80211_key *key; | 218 | struct ieee80211_key *key; |
216 | u32 iv32; | 219 | u32 iv32; |
217 | u16 iv16; | 220 | u16 iv16; |
218 | int err = -ENOENT; | 221 | int err = -ENOENT; |
219 | 222 | ||
220 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 223 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
221 | 224 | ||
222 | rcu_read_lock(); | 225 | rcu_read_lock(); |
223 | 226 | ||
224 | if (mac_addr) { | 227 | if (mac_addr) { |
225 | sta = sta_info_get(sdata->local, mac_addr); | 228 | sta = sta_info_get(sdata->local, mac_addr); |
226 | if (!sta) | 229 | if (!sta) |
227 | goto out; | 230 | goto out; |
228 | 231 | ||
229 | key = sta->key; | 232 | key = sta->key; |
230 | } else | 233 | } else |
231 | key = sdata->keys[key_idx]; | 234 | key = sdata->keys[key_idx]; |
232 | 235 | ||
233 | if (!key) | 236 | if (!key) |
234 | goto out; | 237 | goto out; |
235 | 238 | ||
236 | memset(¶ms, 0, sizeof(params)); | 239 | memset(¶ms, 0, sizeof(params)); |
237 | 240 | ||
238 | switch (key->conf.alg) { | 241 | switch (key->conf.alg) { |
239 | case ALG_TKIP: | 242 | case ALG_TKIP: |
240 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | 243 | params.cipher = WLAN_CIPHER_SUITE_TKIP; |
241 | 244 | ||
242 | iv32 = key->u.tkip.tx.iv32; | 245 | iv32 = key->u.tkip.tx.iv32; |
243 | iv16 = key->u.tkip.tx.iv16; | 246 | iv16 = key->u.tkip.tx.iv16; |
244 | 247 | ||
245 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && | 248 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
246 | sdata->local->ops->get_tkip_seq) | 249 | sdata->local->ops->get_tkip_seq) |
247 | sdata->local->ops->get_tkip_seq( | 250 | sdata->local->ops->get_tkip_seq( |
248 | local_to_hw(sdata->local), | 251 | local_to_hw(sdata->local), |
249 | key->conf.hw_key_idx, | 252 | key->conf.hw_key_idx, |
250 | &iv32, &iv16); | 253 | &iv32, &iv16); |
251 | 254 | ||
252 | seq[0] = iv16 & 0xff; | 255 | seq[0] = iv16 & 0xff; |
253 | seq[1] = (iv16 >> 8) & 0xff; | 256 | seq[1] = (iv16 >> 8) & 0xff; |
254 | seq[2] = iv32 & 0xff; | 257 | seq[2] = iv32 & 0xff; |
255 | seq[3] = (iv32 >> 8) & 0xff; | 258 | seq[3] = (iv32 >> 8) & 0xff; |
256 | seq[4] = (iv32 >> 16) & 0xff; | 259 | seq[4] = (iv32 >> 16) & 0xff; |
257 | seq[5] = (iv32 >> 24) & 0xff; | 260 | seq[5] = (iv32 >> 24) & 0xff; |
258 | params.seq = seq; | 261 | params.seq = seq; |
259 | params.seq_len = 6; | 262 | params.seq_len = 6; |
260 | break; | 263 | break; |
261 | case ALG_CCMP: | 264 | case ALG_CCMP: |
262 | params.cipher = WLAN_CIPHER_SUITE_CCMP; | 265 | params.cipher = WLAN_CIPHER_SUITE_CCMP; |
263 | seq[0] = key->u.ccmp.tx_pn[5]; | 266 | seq[0] = key->u.ccmp.tx_pn[5]; |
264 | seq[1] = key->u.ccmp.tx_pn[4]; | 267 | seq[1] = key->u.ccmp.tx_pn[4]; |
265 | seq[2] = key->u.ccmp.tx_pn[3]; | 268 | seq[2] = key->u.ccmp.tx_pn[3]; |
266 | seq[3] = key->u.ccmp.tx_pn[2]; | 269 | seq[3] = key->u.ccmp.tx_pn[2]; |
267 | seq[4] = key->u.ccmp.tx_pn[1]; | 270 | seq[4] = key->u.ccmp.tx_pn[1]; |
268 | seq[5] = key->u.ccmp.tx_pn[0]; | 271 | seq[5] = key->u.ccmp.tx_pn[0]; |
269 | params.seq = seq; | 272 | params.seq = seq; |
270 | params.seq_len = 6; | 273 | params.seq_len = 6; |
271 | break; | 274 | break; |
272 | case ALG_WEP: | 275 | case ALG_WEP: |
273 | if (key->conf.keylen == 5) | 276 | if (key->conf.keylen == 5) |
274 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | 277 | params.cipher = WLAN_CIPHER_SUITE_WEP40; |
275 | else | 278 | else |
276 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | 279 | params.cipher = WLAN_CIPHER_SUITE_WEP104; |
277 | break; | 280 | break; |
281 | case ALG_AES_CMAC: | ||
282 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
283 | seq[0] = key->u.aes_cmac.tx_pn[5]; | ||
284 | seq[1] = key->u.aes_cmac.tx_pn[4]; | ||
285 | seq[2] = key->u.aes_cmac.tx_pn[3]; | ||
286 | seq[3] = key->u.aes_cmac.tx_pn[2]; | ||
287 | seq[4] = key->u.aes_cmac.tx_pn[1]; | ||
288 | seq[5] = key->u.aes_cmac.tx_pn[0]; | ||
289 | params.seq = seq; | ||
290 | params.seq_len = 6; | ||
291 | break; | ||
278 | } | 292 | } |
279 | 293 | ||
280 | params.key = key->conf.key; | 294 | params.key = key->conf.key; |
281 | params.key_len = key->conf.keylen; | 295 | params.key_len = key->conf.keylen; |
282 | 296 | ||
283 | callback(cookie, ¶ms); | 297 | callback(cookie, ¶ms); |
284 | err = 0; | 298 | err = 0; |
285 | 299 | ||
286 | out: | 300 | out: |
287 | rcu_read_unlock(); | 301 | rcu_read_unlock(); |
288 | return err; | 302 | return err; |
289 | } | 303 | } |
290 | 304 | ||
291 | static int ieee80211_config_default_key(struct wiphy *wiphy, | 305 | static int ieee80211_config_default_key(struct wiphy *wiphy, |
292 | struct net_device *dev, | 306 | struct net_device *dev, |
293 | u8 key_idx) | 307 | u8 key_idx) |
294 | { | 308 | { |
295 | struct ieee80211_sub_if_data *sdata; | 309 | struct ieee80211_sub_if_data *sdata; |
296 | 310 | ||
297 | rcu_read_lock(); | 311 | rcu_read_lock(); |
298 | 312 | ||
299 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 313 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
300 | ieee80211_set_default_key(sdata, key_idx); | 314 | ieee80211_set_default_key(sdata, key_idx); |
301 | 315 | ||
302 | rcu_read_unlock(); | 316 | rcu_read_unlock(); |
303 | 317 | ||
304 | return 0; | 318 | return 0; |
305 | } | 319 | } |
306 | 320 | ||
321 | static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, | ||
322 | struct net_device *dev, | ||
323 | u8 key_idx) | ||
324 | { | ||
325 | struct ieee80211_sub_if_data *sdata; | ||
326 | |||
327 | rcu_read_lock(); | ||
328 | |||
329 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
330 | ieee80211_set_default_mgmt_key(sdata, key_idx); | ||
331 | |||
332 | rcu_read_unlock(); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
307 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 337 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
308 | { | 338 | { |
309 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 339 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
310 | 340 | ||
311 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 341 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
312 | STATION_INFO_RX_BYTES | | 342 | STATION_INFO_RX_BYTES | |
313 | STATION_INFO_TX_BYTES | | 343 | STATION_INFO_TX_BYTES | |
314 | STATION_INFO_TX_BITRATE; | 344 | STATION_INFO_TX_BITRATE; |
315 | 345 | ||
316 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 346 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
317 | sinfo->rx_bytes = sta->rx_bytes; | 347 | sinfo->rx_bytes = sta->rx_bytes; |
318 | sinfo->tx_bytes = sta->tx_bytes; | 348 | sinfo->tx_bytes = sta->tx_bytes; |
319 | 349 | ||
320 | if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { | 350 | if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { |
321 | sinfo->filled |= STATION_INFO_SIGNAL; | 351 | sinfo->filled |= STATION_INFO_SIGNAL; |
322 | sinfo->signal = (s8)sta->last_signal; | 352 | sinfo->signal = (s8)sta->last_signal; |
323 | } | 353 | } |
324 | 354 | ||
325 | sinfo->txrate.flags = 0; | 355 | sinfo->txrate.flags = 0; |
326 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) | 356 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) |
327 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | 357 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; |
328 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 358 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH) |
329 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 359 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
330 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI) | 360 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI) |
331 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | 361 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
332 | 362 | ||
333 | if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) { | 363 | if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) { |
334 | struct ieee80211_supported_band *sband; | 364 | struct ieee80211_supported_band *sband; |
335 | sband = sta->local->hw.wiphy->bands[ | 365 | sband = sta->local->hw.wiphy->bands[ |
336 | sta->local->hw.conf.channel->band]; | 366 | sta->local->hw.conf.channel->band]; |
337 | sinfo->txrate.legacy = | 367 | sinfo->txrate.legacy = |
338 | sband->bitrates[sta->last_tx_rate.idx].bitrate; | 368 | sband->bitrates[sta->last_tx_rate.idx].bitrate; |
339 | } else | 369 | } else |
340 | sinfo->txrate.mcs = sta->last_tx_rate.idx; | 370 | sinfo->txrate.mcs = sta->last_tx_rate.idx; |
341 | 371 | ||
342 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 372 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
343 | #ifdef CONFIG_MAC80211_MESH | 373 | #ifdef CONFIG_MAC80211_MESH |
344 | sinfo->filled |= STATION_INFO_LLID | | 374 | sinfo->filled |= STATION_INFO_LLID | |
345 | STATION_INFO_PLID | | 375 | STATION_INFO_PLID | |
346 | STATION_INFO_PLINK_STATE; | 376 | STATION_INFO_PLINK_STATE; |
347 | 377 | ||
348 | sinfo->llid = le16_to_cpu(sta->llid); | 378 | sinfo->llid = le16_to_cpu(sta->llid); |
349 | sinfo->plid = le16_to_cpu(sta->plid); | 379 | sinfo->plid = le16_to_cpu(sta->plid); |
350 | sinfo->plink_state = sta->plink_state; | 380 | sinfo->plink_state = sta->plink_state; |
351 | #endif | 381 | #endif |
352 | } | 382 | } |
353 | } | 383 | } |
354 | 384 | ||
355 | 385 | ||
356 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 386 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, |
357 | int idx, u8 *mac, struct station_info *sinfo) | 387 | int idx, u8 *mac, struct station_info *sinfo) |
358 | { | 388 | { |
359 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 389 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
360 | struct sta_info *sta; | 390 | struct sta_info *sta; |
361 | int ret = -ENOENT; | 391 | int ret = -ENOENT; |
362 | 392 | ||
363 | rcu_read_lock(); | 393 | rcu_read_lock(); |
364 | 394 | ||
365 | sta = sta_info_get_by_idx(local, idx, dev); | 395 | sta = sta_info_get_by_idx(local, idx, dev); |
366 | if (sta) { | 396 | if (sta) { |
367 | ret = 0; | 397 | ret = 0; |
368 | memcpy(mac, sta->sta.addr, ETH_ALEN); | 398 | memcpy(mac, sta->sta.addr, ETH_ALEN); |
369 | sta_set_sinfo(sta, sinfo); | 399 | sta_set_sinfo(sta, sinfo); |
370 | } | 400 | } |
371 | 401 | ||
372 | rcu_read_unlock(); | 402 | rcu_read_unlock(); |
373 | 403 | ||
374 | return ret; | 404 | return ret; |
375 | } | 405 | } |
376 | 406 | ||
377 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 407 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
378 | u8 *mac, struct station_info *sinfo) | 408 | u8 *mac, struct station_info *sinfo) |
379 | { | 409 | { |
380 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 410 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
381 | struct sta_info *sta; | 411 | struct sta_info *sta; |
382 | int ret = -ENOENT; | 412 | int ret = -ENOENT; |
383 | 413 | ||
384 | rcu_read_lock(); | 414 | rcu_read_lock(); |
385 | 415 | ||
386 | /* XXX: verify sta->dev == dev */ | 416 | /* XXX: verify sta->dev == dev */ |
387 | 417 | ||
388 | sta = sta_info_get(local, mac); | 418 | sta = sta_info_get(local, mac); |
389 | if (sta) { | 419 | if (sta) { |
390 | ret = 0; | 420 | ret = 0; |
391 | sta_set_sinfo(sta, sinfo); | 421 | sta_set_sinfo(sta, sinfo); |
392 | } | 422 | } |
393 | 423 | ||
394 | rcu_read_unlock(); | 424 | rcu_read_unlock(); |
395 | 425 | ||
396 | return ret; | 426 | return ret; |
397 | } | 427 | } |
398 | 428 | ||
399 | /* | 429 | /* |
400 | * This handles both adding a beacon and setting new beacon info | 430 | * This handles both adding a beacon and setting new beacon info |
401 | */ | 431 | */ |
402 | static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | 432 | static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, |
403 | struct beacon_parameters *params) | 433 | struct beacon_parameters *params) |
404 | { | 434 | { |
405 | struct beacon_data *new, *old; | 435 | struct beacon_data *new, *old; |
406 | int new_head_len, new_tail_len; | 436 | int new_head_len, new_tail_len; |
407 | int size; | 437 | int size; |
408 | int err = -EINVAL; | 438 | int err = -EINVAL; |
409 | 439 | ||
410 | old = sdata->u.ap.beacon; | 440 | old = sdata->u.ap.beacon; |
411 | 441 | ||
412 | /* head must not be zero-length */ | 442 | /* head must not be zero-length */ |
413 | if (params->head && !params->head_len) | 443 | if (params->head && !params->head_len) |
414 | return -EINVAL; | 444 | return -EINVAL; |
415 | 445 | ||
416 | /* | 446 | /* |
417 | * This is a kludge. beacon interval should really be part | 447 | * This is a kludge. beacon interval should really be part |
418 | * of the beacon information. | 448 | * of the beacon information. |
419 | */ | 449 | */ |
420 | if (params->interval) { | 450 | if (params->interval) { |
421 | sdata->local->hw.conf.beacon_int = params->interval; | 451 | sdata->local->hw.conf.beacon_int = params->interval; |
422 | err = ieee80211_hw_config(sdata->local, | 452 | err = ieee80211_hw_config(sdata->local, |
423 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL); | 453 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL); |
424 | if (err < 0) | 454 | if (err < 0) |
425 | return err; | 455 | return err; |
426 | /* | 456 | /* |
427 | * We updated some parameter so if below bails out | 457 | * We updated some parameter so if below bails out |
428 | * it's not an error. | 458 | * it's not an error. |
429 | */ | 459 | */ |
430 | err = 0; | 460 | err = 0; |
431 | } | 461 | } |
432 | 462 | ||
433 | /* Need to have a beacon head if we don't have one yet */ | 463 | /* Need to have a beacon head if we don't have one yet */ |
434 | if (!params->head && !old) | 464 | if (!params->head && !old) |
435 | return err; | 465 | return err; |
436 | 466 | ||
437 | /* sorry, no way to start beaconing without dtim period */ | 467 | /* sorry, no way to start beaconing without dtim period */ |
438 | if (!params->dtim_period && !old) | 468 | if (!params->dtim_period && !old) |
439 | return err; | 469 | return err; |
440 | 470 | ||
441 | /* new or old head? */ | 471 | /* new or old head? */ |
442 | if (params->head) | 472 | if (params->head) |
443 | new_head_len = params->head_len; | 473 | new_head_len = params->head_len; |
444 | else | 474 | else |
445 | new_head_len = old->head_len; | 475 | new_head_len = old->head_len; |
446 | 476 | ||
447 | /* new or old tail? */ | 477 | /* new or old tail? */ |
448 | if (params->tail || !old) | 478 | if (params->tail || !old) |
449 | /* params->tail_len will be zero for !params->tail */ | 479 | /* params->tail_len will be zero for !params->tail */ |
450 | new_tail_len = params->tail_len; | 480 | new_tail_len = params->tail_len; |
451 | else | 481 | else |
452 | new_tail_len = old->tail_len; | 482 | new_tail_len = old->tail_len; |
453 | 483 | ||
454 | size = sizeof(*new) + new_head_len + new_tail_len; | 484 | size = sizeof(*new) + new_head_len + new_tail_len; |
455 | 485 | ||
456 | new = kzalloc(size, GFP_KERNEL); | 486 | new = kzalloc(size, GFP_KERNEL); |
457 | if (!new) | 487 | if (!new) |
458 | return -ENOMEM; | 488 | return -ENOMEM; |
459 | 489 | ||
460 | /* start filling the new info now */ | 490 | /* start filling the new info now */ |
461 | 491 | ||
462 | /* new or old dtim period? */ | 492 | /* new or old dtim period? */ |
463 | if (params->dtim_period) | 493 | if (params->dtim_period) |
464 | new->dtim_period = params->dtim_period; | 494 | new->dtim_period = params->dtim_period; |
465 | else | 495 | else |
466 | new->dtim_period = old->dtim_period; | 496 | new->dtim_period = old->dtim_period; |
467 | 497 | ||
468 | /* | 498 | /* |
469 | * pointers go into the block we allocated, | 499 | * pointers go into the block we allocated, |
470 | * memory is | beacon_data | head | tail | | 500 | * memory is | beacon_data | head | tail | |
471 | */ | 501 | */ |
472 | new->head = ((u8 *) new) + sizeof(*new); | 502 | new->head = ((u8 *) new) + sizeof(*new); |
473 | new->tail = new->head + new_head_len; | 503 | new->tail = new->head + new_head_len; |
474 | new->head_len = new_head_len; | 504 | new->head_len = new_head_len; |
475 | new->tail_len = new_tail_len; | 505 | new->tail_len = new_tail_len; |
476 | 506 | ||
477 | /* copy in head */ | 507 | /* copy in head */ |
478 | if (params->head) | 508 | if (params->head) |
479 | memcpy(new->head, params->head, new_head_len); | 509 | memcpy(new->head, params->head, new_head_len); |
480 | else | 510 | else |
481 | memcpy(new->head, old->head, new_head_len); | 511 | memcpy(new->head, old->head, new_head_len); |
482 | 512 | ||
483 | /* copy in optional tail */ | 513 | /* copy in optional tail */ |
484 | if (params->tail) | 514 | if (params->tail) |
485 | memcpy(new->tail, params->tail, new_tail_len); | 515 | memcpy(new->tail, params->tail, new_tail_len); |
486 | else | 516 | else |
487 | if (old) | 517 | if (old) |
488 | memcpy(new->tail, old->tail, new_tail_len); | 518 | memcpy(new->tail, old->tail, new_tail_len); |
489 | 519 | ||
490 | rcu_assign_pointer(sdata->u.ap.beacon, new); | 520 | rcu_assign_pointer(sdata->u.ap.beacon, new); |
491 | 521 | ||
492 | synchronize_rcu(); | 522 | synchronize_rcu(); |
493 | 523 | ||
494 | kfree(old); | 524 | kfree(old); |
495 | 525 | ||
496 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 526 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
497 | } | 527 | } |
498 | 528 | ||
499 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 529 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
500 | struct beacon_parameters *params) | 530 | struct beacon_parameters *params) |
501 | { | 531 | { |
502 | struct ieee80211_sub_if_data *sdata; | 532 | struct ieee80211_sub_if_data *sdata; |
503 | struct beacon_data *old; | 533 | struct beacon_data *old; |
504 | 534 | ||
505 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 535 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
506 | 536 | ||
507 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 537 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
508 | return -EINVAL; | 538 | return -EINVAL; |
509 | 539 | ||
510 | old = sdata->u.ap.beacon; | 540 | old = sdata->u.ap.beacon; |
511 | 541 | ||
512 | if (old) | 542 | if (old) |
513 | return -EALREADY; | 543 | return -EALREADY; |
514 | 544 | ||
515 | return ieee80211_config_beacon(sdata, params); | 545 | return ieee80211_config_beacon(sdata, params); |
516 | } | 546 | } |
517 | 547 | ||
518 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | 548 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, |
519 | struct beacon_parameters *params) | 549 | struct beacon_parameters *params) |
520 | { | 550 | { |
521 | struct ieee80211_sub_if_data *sdata; | 551 | struct ieee80211_sub_if_data *sdata; |
522 | struct beacon_data *old; | 552 | struct beacon_data *old; |
523 | 553 | ||
524 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 554 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
525 | 555 | ||
526 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 556 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
527 | return -EINVAL; | 557 | return -EINVAL; |
528 | 558 | ||
529 | old = sdata->u.ap.beacon; | 559 | old = sdata->u.ap.beacon; |
530 | 560 | ||
531 | if (!old) | 561 | if (!old) |
532 | return -ENOENT; | 562 | return -ENOENT; |
533 | 563 | ||
534 | return ieee80211_config_beacon(sdata, params); | 564 | return ieee80211_config_beacon(sdata, params); |
535 | } | 565 | } |
536 | 566 | ||
537 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | 567 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) |
538 | { | 568 | { |
539 | struct ieee80211_sub_if_data *sdata; | 569 | struct ieee80211_sub_if_data *sdata; |
540 | struct beacon_data *old; | 570 | struct beacon_data *old; |
541 | 571 | ||
542 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 572 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
543 | 573 | ||
544 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 574 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
545 | return -EINVAL; | 575 | return -EINVAL; |
546 | 576 | ||
547 | old = sdata->u.ap.beacon; | 577 | old = sdata->u.ap.beacon; |
548 | 578 | ||
549 | if (!old) | 579 | if (!old) |
550 | return -ENOENT; | 580 | return -ENOENT; |
551 | 581 | ||
552 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 582 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); |
553 | synchronize_rcu(); | 583 | synchronize_rcu(); |
554 | kfree(old); | 584 | kfree(old); |
555 | 585 | ||
556 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 586 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
557 | } | 587 | } |
558 | 588 | ||
559 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ | 589 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ |
560 | struct iapp_layer2_update { | 590 | struct iapp_layer2_update { |
561 | u8 da[ETH_ALEN]; /* broadcast */ | 591 | u8 da[ETH_ALEN]; /* broadcast */ |
562 | u8 sa[ETH_ALEN]; /* STA addr */ | 592 | u8 sa[ETH_ALEN]; /* STA addr */ |
563 | __be16 len; /* 6 */ | 593 | __be16 len; /* 6 */ |
564 | u8 dsap; /* 0 */ | 594 | u8 dsap; /* 0 */ |
565 | u8 ssap; /* 0 */ | 595 | u8 ssap; /* 0 */ |
566 | u8 control; | 596 | u8 control; |
567 | u8 xid_info[3]; | 597 | u8 xid_info[3]; |
568 | } __attribute__ ((packed)); | 598 | } __attribute__ ((packed)); |
569 | 599 | ||
570 | static void ieee80211_send_layer2_update(struct sta_info *sta) | 600 | static void ieee80211_send_layer2_update(struct sta_info *sta) |
571 | { | 601 | { |
572 | struct iapp_layer2_update *msg; | 602 | struct iapp_layer2_update *msg; |
573 | struct sk_buff *skb; | 603 | struct sk_buff *skb; |
574 | 604 | ||
575 | /* Send Level 2 Update Frame to update forwarding tables in layer 2 | 605 | /* Send Level 2 Update Frame to update forwarding tables in layer 2 |
576 | * bridge devices */ | 606 | * bridge devices */ |
577 | 607 | ||
578 | skb = dev_alloc_skb(sizeof(*msg)); | 608 | skb = dev_alloc_skb(sizeof(*msg)); |
579 | if (!skb) | 609 | if (!skb) |
580 | return; | 610 | return; |
581 | msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg)); | 611 | msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg)); |
582 | 612 | ||
583 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) | 613 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) |
584 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ | 614 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ |
585 | 615 | ||
586 | memset(msg->da, 0xff, ETH_ALEN); | 616 | memset(msg->da, 0xff, ETH_ALEN); |
587 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); | 617 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); |
588 | msg->len = htons(6); | 618 | msg->len = htons(6); |
589 | msg->dsap = 0; | 619 | msg->dsap = 0; |
590 | msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ | 620 | msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ |
591 | msg->control = 0xaf; /* XID response lsb.1111F101. | 621 | msg->control = 0xaf; /* XID response lsb.1111F101. |
592 | * F=0 (no poll command; unsolicited frame) */ | 622 | * F=0 (no poll command; unsolicited frame) */ |
593 | msg->xid_info[0] = 0x81; /* XID format identifier */ | 623 | msg->xid_info[0] = 0x81; /* XID format identifier */ |
594 | msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ | 624 | msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ |
595 | msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ | 625 | msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */ |
596 | 626 | ||
597 | skb->dev = sta->sdata->dev; | 627 | skb->dev = sta->sdata->dev; |
598 | skb->protocol = eth_type_trans(skb, sta->sdata->dev); | 628 | skb->protocol = eth_type_trans(skb, sta->sdata->dev); |
599 | memset(skb->cb, 0, sizeof(skb->cb)); | 629 | memset(skb->cb, 0, sizeof(skb->cb)); |
600 | netif_rx(skb); | 630 | netif_rx(skb); |
601 | } | 631 | } |
602 | 632 | ||
603 | static void sta_apply_parameters(struct ieee80211_local *local, | 633 | static void sta_apply_parameters(struct ieee80211_local *local, |
604 | struct sta_info *sta, | 634 | struct sta_info *sta, |
605 | struct station_parameters *params) | 635 | struct station_parameters *params) |
606 | { | 636 | { |
607 | u32 rates; | 637 | u32 rates; |
608 | int i, j; | 638 | int i, j; |
609 | struct ieee80211_supported_band *sband; | 639 | struct ieee80211_supported_band *sband; |
610 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 640 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
611 | 641 | ||
612 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 642 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
613 | 643 | ||
614 | /* | 644 | /* |
615 | * FIXME: updating the flags is racy when this function is | 645 | * FIXME: updating the flags is racy when this function is |
616 | * called from ieee80211_change_station(), this will | 646 | * called from ieee80211_change_station(), this will |
617 | * be resolved in a future patch. | 647 | * be resolved in a future patch. |
618 | */ | 648 | */ |
619 | 649 | ||
620 | if (params->station_flags & STATION_FLAG_CHANGED) { | 650 | if (params->station_flags & STATION_FLAG_CHANGED) { |
621 | spin_lock_bh(&sta->lock); | 651 | spin_lock_bh(&sta->lock); |
622 | sta->flags &= ~WLAN_STA_AUTHORIZED; | 652 | sta->flags &= ~WLAN_STA_AUTHORIZED; |
623 | if (params->station_flags & STATION_FLAG_AUTHORIZED) | 653 | if (params->station_flags & STATION_FLAG_AUTHORIZED) |
624 | sta->flags |= WLAN_STA_AUTHORIZED; | 654 | sta->flags |= WLAN_STA_AUTHORIZED; |
625 | 655 | ||
626 | sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; | 656 | sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; |
627 | if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE) | 657 | if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE) |
628 | sta->flags |= WLAN_STA_SHORT_PREAMBLE; | 658 | sta->flags |= WLAN_STA_SHORT_PREAMBLE; |
629 | 659 | ||
630 | sta->flags &= ~WLAN_STA_WME; | 660 | sta->flags &= ~WLAN_STA_WME; |
631 | if (params->station_flags & STATION_FLAG_WME) | 661 | if (params->station_flags & STATION_FLAG_WME) |
632 | sta->flags |= WLAN_STA_WME; | 662 | sta->flags |= WLAN_STA_WME; |
633 | 663 | ||
634 | sta->flags &= ~WLAN_STA_MFP; | 664 | sta->flags &= ~WLAN_STA_MFP; |
635 | if (params->station_flags & STATION_FLAG_MFP) | 665 | if (params->station_flags & STATION_FLAG_MFP) |
636 | sta->flags |= WLAN_STA_MFP; | 666 | sta->flags |= WLAN_STA_MFP; |
637 | spin_unlock_bh(&sta->lock); | 667 | spin_unlock_bh(&sta->lock); |
638 | } | 668 | } |
639 | 669 | ||
640 | /* | 670 | /* |
641 | * FIXME: updating the following information is racy when this | 671 | * FIXME: updating the following information is racy when this |
642 | * function is called from ieee80211_change_station(). | 672 | * function is called from ieee80211_change_station(). |
643 | * However, all this information should be static so | 673 | * However, all this information should be static so |
644 | * maybe we should just reject attemps to change it. | 674 | * maybe we should just reject attemps to change it. |
645 | */ | 675 | */ |
646 | 676 | ||
647 | if (params->aid) { | 677 | if (params->aid) { |
648 | sta->sta.aid = params->aid; | 678 | sta->sta.aid = params->aid; |
649 | if (sta->sta.aid > IEEE80211_MAX_AID) | 679 | if (sta->sta.aid > IEEE80211_MAX_AID) |
650 | sta->sta.aid = 0; /* XXX: should this be an error? */ | 680 | sta->sta.aid = 0; /* XXX: should this be an error? */ |
651 | } | 681 | } |
652 | 682 | ||
653 | if (params->listen_interval >= 0) | 683 | if (params->listen_interval >= 0) |
654 | sta->listen_interval = params->listen_interval; | 684 | sta->listen_interval = params->listen_interval; |
655 | 685 | ||
656 | if (params->supported_rates) { | 686 | if (params->supported_rates) { |
657 | rates = 0; | 687 | rates = 0; |
658 | 688 | ||
659 | for (i = 0; i < params->supported_rates_len; i++) { | 689 | for (i = 0; i < params->supported_rates_len; i++) { |
660 | int rate = (params->supported_rates[i] & 0x7f) * 5; | 690 | int rate = (params->supported_rates[i] & 0x7f) * 5; |
661 | for (j = 0; j < sband->n_bitrates; j++) { | 691 | for (j = 0; j < sband->n_bitrates; j++) { |
662 | if (sband->bitrates[j].bitrate == rate) | 692 | if (sband->bitrates[j].bitrate == rate) |
663 | rates |= BIT(j); | 693 | rates |= BIT(j); |
664 | } | 694 | } |
665 | } | 695 | } |
666 | sta->sta.supp_rates[local->oper_channel->band] = rates; | 696 | sta->sta.supp_rates[local->oper_channel->band] = rates; |
667 | } | 697 | } |
668 | 698 | ||
669 | if (params->ht_capa) | 699 | if (params->ht_capa) |
670 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, | 700 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, |
671 | params->ht_capa, | 701 | params->ht_capa, |
672 | &sta->sta.ht_cap); | 702 | &sta->sta.ht_cap); |
673 | 703 | ||
674 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { | 704 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { |
675 | switch (params->plink_action) { | 705 | switch (params->plink_action) { |
676 | case PLINK_ACTION_OPEN: | 706 | case PLINK_ACTION_OPEN: |
677 | mesh_plink_open(sta); | 707 | mesh_plink_open(sta); |
678 | break; | 708 | break; |
679 | case PLINK_ACTION_BLOCK: | 709 | case PLINK_ACTION_BLOCK: |
680 | mesh_plink_block(sta); | 710 | mesh_plink_block(sta); |
681 | break; | 711 | break; |
682 | } | 712 | } |
683 | } | 713 | } |
684 | } | 714 | } |
685 | 715 | ||
686 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | 716 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, |
687 | u8 *mac, struct station_parameters *params) | 717 | u8 *mac, struct station_parameters *params) |
688 | { | 718 | { |
689 | struct ieee80211_local *local = wiphy_priv(wiphy); | 719 | struct ieee80211_local *local = wiphy_priv(wiphy); |
690 | struct sta_info *sta; | 720 | struct sta_info *sta; |
691 | struct ieee80211_sub_if_data *sdata; | 721 | struct ieee80211_sub_if_data *sdata; |
692 | int err; | 722 | int err; |
693 | int layer2_update; | 723 | int layer2_update; |
694 | 724 | ||
695 | /* Prevent a race with changing the rate control algorithm */ | 725 | /* Prevent a race with changing the rate control algorithm */ |
696 | if (!netif_running(dev)) | 726 | if (!netif_running(dev)) |
697 | return -ENETDOWN; | 727 | return -ENETDOWN; |
698 | 728 | ||
699 | if (params->vlan) { | 729 | if (params->vlan) { |
700 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 730 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
701 | 731 | ||
702 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 732 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
703 | sdata->vif.type != NL80211_IFTYPE_AP) | 733 | sdata->vif.type != NL80211_IFTYPE_AP) |
704 | return -EINVAL; | 734 | return -EINVAL; |
705 | } else | 735 | } else |
706 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 736 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
707 | 737 | ||
708 | if (compare_ether_addr(mac, dev->dev_addr) == 0) | 738 | if (compare_ether_addr(mac, dev->dev_addr) == 0) |
709 | return -EINVAL; | 739 | return -EINVAL; |
710 | 740 | ||
711 | if (is_multicast_ether_addr(mac)) | 741 | if (is_multicast_ether_addr(mac)) |
712 | return -EINVAL; | 742 | return -EINVAL; |
713 | 743 | ||
714 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); | 744 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); |
715 | if (!sta) | 745 | if (!sta) |
716 | return -ENOMEM; | 746 | return -ENOMEM; |
717 | 747 | ||
718 | sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; | 748 | sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; |
719 | 749 | ||
720 | sta_apply_parameters(local, sta, params); | 750 | sta_apply_parameters(local, sta, params); |
721 | 751 | ||
722 | rate_control_rate_init(sta); | 752 | rate_control_rate_init(sta); |
723 | 753 | ||
724 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 754 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
725 | sdata->vif.type == NL80211_IFTYPE_AP; | 755 | sdata->vif.type == NL80211_IFTYPE_AP; |
726 | 756 | ||
727 | rcu_read_lock(); | 757 | rcu_read_lock(); |
728 | 758 | ||
729 | err = sta_info_insert(sta); | 759 | err = sta_info_insert(sta); |
730 | if (err) { | 760 | if (err) { |
731 | /* STA has been freed */ | 761 | /* STA has been freed */ |
732 | if (err == -EEXIST && layer2_update) { | 762 | if (err == -EEXIST && layer2_update) { |
733 | /* Need to update layer 2 devices on reassociation */ | 763 | /* Need to update layer 2 devices on reassociation */ |
734 | sta = sta_info_get(local, mac); | 764 | sta = sta_info_get(local, mac); |
735 | if (sta) | 765 | if (sta) |
736 | ieee80211_send_layer2_update(sta); | 766 | ieee80211_send_layer2_update(sta); |
737 | } | 767 | } |
738 | rcu_read_unlock(); | 768 | rcu_read_unlock(); |
739 | return err; | 769 | return err; |
740 | } | 770 | } |
741 | 771 | ||
742 | if (layer2_update) | 772 | if (layer2_update) |
743 | ieee80211_send_layer2_update(sta); | 773 | ieee80211_send_layer2_update(sta); |
744 | 774 | ||
745 | rcu_read_unlock(); | 775 | rcu_read_unlock(); |
746 | 776 | ||
747 | return 0; | 777 | return 0; |
748 | } | 778 | } |
749 | 779 | ||
750 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 780 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
751 | u8 *mac) | 781 | u8 *mac) |
752 | { | 782 | { |
753 | struct ieee80211_local *local = wiphy_priv(wiphy); | 783 | struct ieee80211_local *local = wiphy_priv(wiphy); |
754 | struct ieee80211_sub_if_data *sdata; | 784 | struct ieee80211_sub_if_data *sdata; |
755 | struct sta_info *sta; | 785 | struct sta_info *sta; |
756 | 786 | ||
757 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 787 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
758 | 788 | ||
759 | if (mac) { | 789 | if (mac) { |
760 | rcu_read_lock(); | 790 | rcu_read_lock(); |
761 | 791 | ||
762 | /* XXX: get sta belonging to dev */ | 792 | /* XXX: get sta belonging to dev */ |
763 | sta = sta_info_get(local, mac); | 793 | sta = sta_info_get(local, mac); |
764 | if (!sta) { | 794 | if (!sta) { |
765 | rcu_read_unlock(); | 795 | rcu_read_unlock(); |
766 | return -ENOENT; | 796 | return -ENOENT; |
767 | } | 797 | } |
768 | 798 | ||
769 | sta_info_unlink(&sta); | 799 | sta_info_unlink(&sta); |
770 | rcu_read_unlock(); | 800 | rcu_read_unlock(); |
771 | 801 | ||
772 | sta_info_destroy(sta); | 802 | sta_info_destroy(sta); |
773 | } else | 803 | } else |
774 | sta_info_flush(local, sdata); | 804 | sta_info_flush(local, sdata); |
775 | 805 | ||
776 | return 0; | 806 | return 0; |
777 | } | 807 | } |
778 | 808 | ||
779 | static int ieee80211_change_station(struct wiphy *wiphy, | 809 | static int ieee80211_change_station(struct wiphy *wiphy, |
780 | struct net_device *dev, | 810 | struct net_device *dev, |
781 | u8 *mac, | 811 | u8 *mac, |
782 | struct station_parameters *params) | 812 | struct station_parameters *params) |
783 | { | 813 | { |
784 | struct ieee80211_local *local = wiphy_priv(wiphy); | 814 | struct ieee80211_local *local = wiphy_priv(wiphy); |
785 | struct sta_info *sta; | 815 | struct sta_info *sta; |
786 | struct ieee80211_sub_if_data *vlansdata; | 816 | struct ieee80211_sub_if_data *vlansdata; |
787 | 817 | ||
788 | rcu_read_lock(); | 818 | rcu_read_lock(); |
789 | 819 | ||
790 | /* XXX: get sta belonging to dev */ | 820 | /* XXX: get sta belonging to dev */ |
791 | sta = sta_info_get(local, mac); | 821 | sta = sta_info_get(local, mac); |
792 | if (!sta) { | 822 | if (!sta) { |
793 | rcu_read_unlock(); | 823 | rcu_read_unlock(); |
794 | return -ENOENT; | 824 | return -ENOENT; |
795 | } | 825 | } |
796 | 826 | ||
797 | if (params->vlan && params->vlan != sta->sdata->dev) { | 827 | if (params->vlan && params->vlan != sta->sdata->dev) { |
798 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 828 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
799 | 829 | ||
800 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 830 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
801 | vlansdata->vif.type != NL80211_IFTYPE_AP) { | 831 | vlansdata->vif.type != NL80211_IFTYPE_AP) { |
802 | rcu_read_unlock(); | 832 | rcu_read_unlock(); |
803 | return -EINVAL; | 833 | return -EINVAL; |
804 | } | 834 | } |
805 | 835 | ||
806 | sta->sdata = vlansdata; | 836 | sta->sdata = vlansdata; |
807 | ieee80211_send_layer2_update(sta); | 837 | ieee80211_send_layer2_update(sta); |
808 | } | 838 | } |
809 | 839 | ||
810 | sta_apply_parameters(local, sta, params); | 840 | sta_apply_parameters(local, sta, params); |
811 | 841 | ||
812 | rcu_read_unlock(); | 842 | rcu_read_unlock(); |
813 | 843 | ||
814 | return 0; | 844 | return 0; |
815 | } | 845 | } |
816 | 846 | ||
817 | #ifdef CONFIG_MAC80211_MESH | 847 | #ifdef CONFIG_MAC80211_MESH |
818 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | 848 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, |
819 | u8 *dst, u8 *next_hop) | 849 | u8 *dst, u8 *next_hop) |
820 | { | 850 | { |
821 | struct ieee80211_local *local = wiphy_priv(wiphy); | 851 | struct ieee80211_local *local = wiphy_priv(wiphy); |
822 | struct ieee80211_sub_if_data *sdata; | 852 | struct ieee80211_sub_if_data *sdata; |
823 | struct mesh_path *mpath; | 853 | struct mesh_path *mpath; |
824 | struct sta_info *sta; | 854 | struct sta_info *sta; |
825 | int err; | 855 | int err; |
826 | 856 | ||
827 | if (!netif_running(dev)) | 857 | if (!netif_running(dev)) |
828 | return -ENETDOWN; | 858 | return -ENETDOWN; |
829 | 859 | ||
830 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 860 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
831 | 861 | ||
832 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 862 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
833 | return -ENOTSUPP; | 863 | return -ENOTSUPP; |
834 | 864 | ||
835 | rcu_read_lock(); | 865 | rcu_read_lock(); |
836 | sta = sta_info_get(local, next_hop); | 866 | sta = sta_info_get(local, next_hop); |
837 | if (!sta) { | 867 | if (!sta) { |
838 | rcu_read_unlock(); | 868 | rcu_read_unlock(); |
839 | return -ENOENT; | 869 | return -ENOENT; |
840 | } | 870 | } |
841 | 871 | ||
842 | err = mesh_path_add(dst, sdata); | 872 | err = mesh_path_add(dst, sdata); |
843 | if (err) { | 873 | if (err) { |
844 | rcu_read_unlock(); | 874 | rcu_read_unlock(); |
845 | return err; | 875 | return err; |
846 | } | 876 | } |
847 | 877 | ||
848 | mpath = mesh_path_lookup(dst, sdata); | 878 | mpath = mesh_path_lookup(dst, sdata); |
849 | if (!mpath) { | 879 | if (!mpath) { |
850 | rcu_read_unlock(); | 880 | rcu_read_unlock(); |
851 | return -ENXIO; | 881 | return -ENXIO; |
852 | } | 882 | } |
853 | mesh_path_fix_nexthop(mpath, sta); | 883 | mesh_path_fix_nexthop(mpath, sta); |
854 | 884 | ||
855 | rcu_read_unlock(); | 885 | rcu_read_unlock(); |
856 | return 0; | 886 | return 0; |
857 | } | 887 | } |
858 | 888 | ||
859 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | 889 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, |
860 | u8 *dst) | 890 | u8 *dst) |
861 | { | 891 | { |
862 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 892 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
863 | 893 | ||
864 | if (dst) | 894 | if (dst) |
865 | return mesh_path_del(dst, sdata); | 895 | return mesh_path_del(dst, sdata); |
866 | 896 | ||
867 | mesh_path_flush(sdata); | 897 | mesh_path_flush(sdata); |
868 | return 0; | 898 | return 0; |
869 | } | 899 | } |
870 | 900 | ||
871 | static int ieee80211_change_mpath(struct wiphy *wiphy, | 901 | static int ieee80211_change_mpath(struct wiphy *wiphy, |
872 | struct net_device *dev, | 902 | struct net_device *dev, |
873 | u8 *dst, u8 *next_hop) | 903 | u8 *dst, u8 *next_hop) |
874 | { | 904 | { |
875 | struct ieee80211_local *local = wiphy_priv(wiphy); | 905 | struct ieee80211_local *local = wiphy_priv(wiphy); |
876 | struct ieee80211_sub_if_data *sdata; | 906 | struct ieee80211_sub_if_data *sdata; |
877 | struct mesh_path *mpath; | 907 | struct mesh_path *mpath; |
878 | struct sta_info *sta; | 908 | struct sta_info *sta; |
879 | 909 | ||
880 | if (!netif_running(dev)) | 910 | if (!netif_running(dev)) |
881 | return -ENETDOWN; | 911 | return -ENETDOWN; |
882 | 912 | ||
883 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 913 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
884 | 914 | ||
885 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 915 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
886 | return -ENOTSUPP; | 916 | return -ENOTSUPP; |
887 | 917 | ||
888 | rcu_read_lock(); | 918 | rcu_read_lock(); |
889 | 919 | ||
890 | sta = sta_info_get(local, next_hop); | 920 | sta = sta_info_get(local, next_hop); |
891 | if (!sta) { | 921 | if (!sta) { |
892 | rcu_read_unlock(); | 922 | rcu_read_unlock(); |
893 | return -ENOENT; | 923 | return -ENOENT; |
894 | } | 924 | } |
895 | 925 | ||
896 | mpath = mesh_path_lookup(dst, sdata); | 926 | mpath = mesh_path_lookup(dst, sdata); |
897 | if (!mpath) { | 927 | if (!mpath) { |
898 | rcu_read_unlock(); | 928 | rcu_read_unlock(); |
899 | return -ENOENT; | 929 | return -ENOENT; |
900 | } | 930 | } |
901 | 931 | ||
902 | mesh_path_fix_nexthop(mpath, sta); | 932 | mesh_path_fix_nexthop(mpath, sta); |
903 | 933 | ||
904 | rcu_read_unlock(); | 934 | rcu_read_unlock(); |
905 | return 0; | 935 | return 0; |
906 | } | 936 | } |
907 | 937 | ||
908 | static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | 938 | static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, |
909 | struct mpath_info *pinfo) | 939 | struct mpath_info *pinfo) |
910 | { | 940 | { |
911 | if (mpath->next_hop) | 941 | if (mpath->next_hop) |
912 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); | 942 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); |
913 | else | 943 | else |
914 | memset(next_hop, 0, ETH_ALEN); | 944 | memset(next_hop, 0, ETH_ALEN); |
915 | 945 | ||
916 | pinfo->filled = MPATH_INFO_FRAME_QLEN | | 946 | pinfo->filled = MPATH_INFO_FRAME_QLEN | |
917 | MPATH_INFO_DSN | | 947 | MPATH_INFO_DSN | |
918 | MPATH_INFO_METRIC | | 948 | MPATH_INFO_METRIC | |
919 | MPATH_INFO_EXPTIME | | 949 | MPATH_INFO_EXPTIME | |
920 | MPATH_INFO_DISCOVERY_TIMEOUT | | 950 | MPATH_INFO_DISCOVERY_TIMEOUT | |
921 | MPATH_INFO_DISCOVERY_RETRIES | | 951 | MPATH_INFO_DISCOVERY_RETRIES | |
922 | MPATH_INFO_FLAGS; | 952 | MPATH_INFO_FLAGS; |
923 | 953 | ||
924 | pinfo->frame_qlen = mpath->frame_queue.qlen; | 954 | pinfo->frame_qlen = mpath->frame_queue.qlen; |
925 | pinfo->dsn = mpath->dsn; | 955 | pinfo->dsn = mpath->dsn; |
926 | pinfo->metric = mpath->metric; | 956 | pinfo->metric = mpath->metric; |
927 | if (time_before(jiffies, mpath->exp_time)) | 957 | if (time_before(jiffies, mpath->exp_time)) |
928 | pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies); | 958 | pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies); |
929 | pinfo->discovery_timeout = | 959 | pinfo->discovery_timeout = |
930 | jiffies_to_msecs(mpath->discovery_timeout); | 960 | jiffies_to_msecs(mpath->discovery_timeout); |
931 | pinfo->discovery_retries = mpath->discovery_retries; | 961 | pinfo->discovery_retries = mpath->discovery_retries; |
932 | pinfo->flags = 0; | 962 | pinfo->flags = 0; |
933 | if (mpath->flags & MESH_PATH_ACTIVE) | 963 | if (mpath->flags & MESH_PATH_ACTIVE) |
934 | pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; | 964 | pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; |
935 | if (mpath->flags & MESH_PATH_RESOLVING) | 965 | if (mpath->flags & MESH_PATH_RESOLVING) |
936 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; | 966 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; |
937 | if (mpath->flags & MESH_PATH_DSN_VALID) | 967 | if (mpath->flags & MESH_PATH_DSN_VALID) |
938 | pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID; | 968 | pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID; |
939 | if (mpath->flags & MESH_PATH_FIXED) | 969 | if (mpath->flags & MESH_PATH_FIXED) |
940 | pinfo->flags |= NL80211_MPATH_FLAG_FIXED; | 970 | pinfo->flags |= NL80211_MPATH_FLAG_FIXED; |
941 | if (mpath->flags & MESH_PATH_RESOLVING) | 971 | if (mpath->flags & MESH_PATH_RESOLVING) |
942 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; | 972 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; |
943 | 973 | ||
944 | pinfo->flags = mpath->flags; | 974 | pinfo->flags = mpath->flags; |
945 | } | 975 | } |
946 | 976 | ||
947 | static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | 977 | static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, |
948 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) | 978 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) |
949 | 979 | ||
950 | { | 980 | { |
951 | struct ieee80211_sub_if_data *sdata; | 981 | struct ieee80211_sub_if_data *sdata; |
952 | struct mesh_path *mpath; | 982 | struct mesh_path *mpath; |
953 | 983 | ||
954 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 984 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
955 | 985 | ||
956 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 986 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
957 | return -ENOTSUPP; | 987 | return -ENOTSUPP; |
958 | 988 | ||
959 | rcu_read_lock(); | 989 | rcu_read_lock(); |
960 | mpath = mesh_path_lookup(dst, sdata); | 990 | mpath = mesh_path_lookup(dst, sdata); |
961 | if (!mpath) { | 991 | if (!mpath) { |
962 | rcu_read_unlock(); | 992 | rcu_read_unlock(); |
963 | return -ENOENT; | 993 | return -ENOENT; |
964 | } | 994 | } |
965 | memcpy(dst, mpath->dst, ETH_ALEN); | 995 | memcpy(dst, mpath->dst, ETH_ALEN); |
966 | mpath_set_pinfo(mpath, next_hop, pinfo); | 996 | mpath_set_pinfo(mpath, next_hop, pinfo); |
967 | rcu_read_unlock(); | 997 | rcu_read_unlock(); |
968 | return 0; | 998 | return 0; |
969 | } | 999 | } |
970 | 1000 | ||
971 | static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | 1001 | static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, |
972 | int idx, u8 *dst, u8 *next_hop, | 1002 | int idx, u8 *dst, u8 *next_hop, |
973 | struct mpath_info *pinfo) | 1003 | struct mpath_info *pinfo) |
974 | { | 1004 | { |
975 | struct ieee80211_sub_if_data *sdata; | 1005 | struct ieee80211_sub_if_data *sdata; |
976 | struct mesh_path *mpath; | 1006 | struct mesh_path *mpath; |
977 | 1007 | ||
978 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1008 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
979 | 1009 | ||
980 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 1010 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
981 | return -ENOTSUPP; | 1011 | return -ENOTSUPP; |
982 | 1012 | ||
983 | rcu_read_lock(); | 1013 | rcu_read_lock(); |
984 | mpath = mesh_path_lookup_by_idx(idx, sdata); | 1014 | mpath = mesh_path_lookup_by_idx(idx, sdata); |
985 | if (!mpath) { | 1015 | if (!mpath) { |
986 | rcu_read_unlock(); | 1016 | rcu_read_unlock(); |
987 | return -ENOENT; | 1017 | return -ENOENT; |
988 | } | 1018 | } |
989 | memcpy(dst, mpath->dst, ETH_ALEN); | 1019 | memcpy(dst, mpath->dst, ETH_ALEN); |
990 | mpath_set_pinfo(mpath, next_hop, pinfo); | 1020 | mpath_set_pinfo(mpath, next_hop, pinfo); |
991 | rcu_read_unlock(); | 1021 | rcu_read_unlock(); |
992 | return 0; | 1022 | return 0; |
993 | } | 1023 | } |
994 | 1024 | ||
995 | static int ieee80211_get_mesh_params(struct wiphy *wiphy, | 1025 | static int ieee80211_get_mesh_params(struct wiphy *wiphy, |
996 | struct net_device *dev, | 1026 | struct net_device *dev, |
997 | struct mesh_config *conf) | 1027 | struct mesh_config *conf) |
998 | { | 1028 | { |
999 | struct ieee80211_sub_if_data *sdata; | 1029 | struct ieee80211_sub_if_data *sdata; |
1000 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1030 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1001 | 1031 | ||
1002 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 1032 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
1003 | return -ENOTSUPP; | 1033 | return -ENOTSUPP; |
1004 | memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config)); | 1034 | memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config)); |
1005 | return 0; | 1035 | return 0; |
1006 | } | 1036 | } |
1007 | 1037 | ||
1008 | static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) | 1038 | static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) |
1009 | { | 1039 | { |
1010 | return (mask >> (parm-1)) & 0x1; | 1040 | return (mask >> (parm-1)) & 0x1; |
1011 | } | 1041 | } |
1012 | 1042 | ||
1013 | static int ieee80211_set_mesh_params(struct wiphy *wiphy, | 1043 | static int ieee80211_set_mesh_params(struct wiphy *wiphy, |
1014 | struct net_device *dev, | 1044 | struct net_device *dev, |
1015 | const struct mesh_config *nconf, u32 mask) | 1045 | const struct mesh_config *nconf, u32 mask) |
1016 | { | 1046 | { |
1017 | struct mesh_config *conf; | 1047 | struct mesh_config *conf; |
1018 | struct ieee80211_sub_if_data *sdata; | 1048 | struct ieee80211_sub_if_data *sdata; |
1019 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1049 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1020 | 1050 | ||
1021 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 1051 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
1022 | return -ENOTSUPP; | 1052 | return -ENOTSUPP; |
1023 | 1053 | ||
1024 | /* Set the config options which we are interested in setting */ | 1054 | /* Set the config options which we are interested in setting */ |
1025 | conf = &(sdata->u.mesh.mshcfg); | 1055 | conf = &(sdata->u.mesh.mshcfg); |
1026 | if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask)) | 1056 | if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask)) |
1027 | conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout; | 1057 | conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout; |
1028 | if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask)) | 1058 | if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask)) |
1029 | conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout; | 1059 | conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout; |
1030 | if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask)) | 1060 | if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask)) |
1031 | conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout; | 1061 | conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout; |
1032 | if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask)) | 1062 | if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask)) |
1033 | conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks; | 1063 | conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks; |
1034 | if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask)) | 1064 | if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask)) |
1035 | conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; | 1065 | conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries; |
1036 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) | 1066 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) |
1037 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | 1067 | conf->dot11MeshTTL = nconf->dot11MeshTTL; |
1038 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1068 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) |
1039 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1069 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1040 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) | 1070 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) |
1041 | conf->dot11MeshHWMPmaxPREQretries = | 1071 | conf->dot11MeshHWMPmaxPREQretries = |
1042 | nconf->dot11MeshHWMPmaxPREQretries; | 1072 | nconf->dot11MeshHWMPmaxPREQretries; |
1043 | if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask)) | 1073 | if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask)) |
1044 | conf->path_refresh_time = nconf->path_refresh_time; | 1074 | conf->path_refresh_time = nconf->path_refresh_time; |
1045 | if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask)) | 1075 | if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask)) |
1046 | conf->min_discovery_timeout = nconf->min_discovery_timeout; | 1076 | conf->min_discovery_timeout = nconf->min_discovery_timeout; |
1047 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask)) | 1077 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask)) |
1048 | conf->dot11MeshHWMPactivePathTimeout = | 1078 | conf->dot11MeshHWMPactivePathTimeout = |
1049 | nconf->dot11MeshHWMPactivePathTimeout; | 1079 | nconf->dot11MeshHWMPactivePathTimeout; |
1050 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask)) | 1080 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask)) |
1051 | conf->dot11MeshHWMPpreqMinInterval = | 1081 | conf->dot11MeshHWMPpreqMinInterval = |
1052 | nconf->dot11MeshHWMPpreqMinInterval; | 1082 | nconf->dot11MeshHWMPpreqMinInterval; |
1053 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | 1083 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
1054 | mask)) | 1084 | mask)) |
1055 | conf->dot11MeshHWMPnetDiameterTraversalTime = | 1085 | conf->dot11MeshHWMPnetDiameterTraversalTime = |
1056 | nconf->dot11MeshHWMPnetDiameterTraversalTime; | 1086 | nconf->dot11MeshHWMPnetDiameterTraversalTime; |
1057 | return 0; | 1087 | return 0; |
1058 | } | 1088 | } |
1059 | 1089 | ||
1060 | #endif | 1090 | #endif |
1061 | 1091 | ||
1062 | static int ieee80211_change_bss(struct wiphy *wiphy, | 1092 | static int ieee80211_change_bss(struct wiphy *wiphy, |
1063 | struct net_device *dev, | 1093 | struct net_device *dev, |
1064 | struct bss_parameters *params) | 1094 | struct bss_parameters *params) |
1065 | { | 1095 | { |
1066 | struct ieee80211_sub_if_data *sdata; | 1096 | struct ieee80211_sub_if_data *sdata; |
1067 | u32 changed = 0; | 1097 | u32 changed = 0; |
1068 | 1098 | ||
1069 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1099 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1070 | 1100 | ||
1071 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 1101 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
1072 | return -EINVAL; | 1102 | return -EINVAL; |
1073 | 1103 | ||
1074 | if (params->use_cts_prot >= 0) { | 1104 | if (params->use_cts_prot >= 0) { |
1075 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; | 1105 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; |
1076 | changed |= BSS_CHANGED_ERP_CTS_PROT; | 1106 | changed |= BSS_CHANGED_ERP_CTS_PROT; |
1077 | } | 1107 | } |
1078 | if (params->use_short_preamble >= 0) { | 1108 | if (params->use_short_preamble >= 0) { |
1079 | sdata->vif.bss_conf.use_short_preamble = | 1109 | sdata->vif.bss_conf.use_short_preamble = |
1080 | params->use_short_preamble; | 1110 | params->use_short_preamble; |
1081 | changed |= BSS_CHANGED_ERP_PREAMBLE; | 1111 | changed |= BSS_CHANGED_ERP_PREAMBLE; |
1082 | } | 1112 | } |
1083 | if (params->use_short_slot_time >= 0) { | 1113 | if (params->use_short_slot_time >= 0) { |
1084 | sdata->vif.bss_conf.use_short_slot = | 1114 | sdata->vif.bss_conf.use_short_slot = |
1085 | params->use_short_slot_time; | 1115 | params->use_short_slot_time; |
1086 | changed |= BSS_CHANGED_ERP_SLOT; | 1116 | changed |= BSS_CHANGED_ERP_SLOT; |
1087 | } | 1117 | } |
1088 | 1118 | ||
1089 | if (params->basic_rates) { | 1119 | if (params->basic_rates) { |
1090 | int i, j; | 1120 | int i, j; |
1091 | u32 rates = 0; | 1121 | u32 rates = 0; |
1092 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1122 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1093 | struct ieee80211_supported_band *sband = | 1123 | struct ieee80211_supported_band *sband = |
1094 | wiphy->bands[local->oper_channel->band]; | 1124 | wiphy->bands[local->oper_channel->band]; |
1095 | 1125 | ||
1096 | for (i = 0; i < params->basic_rates_len; i++) { | 1126 | for (i = 0; i < params->basic_rates_len; i++) { |
1097 | int rate = (params->basic_rates[i] & 0x7f) * 5; | 1127 | int rate = (params->basic_rates[i] & 0x7f) * 5; |
1098 | for (j = 0; j < sband->n_bitrates; j++) { | 1128 | for (j = 0; j < sband->n_bitrates; j++) { |
1099 | if (sband->bitrates[j].bitrate == rate) | 1129 | if (sband->bitrates[j].bitrate == rate) |
1100 | rates |= BIT(j); | 1130 | rates |= BIT(j); |
1101 | } | 1131 | } |
1102 | } | 1132 | } |
1103 | sdata->vif.bss_conf.basic_rates = rates; | 1133 | sdata->vif.bss_conf.basic_rates = rates; |
1104 | changed |= BSS_CHANGED_BASIC_RATES; | 1134 | changed |= BSS_CHANGED_BASIC_RATES; |
1105 | } | 1135 | } |
1106 | 1136 | ||
1107 | ieee80211_bss_info_change_notify(sdata, changed); | 1137 | ieee80211_bss_info_change_notify(sdata, changed); |
1108 | 1138 | ||
1109 | return 0; | 1139 | return 0; |
1110 | } | 1140 | } |
1111 | 1141 | ||
1112 | static int ieee80211_set_txq_params(struct wiphy *wiphy, | 1142 | static int ieee80211_set_txq_params(struct wiphy *wiphy, |
1113 | struct ieee80211_txq_params *params) | 1143 | struct ieee80211_txq_params *params) |
1114 | { | 1144 | { |
1115 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1145 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1116 | struct ieee80211_tx_queue_params p; | 1146 | struct ieee80211_tx_queue_params p; |
1117 | 1147 | ||
1118 | if (!local->ops->conf_tx) | 1148 | if (!local->ops->conf_tx) |
1119 | return -EOPNOTSUPP; | 1149 | return -EOPNOTSUPP; |
1120 | 1150 | ||
1121 | memset(&p, 0, sizeof(p)); | 1151 | memset(&p, 0, sizeof(p)); |
1122 | p.aifs = params->aifs; | 1152 | p.aifs = params->aifs; |
1123 | p.cw_max = params->cwmax; | 1153 | p.cw_max = params->cwmax; |
1124 | p.cw_min = params->cwmin; | 1154 | p.cw_min = params->cwmin; |
1125 | p.txop = params->txop; | 1155 | p.txop = params->txop; |
1126 | if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) { | 1156 | if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) { |
1127 | printk(KERN_DEBUG "%s: failed to set TX queue " | 1157 | printk(KERN_DEBUG "%s: failed to set TX queue " |
1128 | "parameters for queue %d\n", local->mdev->name, | 1158 | "parameters for queue %d\n", local->mdev->name, |
1129 | params->queue); | 1159 | params->queue); |
1130 | return -EINVAL; | 1160 | return -EINVAL; |
1131 | } | 1161 | } |
1132 | 1162 | ||
1133 | return 0; | 1163 | return 0; |
1134 | } | 1164 | } |
1135 | 1165 | ||
1136 | static int ieee80211_set_channel(struct wiphy *wiphy, | 1166 | static int ieee80211_set_channel(struct wiphy *wiphy, |
1137 | struct ieee80211_channel *chan, | 1167 | struct ieee80211_channel *chan, |
1138 | enum nl80211_channel_type channel_type) | 1168 | enum nl80211_channel_type channel_type) |
1139 | { | 1169 | { |
1140 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1170 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1141 | 1171 | ||
1142 | local->oper_channel = chan; | 1172 | local->oper_channel = chan; |
1143 | local->oper_channel_type = channel_type; | 1173 | local->oper_channel_type = channel_type; |
1144 | 1174 | ||
1145 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1175 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1146 | } | 1176 | } |
1147 | 1177 | ||
1148 | struct cfg80211_ops mac80211_config_ops = { | 1178 | struct cfg80211_ops mac80211_config_ops = { |
1149 | .add_virtual_intf = ieee80211_add_iface, | 1179 | .add_virtual_intf = ieee80211_add_iface, |
1150 | .del_virtual_intf = ieee80211_del_iface, | 1180 | .del_virtual_intf = ieee80211_del_iface, |
1151 | .change_virtual_intf = ieee80211_change_iface, | 1181 | .change_virtual_intf = ieee80211_change_iface, |
1152 | .add_key = ieee80211_add_key, | 1182 | .add_key = ieee80211_add_key, |
1153 | .del_key = ieee80211_del_key, | 1183 | .del_key = ieee80211_del_key, |
1154 | .get_key = ieee80211_get_key, | 1184 | .get_key = ieee80211_get_key, |
1155 | .set_default_key = ieee80211_config_default_key, | 1185 | .set_default_key = ieee80211_config_default_key, |
1186 | .set_default_mgmt_key = ieee80211_config_default_mgmt_key, | ||
1156 | .add_beacon = ieee80211_add_beacon, | 1187 | .add_beacon = ieee80211_add_beacon, |
1157 | .set_beacon = ieee80211_set_beacon, | 1188 | .set_beacon = ieee80211_set_beacon, |
1158 | .del_beacon = ieee80211_del_beacon, | 1189 | .del_beacon = ieee80211_del_beacon, |
1159 | .add_station = ieee80211_add_station, | 1190 | .add_station = ieee80211_add_station, |
1160 | .del_station = ieee80211_del_station, | 1191 | .del_station = ieee80211_del_station, |
1161 | .change_station = ieee80211_change_station, | 1192 | .change_station = ieee80211_change_station, |
1162 | .get_station = ieee80211_get_station, | 1193 | .get_station = ieee80211_get_station, |
1163 | .dump_station = ieee80211_dump_station, | 1194 | .dump_station = ieee80211_dump_station, |
1164 | #ifdef CONFIG_MAC80211_MESH | 1195 | #ifdef CONFIG_MAC80211_MESH |
1165 | .add_mpath = ieee80211_add_mpath, | 1196 | .add_mpath = ieee80211_add_mpath, |
1166 | .del_mpath = ieee80211_del_mpath, | 1197 | .del_mpath = ieee80211_del_mpath, |
1167 | .change_mpath = ieee80211_change_mpath, | 1198 | .change_mpath = ieee80211_change_mpath, |
1168 | .get_mpath = ieee80211_get_mpath, | 1199 | .get_mpath = ieee80211_get_mpath, |
1169 | .dump_mpath = ieee80211_dump_mpath, | 1200 | .dump_mpath = ieee80211_dump_mpath, |
1170 | .set_mesh_params = ieee80211_set_mesh_params, | 1201 | .set_mesh_params = ieee80211_set_mesh_params, |
1171 | .get_mesh_params = ieee80211_get_mesh_params, | 1202 | .get_mesh_params = ieee80211_get_mesh_params, |
1172 | #endif | 1203 | #endif |
1173 | .change_bss = ieee80211_change_bss, | 1204 | .change_bss = ieee80211_change_bss, |
1174 | .set_txq_params = ieee80211_set_txq_params, | 1205 | .set_txq_params = ieee80211_set_txq_params, |
1175 | .set_channel = ieee80211_set_channel, | 1206 | .set_channel = ieee80211_set_channel, |
1176 | }; | 1207 | }; |
1177 | 1208 |
net/mac80211/debugfs_key.c
1 | /* | 1 | /* |
2 | * Copyright 2003-2005 Devicescape Software, Inc. | 2 | * Copyright 2003-2005 Devicescape Software, Inc. |
3 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 3 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
4 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> |
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 <linux/kobject.h> | 11 | #include <linux/kobject.h> |
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | #include "key.h" | 13 | #include "key.h" |
14 | #include "debugfs.h" | 14 | #include "debugfs.h" |
15 | #include "debugfs_key.h" | 15 | #include "debugfs_key.h" |
16 | 16 | ||
17 | #define KEY_READ(name, prop, buflen, format_string) \ | 17 | #define KEY_READ(name, prop, buflen, format_string) \ |
18 | static ssize_t key_##name##_read(struct file *file, \ | 18 | static ssize_t key_##name##_read(struct file *file, \ |
19 | char __user *userbuf, \ | 19 | char __user *userbuf, \ |
20 | size_t count, loff_t *ppos) \ | 20 | size_t count, loff_t *ppos) \ |
21 | { \ | 21 | { \ |
22 | char buf[buflen]; \ | 22 | char buf[buflen]; \ |
23 | struct ieee80211_key *key = file->private_data; \ | 23 | struct ieee80211_key *key = file->private_data; \ |
24 | int res = scnprintf(buf, buflen, format_string, key->prop); \ | 24 | int res = scnprintf(buf, buflen, format_string, key->prop); \ |
25 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ | 25 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ |
26 | } | 26 | } |
27 | #define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n") | 27 | #define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n") |
28 | #define KEY_READ_X(name) KEY_READ(name, name, 20, "0x%x\n") | 28 | #define KEY_READ_X(name) KEY_READ(name, name, 20, "0x%x\n") |
29 | 29 | ||
30 | #define KEY_OPS(name) \ | 30 | #define KEY_OPS(name) \ |
31 | static const struct file_operations key_ ##name## _ops = { \ | 31 | static const struct file_operations key_ ##name## _ops = { \ |
32 | .read = key_##name##_read, \ | 32 | .read = key_##name##_read, \ |
33 | .open = mac80211_open_file_generic, \ | 33 | .open = mac80211_open_file_generic, \ |
34 | } | 34 | } |
35 | 35 | ||
36 | #define KEY_FILE(name, format) \ | 36 | #define KEY_FILE(name, format) \ |
37 | KEY_READ_##format(name) \ | 37 | KEY_READ_##format(name) \ |
38 | KEY_OPS(name) | 38 | KEY_OPS(name) |
39 | 39 | ||
40 | #define KEY_CONF_READ(name, buflen, format_string) \ | 40 | #define KEY_CONF_READ(name, buflen, format_string) \ |
41 | KEY_READ(conf_##name, conf.name, buflen, format_string) | 41 | KEY_READ(conf_##name, conf.name, buflen, format_string) |
42 | #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n") | 42 | #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n") |
43 | 43 | ||
44 | #define KEY_CONF_OPS(name) \ | 44 | #define KEY_CONF_OPS(name) \ |
45 | static const struct file_operations key_ ##name## _ops = { \ | 45 | static const struct file_operations key_ ##name## _ops = { \ |
46 | .read = key_conf_##name##_read, \ | 46 | .read = key_conf_##name##_read, \ |
47 | .open = mac80211_open_file_generic, \ | 47 | .open = mac80211_open_file_generic, \ |
48 | } | 48 | } |
49 | 49 | ||
50 | #define KEY_CONF_FILE(name, format) \ | 50 | #define KEY_CONF_FILE(name, format) \ |
51 | KEY_CONF_READ_##format(name) \ | 51 | KEY_CONF_READ_##format(name) \ |
52 | KEY_CONF_OPS(name) | 52 | KEY_CONF_OPS(name) |
53 | 53 | ||
54 | KEY_CONF_FILE(keylen, D); | 54 | KEY_CONF_FILE(keylen, D); |
55 | KEY_CONF_FILE(keyidx, D); | 55 | KEY_CONF_FILE(keyidx, D); |
56 | KEY_CONF_FILE(hw_key_idx, D); | 56 | KEY_CONF_FILE(hw_key_idx, D); |
57 | KEY_FILE(flags, X); | 57 | KEY_FILE(flags, X); |
58 | KEY_FILE(tx_rx_count, D); | 58 | KEY_FILE(tx_rx_count, D); |
59 | KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n"); | 59 | KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n"); |
60 | KEY_OPS(ifindex); | 60 | KEY_OPS(ifindex); |
61 | 61 | ||
62 | static ssize_t key_algorithm_read(struct file *file, | 62 | static ssize_t key_algorithm_read(struct file *file, |
63 | char __user *userbuf, | 63 | char __user *userbuf, |
64 | size_t count, loff_t *ppos) | 64 | size_t count, loff_t *ppos) |
65 | { | 65 | { |
66 | char *alg; | 66 | char *alg; |
67 | struct ieee80211_key *key = file->private_data; | 67 | struct ieee80211_key *key = file->private_data; |
68 | 68 | ||
69 | switch (key->conf.alg) { | 69 | switch (key->conf.alg) { |
70 | case ALG_WEP: | 70 | case ALG_WEP: |
71 | alg = "WEP\n"; | 71 | alg = "WEP\n"; |
72 | break; | 72 | break; |
73 | case ALG_TKIP: | 73 | case ALG_TKIP: |
74 | alg = "TKIP\n"; | 74 | alg = "TKIP\n"; |
75 | break; | 75 | break; |
76 | case ALG_CCMP: | 76 | case ALG_CCMP: |
77 | alg = "CCMP\n"; | 77 | alg = "CCMP\n"; |
78 | break; | 78 | break; |
79 | case ALG_AES_CMAC: | ||
80 | alg = "AES-128-CMAC\n"; | ||
81 | break; | ||
79 | default: | 82 | default: |
80 | return 0; | 83 | return 0; |
81 | } | 84 | } |
82 | return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg)); | 85 | return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg)); |
83 | } | 86 | } |
84 | KEY_OPS(algorithm); | 87 | KEY_OPS(algorithm); |
85 | 88 | ||
86 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | 89 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, |
87 | size_t count, loff_t *ppos) | 90 | size_t count, loff_t *ppos) |
88 | { | 91 | { |
89 | const u8 *tpn; | 92 | const u8 *tpn; |
90 | char buf[20]; | 93 | char buf[20]; |
91 | int len; | 94 | int len; |
92 | struct ieee80211_key *key = file->private_data; | 95 | struct ieee80211_key *key = file->private_data; |
93 | 96 | ||
94 | switch (key->conf.alg) { | 97 | switch (key->conf.alg) { |
95 | case ALG_WEP: | 98 | case ALG_WEP: |
96 | len = scnprintf(buf, sizeof(buf), "\n"); | 99 | len = scnprintf(buf, sizeof(buf), "\n"); |
97 | break; | 100 | break; |
98 | case ALG_TKIP: | 101 | case ALG_TKIP: |
99 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", | 102 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", |
100 | key->u.tkip.tx.iv32, | 103 | key->u.tkip.tx.iv32, |
101 | key->u.tkip.tx.iv16); | 104 | key->u.tkip.tx.iv16); |
102 | break; | 105 | break; |
103 | case ALG_CCMP: | 106 | case ALG_CCMP: |
104 | tpn = key->u.ccmp.tx_pn; | 107 | tpn = key->u.ccmp.tx_pn; |
105 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 108 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
106 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); | 109 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); |
107 | break; | 110 | break; |
111 | case ALG_AES_CMAC: | ||
112 | tpn = key->u.aes_cmac.tx_pn; | ||
113 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | ||
114 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], | ||
115 | tpn[5]); | ||
116 | break; | ||
108 | default: | 117 | default: |
109 | return 0; | 118 | return 0; |
110 | } | 119 | } |
111 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | 120 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); |
112 | } | 121 | } |
113 | KEY_OPS(tx_spec); | 122 | KEY_OPS(tx_spec); |
114 | 123 | ||
115 | static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | 124 | static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, |
116 | size_t count, loff_t *ppos) | 125 | size_t count, loff_t *ppos) |
117 | { | 126 | { |
118 | struct ieee80211_key *key = file->private_data; | 127 | struct ieee80211_key *key = file->private_data; |
119 | char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf; | 128 | char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf; |
120 | int i, len; | 129 | int i, len; |
121 | const u8 *rpn; | 130 | const u8 *rpn; |
122 | 131 | ||
123 | switch (key->conf.alg) { | 132 | switch (key->conf.alg) { |
124 | case ALG_WEP: | 133 | case ALG_WEP: |
125 | len = scnprintf(buf, sizeof(buf), "\n"); | 134 | len = scnprintf(buf, sizeof(buf), "\n"); |
126 | break; | 135 | break; |
127 | case ALG_TKIP: | 136 | case ALG_TKIP: |
128 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 137 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) |
129 | p += scnprintf(p, sizeof(buf)+buf-p, | 138 | p += scnprintf(p, sizeof(buf)+buf-p, |
130 | "%08x %04x\n", | 139 | "%08x %04x\n", |
131 | key->u.tkip.rx[i].iv32, | 140 | key->u.tkip.rx[i].iv32, |
132 | key->u.tkip.rx[i].iv16); | 141 | key->u.tkip.rx[i].iv16); |
133 | len = p - buf; | 142 | len = p - buf; |
134 | break; | 143 | break; |
135 | case ALG_CCMP: | 144 | case ALG_CCMP: |
136 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { | 145 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { |
137 | rpn = key->u.ccmp.rx_pn[i]; | 146 | rpn = key->u.ccmp.rx_pn[i]; |
138 | p += scnprintf(p, sizeof(buf)+buf-p, | 147 | p += scnprintf(p, sizeof(buf)+buf-p, |
139 | "%02x%02x%02x%02x%02x%02x\n", | 148 | "%02x%02x%02x%02x%02x%02x\n", |
140 | rpn[0], rpn[1], rpn[2], | 149 | rpn[0], rpn[1], rpn[2], |
141 | rpn[3], rpn[4], rpn[5]); | 150 | rpn[3], rpn[4], rpn[5]); |
142 | } | 151 | } |
143 | len = p - buf; | 152 | len = p - buf; |
144 | break; | 153 | break; |
154 | case ALG_AES_CMAC: | ||
155 | rpn = key->u.aes_cmac.rx_pn; | ||
156 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
157 | "%02x%02x%02x%02x%02x%02x\n", | ||
158 | rpn[0], rpn[1], rpn[2], | ||
159 | rpn[3], rpn[4], rpn[5]); | ||
160 | len = p - buf; | ||
161 | break; | ||
145 | default: | 162 | default: |
146 | return 0; | 163 | return 0; |
147 | } | 164 | } |
148 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | 165 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); |
149 | } | 166 | } |
150 | KEY_OPS(rx_spec); | 167 | KEY_OPS(rx_spec); |
151 | 168 | ||
152 | static ssize_t key_replays_read(struct file *file, char __user *userbuf, | 169 | static ssize_t key_replays_read(struct file *file, char __user *userbuf, |
153 | size_t count, loff_t *ppos) | 170 | size_t count, loff_t *ppos) |
154 | { | 171 | { |
155 | struct ieee80211_key *key = file->private_data; | 172 | struct ieee80211_key *key = file->private_data; |
156 | char buf[20]; | 173 | char buf[20]; |
157 | int len; | 174 | int len; |
158 | 175 | ||
159 | if (key->conf.alg != ALG_CCMP) | 176 | switch (key->conf.alg) { |
177 | case ALG_CCMP: | ||
178 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); | ||
179 | break; | ||
180 | case ALG_AES_CMAC: | ||
181 | len = scnprintf(buf, sizeof(buf), "%u\n", | ||
182 | key->u.aes_cmac.replays); | ||
183 | break; | ||
184 | default: | ||
160 | return 0; | 185 | return 0; |
161 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); | 186 | } |
162 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | 187 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); |
163 | } | 188 | } |
164 | KEY_OPS(replays); | 189 | KEY_OPS(replays); |
165 | 190 | ||
191 | static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, | ||
192 | size_t count, loff_t *ppos) | ||
193 | { | ||
194 | struct ieee80211_key *key = file->private_data; | ||
195 | char buf[20]; | ||
196 | int len; | ||
197 | |||
198 | switch (key->conf.alg) { | ||
199 | case ALG_AES_CMAC: | ||
200 | len = scnprintf(buf, sizeof(buf), "%u\n", | ||
201 | key->u.aes_cmac.icverrors); | ||
202 | break; | ||
203 | default: | ||
204 | return 0; | ||
205 | } | ||
206 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | ||
207 | } | ||
208 | KEY_OPS(icverrors); | ||
209 | |||
166 | static ssize_t key_key_read(struct file *file, char __user *userbuf, | 210 | static ssize_t key_key_read(struct file *file, char __user *userbuf, |
167 | size_t count, loff_t *ppos) | 211 | size_t count, loff_t *ppos) |
168 | { | 212 | { |
169 | struct ieee80211_key *key = file->private_data; | 213 | struct ieee80211_key *key = file->private_data; |
170 | int i, res, bufsize = 2 * key->conf.keylen + 2; | 214 | int i, res, bufsize = 2 * key->conf.keylen + 2; |
171 | char *buf = kmalloc(bufsize, GFP_KERNEL); | 215 | char *buf = kmalloc(bufsize, GFP_KERNEL); |
172 | char *p = buf; | 216 | char *p = buf; |
173 | 217 | ||
174 | for (i = 0; i < key->conf.keylen; i++) | 218 | for (i = 0; i < key->conf.keylen; i++) |
175 | p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); | 219 | p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); |
176 | p += scnprintf(p, bufsize+buf-p, "\n"); | 220 | p += scnprintf(p, bufsize+buf-p, "\n"); |
177 | res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | 221 | res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); |
178 | kfree(buf); | 222 | kfree(buf); |
179 | return res; | 223 | return res; |
180 | } | 224 | } |
181 | KEY_OPS(key); | 225 | KEY_OPS(key); |
182 | 226 | ||
183 | #define DEBUGFS_ADD(name) \ | 227 | #define DEBUGFS_ADD(name) \ |
184 | key->debugfs.name = debugfs_create_file(#name, 0400,\ | 228 | key->debugfs.name = debugfs_create_file(#name, 0400,\ |
185 | key->debugfs.dir, key, &key_##name##_ops); | 229 | key->debugfs.dir, key, &key_##name##_ops); |
186 | 230 | ||
187 | void ieee80211_debugfs_key_add(struct ieee80211_key *key) | 231 | void ieee80211_debugfs_key_add(struct ieee80211_key *key) |
188 | { | 232 | { |
189 | static int keycount; | 233 | static int keycount; |
190 | char buf[50]; | 234 | char buf[50]; |
191 | struct sta_info *sta; | 235 | struct sta_info *sta; |
192 | 236 | ||
193 | if (!key->local->debugfs.keys) | 237 | if (!key->local->debugfs.keys) |
194 | return; | 238 | return; |
195 | 239 | ||
196 | sprintf(buf, "%d", keycount); | 240 | sprintf(buf, "%d", keycount); |
197 | key->debugfs.cnt = keycount; | 241 | key->debugfs.cnt = keycount; |
198 | keycount++; | 242 | keycount++; |
199 | key->debugfs.dir = debugfs_create_dir(buf, | 243 | key->debugfs.dir = debugfs_create_dir(buf, |
200 | key->local->debugfs.keys); | 244 | key->local->debugfs.keys); |
201 | 245 | ||
202 | if (!key->debugfs.dir) | 246 | if (!key->debugfs.dir) |
203 | return; | 247 | return; |
204 | 248 | ||
205 | rcu_read_lock(); | 249 | rcu_read_lock(); |
206 | sta = rcu_dereference(key->sta); | 250 | sta = rcu_dereference(key->sta); |
207 | if (sta) | 251 | if (sta) |
208 | sprintf(buf, "../../stations/%pM", sta->sta.addr); | 252 | sprintf(buf, "../../stations/%pM", sta->sta.addr); |
209 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
210 | 254 | ||
211 | /* using sta as a boolean is fine outside RCU lock */ | 255 | /* using sta as a boolean is fine outside RCU lock */ |
212 | if (sta) | 256 | if (sta) |
213 | key->debugfs.stalink = | 257 | key->debugfs.stalink = |
214 | debugfs_create_symlink("station", key->debugfs.dir, buf); | 258 | debugfs_create_symlink("station", key->debugfs.dir, buf); |
215 | 259 | ||
216 | DEBUGFS_ADD(keylen); | 260 | DEBUGFS_ADD(keylen); |
217 | DEBUGFS_ADD(flags); | 261 | DEBUGFS_ADD(flags); |
218 | DEBUGFS_ADD(keyidx); | 262 | DEBUGFS_ADD(keyidx); |
219 | DEBUGFS_ADD(hw_key_idx); | 263 | DEBUGFS_ADD(hw_key_idx); |
220 | DEBUGFS_ADD(tx_rx_count); | 264 | DEBUGFS_ADD(tx_rx_count); |
221 | DEBUGFS_ADD(algorithm); | 265 | DEBUGFS_ADD(algorithm); |
222 | DEBUGFS_ADD(tx_spec); | 266 | DEBUGFS_ADD(tx_spec); |
223 | DEBUGFS_ADD(rx_spec); | 267 | DEBUGFS_ADD(rx_spec); |
224 | DEBUGFS_ADD(replays); | 268 | DEBUGFS_ADD(replays); |
269 | DEBUGFS_ADD(icverrors); | ||
225 | DEBUGFS_ADD(key); | 270 | DEBUGFS_ADD(key); |
226 | DEBUGFS_ADD(ifindex); | 271 | DEBUGFS_ADD(ifindex); |
227 | }; | 272 | }; |
228 | 273 | ||
229 | #define DEBUGFS_DEL(name) \ | 274 | #define DEBUGFS_DEL(name) \ |
230 | debugfs_remove(key->debugfs.name); key->debugfs.name = NULL; | 275 | debugfs_remove(key->debugfs.name); key->debugfs.name = NULL; |
231 | 276 | ||
232 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | 277 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key) |
233 | { | 278 | { |
234 | if (!key) | 279 | if (!key) |
235 | return; | 280 | return; |
236 | 281 | ||
237 | DEBUGFS_DEL(keylen); | 282 | DEBUGFS_DEL(keylen); |
238 | DEBUGFS_DEL(flags); | 283 | DEBUGFS_DEL(flags); |
239 | DEBUGFS_DEL(keyidx); | 284 | DEBUGFS_DEL(keyidx); |
240 | DEBUGFS_DEL(hw_key_idx); | 285 | DEBUGFS_DEL(hw_key_idx); |
241 | DEBUGFS_DEL(tx_rx_count); | 286 | DEBUGFS_DEL(tx_rx_count); |
242 | DEBUGFS_DEL(algorithm); | 287 | DEBUGFS_DEL(algorithm); |
243 | DEBUGFS_DEL(tx_spec); | 288 | DEBUGFS_DEL(tx_spec); |
244 | DEBUGFS_DEL(rx_spec); | 289 | DEBUGFS_DEL(rx_spec); |
245 | DEBUGFS_DEL(replays); | 290 | DEBUGFS_DEL(replays); |
291 | DEBUGFS_DEL(icverrors); | ||
246 | DEBUGFS_DEL(key); | 292 | DEBUGFS_DEL(key); |
247 | DEBUGFS_DEL(ifindex); | 293 | DEBUGFS_DEL(ifindex); |
248 | 294 | ||
249 | debugfs_remove(key->debugfs.stalink); | 295 | debugfs_remove(key->debugfs.stalink); |
250 | key->debugfs.stalink = NULL; | 296 | key->debugfs.stalink = NULL; |
251 | debugfs_remove(key->debugfs.dir); | 297 | debugfs_remove(key->debugfs.dir); |
252 | key->debugfs.dir = NULL; | 298 | key->debugfs.dir = NULL; |
253 | } | 299 | } |
254 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | 300 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) |
255 | { | 301 | { |
256 | char buf[50]; | 302 | char buf[50]; |
257 | struct ieee80211_key *key; | 303 | struct ieee80211_key *key; |
258 | 304 | ||
259 | if (!sdata->debugfsdir) | 305 | if (!sdata->debugfsdir) |
260 | return; | 306 | return; |
261 | 307 | ||
262 | /* this is running under the key lock */ | 308 | /* this is running under the key lock */ |
263 | 309 | ||
264 | key = sdata->default_key; | 310 | key = sdata->default_key; |
265 | if (key) { | 311 | if (key) { |
266 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 312 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
267 | sdata->common_debugfs.default_key = | 313 | sdata->common_debugfs.default_key = |
268 | debugfs_create_symlink("default_key", | 314 | debugfs_create_symlink("default_key", |
269 | sdata->debugfsdir, buf); | 315 | sdata->debugfsdir, buf); |
270 | } else | 316 | } else |
271 | ieee80211_debugfs_key_remove_default(sdata); | 317 | ieee80211_debugfs_key_remove_default(sdata); |
272 | } | 318 | } |
273 | 319 | ||
274 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) | 320 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) |
275 | { | 321 | { |
276 | if (!sdata) | 322 | if (!sdata) |
277 | return; | 323 | return; |
278 | 324 | ||
279 | debugfs_remove(sdata->common_debugfs.default_key); | 325 | debugfs_remove(sdata->common_debugfs.default_key); |
280 | sdata->common_debugfs.default_key = NULL; | 326 | sdata->common_debugfs.default_key = NULL; |
327 | } | ||
328 | |||
329 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | ||
330 | { | ||
331 | char buf[50]; | ||
332 | struct ieee80211_key *key; | ||
333 | |||
334 | if (!sdata->debugfsdir) | ||
335 | return; | ||
336 | |||
337 | /* this is running under the key lock */ | ||
338 | |||
339 | key = sdata->default_mgmt_key; | ||
340 | if (key) { | ||
341 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | ||
342 | sdata->common_debugfs.default_mgmt_key = | ||
343 | debugfs_create_symlink("default_mgmt_key", | ||
344 | sdata->debugfsdir, buf); | ||
345 | } else | ||
346 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | ||
347 | } | ||
348 | |||
349 | void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) | ||
350 | { | ||
351 | if (!sdata) | ||
352 | return; | ||
353 | |||
354 | debugfs_remove(sdata->common_debugfs.default_mgmt_key); | ||
355 | sdata->common_debugfs.default_mgmt_key = NULL; | ||
281 | } | 356 | } |
282 | 357 | ||
283 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, | 358 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, |
284 | struct sta_info *sta) | 359 | struct sta_info *sta) |
285 | { | 360 | { |
286 | debugfs_remove(key->debugfs.stalink); | 361 | debugfs_remove(key->debugfs.stalink); |
287 | key->debugfs.stalink = NULL; | 362 | key->debugfs.stalink = NULL; |
288 | } | 363 | } |
289 | 364 |
net/mac80211/debugfs_key.h
1 | #ifndef __MAC80211_DEBUGFS_KEY_H | 1 | #ifndef __MAC80211_DEBUGFS_KEY_H |
2 | #define __MAC80211_DEBUGFS_KEY_H | 2 | #define __MAC80211_DEBUGFS_KEY_H |
3 | 3 | ||
4 | #ifdef CONFIG_MAC80211_DEBUGFS | 4 | #ifdef CONFIG_MAC80211_DEBUGFS |
5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); | 5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); |
6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); | 6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); |
7 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); | 8 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); |
9 | void ieee80211_debugfs_key_add_mgmt_default( | ||
10 | struct ieee80211_sub_if_data *sdata); | ||
11 | void ieee80211_debugfs_key_remove_mgmt_default( | ||
12 | struct ieee80211_sub_if_data *sdata); | ||
9 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, | 13 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, |
10 | struct sta_info *sta); | 14 | struct sta_info *sta); |
11 | #else | 15 | #else |
12 | static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key) | 16 | static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key) |
13 | {} | 17 | {} |
14 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | 18 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) |
15 | {} | 19 | {} |
16 | static inline void ieee80211_debugfs_key_add_default( | 20 | static inline void ieee80211_debugfs_key_add_default( |
17 | struct ieee80211_sub_if_data *sdata) | 21 | struct ieee80211_sub_if_data *sdata) |
18 | {} | 22 | {} |
19 | static inline void ieee80211_debugfs_key_remove_default( | 23 | static inline void ieee80211_debugfs_key_remove_default( |
24 | struct ieee80211_sub_if_data *sdata) | ||
25 | {} | ||
26 | static inline void ieee80211_debugfs_key_add_mgmt_default( | ||
27 | struct ieee80211_sub_if_data *sdata) | ||
28 | {} | ||
29 | static inline void ieee80211_debugfs_key_remove_mgmt_default( | ||
20 | struct ieee80211_sub_if_data *sdata) | 30 | struct ieee80211_sub_if_data *sdata) |
21 | {} | 31 | {} |
22 | static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, | 32 | static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, |
23 | struct sta_info *sta) | 33 | struct sta_info *sta) |
24 | {} | 34 | {} |
25 | #endif | 35 | #endif |
26 | 36 | ||
27 | #endif /* __MAC80211_DEBUGFS_KEY_H */ | 37 | #endif /* __MAC80211_DEBUGFS_KEY_H */ |
28 | 38 |
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/wireless.h> | 27 | #include <net/wireless.h> |
28 | #include <net/iw_handler.h> | 28 | #include <net/iw_handler.h> |
29 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
30 | #include "key.h" | 30 | #include "key.h" |
31 | #include "sta_info.h" | 31 | #include "sta_info.h" |
32 | 32 | ||
33 | struct ieee80211_local; | 33 | struct ieee80211_local; |
34 | 34 | ||
35 | /* Maximum number of broadcast/multicast frames to buffer when some of the | 35 | /* Maximum number of broadcast/multicast frames to buffer when some of the |
36 | * associated stations are using power saving. */ | 36 | * associated stations are using power saving. */ |
37 | #define AP_MAX_BC_BUFFER 128 | 37 | #define AP_MAX_BC_BUFFER 128 |
38 | 38 | ||
39 | /* Maximum number of frames buffered to all STAs, including multicast frames. | 39 | /* Maximum number of frames buffered to all STAs, including multicast frames. |
40 | * Note: increasing this limit increases the potential memory requirement. Each | 40 | * Note: increasing this limit increases the potential memory requirement. Each |
41 | * frame can be up to about 2 kB long. */ | 41 | * frame can be up to about 2 kB long. */ |
42 | #define TOTAL_MAX_TX_BUFFER 512 | 42 | #define TOTAL_MAX_TX_BUFFER 512 |
43 | 43 | ||
44 | /* Required encryption head and tailroom */ | 44 | /* Required encryption head and tailroom */ |
45 | #define IEEE80211_ENCRYPT_HEADROOM 8 | 45 | #define IEEE80211_ENCRYPT_HEADROOM 8 |
46 | #define IEEE80211_ENCRYPT_TAILROOM 18 | 46 | #define IEEE80211_ENCRYPT_TAILROOM 18 |
47 | 47 | ||
48 | /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent | 48 | /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent |
49 | * reception of at least three fragmented frames. This limit can be increased | 49 | * reception of at least three fragmented frames. This limit can be increased |
50 | * by changing this define, at the cost of slower frame reassembly and | 50 | * by changing this define, at the cost of slower frame reassembly and |
51 | * increased memory use (about 2 kB of RAM per entry). */ | 51 | * increased memory use (about 2 kB of RAM per entry). */ |
52 | #define IEEE80211_FRAGMENT_MAX 4 | 52 | #define IEEE80211_FRAGMENT_MAX 4 |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * Time after which we ignore scan results and no longer report/use | 55 | * Time after which we ignore scan results and no longer report/use |
56 | * them in any way. | 56 | * them in any way. |
57 | */ | 57 | */ |
58 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | 58 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) |
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 | struct list_head list; | 73 | struct list_head list; |
74 | struct ieee80211_bss *hnext; | 74 | struct ieee80211_bss *hnext; |
75 | size_t ssid_len; | 75 | size_t ssid_len; |
76 | 76 | ||
77 | atomic_t users; | 77 | atomic_t users; |
78 | 78 | ||
79 | u8 bssid[ETH_ALEN]; | 79 | u8 bssid[ETH_ALEN]; |
80 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 80 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
81 | u8 dtim_period; | 81 | u8 dtim_period; |
82 | u16 capability; /* host byte order */ | 82 | u16 capability; /* host byte order */ |
83 | enum ieee80211_band band; | 83 | enum ieee80211_band band; |
84 | int freq; | 84 | int freq; |
85 | int signal, noise, qual; | 85 | int signal, noise, qual; |
86 | u8 *ies; /* all information elements from the last Beacon or Probe | 86 | u8 *ies; /* all information elements from the last Beacon or Probe |
87 | * Response frames; note Beacon frame is not allowed to | 87 | * Response frames; note Beacon frame is not allowed to |
88 | * override values from Probe Response */ | 88 | * override values from Probe Response */ |
89 | size_t ies_len; | 89 | size_t ies_len; |
90 | bool wmm_used; | 90 | bool wmm_used; |
91 | #ifdef CONFIG_MAC80211_MESH | 91 | #ifdef CONFIG_MAC80211_MESH |
92 | u8 *mesh_id; | 92 | u8 *mesh_id; |
93 | size_t mesh_id_len; | 93 | size_t mesh_id_len; |
94 | u8 *mesh_cfg; | 94 | u8 *mesh_cfg; |
95 | #endif | 95 | #endif |
96 | #define IEEE80211_MAX_SUPP_RATES 32 | 96 | #define IEEE80211_MAX_SUPP_RATES 32 |
97 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 97 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
98 | size_t supp_rates_len; | 98 | size_t supp_rates_len; |
99 | u64 timestamp; | 99 | u64 timestamp; |
100 | int beacon_int; | 100 | int beacon_int; |
101 | 101 | ||
102 | unsigned long last_probe_resp; | 102 | unsigned long last_probe_resp; |
103 | unsigned long last_update; | 103 | unsigned long last_update; |
104 | 104 | ||
105 | /* during assocation, we save an ERP value from a probe response so | 105 | /* during assocation, we save an ERP value from a probe response so |
106 | * that we can feed ERP info to the driver when handling the | 106 | * that we can feed ERP info to the driver when handling the |
107 | * association completes. these fields probably won't be up-to-date | 107 | * association completes. these fields probably won't be up-to-date |
108 | * otherwise, you probably don't want to use them. */ | 108 | * otherwise, you probably don't want to use them. */ |
109 | int has_erp_value; | 109 | int has_erp_value; |
110 | u8 erp_value; | 110 | u8 erp_value; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) | 113 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) |
114 | { | 114 | { |
115 | #ifdef CONFIG_MAC80211_MESH | 115 | #ifdef CONFIG_MAC80211_MESH |
116 | return bss->mesh_cfg; | 116 | return bss->mesh_cfg; |
117 | #endif | 117 | #endif |
118 | return NULL; | 118 | return NULL; |
119 | } | 119 | } |
120 | 120 | ||
121 | static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) | 121 | static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) |
122 | { | 122 | { |
123 | #ifdef CONFIG_MAC80211_MESH | 123 | #ifdef CONFIG_MAC80211_MESH |
124 | return bss->mesh_id; | 124 | return bss->mesh_id; |
125 | #endif | 125 | #endif |
126 | return NULL; | 126 | return NULL; |
127 | } | 127 | } |
128 | 128 | ||
129 | static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) | 129 | static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) |
130 | { | 130 | { |
131 | #ifdef CONFIG_MAC80211_MESH | 131 | #ifdef CONFIG_MAC80211_MESH |
132 | return bss->mesh_id_len; | 132 | return bss->mesh_id_len; |
133 | #endif | 133 | #endif |
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
136 | 136 | ||
137 | 137 | ||
138 | typedef unsigned __bitwise__ ieee80211_tx_result; | 138 | typedef unsigned __bitwise__ ieee80211_tx_result; |
139 | #define TX_CONTINUE ((__force ieee80211_tx_result) 0u) | 139 | #define TX_CONTINUE ((__force ieee80211_tx_result) 0u) |
140 | #define TX_DROP ((__force ieee80211_tx_result) 1u) | 140 | #define TX_DROP ((__force ieee80211_tx_result) 1u) |
141 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) | 141 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) |
142 | 142 | ||
143 | #define IEEE80211_TX_FRAGMENTED BIT(0) | 143 | #define IEEE80211_TX_FRAGMENTED BIT(0) |
144 | #define IEEE80211_TX_UNICAST BIT(1) | 144 | #define IEEE80211_TX_UNICAST BIT(1) |
145 | #define IEEE80211_TX_PS_BUFFERED BIT(2) | 145 | #define IEEE80211_TX_PS_BUFFERED BIT(2) |
146 | 146 | ||
147 | struct ieee80211_tx_data { | 147 | struct ieee80211_tx_data { |
148 | struct sk_buff *skb; | 148 | struct sk_buff *skb; |
149 | struct net_device *dev; | 149 | struct net_device *dev; |
150 | struct ieee80211_local *local; | 150 | struct ieee80211_local *local; |
151 | struct ieee80211_sub_if_data *sdata; | 151 | struct ieee80211_sub_if_data *sdata; |
152 | struct sta_info *sta; | 152 | struct sta_info *sta; |
153 | struct ieee80211_key *key; | 153 | struct ieee80211_key *key; |
154 | 154 | ||
155 | struct ieee80211_channel *channel; | 155 | struct ieee80211_channel *channel; |
156 | 156 | ||
157 | /* Extra fragments (in addition to the first fragment | 157 | /* Extra fragments (in addition to the first fragment |
158 | * in skb) */ | 158 | * in skb) */ |
159 | struct sk_buff **extra_frag; | 159 | struct sk_buff **extra_frag; |
160 | int num_extra_frag; | 160 | int num_extra_frag; |
161 | 161 | ||
162 | u16 ethertype; | 162 | u16 ethertype; |
163 | unsigned int flags; | 163 | unsigned int flags; |
164 | }; | 164 | }; |
165 | 165 | ||
166 | 166 | ||
167 | typedef unsigned __bitwise__ ieee80211_rx_result; | 167 | typedef unsigned __bitwise__ ieee80211_rx_result; |
168 | #define RX_CONTINUE ((__force ieee80211_rx_result) 0u) | 168 | #define RX_CONTINUE ((__force ieee80211_rx_result) 0u) |
169 | #define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u) | 169 | #define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u) |
170 | #define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u) | 170 | #define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u) |
171 | #define RX_QUEUED ((__force ieee80211_rx_result) 3u) | 171 | #define RX_QUEUED ((__force ieee80211_rx_result) 3u) |
172 | 172 | ||
173 | #define IEEE80211_RX_IN_SCAN BIT(0) | 173 | #define IEEE80211_RX_IN_SCAN BIT(0) |
174 | /* frame is destined to interface currently processed (incl. multicast frames) */ | 174 | /* frame is destined to interface currently processed (incl. multicast frames) */ |
175 | #define IEEE80211_RX_RA_MATCH BIT(1) | 175 | #define IEEE80211_RX_RA_MATCH BIT(1) |
176 | #define IEEE80211_RX_AMSDU BIT(2) | 176 | #define IEEE80211_RX_AMSDU BIT(2) |
177 | #define IEEE80211_RX_CMNTR_REPORTED BIT(3) | 177 | #define IEEE80211_RX_CMNTR_REPORTED BIT(3) |
178 | #define IEEE80211_RX_FRAGMENTED BIT(4) | 178 | #define IEEE80211_RX_FRAGMENTED BIT(4) |
179 | 179 | ||
180 | struct ieee80211_rx_data { | 180 | struct ieee80211_rx_data { |
181 | struct sk_buff *skb; | 181 | struct sk_buff *skb; |
182 | struct net_device *dev; | 182 | struct net_device *dev; |
183 | struct ieee80211_local *local; | 183 | struct ieee80211_local *local; |
184 | struct ieee80211_sub_if_data *sdata; | 184 | struct ieee80211_sub_if_data *sdata; |
185 | struct sta_info *sta; | 185 | struct sta_info *sta; |
186 | struct ieee80211_key *key; | 186 | struct ieee80211_key *key; |
187 | struct ieee80211_rx_status *status; | 187 | struct ieee80211_rx_status *status; |
188 | struct ieee80211_rate *rate; | 188 | struct ieee80211_rate *rate; |
189 | 189 | ||
190 | unsigned int flags; | 190 | unsigned int flags; |
191 | int sent_ps_buffered; | 191 | int sent_ps_buffered; |
192 | int queue; | 192 | int queue; |
193 | u32 tkip_iv32; | 193 | u32 tkip_iv32; |
194 | u16 tkip_iv16; | 194 | u16 tkip_iv16; |
195 | }; | 195 | }; |
196 | 196 | ||
197 | struct ieee80211_tx_stored_packet { | 197 | struct ieee80211_tx_stored_packet { |
198 | struct sk_buff *skb; | 198 | struct sk_buff *skb; |
199 | struct sk_buff **extra_frag; | 199 | struct sk_buff **extra_frag; |
200 | int num_extra_frag; | 200 | int num_extra_frag; |
201 | }; | 201 | }; |
202 | 202 | ||
203 | struct beacon_data { | 203 | struct beacon_data { |
204 | u8 *head, *tail; | 204 | u8 *head, *tail; |
205 | int head_len, tail_len; | 205 | int head_len, tail_len; |
206 | int dtim_period; | 206 | int dtim_period; |
207 | }; | 207 | }; |
208 | 208 | ||
209 | struct ieee80211_if_ap { | 209 | struct ieee80211_if_ap { |
210 | struct beacon_data *beacon; | 210 | struct beacon_data *beacon; |
211 | 211 | ||
212 | struct list_head vlans; | 212 | struct list_head vlans; |
213 | 213 | ||
214 | /* yes, this looks ugly, but guarantees that we can later use | 214 | /* yes, this looks ugly, but guarantees that we can later use |
215 | * bitmap_empty :) | 215 | * bitmap_empty :) |
216 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ | 216 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ |
217 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 217 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; |
218 | struct sk_buff_head ps_bc_buf; | 218 | struct sk_buff_head ps_bc_buf; |
219 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 219 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
220 | int dtim_count; | 220 | int dtim_count; |
221 | }; | 221 | }; |
222 | 222 | ||
223 | struct ieee80211_if_wds { | 223 | struct ieee80211_if_wds { |
224 | struct sta_info *sta; | 224 | struct sta_info *sta; |
225 | u8 remote_addr[ETH_ALEN]; | 225 | u8 remote_addr[ETH_ALEN]; |
226 | }; | 226 | }; |
227 | 227 | ||
228 | struct ieee80211_if_vlan { | 228 | struct ieee80211_if_vlan { |
229 | struct list_head list; | 229 | struct list_head list; |
230 | }; | 230 | }; |
231 | 231 | ||
232 | struct mesh_stats { | 232 | struct mesh_stats { |
233 | __u32 fwded_frames; /* Mesh forwarded frames */ | 233 | __u32 fwded_frames; /* Mesh forwarded frames */ |
234 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ | 234 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ |
235 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ | 235 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ |
236 | atomic_t estab_plinks; | 236 | atomic_t estab_plinks; |
237 | }; | 237 | }; |
238 | 238 | ||
239 | #define PREQ_Q_F_START 0x1 | 239 | #define PREQ_Q_F_START 0x1 |
240 | #define PREQ_Q_F_REFRESH 0x2 | 240 | #define PREQ_Q_F_REFRESH 0x2 |
241 | struct mesh_preq_queue { | 241 | struct mesh_preq_queue { |
242 | struct list_head list; | 242 | struct list_head list; |
243 | u8 dst[ETH_ALEN]; | 243 | u8 dst[ETH_ALEN]; |
244 | u8 flags; | 244 | u8 flags; |
245 | }; | 245 | }; |
246 | 246 | ||
247 | /* flags used in struct ieee80211_if_sta.flags */ | 247 | /* flags used in struct ieee80211_if_sta.flags */ |
248 | #define IEEE80211_STA_SSID_SET BIT(0) | 248 | #define IEEE80211_STA_SSID_SET BIT(0) |
249 | #define IEEE80211_STA_BSSID_SET BIT(1) | 249 | #define IEEE80211_STA_BSSID_SET BIT(1) |
250 | #define IEEE80211_STA_PREV_BSSID_SET BIT(2) | 250 | #define IEEE80211_STA_PREV_BSSID_SET BIT(2) |
251 | #define IEEE80211_STA_AUTHENTICATED BIT(3) | 251 | #define IEEE80211_STA_AUTHENTICATED BIT(3) |
252 | #define IEEE80211_STA_ASSOCIATED BIT(4) | 252 | #define IEEE80211_STA_ASSOCIATED BIT(4) |
253 | #define IEEE80211_STA_PROBEREQ_POLL BIT(5) | 253 | #define IEEE80211_STA_PROBEREQ_POLL BIT(5) |
254 | #define IEEE80211_STA_CREATE_IBSS BIT(6) | 254 | #define IEEE80211_STA_CREATE_IBSS BIT(6) |
255 | #define IEEE80211_STA_MIXED_CELL BIT(7) | 255 | #define IEEE80211_STA_MIXED_CELL BIT(7) |
256 | #define IEEE80211_STA_WMM_ENABLED BIT(8) | 256 | #define IEEE80211_STA_WMM_ENABLED BIT(8) |
257 | #define IEEE80211_STA_AUTO_SSID_SEL BIT(10) | 257 | #define IEEE80211_STA_AUTO_SSID_SEL BIT(10) |
258 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) | 258 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) |
259 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) | 259 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) |
260 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) | 260 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) |
261 | #define IEEE80211_STA_TKIP_WEP_USED BIT(14) | 261 | #define IEEE80211_STA_TKIP_WEP_USED BIT(14) |
262 | #define IEEE80211_STA_CSA_RECEIVED BIT(15) | 262 | #define IEEE80211_STA_CSA_RECEIVED BIT(15) |
263 | #define IEEE80211_STA_MFP_ENABLED BIT(16) | 263 | #define IEEE80211_STA_MFP_ENABLED BIT(16) |
264 | /* flags for MLME request */ | 264 | /* flags for MLME request */ |
265 | #define IEEE80211_STA_REQ_SCAN 0 | 265 | #define IEEE80211_STA_REQ_SCAN 0 |
266 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 | 266 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 |
267 | #define IEEE80211_STA_REQ_AUTH 2 | 267 | #define IEEE80211_STA_REQ_AUTH 2 |
268 | #define IEEE80211_STA_REQ_RUN 3 | 268 | #define IEEE80211_STA_REQ_RUN 3 |
269 | 269 | ||
270 | /* STA/IBSS MLME states */ | 270 | /* STA/IBSS MLME states */ |
271 | enum ieee80211_sta_mlme_state { | 271 | enum ieee80211_sta_mlme_state { |
272 | IEEE80211_STA_MLME_DISABLED, | 272 | IEEE80211_STA_MLME_DISABLED, |
273 | IEEE80211_STA_MLME_DIRECT_PROBE, | 273 | IEEE80211_STA_MLME_DIRECT_PROBE, |
274 | IEEE80211_STA_MLME_AUTHENTICATE, | 274 | IEEE80211_STA_MLME_AUTHENTICATE, |
275 | IEEE80211_STA_MLME_ASSOCIATE, | 275 | IEEE80211_STA_MLME_ASSOCIATE, |
276 | IEEE80211_STA_MLME_ASSOCIATED, | 276 | IEEE80211_STA_MLME_ASSOCIATED, |
277 | IEEE80211_STA_MLME_IBSS_SEARCH, | 277 | IEEE80211_STA_MLME_IBSS_SEARCH, |
278 | IEEE80211_STA_MLME_IBSS_JOINED, | 278 | IEEE80211_STA_MLME_IBSS_JOINED, |
279 | }; | 279 | }; |
280 | 280 | ||
281 | /* bitfield of allowed auth algs */ | 281 | /* bitfield of allowed auth algs */ |
282 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | 282 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) |
283 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) | 283 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) |
284 | #define IEEE80211_AUTH_ALG_LEAP BIT(2) | 284 | #define IEEE80211_AUTH_ALG_LEAP BIT(2) |
285 | 285 | ||
286 | struct ieee80211_if_sta { | 286 | struct ieee80211_if_sta { |
287 | struct timer_list timer; | 287 | struct timer_list timer; |
288 | struct timer_list chswitch_timer; | 288 | struct timer_list chswitch_timer; |
289 | struct work_struct work; | 289 | struct work_struct work; |
290 | struct work_struct chswitch_work; | 290 | struct work_struct chswitch_work; |
291 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | 291 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; |
292 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 292 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
293 | enum ieee80211_sta_mlme_state state; | 293 | enum ieee80211_sta_mlme_state state; |
294 | size_t ssid_len; | 294 | size_t ssid_len; |
295 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 295 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
296 | size_t scan_ssid_len; | 296 | size_t scan_ssid_len; |
297 | u16 aid; | 297 | u16 aid; |
298 | u16 ap_capab, capab; | 298 | u16 ap_capab, capab; |
299 | u8 *extra_ie; /* to be added to the end of AssocReq */ | 299 | u8 *extra_ie; /* to be added to the end of AssocReq */ |
300 | size_t extra_ie_len; | 300 | size_t extra_ie_len; |
301 | 301 | ||
302 | /* The last AssocReq/Resp IEs */ | 302 | /* The last AssocReq/Resp IEs */ |
303 | u8 *assocreq_ies, *assocresp_ies; | 303 | u8 *assocreq_ies, *assocresp_ies; |
304 | size_t assocreq_ies_len, assocresp_ies_len; | 304 | size_t assocreq_ies_len, assocresp_ies_len; |
305 | 305 | ||
306 | struct sk_buff_head skb_queue; | 306 | struct sk_buff_head skb_queue; |
307 | 307 | ||
308 | int assoc_scan_tries; /* number of scans done pre-association */ | 308 | int assoc_scan_tries; /* number of scans done pre-association */ |
309 | int direct_probe_tries; /* retries for direct probes */ | 309 | int direct_probe_tries; /* retries for direct probes */ |
310 | int auth_tries; /* retries for auth req */ | 310 | int auth_tries; /* retries for auth req */ |
311 | int assoc_tries; /* retries for assoc req */ | 311 | int assoc_tries; /* retries for assoc req */ |
312 | 312 | ||
313 | unsigned long request; | 313 | unsigned long request; |
314 | 314 | ||
315 | unsigned long last_probe; | 315 | unsigned long last_probe; |
316 | 316 | ||
317 | unsigned int flags; | 317 | unsigned int flags; |
318 | 318 | ||
319 | unsigned int auth_algs; /* bitfield of allowed auth algs */ | 319 | unsigned int auth_algs; /* bitfield of allowed auth algs */ |
320 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ | 320 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ |
321 | int auth_transaction; | 321 | int auth_transaction; |
322 | 322 | ||
323 | unsigned long ibss_join_req; | 323 | unsigned long ibss_join_req; |
324 | struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ | 324 | struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ |
325 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; | 325 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; |
326 | 326 | ||
327 | int wmm_last_param_set; | 327 | int wmm_last_param_set; |
328 | }; | 328 | }; |
329 | 329 | ||
330 | struct ieee80211_if_mesh { | 330 | struct ieee80211_if_mesh { |
331 | struct work_struct work; | 331 | struct work_struct work; |
332 | struct timer_list housekeeping_timer; | 332 | struct timer_list housekeeping_timer; |
333 | struct timer_list mesh_path_timer; | 333 | struct timer_list mesh_path_timer; |
334 | struct sk_buff_head skb_queue; | 334 | struct sk_buff_head skb_queue; |
335 | 335 | ||
336 | bool housekeeping; | 336 | bool housekeeping; |
337 | 337 | ||
338 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | 338 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; |
339 | size_t mesh_id_len; | 339 | size_t mesh_id_len; |
340 | /* Active Path Selection Protocol Identifier */ | 340 | /* Active Path Selection Protocol Identifier */ |
341 | u8 mesh_pp_id[4]; | 341 | u8 mesh_pp_id[4]; |
342 | /* Active Path Selection Metric Identifier */ | 342 | /* Active Path Selection Metric Identifier */ |
343 | u8 mesh_pm_id[4]; | 343 | u8 mesh_pm_id[4]; |
344 | /* Congestion Control Mode Identifier */ | 344 | /* Congestion Control Mode Identifier */ |
345 | u8 mesh_cc_id[4]; | 345 | u8 mesh_cc_id[4]; |
346 | /* Local mesh Destination Sequence Number */ | 346 | /* Local mesh Destination Sequence Number */ |
347 | u32 dsn; | 347 | u32 dsn; |
348 | /* Last used PREQ ID */ | 348 | /* Last used PREQ ID */ |
349 | u32 preq_id; | 349 | u32 preq_id; |
350 | atomic_t mpaths; | 350 | atomic_t mpaths; |
351 | /* Timestamp of last DSN update */ | 351 | /* Timestamp of last DSN update */ |
352 | unsigned long last_dsn_update; | 352 | unsigned long last_dsn_update; |
353 | /* Timestamp of last DSN sent */ | 353 | /* Timestamp of last DSN sent */ |
354 | unsigned long last_preq; | 354 | unsigned long last_preq; |
355 | struct mesh_rmc *rmc; | 355 | struct mesh_rmc *rmc; |
356 | spinlock_t mesh_preq_queue_lock; | 356 | spinlock_t mesh_preq_queue_lock; |
357 | struct mesh_preq_queue preq_queue; | 357 | struct mesh_preq_queue preq_queue; |
358 | int preq_queue_len; | 358 | int preq_queue_len; |
359 | struct mesh_stats mshstats; | 359 | struct mesh_stats mshstats; |
360 | struct mesh_config mshcfg; | 360 | struct mesh_config mshcfg; |
361 | u32 mesh_seqnum; | 361 | u32 mesh_seqnum; |
362 | bool accepting_plinks; | 362 | bool accepting_plinks; |
363 | }; | 363 | }; |
364 | 364 | ||
365 | #ifdef CONFIG_MAC80211_MESH | 365 | #ifdef CONFIG_MAC80211_MESH |
366 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ | 366 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
367 | do { (msh)->mshstats.name++; } while (0) | 367 | do { (msh)->mshstats.name++; } while (0) |
368 | #else | 368 | #else |
369 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ | 369 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
370 | do { } while (0) | 370 | do { } while (0) |
371 | #endif | 371 | #endif |
372 | 372 | ||
373 | /** | 373 | /** |
374 | * enum ieee80211_sub_if_data_flags - virtual interface flags | 374 | * enum ieee80211_sub_if_data_flags - virtual interface flags |
375 | * | 375 | * |
376 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets | 376 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets |
377 | * @IEEE80211_SDATA_PROMISC: interface is promisc | 377 | * @IEEE80211_SDATA_PROMISC: interface is promisc |
378 | * @IEEE80211_SDATA_USERSPACE_MLME: userspace MLME is active | 378 | * @IEEE80211_SDATA_USERSPACE_MLME: userspace MLME is active |
379 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode | 379 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode |
380 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between | 380 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between |
381 | * associated stations and deliver multicast frames both | 381 | * associated stations and deliver multicast frames both |
382 | * back to wireless media and to the local net stack. | 382 | * back to wireless media and to the local net stack. |
383 | */ | 383 | */ |
384 | enum ieee80211_sub_if_data_flags { | 384 | enum ieee80211_sub_if_data_flags { |
385 | IEEE80211_SDATA_ALLMULTI = BIT(0), | 385 | IEEE80211_SDATA_ALLMULTI = BIT(0), |
386 | IEEE80211_SDATA_PROMISC = BIT(1), | 386 | IEEE80211_SDATA_PROMISC = BIT(1), |
387 | IEEE80211_SDATA_USERSPACE_MLME = BIT(2), | 387 | IEEE80211_SDATA_USERSPACE_MLME = BIT(2), |
388 | IEEE80211_SDATA_OPERATING_GMODE = BIT(3), | 388 | IEEE80211_SDATA_OPERATING_GMODE = BIT(3), |
389 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(4), | 389 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(4), |
390 | }; | 390 | }; |
391 | 391 | ||
392 | struct ieee80211_sub_if_data { | 392 | struct ieee80211_sub_if_data { |
393 | struct list_head list; | 393 | struct list_head list; |
394 | 394 | ||
395 | struct wireless_dev wdev; | 395 | struct wireless_dev wdev; |
396 | 396 | ||
397 | /* keys */ | 397 | /* keys */ |
398 | struct list_head key_list; | 398 | struct list_head key_list; |
399 | 399 | ||
400 | struct net_device *dev; | 400 | struct net_device *dev; |
401 | struct ieee80211_local *local; | 401 | struct ieee80211_local *local; |
402 | 402 | ||
403 | unsigned int flags; | 403 | unsigned int flags; |
404 | 404 | ||
405 | int drop_unencrypted; | 405 | int drop_unencrypted; |
406 | 406 | ||
407 | /* Fragment table for host-based reassembly */ | 407 | /* Fragment table for host-based reassembly */ |
408 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 408 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
409 | unsigned int fragment_next; | 409 | unsigned int fragment_next; |
410 | 410 | ||
411 | #define NUM_DEFAULT_KEYS 4 | 411 | #define NUM_DEFAULT_KEYS 4 |
412 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; | 412 | #define NUM_DEFAULT_MGMT_KEYS 2 |
413 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | ||
413 | struct ieee80211_key *default_key; | 414 | struct ieee80211_key *default_key; |
415 | struct ieee80211_key *default_mgmt_key; | ||
414 | 416 | ||
415 | u16 sequence_number; | 417 | u16 sequence_number; |
416 | 418 | ||
417 | /* | 419 | /* |
418 | * AP this belongs to: self in AP mode and | 420 | * AP this belongs to: self in AP mode and |
419 | * corresponding AP in VLAN mode, NULL for | 421 | * corresponding AP in VLAN mode, NULL for |
420 | * all others (might be needed later in IBSS) | 422 | * all others (might be needed later in IBSS) |
421 | */ | 423 | */ |
422 | struct ieee80211_if_ap *bss; | 424 | struct ieee80211_if_ap *bss; |
423 | 425 | ||
424 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | 426 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ |
425 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | 427 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ |
426 | 428 | ||
427 | union { | 429 | union { |
428 | struct ieee80211_if_ap ap; | 430 | struct ieee80211_if_ap ap; |
429 | struct ieee80211_if_wds wds; | 431 | struct ieee80211_if_wds wds; |
430 | struct ieee80211_if_vlan vlan; | 432 | struct ieee80211_if_vlan vlan; |
431 | struct ieee80211_if_sta sta; | 433 | struct ieee80211_if_sta sta; |
432 | #ifdef CONFIG_MAC80211_MESH | 434 | #ifdef CONFIG_MAC80211_MESH |
433 | struct ieee80211_if_mesh mesh; | 435 | struct ieee80211_if_mesh mesh; |
434 | #endif | 436 | #endif |
435 | u32 mntr_flags; | 437 | u32 mntr_flags; |
436 | } u; | 438 | } u; |
437 | 439 | ||
438 | #ifdef CONFIG_MAC80211_DEBUGFS | 440 | #ifdef CONFIG_MAC80211_DEBUGFS |
439 | struct dentry *debugfsdir; | 441 | struct dentry *debugfsdir; |
440 | union { | 442 | union { |
441 | struct { | 443 | struct { |
442 | struct dentry *drop_unencrypted; | 444 | struct dentry *drop_unencrypted; |
443 | struct dentry *state; | 445 | struct dentry *state; |
444 | struct dentry *bssid; | 446 | struct dentry *bssid; |
445 | struct dentry *prev_bssid; | 447 | struct dentry *prev_bssid; |
446 | struct dentry *ssid_len; | 448 | struct dentry *ssid_len; |
447 | struct dentry *aid; | 449 | struct dentry *aid; |
448 | struct dentry *ap_capab; | 450 | struct dentry *ap_capab; |
449 | struct dentry *capab; | 451 | struct dentry *capab; |
450 | struct dentry *extra_ie_len; | 452 | struct dentry *extra_ie_len; |
451 | struct dentry *auth_tries; | 453 | struct dentry *auth_tries; |
452 | struct dentry *assoc_tries; | 454 | struct dentry *assoc_tries; |
453 | struct dentry *auth_algs; | 455 | struct dentry *auth_algs; |
454 | struct dentry *auth_alg; | 456 | struct dentry *auth_alg; |
455 | struct dentry *auth_transaction; | 457 | struct dentry *auth_transaction; |
456 | struct dentry *flags; | 458 | struct dentry *flags; |
457 | struct dentry *force_unicast_rateidx; | 459 | struct dentry *force_unicast_rateidx; |
458 | struct dentry *max_ratectrl_rateidx; | 460 | struct dentry *max_ratectrl_rateidx; |
459 | } sta; | 461 | } sta; |
460 | struct { | 462 | struct { |
461 | struct dentry *drop_unencrypted; | 463 | struct dentry *drop_unencrypted; |
462 | struct dentry *num_sta_ps; | 464 | struct dentry *num_sta_ps; |
463 | struct dentry *dtim_count; | 465 | struct dentry *dtim_count; |
464 | struct dentry *force_unicast_rateidx; | 466 | struct dentry *force_unicast_rateidx; |
465 | struct dentry *max_ratectrl_rateidx; | 467 | struct dentry *max_ratectrl_rateidx; |
466 | struct dentry *num_buffered_multicast; | 468 | struct dentry *num_buffered_multicast; |
467 | } ap; | 469 | } ap; |
468 | struct { | 470 | struct { |
469 | struct dentry *drop_unencrypted; | 471 | struct dentry *drop_unencrypted; |
470 | struct dentry *peer; | 472 | struct dentry *peer; |
471 | struct dentry *force_unicast_rateidx; | 473 | struct dentry *force_unicast_rateidx; |
472 | struct dentry *max_ratectrl_rateidx; | 474 | struct dentry *max_ratectrl_rateidx; |
473 | } wds; | 475 | } wds; |
474 | struct { | 476 | struct { |
475 | struct dentry *drop_unencrypted; | 477 | struct dentry *drop_unencrypted; |
476 | struct dentry *force_unicast_rateidx; | 478 | struct dentry *force_unicast_rateidx; |
477 | struct dentry *max_ratectrl_rateidx; | 479 | struct dentry *max_ratectrl_rateidx; |
478 | } vlan; | 480 | } vlan; |
479 | struct { | 481 | struct { |
480 | struct dentry *mode; | 482 | struct dentry *mode; |
481 | } monitor; | 483 | } monitor; |
482 | } debugfs; | 484 | } debugfs; |
483 | struct { | 485 | struct { |
484 | struct dentry *default_key; | 486 | struct dentry *default_key; |
487 | struct dentry *default_mgmt_key; | ||
485 | } common_debugfs; | 488 | } common_debugfs; |
486 | 489 | ||
487 | #ifdef CONFIG_MAC80211_MESH | 490 | #ifdef CONFIG_MAC80211_MESH |
488 | struct dentry *mesh_stats_dir; | 491 | struct dentry *mesh_stats_dir; |
489 | struct { | 492 | struct { |
490 | struct dentry *fwded_frames; | 493 | struct dentry *fwded_frames; |
491 | struct dentry *dropped_frames_ttl; | 494 | struct dentry *dropped_frames_ttl; |
492 | struct dentry *dropped_frames_no_route; | 495 | struct dentry *dropped_frames_no_route; |
493 | struct dentry *estab_plinks; | 496 | struct dentry *estab_plinks; |
494 | struct timer_list mesh_path_timer; | 497 | struct timer_list mesh_path_timer; |
495 | } mesh_stats; | 498 | } mesh_stats; |
496 | 499 | ||
497 | struct dentry *mesh_config_dir; | 500 | struct dentry *mesh_config_dir; |
498 | struct { | 501 | struct { |
499 | struct dentry *dot11MeshRetryTimeout; | 502 | struct dentry *dot11MeshRetryTimeout; |
500 | struct dentry *dot11MeshConfirmTimeout; | 503 | struct dentry *dot11MeshConfirmTimeout; |
501 | struct dentry *dot11MeshHoldingTimeout; | 504 | struct dentry *dot11MeshHoldingTimeout; |
502 | struct dentry *dot11MeshMaxRetries; | 505 | struct dentry *dot11MeshMaxRetries; |
503 | struct dentry *dot11MeshTTL; | 506 | struct dentry *dot11MeshTTL; |
504 | struct dentry *auto_open_plinks; | 507 | struct dentry *auto_open_plinks; |
505 | struct dentry *dot11MeshMaxPeerLinks; | 508 | struct dentry *dot11MeshMaxPeerLinks; |
506 | struct dentry *dot11MeshHWMPactivePathTimeout; | 509 | struct dentry *dot11MeshHWMPactivePathTimeout; |
507 | struct dentry *dot11MeshHWMPpreqMinInterval; | 510 | struct dentry *dot11MeshHWMPpreqMinInterval; |
508 | struct dentry *dot11MeshHWMPnetDiameterTraversalTime; | 511 | struct dentry *dot11MeshHWMPnetDiameterTraversalTime; |
509 | struct dentry *dot11MeshHWMPmaxPREQretries; | 512 | struct dentry *dot11MeshHWMPmaxPREQretries; |
510 | struct dentry *path_refresh_time; | 513 | struct dentry *path_refresh_time; |
511 | struct dentry *min_discovery_timeout; | 514 | struct dentry *min_discovery_timeout; |
512 | } mesh_config; | 515 | } mesh_config; |
513 | #endif | 516 | #endif |
514 | 517 | ||
515 | #endif | 518 | #endif |
516 | /* must be last, dynamically sized area in this! */ | 519 | /* must be last, dynamically sized area in this! */ |
517 | struct ieee80211_vif vif; | 520 | struct ieee80211_vif vif; |
518 | }; | 521 | }; |
519 | 522 | ||
520 | static inline | 523 | static inline |
521 | struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | 524 | struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) |
522 | { | 525 | { |
523 | return container_of(p, struct ieee80211_sub_if_data, vif); | 526 | return container_of(p, struct ieee80211_sub_if_data, vif); |
524 | } | 527 | } |
525 | 528 | ||
526 | static inline void | 529 | static inline void |
527 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | 530 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, |
528 | u8 mesh_id_len, u8 *mesh_id) | 531 | u8 mesh_id_len, u8 *mesh_id) |
529 | { | 532 | { |
530 | #ifdef CONFIG_MAC80211_MESH | 533 | #ifdef CONFIG_MAC80211_MESH |
531 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 534 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
532 | ifmsh->mesh_id_len = mesh_id_len; | 535 | ifmsh->mesh_id_len = mesh_id_len; |
533 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); | 536 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); |
534 | #else | 537 | #else |
535 | WARN_ON(1); | 538 | WARN_ON(1); |
536 | #endif | 539 | #endif |
537 | } | 540 | } |
538 | 541 | ||
539 | enum { | 542 | enum { |
540 | IEEE80211_RX_MSG = 1, | 543 | IEEE80211_RX_MSG = 1, |
541 | IEEE80211_TX_STATUS_MSG = 2, | 544 | IEEE80211_TX_STATUS_MSG = 2, |
542 | IEEE80211_DELBA_MSG = 3, | 545 | IEEE80211_DELBA_MSG = 3, |
543 | IEEE80211_ADDBA_MSG = 4, | 546 | IEEE80211_ADDBA_MSG = 4, |
544 | }; | 547 | }; |
545 | 548 | ||
546 | enum queue_stop_reason { | 549 | enum queue_stop_reason { |
547 | IEEE80211_QUEUE_STOP_REASON_DRIVER, | 550 | IEEE80211_QUEUE_STOP_REASON_DRIVER, |
548 | IEEE80211_QUEUE_STOP_REASON_PS, | 551 | IEEE80211_QUEUE_STOP_REASON_PS, |
549 | IEEE80211_QUEUE_STOP_REASON_CSA | 552 | IEEE80211_QUEUE_STOP_REASON_CSA |
550 | }; | 553 | }; |
551 | 554 | ||
552 | /* maximum number of hardware queues we support. */ | 555 | /* maximum number of hardware queues we support. */ |
553 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) | 556 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) |
554 | 557 | ||
555 | struct ieee80211_master_priv { | 558 | struct ieee80211_master_priv { |
556 | struct ieee80211_local *local; | 559 | struct ieee80211_local *local; |
557 | }; | 560 | }; |
558 | 561 | ||
559 | struct ieee80211_local { | 562 | struct ieee80211_local { |
560 | /* embed the driver visible part. | 563 | /* embed the driver visible part. |
561 | * don't cast (use the static inlines below), but we keep | 564 | * don't cast (use the static inlines below), but we keep |
562 | * it first anyway so they become a no-op */ | 565 | * it first anyway so they become a no-op */ |
563 | struct ieee80211_hw hw; | 566 | struct ieee80211_hw hw; |
564 | 567 | ||
565 | const struct ieee80211_ops *ops; | 568 | const struct ieee80211_ops *ops; |
566 | 569 | ||
567 | unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)]; | 570 | unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)]; |
568 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | 571 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; |
569 | spinlock_t queue_stop_reason_lock; | 572 | spinlock_t queue_stop_reason_lock; |
570 | struct net_device *mdev; /* wmaster# - "master" 802.11 device */ | 573 | struct net_device *mdev; /* wmaster# - "master" 802.11 device */ |
571 | int open_count; | 574 | int open_count; |
572 | int monitors, cooked_mntrs; | 575 | int monitors, cooked_mntrs; |
573 | /* number of interfaces with corresponding FIF_ flags */ | 576 | /* number of interfaces with corresponding FIF_ flags */ |
574 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; | 577 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; |
575 | unsigned int filter_flags; /* FIF_* */ | 578 | unsigned int filter_flags; /* FIF_* */ |
576 | struct iw_statistics wstats; | 579 | struct iw_statistics wstats; |
577 | u8 wstats_flags; | 580 | u8 wstats_flags; |
578 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 581 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
579 | int tx_headroom; /* required headroom for hardware/radiotap */ | 582 | int tx_headroom; /* required headroom for hardware/radiotap */ |
580 | 583 | ||
581 | /* Tasklet and skb queue to process calls from IRQ mode. All frames | 584 | /* Tasklet and skb queue to process calls from IRQ mode. All frames |
582 | * added to skb_queue will be processed, but frames in | 585 | * added to skb_queue will be processed, but frames in |
583 | * skb_queue_unreliable may be dropped if the total length of these | 586 | * skb_queue_unreliable may be dropped if the total length of these |
584 | * queues increases over the limit. */ | 587 | * queues increases over the limit. */ |
585 | #define IEEE80211_IRQSAFE_QUEUE_LIMIT 128 | 588 | #define IEEE80211_IRQSAFE_QUEUE_LIMIT 128 |
586 | struct tasklet_struct tasklet; | 589 | struct tasklet_struct tasklet; |
587 | struct sk_buff_head skb_queue; | 590 | struct sk_buff_head skb_queue; |
588 | struct sk_buff_head skb_queue_unreliable; | 591 | struct sk_buff_head skb_queue_unreliable; |
589 | 592 | ||
590 | /* Station data */ | 593 | /* Station data */ |
591 | /* | 594 | /* |
592 | * The lock only protects the list, hash, timer and counter | 595 | * The lock only protects the list, hash, timer and counter |
593 | * against manipulation, reads are done in RCU. Additionally, | 596 | * against manipulation, reads are done in RCU. Additionally, |
594 | * the lock protects each BSS's TIM bitmap. | 597 | * the lock protects each BSS's TIM bitmap. |
595 | */ | 598 | */ |
596 | spinlock_t sta_lock; | 599 | spinlock_t sta_lock; |
597 | unsigned long num_sta; | 600 | unsigned long num_sta; |
598 | struct list_head sta_list; | 601 | struct list_head sta_list; |
599 | struct list_head sta_flush_list; | 602 | struct list_head sta_flush_list; |
600 | struct work_struct sta_flush_work; | 603 | struct work_struct sta_flush_work; |
601 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 604 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
602 | struct timer_list sta_cleanup; | 605 | struct timer_list sta_cleanup; |
603 | 606 | ||
604 | unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; | 607 | unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; |
605 | unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; | 608 | unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; |
606 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; | 609 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; |
607 | struct tasklet_struct tx_pending_tasklet; | 610 | struct tasklet_struct tx_pending_tasklet; |
608 | 611 | ||
609 | /* number of interfaces with corresponding IFF_ flags */ | 612 | /* number of interfaces with corresponding IFF_ flags */ |
610 | atomic_t iff_allmultis, iff_promiscs; | 613 | atomic_t iff_allmultis, iff_promiscs; |
611 | 614 | ||
612 | struct rate_control_ref *rate_ctrl; | 615 | struct rate_control_ref *rate_ctrl; |
613 | 616 | ||
614 | int rts_threshold; | 617 | int rts_threshold; |
615 | int fragmentation_threshold; | 618 | int fragmentation_threshold; |
616 | 619 | ||
617 | struct crypto_blkcipher *wep_tx_tfm; | 620 | struct crypto_blkcipher *wep_tx_tfm; |
618 | struct crypto_blkcipher *wep_rx_tfm; | 621 | struct crypto_blkcipher *wep_rx_tfm; |
619 | u32 wep_iv; | 622 | u32 wep_iv; |
620 | 623 | ||
621 | struct list_head interfaces; | 624 | struct list_head interfaces; |
622 | 625 | ||
623 | /* | 626 | /* |
624 | * Key lock, protects sdata's key_list and sta_info's | 627 | * Key lock, protects sdata's key_list and sta_info's |
625 | * key pointers (write access, they're RCU.) | 628 | * key pointers (write access, they're RCU.) |
626 | */ | 629 | */ |
627 | spinlock_t key_lock; | 630 | spinlock_t key_lock; |
628 | 631 | ||
629 | 632 | ||
630 | /* Scanning and BSS list */ | 633 | /* Scanning and BSS list */ |
631 | bool sw_scanning, hw_scanning; | 634 | bool sw_scanning, hw_scanning; |
632 | int scan_channel_idx; | 635 | int scan_channel_idx; |
633 | enum ieee80211_band scan_band; | 636 | enum ieee80211_band scan_band; |
634 | 637 | ||
635 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; | 638 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; |
636 | unsigned long last_scan_completed; | 639 | unsigned long last_scan_completed; |
637 | struct delayed_work scan_work; | 640 | struct delayed_work scan_work; |
638 | struct ieee80211_sub_if_data *scan_sdata; | 641 | struct ieee80211_sub_if_data *scan_sdata; |
639 | struct ieee80211_channel *oper_channel, *scan_channel, *csa_channel; | 642 | struct ieee80211_channel *oper_channel, *scan_channel, *csa_channel; |
640 | enum nl80211_channel_type oper_channel_type; | 643 | enum nl80211_channel_type oper_channel_type; |
641 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 644 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
642 | size_t scan_ssid_len; | 645 | size_t scan_ssid_len; |
643 | struct list_head bss_list; | 646 | struct list_head bss_list; |
644 | struct ieee80211_bss *bss_hash[STA_HASH_SIZE]; | 647 | struct ieee80211_bss *bss_hash[STA_HASH_SIZE]; |
645 | spinlock_t bss_lock; | 648 | spinlock_t bss_lock; |
646 | 649 | ||
647 | /* SNMP counters */ | 650 | /* SNMP counters */ |
648 | /* dot11CountersTable */ | 651 | /* dot11CountersTable */ |
649 | u32 dot11TransmittedFragmentCount; | 652 | u32 dot11TransmittedFragmentCount; |
650 | u32 dot11MulticastTransmittedFrameCount; | 653 | u32 dot11MulticastTransmittedFrameCount; |
651 | u32 dot11FailedCount; | 654 | u32 dot11FailedCount; |
652 | u32 dot11RetryCount; | 655 | u32 dot11RetryCount; |
653 | u32 dot11MultipleRetryCount; | 656 | u32 dot11MultipleRetryCount; |
654 | u32 dot11FrameDuplicateCount; | 657 | u32 dot11FrameDuplicateCount; |
655 | u32 dot11ReceivedFragmentCount; | 658 | u32 dot11ReceivedFragmentCount; |
656 | u32 dot11MulticastReceivedFrameCount; | 659 | u32 dot11MulticastReceivedFrameCount; |
657 | u32 dot11TransmittedFrameCount; | 660 | u32 dot11TransmittedFrameCount; |
658 | 661 | ||
659 | #ifdef CONFIG_MAC80211_LEDS | 662 | #ifdef CONFIG_MAC80211_LEDS |
660 | int tx_led_counter, rx_led_counter; | 663 | int tx_led_counter, rx_led_counter; |
661 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; | 664 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; |
662 | char tx_led_name[32], rx_led_name[32], | 665 | char tx_led_name[32], rx_led_name[32], |
663 | assoc_led_name[32], radio_led_name[32]; | 666 | assoc_led_name[32], radio_led_name[32]; |
664 | #endif | 667 | #endif |
665 | 668 | ||
666 | #ifdef CONFIG_MAC80211_DEBUGFS | 669 | #ifdef CONFIG_MAC80211_DEBUGFS |
667 | struct work_struct sta_debugfs_add; | 670 | struct work_struct sta_debugfs_add; |
668 | #endif | 671 | #endif |
669 | 672 | ||
670 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 673 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
671 | /* TX/RX handler statistics */ | 674 | /* TX/RX handler statistics */ |
672 | unsigned int tx_handlers_drop; | 675 | unsigned int tx_handlers_drop; |
673 | unsigned int tx_handlers_queued; | 676 | unsigned int tx_handlers_queued; |
674 | unsigned int tx_handlers_drop_unencrypted; | 677 | unsigned int tx_handlers_drop_unencrypted; |
675 | unsigned int tx_handlers_drop_fragment; | 678 | unsigned int tx_handlers_drop_fragment; |
676 | unsigned int tx_handlers_drop_wep; | 679 | unsigned int tx_handlers_drop_wep; |
677 | unsigned int tx_handlers_drop_not_assoc; | 680 | unsigned int tx_handlers_drop_not_assoc; |
678 | unsigned int tx_handlers_drop_unauth_port; | 681 | unsigned int tx_handlers_drop_unauth_port; |
679 | unsigned int rx_handlers_drop; | 682 | unsigned int rx_handlers_drop; |
680 | unsigned int rx_handlers_queued; | 683 | unsigned int rx_handlers_queued; |
681 | unsigned int rx_handlers_drop_nullfunc; | 684 | unsigned int rx_handlers_drop_nullfunc; |
682 | unsigned int rx_handlers_drop_defrag; | 685 | unsigned int rx_handlers_drop_defrag; |
683 | unsigned int rx_handlers_drop_short; | 686 | unsigned int rx_handlers_drop_short; |
684 | unsigned int rx_handlers_drop_passive_scan; | 687 | unsigned int rx_handlers_drop_passive_scan; |
685 | unsigned int tx_expand_skb_head; | 688 | unsigned int tx_expand_skb_head; |
686 | unsigned int tx_expand_skb_head_cloned; | 689 | unsigned int tx_expand_skb_head_cloned; |
687 | unsigned int rx_expand_skb_head; | 690 | unsigned int rx_expand_skb_head; |
688 | unsigned int rx_expand_skb_head2; | 691 | unsigned int rx_expand_skb_head2; |
689 | unsigned int rx_handlers_fragments; | 692 | unsigned int rx_handlers_fragments; |
690 | unsigned int tx_status_drop; | 693 | unsigned int tx_status_drop; |
691 | #define I802_DEBUG_INC(c) (c)++ | 694 | #define I802_DEBUG_INC(c) (c)++ |
692 | #else /* CONFIG_MAC80211_DEBUG_COUNTERS */ | 695 | #else /* CONFIG_MAC80211_DEBUG_COUNTERS */ |
693 | #define I802_DEBUG_INC(c) do { } while (0) | 696 | #define I802_DEBUG_INC(c) do { } while (0) |
694 | #endif /* CONFIG_MAC80211_DEBUG_COUNTERS */ | 697 | #endif /* CONFIG_MAC80211_DEBUG_COUNTERS */ |
695 | 698 | ||
696 | 699 | ||
697 | int total_ps_buffered; /* total number of all buffered unicast and | 700 | int total_ps_buffered; /* total number of all buffered unicast and |
698 | * multicast packets for power saving stations | 701 | * multicast packets for power saving stations |
699 | */ | 702 | */ |
700 | int wifi_wme_noack_test; | 703 | int wifi_wme_noack_test; |
701 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 704 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
702 | 705 | ||
703 | bool powersave; | 706 | bool powersave; |
704 | struct work_struct dynamic_ps_enable_work; | 707 | struct work_struct dynamic_ps_enable_work; |
705 | struct work_struct dynamic_ps_disable_work; | 708 | struct work_struct dynamic_ps_disable_work; |
706 | struct timer_list dynamic_ps_timer; | 709 | struct timer_list dynamic_ps_timer; |
707 | 710 | ||
708 | int user_power_level; /* in dBm */ | 711 | int user_power_level; /* in dBm */ |
709 | 712 | ||
710 | #ifdef CONFIG_MAC80211_DEBUGFS | 713 | #ifdef CONFIG_MAC80211_DEBUGFS |
711 | struct local_debugfsdentries { | 714 | struct local_debugfsdentries { |
712 | struct dentry *rcdir; | 715 | struct dentry *rcdir; |
713 | struct dentry *rcname; | 716 | struct dentry *rcname; |
714 | struct dentry *frequency; | 717 | struct dentry *frequency; |
715 | struct dentry *rts_threshold; | 718 | struct dentry *rts_threshold; |
716 | struct dentry *fragmentation_threshold; | 719 | struct dentry *fragmentation_threshold; |
717 | struct dentry *short_retry_limit; | 720 | struct dentry *short_retry_limit; |
718 | struct dentry *long_retry_limit; | 721 | struct dentry *long_retry_limit; |
719 | struct dentry *total_ps_buffered; | 722 | struct dentry *total_ps_buffered; |
720 | struct dentry *wep_iv; | 723 | struct dentry *wep_iv; |
721 | struct dentry *statistics; | 724 | struct dentry *statistics; |
722 | struct local_debugfsdentries_statsdentries { | 725 | struct local_debugfsdentries_statsdentries { |
723 | struct dentry *transmitted_fragment_count; | 726 | struct dentry *transmitted_fragment_count; |
724 | struct dentry *multicast_transmitted_frame_count; | 727 | struct dentry *multicast_transmitted_frame_count; |
725 | struct dentry *failed_count; | 728 | struct dentry *failed_count; |
726 | struct dentry *retry_count; | 729 | struct dentry *retry_count; |
727 | struct dentry *multiple_retry_count; | 730 | struct dentry *multiple_retry_count; |
728 | struct dentry *frame_duplicate_count; | 731 | struct dentry *frame_duplicate_count; |
729 | struct dentry *received_fragment_count; | 732 | struct dentry *received_fragment_count; |
730 | struct dentry *multicast_received_frame_count; | 733 | struct dentry *multicast_received_frame_count; |
731 | struct dentry *transmitted_frame_count; | 734 | struct dentry *transmitted_frame_count; |
732 | struct dentry *wep_undecryptable_count; | 735 | struct dentry *wep_undecryptable_count; |
733 | struct dentry *num_scans; | 736 | struct dentry *num_scans; |
734 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 737 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
735 | struct dentry *tx_handlers_drop; | 738 | struct dentry *tx_handlers_drop; |
736 | struct dentry *tx_handlers_queued; | 739 | struct dentry *tx_handlers_queued; |
737 | struct dentry *tx_handlers_drop_unencrypted; | 740 | struct dentry *tx_handlers_drop_unencrypted; |
738 | struct dentry *tx_handlers_drop_fragment; | 741 | struct dentry *tx_handlers_drop_fragment; |
739 | struct dentry *tx_handlers_drop_wep; | 742 | struct dentry *tx_handlers_drop_wep; |
740 | struct dentry *tx_handlers_drop_not_assoc; | 743 | struct dentry *tx_handlers_drop_not_assoc; |
741 | struct dentry *tx_handlers_drop_unauth_port; | 744 | struct dentry *tx_handlers_drop_unauth_port; |
742 | struct dentry *rx_handlers_drop; | 745 | struct dentry *rx_handlers_drop; |
743 | struct dentry *rx_handlers_queued; | 746 | struct dentry *rx_handlers_queued; |
744 | struct dentry *rx_handlers_drop_nullfunc; | 747 | struct dentry *rx_handlers_drop_nullfunc; |
745 | struct dentry *rx_handlers_drop_defrag; | 748 | struct dentry *rx_handlers_drop_defrag; |
746 | struct dentry *rx_handlers_drop_short; | 749 | struct dentry *rx_handlers_drop_short; |
747 | struct dentry *rx_handlers_drop_passive_scan; | 750 | struct dentry *rx_handlers_drop_passive_scan; |
748 | struct dentry *tx_expand_skb_head; | 751 | struct dentry *tx_expand_skb_head; |
749 | struct dentry *tx_expand_skb_head_cloned; | 752 | struct dentry *tx_expand_skb_head_cloned; |
750 | struct dentry *rx_expand_skb_head; | 753 | struct dentry *rx_expand_skb_head; |
751 | struct dentry *rx_expand_skb_head2; | 754 | struct dentry *rx_expand_skb_head2; |
752 | struct dentry *rx_handlers_fragments; | 755 | struct dentry *rx_handlers_fragments; |
753 | struct dentry *tx_status_drop; | 756 | struct dentry *tx_status_drop; |
754 | #endif | 757 | #endif |
755 | struct dentry *dot11ACKFailureCount; | 758 | struct dentry *dot11ACKFailureCount; |
756 | struct dentry *dot11RTSFailureCount; | 759 | struct dentry *dot11RTSFailureCount; |
757 | struct dentry *dot11FCSErrorCount; | 760 | struct dentry *dot11FCSErrorCount; |
758 | struct dentry *dot11RTSSuccessCount; | 761 | struct dentry *dot11RTSSuccessCount; |
759 | } stats; | 762 | } stats; |
760 | struct dentry *stations; | 763 | struct dentry *stations; |
761 | struct dentry *keys; | 764 | struct dentry *keys; |
762 | } debugfs; | 765 | } debugfs; |
763 | #endif | 766 | #endif |
764 | }; | 767 | }; |
765 | 768 | ||
766 | static inline struct ieee80211_sub_if_data * | 769 | static inline struct ieee80211_sub_if_data * |
767 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | 770 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) |
768 | { | 771 | { |
769 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 772 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
770 | 773 | ||
771 | BUG_ON(!local || local->mdev == dev); | 774 | BUG_ON(!local || local->mdev == dev); |
772 | 775 | ||
773 | return netdev_priv(dev); | 776 | return netdev_priv(dev); |
774 | } | 777 | } |
775 | 778 | ||
776 | /* this struct represents 802.11n's RA/TID combination */ | 779 | /* this struct represents 802.11n's RA/TID combination */ |
777 | struct ieee80211_ra_tid { | 780 | struct ieee80211_ra_tid { |
778 | u8 ra[ETH_ALEN]; | 781 | u8 ra[ETH_ALEN]; |
779 | u16 tid; | 782 | u16 tid; |
780 | }; | 783 | }; |
781 | 784 | ||
782 | /* Parsed Information Elements */ | 785 | /* Parsed Information Elements */ |
783 | struct ieee802_11_elems { | 786 | struct ieee802_11_elems { |
784 | u8 *ie_start; | 787 | u8 *ie_start; |
785 | size_t total_len; | 788 | size_t total_len; |
786 | 789 | ||
787 | /* pointers to IEs */ | 790 | /* pointers to IEs */ |
788 | u8 *ssid; | 791 | u8 *ssid; |
789 | u8 *supp_rates; | 792 | u8 *supp_rates; |
790 | u8 *fh_params; | 793 | u8 *fh_params; |
791 | u8 *ds_params; | 794 | u8 *ds_params; |
792 | u8 *cf_params; | 795 | u8 *cf_params; |
793 | u8 *tim; | 796 | u8 *tim; |
794 | u8 *ibss_params; | 797 | u8 *ibss_params; |
795 | u8 *challenge; | 798 | u8 *challenge; |
796 | u8 *wpa; | 799 | u8 *wpa; |
797 | u8 *rsn; | 800 | u8 *rsn; |
798 | u8 *erp_info; | 801 | u8 *erp_info; |
799 | u8 *ext_supp_rates; | 802 | u8 *ext_supp_rates; |
800 | u8 *wmm_info; | 803 | u8 *wmm_info; |
801 | u8 *wmm_param; | 804 | u8 *wmm_param; |
802 | struct ieee80211_ht_cap *ht_cap_elem; | 805 | struct ieee80211_ht_cap *ht_cap_elem; |
803 | struct ieee80211_ht_info *ht_info_elem; | 806 | struct ieee80211_ht_info *ht_info_elem; |
804 | u8 *mesh_config; | 807 | u8 *mesh_config; |
805 | u8 *mesh_id; | 808 | u8 *mesh_id; |
806 | u8 *peer_link; | 809 | u8 *peer_link; |
807 | u8 *preq; | 810 | u8 *preq; |
808 | u8 *prep; | 811 | u8 *prep; |
809 | u8 *perr; | 812 | u8 *perr; |
810 | u8 *ch_switch_elem; | 813 | u8 *ch_switch_elem; |
811 | u8 *country_elem; | 814 | u8 *country_elem; |
812 | u8 *pwr_constr_elem; | 815 | u8 *pwr_constr_elem; |
813 | u8 *quiet_elem; /* first quite element */ | 816 | u8 *quiet_elem; /* first quite element */ |
814 | 817 | ||
815 | /* length of them, respectively */ | 818 | /* length of them, respectively */ |
816 | u8 ssid_len; | 819 | u8 ssid_len; |
817 | u8 supp_rates_len; | 820 | u8 supp_rates_len; |
818 | u8 fh_params_len; | 821 | u8 fh_params_len; |
819 | u8 ds_params_len; | 822 | u8 ds_params_len; |
820 | u8 cf_params_len; | 823 | u8 cf_params_len; |
821 | u8 tim_len; | 824 | u8 tim_len; |
822 | u8 ibss_params_len; | 825 | u8 ibss_params_len; |
823 | u8 challenge_len; | 826 | u8 challenge_len; |
824 | u8 wpa_len; | 827 | u8 wpa_len; |
825 | u8 rsn_len; | 828 | u8 rsn_len; |
826 | u8 erp_info_len; | 829 | u8 erp_info_len; |
827 | u8 ext_supp_rates_len; | 830 | u8 ext_supp_rates_len; |
828 | u8 wmm_info_len; | 831 | u8 wmm_info_len; |
829 | u8 wmm_param_len; | 832 | u8 wmm_param_len; |
830 | u8 mesh_config_len; | 833 | u8 mesh_config_len; |
831 | u8 mesh_id_len; | 834 | u8 mesh_id_len; |
832 | u8 peer_link_len; | 835 | u8 peer_link_len; |
833 | u8 preq_len; | 836 | u8 preq_len; |
834 | u8 prep_len; | 837 | u8 prep_len; |
835 | u8 perr_len; | 838 | u8 perr_len; |
836 | u8 ch_switch_elem_len; | 839 | u8 ch_switch_elem_len; |
837 | u8 country_elem_len; | 840 | u8 country_elem_len; |
838 | u8 pwr_constr_elem_len; | 841 | u8 pwr_constr_elem_len; |
839 | u8 quiet_elem_len; | 842 | u8 quiet_elem_len; |
840 | u8 num_of_quiet_elem; /* can be more the one */ | 843 | u8 num_of_quiet_elem; /* can be more the one */ |
841 | }; | 844 | }; |
842 | 845 | ||
843 | static inline struct ieee80211_local *hw_to_local( | 846 | static inline struct ieee80211_local *hw_to_local( |
844 | struct ieee80211_hw *hw) | 847 | struct ieee80211_hw *hw) |
845 | { | 848 | { |
846 | return container_of(hw, struct ieee80211_local, hw); | 849 | return container_of(hw, struct ieee80211_local, hw); |
847 | } | 850 | } |
848 | 851 | ||
849 | static inline struct ieee80211_hw *local_to_hw( | 852 | static inline struct ieee80211_hw *local_to_hw( |
850 | struct ieee80211_local *local) | 853 | struct ieee80211_local *local) |
851 | { | 854 | { |
852 | return &local->hw; | 855 | return &local->hw; |
853 | } | 856 | } |
854 | 857 | ||
855 | 858 | ||
856 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | 859 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) |
857 | { | 860 | { |
858 | return compare_ether_addr(raddr, addr) == 0 || | 861 | return compare_ether_addr(raddr, addr) == 0 || |
859 | is_broadcast_ether_addr(raddr); | 862 | is_broadcast_ether_addr(raddr); |
860 | } | 863 | } |
861 | 864 | ||
862 | 865 | ||
863 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); | 866 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); |
864 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); | 867 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); |
865 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 868 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
866 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 869 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, |
867 | u32 changed); | 870 | u32 changed); |
868 | void ieee80211_configure_filter(struct ieee80211_local *local); | 871 | void ieee80211_configure_filter(struct ieee80211_local *local); |
869 | 872 | ||
870 | /* wireless extensions */ | 873 | /* wireless extensions */ |
871 | extern const struct iw_handler_def ieee80211_iw_handler_def; | 874 | extern const struct iw_handler_def ieee80211_iw_handler_def; |
872 | 875 | ||
873 | /* STA/IBSS code */ | 876 | /* STA/IBSS code */ |
874 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); | 877 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
875 | void ieee80211_scan_work(struct work_struct *work); | 878 | void ieee80211_scan_work(struct work_struct *work); |
876 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 879 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
877 | struct ieee80211_rx_status *rx_status); | 880 | struct ieee80211_rx_status *rx_status); |
878 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); | 881 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); |
879 | int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); | 882 | int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); |
880 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); | 883 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); |
881 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, | 884 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, |
882 | struct ieee80211_if_sta *ifsta); | 885 | struct ieee80211_if_sta *ifsta); |
883 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 886 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
884 | u8 *bssid, u8 *addr, u64 supp_rates); | 887 | u8 *bssid, u8 *addr, u64 supp_rates); |
885 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); | 888 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); |
886 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); | 889 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); |
887 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 890 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
888 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 891 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, |
889 | struct ieee802_11_elems *elems, | 892 | struct ieee802_11_elems *elems, |
890 | enum ieee80211_band band); | 893 | enum ieee80211_band band); |
891 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 894 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
892 | u8 *ssid, size_t ssid_len); | 895 | u8 *ssid, size_t ssid_len); |
893 | 896 | ||
894 | /* scan/BSS handling */ | 897 | /* scan/BSS handling */ |
895 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 898 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
896 | u8 *ssid, size_t ssid_len); | 899 | u8 *ssid, size_t ssid_len); |
897 | int ieee80211_scan_results(struct ieee80211_local *local, | 900 | int ieee80211_scan_results(struct ieee80211_local *local, |
898 | struct iw_request_info *info, | 901 | struct iw_request_info *info, |
899 | char *buf, size_t len); | 902 | char *buf, size_t len); |
900 | ieee80211_rx_result | 903 | ieee80211_rx_result |
901 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, | 904 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, |
902 | struct sk_buff *skb, | 905 | struct sk_buff *skb, |
903 | struct ieee80211_rx_status *rx_status); | 906 | struct ieee80211_rx_status *rx_status); |
904 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); | 907 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); |
905 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); | 908 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); |
906 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, | 909 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, |
907 | char *ie, size_t len); | 910 | char *ie, size_t len); |
908 | 911 | ||
909 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | 912 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); |
910 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | 913 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, |
911 | u8 *ssid, size_t ssid_len); | 914 | u8 *ssid, size_t ssid_len); |
912 | struct ieee80211_bss * | 915 | struct ieee80211_bss * |
913 | ieee80211_bss_info_update(struct ieee80211_local *local, | 916 | ieee80211_bss_info_update(struct ieee80211_local *local, |
914 | struct ieee80211_rx_status *rx_status, | 917 | struct ieee80211_rx_status *rx_status, |
915 | struct ieee80211_mgmt *mgmt, | 918 | struct ieee80211_mgmt *mgmt, |
916 | size_t len, | 919 | size_t len, |
917 | struct ieee802_11_elems *elems, | 920 | struct ieee802_11_elems *elems, |
918 | int freq, bool beacon); | 921 | int freq, bool beacon); |
919 | struct ieee80211_bss * | 922 | struct ieee80211_bss * |
920 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | 923 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, |
921 | u8 *ssid, u8 ssid_len); | 924 | u8 *ssid, u8 ssid_len); |
922 | struct ieee80211_bss * | 925 | struct ieee80211_bss * |
923 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 926 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
924 | u8 *ssid, u8 ssid_len); | 927 | u8 *ssid, u8 ssid_len); |
925 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 928 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
926 | struct ieee80211_bss *bss); | 929 | struct ieee80211_bss *bss); |
927 | 930 | ||
928 | /* interface handling */ | 931 | /* interface handling */ |
929 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 932 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
930 | struct net_device **new_dev, enum nl80211_iftype type, | 933 | struct net_device **new_dev, enum nl80211_iftype type, |
931 | struct vif_params *params); | 934 | struct vif_params *params); |
932 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 935 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
933 | enum nl80211_iftype type); | 936 | enum nl80211_iftype type); |
934 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | 937 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
935 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 938 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
936 | 939 | ||
937 | /* tx handling */ | 940 | /* tx handling */ |
938 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 941 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
939 | void ieee80211_tx_pending(unsigned long data); | 942 | void ieee80211_tx_pending(unsigned long data); |
940 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); | 943 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); |
941 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | 944 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); |
942 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | 945 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); |
943 | 946 | ||
944 | /* HT */ | 947 | /* HT */ |
945 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 948 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, |
946 | struct ieee80211_ht_cap *ht_cap_ie, | 949 | struct ieee80211_ht_cap *ht_cap_ie, |
947 | struct ieee80211_sta_ht_cap *ht_cap); | 950 | struct ieee80211_sta_ht_cap *ht_cap); |
948 | u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | 951 | u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, |
949 | struct ieee80211_ht_info *hti, | 952 | struct ieee80211_ht_info *hti, |
950 | u16 ap_ht_cap_flags); | 953 | u16 ap_ht_cap_flags); |
951 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); | 954 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); |
952 | 955 | ||
953 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | 956 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, |
954 | u16 tid, u16 initiator, u16 reason); | 957 | u16 tid, u16 initiator, u16 reason); |
955 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); | 958 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); |
956 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 959 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
957 | struct sta_info *sta, | 960 | struct sta_info *sta, |
958 | struct ieee80211_mgmt *mgmt, size_t len); | 961 | struct ieee80211_mgmt *mgmt, size_t len); |
959 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | 962 | void ieee80211_process_addba_resp(struct ieee80211_local *local, |
960 | struct sta_info *sta, | 963 | struct sta_info *sta, |
961 | struct ieee80211_mgmt *mgmt, | 964 | struct ieee80211_mgmt *mgmt, |
962 | size_t len); | 965 | size_t len); |
963 | void ieee80211_process_addba_request(struct ieee80211_local *local, | 966 | void ieee80211_process_addba_request(struct ieee80211_local *local, |
964 | struct sta_info *sta, | 967 | struct sta_info *sta, |
965 | struct ieee80211_mgmt *mgmt, | 968 | struct ieee80211_mgmt *mgmt, |
966 | size_t len); | 969 | size_t len); |
967 | 970 | ||
968 | /* Spectrum management */ | 971 | /* Spectrum management */ |
969 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 972 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
970 | struct ieee80211_mgmt *mgmt, | 973 | struct ieee80211_mgmt *mgmt, |
971 | size_t len); | 974 | size_t len); |
972 | void ieee80211_chswitch_timer(unsigned long data); | 975 | void ieee80211_chswitch_timer(unsigned long data); |
973 | void ieee80211_chswitch_work(struct work_struct *work); | 976 | void ieee80211_chswitch_work(struct work_struct *work); |
974 | void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 977 | void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
975 | struct ieee80211_channel_sw_ie *sw_elem, | 978 | struct ieee80211_channel_sw_ie *sw_elem, |
976 | struct ieee80211_bss *bss); | 979 | struct ieee80211_bss *bss); |
977 | 980 | ||
978 | /* utility functions/constants */ | 981 | /* utility functions/constants */ |
979 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 982 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
980 | extern const unsigned char rfc1042_header[6]; | 983 | extern const unsigned char rfc1042_header[6]; |
981 | extern const unsigned char bridge_tunnel_header[6]; | 984 | extern const unsigned char bridge_tunnel_header[6]; |
982 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 985 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
983 | enum nl80211_iftype type); | 986 | enum nl80211_iftype type); |
984 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 987 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, |
985 | int rate, int erp, int short_preamble); | 988 | int rate, int erp, int short_preamble); |
986 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | 989 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
987 | struct ieee80211_hdr *hdr); | 990 | struct ieee80211_hdr *hdr); |
988 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 991 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); |
989 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 992 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
990 | int encrypt); | 993 | int encrypt); |
991 | void ieee802_11_parse_elems(u8 *start, size_t len, | 994 | void ieee802_11_parse_elems(u8 *start, size_t len, |
992 | struct ieee802_11_elems *elems); | 995 | struct ieee802_11_elems *elems); |
993 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); | 996 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); |
994 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | 997 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, |
995 | enum ieee80211_band band); | 998 | enum ieee80211_band band); |
996 | 999 | ||
997 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); | 1000 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); |
998 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); | 1001 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); |
999 | void ieee80211_dynamic_ps_timer(unsigned long data); | 1002 | void ieee80211_dynamic_ps_timer(unsigned long data); |
1000 | void ieee80211_send_nullfunc(struct ieee80211_local *local, | 1003 | void ieee80211_send_nullfunc(struct ieee80211_local *local, |
1001 | struct ieee80211_sub_if_data *sdata, | 1004 | struct ieee80211_sub_if_data *sdata, |
1002 | int powersave); | 1005 | int powersave); |
1003 | 1006 | ||
1004 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1007 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1005 | enum queue_stop_reason reason); | 1008 | enum queue_stop_reason reason); |
1006 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 1009 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
1007 | enum queue_stop_reason reason); | 1010 | enum queue_stop_reason reason); |
1008 | 1011 | ||
1009 | #ifdef CONFIG_MAC80211_NOINLINE | 1012 | #ifdef CONFIG_MAC80211_NOINLINE |
1010 | #define debug_noinline noinline | 1013 | #define debug_noinline noinline |
1011 | #else | 1014 | #else |
1012 | #define debug_noinline | 1015 | #define debug_noinline |
1013 | #endif | 1016 | #endif |
1014 | 1017 | ||
1015 | #endif /* IEEE80211_I_H */ | 1018 | #endif /* IEEE80211_I_H */ |
1016 | 1019 |
net/mac80211/key.c
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, 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 | #include <linux/if_ether.h> | 12 | #include <linux/if_ether.h> |
13 | #include <linux/etherdevice.h> | 13 | #include <linux/etherdevice.h> |
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | #include <linux/rcupdate.h> | 15 | #include <linux/rcupdate.h> |
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "debugfs_key.h" | 19 | #include "debugfs_key.h" |
20 | #include "aes_ccm.h" | 20 | #include "aes_ccm.h" |
21 | #include "aes_cmac.h" | ||
21 | 22 | ||
22 | 23 | ||
23 | /** | 24 | /** |
24 | * DOC: Key handling basics | 25 | * DOC: Key handling basics |
25 | * | 26 | * |
26 | * Key handling in mac80211 is done based on per-interface (sub_if_data) | 27 | * Key handling in mac80211 is done based on per-interface (sub_if_data) |
27 | * keys and per-station keys. Since each station belongs to an interface, | 28 | * keys and per-station keys. Since each station belongs to an interface, |
28 | * each station key also belongs to that interface. | 29 | * each station key also belongs to that interface. |
29 | * | 30 | * |
30 | * Hardware acceleration is done on a best-effort basis, for each key | 31 | * Hardware acceleration is done on a best-effort basis, for each key |
31 | * that is eligible the hardware is asked to enable that key but if | 32 | * that is eligible the hardware is asked to enable that key but if |
32 | * it cannot do that they key is simply kept for software encryption. | 33 | * it cannot do that they key is simply kept for software encryption. |
33 | * There is currently no way of knowing this except by looking into | 34 | * There is currently no way of knowing this except by looking into |
34 | * debugfs. | 35 | * debugfs. |
35 | * | 36 | * |
36 | * All key operations are protected internally so you can call them at | 37 | * All key operations are protected internally so you can call them at |
37 | * any time. | 38 | * any time. |
38 | * | 39 | * |
39 | * Within mac80211, key references are, just as STA structure references, | 40 | * Within mac80211, key references are, just as STA structure references, |
40 | * protected by RCU. Note, however, that some things are unprotected, | 41 | * protected by RCU. Note, however, that some things are unprotected, |
41 | * namely the key->sta dereferences within the hardware acceleration | 42 | * namely the key->sta dereferences within the hardware acceleration |
42 | * functions. This means that sta_info_destroy() must flush the key todo | 43 | * functions. This means that sta_info_destroy() must flush the key todo |
43 | * list. | 44 | * list. |
44 | * | 45 | * |
45 | * All the direct key list manipulation functions must not sleep because | 46 | * All the direct key list manipulation functions must not sleep because |
46 | * they can operate on STA info structs that are protected by RCU. | 47 | * they can operate on STA info structs that are protected by RCU. |
47 | */ | 48 | */ |
48 | 49 | ||
49 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 50 | static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
50 | 51 | ||
51 | /* key mutex: used to synchronise todo runners */ | 52 | /* key mutex: used to synchronise todo runners */ |
52 | static DEFINE_MUTEX(key_mutex); | 53 | static DEFINE_MUTEX(key_mutex); |
53 | static DEFINE_SPINLOCK(todo_lock); | 54 | static DEFINE_SPINLOCK(todo_lock); |
54 | static LIST_HEAD(todo_list); | 55 | static LIST_HEAD(todo_list); |
55 | 56 | ||
56 | static void key_todo(struct work_struct *work) | 57 | static void key_todo(struct work_struct *work) |
57 | { | 58 | { |
58 | ieee80211_key_todo(); | 59 | ieee80211_key_todo(); |
59 | } | 60 | } |
60 | 61 | ||
61 | static DECLARE_WORK(todo_work, key_todo); | 62 | static DECLARE_WORK(todo_work, key_todo); |
62 | 63 | ||
63 | /** | 64 | /** |
64 | * add_todo - add todo item for a key | 65 | * add_todo - add todo item for a key |
65 | * | 66 | * |
66 | * @key: key to add to do item for | 67 | * @key: key to add to do item for |
67 | * @flag: todo flag(s) | 68 | * @flag: todo flag(s) |
68 | */ | 69 | */ |
69 | static void add_todo(struct ieee80211_key *key, u32 flag) | 70 | static void add_todo(struct ieee80211_key *key, u32 flag) |
70 | { | 71 | { |
71 | if (!key) | 72 | if (!key) |
72 | return; | 73 | return; |
73 | 74 | ||
74 | spin_lock(&todo_lock); | 75 | spin_lock(&todo_lock); |
75 | key->flags |= flag; | 76 | key->flags |= flag; |
76 | /* | 77 | /* |
77 | * Remove again if already on the list so that we move it to the end. | 78 | * Remove again if already on the list so that we move it to the end. |
78 | */ | 79 | */ |
79 | if (!list_empty(&key->todo)) | 80 | if (!list_empty(&key->todo)) |
80 | list_del(&key->todo); | 81 | list_del(&key->todo); |
81 | list_add_tail(&key->todo, &todo_list); | 82 | list_add_tail(&key->todo, &todo_list); |
82 | schedule_work(&todo_work); | 83 | schedule_work(&todo_work); |
83 | spin_unlock(&todo_lock); | 84 | spin_unlock(&todo_lock); |
84 | } | 85 | } |
85 | 86 | ||
86 | /** | 87 | /** |
87 | * ieee80211_key_lock - lock the mac80211 key operation lock | 88 | * ieee80211_key_lock - lock the mac80211 key operation lock |
88 | * | 89 | * |
89 | * This locks the (global) mac80211 key operation lock, all | 90 | * This locks the (global) mac80211 key operation lock, all |
90 | * key operations must be done under this lock. | 91 | * key operations must be done under this lock. |
91 | */ | 92 | */ |
92 | static void ieee80211_key_lock(void) | 93 | static void ieee80211_key_lock(void) |
93 | { | 94 | { |
94 | mutex_lock(&key_mutex); | 95 | mutex_lock(&key_mutex); |
95 | } | 96 | } |
96 | 97 | ||
97 | /** | 98 | /** |
98 | * ieee80211_key_unlock - unlock the mac80211 key operation lock | 99 | * ieee80211_key_unlock - unlock the mac80211 key operation lock |
99 | */ | 100 | */ |
100 | static void ieee80211_key_unlock(void) | 101 | static void ieee80211_key_unlock(void) |
101 | { | 102 | { |
102 | mutex_unlock(&key_mutex); | 103 | mutex_unlock(&key_mutex); |
103 | } | 104 | } |
104 | 105 | ||
105 | static void assert_key_lock(void) | 106 | static void assert_key_lock(void) |
106 | { | 107 | { |
107 | WARN_ON(!mutex_is_locked(&key_mutex)); | 108 | WARN_ON(!mutex_is_locked(&key_mutex)); |
108 | } | 109 | } |
109 | 110 | ||
110 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) | 111 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) |
111 | { | 112 | { |
112 | if (key->sta) | 113 | if (key->sta) |
113 | return &key->sta->sta; | 114 | return &key->sta->sta; |
114 | 115 | ||
115 | return NULL; | 116 | return NULL; |
116 | } | 117 | } |
117 | 118 | ||
118 | static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | 119 | static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
119 | { | 120 | { |
120 | struct ieee80211_sub_if_data *sdata; | 121 | struct ieee80211_sub_if_data *sdata; |
121 | struct ieee80211_sta *sta; | 122 | struct ieee80211_sta *sta; |
122 | int ret; | 123 | int ret; |
123 | 124 | ||
124 | assert_key_lock(); | 125 | assert_key_lock(); |
125 | might_sleep(); | 126 | might_sleep(); |
126 | 127 | ||
127 | if (!key->local->ops->set_key) | 128 | if (!key->local->ops->set_key) |
128 | return; | 129 | return; |
129 | 130 | ||
130 | sta = get_sta_for_key(key); | 131 | sta = get_sta_for_key(key); |
131 | 132 | ||
132 | sdata = key->sdata; | 133 | sdata = key->sdata; |
133 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 134 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
134 | sdata = container_of(sdata->bss, | 135 | sdata = container_of(sdata->bss, |
135 | struct ieee80211_sub_if_data, | 136 | struct ieee80211_sub_if_data, |
136 | u.ap); | 137 | u.ap); |
137 | 138 | ||
138 | ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, | 139 | ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, |
139 | &sdata->vif, sta, &key->conf); | 140 | &sdata->vif, sta, &key->conf); |
140 | 141 | ||
141 | if (!ret) { | 142 | if (!ret) { |
142 | spin_lock(&todo_lock); | 143 | spin_lock(&todo_lock); |
143 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 144 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
144 | spin_unlock(&todo_lock); | 145 | spin_unlock(&todo_lock); |
145 | } | 146 | } |
146 | 147 | ||
147 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) | 148 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) |
148 | printk(KERN_ERR "mac80211-%s: failed to set key " | 149 | printk(KERN_ERR "mac80211-%s: failed to set key " |
149 | "(%d, %pM) to hardware (%d)\n", | 150 | "(%d, %pM) to hardware (%d)\n", |
150 | wiphy_name(key->local->hw.wiphy), | 151 | wiphy_name(key->local->hw.wiphy), |
151 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 152 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
152 | } | 153 | } |
153 | 154 | ||
154 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | 155 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) |
155 | { | 156 | { |
156 | struct ieee80211_sub_if_data *sdata; | 157 | struct ieee80211_sub_if_data *sdata; |
157 | struct ieee80211_sta *sta; | 158 | struct ieee80211_sta *sta; |
158 | int ret; | 159 | int ret; |
159 | 160 | ||
160 | assert_key_lock(); | 161 | assert_key_lock(); |
161 | might_sleep(); | 162 | might_sleep(); |
162 | 163 | ||
163 | if (!key || !key->local->ops->set_key) | 164 | if (!key || !key->local->ops->set_key) |
164 | return; | 165 | return; |
165 | 166 | ||
166 | spin_lock(&todo_lock); | 167 | spin_lock(&todo_lock); |
167 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { | 168 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
168 | spin_unlock(&todo_lock); | 169 | spin_unlock(&todo_lock); |
169 | return; | 170 | return; |
170 | } | 171 | } |
171 | spin_unlock(&todo_lock); | 172 | spin_unlock(&todo_lock); |
172 | 173 | ||
173 | sta = get_sta_for_key(key); | 174 | sta = get_sta_for_key(key); |
174 | sdata = key->sdata; | 175 | sdata = key->sdata; |
175 | 176 | ||
176 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 177 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
177 | sdata = container_of(sdata->bss, | 178 | sdata = container_of(sdata->bss, |
178 | struct ieee80211_sub_if_data, | 179 | struct ieee80211_sub_if_data, |
179 | u.ap); | 180 | u.ap); |
180 | 181 | ||
181 | ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, | 182 | ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, |
182 | &sdata->vif, sta, &key->conf); | 183 | &sdata->vif, sta, &key->conf); |
183 | 184 | ||
184 | if (ret) | 185 | if (ret) |
185 | printk(KERN_ERR "mac80211-%s: failed to remove key " | 186 | printk(KERN_ERR "mac80211-%s: failed to remove key " |
186 | "(%d, %pM) from hardware (%d)\n", | 187 | "(%d, %pM) from hardware (%d)\n", |
187 | wiphy_name(key->local->hw.wiphy), | 188 | wiphy_name(key->local->hw.wiphy), |
188 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 189 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
189 | 190 | ||
190 | spin_lock(&todo_lock); | 191 | spin_lock(&todo_lock); |
191 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 192 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
192 | spin_unlock(&todo_lock); | 193 | spin_unlock(&todo_lock); |
193 | } | 194 | } |
194 | 195 | ||
195 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 196 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
196 | int idx) | 197 | int idx) |
197 | { | 198 | { |
198 | struct ieee80211_key *key = NULL; | 199 | struct ieee80211_key *key = NULL; |
199 | 200 | ||
200 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) | 201 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) |
201 | key = sdata->keys[idx]; | 202 | key = sdata->keys[idx]; |
202 | 203 | ||
203 | rcu_assign_pointer(sdata->default_key, key); | 204 | rcu_assign_pointer(sdata->default_key, key); |
204 | 205 | ||
205 | if (key) | 206 | if (key) |
206 | add_todo(key, KEY_FLAG_TODO_DEFKEY); | 207 | add_todo(key, KEY_FLAG_TODO_DEFKEY); |
207 | } | 208 | } |
208 | 209 | ||
209 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) | 210 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) |
210 | { | 211 | { |
211 | unsigned long flags; | 212 | unsigned long flags; |
212 | 213 | ||
213 | spin_lock_irqsave(&sdata->local->key_lock, flags); | 214 | spin_lock_irqsave(&sdata->local->key_lock, flags); |
214 | __ieee80211_set_default_key(sdata, idx); | 215 | __ieee80211_set_default_key(sdata, idx); |
215 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | 216 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
216 | } | 217 | } |
217 | 218 | ||
219 | static void | ||
220 | __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) | ||
221 | { | ||
222 | struct ieee80211_key *key = NULL; | ||
218 | 223 | ||
224 | if (idx >= NUM_DEFAULT_KEYS && | ||
225 | idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
226 | key = sdata->keys[idx]; | ||
227 | |||
228 | rcu_assign_pointer(sdata->default_mgmt_key, key); | ||
229 | |||
230 | if (key) | ||
231 | add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY); | ||
232 | } | ||
233 | |||
234 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | ||
235 | int idx) | ||
236 | { | ||
237 | unsigned long flags; | ||
238 | |||
239 | spin_lock_irqsave(&sdata->local->key_lock, flags); | ||
240 | __ieee80211_set_default_mgmt_key(sdata, idx); | ||
241 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | ||
242 | } | ||
243 | |||
244 | |||
219 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | 245 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, |
220 | struct sta_info *sta, | 246 | struct sta_info *sta, |
221 | struct ieee80211_key *old, | 247 | struct ieee80211_key *old, |
222 | struct ieee80211_key *new) | 248 | struct ieee80211_key *new) |
223 | { | 249 | { |
224 | int idx, defkey; | 250 | int idx, defkey, defmgmtkey; |
225 | 251 | ||
226 | if (new) | 252 | if (new) |
227 | list_add(&new->list, &sdata->key_list); | 253 | list_add(&new->list, &sdata->key_list); |
228 | 254 | ||
229 | if (sta) { | 255 | if (sta) { |
230 | rcu_assign_pointer(sta->key, new); | 256 | rcu_assign_pointer(sta->key, new); |
231 | } else { | 257 | } else { |
232 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); | 258 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); |
233 | 259 | ||
234 | if (old) | 260 | if (old) |
235 | idx = old->conf.keyidx; | 261 | idx = old->conf.keyidx; |
236 | else | 262 | else |
237 | idx = new->conf.keyidx; | 263 | idx = new->conf.keyidx; |
238 | 264 | ||
239 | defkey = old && sdata->default_key == old; | 265 | defkey = old && sdata->default_key == old; |
266 | defmgmtkey = old && sdata->default_mgmt_key == old; | ||
240 | 267 | ||
241 | if (defkey && !new) | 268 | if (defkey && !new) |
242 | __ieee80211_set_default_key(sdata, -1); | 269 | __ieee80211_set_default_key(sdata, -1); |
270 | if (defmgmtkey && !new) | ||
271 | __ieee80211_set_default_mgmt_key(sdata, -1); | ||
243 | 272 | ||
244 | rcu_assign_pointer(sdata->keys[idx], new); | 273 | rcu_assign_pointer(sdata->keys[idx], new); |
245 | if (defkey && new) | 274 | if (defkey && new) |
246 | __ieee80211_set_default_key(sdata, new->conf.keyidx); | 275 | __ieee80211_set_default_key(sdata, new->conf.keyidx); |
276 | if (defmgmtkey && new) | ||
277 | __ieee80211_set_default_mgmt_key(sdata, | ||
278 | new->conf.keyidx); | ||
247 | } | 279 | } |
248 | 280 | ||
249 | if (old) { | 281 | if (old) { |
250 | /* | 282 | /* |
251 | * We'll use an empty list to indicate that the key | 283 | * We'll use an empty list to indicate that the key |
252 | * has already been removed. | 284 | * has already been removed. |
253 | */ | 285 | */ |
254 | list_del_init(&old->list); | 286 | list_del_init(&old->list); |
255 | } | 287 | } |
256 | } | 288 | } |
257 | 289 | ||
258 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 290 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, |
259 | int idx, | 291 | int idx, |
260 | size_t key_len, | 292 | size_t key_len, |
261 | const u8 *key_data) | 293 | const u8 *key_data) |
262 | { | 294 | { |
263 | struct ieee80211_key *key; | 295 | struct ieee80211_key *key; |
264 | 296 | ||
265 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS); | 297 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); |
266 | 298 | ||
267 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); | 299 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); |
268 | if (!key) | 300 | if (!key) |
269 | return NULL; | 301 | return NULL; |
270 | 302 | ||
271 | /* | 303 | /* |
272 | * Default to software encryption; we'll later upload the | 304 | * Default to software encryption; we'll later upload the |
273 | * key to the hardware if possible. | 305 | * key to the hardware if possible. |
274 | */ | 306 | */ |
275 | key->conf.flags = 0; | 307 | key->conf.flags = 0; |
276 | key->flags = 0; | 308 | key->flags = 0; |
277 | 309 | ||
278 | key->conf.alg = alg; | 310 | key->conf.alg = alg; |
279 | key->conf.keyidx = idx; | 311 | key->conf.keyidx = idx; |
280 | key->conf.keylen = key_len; | 312 | key->conf.keylen = key_len; |
281 | switch (alg) { | 313 | switch (alg) { |
282 | case ALG_WEP: | 314 | case ALG_WEP: |
283 | key->conf.iv_len = WEP_IV_LEN; | 315 | key->conf.iv_len = WEP_IV_LEN; |
284 | key->conf.icv_len = WEP_ICV_LEN; | 316 | key->conf.icv_len = WEP_ICV_LEN; |
285 | break; | 317 | break; |
286 | case ALG_TKIP: | 318 | case ALG_TKIP: |
287 | key->conf.iv_len = TKIP_IV_LEN; | 319 | key->conf.iv_len = TKIP_IV_LEN; |
288 | key->conf.icv_len = TKIP_ICV_LEN; | 320 | key->conf.icv_len = TKIP_ICV_LEN; |
289 | break; | 321 | break; |
290 | case ALG_CCMP: | 322 | case ALG_CCMP: |
291 | key->conf.iv_len = CCMP_HDR_LEN; | 323 | key->conf.iv_len = CCMP_HDR_LEN; |
292 | key->conf.icv_len = CCMP_MIC_LEN; | 324 | key->conf.icv_len = CCMP_MIC_LEN; |
293 | break; | 325 | break; |
326 | case ALG_AES_CMAC: | ||
327 | key->conf.iv_len = 0; | ||
328 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
329 | break; | ||
294 | } | 330 | } |
295 | memcpy(key->conf.key, key_data, key_len); | 331 | memcpy(key->conf.key, key_data, key_len); |
296 | INIT_LIST_HEAD(&key->list); | 332 | INIT_LIST_HEAD(&key->list); |
297 | INIT_LIST_HEAD(&key->todo); | 333 | INIT_LIST_HEAD(&key->todo); |
298 | 334 | ||
299 | if (alg == ALG_CCMP) { | 335 | if (alg == ALG_CCMP) { |
300 | /* | 336 | /* |
301 | * Initialize AES key state here as an optimization so that | 337 | * Initialize AES key state here as an optimization so that |
302 | * it does not need to be initialized for every packet. | 338 | * it does not need to be initialized for every packet. |
303 | */ | 339 | */ |
304 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); | 340 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); |
305 | if (!key->u.ccmp.tfm) { | 341 | if (!key->u.ccmp.tfm) { |
306 | kfree(key); | 342 | kfree(key); |
307 | return NULL; | 343 | return NULL; |
308 | } | 344 | } |
309 | } | 345 | } |
310 | 346 | ||
347 | if (alg == ALG_AES_CMAC) { | ||
348 | /* | ||
349 | * Initialize AES key state here as an optimization so that | ||
350 | * it does not need to be initialized for every packet. | ||
351 | */ | ||
352 | key->u.aes_cmac.tfm = | ||
353 | ieee80211_aes_cmac_key_setup(key_data); | ||
354 | if (!key->u.aes_cmac.tfm) { | ||
355 | kfree(key); | ||
356 | return NULL; | ||
357 | } | ||
358 | } | ||
359 | |||
311 | return key; | 360 | return key; |
312 | } | 361 | } |
313 | 362 | ||
314 | void ieee80211_key_link(struct ieee80211_key *key, | 363 | void ieee80211_key_link(struct ieee80211_key *key, |
315 | struct ieee80211_sub_if_data *sdata, | 364 | struct ieee80211_sub_if_data *sdata, |
316 | struct sta_info *sta) | 365 | struct sta_info *sta) |
317 | { | 366 | { |
318 | struct ieee80211_key *old_key; | 367 | struct ieee80211_key *old_key; |
319 | unsigned long flags; | 368 | unsigned long flags; |
320 | int idx; | 369 | int idx; |
321 | 370 | ||
322 | BUG_ON(!sdata); | 371 | BUG_ON(!sdata); |
323 | BUG_ON(!key); | 372 | BUG_ON(!key); |
324 | 373 | ||
325 | idx = key->conf.keyidx; | 374 | idx = key->conf.keyidx; |
326 | key->local = sdata->local; | 375 | key->local = sdata->local; |
327 | key->sdata = sdata; | 376 | key->sdata = sdata; |
328 | key->sta = sta; | 377 | key->sta = sta; |
329 | 378 | ||
330 | if (sta) { | 379 | if (sta) { |
331 | /* | 380 | /* |
332 | * some hardware cannot handle TKIP with QoS, so | 381 | * some hardware cannot handle TKIP with QoS, so |
333 | * we indicate whether QoS could be in use. | 382 | * we indicate whether QoS could be in use. |
334 | */ | 383 | */ |
335 | if (test_sta_flags(sta, WLAN_STA_WME)) | 384 | if (test_sta_flags(sta, WLAN_STA_WME)) |
336 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | 385 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; |
337 | 386 | ||
338 | /* | 387 | /* |
339 | * This key is for a specific sta interface, | 388 | * This key is for a specific sta interface, |
340 | * inform the driver that it should try to store | 389 | * inform the driver that it should try to store |
341 | * this key as pairwise key. | 390 | * this key as pairwise key. |
342 | */ | 391 | */ |
343 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | 392 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
344 | } else { | 393 | } else { |
345 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 394 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
346 | struct sta_info *ap; | 395 | struct sta_info *ap; |
347 | 396 | ||
348 | /* | 397 | /* |
349 | * We're getting a sta pointer in, | 398 | * We're getting a sta pointer in, |
350 | * so must be under RCU read lock. | 399 | * so must be under RCU read lock. |
351 | */ | 400 | */ |
352 | 401 | ||
353 | /* same here, the AP could be using QoS */ | 402 | /* same here, the AP could be using QoS */ |
354 | ap = sta_info_get(key->local, key->sdata->u.sta.bssid); | 403 | ap = sta_info_get(key->local, key->sdata->u.sta.bssid); |
355 | if (ap) { | 404 | if (ap) { |
356 | if (test_sta_flags(ap, WLAN_STA_WME)) | 405 | if (test_sta_flags(ap, WLAN_STA_WME)) |
357 | key->conf.flags |= | 406 | key->conf.flags |= |
358 | IEEE80211_KEY_FLAG_WMM_STA; | 407 | IEEE80211_KEY_FLAG_WMM_STA; |
359 | } | 408 | } |
360 | } | 409 | } |
361 | } | 410 | } |
362 | 411 | ||
363 | spin_lock_irqsave(&sdata->local->key_lock, flags); | 412 | spin_lock_irqsave(&sdata->local->key_lock, flags); |
364 | 413 | ||
365 | if (sta) | 414 | if (sta) |
366 | old_key = sta->key; | 415 | old_key = sta->key; |
367 | else | 416 | else |
368 | old_key = sdata->keys[idx]; | 417 | old_key = sdata->keys[idx]; |
369 | 418 | ||
370 | __ieee80211_key_replace(sdata, sta, old_key, key); | 419 | __ieee80211_key_replace(sdata, sta, old_key, key); |
371 | 420 | ||
372 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | 421 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
373 | 422 | ||
374 | /* free old key later */ | 423 | /* free old key later */ |
375 | add_todo(old_key, KEY_FLAG_TODO_DELETE); | 424 | add_todo(old_key, KEY_FLAG_TODO_DELETE); |
376 | 425 | ||
377 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); | 426 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); |
378 | if (netif_running(sdata->dev)) | 427 | if (netif_running(sdata->dev)) |
379 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); | 428 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); |
380 | } | 429 | } |
381 | 430 | ||
382 | static void __ieee80211_key_free(struct ieee80211_key *key) | 431 | static void __ieee80211_key_free(struct ieee80211_key *key) |
383 | { | 432 | { |
384 | /* | 433 | /* |
385 | * Replace key with nothingness if it was ever used. | 434 | * Replace key with nothingness if it was ever used. |
386 | */ | 435 | */ |
387 | if (key->sdata) | 436 | if (key->sdata) |
388 | __ieee80211_key_replace(key->sdata, key->sta, | 437 | __ieee80211_key_replace(key->sdata, key->sta, |
389 | key, NULL); | 438 | key, NULL); |
390 | 439 | ||
391 | add_todo(key, KEY_FLAG_TODO_DELETE); | 440 | add_todo(key, KEY_FLAG_TODO_DELETE); |
392 | } | 441 | } |
393 | 442 | ||
394 | void ieee80211_key_free(struct ieee80211_key *key) | 443 | void ieee80211_key_free(struct ieee80211_key *key) |
395 | { | 444 | { |
396 | unsigned long flags; | 445 | unsigned long flags; |
397 | 446 | ||
398 | if (!key) | 447 | if (!key) |
399 | return; | 448 | return; |
400 | 449 | ||
401 | if (!key->sdata) { | 450 | if (!key->sdata) { |
402 | /* The key has not been linked yet, simply free it | 451 | /* The key has not been linked yet, simply free it |
403 | * and don't Oops */ | 452 | * and don't Oops */ |
404 | if (key->conf.alg == ALG_CCMP) | 453 | if (key->conf.alg == ALG_CCMP) |
405 | ieee80211_aes_key_free(key->u.ccmp.tfm); | 454 | ieee80211_aes_key_free(key->u.ccmp.tfm); |
406 | kfree(key); | 455 | kfree(key); |
407 | return; | 456 | return; |
408 | } | 457 | } |
409 | 458 | ||
410 | spin_lock_irqsave(&key->sdata->local->key_lock, flags); | 459 | spin_lock_irqsave(&key->sdata->local->key_lock, flags); |
411 | __ieee80211_key_free(key); | 460 | __ieee80211_key_free(key); |
412 | spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); | 461 | spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); |
413 | } | 462 | } |
414 | 463 | ||
415 | /* | 464 | /* |
416 | * To be safe against concurrent manipulations of the list (which shouldn't | 465 | * To be safe against concurrent manipulations of the list (which shouldn't |
417 | * actually happen) we need to hold the spinlock. But under the spinlock we | 466 | * actually happen) we need to hold the spinlock. But under the spinlock we |
418 | * can't actually do much, so we defer processing to the todo list. Then run | 467 | * can't actually do much, so we defer processing to the todo list. Then run |
419 | * the todo list to be sure the operation and possibly previously pending | 468 | * the todo list to be sure the operation and possibly previously pending |
420 | * operations are completed. | 469 | * operations are completed. |
421 | */ | 470 | */ |
422 | static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata, | 471 | static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata, |
423 | u32 todo_flags) | 472 | u32 todo_flags) |
424 | { | 473 | { |
425 | struct ieee80211_key *key; | 474 | struct ieee80211_key *key; |
426 | unsigned long flags; | 475 | unsigned long flags; |
427 | 476 | ||
428 | might_sleep(); | 477 | might_sleep(); |
429 | 478 | ||
430 | spin_lock_irqsave(&sdata->local->key_lock, flags); | 479 | spin_lock_irqsave(&sdata->local->key_lock, flags); |
431 | list_for_each_entry(key, &sdata->key_list, list) | 480 | list_for_each_entry(key, &sdata->key_list, list) |
432 | add_todo(key, todo_flags); | 481 | add_todo(key, todo_flags); |
433 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | 482 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
434 | 483 | ||
435 | ieee80211_key_todo(); | 484 | ieee80211_key_todo(); |
436 | } | 485 | } |
437 | 486 | ||
438 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | 487 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) |
439 | { | 488 | { |
440 | ASSERT_RTNL(); | 489 | ASSERT_RTNL(); |
441 | 490 | ||
442 | if (WARN_ON(!netif_running(sdata->dev))) | 491 | if (WARN_ON(!netif_running(sdata->dev))) |
443 | return; | 492 | return; |
444 | 493 | ||
445 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); | 494 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); |
446 | } | 495 | } |
447 | 496 | ||
448 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) | 497 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) |
449 | { | 498 | { |
450 | ASSERT_RTNL(); | 499 | ASSERT_RTNL(); |
451 | 500 | ||
452 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE); | 501 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE); |
453 | } | 502 | } |
454 | 503 | ||
455 | static void __ieee80211_key_destroy(struct ieee80211_key *key) | 504 | static void __ieee80211_key_destroy(struct ieee80211_key *key) |
456 | { | 505 | { |
457 | if (!key) | 506 | if (!key) |
458 | return; | 507 | return; |
459 | 508 | ||
460 | ieee80211_key_disable_hw_accel(key); | 509 | ieee80211_key_disable_hw_accel(key); |
461 | 510 | ||
462 | if (key->conf.alg == ALG_CCMP) | 511 | if (key->conf.alg == ALG_CCMP) |
463 | ieee80211_aes_key_free(key->u.ccmp.tfm); | 512 | ieee80211_aes_key_free(key->u.ccmp.tfm); |
513 | if (key->conf.alg == ALG_AES_CMAC) | ||
514 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | ||
464 | ieee80211_debugfs_key_remove(key); | 515 | ieee80211_debugfs_key_remove(key); |
465 | 516 | ||
466 | kfree(key); | 517 | kfree(key); |
467 | } | 518 | } |
468 | 519 | ||
469 | static void __ieee80211_key_todo(void) | 520 | static void __ieee80211_key_todo(void) |
470 | { | 521 | { |
471 | struct ieee80211_key *key; | 522 | struct ieee80211_key *key; |
472 | bool work_done; | 523 | bool work_done; |
473 | u32 todoflags; | 524 | u32 todoflags; |
474 | 525 | ||
475 | /* | 526 | /* |
476 | * NB: sta_info_destroy relies on this! | 527 | * NB: sta_info_destroy relies on this! |
477 | */ | 528 | */ |
478 | synchronize_rcu(); | 529 | synchronize_rcu(); |
479 | 530 | ||
480 | spin_lock(&todo_lock); | 531 | spin_lock(&todo_lock); |
481 | while (!list_empty(&todo_list)) { | 532 | while (!list_empty(&todo_list)) { |
482 | key = list_first_entry(&todo_list, struct ieee80211_key, todo); | 533 | key = list_first_entry(&todo_list, struct ieee80211_key, todo); |
483 | list_del_init(&key->todo); | 534 | list_del_init(&key->todo); |
484 | todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | | 535 | todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | |
485 | KEY_FLAG_TODO_DEFKEY | | 536 | KEY_FLAG_TODO_DEFKEY | |
537 | KEY_FLAG_TODO_DEFMGMTKEY | | ||
486 | KEY_FLAG_TODO_HWACCEL_ADD | | 538 | KEY_FLAG_TODO_HWACCEL_ADD | |
487 | KEY_FLAG_TODO_HWACCEL_REMOVE | | 539 | KEY_FLAG_TODO_HWACCEL_REMOVE | |
488 | KEY_FLAG_TODO_DELETE); | 540 | KEY_FLAG_TODO_DELETE); |
489 | key->flags &= ~todoflags; | 541 | key->flags &= ~todoflags; |
490 | spin_unlock(&todo_lock); | 542 | spin_unlock(&todo_lock); |
491 | 543 | ||
492 | work_done = false; | 544 | work_done = false; |
493 | 545 | ||
494 | if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) { | 546 | if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) { |
495 | ieee80211_debugfs_key_add(key); | 547 | ieee80211_debugfs_key_add(key); |
496 | work_done = true; | 548 | work_done = true; |
497 | } | 549 | } |
498 | if (todoflags & KEY_FLAG_TODO_DEFKEY) { | 550 | if (todoflags & KEY_FLAG_TODO_DEFKEY) { |
499 | ieee80211_debugfs_key_remove_default(key->sdata); | 551 | ieee80211_debugfs_key_remove_default(key->sdata); |
500 | ieee80211_debugfs_key_add_default(key->sdata); | 552 | ieee80211_debugfs_key_add_default(key->sdata); |
501 | work_done = true; | 553 | work_done = true; |
502 | } | 554 | } |
555 | if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) { | ||
556 | ieee80211_debugfs_key_remove_mgmt_default(key->sdata); | ||
557 | ieee80211_debugfs_key_add_mgmt_default(key->sdata); | ||
558 | work_done = true; | ||
559 | } | ||
503 | if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { | 560 | if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { |
504 | ieee80211_key_enable_hw_accel(key); | 561 | ieee80211_key_enable_hw_accel(key); |
505 | work_done = true; | 562 | work_done = true; |
506 | } | 563 | } |
507 | if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) { | 564 | if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) { |
508 | ieee80211_key_disable_hw_accel(key); | 565 | ieee80211_key_disable_hw_accel(key); |
509 | work_done = true; | 566 | work_done = true; |
510 | } | 567 | } |
511 | if (todoflags & KEY_FLAG_TODO_DELETE) { | 568 | if (todoflags & KEY_FLAG_TODO_DELETE) { |
512 | __ieee80211_key_destroy(key); | 569 | __ieee80211_key_destroy(key); |
513 | work_done = true; | 570 | work_done = true; |
514 | } | 571 | } |
515 | 572 | ||
516 | WARN_ON(!work_done); | 573 | WARN_ON(!work_done); |
517 | 574 | ||
518 | spin_lock(&todo_lock); | 575 | spin_lock(&todo_lock); |
519 | } | 576 | } |
520 | spin_unlock(&todo_lock); | 577 | spin_unlock(&todo_lock); |
521 | } | 578 | } |
522 | 579 | ||
523 | void ieee80211_key_todo(void) | 580 | void ieee80211_key_todo(void) |
524 | { | 581 | { |
525 | ieee80211_key_lock(); | 582 | ieee80211_key_lock(); |
526 | __ieee80211_key_todo(); | 583 | __ieee80211_key_todo(); |
527 | ieee80211_key_unlock(); | 584 | ieee80211_key_unlock(); |
528 | } | 585 | } |
529 | 586 | ||
530 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | 587 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) |
531 | { | 588 | { |
532 | struct ieee80211_key *key, *tmp; | 589 | struct ieee80211_key *key, *tmp; |
533 | unsigned long flags; | 590 | unsigned long flags; |
534 | 591 | ||
535 | ieee80211_key_lock(); | 592 | ieee80211_key_lock(); |
536 | 593 | ||
537 | ieee80211_debugfs_key_remove_default(sdata); | 594 | ieee80211_debugfs_key_remove_default(sdata); |
595 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | ||
538 | 596 | ||
539 | spin_lock_irqsave(&sdata->local->key_lock, flags); | 597 | spin_lock_irqsave(&sdata->local->key_lock, flags); |
540 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 598 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
541 | __ieee80211_key_free(key); | 599 | __ieee80211_key_free(key); |
542 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | 600 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
543 | 601 | ||
544 | __ieee80211_key_todo(); | 602 | __ieee80211_key_todo(); |
545 | 603 | ||
546 | ieee80211_key_unlock(); | 604 | ieee80211_key_unlock(); |
547 | } | 605 | } |
548 | 606 |
net/mac80211/key.h
1 | /* | 1 | /* |
2 | * Copyright 2002-2004, Instant802 Networks, Inc. | 2 | * Copyright 2002-2004, Instant802 Networks, Inc. |
3 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #ifndef IEEE80211_KEY_H | 10 | #ifndef IEEE80211_KEY_H |
11 | #define IEEE80211_KEY_H | 11 | #define IEEE80211_KEY_H |
12 | 12 | ||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | #include <linux/crypto.h> | 15 | #include <linux/crypto.h> |
16 | #include <linux/rcupdate.h> | 16 | #include <linux/rcupdate.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | 18 | ||
19 | #define WEP_IV_LEN 4 | 19 | #define WEP_IV_LEN 4 |
20 | #define WEP_ICV_LEN 4 | 20 | #define WEP_ICV_LEN 4 |
21 | #define ALG_TKIP_KEY_LEN 32 | 21 | #define ALG_TKIP_KEY_LEN 32 |
22 | #define ALG_CCMP_KEY_LEN 16 | 22 | #define ALG_CCMP_KEY_LEN 16 |
23 | #define CCMP_HDR_LEN 8 | 23 | #define CCMP_HDR_LEN 8 |
24 | #define CCMP_MIC_LEN 8 | 24 | #define CCMP_MIC_LEN 8 |
25 | #define CCMP_TK_LEN 16 | 25 | #define CCMP_TK_LEN 16 |
26 | #define CCMP_PN_LEN 6 | 26 | #define CCMP_PN_LEN 6 |
27 | #define TKIP_IV_LEN 8 | 27 | #define TKIP_IV_LEN 8 |
28 | #define TKIP_ICV_LEN 4 | 28 | #define TKIP_ICV_LEN 4 |
29 | 29 | ||
30 | #define NUM_RX_DATA_QUEUES 17 | 30 | #define NUM_RX_DATA_QUEUES 17 |
31 | 31 | ||
32 | struct ieee80211_local; | 32 | struct ieee80211_local; |
33 | struct ieee80211_sub_if_data; | 33 | struct ieee80211_sub_if_data; |
34 | struct sta_info; | 34 | struct sta_info; |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * enum ieee80211_internal_key_flags - internal key flags | 37 | * enum ieee80211_internal_key_flags - internal key flags |
38 | * | 38 | * |
39 | * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present | 39 | * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present |
40 | * in the hardware for TX crypto hardware acceleration. | 40 | * in the hardware for TX crypto hardware acceleration. |
41 | * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an | 41 | * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an |
42 | * RCU grace period, no longer be reachable other than from the | 42 | * RCU grace period, no longer be reachable other than from the |
43 | * todo list. | 43 | * todo list. |
44 | * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration. | 44 | * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration. |
45 | * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware | 45 | * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware |
46 | * acceleration. | 46 | * acceleration. |
47 | * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. | 47 | * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. |
48 | * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. | 48 | * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. |
49 | * @KEY_FLAG_TODO_DEFMGMTKEY: Key is default management key and debugfs needs | ||
50 | * to be updated. | ||
49 | */ | 51 | */ |
50 | enum ieee80211_internal_key_flags { | 52 | enum ieee80211_internal_key_flags { |
51 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), | 53 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), |
52 | KEY_FLAG_TODO_DELETE = BIT(1), | 54 | KEY_FLAG_TODO_DELETE = BIT(1), |
53 | KEY_FLAG_TODO_HWACCEL_ADD = BIT(2), | 55 | KEY_FLAG_TODO_HWACCEL_ADD = BIT(2), |
54 | KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), | 56 | KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), |
55 | KEY_FLAG_TODO_DEFKEY = BIT(4), | 57 | KEY_FLAG_TODO_DEFKEY = BIT(4), |
56 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), | 58 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), |
59 | KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | struct tkip_ctx { | 62 | struct tkip_ctx { |
60 | u32 iv32; | 63 | u32 iv32; |
61 | u16 iv16; | 64 | u16 iv16; |
62 | u16 p1k[5]; | 65 | u16 p1k[5]; |
63 | int initialized; | 66 | int initialized; |
64 | }; | 67 | }; |
65 | 68 | ||
66 | struct ieee80211_key { | 69 | struct ieee80211_key { |
67 | struct ieee80211_local *local; | 70 | struct ieee80211_local *local; |
68 | struct ieee80211_sub_if_data *sdata; | 71 | struct ieee80211_sub_if_data *sdata; |
69 | struct sta_info *sta; | 72 | struct sta_info *sta; |
70 | 73 | ||
71 | /* for sdata list */ | 74 | /* for sdata list */ |
72 | struct list_head list; | 75 | struct list_head list; |
73 | /* for todo list */ | 76 | /* for todo list */ |
74 | struct list_head todo; | 77 | struct list_head todo; |
75 | 78 | ||
76 | /* protected by todo lock! */ | 79 | /* protected by todo lock! */ |
77 | unsigned int flags; | 80 | unsigned int flags; |
78 | 81 | ||
79 | union { | 82 | union { |
80 | struct { | 83 | struct { |
81 | /* last used TSC */ | 84 | /* last used TSC */ |
82 | struct tkip_ctx tx; | 85 | struct tkip_ctx tx; |
83 | 86 | ||
84 | /* last received RSC */ | 87 | /* last received RSC */ |
85 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; | 88 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; |
86 | } tkip; | 89 | } tkip; |
87 | struct { | 90 | struct { |
88 | u8 tx_pn[6]; | 91 | u8 tx_pn[6]; |
89 | u8 rx_pn[NUM_RX_DATA_QUEUES][6]; | 92 | u8 rx_pn[NUM_RX_DATA_QUEUES][6]; |
90 | struct crypto_cipher *tfm; | 93 | struct crypto_cipher *tfm; |
91 | u32 replays; /* dot11RSNAStatsCCMPReplays */ | 94 | u32 replays; /* dot11RSNAStatsCCMPReplays */ |
92 | /* scratch buffers for virt_to_page() (crypto API) */ | 95 | /* scratch buffers for virt_to_page() (crypto API) */ |
93 | #ifndef AES_BLOCK_LEN | 96 | #ifndef AES_BLOCK_LEN |
94 | #define AES_BLOCK_LEN 16 | 97 | #define AES_BLOCK_LEN 16 |
95 | #endif | 98 | #endif |
96 | u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; | 99 | u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; |
97 | u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; | 100 | u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; |
98 | } ccmp; | 101 | } ccmp; |
99 | struct { | 102 | struct { |
100 | u8 tx_pn[6]; | 103 | u8 tx_pn[6]; |
101 | u8 rx_pn[6]; | 104 | u8 rx_pn[6]; |
102 | struct crypto_cipher *tfm; | 105 | struct crypto_cipher *tfm; |
103 | u32 replays; /* dot11RSNAStatsCMACReplays */ | 106 | u32 replays; /* dot11RSNAStatsCMACReplays */ |
104 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ | 107 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ |
105 | /* scratch buffers for virt_to_page() (crypto API) */ | 108 | /* scratch buffers for virt_to_page() (crypto API) */ |
106 | u8 tx_crypto_buf[2 * AES_BLOCK_LEN]; | 109 | u8 tx_crypto_buf[2 * AES_BLOCK_LEN]; |
107 | u8 rx_crypto_buf[2 * AES_BLOCK_LEN]; | 110 | u8 rx_crypto_buf[2 * AES_BLOCK_LEN]; |
108 | } aes_cmac; | 111 | } aes_cmac; |
109 | } u; | 112 | } u; |
110 | 113 | ||
111 | /* number of times this key has been used */ | 114 | /* number of times this key has been used */ |
112 | int tx_rx_count; | 115 | int tx_rx_count; |
113 | 116 | ||
114 | #ifdef CONFIG_MAC80211_DEBUGFS | 117 | #ifdef CONFIG_MAC80211_DEBUGFS |
115 | struct { | 118 | struct { |
116 | struct dentry *stalink; | 119 | struct dentry *stalink; |
117 | struct dentry *dir; | 120 | struct dentry *dir; |
118 | struct dentry *keylen; | 121 | struct dentry *keylen; |
119 | struct dentry *flags; | 122 | struct dentry *flags; |
120 | struct dentry *keyidx; | 123 | struct dentry *keyidx; |
121 | struct dentry *hw_key_idx; | 124 | struct dentry *hw_key_idx; |
122 | struct dentry *tx_rx_count; | 125 | struct dentry *tx_rx_count; |
123 | struct dentry *algorithm; | 126 | struct dentry *algorithm; |
124 | struct dentry *tx_spec; | 127 | struct dentry *tx_spec; |
125 | struct dentry *rx_spec; | 128 | struct dentry *rx_spec; |
126 | struct dentry *replays; | 129 | struct dentry *replays; |
130 | struct dentry *icverrors; | ||
127 | struct dentry *key; | 131 | struct dentry *key; |
128 | struct dentry *ifindex; | 132 | struct dentry *ifindex; |
129 | int cnt; | 133 | int cnt; |
130 | } debugfs; | 134 | } debugfs; |
131 | #endif | 135 | #endif |
132 | 136 | ||
133 | /* | 137 | /* |
134 | * key config, must be last because it contains key | 138 | * key config, must be last because it contains key |
135 | * material as variable length member | 139 | * material as variable length member |
136 | */ | 140 | */ |
137 | struct ieee80211_key_conf conf; | 141 | struct ieee80211_key_conf conf; |
138 | }; | 142 | }; |
139 | 143 | ||
140 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 144 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, |
141 | int idx, | 145 | int idx, |
142 | size_t key_len, | 146 | size_t key_len, |
143 | const u8 *key_data); | 147 | const u8 *key_data); |
144 | /* | 148 | /* |
145 | * Insert a key into data structures (sdata, sta if necessary) | 149 | * Insert a key into data structures (sdata, sta if necessary) |
146 | * to make it used, free old key. | 150 | * to make it used, free old key. |
147 | */ | 151 | */ |
148 | void ieee80211_key_link(struct ieee80211_key *key, | 152 | void ieee80211_key_link(struct ieee80211_key *key, |
149 | struct ieee80211_sub_if_data *sdata, | 153 | struct ieee80211_sub_if_data *sdata, |
150 | struct sta_info *sta); | 154 | struct sta_info *sta); |
151 | void ieee80211_key_free(struct ieee80211_key *key); | 155 | void ieee80211_key_free(struct ieee80211_key *key); |
152 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); | 156 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); |
157 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | ||
158 | int idx); | ||
153 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 159 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
154 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 160 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
155 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); | 161 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); |
156 | 162 | ||
157 | void ieee80211_key_todo(void); | 163 | void ieee80211_key_todo(void); |
158 | 164 | ||
159 | #endif /* IEEE80211_KEY_H */ | 165 | #endif /* IEEE80211_KEY_H */ |
160 | 166 |
net/mac80211/rx.c
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007 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 | #include <linux/jiffies.h> | 12 | #include <linux/jiffies.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/etherdevice.h> | 16 | #include <linux/etherdevice.h> |
17 | #include <linux/rcupdate.h> | 17 | #include <linux/rcupdate.h> |
18 | #include <net/mac80211.h> | 18 | #include <net/mac80211.h> |
19 | #include <net/ieee80211_radiotap.h> | 19 | #include <net/ieee80211_radiotap.h> |
20 | 20 | ||
21 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
22 | #include "led.h" | 22 | #include "led.h" |
23 | #include "mesh.h" | 23 | #include "mesh.h" |
24 | #include "wep.h" | 24 | #include "wep.h" |
25 | #include "wpa.h" | 25 | #include "wpa.h" |
26 | #include "tkip.h" | 26 | #include "tkip.h" |
27 | #include "wme.h" | 27 | #include "wme.h" |
28 | 28 | ||
29 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 29 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, |
30 | struct tid_ampdu_rx *tid_agg_rx, | 30 | struct tid_ampdu_rx *tid_agg_rx, |
31 | struct sk_buff *skb, | 31 | struct sk_buff *skb, |
32 | u16 mpdu_seq_num, | 32 | u16 mpdu_seq_num, |
33 | int bar_req); | 33 | int bar_req); |
34 | /* | 34 | /* |
35 | * monitor mode reception | 35 | * monitor mode reception |
36 | * | 36 | * |
37 | * This function cleans up the SKB, i.e. it removes all the stuff | 37 | * This function cleans up the SKB, i.e. it removes all the stuff |
38 | * only useful for monitoring. | 38 | * only useful for monitoring. |
39 | */ | 39 | */ |
40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | 40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, |
41 | struct sk_buff *skb, | 41 | struct sk_buff *skb, |
42 | int rtap_len) | 42 | int rtap_len) |
43 | { | 43 | { |
44 | skb_pull(skb, rtap_len); | 44 | skb_pull(skb, rtap_len); |
45 | 45 | ||
46 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 46 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
47 | if (likely(skb->len > FCS_LEN)) | 47 | if (likely(skb->len > FCS_LEN)) |
48 | skb_trim(skb, skb->len - FCS_LEN); | 48 | skb_trim(skb, skb->len - FCS_LEN); |
49 | else { | 49 | else { |
50 | /* driver bug */ | 50 | /* driver bug */ |
51 | WARN_ON(1); | 51 | WARN_ON(1); |
52 | dev_kfree_skb(skb); | 52 | dev_kfree_skb(skb); |
53 | skb = NULL; | 53 | skb = NULL; |
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | return skb; | 57 | return skb; |
58 | } | 58 | } |
59 | 59 | ||
60 | static inline int should_drop_frame(struct ieee80211_rx_status *status, | 60 | static inline int should_drop_frame(struct ieee80211_rx_status *status, |
61 | struct sk_buff *skb, | 61 | struct sk_buff *skb, |
62 | int present_fcs_len, | 62 | int present_fcs_len, |
63 | int radiotap_len) | 63 | int radiotap_len) |
64 | { | 64 | { |
65 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 65 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
66 | 66 | ||
67 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 67 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
68 | return 1; | 68 | return 1; |
69 | if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len)) | 69 | if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len)) |
70 | return 1; | 70 | return 1; |
71 | if (ieee80211_is_ctl(hdr->frame_control) && | 71 | if (ieee80211_is_ctl(hdr->frame_control) && |
72 | !ieee80211_is_pspoll(hdr->frame_control) && | 72 | !ieee80211_is_pspoll(hdr->frame_control) && |
73 | !ieee80211_is_back_req(hdr->frame_control)) | 73 | !ieee80211_is_back_req(hdr->frame_control)) |
74 | return 1; | 74 | return 1; |
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | 77 | ||
78 | static int | 78 | static int |
79 | ieee80211_rx_radiotap_len(struct ieee80211_local *local, | 79 | ieee80211_rx_radiotap_len(struct ieee80211_local *local, |
80 | struct ieee80211_rx_status *status) | 80 | struct ieee80211_rx_status *status) |
81 | { | 81 | { |
82 | int len; | 82 | int len; |
83 | 83 | ||
84 | /* always present fields */ | 84 | /* always present fields */ |
85 | len = sizeof(struct ieee80211_radiotap_header) + 9; | 85 | len = sizeof(struct ieee80211_radiotap_header) + 9; |
86 | 86 | ||
87 | if (status->flag & RX_FLAG_TSFT) | 87 | if (status->flag & RX_FLAG_TSFT) |
88 | len += 8; | 88 | len += 8; |
89 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB || | 89 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB || |
90 | local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 90 | local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
91 | len += 1; | 91 | len += 1; |
92 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | 92 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) |
93 | len += 1; | 93 | len += 1; |
94 | 94 | ||
95 | if (len & 1) /* padding for RX_FLAGS if necessary */ | 95 | if (len & 1) /* padding for RX_FLAGS if necessary */ |
96 | len++; | 96 | len++; |
97 | 97 | ||
98 | /* make sure radiotap starts at a naturally aligned address */ | 98 | /* make sure radiotap starts at a naturally aligned address */ |
99 | if (len % 8) | 99 | if (len % 8) |
100 | len = roundup(len, 8); | 100 | len = roundup(len, 8); |
101 | 101 | ||
102 | return len; | 102 | return len; |
103 | } | 103 | } |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * ieee80211_add_rx_radiotap_header - add radiotap header | 106 | * ieee80211_add_rx_radiotap_header - add radiotap header |
107 | * | 107 | * |
108 | * add a radiotap header containing all the fields which the hardware provided. | 108 | * add a radiotap header containing all the fields which the hardware provided. |
109 | */ | 109 | */ |
110 | static void | 110 | static void |
111 | ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | 111 | ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, |
112 | struct sk_buff *skb, | 112 | struct sk_buff *skb, |
113 | struct ieee80211_rx_status *status, | 113 | struct ieee80211_rx_status *status, |
114 | struct ieee80211_rate *rate, | 114 | struct ieee80211_rate *rate, |
115 | int rtap_len) | 115 | int rtap_len) |
116 | { | 116 | { |
117 | struct ieee80211_radiotap_header *rthdr; | 117 | struct ieee80211_radiotap_header *rthdr; |
118 | unsigned char *pos; | 118 | unsigned char *pos; |
119 | 119 | ||
120 | rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); | 120 | rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); |
121 | memset(rthdr, 0, rtap_len); | 121 | memset(rthdr, 0, rtap_len); |
122 | 122 | ||
123 | /* radiotap header, set always present flags */ | 123 | /* radiotap header, set always present flags */ |
124 | rthdr->it_present = | 124 | rthdr->it_present = |
125 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | 125 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
126 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 126 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
127 | (1 << IEEE80211_RADIOTAP_ANTENNA) | | 127 | (1 << IEEE80211_RADIOTAP_ANTENNA) | |
128 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | 128 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); |
129 | rthdr->it_len = cpu_to_le16(rtap_len); | 129 | rthdr->it_len = cpu_to_le16(rtap_len); |
130 | 130 | ||
131 | pos = (unsigned char *)(rthdr+1); | 131 | pos = (unsigned char *)(rthdr+1); |
132 | 132 | ||
133 | /* the order of the following fields is important */ | 133 | /* the order of the following fields is important */ |
134 | 134 | ||
135 | /* IEEE80211_RADIOTAP_TSFT */ | 135 | /* IEEE80211_RADIOTAP_TSFT */ |
136 | if (status->flag & RX_FLAG_TSFT) { | 136 | if (status->flag & RX_FLAG_TSFT) { |
137 | *(__le64 *)pos = cpu_to_le64(status->mactime); | 137 | *(__le64 *)pos = cpu_to_le64(status->mactime); |
138 | rthdr->it_present |= | 138 | rthdr->it_present |= |
139 | cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); | 139 | cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); |
140 | pos += 8; | 140 | pos += 8; |
141 | } | 141 | } |
142 | 142 | ||
143 | /* IEEE80211_RADIOTAP_FLAGS */ | 143 | /* IEEE80211_RADIOTAP_FLAGS */ |
144 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 144 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
145 | *pos |= IEEE80211_RADIOTAP_F_FCS; | 145 | *pos |= IEEE80211_RADIOTAP_F_FCS; |
146 | if (status->flag & RX_FLAG_SHORTPRE) | 146 | if (status->flag & RX_FLAG_SHORTPRE) |
147 | *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; | 147 | *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; |
148 | pos++; | 148 | pos++; |
149 | 149 | ||
150 | /* IEEE80211_RADIOTAP_RATE */ | 150 | /* IEEE80211_RADIOTAP_RATE */ |
151 | if (status->flag & RX_FLAG_HT) { | 151 | if (status->flag & RX_FLAG_HT) { |
152 | /* | 152 | /* |
153 | * TODO: add following information into radiotap header once | 153 | * TODO: add following information into radiotap header once |
154 | * suitable fields are defined for it: | 154 | * suitable fields are defined for it: |
155 | * - MCS index (status->rate_idx) | 155 | * - MCS index (status->rate_idx) |
156 | * - HT40 (status->flag & RX_FLAG_40MHZ) | 156 | * - HT40 (status->flag & RX_FLAG_40MHZ) |
157 | * - short-GI (status->flag & RX_FLAG_SHORT_GI) | 157 | * - short-GI (status->flag & RX_FLAG_SHORT_GI) |
158 | */ | 158 | */ |
159 | *pos = 0; | 159 | *pos = 0; |
160 | } else { | 160 | } else { |
161 | rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE); | 161 | rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE); |
162 | *pos = rate->bitrate / 5; | 162 | *pos = rate->bitrate / 5; |
163 | } | 163 | } |
164 | pos++; | 164 | pos++; |
165 | 165 | ||
166 | /* IEEE80211_RADIOTAP_CHANNEL */ | 166 | /* IEEE80211_RADIOTAP_CHANNEL */ |
167 | *(__le16 *)pos = cpu_to_le16(status->freq); | 167 | *(__le16 *)pos = cpu_to_le16(status->freq); |
168 | pos += 2; | 168 | pos += 2; |
169 | if (status->band == IEEE80211_BAND_5GHZ) | 169 | if (status->band == IEEE80211_BAND_5GHZ) |
170 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | | 170 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | |
171 | IEEE80211_CHAN_5GHZ); | 171 | IEEE80211_CHAN_5GHZ); |
172 | else if (rate->flags & IEEE80211_RATE_ERP_G) | 172 | else if (rate->flags & IEEE80211_RATE_ERP_G) |
173 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | | 173 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | |
174 | IEEE80211_CHAN_2GHZ); | 174 | IEEE80211_CHAN_2GHZ); |
175 | else | 175 | else |
176 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | | 176 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | |
177 | IEEE80211_CHAN_2GHZ); | 177 | IEEE80211_CHAN_2GHZ); |
178 | pos += 2; | 178 | pos += 2; |
179 | 179 | ||
180 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ | 180 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ |
181 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { | 181 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { |
182 | *pos = status->signal; | 182 | *pos = status->signal; |
183 | rthdr->it_present |= | 183 | rthdr->it_present |= |
184 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); | 184 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); |
185 | pos++; | 185 | pos++; |
186 | } | 186 | } |
187 | 187 | ||
188 | /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ | 188 | /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ |
189 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) { | 189 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) { |
190 | *pos = status->noise; | 190 | *pos = status->noise; |
191 | rthdr->it_present |= | 191 | rthdr->it_present |= |
192 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE); | 192 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE); |
193 | pos++; | 193 | pos++; |
194 | } | 194 | } |
195 | 195 | ||
196 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ | 196 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ |
197 | 197 | ||
198 | /* IEEE80211_RADIOTAP_ANTENNA */ | 198 | /* IEEE80211_RADIOTAP_ANTENNA */ |
199 | *pos = status->antenna; | 199 | *pos = status->antenna; |
200 | pos++; | 200 | pos++; |
201 | 201 | ||
202 | /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */ | 202 | /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */ |
203 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) { | 203 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) { |
204 | *pos = status->signal; | 204 | *pos = status->signal; |
205 | rthdr->it_present |= | 205 | rthdr->it_present |= |
206 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL); | 206 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL); |
207 | pos++; | 207 | pos++; |
208 | } | 208 | } |
209 | 209 | ||
210 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ | 210 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ |
211 | 211 | ||
212 | /* IEEE80211_RADIOTAP_RX_FLAGS */ | 212 | /* IEEE80211_RADIOTAP_RX_FLAGS */ |
213 | /* ensure 2 byte alignment for the 2 byte field as required */ | 213 | /* ensure 2 byte alignment for the 2 byte field as required */ |
214 | if ((pos - (unsigned char *)rthdr) & 1) | 214 | if ((pos - (unsigned char *)rthdr) & 1) |
215 | pos++; | 215 | pos++; |
216 | /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ | 216 | /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ |
217 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 217 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
218 | *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); | 218 | *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); |
219 | pos += 2; | 219 | pos += 2; |
220 | } | 220 | } |
221 | 221 | ||
222 | /* | 222 | /* |
223 | * This function copies a received frame to all monitor interfaces and | 223 | * This function copies a received frame to all monitor interfaces and |
224 | * returns a cleaned-up SKB that no longer includes the FCS nor the | 224 | * returns a cleaned-up SKB that no longer includes the FCS nor the |
225 | * radiotap header the driver might have added. | 225 | * radiotap header the driver might have added. |
226 | */ | 226 | */ |
227 | static struct sk_buff * | 227 | static struct sk_buff * |
228 | ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | 228 | ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, |
229 | struct ieee80211_rx_status *status, | 229 | struct ieee80211_rx_status *status, |
230 | struct ieee80211_rate *rate) | 230 | struct ieee80211_rate *rate) |
231 | { | 231 | { |
232 | struct ieee80211_sub_if_data *sdata; | 232 | struct ieee80211_sub_if_data *sdata; |
233 | int needed_headroom = 0; | 233 | int needed_headroom = 0; |
234 | struct sk_buff *skb, *skb2; | 234 | struct sk_buff *skb, *skb2; |
235 | struct net_device *prev_dev = NULL; | 235 | struct net_device *prev_dev = NULL; |
236 | int present_fcs_len = 0; | 236 | int present_fcs_len = 0; |
237 | int rtap_len = 0; | 237 | int rtap_len = 0; |
238 | 238 | ||
239 | /* | 239 | /* |
240 | * First, we may need to make a copy of the skb because | 240 | * First, we may need to make a copy of the skb because |
241 | * (1) we need to modify it for radiotap (if not present), and | 241 | * (1) we need to modify it for radiotap (if not present), and |
242 | * (2) the other RX handlers will modify the skb we got. | 242 | * (2) the other RX handlers will modify the skb we got. |
243 | * | 243 | * |
244 | * We don't need to, of course, if we aren't going to return | 244 | * We don't need to, of course, if we aren't going to return |
245 | * the SKB because it has a bad FCS/PLCP checksum. | 245 | * the SKB because it has a bad FCS/PLCP checksum. |
246 | */ | 246 | */ |
247 | if (status->flag & RX_FLAG_RADIOTAP) | 247 | if (status->flag & RX_FLAG_RADIOTAP) |
248 | rtap_len = ieee80211_get_radiotap_len(origskb->data); | 248 | rtap_len = ieee80211_get_radiotap_len(origskb->data); |
249 | else | 249 | else |
250 | /* room for the radiotap header based on driver features */ | 250 | /* room for the radiotap header based on driver features */ |
251 | needed_headroom = ieee80211_rx_radiotap_len(local, status); | 251 | needed_headroom = ieee80211_rx_radiotap_len(local, status); |
252 | 252 | ||
253 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 253 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
254 | present_fcs_len = FCS_LEN; | 254 | present_fcs_len = FCS_LEN; |
255 | 255 | ||
256 | if (!local->monitors) { | 256 | if (!local->monitors) { |
257 | if (should_drop_frame(status, origskb, present_fcs_len, | 257 | if (should_drop_frame(status, origskb, present_fcs_len, |
258 | rtap_len)) { | 258 | rtap_len)) { |
259 | dev_kfree_skb(origskb); | 259 | dev_kfree_skb(origskb); |
260 | return NULL; | 260 | return NULL; |
261 | } | 261 | } |
262 | 262 | ||
263 | return remove_monitor_info(local, origskb, rtap_len); | 263 | return remove_monitor_info(local, origskb, rtap_len); |
264 | } | 264 | } |
265 | 265 | ||
266 | if (should_drop_frame(status, origskb, present_fcs_len, rtap_len)) { | 266 | if (should_drop_frame(status, origskb, present_fcs_len, rtap_len)) { |
267 | /* only need to expand headroom if necessary */ | 267 | /* only need to expand headroom if necessary */ |
268 | skb = origskb; | 268 | skb = origskb; |
269 | origskb = NULL; | 269 | origskb = NULL; |
270 | 270 | ||
271 | /* | 271 | /* |
272 | * This shouldn't trigger often because most devices have an | 272 | * This shouldn't trigger often because most devices have an |
273 | * RX header they pull before we get here, and that should | 273 | * RX header they pull before we get here, and that should |
274 | * be big enough for our radiotap information. We should | 274 | * be big enough for our radiotap information. We should |
275 | * probably export the length to drivers so that we can have | 275 | * probably export the length to drivers so that we can have |
276 | * them allocate enough headroom to start with. | 276 | * them allocate enough headroom to start with. |
277 | */ | 277 | */ |
278 | if (skb_headroom(skb) < needed_headroom && | 278 | if (skb_headroom(skb) < needed_headroom && |
279 | pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) { | 279 | pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) { |
280 | dev_kfree_skb(skb); | 280 | dev_kfree_skb(skb); |
281 | return NULL; | 281 | return NULL; |
282 | } | 282 | } |
283 | } else { | 283 | } else { |
284 | /* | 284 | /* |
285 | * Need to make a copy and possibly remove radiotap header | 285 | * Need to make a copy and possibly remove radiotap header |
286 | * and FCS from the original. | 286 | * and FCS from the original. |
287 | */ | 287 | */ |
288 | skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); | 288 | skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); |
289 | 289 | ||
290 | origskb = remove_monitor_info(local, origskb, rtap_len); | 290 | origskb = remove_monitor_info(local, origskb, rtap_len); |
291 | 291 | ||
292 | if (!skb) | 292 | if (!skb) |
293 | return origskb; | 293 | return origskb; |
294 | } | 294 | } |
295 | 295 | ||
296 | /* if necessary, prepend radiotap information */ | 296 | /* if necessary, prepend radiotap information */ |
297 | if (!(status->flag & RX_FLAG_RADIOTAP)) | 297 | if (!(status->flag & RX_FLAG_RADIOTAP)) |
298 | ieee80211_add_rx_radiotap_header(local, skb, status, rate, | 298 | ieee80211_add_rx_radiotap_header(local, skb, status, rate, |
299 | needed_headroom); | 299 | needed_headroom); |
300 | 300 | ||
301 | skb_reset_mac_header(skb); | 301 | skb_reset_mac_header(skb); |
302 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 302 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
303 | skb->pkt_type = PACKET_OTHERHOST; | 303 | skb->pkt_type = PACKET_OTHERHOST; |
304 | skb->protocol = htons(ETH_P_802_2); | 304 | skb->protocol = htons(ETH_P_802_2); |
305 | 305 | ||
306 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 306 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
307 | if (!netif_running(sdata->dev)) | 307 | if (!netif_running(sdata->dev)) |
308 | continue; | 308 | continue; |
309 | 309 | ||
310 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 310 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
311 | continue; | 311 | continue; |
312 | 312 | ||
313 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) | 313 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) |
314 | continue; | 314 | continue; |
315 | 315 | ||
316 | if (prev_dev) { | 316 | if (prev_dev) { |
317 | skb2 = skb_clone(skb, GFP_ATOMIC); | 317 | skb2 = skb_clone(skb, GFP_ATOMIC); |
318 | if (skb2) { | 318 | if (skb2) { |
319 | skb2->dev = prev_dev; | 319 | skb2->dev = prev_dev; |
320 | netif_rx(skb2); | 320 | netif_rx(skb2); |
321 | } | 321 | } |
322 | } | 322 | } |
323 | 323 | ||
324 | prev_dev = sdata->dev; | 324 | prev_dev = sdata->dev; |
325 | sdata->dev->stats.rx_packets++; | 325 | sdata->dev->stats.rx_packets++; |
326 | sdata->dev->stats.rx_bytes += skb->len; | 326 | sdata->dev->stats.rx_bytes += skb->len; |
327 | } | 327 | } |
328 | 328 | ||
329 | if (prev_dev) { | 329 | if (prev_dev) { |
330 | skb->dev = prev_dev; | 330 | skb->dev = prev_dev; |
331 | netif_rx(skb); | 331 | netif_rx(skb); |
332 | } else | 332 | } else |
333 | dev_kfree_skb(skb); | 333 | dev_kfree_skb(skb); |
334 | 334 | ||
335 | return origskb; | 335 | return origskb; |
336 | } | 336 | } |
337 | 337 | ||
338 | 338 | ||
339 | static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | 339 | static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) |
340 | { | 340 | { |
341 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 341 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
342 | int tid; | 342 | int tid; |
343 | 343 | ||
344 | /* does the frame have a qos control field? */ | 344 | /* does the frame have a qos control field? */ |
345 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 345 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
346 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 346 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
347 | /* frame has qos control */ | 347 | /* frame has qos control */ |
348 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 348 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
349 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | 349 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) |
350 | rx->flags |= IEEE80211_RX_AMSDU; | 350 | rx->flags |= IEEE80211_RX_AMSDU; |
351 | else | 351 | else |
352 | rx->flags &= ~IEEE80211_RX_AMSDU; | 352 | rx->flags &= ~IEEE80211_RX_AMSDU; |
353 | } else { | 353 | } else { |
354 | /* | 354 | /* |
355 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): | 355 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): |
356 | * | 356 | * |
357 | * Sequence numbers for management frames, QoS data | 357 | * Sequence numbers for management frames, QoS data |
358 | * frames with a broadcast/multicast address in the | 358 | * frames with a broadcast/multicast address in the |
359 | * Address 1 field, and all non-QoS data frames sent | 359 | * Address 1 field, and all non-QoS data frames sent |
360 | * by QoS STAs are assigned using an additional single | 360 | * by QoS STAs are assigned using an additional single |
361 | * modulo-4096 counter, [...] | 361 | * modulo-4096 counter, [...] |
362 | * | 362 | * |
363 | * We also use that counter for non-QoS STAs. | 363 | * We also use that counter for non-QoS STAs. |
364 | */ | 364 | */ |
365 | tid = NUM_RX_DATA_QUEUES - 1; | 365 | tid = NUM_RX_DATA_QUEUES - 1; |
366 | } | 366 | } |
367 | 367 | ||
368 | rx->queue = tid; | 368 | rx->queue = tid; |
369 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. | 369 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. |
370 | * For now, set skb->priority to 0 for other cases. */ | 370 | * For now, set skb->priority to 0 for other cases. */ |
371 | rx->skb->priority = (tid > 7) ? 0 : tid; | 371 | rx->skb->priority = (tid > 7) ? 0 : tid; |
372 | } | 372 | } |
373 | 373 | ||
374 | /** | 374 | /** |
375 | * DOC: Packet alignment | 375 | * DOC: Packet alignment |
376 | * | 376 | * |
377 | * Drivers always need to pass packets that are aligned to two-byte boundaries | 377 | * Drivers always need to pass packets that are aligned to two-byte boundaries |
378 | * to the stack. | 378 | * to the stack. |
379 | * | 379 | * |
380 | * Additionally, should, if possible, align the payload data in a way that | 380 | * Additionally, should, if possible, align the payload data in a way that |
381 | * guarantees that the contained IP header is aligned to a four-byte | 381 | * guarantees that the contained IP header is aligned to a four-byte |
382 | * boundary. In the case of regular frames, this simply means aligning the | 382 | * boundary. In the case of regular frames, this simply means aligning the |
383 | * payload to a four-byte boundary (because either the IP header is directly | 383 | * payload to a four-byte boundary (because either the IP header is directly |
384 | * contained, or IV/RFC1042 headers that have a length divisible by four are | 384 | * contained, or IV/RFC1042 headers that have a length divisible by four are |
385 | * in front of it). | 385 | * in front of it). |
386 | * | 386 | * |
387 | * With A-MSDU frames, however, the payload data address must yield two modulo | 387 | * With A-MSDU frames, however, the payload data address must yield two modulo |
388 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that | 388 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that |
389 | * push the IP header further back to a multiple of four again. Thankfully, the | 389 | * push the IP header further back to a multiple of four again. Thankfully, the |
390 | * specs were sane enough this time around to require padding each A-MSDU | 390 | * specs were sane enough this time around to require padding each A-MSDU |
391 | * subframe to a length that is a multiple of four. | 391 | * subframe to a length that is a multiple of four. |
392 | * | 392 | * |
393 | * Padding like Atheros hardware adds which is inbetween the 802.11 header and | 393 | * Padding like Atheros hardware adds which is inbetween the 802.11 header and |
394 | * the payload is not supported, the driver is required to move the 802.11 | 394 | * the payload is not supported, the driver is required to move the 802.11 |
395 | * header to be directly in front of the payload in that case. | 395 | * header to be directly in front of the payload in that case. |
396 | */ | 396 | */ |
397 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) | 397 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) |
398 | { | 398 | { |
399 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 399 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
400 | int hdrlen; | 400 | int hdrlen; |
401 | 401 | ||
402 | #ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | 402 | #ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT |
403 | return; | 403 | return; |
404 | #endif | 404 | #endif |
405 | 405 | ||
406 | if (WARN_ONCE((unsigned long)rx->skb->data & 1, | 406 | if (WARN_ONCE((unsigned long)rx->skb->data & 1, |
407 | "unaligned packet at 0x%p\n", rx->skb->data)) | 407 | "unaligned packet at 0x%p\n", rx->skb->data)) |
408 | return; | 408 | return; |
409 | 409 | ||
410 | if (!ieee80211_is_data_present(hdr->frame_control)) | 410 | if (!ieee80211_is_data_present(hdr->frame_control)) |
411 | return; | 411 | return; |
412 | 412 | ||
413 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 413 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
414 | if (rx->flags & IEEE80211_RX_AMSDU) | 414 | if (rx->flags & IEEE80211_RX_AMSDU) |
415 | hdrlen += ETH_HLEN; | 415 | hdrlen += ETH_HLEN; |
416 | WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, | 416 | WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, |
417 | "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); | 417 | "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); |
418 | } | 418 | } |
419 | 419 | ||
420 | 420 | ||
421 | /* rx handlers */ | 421 | /* rx handlers */ |
422 | 422 | ||
423 | static ieee80211_rx_result debug_noinline | 423 | static ieee80211_rx_result debug_noinline |
424 | ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | 424 | ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) |
425 | { | 425 | { |
426 | struct ieee80211_local *local = rx->local; | 426 | struct ieee80211_local *local = rx->local; |
427 | struct sk_buff *skb = rx->skb; | 427 | struct sk_buff *skb = rx->skb; |
428 | 428 | ||
429 | if (unlikely(local->hw_scanning)) | 429 | if (unlikely(local->hw_scanning)) |
430 | return ieee80211_scan_rx(rx->sdata, skb, rx->status); | 430 | return ieee80211_scan_rx(rx->sdata, skb, rx->status); |
431 | 431 | ||
432 | if (unlikely(local->sw_scanning)) { | 432 | if (unlikely(local->sw_scanning)) { |
433 | /* drop all the other packets during a software scan anyway */ | 433 | /* drop all the other packets during a software scan anyway */ |
434 | if (ieee80211_scan_rx(rx->sdata, skb, rx->status) | 434 | if (ieee80211_scan_rx(rx->sdata, skb, rx->status) |
435 | != RX_QUEUED) | 435 | != RX_QUEUED) |
436 | dev_kfree_skb(skb); | 436 | dev_kfree_skb(skb); |
437 | return RX_QUEUED; | 437 | return RX_QUEUED; |
438 | } | 438 | } |
439 | 439 | ||
440 | if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) { | 440 | if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) { |
441 | /* scanning finished during invoking of handlers */ | 441 | /* scanning finished during invoking of handlers */ |
442 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); | 442 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); |
443 | return RX_DROP_UNUSABLE; | 443 | return RX_DROP_UNUSABLE; |
444 | } | 444 | } |
445 | 445 | ||
446 | return RX_CONTINUE; | 446 | return RX_CONTINUE; |
447 | } | 447 | } |
448 | 448 | ||
449 | |||
450 | static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | ||
451 | { | ||
452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
453 | |||
454 | if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) | ||
455 | return 0; | ||
456 | |||
457 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
458 | } | ||
459 | |||
460 | |||
461 | static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) | ||
462 | { | ||
463 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
464 | |||
465 | if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) | ||
466 | return 0; | ||
467 | |||
468 | return ieee80211_is_robust_mgmt_frame(hdr); | ||
469 | } | ||
470 | |||
471 | |||
472 | /* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */ | ||
473 | static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | ||
474 | { | ||
475 | struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; | ||
476 | struct ieee80211_mmie *mmie; | ||
477 | |||
478 | if (skb->len < 24 + sizeof(*mmie) || | ||
479 | !is_multicast_ether_addr(hdr->da)) | ||
480 | return -1; | ||
481 | |||
482 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | ||
483 | return -1; /* not a robust management frame */ | ||
484 | |||
485 | mmie = (struct ieee80211_mmie *) | ||
486 | (skb->data + skb->len - sizeof(*mmie)); | ||
487 | if (mmie->element_id != WLAN_EID_MMIE || | ||
488 | mmie->length != sizeof(*mmie) - 2) | ||
489 | return -1; | ||
490 | |||
491 | return le16_to_cpu(mmie->key_id); | ||
492 | } | ||
493 | |||
494 | |||
449 | static ieee80211_rx_result | 495 | static ieee80211_rx_result |
450 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | 496 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
451 | { | 497 | { |
452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 498 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
453 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); | 499 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
454 | 500 | ||
455 | if (ieee80211_is_data(hdr->frame_control)) { | 501 | if (ieee80211_is_data(hdr->frame_control)) { |
456 | if (!ieee80211_has_a4(hdr->frame_control)) | 502 | if (!ieee80211_has_a4(hdr->frame_control)) |
457 | return RX_DROP_MONITOR; | 503 | return RX_DROP_MONITOR; |
458 | if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) | 504 | if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) |
459 | return RX_DROP_MONITOR; | 505 | return RX_DROP_MONITOR; |
460 | } | 506 | } |
461 | 507 | ||
462 | /* If there is not an established peer link and this is not a peer link | 508 | /* If there is not an established peer link and this is not a peer link |
463 | * establisment frame, beacon or probe, drop the frame. | 509 | * establisment frame, beacon or probe, drop the frame. |
464 | */ | 510 | */ |
465 | 511 | ||
466 | if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) { | 512 | if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) { |
467 | struct ieee80211_mgmt *mgmt; | 513 | struct ieee80211_mgmt *mgmt; |
468 | 514 | ||
469 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 515 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
470 | return RX_DROP_MONITOR; | 516 | return RX_DROP_MONITOR; |
471 | 517 | ||
472 | if (ieee80211_is_action(hdr->frame_control)) { | 518 | if (ieee80211_is_action(hdr->frame_control)) { |
473 | mgmt = (struct ieee80211_mgmt *)hdr; | 519 | mgmt = (struct ieee80211_mgmt *)hdr; |
474 | if (mgmt->u.action.category != PLINK_CATEGORY) | 520 | if (mgmt->u.action.category != PLINK_CATEGORY) |
475 | return RX_DROP_MONITOR; | 521 | return RX_DROP_MONITOR; |
476 | return RX_CONTINUE; | 522 | return RX_CONTINUE; |
477 | } | 523 | } |
478 | 524 | ||
479 | if (ieee80211_is_probe_req(hdr->frame_control) || | 525 | if (ieee80211_is_probe_req(hdr->frame_control) || |
480 | ieee80211_is_probe_resp(hdr->frame_control) || | 526 | ieee80211_is_probe_resp(hdr->frame_control) || |
481 | ieee80211_is_beacon(hdr->frame_control)) | 527 | ieee80211_is_beacon(hdr->frame_control)) |
482 | return RX_CONTINUE; | 528 | return RX_CONTINUE; |
483 | 529 | ||
484 | return RX_DROP_MONITOR; | 530 | return RX_DROP_MONITOR; |
485 | 531 | ||
486 | } | 532 | } |
487 | 533 | ||
488 | #define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) | 534 | #define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) |
489 | 535 | ||
490 | if (ieee80211_is_data(hdr->frame_control) && | 536 | if (ieee80211_is_data(hdr->frame_control) && |
491 | is_multicast_ether_addr(hdr->addr1) && | 537 | is_multicast_ether_addr(hdr->addr1) && |
492 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) | 538 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) |
493 | return RX_DROP_MONITOR; | 539 | return RX_DROP_MONITOR; |
494 | #undef msh_h_get | 540 | #undef msh_h_get |
495 | 541 | ||
496 | return RX_CONTINUE; | 542 | return RX_CONTINUE; |
497 | } | 543 | } |
498 | 544 | ||
499 | 545 | ||
500 | static ieee80211_rx_result debug_noinline | 546 | static ieee80211_rx_result debug_noinline |
501 | ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | 547 | ieee80211_rx_h_check(struct ieee80211_rx_data *rx) |
502 | { | 548 | { |
503 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 549 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
504 | 550 | ||
505 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ | 551 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ |
506 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { | 552 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { |
507 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && | 553 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && |
508 | rx->sta->last_seq_ctrl[rx->queue] == | 554 | rx->sta->last_seq_ctrl[rx->queue] == |
509 | hdr->seq_ctrl)) { | 555 | hdr->seq_ctrl)) { |
510 | if (rx->flags & IEEE80211_RX_RA_MATCH) { | 556 | if (rx->flags & IEEE80211_RX_RA_MATCH) { |
511 | rx->local->dot11FrameDuplicateCount++; | 557 | rx->local->dot11FrameDuplicateCount++; |
512 | rx->sta->num_duplicates++; | 558 | rx->sta->num_duplicates++; |
513 | } | 559 | } |
514 | return RX_DROP_MONITOR; | 560 | return RX_DROP_MONITOR; |
515 | } else | 561 | } else |
516 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; | 562 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; |
517 | } | 563 | } |
518 | 564 | ||
519 | if (unlikely(rx->skb->len < 16)) { | 565 | if (unlikely(rx->skb->len < 16)) { |
520 | I802_DEBUG_INC(rx->local->rx_handlers_drop_short); | 566 | I802_DEBUG_INC(rx->local->rx_handlers_drop_short); |
521 | return RX_DROP_MONITOR; | 567 | return RX_DROP_MONITOR; |
522 | } | 568 | } |
523 | 569 | ||
524 | /* Drop disallowed frame classes based on STA auth/assoc state; | 570 | /* Drop disallowed frame classes based on STA auth/assoc state; |
525 | * IEEE 802.11, Chap 5.5. | 571 | * IEEE 802.11, Chap 5.5. |
526 | * | 572 | * |
527 | * mac80211 filters only based on association state, i.e. it drops | 573 | * mac80211 filters only based on association state, i.e. it drops |
528 | * Class 3 frames from not associated stations. hostapd sends | 574 | * Class 3 frames from not associated stations. hostapd sends |
529 | * deauth/disassoc frames when needed. In addition, hostapd is | 575 | * deauth/disassoc frames when needed. In addition, hostapd is |
530 | * responsible for filtering on both auth and assoc states. | 576 | * responsible for filtering on both auth and assoc states. |
531 | */ | 577 | */ |
532 | 578 | ||
533 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) | 579 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
534 | return ieee80211_rx_mesh_check(rx); | 580 | return ieee80211_rx_mesh_check(rx); |
535 | 581 | ||
536 | if (unlikely((ieee80211_is_data(hdr->frame_control) || | 582 | if (unlikely((ieee80211_is_data(hdr->frame_control) || |
537 | ieee80211_is_pspoll(hdr->frame_control)) && | 583 | ieee80211_is_pspoll(hdr->frame_control)) && |
538 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 584 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
539 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { | 585 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
540 | if ((!ieee80211_has_fromds(hdr->frame_control) && | 586 | if ((!ieee80211_has_fromds(hdr->frame_control) && |
541 | !ieee80211_has_tods(hdr->frame_control) && | 587 | !ieee80211_has_tods(hdr->frame_control) && |
542 | ieee80211_is_data(hdr->frame_control)) || | 588 | ieee80211_is_data(hdr->frame_control)) || |
543 | !(rx->flags & IEEE80211_RX_RA_MATCH)) { | 589 | !(rx->flags & IEEE80211_RX_RA_MATCH)) { |
544 | /* Drop IBSS frames and frames for other hosts | 590 | /* Drop IBSS frames and frames for other hosts |
545 | * silently. */ | 591 | * silently. */ |
546 | return RX_DROP_MONITOR; | 592 | return RX_DROP_MONITOR; |
547 | } | 593 | } |
548 | 594 | ||
549 | return RX_DROP_MONITOR; | 595 | return RX_DROP_MONITOR; |
550 | } | 596 | } |
551 | 597 | ||
552 | return RX_CONTINUE; | 598 | return RX_CONTINUE; |
553 | } | 599 | } |
554 | 600 | ||
555 | 601 | ||
556 | static ieee80211_rx_result debug_noinline | 602 | static ieee80211_rx_result debug_noinline |
557 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | 603 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) |
558 | { | 604 | { |
559 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 605 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
560 | int keyidx; | 606 | int keyidx; |
561 | int hdrlen; | 607 | int hdrlen; |
562 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 608 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
563 | struct ieee80211_key *stakey = NULL; | 609 | struct ieee80211_key *stakey = NULL; |
610 | int mmie_keyidx = -1; | ||
564 | 611 | ||
565 | /* | 612 | /* |
566 | * Key selection 101 | 613 | * Key selection 101 |
567 | * | 614 | * |
568 | * There are three types of keys: | 615 | * There are four types of keys: |
569 | * - GTK (group keys) | 616 | * - GTK (group keys) |
617 | * - IGTK (group keys for management frames) | ||
570 | * - PTK (pairwise keys) | 618 | * - PTK (pairwise keys) |
571 | * - STK (station-to-station pairwise keys) | 619 | * - STK (station-to-station pairwise keys) |
572 | * | 620 | * |
573 | * When selecting a key, we have to distinguish between multicast | 621 | * When selecting a key, we have to distinguish between multicast |
574 | * (including broadcast) and unicast frames, the latter can only | 622 | * (including broadcast) and unicast frames, the latter can only |
575 | * use PTKs and STKs while the former always use GTKs. Unless, of | 623 | * use PTKs and STKs while the former always use GTKs and IGTKs. |
576 | * course, actual WEP keys ("pre-RSNA") are used, then unicast | 624 | * Unless, of course, actual WEP keys ("pre-RSNA") are used, then |
577 | * frames can also use key indizes like GTKs. Hence, if we don't | 625 | * unicast frames can also use key indices like GTKs. Hence, if we |
578 | * have a PTK/STK we check the key index for a WEP key. | 626 | * don't have a PTK/STK we check the key index for a WEP key. |
579 | * | 627 | * |
580 | * Note that in a regular BSS, multicast frames are sent by the | 628 | * Note that in a regular BSS, multicast frames are sent by the |
581 | * AP only, associated stations unicast the frame to the AP first | 629 | * AP only, associated stations unicast the frame to the AP first |
582 | * which then multicasts it on their behalf. | 630 | * which then multicasts it on their behalf. |
583 | * | 631 | * |
584 | * There is also a slight problem in IBSS mode: GTKs are negotiated | 632 | * There is also a slight problem in IBSS mode: GTKs are negotiated |
585 | * with each station, that is something we don't currently handle. | 633 | * with each station, that is something we don't currently handle. |
586 | * The spec seems to expect that one negotiates the same key with | 634 | * The spec seems to expect that one negotiates the same key with |
587 | * every station but there's no such requirement; VLANs could be | 635 | * every station but there's no such requirement; VLANs could be |
588 | * possible. | 636 | * possible. |
589 | */ | 637 | */ |
590 | 638 | ||
591 | if (!ieee80211_has_protected(hdr->frame_control)) | 639 | if (!ieee80211_has_protected(hdr->frame_control)) { |
592 | return RX_CONTINUE; | 640 | if (!ieee80211_is_mgmt(hdr->frame_control) || |
641 | rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) | ||
642 | return RX_CONTINUE; | ||
643 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
644 | if (mmie_keyidx < 0) | ||
645 | return RX_CONTINUE; | ||
646 | } | ||
593 | 647 | ||
594 | /* | 648 | /* |
595 | * No point in finding a key and decrypting if the frame is neither | 649 | * No point in finding a key and decrypting if the frame is neither |
596 | * addressed to us nor a multicast frame. | 650 | * addressed to us nor a multicast frame. |
597 | */ | 651 | */ |
598 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 652 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
599 | return RX_CONTINUE; | 653 | return RX_CONTINUE; |
600 | 654 | ||
601 | if (rx->sta) | 655 | if (rx->sta) |
602 | stakey = rcu_dereference(rx->sta->key); | 656 | stakey = rcu_dereference(rx->sta->key); |
603 | 657 | ||
604 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 658 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
605 | rx->key = stakey; | 659 | rx->key = stakey; |
660 | } else if (mmie_keyidx >= 0) { | ||
661 | /* Broadcast/multicast robust management frame / BIP */ | ||
662 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | ||
663 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | ||
664 | return RX_CONTINUE; | ||
665 | |||
666 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | ||
667 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
668 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | ||
669 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
606 | } else { | 670 | } else { |
607 | /* | 671 | /* |
608 | * The device doesn't give us the IV so we won't be | 672 | * The device doesn't give us the IV so we won't be |
609 | * able to look up the key. That's ok though, we | 673 | * able to look up the key. That's ok though, we |
610 | * don't need to decrypt the frame, we just won't | 674 | * don't need to decrypt the frame, we just won't |
611 | * be able to keep statistics accurate. | 675 | * be able to keep statistics accurate. |
612 | * Except for key threshold notifications, should | 676 | * Except for key threshold notifications, should |
613 | * we somehow allow the driver to tell us which key | 677 | * we somehow allow the driver to tell us which key |
614 | * the hardware used if this flag is set? | 678 | * the hardware used if this flag is set? |
615 | */ | 679 | */ |
616 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | 680 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && |
617 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | 681 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) |
618 | return RX_CONTINUE; | 682 | return RX_CONTINUE; |
619 | 683 | ||
620 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 684 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
621 | 685 | ||
622 | if (rx->skb->len < 8 + hdrlen) | 686 | if (rx->skb->len < 8 + hdrlen) |
623 | return RX_DROP_UNUSABLE; /* TODO: count this? */ | 687 | return RX_DROP_UNUSABLE; /* TODO: count this? */ |
624 | 688 | ||
625 | /* | 689 | /* |
626 | * no need to call ieee80211_wep_get_keyidx, | 690 | * no need to call ieee80211_wep_get_keyidx, |
627 | * it verifies a bunch of things we've done already | 691 | * it verifies a bunch of things we've done already |
628 | */ | 692 | */ |
629 | keyidx = rx->skb->data[hdrlen + 3] >> 6; | 693 | keyidx = rx->skb->data[hdrlen + 3] >> 6; |
630 | 694 | ||
631 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | 695 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); |
632 | 696 | ||
633 | /* | 697 | /* |
634 | * RSNA-protected unicast frames should always be sent with | 698 | * RSNA-protected unicast frames should always be sent with |
635 | * pairwise or station-to-station keys, but for WEP we allow | 699 | * pairwise or station-to-station keys, but for WEP we allow |
636 | * using a key index as well. | 700 | * using a key index as well. |
637 | */ | 701 | */ |
638 | if (rx->key && rx->key->conf.alg != ALG_WEP && | 702 | if (rx->key && rx->key->conf.alg != ALG_WEP && |
639 | !is_multicast_ether_addr(hdr->addr1)) | 703 | !is_multicast_ether_addr(hdr->addr1)) |
640 | rx->key = NULL; | 704 | rx->key = NULL; |
641 | } | 705 | } |
642 | 706 | ||
643 | if (rx->key) { | 707 | if (rx->key) { |
644 | rx->key->tx_rx_count++; | 708 | rx->key->tx_rx_count++; |
645 | /* TODO: add threshold stuff again */ | 709 | /* TODO: add threshold stuff again */ |
646 | } else { | 710 | } else { |
647 | return RX_DROP_MONITOR; | 711 | return RX_DROP_MONITOR; |
648 | } | 712 | } |
649 | 713 | ||
650 | /* Check for weak IVs if possible */ | 714 | /* Check for weak IVs if possible */ |
651 | if (rx->sta && rx->key->conf.alg == ALG_WEP && | 715 | if (rx->sta && rx->key->conf.alg == ALG_WEP && |
652 | ieee80211_is_data(hdr->frame_control) && | 716 | ieee80211_is_data(hdr->frame_control) && |
653 | (!(rx->status->flag & RX_FLAG_IV_STRIPPED) || | 717 | (!(rx->status->flag & RX_FLAG_IV_STRIPPED) || |
654 | !(rx->status->flag & RX_FLAG_DECRYPTED)) && | 718 | !(rx->status->flag & RX_FLAG_DECRYPTED)) && |
655 | ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | 719 | ieee80211_wep_is_weak_iv(rx->skb, rx->key)) |
656 | rx->sta->wep_weak_iv_count++; | 720 | rx->sta->wep_weak_iv_count++; |
657 | 721 | ||
658 | switch (rx->key->conf.alg) { | 722 | switch (rx->key->conf.alg) { |
659 | case ALG_WEP: | 723 | case ALG_WEP: |
660 | result = ieee80211_crypto_wep_decrypt(rx); | 724 | result = ieee80211_crypto_wep_decrypt(rx); |
661 | break; | 725 | break; |
662 | case ALG_TKIP: | 726 | case ALG_TKIP: |
663 | result = ieee80211_crypto_tkip_decrypt(rx); | 727 | result = ieee80211_crypto_tkip_decrypt(rx); |
664 | break; | 728 | break; |
665 | case ALG_CCMP: | 729 | case ALG_CCMP: |
666 | result = ieee80211_crypto_ccmp_decrypt(rx); | 730 | result = ieee80211_crypto_ccmp_decrypt(rx); |
667 | break; | 731 | break; |
732 | case ALG_AES_CMAC: | ||
733 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | ||
734 | break; | ||
668 | } | 735 | } |
669 | 736 | ||
670 | /* either the frame has been decrypted or will be dropped */ | 737 | /* either the frame has been decrypted or will be dropped */ |
671 | rx->status->flag |= RX_FLAG_DECRYPTED; | 738 | rx->status->flag |= RX_FLAG_DECRYPTED; |
672 | 739 | ||
673 | return result; | 740 | return result; |
674 | } | 741 | } |
675 | 742 | ||
676 | static void ap_sta_ps_start(struct sta_info *sta) | 743 | static void ap_sta_ps_start(struct sta_info *sta) |
677 | { | 744 | { |
678 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 745 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
679 | struct ieee80211_local *local = sdata->local; | 746 | struct ieee80211_local *local = sdata->local; |
680 | 747 | ||
681 | atomic_inc(&sdata->bss->num_sta_ps); | 748 | atomic_inc(&sdata->bss->num_sta_ps); |
682 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 749 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
683 | if (local->ops->sta_notify) | 750 | if (local->ops->sta_notify) |
684 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 751 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
685 | STA_NOTIFY_SLEEP, &sta->sta); | 752 | STA_NOTIFY_SLEEP, &sta->sta); |
686 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 753 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
687 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 754 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
688 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 755 | sdata->dev->name, sta->sta.addr, sta->sta.aid); |
689 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 756 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
690 | } | 757 | } |
691 | 758 | ||
692 | static int ap_sta_ps_end(struct sta_info *sta) | 759 | static int ap_sta_ps_end(struct sta_info *sta) |
693 | { | 760 | { |
694 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 761 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
695 | struct ieee80211_local *local = sdata->local; | 762 | struct ieee80211_local *local = sdata->local; |
696 | struct sk_buff *skb; | 763 | struct sk_buff *skb; |
697 | int sent = 0; | 764 | int sent = 0; |
698 | 765 | ||
699 | atomic_dec(&sdata->bss->num_sta_ps); | 766 | atomic_dec(&sdata->bss->num_sta_ps); |
700 | 767 | ||
701 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 768 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
702 | if (local->ops->sta_notify) | 769 | if (local->ops->sta_notify) |
703 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 770 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
704 | STA_NOTIFY_AWAKE, &sta->sta); | 771 | STA_NOTIFY_AWAKE, &sta->sta); |
705 | 772 | ||
706 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 773 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
707 | sta_info_clear_tim_bit(sta); | 774 | sta_info_clear_tim_bit(sta); |
708 | 775 | ||
709 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 776 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
710 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 777 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", |
711 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 778 | sdata->dev->name, sta->sta.addr, sta->sta.aid); |
712 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 779 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
713 | 780 | ||
714 | /* Send all buffered frames to the station */ | 781 | /* Send all buffered frames to the station */ |
715 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 782 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { |
716 | sent++; | 783 | sent++; |
717 | skb->requeue = 1; | 784 | skb->requeue = 1; |
718 | dev_queue_xmit(skb); | 785 | dev_queue_xmit(skb); |
719 | } | 786 | } |
720 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | 787 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { |
721 | local->total_ps_buffered--; | 788 | local->total_ps_buffered--; |
722 | sent++; | 789 | sent++; |
723 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 790 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
724 | printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame " | 791 | printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame " |
725 | "since STA not sleeping anymore\n", sdata->dev->name, | 792 | "since STA not sleeping anymore\n", sdata->dev->name, |
726 | sta->sta.addr, sta->sta.aid); | 793 | sta->sta.addr, sta->sta.aid); |
727 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 794 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
728 | skb->requeue = 1; | 795 | skb->requeue = 1; |
729 | dev_queue_xmit(skb); | 796 | dev_queue_xmit(skb); |
730 | } | 797 | } |
731 | 798 | ||
732 | return sent; | 799 | return sent; |
733 | } | 800 | } |
734 | 801 | ||
735 | static ieee80211_rx_result debug_noinline | 802 | static ieee80211_rx_result debug_noinline |
736 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 803 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
737 | { | 804 | { |
738 | struct sta_info *sta = rx->sta; | 805 | struct sta_info *sta = rx->sta; |
739 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 806 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
740 | 807 | ||
741 | if (!sta) | 808 | if (!sta) |
742 | return RX_CONTINUE; | 809 | return RX_CONTINUE; |
743 | 810 | ||
744 | /* Update last_rx only for IBSS packets which are for the current | 811 | /* Update last_rx only for IBSS packets which are for the current |
745 | * BSSID to avoid keeping the current IBSS network alive in cases where | 812 | * BSSID to avoid keeping the current IBSS network alive in cases where |
746 | * other STAs are using different BSSID. */ | 813 | * other STAs are using different BSSID. */ |
747 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 814 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
748 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 815 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, |
749 | NL80211_IFTYPE_ADHOC); | 816 | NL80211_IFTYPE_ADHOC); |
750 | if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) | 817 | if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) |
751 | sta->last_rx = jiffies; | 818 | sta->last_rx = jiffies; |
752 | } else | 819 | } else |
753 | if (!is_multicast_ether_addr(hdr->addr1) || | 820 | if (!is_multicast_ether_addr(hdr->addr1) || |
754 | rx->sdata->vif.type == NL80211_IFTYPE_STATION) { | 821 | rx->sdata->vif.type == NL80211_IFTYPE_STATION) { |
755 | /* Update last_rx only for unicast frames in order to prevent | 822 | /* Update last_rx only for unicast frames in order to prevent |
756 | * the Probe Request frames (the only broadcast frames from a | 823 | * the Probe Request frames (the only broadcast frames from a |
757 | * STA in infrastructure mode) from keeping a connection alive. | 824 | * STA in infrastructure mode) from keeping a connection alive. |
758 | * Mesh beacons will update last_rx when if they are found to | 825 | * Mesh beacons will update last_rx when if they are found to |
759 | * match the current local configuration when processed. | 826 | * match the current local configuration when processed. |
760 | */ | 827 | */ |
761 | sta->last_rx = jiffies; | 828 | sta->last_rx = jiffies; |
762 | } | 829 | } |
763 | 830 | ||
764 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 831 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
765 | return RX_CONTINUE; | 832 | return RX_CONTINUE; |
766 | 833 | ||
767 | sta->rx_fragments++; | 834 | sta->rx_fragments++; |
768 | sta->rx_bytes += rx->skb->len; | 835 | sta->rx_bytes += rx->skb->len; |
769 | sta->last_signal = rx->status->signal; | 836 | sta->last_signal = rx->status->signal; |
770 | sta->last_qual = rx->status->qual; | 837 | sta->last_qual = rx->status->qual; |
771 | sta->last_noise = rx->status->noise; | 838 | sta->last_noise = rx->status->noise; |
772 | 839 | ||
773 | /* | 840 | /* |
774 | * Change STA power saving mode only at the end of a frame | 841 | * Change STA power saving mode only at the end of a frame |
775 | * exchange sequence. | 842 | * exchange sequence. |
776 | */ | 843 | */ |
777 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 844 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
778 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 845 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
779 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 846 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
780 | if (test_sta_flags(sta, WLAN_STA_PS)) { | 847 | if (test_sta_flags(sta, WLAN_STA_PS)) { |
781 | /* | 848 | /* |
782 | * Ignore doze->wake transitions that are | 849 | * Ignore doze->wake transitions that are |
783 | * indicated by non-data frames, the standard | 850 | * indicated by non-data frames, the standard |
784 | * is unclear here, but for example going to | 851 | * is unclear here, but for example going to |
785 | * PS mode and then scanning would cause a | 852 | * PS mode and then scanning would cause a |
786 | * doze->wake transition for the probe request, | 853 | * doze->wake transition for the probe request, |
787 | * and that is clearly undesirable. | 854 | * and that is clearly undesirable. |
788 | */ | 855 | */ |
789 | if (ieee80211_is_data(hdr->frame_control) && | 856 | if (ieee80211_is_data(hdr->frame_control) && |
790 | !ieee80211_has_pm(hdr->frame_control)) | 857 | !ieee80211_has_pm(hdr->frame_control)) |
791 | rx->sent_ps_buffered += ap_sta_ps_end(sta); | 858 | rx->sent_ps_buffered += ap_sta_ps_end(sta); |
792 | } else { | 859 | } else { |
793 | if (ieee80211_has_pm(hdr->frame_control)) | 860 | if (ieee80211_has_pm(hdr->frame_control)) |
794 | ap_sta_ps_start(sta); | 861 | ap_sta_ps_start(sta); |
795 | } | 862 | } |
796 | } | 863 | } |
797 | 864 | ||
798 | /* Drop data::nullfunc frames silently, since they are used only to | 865 | /* Drop data::nullfunc frames silently, since they are used only to |
799 | * control station power saving mode. */ | 866 | * control station power saving mode. */ |
800 | if (ieee80211_is_nullfunc(hdr->frame_control)) { | 867 | if (ieee80211_is_nullfunc(hdr->frame_control)) { |
801 | I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); | 868 | I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); |
802 | /* Update counter and free packet here to avoid counting this | 869 | /* Update counter and free packet here to avoid counting this |
803 | * as a dropped packed. */ | 870 | * as a dropped packed. */ |
804 | sta->rx_packets++; | 871 | sta->rx_packets++; |
805 | dev_kfree_skb(rx->skb); | 872 | dev_kfree_skb(rx->skb); |
806 | return RX_QUEUED; | 873 | return RX_QUEUED; |
807 | } | 874 | } |
808 | 875 | ||
809 | return RX_CONTINUE; | 876 | return RX_CONTINUE; |
810 | } /* ieee80211_rx_h_sta_process */ | 877 | } /* ieee80211_rx_h_sta_process */ |
811 | 878 | ||
812 | static inline struct ieee80211_fragment_entry * | 879 | static inline struct ieee80211_fragment_entry * |
813 | ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | 880 | ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, |
814 | unsigned int frag, unsigned int seq, int rx_queue, | 881 | unsigned int frag, unsigned int seq, int rx_queue, |
815 | struct sk_buff **skb) | 882 | struct sk_buff **skb) |
816 | { | 883 | { |
817 | struct ieee80211_fragment_entry *entry; | 884 | struct ieee80211_fragment_entry *entry; |
818 | int idx; | 885 | int idx; |
819 | 886 | ||
820 | idx = sdata->fragment_next; | 887 | idx = sdata->fragment_next; |
821 | entry = &sdata->fragments[sdata->fragment_next++]; | 888 | entry = &sdata->fragments[sdata->fragment_next++]; |
822 | if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX) | 889 | if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX) |
823 | sdata->fragment_next = 0; | 890 | sdata->fragment_next = 0; |
824 | 891 | ||
825 | if (!skb_queue_empty(&entry->skb_list)) { | 892 | if (!skb_queue_empty(&entry->skb_list)) { |
826 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 893 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
827 | struct ieee80211_hdr *hdr = | 894 | struct ieee80211_hdr *hdr = |
828 | (struct ieee80211_hdr *) entry->skb_list.next->data; | 895 | (struct ieee80211_hdr *) entry->skb_list.next->data; |
829 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " | 896 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " |
830 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " | 897 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " |
831 | "addr1=%pM addr2=%pM\n", | 898 | "addr1=%pM addr2=%pM\n", |
832 | sdata->dev->name, idx, | 899 | sdata->dev->name, idx, |
833 | jiffies - entry->first_frag_time, entry->seq, | 900 | jiffies - entry->first_frag_time, entry->seq, |
834 | entry->last_frag, hdr->addr1, hdr->addr2); | 901 | entry->last_frag, hdr->addr1, hdr->addr2); |
835 | #endif | 902 | #endif |
836 | __skb_queue_purge(&entry->skb_list); | 903 | __skb_queue_purge(&entry->skb_list); |
837 | } | 904 | } |
838 | 905 | ||
839 | __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */ | 906 | __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */ |
840 | *skb = NULL; | 907 | *skb = NULL; |
841 | entry->first_frag_time = jiffies; | 908 | entry->first_frag_time = jiffies; |
842 | entry->seq = seq; | 909 | entry->seq = seq; |
843 | entry->rx_queue = rx_queue; | 910 | entry->rx_queue = rx_queue; |
844 | entry->last_frag = frag; | 911 | entry->last_frag = frag; |
845 | entry->ccmp = 0; | 912 | entry->ccmp = 0; |
846 | entry->extra_len = 0; | 913 | entry->extra_len = 0; |
847 | 914 | ||
848 | return entry; | 915 | return entry; |
849 | } | 916 | } |
850 | 917 | ||
851 | static inline struct ieee80211_fragment_entry * | 918 | static inline struct ieee80211_fragment_entry * |
852 | ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, | 919 | ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, |
853 | unsigned int frag, unsigned int seq, | 920 | unsigned int frag, unsigned int seq, |
854 | int rx_queue, struct ieee80211_hdr *hdr) | 921 | int rx_queue, struct ieee80211_hdr *hdr) |
855 | { | 922 | { |
856 | struct ieee80211_fragment_entry *entry; | 923 | struct ieee80211_fragment_entry *entry; |
857 | int i, idx; | 924 | int i, idx; |
858 | 925 | ||
859 | idx = sdata->fragment_next; | 926 | idx = sdata->fragment_next; |
860 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { | 927 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { |
861 | struct ieee80211_hdr *f_hdr; | 928 | struct ieee80211_hdr *f_hdr; |
862 | 929 | ||
863 | idx--; | 930 | idx--; |
864 | if (idx < 0) | 931 | if (idx < 0) |
865 | idx = IEEE80211_FRAGMENT_MAX - 1; | 932 | idx = IEEE80211_FRAGMENT_MAX - 1; |
866 | 933 | ||
867 | entry = &sdata->fragments[idx]; | 934 | entry = &sdata->fragments[idx]; |
868 | if (skb_queue_empty(&entry->skb_list) || entry->seq != seq || | 935 | if (skb_queue_empty(&entry->skb_list) || entry->seq != seq || |
869 | entry->rx_queue != rx_queue || | 936 | entry->rx_queue != rx_queue || |
870 | entry->last_frag + 1 != frag) | 937 | entry->last_frag + 1 != frag) |
871 | continue; | 938 | continue; |
872 | 939 | ||
873 | f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data; | 940 | f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data; |
874 | 941 | ||
875 | /* | 942 | /* |
876 | * Check ftype and addresses are equal, else check next fragment | 943 | * Check ftype and addresses are equal, else check next fragment |
877 | */ | 944 | */ |
878 | if (((hdr->frame_control ^ f_hdr->frame_control) & | 945 | if (((hdr->frame_control ^ f_hdr->frame_control) & |
879 | cpu_to_le16(IEEE80211_FCTL_FTYPE)) || | 946 | cpu_to_le16(IEEE80211_FCTL_FTYPE)) || |
880 | compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || | 947 | compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || |
881 | compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) | 948 | compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) |
882 | continue; | 949 | continue; |
883 | 950 | ||
884 | if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) { | 951 | if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) { |
885 | __skb_queue_purge(&entry->skb_list); | 952 | __skb_queue_purge(&entry->skb_list); |
886 | continue; | 953 | continue; |
887 | } | 954 | } |
888 | return entry; | 955 | return entry; |
889 | } | 956 | } |
890 | 957 | ||
891 | return NULL; | 958 | return NULL; |
892 | } | 959 | } |
893 | 960 | ||
894 | static ieee80211_rx_result debug_noinline | 961 | static ieee80211_rx_result debug_noinline |
895 | ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | 962 | ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) |
896 | { | 963 | { |
897 | struct ieee80211_hdr *hdr; | 964 | struct ieee80211_hdr *hdr; |
898 | u16 sc; | 965 | u16 sc; |
899 | __le16 fc; | 966 | __le16 fc; |
900 | unsigned int frag, seq; | 967 | unsigned int frag, seq; |
901 | struct ieee80211_fragment_entry *entry; | 968 | struct ieee80211_fragment_entry *entry; |
902 | struct sk_buff *skb; | 969 | struct sk_buff *skb; |
903 | 970 | ||
904 | hdr = (struct ieee80211_hdr *)rx->skb->data; | 971 | hdr = (struct ieee80211_hdr *)rx->skb->data; |
905 | fc = hdr->frame_control; | 972 | fc = hdr->frame_control; |
906 | sc = le16_to_cpu(hdr->seq_ctrl); | 973 | sc = le16_to_cpu(hdr->seq_ctrl); |
907 | frag = sc & IEEE80211_SCTL_FRAG; | 974 | frag = sc & IEEE80211_SCTL_FRAG; |
908 | 975 | ||
909 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || | 976 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || |
910 | (rx->skb)->len < 24 || | 977 | (rx->skb)->len < 24 || |
911 | is_multicast_ether_addr(hdr->addr1))) { | 978 | is_multicast_ether_addr(hdr->addr1))) { |
912 | /* not fragmented */ | 979 | /* not fragmented */ |
913 | goto out; | 980 | goto out; |
914 | } | 981 | } |
915 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); | 982 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); |
916 | 983 | ||
917 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | 984 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; |
918 | 985 | ||
919 | if (frag == 0) { | 986 | if (frag == 0) { |
920 | /* This is the first fragment of a new frame. */ | 987 | /* This is the first fragment of a new frame. */ |
921 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 988 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
922 | rx->queue, &(rx->skb)); | 989 | rx->queue, &(rx->skb)); |
923 | if (rx->key && rx->key->conf.alg == ALG_CCMP && | 990 | if (rx->key && rx->key->conf.alg == ALG_CCMP && |
924 | ieee80211_has_protected(fc)) { | 991 | ieee80211_has_protected(fc)) { |
925 | /* Store CCMP PN so that we can verify that the next | 992 | /* Store CCMP PN so that we can verify that the next |
926 | * fragment has a sequential PN value. */ | 993 | * fragment has a sequential PN value. */ |
927 | entry->ccmp = 1; | 994 | entry->ccmp = 1; |
928 | memcpy(entry->last_pn, | 995 | memcpy(entry->last_pn, |
929 | rx->key->u.ccmp.rx_pn[rx->queue], | 996 | rx->key->u.ccmp.rx_pn[rx->queue], |
930 | CCMP_PN_LEN); | 997 | CCMP_PN_LEN); |
931 | } | 998 | } |
932 | return RX_QUEUED; | 999 | return RX_QUEUED; |
933 | } | 1000 | } |
934 | 1001 | ||
935 | /* This is a fragment for a frame that should already be pending in | 1002 | /* This is a fragment for a frame that should already be pending in |
936 | * fragment cache. Add this fragment to the end of the pending entry. | 1003 | * fragment cache. Add this fragment to the end of the pending entry. |
937 | */ | 1004 | */ |
938 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); | 1005 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); |
939 | if (!entry) { | 1006 | if (!entry) { |
940 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 1007 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
941 | return RX_DROP_MONITOR; | 1008 | return RX_DROP_MONITOR; |
942 | } | 1009 | } |
943 | 1010 | ||
944 | /* Verify that MPDUs within one MSDU have sequential PN values. | 1011 | /* Verify that MPDUs within one MSDU have sequential PN values. |
945 | * (IEEE 802.11i, 8.3.3.4.5) */ | 1012 | * (IEEE 802.11i, 8.3.3.4.5) */ |
946 | if (entry->ccmp) { | 1013 | if (entry->ccmp) { |
947 | int i; | 1014 | int i; |
948 | u8 pn[CCMP_PN_LEN], *rpn; | 1015 | u8 pn[CCMP_PN_LEN], *rpn; |
949 | if (!rx->key || rx->key->conf.alg != ALG_CCMP) | 1016 | if (!rx->key || rx->key->conf.alg != ALG_CCMP) |
950 | return RX_DROP_UNUSABLE; | 1017 | return RX_DROP_UNUSABLE; |
951 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); | 1018 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); |
952 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { | 1019 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { |
953 | pn[i]++; | 1020 | pn[i]++; |
954 | if (pn[i]) | 1021 | if (pn[i]) |
955 | break; | 1022 | break; |
956 | } | 1023 | } |
957 | rpn = rx->key->u.ccmp.rx_pn[rx->queue]; | 1024 | rpn = rx->key->u.ccmp.rx_pn[rx->queue]; |
958 | if (memcmp(pn, rpn, CCMP_PN_LEN)) | 1025 | if (memcmp(pn, rpn, CCMP_PN_LEN)) |
959 | return RX_DROP_UNUSABLE; | 1026 | return RX_DROP_UNUSABLE; |
960 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); | 1027 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); |
961 | } | 1028 | } |
962 | 1029 | ||
963 | skb_pull(rx->skb, ieee80211_hdrlen(fc)); | 1030 | skb_pull(rx->skb, ieee80211_hdrlen(fc)); |
964 | __skb_queue_tail(&entry->skb_list, rx->skb); | 1031 | __skb_queue_tail(&entry->skb_list, rx->skb); |
965 | entry->last_frag = frag; | 1032 | entry->last_frag = frag; |
966 | entry->extra_len += rx->skb->len; | 1033 | entry->extra_len += rx->skb->len; |
967 | if (ieee80211_has_morefrags(fc)) { | 1034 | if (ieee80211_has_morefrags(fc)) { |
968 | rx->skb = NULL; | 1035 | rx->skb = NULL; |
969 | return RX_QUEUED; | 1036 | return RX_QUEUED; |
970 | } | 1037 | } |
971 | 1038 | ||
972 | rx->skb = __skb_dequeue(&entry->skb_list); | 1039 | rx->skb = __skb_dequeue(&entry->skb_list); |
973 | if (skb_tailroom(rx->skb) < entry->extra_len) { | 1040 | if (skb_tailroom(rx->skb) < entry->extra_len) { |
974 | I802_DEBUG_INC(rx->local->rx_expand_skb_head2); | 1041 | I802_DEBUG_INC(rx->local->rx_expand_skb_head2); |
975 | if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len, | 1042 | if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len, |
976 | GFP_ATOMIC))) { | 1043 | GFP_ATOMIC))) { |
977 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 1044 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
978 | __skb_queue_purge(&entry->skb_list); | 1045 | __skb_queue_purge(&entry->skb_list); |
979 | return RX_DROP_UNUSABLE; | 1046 | return RX_DROP_UNUSABLE; |
980 | } | 1047 | } |
981 | } | 1048 | } |
982 | while ((skb = __skb_dequeue(&entry->skb_list))) { | 1049 | while ((skb = __skb_dequeue(&entry->skb_list))) { |
983 | memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len); | 1050 | memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len); |
984 | dev_kfree_skb(skb); | 1051 | dev_kfree_skb(skb); |
985 | } | 1052 | } |
986 | 1053 | ||
987 | /* Complete frame has been reassembled - process it now */ | 1054 | /* Complete frame has been reassembled - process it now */ |
988 | rx->flags |= IEEE80211_RX_FRAGMENTED; | 1055 | rx->flags |= IEEE80211_RX_FRAGMENTED; |
989 | 1056 | ||
990 | out: | 1057 | out: |
991 | if (rx->sta) | 1058 | if (rx->sta) |
992 | rx->sta->rx_packets++; | 1059 | rx->sta->rx_packets++; |
993 | if (is_multicast_ether_addr(hdr->addr1)) | 1060 | if (is_multicast_ether_addr(hdr->addr1)) |
994 | rx->local->dot11MulticastReceivedFrameCount++; | 1061 | rx->local->dot11MulticastReceivedFrameCount++; |
995 | else | 1062 | else |
996 | ieee80211_led_rx(rx->local); | 1063 | ieee80211_led_rx(rx->local); |
997 | return RX_CONTINUE; | 1064 | return RX_CONTINUE; |
998 | } | 1065 | } |
999 | 1066 | ||
1000 | static ieee80211_rx_result debug_noinline | 1067 | static ieee80211_rx_result debug_noinline |
1001 | ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | 1068 | ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) |
1002 | { | 1069 | { |
1003 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1070 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1004 | struct sk_buff *skb; | 1071 | struct sk_buff *skb; |
1005 | int no_pending_pkts; | 1072 | int no_pending_pkts; |
1006 | __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; | 1073 | __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; |
1007 | 1074 | ||
1008 | if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || | 1075 | if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || |
1009 | !(rx->flags & IEEE80211_RX_RA_MATCH))) | 1076 | !(rx->flags & IEEE80211_RX_RA_MATCH))) |
1010 | return RX_CONTINUE; | 1077 | return RX_CONTINUE; |
1011 | 1078 | ||
1012 | if ((sdata->vif.type != NL80211_IFTYPE_AP) && | 1079 | if ((sdata->vif.type != NL80211_IFTYPE_AP) && |
1013 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) | 1080 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
1014 | return RX_DROP_UNUSABLE; | 1081 | return RX_DROP_UNUSABLE; |
1015 | 1082 | ||
1016 | skb = skb_dequeue(&rx->sta->tx_filtered); | 1083 | skb = skb_dequeue(&rx->sta->tx_filtered); |
1017 | if (!skb) { | 1084 | if (!skb) { |
1018 | skb = skb_dequeue(&rx->sta->ps_tx_buf); | 1085 | skb = skb_dequeue(&rx->sta->ps_tx_buf); |
1019 | if (skb) | 1086 | if (skb) |
1020 | rx->local->total_ps_buffered--; | 1087 | rx->local->total_ps_buffered--; |
1021 | } | 1088 | } |
1022 | no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) && | 1089 | no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) && |
1023 | skb_queue_empty(&rx->sta->ps_tx_buf); | 1090 | skb_queue_empty(&rx->sta->ps_tx_buf); |
1024 | 1091 | ||
1025 | if (skb) { | 1092 | if (skb) { |
1026 | struct ieee80211_hdr *hdr = | 1093 | struct ieee80211_hdr *hdr = |
1027 | (struct ieee80211_hdr *) skb->data; | 1094 | (struct ieee80211_hdr *) skb->data; |
1028 | 1095 | ||
1029 | /* | 1096 | /* |
1030 | * Tell TX path to send one frame even though the STA may | 1097 | * Tell TX path to send one frame even though the STA may |
1031 | * still remain is PS mode after this frame exchange. | 1098 | * still remain is PS mode after this frame exchange. |
1032 | */ | 1099 | */ |
1033 | set_sta_flags(rx->sta, WLAN_STA_PSPOLL); | 1100 | set_sta_flags(rx->sta, WLAN_STA_PSPOLL); |
1034 | 1101 | ||
1035 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1102 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1036 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", | 1103 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", |
1037 | rx->sta->sta.addr, rx->sta->sta.aid, | 1104 | rx->sta->sta.addr, rx->sta->sta.aid, |
1038 | skb_queue_len(&rx->sta->ps_tx_buf)); | 1105 | skb_queue_len(&rx->sta->ps_tx_buf)); |
1039 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1106 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1040 | 1107 | ||
1041 | /* Use MoreData flag to indicate whether there are more | 1108 | /* Use MoreData flag to indicate whether there are more |
1042 | * buffered frames for this STA */ | 1109 | * buffered frames for this STA */ |
1043 | if (no_pending_pkts) | 1110 | if (no_pending_pkts) |
1044 | hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | 1111 | hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); |
1045 | else | 1112 | else |
1046 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1113 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
1047 | 1114 | ||
1048 | dev_queue_xmit(skb); | 1115 | dev_queue_xmit(skb); |
1049 | 1116 | ||
1050 | if (no_pending_pkts) | 1117 | if (no_pending_pkts) |
1051 | sta_info_clear_tim_bit(rx->sta); | 1118 | sta_info_clear_tim_bit(rx->sta); |
1052 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1119 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1053 | } else if (!rx->sent_ps_buffered) { | 1120 | } else if (!rx->sent_ps_buffered) { |
1054 | /* | 1121 | /* |
1055 | * FIXME: This can be the result of a race condition between | 1122 | * FIXME: This can be the result of a race condition between |
1056 | * us expiring a frame and the station polling for it. | 1123 | * us expiring a frame and the station polling for it. |
1057 | * Should we send it a null-func frame indicating we | 1124 | * Should we send it a null-func frame indicating we |
1058 | * have nothing buffered for it? | 1125 | * have nothing buffered for it? |
1059 | */ | 1126 | */ |
1060 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " | 1127 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " |
1061 | "though there are no buffered frames for it\n", | 1128 | "though there are no buffered frames for it\n", |
1062 | rx->dev->name, rx->sta->sta.addr); | 1129 | rx->dev->name, rx->sta->sta.addr); |
1063 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1130 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1064 | } | 1131 | } |
1065 | 1132 | ||
1066 | /* Free PS Poll skb here instead of returning RX_DROP that would | 1133 | /* Free PS Poll skb here instead of returning RX_DROP that would |
1067 | * count as an dropped frame. */ | 1134 | * count as an dropped frame. */ |
1068 | dev_kfree_skb(rx->skb); | 1135 | dev_kfree_skb(rx->skb); |
1069 | 1136 | ||
1070 | return RX_QUEUED; | 1137 | return RX_QUEUED; |
1071 | } | 1138 | } |
1072 | 1139 | ||
1073 | static ieee80211_rx_result debug_noinline | 1140 | static ieee80211_rx_result debug_noinline |
1074 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | 1141 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) |
1075 | { | 1142 | { |
1076 | u8 *data = rx->skb->data; | 1143 | u8 *data = rx->skb->data; |
1077 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; | 1144 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; |
1078 | 1145 | ||
1079 | if (!ieee80211_is_data_qos(hdr->frame_control)) | 1146 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
1080 | return RX_CONTINUE; | 1147 | return RX_CONTINUE; |
1081 | 1148 | ||
1082 | /* remove the qos control field, update frame type and meta-data */ | 1149 | /* remove the qos control field, update frame type and meta-data */ |
1083 | memmove(data + IEEE80211_QOS_CTL_LEN, data, | 1150 | memmove(data + IEEE80211_QOS_CTL_LEN, data, |
1084 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); | 1151 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); |
1085 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); | 1152 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); |
1086 | /* change frame type to non QOS */ | 1153 | /* change frame type to non QOS */ |
1087 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | 1154 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1088 | 1155 | ||
1089 | return RX_CONTINUE; | 1156 | return RX_CONTINUE; |
1090 | } | 1157 | } |
1091 | 1158 | ||
1092 | static int | 1159 | static int |
1093 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | 1160 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) |
1094 | { | 1161 | { |
1095 | if (unlikely(!rx->sta || | 1162 | if (unlikely(!rx->sta || |
1096 | !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) | 1163 | !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) |
1097 | return -EACCES; | 1164 | return -EACCES; |
1098 | 1165 | ||
1099 | return 0; | 1166 | return 0; |
1100 | } | 1167 | } |
1101 | 1168 | ||
1102 | static int | 1169 | static int |
1103 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | 1170 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) |
1104 | { | 1171 | { |
1105 | /* | 1172 | /* |
1106 | * Pass through unencrypted frames if the hardware has | 1173 | * Pass through unencrypted frames if the hardware has |
1107 | * decrypted them already. | 1174 | * decrypted them already. |
1108 | */ | 1175 | */ |
1109 | if (rx->status->flag & RX_FLAG_DECRYPTED) | 1176 | if (rx->status->flag & RX_FLAG_DECRYPTED) |
1110 | return 0; | 1177 | return 0; |
1111 | 1178 | ||
1112 | /* Drop unencrypted frames if key is set. */ | 1179 | /* Drop unencrypted frames if key is set. */ |
1113 | if (unlikely(!ieee80211_has_protected(fc) && | 1180 | if (unlikely(!ieee80211_has_protected(fc) && |
1114 | !ieee80211_is_nullfunc(fc) && | 1181 | !ieee80211_is_nullfunc(fc) && |
1182 | (!ieee80211_is_mgmt(fc) || | ||
1183 | (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1184 | rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && | ||
1185 | (rx->key || rx->sdata->drop_unencrypted))) | ||
1186 | return -EACCES; | ||
1187 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1188 | if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && | ||
1189 | ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | ||
1190 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1115 | (rx->key || rx->sdata->drop_unencrypted))) | 1191 | (rx->key || rx->sdata->drop_unencrypted))) |
1116 | return -EACCES; | 1192 | return -EACCES; |
1117 | 1193 | ||
1118 | return 0; | 1194 | return 0; |
1119 | } | 1195 | } |
1120 | 1196 | ||
1121 | static int | 1197 | static int |
1122 | ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | 1198 | ieee80211_data_to_8023(struct ieee80211_rx_data *rx) |
1123 | { | 1199 | { |
1124 | struct net_device *dev = rx->dev; | 1200 | struct net_device *dev = rx->dev; |
1125 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 1201 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
1126 | u16 hdrlen, ethertype; | 1202 | u16 hdrlen, ethertype; |
1127 | u8 *payload; | 1203 | u8 *payload; |
1128 | u8 dst[ETH_ALEN]; | 1204 | u8 dst[ETH_ALEN]; |
1129 | u8 src[ETH_ALEN] __aligned(2); | 1205 | u8 src[ETH_ALEN] __aligned(2); |
1130 | struct sk_buff *skb = rx->skb; | 1206 | struct sk_buff *skb = rx->skb; |
1131 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1207 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1132 | 1208 | ||
1133 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) | 1209 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
1134 | return -1; | 1210 | return -1; |
1135 | 1211 | ||
1136 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1212 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1137 | 1213 | ||
1138 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | 1214 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet |
1139 | * header | 1215 | * header |
1140 | * IEEE 802.11 address fields: | 1216 | * IEEE 802.11 address fields: |
1141 | * ToDS FromDS Addr1 Addr2 Addr3 Addr4 | 1217 | * ToDS FromDS Addr1 Addr2 Addr3 Addr4 |
1142 | * 0 0 DA SA BSSID n/a | 1218 | * 0 0 DA SA BSSID n/a |
1143 | * 0 1 DA BSSID SA n/a | 1219 | * 0 1 DA BSSID SA n/a |
1144 | * 1 0 BSSID SA DA n/a | 1220 | * 1 0 BSSID SA DA n/a |
1145 | * 1 1 RA TA DA SA | 1221 | * 1 1 RA TA DA SA |
1146 | */ | 1222 | */ |
1147 | memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); | 1223 | memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); |
1148 | memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); | 1224 | memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); |
1149 | 1225 | ||
1150 | switch (hdr->frame_control & | 1226 | switch (hdr->frame_control & |
1151 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | 1227 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { |
1152 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): | 1228 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): |
1153 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && | 1229 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && |
1154 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) | 1230 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
1155 | return -1; | 1231 | return -1; |
1156 | break; | 1232 | break; |
1157 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | 1233 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): |
1158 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | 1234 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1159 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | 1235 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1160 | return -1; | 1236 | return -1; |
1161 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1237 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1162 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) | 1238 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) |
1163 | (skb->data + hdrlen); | 1239 | (skb->data + hdrlen); |
1164 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | 1240 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); |
1165 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | 1241 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
1166 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | 1242 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); |
1167 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | 1243 | memcpy(src, meshdr->eaddr2, ETH_ALEN); |
1168 | } | 1244 | } |
1169 | } | 1245 | } |
1170 | break; | 1246 | break; |
1171 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): | 1247 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1172 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | 1248 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
1173 | (is_multicast_ether_addr(dst) && | 1249 | (is_multicast_ether_addr(dst) && |
1174 | !compare_ether_addr(src, dev->dev_addr))) | 1250 | !compare_ether_addr(src, dev->dev_addr))) |
1175 | return -1; | 1251 | return -1; |
1176 | break; | 1252 | break; |
1177 | case __constant_cpu_to_le16(0): | 1253 | case __constant_cpu_to_le16(0): |
1178 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1254 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1179 | return -1; | 1255 | return -1; |
1180 | break; | 1256 | break; |
1181 | } | 1257 | } |
1182 | 1258 | ||
1183 | if (unlikely(skb->len - hdrlen < 8)) | 1259 | if (unlikely(skb->len - hdrlen < 8)) |
1184 | return -1; | 1260 | return -1; |
1185 | 1261 | ||
1186 | payload = skb->data + hdrlen; | 1262 | payload = skb->data + hdrlen; |
1187 | ethertype = (payload[6] << 8) | payload[7]; | 1263 | ethertype = (payload[6] << 8) | payload[7]; |
1188 | 1264 | ||
1189 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && | 1265 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && |
1190 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | 1266 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || |
1191 | compare_ether_addr(payload, bridge_tunnel_header) == 0)) { | 1267 | compare_ether_addr(payload, bridge_tunnel_header) == 0)) { |
1192 | /* remove RFC1042 or Bridge-Tunnel encapsulation and | 1268 | /* remove RFC1042 or Bridge-Tunnel encapsulation and |
1193 | * replace EtherType */ | 1269 | * replace EtherType */ |
1194 | skb_pull(skb, hdrlen + 6); | 1270 | skb_pull(skb, hdrlen + 6); |
1195 | memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); | 1271 | memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); |
1196 | memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); | 1272 | memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); |
1197 | } else { | 1273 | } else { |
1198 | struct ethhdr *ehdr; | 1274 | struct ethhdr *ehdr; |
1199 | __be16 len; | 1275 | __be16 len; |
1200 | 1276 | ||
1201 | skb_pull(skb, hdrlen); | 1277 | skb_pull(skb, hdrlen); |
1202 | len = htons(skb->len); | 1278 | len = htons(skb->len); |
1203 | ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); | 1279 | ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); |
1204 | memcpy(ehdr->h_dest, dst, ETH_ALEN); | 1280 | memcpy(ehdr->h_dest, dst, ETH_ALEN); |
1205 | memcpy(ehdr->h_source, src, ETH_ALEN); | 1281 | memcpy(ehdr->h_source, src, ETH_ALEN); |
1206 | ehdr->h_proto = len; | 1282 | ehdr->h_proto = len; |
1207 | } | 1283 | } |
1208 | return 0; | 1284 | return 0; |
1209 | } | 1285 | } |
1210 | 1286 | ||
1211 | /* | 1287 | /* |
1212 | * requires that rx->skb is a frame with ethernet header | 1288 | * requires that rx->skb is a frame with ethernet header |
1213 | */ | 1289 | */ |
1214 | static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) | 1290 | static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) |
1215 | { | 1291 | { |
1216 | static const u8 pae_group_addr[ETH_ALEN] __aligned(2) | 1292 | static const u8 pae_group_addr[ETH_ALEN] __aligned(2) |
1217 | = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; | 1293 | = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; |
1218 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | 1294 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; |
1219 | 1295 | ||
1220 | /* | 1296 | /* |
1221 | * Allow EAPOL frames to us/the PAE group address regardless | 1297 | * Allow EAPOL frames to us/the PAE group address regardless |
1222 | * of whether the frame was encrypted or not. | 1298 | * of whether the frame was encrypted or not. |
1223 | */ | 1299 | */ |
1224 | if (ehdr->h_proto == htons(ETH_P_PAE) && | 1300 | if (ehdr->h_proto == htons(ETH_P_PAE) && |
1225 | (compare_ether_addr(ehdr->h_dest, rx->dev->dev_addr) == 0 || | 1301 | (compare_ether_addr(ehdr->h_dest, rx->dev->dev_addr) == 0 || |
1226 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) | 1302 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) |
1227 | return true; | 1303 | return true; |
1228 | 1304 | ||
1229 | if (ieee80211_802_1x_port_control(rx) || | 1305 | if (ieee80211_802_1x_port_control(rx) || |
1230 | ieee80211_drop_unencrypted(rx, fc)) | 1306 | ieee80211_drop_unencrypted(rx, fc)) |
1231 | return false; | 1307 | return false; |
1232 | 1308 | ||
1233 | return true; | 1309 | return true; |
1234 | } | 1310 | } |
1235 | 1311 | ||
1236 | /* | 1312 | /* |
1237 | * requires that rx->skb is a frame with ethernet header | 1313 | * requires that rx->skb is a frame with ethernet header |
1238 | */ | 1314 | */ |
1239 | static void | 1315 | static void |
1240 | ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | 1316 | ieee80211_deliver_skb(struct ieee80211_rx_data *rx) |
1241 | { | 1317 | { |
1242 | struct net_device *dev = rx->dev; | 1318 | struct net_device *dev = rx->dev; |
1243 | struct ieee80211_local *local = rx->local; | 1319 | struct ieee80211_local *local = rx->local; |
1244 | struct sk_buff *skb, *xmit_skb; | 1320 | struct sk_buff *skb, *xmit_skb; |
1245 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1321 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1246 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | 1322 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; |
1247 | struct sta_info *dsta; | 1323 | struct sta_info *dsta; |
1248 | 1324 | ||
1249 | skb = rx->skb; | 1325 | skb = rx->skb; |
1250 | xmit_skb = NULL; | 1326 | xmit_skb = NULL; |
1251 | 1327 | ||
1252 | if ((sdata->vif.type == NL80211_IFTYPE_AP || | 1328 | if ((sdata->vif.type == NL80211_IFTYPE_AP || |
1253 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && | 1329 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
1254 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && | 1330 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && |
1255 | (rx->flags & IEEE80211_RX_RA_MATCH)) { | 1331 | (rx->flags & IEEE80211_RX_RA_MATCH)) { |
1256 | if (is_multicast_ether_addr(ehdr->h_dest)) { | 1332 | if (is_multicast_ether_addr(ehdr->h_dest)) { |
1257 | /* | 1333 | /* |
1258 | * send multicast frames both to higher layers in | 1334 | * send multicast frames both to higher layers in |
1259 | * local net stack and back to the wireless medium | 1335 | * local net stack and back to the wireless medium |
1260 | */ | 1336 | */ |
1261 | xmit_skb = skb_copy(skb, GFP_ATOMIC); | 1337 | xmit_skb = skb_copy(skb, GFP_ATOMIC); |
1262 | if (!xmit_skb && net_ratelimit()) | 1338 | if (!xmit_skb && net_ratelimit()) |
1263 | printk(KERN_DEBUG "%s: failed to clone " | 1339 | printk(KERN_DEBUG "%s: failed to clone " |
1264 | "multicast frame\n", dev->name); | 1340 | "multicast frame\n", dev->name); |
1265 | } else { | 1341 | } else { |
1266 | dsta = sta_info_get(local, skb->data); | 1342 | dsta = sta_info_get(local, skb->data); |
1267 | if (dsta && dsta->sdata->dev == dev) { | 1343 | if (dsta && dsta->sdata->dev == dev) { |
1268 | /* | 1344 | /* |
1269 | * The destination station is associated to | 1345 | * The destination station is associated to |
1270 | * this AP (in this VLAN), so send the frame | 1346 | * this AP (in this VLAN), so send the frame |
1271 | * directly to it and do not pass it to local | 1347 | * directly to it and do not pass it to local |
1272 | * net stack. | 1348 | * net stack. |
1273 | */ | 1349 | */ |
1274 | xmit_skb = skb; | 1350 | xmit_skb = skb; |
1275 | skb = NULL; | 1351 | skb = NULL; |
1276 | } | 1352 | } |
1277 | } | 1353 | } |
1278 | } | 1354 | } |
1279 | 1355 | ||
1280 | if (skb) { | 1356 | if (skb) { |
1281 | int align __maybe_unused; | 1357 | int align __maybe_unused; |
1282 | 1358 | ||
1283 | #if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 1359 | #if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
1284 | /* | 1360 | /* |
1285 | * 'align' will only take the values 0 or 2 here | 1361 | * 'align' will only take the values 0 or 2 here |
1286 | * since all frames are required to be aligned | 1362 | * since all frames are required to be aligned |
1287 | * to 2-byte boundaries when being passed to | 1363 | * to 2-byte boundaries when being passed to |
1288 | * mac80211. That also explains the __skb_push() | 1364 | * mac80211. That also explains the __skb_push() |
1289 | * below. | 1365 | * below. |
1290 | */ | 1366 | */ |
1291 | align = (unsigned long)skb->data & 4; | 1367 | align = (unsigned long)skb->data & 4; |
1292 | if (align) { | 1368 | if (align) { |
1293 | if (WARN_ON(skb_headroom(skb) < 3)) { | 1369 | if (WARN_ON(skb_headroom(skb) < 3)) { |
1294 | dev_kfree_skb(skb); | 1370 | dev_kfree_skb(skb); |
1295 | skb = NULL; | 1371 | skb = NULL; |
1296 | } else { | 1372 | } else { |
1297 | u8 *data = skb->data; | 1373 | u8 *data = skb->data; |
1298 | size_t len = skb->len; | 1374 | size_t len = skb->len; |
1299 | u8 *new = __skb_push(skb, align); | 1375 | u8 *new = __skb_push(skb, align); |
1300 | memmove(new, data, len); | 1376 | memmove(new, data, len); |
1301 | __skb_trim(skb, len); | 1377 | __skb_trim(skb, len); |
1302 | } | 1378 | } |
1303 | } | 1379 | } |
1304 | #endif | 1380 | #endif |
1305 | 1381 | ||
1306 | if (skb) { | 1382 | if (skb) { |
1307 | /* deliver to local stack */ | 1383 | /* deliver to local stack */ |
1308 | skb->protocol = eth_type_trans(skb, dev); | 1384 | skb->protocol = eth_type_trans(skb, dev); |
1309 | memset(skb->cb, 0, sizeof(skb->cb)); | 1385 | memset(skb->cb, 0, sizeof(skb->cb)); |
1310 | netif_rx(skb); | 1386 | netif_rx(skb); |
1311 | } | 1387 | } |
1312 | } | 1388 | } |
1313 | 1389 | ||
1314 | if (xmit_skb) { | 1390 | if (xmit_skb) { |
1315 | /* send to wireless media */ | 1391 | /* send to wireless media */ |
1316 | xmit_skb->protocol = htons(ETH_P_802_3); | 1392 | xmit_skb->protocol = htons(ETH_P_802_3); |
1317 | skb_reset_network_header(xmit_skb); | 1393 | skb_reset_network_header(xmit_skb); |
1318 | skb_reset_mac_header(xmit_skb); | 1394 | skb_reset_mac_header(xmit_skb); |
1319 | dev_queue_xmit(xmit_skb); | 1395 | dev_queue_xmit(xmit_skb); |
1320 | } | 1396 | } |
1321 | } | 1397 | } |
1322 | 1398 | ||
1323 | static ieee80211_rx_result debug_noinline | 1399 | static ieee80211_rx_result debug_noinline |
1324 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | 1400 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) |
1325 | { | 1401 | { |
1326 | struct net_device *dev = rx->dev; | 1402 | struct net_device *dev = rx->dev; |
1327 | struct ieee80211_local *local = rx->local; | 1403 | struct ieee80211_local *local = rx->local; |
1328 | u16 ethertype; | 1404 | u16 ethertype; |
1329 | u8 *payload; | 1405 | u8 *payload; |
1330 | struct sk_buff *skb = rx->skb, *frame = NULL; | 1406 | struct sk_buff *skb = rx->skb, *frame = NULL; |
1331 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1332 | __le16 fc = hdr->frame_control; | 1408 | __le16 fc = hdr->frame_control; |
1333 | const struct ethhdr *eth; | 1409 | const struct ethhdr *eth; |
1334 | int remaining, err; | 1410 | int remaining, err; |
1335 | u8 dst[ETH_ALEN]; | 1411 | u8 dst[ETH_ALEN]; |
1336 | u8 src[ETH_ALEN]; | 1412 | u8 src[ETH_ALEN]; |
1337 | 1413 | ||
1338 | if (unlikely(!ieee80211_is_data(fc))) | 1414 | if (unlikely(!ieee80211_is_data(fc))) |
1339 | return RX_CONTINUE; | 1415 | return RX_CONTINUE; |
1340 | 1416 | ||
1341 | if (unlikely(!ieee80211_is_data_present(fc))) | 1417 | if (unlikely(!ieee80211_is_data_present(fc))) |
1342 | return RX_DROP_MONITOR; | 1418 | return RX_DROP_MONITOR; |
1343 | 1419 | ||
1344 | if (!(rx->flags & IEEE80211_RX_AMSDU)) | 1420 | if (!(rx->flags & IEEE80211_RX_AMSDU)) |
1345 | return RX_CONTINUE; | 1421 | return RX_CONTINUE; |
1346 | 1422 | ||
1347 | err = ieee80211_data_to_8023(rx); | 1423 | err = ieee80211_data_to_8023(rx); |
1348 | if (unlikely(err)) | 1424 | if (unlikely(err)) |
1349 | return RX_DROP_UNUSABLE; | 1425 | return RX_DROP_UNUSABLE; |
1350 | 1426 | ||
1351 | skb->dev = dev; | 1427 | skb->dev = dev; |
1352 | 1428 | ||
1353 | dev->stats.rx_packets++; | 1429 | dev->stats.rx_packets++; |
1354 | dev->stats.rx_bytes += skb->len; | 1430 | dev->stats.rx_bytes += skb->len; |
1355 | 1431 | ||
1356 | /* skip the wrapping header */ | 1432 | /* skip the wrapping header */ |
1357 | eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); | 1433 | eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); |
1358 | if (!eth) | 1434 | if (!eth) |
1359 | return RX_DROP_UNUSABLE; | 1435 | return RX_DROP_UNUSABLE; |
1360 | 1436 | ||
1361 | while (skb != frame) { | 1437 | while (skb != frame) { |
1362 | u8 padding; | 1438 | u8 padding; |
1363 | __be16 len = eth->h_proto; | 1439 | __be16 len = eth->h_proto; |
1364 | unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len); | 1440 | unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len); |
1365 | 1441 | ||
1366 | remaining = skb->len; | 1442 | remaining = skb->len; |
1367 | memcpy(dst, eth->h_dest, ETH_ALEN); | 1443 | memcpy(dst, eth->h_dest, ETH_ALEN); |
1368 | memcpy(src, eth->h_source, ETH_ALEN); | 1444 | memcpy(src, eth->h_source, ETH_ALEN); |
1369 | 1445 | ||
1370 | padding = ((4 - subframe_len) & 0x3); | 1446 | padding = ((4 - subframe_len) & 0x3); |
1371 | /* the last MSDU has no padding */ | 1447 | /* the last MSDU has no padding */ |
1372 | if (subframe_len > remaining) | 1448 | if (subframe_len > remaining) |
1373 | return RX_DROP_UNUSABLE; | 1449 | return RX_DROP_UNUSABLE; |
1374 | 1450 | ||
1375 | skb_pull(skb, sizeof(struct ethhdr)); | 1451 | skb_pull(skb, sizeof(struct ethhdr)); |
1376 | /* if last subframe reuse skb */ | 1452 | /* if last subframe reuse skb */ |
1377 | if (remaining <= subframe_len + padding) | 1453 | if (remaining <= subframe_len + padding) |
1378 | frame = skb; | 1454 | frame = skb; |
1379 | else { | 1455 | else { |
1380 | /* | 1456 | /* |
1381 | * Allocate and reserve two bytes more for payload | 1457 | * Allocate and reserve two bytes more for payload |
1382 | * alignment since sizeof(struct ethhdr) is 14. | 1458 | * alignment since sizeof(struct ethhdr) is 14. |
1383 | */ | 1459 | */ |
1384 | frame = dev_alloc_skb( | 1460 | frame = dev_alloc_skb( |
1385 | ALIGN(local->hw.extra_tx_headroom, 4) + | 1461 | ALIGN(local->hw.extra_tx_headroom, 4) + |
1386 | subframe_len + 2); | 1462 | subframe_len + 2); |
1387 | 1463 | ||
1388 | if (frame == NULL) | 1464 | if (frame == NULL) |
1389 | return RX_DROP_UNUSABLE; | 1465 | return RX_DROP_UNUSABLE; |
1390 | 1466 | ||
1391 | skb_reserve(frame, | 1467 | skb_reserve(frame, |
1392 | ALIGN(local->hw.extra_tx_headroom, 4) + | 1468 | ALIGN(local->hw.extra_tx_headroom, 4) + |
1393 | sizeof(struct ethhdr) + 2); | 1469 | sizeof(struct ethhdr) + 2); |
1394 | memcpy(skb_put(frame, ntohs(len)), skb->data, | 1470 | memcpy(skb_put(frame, ntohs(len)), skb->data, |
1395 | ntohs(len)); | 1471 | ntohs(len)); |
1396 | 1472 | ||
1397 | eth = (struct ethhdr *) skb_pull(skb, ntohs(len) + | 1473 | eth = (struct ethhdr *) skb_pull(skb, ntohs(len) + |
1398 | padding); | 1474 | padding); |
1399 | if (!eth) { | 1475 | if (!eth) { |
1400 | dev_kfree_skb(frame); | 1476 | dev_kfree_skb(frame); |
1401 | return RX_DROP_UNUSABLE; | 1477 | return RX_DROP_UNUSABLE; |
1402 | } | 1478 | } |
1403 | } | 1479 | } |
1404 | 1480 | ||
1405 | skb_reset_network_header(frame); | 1481 | skb_reset_network_header(frame); |
1406 | frame->dev = dev; | 1482 | frame->dev = dev; |
1407 | frame->priority = skb->priority; | 1483 | frame->priority = skb->priority; |
1408 | rx->skb = frame; | 1484 | rx->skb = frame; |
1409 | 1485 | ||
1410 | payload = frame->data; | 1486 | payload = frame->data; |
1411 | ethertype = (payload[6] << 8) | payload[7]; | 1487 | ethertype = (payload[6] << 8) | payload[7]; |
1412 | 1488 | ||
1413 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && | 1489 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && |
1414 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | 1490 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || |
1415 | compare_ether_addr(payload, | 1491 | compare_ether_addr(payload, |
1416 | bridge_tunnel_header) == 0)) { | 1492 | bridge_tunnel_header) == 0)) { |
1417 | /* remove RFC1042 or Bridge-Tunnel | 1493 | /* remove RFC1042 or Bridge-Tunnel |
1418 | * encapsulation and replace EtherType */ | 1494 | * encapsulation and replace EtherType */ |
1419 | skb_pull(frame, 6); | 1495 | skb_pull(frame, 6); |
1420 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | 1496 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); |
1421 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | 1497 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); |
1422 | } else { | 1498 | } else { |
1423 | memcpy(skb_push(frame, sizeof(__be16)), | 1499 | memcpy(skb_push(frame, sizeof(__be16)), |
1424 | &len, sizeof(__be16)); | 1500 | &len, sizeof(__be16)); |
1425 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | 1501 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); |
1426 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | 1502 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); |
1427 | } | 1503 | } |
1428 | 1504 | ||
1429 | if (!ieee80211_frame_allowed(rx, fc)) { | 1505 | if (!ieee80211_frame_allowed(rx, fc)) { |
1430 | if (skb == frame) /* last frame */ | 1506 | if (skb == frame) /* last frame */ |
1431 | return RX_DROP_UNUSABLE; | 1507 | return RX_DROP_UNUSABLE; |
1432 | dev_kfree_skb(frame); | 1508 | dev_kfree_skb(frame); |
1433 | continue; | 1509 | continue; |
1434 | } | 1510 | } |
1435 | 1511 | ||
1436 | ieee80211_deliver_skb(rx); | 1512 | ieee80211_deliver_skb(rx); |
1437 | } | 1513 | } |
1438 | 1514 | ||
1439 | return RX_QUEUED; | 1515 | return RX_QUEUED; |
1440 | } | 1516 | } |
1441 | 1517 | ||
1442 | #ifdef CONFIG_MAC80211_MESH | 1518 | #ifdef CONFIG_MAC80211_MESH |
1443 | static ieee80211_rx_result | 1519 | static ieee80211_rx_result |
1444 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | 1520 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1445 | { | 1521 | { |
1446 | struct ieee80211_hdr *hdr; | 1522 | struct ieee80211_hdr *hdr; |
1447 | struct ieee80211s_hdr *mesh_hdr; | 1523 | struct ieee80211s_hdr *mesh_hdr; |
1448 | unsigned int hdrlen; | 1524 | unsigned int hdrlen; |
1449 | struct sk_buff *skb = rx->skb, *fwd_skb; | 1525 | struct sk_buff *skb = rx->skb, *fwd_skb; |
1450 | 1526 | ||
1451 | hdr = (struct ieee80211_hdr *) skb->data; | 1527 | hdr = (struct ieee80211_hdr *) skb->data; |
1452 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1528 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1453 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1529 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1454 | 1530 | ||
1455 | if (!ieee80211_is_data(hdr->frame_control)) | 1531 | if (!ieee80211_is_data(hdr->frame_control)) |
1456 | return RX_CONTINUE; | 1532 | return RX_CONTINUE; |
1457 | 1533 | ||
1458 | if (!mesh_hdr->ttl) | 1534 | if (!mesh_hdr->ttl) |
1459 | /* illegal frame */ | 1535 | /* illegal frame */ |
1460 | return RX_DROP_MONITOR; | 1536 | return RX_DROP_MONITOR; |
1461 | 1537 | ||
1462 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | 1538 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ |
1463 | struct ieee80211_sub_if_data *sdata; | 1539 | struct ieee80211_sub_if_data *sdata; |
1464 | struct mesh_path *mppath; | 1540 | struct mesh_path *mppath; |
1465 | 1541 | ||
1466 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1542 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1467 | rcu_read_lock(); | 1543 | rcu_read_lock(); |
1468 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | 1544 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); |
1469 | if (!mppath) { | 1545 | if (!mppath) { |
1470 | mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); | 1546 | mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); |
1471 | } else { | 1547 | } else { |
1472 | spin_lock_bh(&mppath->state_lock); | 1548 | spin_lock_bh(&mppath->state_lock); |
1473 | mppath->exp_time = jiffies; | 1549 | mppath->exp_time = jiffies; |
1474 | if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) | 1550 | if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) |
1475 | memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); | 1551 | memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); |
1476 | spin_unlock_bh(&mppath->state_lock); | 1552 | spin_unlock_bh(&mppath->state_lock); |
1477 | } | 1553 | } |
1478 | rcu_read_unlock(); | 1554 | rcu_read_unlock(); |
1479 | } | 1555 | } |
1480 | 1556 | ||
1481 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1557 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) |
1482 | return RX_CONTINUE; | 1558 | return RX_CONTINUE; |
1483 | 1559 | ||
1484 | mesh_hdr->ttl--; | 1560 | mesh_hdr->ttl--; |
1485 | 1561 | ||
1486 | if (rx->flags & IEEE80211_RX_RA_MATCH) { | 1562 | if (rx->flags & IEEE80211_RX_RA_MATCH) { |
1487 | if (!mesh_hdr->ttl) | 1563 | if (!mesh_hdr->ttl) |
1488 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, | 1564 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, |
1489 | dropped_frames_ttl); | 1565 | dropped_frames_ttl); |
1490 | else { | 1566 | else { |
1491 | struct ieee80211_hdr *fwd_hdr; | 1567 | struct ieee80211_hdr *fwd_hdr; |
1492 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | 1568 | fwd_skb = skb_copy(skb, GFP_ATOMIC); |
1493 | 1569 | ||
1494 | if (!fwd_skb && net_ratelimit()) | 1570 | if (!fwd_skb && net_ratelimit()) |
1495 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1571 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1496 | rx->dev->name); | 1572 | rx->dev->name); |
1497 | 1573 | ||
1498 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1574 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1499 | /* | 1575 | /* |
1500 | * Save TA to addr1 to send TA a path error if a | 1576 | * Save TA to addr1 to send TA a path error if a |
1501 | * suitable next hop is not found | 1577 | * suitable next hop is not found |
1502 | */ | 1578 | */ |
1503 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); | 1579 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); |
1504 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); | 1580 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); |
1505 | fwd_skb->dev = rx->local->mdev; | 1581 | fwd_skb->dev = rx->local->mdev; |
1506 | fwd_skb->iif = rx->dev->ifindex; | 1582 | fwd_skb->iif = rx->dev->ifindex; |
1507 | dev_queue_xmit(fwd_skb); | 1583 | dev_queue_xmit(fwd_skb); |
1508 | } | 1584 | } |
1509 | } | 1585 | } |
1510 | 1586 | ||
1511 | if (is_multicast_ether_addr(hdr->addr3) || | 1587 | if (is_multicast_ether_addr(hdr->addr3) || |
1512 | rx->dev->flags & IFF_PROMISC) | 1588 | rx->dev->flags & IFF_PROMISC) |
1513 | return RX_CONTINUE; | 1589 | return RX_CONTINUE; |
1514 | else | 1590 | else |
1515 | return RX_DROP_MONITOR; | 1591 | return RX_DROP_MONITOR; |
1516 | } | 1592 | } |
1517 | #endif | 1593 | #endif |
1518 | 1594 | ||
1519 | static ieee80211_rx_result debug_noinline | 1595 | static ieee80211_rx_result debug_noinline |
1520 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | 1596 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) |
1521 | { | 1597 | { |
1522 | struct net_device *dev = rx->dev; | 1598 | struct net_device *dev = rx->dev; |
1523 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1599 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1524 | __le16 fc = hdr->frame_control; | 1600 | __le16 fc = hdr->frame_control; |
1525 | int err; | 1601 | int err; |
1526 | 1602 | ||
1527 | if (unlikely(!ieee80211_is_data(hdr->frame_control))) | 1603 | if (unlikely(!ieee80211_is_data(hdr->frame_control))) |
1528 | return RX_CONTINUE; | 1604 | return RX_CONTINUE; |
1529 | 1605 | ||
1530 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) | 1606 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
1531 | return RX_DROP_MONITOR; | 1607 | return RX_DROP_MONITOR; |
1532 | 1608 | ||
1533 | err = ieee80211_data_to_8023(rx); | 1609 | err = ieee80211_data_to_8023(rx); |
1534 | if (unlikely(err)) | 1610 | if (unlikely(err)) |
1535 | return RX_DROP_UNUSABLE; | 1611 | return RX_DROP_UNUSABLE; |
1536 | 1612 | ||
1537 | if (!ieee80211_frame_allowed(rx, fc)) | 1613 | if (!ieee80211_frame_allowed(rx, fc)) |
1538 | return RX_DROP_MONITOR; | 1614 | return RX_DROP_MONITOR; |
1539 | 1615 | ||
1540 | rx->skb->dev = dev; | 1616 | rx->skb->dev = dev; |
1541 | 1617 | ||
1542 | dev->stats.rx_packets++; | 1618 | dev->stats.rx_packets++; |
1543 | dev->stats.rx_bytes += rx->skb->len; | 1619 | dev->stats.rx_bytes += rx->skb->len; |
1544 | 1620 | ||
1545 | ieee80211_deliver_skb(rx); | 1621 | ieee80211_deliver_skb(rx); |
1546 | 1622 | ||
1547 | return RX_QUEUED; | 1623 | return RX_QUEUED; |
1548 | } | 1624 | } |
1549 | 1625 | ||
1550 | static ieee80211_rx_result debug_noinline | 1626 | static ieee80211_rx_result debug_noinline |
1551 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | 1627 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) |
1552 | { | 1628 | { |
1553 | struct ieee80211_local *local = rx->local; | 1629 | struct ieee80211_local *local = rx->local; |
1554 | struct ieee80211_hw *hw = &local->hw; | 1630 | struct ieee80211_hw *hw = &local->hw; |
1555 | struct sk_buff *skb = rx->skb; | 1631 | struct sk_buff *skb = rx->skb; |
1556 | struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; | 1632 | struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; |
1557 | struct tid_ampdu_rx *tid_agg_rx; | 1633 | struct tid_ampdu_rx *tid_agg_rx; |
1558 | u16 start_seq_num; | 1634 | u16 start_seq_num; |
1559 | u16 tid; | 1635 | u16 tid; |
1560 | 1636 | ||
1561 | if (likely(!ieee80211_is_ctl(bar->frame_control))) | 1637 | if (likely(!ieee80211_is_ctl(bar->frame_control))) |
1562 | return RX_CONTINUE; | 1638 | return RX_CONTINUE; |
1563 | 1639 | ||
1564 | if (ieee80211_is_back_req(bar->frame_control)) { | 1640 | if (ieee80211_is_back_req(bar->frame_control)) { |
1565 | if (!rx->sta) | 1641 | if (!rx->sta) |
1566 | return RX_CONTINUE; | 1642 | return RX_CONTINUE; |
1567 | tid = le16_to_cpu(bar->control) >> 12; | 1643 | tid = le16_to_cpu(bar->control) >> 12; |
1568 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] | 1644 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] |
1569 | != HT_AGG_STATE_OPERATIONAL) | 1645 | != HT_AGG_STATE_OPERATIONAL) |
1570 | return RX_CONTINUE; | 1646 | return RX_CONTINUE; |
1571 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | 1647 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; |
1572 | 1648 | ||
1573 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1649 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
1574 | 1650 | ||
1575 | /* reset session timer */ | 1651 | /* reset session timer */ |
1576 | if (tid_agg_rx->timeout) { | 1652 | if (tid_agg_rx->timeout) { |
1577 | unsigned long expires = | 1653 | unsigned long expires = |
1578 | jiffies + (tid_agg_rx->timeout / 1000) * HZ; | 1654 | jiffies + (tid_agg_rx->timeout / 1000) * HZ; |
1579 | mod_timer(&tid_agg_rx->session_timer, expires); | 1655 | mod_timer(&tid_agg_rx->session_timer, expires); |
1580 | } | 1656 | } |
1581 | 1657 | ||
1582 | /* manage reordering buffer according to requested */ | 1658 | /* manage reordering buffer according to requested */ |
1583 | /* sequence number */ | 1659 | /* sequence number */ |
1584 | rcu_read_lock(); | 1660 | rcu_read_lock(); |
1585 | ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, | 1661 | ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, |
1586 | start_seq_num, 1); | 1662 | start_seq_num, 1); |
1587 | rcu_read_unlock(); | 1663 | rcu_read_unlock(); |
1588 | return RX_DROP_UNUSABLE; | 1664 | return RX_DROP_UNUSABLE; |
1589 | } | 1665 | } |
1590 | 1666 | ||
1591 | return RX_CONTINUE; | 1667 | return RX_CONTINUE; |
1592 | } | 1668 | } |
1593 | 1669 | ||
1594 | static ieee80211_rx_result debug_noinline | 1670 | static ieee80211_rx_result debug_noinline |
1595 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1671 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1596 | { | 1672 | { |
1597 | struct ieee80211_local *local = rx->local; | 1673 | struct ieee80211_local *local = rx->local; |
1598 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1674 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1599 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 1675 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
1600 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1676 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1601 | struct ieee80211_bss *bss; | 1677 | struct ieee80211_bss *bss; |
1602 | int len = rx->skb->len; | 1678 | int len = rx->skb->len; |
1603 | 1679 | ||
1604 | if (!ieee80211_is_action(mgmt->frame_control)) | 1680 | if (!ieee80211_is_action(mgmt->frame_control)) |
1605 | return RX_CONTINUE; | 1681 | return RX_CONTINUE; |
1606 | 1682 | ||
1607 | if (!rx->sta) | 1683 | if (!rx->sta) |
1608 | return RX_DROP_MONITOR; | 1684 | return RX_DROP_MONITOR; |
1609 | 1685 | ||
1610 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1686 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1611 | return RX_DROP_MONITOR; | 1687 | return RX_DROP_MONITOR; |
1612 | 1688 | ||
1613 | /* all categories we currently handle have action_code */ | 1689 | /* all categories we currently handle have action_code */ |
1614 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1690 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
1615 | return RX_DROP_MONITOR; | 1691 | return RX_DROP_MONITOR; |
1616 | 1692 | ||
1617 | switch (mgmt->u.action.category) { | 1693 | switch (mgmt->u.action.category) { |
1618 | case WLAN_CATEGORY_BACK: | 1694 | case WLAN_CATEGORY_BACK: |
1619 | switch (mgmt->u.action.u.addba_req.action_code) { | 1695 | switch (mgmt->u.action.u.addba_req.action_code) { |
1620 | case WLAN_ACTION_ADDBA_REQ: | 1696 | case WLAN_ACTION_ADDBA_REQ: |
1621 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1697 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1622 | sizeof(mgmt->u.action.u.addba_req))) | 1698 | sizeof(mgmt->u.action.u.addba_req))) |
1623 | return RX_DROP_MONITOR; | 1699 | return RX_DROP_MONITOR; |
1624 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | 1700 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); |
1625 | break; | 1701 | break; |
1626 | case WLAN_ACTION_ADDBA_RESP: | 1702 | case WLAN_ACTION_ADDBA_RESP: |
1627 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1703 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1628 | sizeof(mgmt->u.action.u.addba_resp))) | 1704 | sizeof(mgmt->u.action.u.addba_resp))) |
1629 | return RX_DROP_MONITOR; | 1705 | return RX_DROP_MONITOR; |
1630 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | 1706 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); |
1631 | break; | 1707 | break; |
1632 | case WLAN_ACTION_DELBA: | 1708 | case WLAN_ACTION_DELBA: |
1633 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1709 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1634 | sizeof(mgmt->u.action.u.delba))) | 1710 | sizeof(mgmt->u.action.u.delba))) |
1635 | return RX_DROP_MONITOR; | 1711 | return RX_DROP_MONITOR; |
1636 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | 1712 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); |
1637 | break; | 1713 | break; |
1638 | } | 1714 | } |
1639 | break; | 1715 | break; |
1640 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 1716 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
1641 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 1717 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) |
1642 | return RX_DROP_MONITOR; | 1718 | return RX_DROP_MONITOR; |
1643 | switch (mgmt->u.action.u.measurement.action_code) { | 1719 | switch (mgmt->u.action.u.measurement.action_code) { |
1644 | case WLAN_ACTION_SPCT_MSR_REQ: | 1720 | case WLAN_ACTION_SPCT_MSR_REQ: |
1645 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1721 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1646 | sizeof(mgmt->u.action.u.measurement))) | 1722 | sizeof(mgmt->u.action.u.measurement))) |
1647 | return RX_DROP_MONITOR; | 1723 | return RX_DROP_MONITOR; |
1648 | ieee80211_process_measurement_req(sdata, mgmt, len); | 1724 | ieee80211_process_measurement_req(sdata, mgmt, len); |
1649 | break; | 1725 | break; |
1650 | case WLAN_ACTION_SPCT_CHL_SWITCH: | 1726 | case WLAN_ACTION_SPCT_CHL_SWITCH: |
1651 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1727 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1652 | sizeof(mgmt->u.action.u.chan_switch))) | 1728 | sizeof(mgmt->u.action.u.chan_switch))) |
1653 | return RX_DROP_MONITOR; | 1729 | return RX_DROP_MONITOR; |
1654 | 1730 | ||
1655 | if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0) | 1731 | if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0) |
1656 | return RX_DROP_MONITOR; | 1732 | return RX_DROP_MONITOR; |
1657 | 1733 | ||
1658 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, | 1734 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
1659 | local->hw.conf.channel->center_freq, | 1735 | local->hw.conf.channel->center_freq, |
1660 | ifsta->ssid, ifsta->ssid_len); | 1736 | ifsta->ssid, ifsta->ssid_len); |
1661 | if (!bss) | 1737 | if (!bss) |
1662 | return RX_DROP_MONITOR; | 1738 | return RX_DROP_MONITOR; |
1663 | 1739 | ||
1664 | ieee80211_process_chanswitch(sdata, | 1740 | ieee80211_process_chanswitch(sdata, |
1665 | &mgmt->u.action.u.chan_switch.sw_elem, bss); | 1741 | &mgmt->u.action.u.chan_switch.sw_elem, bss); |
1666 | ieee80211_rx_bss_put(local, bss); | 1742 | ieee80211_rx_bss_put(local, bss); |
1667 | break; | 1743 | break; |
1668 | } | 1744 | } |
1669 | break; | 1745 | break; |
1670 | default: | 1746 | default: |
1671 | return RX_CONTINUE; | 1747 | return RX_CONTINUE; |
1672 | } | 1748 | } |
1673 | 1749 | ||
1674 | rx->sta->rx_packets++; | 1750 | rx->sta->rx_packets++; |
1675 | dev_kfree_skb(rx->skb); | 1751 | dev_kfree_skb(rx->skb); |
1676 | return RX_QUEUED; | 1752 | return RX_QUEUED; |
1677 | } | 1753 | } |
1678 | 1754 | ||
1679 | static ieee80211_rx_result debug_noinline | 1755 | static ieee80211_rx_result debug_noinline |
1680 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 1756 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1681 | { | 1757 | { |
1682 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1758 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1683 | 1759 | ||
1684 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1760 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1685 | return RX_DROP_MONITOR; | 1761 | return RX_DROP_MONITOR; |
1686 | 1762 | ||
1687 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1763 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1688 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); | 1764 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); |
1689 | 1765 | ||
1690 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1766 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1691 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1767 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1692 | return RX_DROP_MONITOR; | 1768 | return RX_DROP_MONITOR; |
1693 | 1769 | ||
1694 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) | 1770 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) |
1695 | return RX_DROP_MONITOR; | 1771 | return RX_DROP_MONITOR; |
1696 | 1772 | ||
1697 | ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); | 1773 | ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); |
1698 | return RX_QUEUED; | 1774 | return RX_QUEUED; |
1699 | } | 1775 | } |
1700 | 1776 | ||
1701 | static void ieee80211_rx_michael_mic_report(struct net_device *dev, | 1777 | static void ieee80211_rx_michael_mic_report(struct net_device *dev, |
1702 | struct ieee80211_hdr *hdr, | 1778 | struct ieee80211_hdr *hdr, |
1703 | struct ieee80211_rx_data *rx) | 1779 | struct ieee80211_rx_data *rx) |
1704 | { | 1780 | { |
1705 | int keyidx; | 1781 | int keyidx; |
1706 | unsigned int hdrlen; | 1782 | unsigned int hdrlen; |
1707 | 1783 | ||
1708 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1784 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1709 | if (rx->skb->len >= hdrlen + 4) | 1785 | if (rx->skb->len >= hdrlen + 4) |
1710 | keyidx = rx->skb->data[hdrlen + 3] >> 6; | 1786 | keyidx = rx->skb->data[hdrlen + 3] >> 6; |
1711 | else | 1787 | else |
1712 | keyidx = -1; | 1788 | keyidx = -1; |
1713 | 1789 | ||
1714 | if (!rx->sta) { | 1790 | if (!rx->sta) { |
1715 | /* | 1791 | /* |
1716 | * Some hardware seem to generate incorrect Michael MIC | 1792 | * Some hardware seem to generate incorrect Michael MIC |
1717 | * reports; ignore them to avoid triggering countermeasures. | 1793 | * reports; ignore them to avoid triggering countermeasures. |
1718 | */ | 1794 | */ |
1719 | goto ignore; | 1795 | goto ignore; |
1720 | } | 1796 | } |
1721 | 1797 | ||
1722 | if (!ieee80211_has_protected(hdr->frame_control)) | 1798 | if (!ieee80211_has_protected(hdr->frame_control)) |
1723 | goto ignore; | 1799 | goto ignore; |
1724 | 1800 | ||
1725 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { | 1801 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { |
1726 | /* | 1802 | /* |
1727 | * APs with pairwise keys should never receive Michael MIC | 1803 | * APs with pairwise keys should never receive Michael MIC |
1728 | * errors for non-zero keyidx because these are reserved for | 1804 | * errors for non-zero keyidx because these are reserved for |
1729 | * group keys and only the AP is sending real multicast | 1805 | * group keys and only the AP is sending real multicast |
1730 | * frames in the BSS. | 1806 | * frames in the BSS. |
1731 | */ | 1807 | */ |
1732 | goto ignore; | 1808 | goto ignore; |
1733 | } | 1809 | } |
1734 | 1810 | ||
1735 | if (!ieee80211_is_data(hdr->frame_control) && | 1811 | if (!ieee80211_is_data(hdr->frame_control) && |
1736 | !ieee80211_is_auth(hdr->frame_control)) | 1812 | !ieee80211_is_auth(hdr->frame_control)) |
1737 | goto ignore; | 1813 | goto ignore; |
1738 | 1814 | ||
1739 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); | 1815 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); |
1740 | ignore: | 1816 | ignore: |
1741 | dev_kfree_skb(rx->skb); | 1817 | dev_kfree_skb(rx->skb); |
1742 | rx->skb = NULL; | 1818 | rx->skb = NULL; |
1743 | } | 1819 | } |
1744 | 1820 | ||
1745 | /* TODO: use IEEE80211_RX_FRAGMENTED */ | 1821 | /* TODO: use IEEE80211_RX_FRAGMENTED */ |
1746 | static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) | 1822 | static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) |
1747 | { | 1823 | { |
1748 | struct ieee80211_sub_if_data *sdata; | 1824 | struct ieee80211_sub_if_data *sdata; |
1749 | struct ieee80211_local *local = rx->local; | 1825 | struct ieee80211_local *local = rx->local; |
1750 | struct ieee80211_rtap_hdr { | 1826 | struct ieee80211_rtap_hdr { |
1751 | struct ieee80211_radiotap_header hdr; | 1827 | struct ieee80211_radiotap_header hdr; |
1752 | u8 flags; | 1828 | u8 flags; |
1753 | u8 rate; | 1829 | u8 rate; |
1754 | __le16 chan_freq; | 1830 | __le16 chan_freq; |
1755 | __le16 chan_flags; | 1831 | __le16 chan_flags; |
1756 | } __attribute__ ((packed)) *rthdr; | 1832 | } __attribute__ ((packed)) *rthdr; |
1757 | struct sk_buff *skb = rx->skb, *skb2; | 1833 | struct sk_buff *skb = rx->skb, *skb2; |
1758 | struct net_device *prev_dev = NULL; | 1834 | struct net_device *prev_dev = NULL; |
1759 | struct ieee80211_rx_status *status = rx->status; | 1835 | struct ieee80211_rx_status *status = rx->status; |
1760 | 1836 | ||
1761 | if (rx->flags & IEEE80211_RX_CMNTR_REPORTED) | 1837 | if (rx->flags & IEEE80211_RX_CMNTR_REPORTED) |
1762 | goto out_free_skb; | 1838 | goto out_free_skb; |
1763 | 1839 | ||
1764 | if (skb_headroom(skb) < sizeof(*rthdr) && | 1840 | if (skb_headroom(skb) < sizeof(*rthdr) && |
1765 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) | 1841 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) |
1766 | goto out_free_skb; | 1842 | goto out_free_skb; |
1767 | 1843 | ||
1768 | rthdr = (void *)skb_push(skb, sizeof(*rthdr)); | 1844 | rthdr = (void *)skb_push(skb, sizeof(*rthdr)); |
1769 | memset(rthdr, 0, sizeof(*rthdr)); | 1845 | memset(rthdr, 0, sizeof(*rthdr)); |
1770 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | 1846 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); |
1771 | rthdr->hdr.it_present = | 1847 | rthdr->hdr.it_present = |
1772 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | 1848 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
1773 | (1 << IEEE80211_RADIOTAP_RATE) | | 1849 | (1 << IEEE80211_RADIOTAP_RATE) | |
1774 | (1 << IEEE80211_RADIOTAP_CHANNEL)); | 1850 | (1 << IEEE80211_RADIOTAP_CHANNEL)); |
1775 | 1851 | ||
1776 | rthdr->rate = rx->rate->bitrate / 5; | 1852 | rthdr->rate = rx->rate->bitrate / 5; |
1777 | rthdr->chan_freq = cpu_to_le16(status->freq); | 1853 | rthdr->chan_freq = cpu_to_le16(status->freq); |
1778 | 1854 | ||
1779 | if (status->band == IEEE80211_BAND_5GHZ) | 1855 | if (status->band == IEEE80211_BAND_5GHZ) |
1780 | rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM | | 1856 | rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM | |
1781 | IEEE80211_CHAN_5GHZ); | 1857 | IEEE80211_CHAN_5GHZ); |
1782 | else | 1858 | else |
1783 | rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN | | 1859 | rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN | |
1784 | IEEE80211_CHAN_2GHZ); | 1860 | IEEE80211_CHAN_2GHZ); |
1785 | 1861 | ||
1786 | skb_set_mac_header(skb, 0); | 1862 | skb_set_mac_header(skb, 0); |
1787 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1863 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1788 | skb->pkt_type = PACKET_OTHERHOST; | 1864 | skb->pkt_type = PACKET_OTHERHOST; |
1789 | skb->protocol = htons(ETH_P_802_2); | 1865 | skb->protocol = htons(ETH_P_802_2); |
1790 | 1866 | ||
1791 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 1867 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
1792 | if (!netif_running(sdata->dev)) | 1868 | if (!netif_running(sdata->dev)) |
1793 | continue; | 1869 | continue; |
1794 | 1870 | ||
1795 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || | 1871 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || |
1796 | !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) | 1872 | !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) |
1797 | continue; | 1873 | continue; |
1798 | 1874 | ||
1799 | if (prev_dev) { | 1875 | if (prev_dev) { |
1800 | skb2 = skb_clone(skb, GFP_ATOMIC); | 1876 | skb2 = skb_clone(skb, GFP_ATOMIC); |
1801 | if (skb2) { | 1877 | if (skb2) { |
1802 | skb2->dev = prev_dev; | 1878 | skb2->dev = prev_dev; |
1803 | netif_rx(skb2); | 1879 | netif_rx(skb2); |
1804 | } | 1880 | } |
1805 | } | 1881 | } |
1806 | 1882 | ||
1807 | prev_dev = sdata->dev; | 1883 | prev_dev = sdata->dev; |
1808 | sdata->dev->stats.rx_packets++; | 1884 | sdata->dev->stats.rx_packets++; |
1809 | sdata->dev->stats.rx_bytes += skb->len; | 1885 | sdata->dev->stats.rx_bytes += skb->len; |
1810 | } | 1886 | } |
1811 | 1887 | ||
1812 | if (prev_dev) { | 1888 | if (prev_dev) { |
1813 | skb->dev = prev_dev; | 1889 | skb->dev = prev_dev; |
1814 | netif_rx(skb); | 1890 | netif_rx(skb); |
1815 | skb = NULL; | 1891 | skb = NULL; |
1816 | } else | 1892 | } else |
1817 | goto out_free_skb; | 1893 | goto out_free_skb; |
1818 | 1894 | ||
1819 | rx->flags |= IEEE80211_RX_CMNTR_REPORTED; | 1895 | rx->flags |= IEEE80211_RX_CMNTR_REPORTED; |
1820 | return; | 1896 | return; |
1821 | 1897 | ||
1822 | out_free_skb: | 1898 | out_free_skb: |
1823 | dev_kfree_skb(skb); | 1899 | dev_kfree_skb(skb); |
1824 | } | 1900 | } |
1825 | 1901 | ||
1826 | 1902 | ||
1827 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | 1903 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, |
1828 | struct ieee80211_rx_data *rx, | 1904 | struct ieee80211_rx_data *rx, |
1829 | struct sk_buff *skb) | 1905 | struct sk_buff *skb) |
1830 | { | 1906 | { |
1831 | ieee80211_rx_result res = RX_DROP_MONITOR; | 1907 | ieee80211_rx_result res = RX_DROP_MONITOR; |
1832 | 1908 | ||
1833 | rx->skb = skb; | 1909 | rx->skb = skb; |
1834 | rx->sdata = sdata; | 1910 | rx->sdata = sdata; |
1835 | rx->dev = sdata->dev; | 1911 | rx->dev = sdata->dev; |
1836 | 1912 | ||
1837 | #define CALL_RXH(rxh) \ | 1913 | #define CALL_RXH(rxh) \ |
1838 | do { \ | 1914 | do { \ |
1839 | res = rxh(rx); \ | 1915 | res = rxh(rx); \ |
1840 | if (res != RX_CONTINUE) \ | 1916 | if (res != RX_CONTINUE) \ |
1841 | goto rxh_done; \ | 1917 | goto rxh_done; \ |
1842 | } while (0); | 1918 | } while (0); |
1843 | 1919 | ||
1844 | CALL_RXH(ieee80211_rx_h_passive_scan) | 1920 | CALL_RXH(ieee80211_rx_h_passive_scan) |
1845 | CALL_RXH(ieee80211_rx_h_check) | 1921 | CALL_RXH(ieee80211_rx_h_check) |
1846 | CALL_RXH(ieee80211_rx_h_decrypt) | 1922 | CALL_RXH(ieee80211_rx_h_decrypt) |
1847 | CALL_RXH(ieee80211_rx_h_sta_process) | 1923 | CALL_RXH(ieee80211_rx_h_sta_process) |
1848 | CALL_RXH(ieee80211_rx_h_defragment) | 1924 | CALL_RXH(ieee80211_rx_h_defragment) |
1849 | CALL_RXH(ieee80211_rx_h_ps_poll) | 1925 | CALL_RXH(ieee80211_rx_h_ps_poll) |
1850 | CALL_RXH(ieee80211_rx_h_michael_mic_verify) | 1926 | CALL_RXH(ieee80211_rx_h_michael_mic_verify) |
1851 | /* must be after MMIC verify so header is counted in MPDU mic */ | 1927 | /* must be after MMIC verify so header is counted in MPDU mic */ |
1852 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | 1928 | CALL_RXH(ieee80211_rx_h_remove_qos_control) |
1853 | CALL_RXH(ieee80211_rx_h_amsdu) | 1929 | CALL_RXH(ieee80211_rx_h_amsdu) |
1854 | #ifdef CONFIG_MAC80211_MESH | 1930 | #ifdef CONFIG_MAC80211_MESH |
1855 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1931 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1856 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 1932 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
1857 | #endif | 1933 | #endif |
1858 | CALL_RXH(ieee80211_rx_h_data) | 1934 | CALL_RXH(ieee80211_rx_h_data) |
1859 | CALL_RXH(ieee80211_rx_h_ctrl) | 1935 | CALL_RXH(ieee80211_rx_h_ctrl) |
1860 | CALL_RXH(ieee80211_rx_h_action) | 1936 | CALL_RXH(ieee80211_rx_h_action) |
1861 | CALL_RXH(ieee80211_rx_h_mgmt) | 1937 | CALL_RXH(ieee80211_rx_h_mgmt) |
1862 | 1938 | ||
1863 | #undef CALL_RXH | 1939 | #undef CALL_RXH |
1864 | 1940 | ||
1865 | rxh_done: | 1941 | rxh_done: |
1866 | switch (res) { | 1942 | switch (res) { |
1867 | case RX_DROP_MONITOR: | 1943 | case RX_DROP_MONITOR: |
1868 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 1944 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); |
1869 | if (rx->sta) | 1945 | if (rx->sta) |
1870 | rx->sta->rx_dropped++; | 1946 | rx->sta->rx_dropped++; |
1871 | /* fall through */ | 1947 | /* fall through */ |
1872 | case RX_CONTINUE: | 1948 | case RX_CONTINUE: |
1873 | ieee80211_rx_cooked_monitor(rx); | 1949 | ieee80211_rx_cooked_monitor(rx); |
1874 | break; | 1950 | break; |
1875 | case RX_DROP_UNUSABLE: | 1951 | case RX_DROP_UNUSABLE: |
1876 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 1952 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); |
1877 | if (rx->sta) | 1953 | if (rx->sta) |
1878 | rx->sta->rx_dropped++; | 1954 | rx->sta->rx_dropped++; |
1879 | dev_kfree_skb(rx->skb); | 1955 | dev_kfree_skb(rx->skb); |
1880 | break; | 1956 | break; |
1881 | case RX_QUEUED: | 1957 | case RX_QUEUED: |
1882 | I802_DEBUG_INC(sdata->local->rx_handlers_queued); | 1958 | I802_DEBUG_INC(sdata->local->rx_handlers_queued); |
1883 | break; | 1959 | break; |
1884 | } | 1960 | } |
1885 | } | 1961 | } |
1886 | 1962 | ||
1887 | /* main receive path */ | 1963 | /* main receive path */ |
1888 | 1964 | ||
1889 | static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | 1965 | static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, |
1890 | u8 *bssid, struct ieee80211_rx_data *rx, | 1966 | u8 *bssid, struct ieee80211_rx_data *rx, |
1891 | struct ieee80211_hdr *hdr) | 1967 | struct ieee80211_hdr *hdr) |
1892 | { | 1968 | { |
1893 | int multicast = is_multicast_ether_addr(hdr->addr1); | 1969 | int multicast = is_multicast_ether_addr(hdr->addr1); |
1894 | 1970 | ||
1895 | switch (sdata->vif.type) { | 1971 | switch (sdata->vif.type) { |
1896 | case NL80211_IFTYPE_STATION: | 1972 | case NL80211_IFTYPE_STATION: |
1897 | if (!bssid) | 1973 | if (!bssid) |
1898 | return 0; | 1974 | return 0; |
1899 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { | 1975 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { |
1900 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) | 1976 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) |
1901 | return 0; | 1977 | return 0; |
1902 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1978 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1903 | } else if (!multicast && | 1979 | } else if (!multicast && |
1904 | compare_ether_addr(sdata->dev->dev_addr, | 1980 | compare_ether_addr(sdata->dev->dev_addr, |
1905 | hdr->addr1) != 0) { | 1981 | hdr->addr1) != 0) { |
1906 | if (!(sdata->dev->flags & IFF_PROMISC)) | 1982 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1907 | return 0; | 1983 | return 0; |
1908 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1984 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1909 | } | 1985 | } |
1910 | break; | 1986 | break; |
1911 | case NL80211_IFTYPE_ADHOC: | 1987 | case NL80211_IFTYPE_ADHOC: |
1912 | if (!bssid) | 1988 | if (!bssid) |
1913 | return 0; | 1989 | return 0; |
1914 | if (ieee80211_is_beacon(hdr->frame_control)) { | 1990 | if (ieee80211_is_beacon(hdr->frame_control)) { |
1915 | return 1; | 1991 | return 1; |
1916 | } | 1992 | } |
1917 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { | 1993 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { |
1918 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) | 1994 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) |
1919 | return 0; | 1995 | return 0; |
1920 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1996 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1921 | } else if (!multicast && | 1997 | } else if (!multicast && |
1922 | compare_ether_addr(sdata->dev->dev_addr, | 1998 | compare_ether_addr(sdata->dev->dev_addr, |
1923 | hdr->addr1) != 0) { | 1999 | hdr->addr1) != 0) { |
1924 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2000 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1925 | return 0; | 2001 | return 0; |
1926 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2002 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1927 | } else if (!rx->sta) { | 2003 | } else if (!rx->sta) { |
1928 | int rate_idx; | 2004 | int rate_idx; |
1929 | if (rx->status->flag & RX_FLAG_HT) | 2005 | if (rx->status->flag & RX_FLAG_HT) |
1930 | rate_idx = 0; /* TODO: HT rates */ | 2006 | rate_idx = 0; /* TODO: HT rates */ |
1931 | else | 2007 | else |
1932 | rate_idx = rx->status->rate_idx; | 2008 | rate_idx = rx->status->rate_idx; |
1933 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, | 2009 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, |
1934 | BIT(rate_idx)); | 2010 | BIT(rate_idx)); |
1935 | } | 2011 | } |
1936 | break; | 2012 | break; |
1937 | case NL80211_IFTYPE_MESH_POINT: | 2013 | case NL80211_IFTYPE_MESH_POINT: |
1938 | if (!multicast && | 2014 | if (!multicast && |
1939 | compare_ether_addr(sdata->dev->dev_addr, | 2015 | compare_ether_addr(sdata->dev->dev_addr, |
1940 | hdr->addr1) != 0) { | 2016 | hdr->addr1) != 0) { |
1941 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2017 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1942 | return 0; | 2018 | return 0; |
1943 | 2019 | ||
1944 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2020 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1945 | } | 2021 | } |
1946 | break; | 2022 | break; |
1947 | case NL80211_IFTYPE_AP_VLAN: | 2023 | case NL80211_IFTYPE_AP_VLAN: |
1948 | case NL80211_IFTYPE_AP: | 2024 | case NL80211_IFTYPE_AP: |
1949 | if (!bssid) { | 2025 | if (!bssid) { |
1950 | if (compare_ether_addr(sdata->dev->dev_addr, | 2026 | if (compare_ether_addr(sdata->dev->dev_addr, |
1951 | hdr->addr1)) | 2027 | hdr->addr1)) |
1952 | return 0; | 2028 | return 0; |
1953 | } else if (!ieee80211_bssid_match(bssid, | 2029 | } else if (!ieee80211_bssid_match(bssid, |
1954 | sdata->dev->dev_addr)) { | 2030 | sdata->dev->dev_addr)) { |
1955 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) | 2031 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) |
1956 | return 0; | 2032 | return 0; |
1957 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2033 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1958 | } | 2034 | } |
1959 | break; | 2035 | break; |
1960 | case NL80211_IFTYPE_WDS: | 2036 | case NL80211_IFTYPE_WDS: |
1961 | if (bssid || !ieee80211_is_data(hdr->frame_control)) | 2037 | if (bssid || !ieee80211_is_data(hdr->frame_control)) |
1962 | return 0; | 2038 | return 0; |
1963 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) | 2039 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
1964 | return 0; | 2040 | return 0; |
1965 | break; | 2041 | break; |
1966 | case NL80211_IFTYPE_MONITOR: | 2042 | case NL80211_IFTYPE_MONITOR: |
1967 | /* take everything */ | 2043 | /* take everything */ |
1968 | break; | 2044 | break; |
1969 | case NL80211_IFTYPE_UNSPECIFIED: | 2045 | case NL80211_IFTYPE_UNSPECIFIED: |
1970 | case __NL80211_IFTYPE_AFTER_LAST: | 2046 | case __NL80211_IFTYPE_AFTER_LAST: |
1971 | /* should never get here */ | 2047 | /* should never get here */ |
1972 | WARN_ON(1); | 2048 | WARN_ON(1); |
1973 | break; | 2049 | break; |
1974 | } | 2050 | } |
1975 | 2051 | ||
1976 | return 1; | 2052 | return 1; |
1977 | } | 2053 | } |
1978 | 2054 | ||
1979 | /* | 2055 | /* |
1980 | * This is the actual Rx frames handler. as it blongs to Rx path it must | 2056 | * This is the actual Rx frames handler. as it blongs to Rx path it must |
1981 | * be called with rcu_read_lock protection. | 2057 | * be called with rcu_read_lock protection. |
1982 | */ | 2058 | */ |
1983 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 2059 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
1984 | struct sk_buff *skb, | 2060 | struct sk_buff *skb, |
1985 | struct ieee80211_rx_status *status, | 2061 | struct ieee80211_rx_status *status, |
1986 | struct ieee80211_rate *rate) | 2062 | struct ieee80211_rate *rate) |
1987 | { | 2063 | { |
1988 | struct ieee80211_local *local = hw_to_local(hw); | 2064 | struct ieee80211_local *local = hw_to_local(hw); |
1989 | struct ieee80211_sub_if_data *sdata; | 2065 | struct ieee80211_sub_if_data *sdata; |
1990 | struct ieee80211_hdr *hdr; | 2066 | struct ieee80211_hdr *hdr; |
1991 | struct ieee80211_rx_data rx; | 2067 | struct ieee80211_rx_data rx; |
1992 | int prepares; | 2068 | int prepares; |
1993 | struct ieee80211_sub_if_data *prev = NULL; | 2069 | struct ieee80211_sub_if_data *prev = NULL; |
1994 | struct sk_buff *skb_new; | 2070 | struct sk_buff *skb_new; |
1995 | u8 *bssid; | 2071 | u8 *bssid; |
1996 | 2072 | ||
1997 | hdr = (struct ieee80211_hdr *)skb->data; | 2073 | hdr = (struct ieee80211_hdr *)skb->data; |
1998 | memset(&rx, 0, sizeof(rx)); | 2074 | memset(&rx, 0, sizeof(rx)); |
1999 | rx.skb = skb; | 2075 | rx.skb = skb; |
2000 | rx.local = local; | 2076 | rx.local = local; |
2001 | 2077 | ||
2002 | rx.status = status; | 2078 | rx.status = status; |
2003 | rx.rate = rate; | 2079 | rx.rate = rate; |
2004 | 2080 | ||
2005 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) | 2081 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) |
2006 | local->dot11ReceivedFragmentCount++; | 2082 | local->dot11ReceivedFragmentCount++; |
2007 | 2083 | ||
2008 | rx.sta = sta_info_get(local, hdr->addr2); | 2084 | rx.sta = sta_info_get(local, hdr->addr2); |
2009 | if (rx.sta) { | 2085 | if (rx.sta) { |
2010 | rx.sdata = rx.sta->sdata; | 2086 | rx.sdata = rx.sta->sdata; |
2011 | rx.dev = rx.sta->sdata->dev; | 2087 | rx.dev = rx.sta->sdata->dev; |
2012 | } | 2088 | } |
2013 | 2089 | ||
2014 | if ((status->flag & RX_FLAG_MMIC_ERROR)) { | 2090 | if ((status->flag & RX_FLAG_MMIC_ERROR)) { |
2015 | ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx); | 2091 | ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx); |
2016 | return; | 2092 | return; |
2017 | } | 2093 | } |
2018 | 2094 | ||
2019 | if (unlikely(local->sw_scanning || local->hw_scanning)) | 2095 | if (unlikely(local->sw_scanning || local->hw_scanning)) |
2020 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2096 | rx.flags |= IEEE80211_RX_IN_SCAN; |
2021 | 2097 | ||
2022 | ieee80211_parse_qos(&rx); | 2098 | ieee80211_parse_qos(&rx); |
2023 | ieee80211_verify_alignment(&rx); | 2099 | ieee80211_verify_alignment(&rx); |
2024 | 2100 | ||
2025 | skb = rx.skb; | 2101 | skb = rx.skb; |
2026 | 2102 | ||
2027 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2103 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2028 | if (!netif_running(sdata->dev)) | 2104 | if (!netif_running(sdata->dev)) |
2029 | continue; | 2105 | continue; |
2030 | 2106 | ||
2031 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | 2107 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) |
2032 | continue; | 2108 | continue; |
2033 | 2109 | ||
2034 | bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); | 2110 | bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); |
2035 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2111 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2036 | prepares = prepare_for_handlers(sdata, bssid, &rx, hdr); | 2112 | prepares = prepare_for_handlers(sdata, bssid, &rx, hdr); |
2037 | 2113 | ||
2038 | if (!prepares) | 2114 | if (!prepares) |
2039 | continue; | 2115 | continue; |
2040 | 2116 | ||
2041 | /* | 2117 | /* |
2042 | * frame is destined for this interface, but if it's not | 2118 | * frame is destined for this interface, but if it's not |
2043 | * also for the previous one we handle that after the | 2119 | * also for the previous one we handle that after the |
2044 | * loop to avoid copying the SKB once too much | 2120 | * loop to avoid copying the SKB once too much |
2045 | */ | 2121 | */ |
2046 | 2122 | ||
2047 | if (!prev) { | 2123 | if (!prev) { |
2048 | prev = sdata; | 2124 | prev = sdata; |
2049 | continue; | 2125 | continue; |
2050 | } | 2126 | } |
2051 | 2127 | ||
2052 | /* | 2128 | /* |
2053 | * frame was destined for the previous interface | 2129 | * frame was destined for the previous interface |
2054 | * so invoke RX handlers for it | 2130 | * so invoke RX handlers for it |
2055 | */ | 2131 | */ |
2056 | 2132 | ||
2057 | skb_new = skb_copy(skb, GFP_ATOMIC); | 2133 | skb_new = skb_copy(skb, GFP_ATOMIC); |
2058 | if (!skb_new) { | 2134 | if (!skb_new) { |
2059 | if (net_ratelimit()) | 2135 | if (net_ratelimit()) |
2060 | printk(KERN_DEBUG "%s: failed to copy " | 2136 | printk(KERN_DEBUG "%s: failed to copy " |
2061 | "multicast frame for %s\n", | 2137 | "multicast frame for %s\n", |
2062 | wiphy_name(local->hw.wiphy), | 2138 | wiphy_name(local->hw.wiphy), |
2063 | prev->dev->name); | 2139 | prev->dev->name); |
2064 | continue; | 2140 | continue; |
2065 | } | 2141 | } |
2066 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); | 2142 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); |
2067 | prev = sdata; | 2143 | prev = sdata; |
2068 | } | 2144 | } |
2069 | if (prev) | 2145 | if (prev) |
2070 | ieee80211_invoke_rx_handlers(prev, &rx, skb); | 2146 | ieee80211_invoke_rx_handlers(prev, &rx, skb); |
2071 | else | 2147 | else |
2072 | dev_kfree_skb(skb); | 2148 | dev_kfree_skb(skb); |
2073 | } | 2149 | } |
2074 | 2150 | ||
2075 | #define SEQ_MODULO 0x1000 | 2151 | #define SEQ_MODULO 0x1000 |
2076 | #define SEQ_MASK 0xfff | 2152 | #define SEQ_MASK 0xfff |
2077 | 2153 | ||
2078 | static inline int seq_less(u16 sq1, u16 sq2) | 2154 | static inline int seq_less(u16 sq1, u16 sq2) |
2079 | { | 2155 | { |
2080 | return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); | 2156 | return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); |
2081 | } | 2157 | } |
2082 | 2158 | ||
2083 | static inline u16 seq_inc(u16 sq) | 2159 | static inline u16 seq_inc(u16 sq) |
2084 | { | 2160 | { |
2085 | return (sq + 1) & SEQ_MASK; | 2161 | return (sq + 1) & SEQ_MASK; |
2086 | } | 2162 | } |
2087 | 2163 | ||
2088 | static inline u16 seq_sub(u16 sq1, u16 sq2) | 2164 | static inline u16 seq_sub(u16 sq1, u16 sq2) |
2089 | { | 2165 | { |
2090 | return (sq1 - sq2) & SEQ_MASK; | 2166 | return (sq1 - sq2) & SEQ_MASK; |
2091 | } | 2167 | } |
2092 | 2168 | ||
2093 | 2169 | ||
2094 | /* | 2170 | /* |
2095 | * As it function blongs to Rx path it must be called with | 2171 | * As it function blongs to Rx path it must be called with |
2096 | * the proper rcu_read_lock protection for its flow. | 2172 | * the proper rcu_read_lock protection for its flow. |
2097 | */ | 2173 | */ |
2098 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 2174 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, |
2099 | struct tid_ampdu_rx *tid_agg_rx, | 2175 | struct tid_ampdu_rx *tid_agg_rx, |
2100 | struct sk_buff *skb, | 2176 | struct sk_buff *skb, |
2101 | u16 mpdu_seq_num, | 2177 | u16 mpdu_seq_num, |
2102 | int bar_req) | 2178 | int bar_req) |
2103 | { | 2179 | { |
2104 | struct ieee80211_local *local = hw_to_local(hw); | 2180 | struct ieee80211_local *local = hw_to_local(hw); |
2105 | struct ieee80211_rx_status status; | 2181 | struct ieee80211_rx_status status; |
2106 | u16 head_seq_num, buf_size; | 2182 | u16 head_seq_num, buf_size; |
2107 | int index; | 2183 | int index; |
2108 | struct ieee80211_supported_band *sband; | 2184 | struct ieee80211_supported_band *sband; |
2109 | struct ieee80211_rate *rate; | 2185 | struct ieee80211_rate *rate; |
2110 | 2186 | ||
2111 | buf_size = tid_agg_rx->buf_size; | 2187 | buf_size = tid_agg_rx->buf_size; |
2112 | head_seq_num = tid_agg_rx->head_seq_num; | 2188 | head_seq_num = tid_agg_rx->head_seq_num; |
2113 | 2189 | ||
2114 | /* frame with out of date sequence number */ | 2190 | /* frame with out of date sequence number */ |
2115 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 2191 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
2116 | dev_kfree_skb(skb); | 2192 | dev_kfree_skb(skb); |
2117 | return 1; | 2193 | return 1; |
2118 | } | 2194 | } |
2119 | 2195 | ||
2120 | /* if frame sequence number exceeds our buffering window size or | 2196 | /* if frame sequence number exceeds our buffering window size or |
2121 | * block Ack Request arrived - release stored frames */ | 2197 | * block Ack Request arrived - release stored frames */ |
2122 | if ((!seq_less(mpdu_seq_num, head_seq_num + buf_size)) || (bar_req)) { | 2198 | if ((!seq_less(mpdu_seq_num, head_seq_num + buf_size)) || (bar_req)) { |
2123 | /* new head to the ordering buffer */ | 2199 | /* new head to the ordering buffer */ |
2124 | if (bar_req) | 2200 | if (bar_req) |
2125 | head_seq_num = mpdu_seq_num; | 2201 | head_seq_num = mpdu_seq_num; |
2126 | else | 2202 | else |
2127 | head_seq_num = | 2203 | head_seq_num = |
2128 | seq_inc(seq_sub(mpdu_seq_num, buf_size)); | 2204 | seq_inc(seq_sub(mpdu_seq_num, buf_size)); |
2129 | /* release stored frames up to new head to stack */ | 2205 | /* release stored frames up to new head to stack */ |
2130 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 2206 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
2131 | index = seq_sub(tid_agg_rx->head_seq_num, | 2207 | index = seq_sub(tid_agg_rx->head_seq_num, |
2132 | tid_agg_rx->ssn) | 2208 | tid_agg_rx->ssn) |
2133 | % tid_agg_rx->buf_size; | 2209 | % tid_agg_rx->buf_size; |
2134 | 2210 | ||
2135 | if (tid_agg_rx->reorder_buf[index]) { | 2211 | if (tid_agg_rx->reorder_buf[index]) { |
2136 | /* release the reordered frames to stack */ | 2212 | /* release the reordered frames to stack */ |
2137 | memcpy(&status, | 2213 | memcpy(&status, |
2138 | tid_agg_rx->reorder_buf[index]->cb, | 2214 | tid_agg_rx->reorder_buf[index]->cb, |
2139 | sizeof(status)); | 2215 | sizeof(status)); |
2140 | sband = local->hw.wiphy->bands[status.band]; | 2216 | sband = local->hw.wiphy->bands[status.band]; |
2141 | if (status.flag & RX_FLAG_HT) { | 2217 | if (status.flag & RX_FLAG_HT) { |
2142 | /* TODO: HT rates */ | 2218 | /* TODO: HT rates */ |
2143 | rate = sband->bitrates; | 2219 | rate = sband->bitrates; |
2144 | } else { | 2220 | } else { |
2145 | rate = &sband->bitrates | 2221 | rate = &sband->bitrates |
2146 | [status.rate_idx]; | 2222 | [status.rate_idx]; |
2147 | } | 2223 | } |
2148 | __ieee80211_rx_handle_packet(hw, | 2224 | __ieee80211_rx_handle_packet(hw, |
2149 | tid_agg_rx->reorder_buf[index], | 2225 | tid_agg_rx->reorder_buf[index], |
2150 | &status, rate); | 2226 | &status, rate); |
2151 | tid_agg_rx->stored_mpdu_num--; | 2227 | tid_agg_rx->stored_mpdu_num--; |
2152 | tid_agg_rx->reorder_buf[index] = NULL; | 2228 | tid_agg_rx->reorder_buf[index] = NULL; |
2153 | } | 2229 | } |
2154 | tid_agg_rx->head_seq_num = | 2230 | tid_agg_rx->head_seq_num = |
2155 | seq_inc(tid_agg_rx->head_seq_num); | 2231 | seq_inc(tid_agg_rx->head_seq_num); |
2156 | } | 2232 | } |
2157 | if (bar_req) | 2233 | if (bar_req) |
2158 | return 1; | 2234 | return 1; |
2159 | } | 2235 | } |
2160 | 2236 | ||
2161 | /* now the new frame is always in the range of the reordering */ | 2237 | /* now the new frame is always in the range of the reordering */ |
2162 | /* buffer window */ | 2238 | /* buffer window */ |
2163 | index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) | 2239 | index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) |
2164 | % tid_agg_rx->buf_size; | 2240 | % tid_agg_rx->buf_size; |
2165 | /* check if we already stored this frame */ | 2241 | /* check if we already stored this frame */ |
2166 | if (tid_agg_rx->reorder_buf[index]) { | 2242 | if (tid_agg_rx->reorder_buf[index]) { |
2167 | dev_kfree_skb(skb); | 2243 | dev_kfree_skb(skb); |
2168 | return 1; | 2244 | return 1; |
2169 | } | 2245 | } |
2170 | 2246 | ||
2171 | /* if arrived mpdu is in the right order and nothing else stored */ | 2247 | /* if arrived mpdu is in the right order and nothing else stored */ |
2172 | /* release it immediately */ | 2248 | /* release it immediately */ |
2173 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 2249 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
2174 | tid_agg_rx->stored_mpdu_num == 0) { | 2250 | tid_agg_rx->stored_mpdu_num == 0) { |
2175 | tid_agg_rx->head_seq_num = | 2251 | tid_agg_rx->head_seq_num = |
2176 | seq_inc(tid_agg_rx->head_seq_num); | 2252 | seq_inc(tid_agg_rx->head_seq_num); |
2177 | return 0; | 2253 | return 0; |
2178 | } | 2254 | } |
2179 | 2255 | ||
2180 | /* put the frame in the reordering buffer */ | 2256 | /* put the frame in the reordering buffer */ |
2181 | tid_agg_rx->reorder_buf[index] = skb; | 2257 | tid_agg_rx->reorder_buf[index] = skb; |
2182 | tid_agg_rx->stored_mpdu_num++; | 2258 | tid_agg_rx->stored_mpdu_num++; |
2183 | /* release the buffer until next missing frame */ | 2259 | /* release the buffer until next missing frame */ |
2184 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | 2260 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) |
2185 | % tid_agg_rx->buf_size; | 2261 | % tid_agg_rx->buf_size; |
2186 | while (tid_agg_rx->reorder_buf[index]) { | 2262 | while (tid_agg_rx->reorder_buf[index]) { |
2187 | /* release the reordered frame back to stack */ | 2263 | /* release the reordered frame back to stack */ |
2188 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, | 2264 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, |
2189 | sizeof(status)); | 2265 | sizeof(status)); |
2190 | sband = local->hw.wiphy->bands[status.band]; | 2266 | sband = local->hw.wiphy->bands[status.band]; |
2191 | if (status.flag & RX_FLAG_HT) | 2267 | if (status.flag & RX_FLAG_HT) |
2192 | rate = sband->bitrates; /* TODO: HT rates */ | 2268 | rate = sband->bitrates; /* TODO: HT rates */ |
2193 | else | 2269 | else |
2194 | rate = &sband->bitrates[status.rate_idx]; | 2270 | rate = &sband->bitrates[status.rate_idx]; |
2195 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | 2271 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], |
2196 | &status, rate); | 2272 | &status, rate); |
2197 | tid_agg_rx->stored_mpdu_num--; | 2273 | tid_agg_rx->stored_mpdu_num--; |
2198 | tid_agg_rx->reorder_buf[index] = NULL; | 2274 | tid_agg_rx->reorder_buf[index] = NULL; |
2199 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 2275 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
2200 | index = seq_sub(tid_agg_rx->head_seq_num, | 2276 | index = seq_sub(tid_agg_rx->head_seq_num, |
2201 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 2277 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
2202 | } | 2278 | } |
2203 | return 1; | 2279 | return 1; |
2204 | } | 2280 | } |
2205 | 2281 | ||
2206 | static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | 2282 | static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, |
2207 | struct sk_buff *skb) | 2283 | struct sk_buff *skb) |
2208 | { | 2284 | { |
2209 | struct ieee80211_hw *hw = &local->hw; | 2285 | struct ieee80211_hw *hw = &local->hw; |
2210 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 2286 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
2211 | struct sta_info *sta; | 2287 | struct sta_info *sta; |
2212 | struct tid_ampdu_rx *tid_agg_rx; | 2288 | struct tid_ampdu_rx *tid_agg_rx; |
2213 | u16 sc; | 2289 | u16 sc; |
2214 | u16 mpdu_seq_num; | 2290 | u16 mpdu_seq_num; |
2215 | u8 ret = 0; | 2291 | u8 ret = 0; |
2216 | int tid; | 2292 | int tid; |
2217 | 2293 | ||
2218 | sta = sta_info_get(local, hdr->addr2); | 2294 | sta = sta_info_get(local, hdr->addr2); |
2219 | if (!sta) | 2295 | if (!sta) |
2220 | return ret; | 2296 | return ret; |
2221 | 2297 | ||
2222 | /* filter the QoS data rx stream according to | 2298 | /* filter the QoS data rx stream according to |
2223 | * STA/TID and check if this STA/TID is on aggregation */ | 2299 | * STA/TID and check if this STA/TID is on aggregation */ |
2224 | if (!ieee80211_is_data_qos(hdr->frame_control)) | 2300 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
2225 | goto end_reorder; | 2301 | goto end_reorder; |
2226 | 2302 | ||
2227 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 2303 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
2228 | 2304 | ||
2229 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 2305 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) |
2230 | goto end_reorder; | 2306 | goto end_reorder; |
2231 | 2307 | ||
2232 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 2308 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
2233 | 2309 | ||
2234 | /* qos null data frames are excluded */ | 2310 | /* qos null data frames are excluded */ |
2235 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 2311 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
2236 | goto end_reorder; | 2312 | goto end_reorder; |
2237 | 2313 | ||
2238 | /* new un-ordered ampdu frame - process it */ | 2314 | /* new un-ordered ampdu frame - process it */ |
2239 | 2315 | ||
2240 | /* reset session timer */ | 2316 | /* reset session timer */ |
2241 | if (tid_agg_rx->timeout) { | 2317 | if (tid_agg_rx->timeout) { |
2242 | unsigned long expires = | 2318 | unsigned long expires = |
2243 | jiffies + (tid_agg_rx->timeout / 1000) * HZ; | 2319 | jiffies + (tid_agg_rx->timeout / 1000) * HZ; |
2244 | mod_timer(&tid_agg_rx->session_timer, expires); | 2320 | mod_timer(&tid_agg_rx->session_timer, expires); |
2245 | } | 2321 | } |
2246 | 2322 | ||
2247 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 2323 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
2248 | sc = le16_to_cpu(hdr->seq_ctrl); | 2324 | sc = le16_to_cpu(hdr->seq_ctrl); |
2249 | if (sc & IEEE80211_SCTL_FRAG) { | 2325 | if (sc & IEEE80211_SCTL_FRAG) { |
2250 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 2326 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, |
2251 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 2327 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); |
2252 | ret = 1; | 2328 | ret = 1; |
2253 | goto end_reorder; | 2329 | goto end_reorder; |
2254 | } | 2330 | } |
2255 | 2331 | ||
2256 | /* according to mpdu sequence number deal with reordering buffer */ | 2332 | /* according to mpdu sequence number deal with reordering buffer */ |
2257 | mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | 2333 | mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; |
2258 | ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, | 2334 | ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, |
2259 | mpdu_seq_num, 0); | 2335 | mpdu_seq_num, 0); |
2260 | end_reorder: | 2336 | end_reorder: |
2261 | return ret; | 2337 | return ret; |
2262 | } | 2338 | } |
2263 | 2339 | ||
2264 | /* | 2340 | /* |
2265 | * This is the receive path handler. It is called by a low level driver when an | 2341 | * This is the receive path handler. It is called by a low level driver when an |
2266 | * 802.11 MPDU is received from the hardware. | 2342 | * 802.11 MPDU is received from the hardware. |
2267 | */ | 2343 | */ |
2268 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | 2344 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, |
2269 | struct ieee80211_rx_status *status) | 2345 | struct ieee80211_rx_status *status) |
2270 | { | 2346 | { |
2271 | struct ieee80211_local *local = hw_to_local(hw); | 2347 | struct ieee80211_local *local = hw_to_local(hw); |
2272 | struct ieee80211_rate *rate = NULL; | 2348 | struct ieee80211_rate *rate = NULL; |
2273 | struct ieee80211_supported_band *sband; | 2349 | struct ieee80211_supported_band *sband; |
2274 | 2350 | ||
2275 | if (status->band < 0 || | 2351 | if (status->band < 0 || |
2276 | status->band >= IEEE80211_NUM_BANDS) { | 2352 | status->band >= IEEE80211_NUM_BANDS) { |
2277 | WARN_ON(1); | 2353 | WARN_ON(1); |
2278 | return; | 2354 | return; |
2279 | } | 2355 | } |
2280 | 2356 | ||
2281 | sband = local->hw.wiphy->bands[status->band]; | 2357 | sband = local->hw.wiphy->bands[status->band]; |
2282 | if (!sband) { | 2358 | if (!sband) { |
2283 | WARN_ON(1); | 2359 | WARN_ON(1); |
2284 | return; | 2360 | return; |
2285 | } | 2361 | } |
2286 | 2362 | ||
2287 | if (status->flag & RX_FLAG_HT) { | 2363 | if (status->flag & RX_FLAG_HT) { |
2288 | /* rate_idx is MCS index */ | 2364 | /* rate_idx is MCS index */ |
2289 | if (WARN_ON(status->rate_idx < 0 || | 2365 | if (WARN_ON(status->rate_idx < 0 || |
2290 | status->rate_idx >= 76)) | 2366 | status->rate_idx >= 76)) |
2291 | return; | 2367 | return; |
2292 | /* HT rates are not in the table - use the highest legacy rate | 2368 | /* HT rates are not in the table - use the highest legacy rate |
2293 | * for now since other parts of mac80211 may not yet be fully | 2369 | * for now since other parts of mac80211 may not yet be fully |
2294 | * MCS aware. */ | 2370 | * MCS aware. */ |
2295 | rate = &sband->bitrates[sband->n_bitrates - 1]; | 2371 | rate = &sband->bitrates[sband->n_bitrates - 1]; |
2296 | } else { | 2372 | } else { |
2297 | if (WARN_ON(status->rate_idx < 0 || | 2373 | if (WARN_ON(status->rate_idx < 0 || |
2298 | status->rate_idx >= sband->n_bitrates)) | 2374 | status->rate_idx >= sband->n_bitrates)) |
2299 | return; | 2375 | return; |
2300 | rate = &sband->bitrates[status->rate_idx]; | 2376 | rate = &sband->bitrates[status->rate_idx]; |
2301 | } | 2377 | } |
2302 | 2378 | ||
2303 | /* | 2379 | /* |
2304 | * key references and virtual interfaces are protected using RCU | 2380 | * key references and virtual interfaces are protected using RCU |
2305 | * and this requires that we are in a read-side RCU section during | 2381 | * and this requires that we are in a read-side RCU section during |
2306 | * receive processing | 2382 | * receive processing |
2307 | */ | 2383 | */ |
2308 | rcu_read_lock(); | 2384 | rcu_read_lock(); |
2309 | 2385 | ||
2310 | /* | 2386 | /* |
2311 | * Frames with failed FCS/PLCP checksum are not returned, | 2387 | * Frames with failed FCS/PLCP checksum are not returned, |
2312 | * all other frames are returned without radiotap header | 2388 | * all other frames are returned without radiotap header |
2313 | * if it was previously present. | 2389 | * if it was previously present. |
2314 | * Also, frames with less than 16 bytes are dropped. | 2390 | * Also, frames with less than 16 bytes are dropped. |
2315 | */ | 2391 | */ |
2316 | skb = ieee80211_rx_monitor(local, skb, status, rate); | 2392 | skb = ieee80211_rx_monitor(local, skb, status, rate); |
2317 | if (!skb) { | 2393 | if (!skb) { |
2318 | rcu_read_unlock(); | 2394 | rcu_read_unlock(); |
2319 | return; | 2395 | return; |
2320 | } | 2396 | } |
2321 | 2397 | ||
2322 | if (!ieee80211_rx_reorder_ampdu(local, skb)) | 2398 | if (!ieee80211_rx_reorder_ampdu(local, skb)) |
2323 | __ieee80211_rx_handle_packet(hw, skb, status, rate); | 2399 | __ieee80211_rx_handle_packet(hw, skb, status, rate); |
2324 | 2400 | ||
2325 | rcu_read_unlock(); | 2401 | rcu_read_unlock(); |
2326 | } | 2402 | } |
2327 | EXPORT_SYMBOL(__ieee80211_rx); | 2403 | EXPORT_SYMBOL(__ieee80211_rx); |
2328 | 2404 | ||
2329 | /* This is a version of the rx handler that can be called from hard irq | 2405 | /* This is a version of the rx handler that can be called from hard irq |
2330 | * context. Post the skb on the queue and schedule the tasklet */ | 2406 | * context. Post the skb on the queue and schedule the tasklet */ |
2331 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb, | 2407 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb, |
2332 | struct ieee80211_rx_status *status) | 2408 | struct ieee80211_rx_status *status) |
2333 | { | 2409 | { |
2334 | struct ieee80211_local *local = hw_to_local(hw); | 2410 | struct ieee80211_local *local = hw_to_local(hw); |
2335 | 2411 | ||
2336 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); | 2412 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); |
2337 | 2413 | ||
2338 | skb->dev = local->mdev; | 2414 | skb->dev = local->mdev; |
2339 | /* copy status into skb->cb for use by tasklet */ | 2415 | /* copy status into skb->cb for use by tasklet */ |
2340 | memcpy(skb->cb, status, sizeof(*status)); | 2416 | memcpy(skb->cb, status, sizeof(*status)); |
2341 | skb->pkt_type = IEEE80211_RX_MSG; | 2417 | skb->pkt_type = IEEE80211_RX_MSG; |
2342 | skb_queue_tail(&local->skb_queue, skb); | 2418 | skb_queue_tail(&local->skb_queue, skb); |
2343 | tasklet_schedule(&local->tasklet); | 2419 | tasklet_schedule(&local->tasklet); |
2344 | } | 2420 | } |
2345 | EXPORT_SYMBOL(ieee80211_rx_irqsafe); | 2421 | EXPORT_SYMBOL(ieee80211_rx_irqsafe); |
2346 | 2422 |
net/mac80211/tx.c
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007 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 | * Transmit and frame generation functions. | 12 | * Transmit and frame generation functions. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/bitmap.h> | 19 | #include <linux/bitmap.h> |
20 | #include <linux/rcupdate.h> | 20 | #include <linux/rcupdate.h> |
21 | #include <net/net_namespace.h> | 21 | #include <net/net_namespace.h> |
22 | #include <net/ieee80211_radiotap.h> | 22 | #include <net/ieee80211_radiotap.h> |
23 | #include <net/cfg80211.h> | 23 | #include <net/cfg80211.h> |
24 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
25 | #include <asm/unaligned.h> | 25 | #include <asm/unaligned.h> |
26 | 26 | ||
27 | #include "ieee80211_i.h" | 27 | #include "ieee80211_i.h" |
28 | #include "led.h" | 28 | #include "led.h" |
29 | #include "mesh.h" | 29 | #include "mesh.h" |
30 | #include "wep.h" | 30 | #include "wep.h" |
31 | #include "wpa.h" | 31 | #include "wpa.h" |
32 | #include "wme.h" | 32 | #include "wme.h" |
33 | #include "rate.h" | 33 | #include "rate.h" |
34 | 34 | ||
35 | #define IEEE80211_TX_OK 0 | 35 | #define IEEE80211_TX_OK 0 |
36 | #define IEEE80211_TX_AGAIN 1 | 36 | #define IEEE80211_TX_AGAIN 1 |
37 | #define IEEE80211_TX_FRAG_AGAIN 2 | 37 | #define IEEE80211_TX_FRAG_AGAIN 2 |
38 | 38 | ||
39 | /* misc utils */ | 39 | /* misc utils */ |
40 | 40 | ||
41 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | 41 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, |
42 | int next_frag_len) | 42 | int next_frag_len) |
43 | { | 43 | { |
44 | int rate, mrate, erp, dur, i; | 44 | int rate, mrate, erp, dur, i; |
45 | struct ieee80211_rate *txrate; | 45 | struct ieee80211_rate *txrate; |
46 | struct ieee80211_local *local = tx->local; | 46 | struct ieee80211_local *local = tx->local; |
47 | struct ieee80211_supported_band *sband; | 47 | struct ieee80211_supported_band *sband; |
48 | struct ieee80211_hdr *hdr; | 48 | struct ieee80211_hdr *hdr; |
49 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 49 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
50 | 50 | ||
51 | /* assume HW handles this */ | 51 | /* assume HW handles this */ |
52 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) | 52 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) |
53 | return 0; | 53 | return 0; |
54 | 54 | ||
55 | /* uh huh? */ | 55 | /* uh huh? */ |
56 | if (WARN_ON_ONCE(info->control.rates[0].idx < 0)) | 56 | if (WARN_ON_ONCE(info->control.rates[0].idx < 0)) |
57 | return 0; | 57 | return 0; |
58 | 58 | ||
59 | sband = local->hw.wiphy->bands[tx->channel->band]; | 59 | sband = local->hw.wiphy->bands[tx->channel->band]; |
60 | txrate = &sband->bitrates[info->control.rates[0].idx]; | 60 | txrate = &sband->bitrates[info->control.rates[0].idx]; |
61 | 61 | ||
62 | erp = txrate->flags & IEEE80211_RATE_ERP_G; | 62 | erp = txrate->flags & IEEE80211_RATE_ERP_G; |
63 | 63 | ||
64 | /* | 64 | /* |
65 | * data and mgmt (except PS Poll): | 65 | * data and mgmt (except PS Poll): |
66 | * - during CFP: 32768 | 66 | * - during CFP: 32768 |
67 | * - during contention period: | 67 | * - during contention period: |
68 | * if addr1 is group address: 0 | 68 | * if addr1 is group address: 0 |
69 | * if more fragments = 0 and addr1 is individual address: time to | 69 | * if more fragments = 0 and addr1 is individual address: time to |
70 | * transmit one ACK plus SIFS | 70 | * transmit one ACK plus SIFS |
71 | * if more fragments = 1 and addr1 is individual address: time to | 71 | * if more fragments = 1 and addr1 is individual address: time to |
72 | * transmit next fragment plus 2 x ACK plus 3 x SIFS | 72 | * transmit next fragment plus 2 x ACK plus 3 x SIFS |
73 | * | 73 | * |
74 | * IEEE 802.11, 9.6: | 74 | * IEEE 802.11, 9.6: |
75 | * - control response frame (CTS or ACK) shall be transmitted using the | 75 | * - control response frame (CTS or ACK) shall be transmitted using the |
76 | * same rate as the immediately previous frame in the frame exchange | 76 | * same rate as the immediately previous frame in the frame exchange |
77 | * sequence, if this rate belongs to the PHY mandatory rates, or else | 77 | * sequence, if this rate belongs to the PHY mandatory rates, or else |
78 | * at the highest possible rate belonging to the PHY rates in the | 78 | * at the highest possible rate belonging to the PHY rates in the |
79 | * BSSBasicRateSet | 79 | * BSSBasicRateSet |
80 | */ | 80 | */ |
81 | hdr = (struct ieee80211_hdr *)tx->skb->data; | 81 | hdr = (struct ieee80211_hdr *)tx->skb->data; |
82 | if (ieee80211_is_ctl(hdr->frame_control)) { | 82 | if (ieee80211_is_ctl(hdr->frame_control)) { |
83 | /* TODO: These control frames are not currently sent by | 83 | /* TODO: These control frames are not currently sent by |
84 | * mac80211, but should they be implemented, this function | 84 | * mac80211, but should they be implemented, this function |
85 | * needs to be updated to support duration field calculation. | 85 | * needs to be updated to support duration field calculation. |
86 | * | 86 | * |
87 | * RTS: time needed to transmit pending data/mgmt frame plus | 87 | * RTS: time needed to transmit pending data/mgmt frame plus |
88 | * one CTS frame plus one ACK frame plus 3 x SIFS | 88 | * one CTS frame plus one ACK frame plus 3 x SIFS |
89 | * CTS: duration of immediately previous RTS minus time | 89 | * CTS: duration of immediately previous RTS minus time |
90 | * required to transmit CTS and its SIFS | 90 | * required to transmit CTS and its SIFS |
91 | * ACK: 0 if immediately previous directed data/mgmt had | 91 | * ACK: 0 if immediately previous directed data/mgmt had |
92 | * more=0, with more=1 duration in ACK frame is duration | 92 | * more=0, with more=1 duration in ACK frame is duration |
93 | * from previous frame minus time needed to transmit ACK | 93 | * from previous frame minus time needed to transmit ACK |
94 | * and its SIFS | 94 | * and its SIFS |
95 | * PS Poll: BIT(15) | BIT(14) | aid | 95 | * PS Poll: BIT(15) | BIT(14) | aid |
96 | */ | 96 | */ |
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | 99 | ||
100 | /* data/mgmt */ | 100 | /* data/mgmt */ |
101 | if (0 /* FIX: data/mgmt during CFP */) | 101 | if (0 /* FIX: data/mgmt during CFP */) |
102 | return cpu_to_le16(32768); | 102 | return cpu_to_le16(32768); |
103 | 103 | ||
104 | if (group_addr) /* Group address as the destination - no ACK */ | 104 | if (group_addr) /* Group address as the destination - no ACK */ |
105 | return 0; | 105 | return 0; |
106 | 106 | ||
107 | /* Individual destination address: | 107 | /* Individual destination address: |
108 | * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes) | 108 | * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes) |
109 | * CTS and ACK frames shall be transmitted using the highest rate in | 109 | * CTS and ACK frames shall be transmitted using the highest rate in |
110 | * basic rate set that is less than or equal to the rate of the | 110 | * basic rate set that is less than or equal to the rate of the |
111 | * immediately previous frame and that is using the same modulation | 111 | * immediately previous frame and that is using the same modulation |
112 | * (CCK or OFDM). If no basic rate set matches with these requirements, | 112 | * (CCK or OFDM). If no basic rate set matches with these requirements, |
113 | * the highest mandatory rate of the PHY that is less than or equal to | 113 | * the highest mandatory rate of the PHY that is less than or equal to |
114 | * the rate of the previous frame is used. | 114 | * the rate of the previous frame is used. |
115 | * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps | 115 | * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps |
116 | */ | 116 | */ |
117 | rate = -1; | 117 | rate = -1; |
118 | /* use lowest available if everything fails */ | 118 | /* use lowest available if everything fails */ |
119 | mrate = sband->bitrates[0].bitrate; | 119 | mrate = sband->bitrates[0].bitrate; |
120 | for (i = 0; i < sband->n_bitrates; i++) { | 120 | for (i = 0; i < sband->n_bitrates; i++) { |
121 | struct ieee80211_rate *r = &sband->bitrates[i]; | 121 | struct ieee80211_rate *r = &sband->bitrates[i]; |
122 | 122 | ||
123 | if (r->bitrate > txrate->bitrate) | 123 | if (r->bitrate > txrate->bitrate) |
124 | break; | 124 | break; |
125 | 125 | ||
126 | if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) | 126 | if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) |
127 | rate = r->bitrate; | 127 | rate = r->bitrate; |
128 | 128 | ||
129 | switch (sband->band) { | 129 | switch (sband->band) { |
130 | case IEEE80211_BAND_2GHZ: { | 130 | case IEEE80211_BAND_2GHZ: { |
131 | u32 flag; | 131 | u32 flag; |
132 | if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 132 | if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
133 | flag = IEEE80211_RATE_MANDATORY_G; | 133 | flag = IEEE80211_RATE_MANDATORY_G; |
134 | else | 134 | else |
135 | flag = IEEE80211_RATE_MANDATORY_B; | 135 | flag = IEEE80211_RATE_MANDATORY_B; |
136 | if (r->flags & flag) | 136 | if (r->flags & flag) |
137 | mrate = r->bitrate; | 137 | mrate = r->bitrate; |
138 | break; | 138 | break; |
139 | } | 139 | } |
140 | case IEEE80211_BAND_5GHZ: | 140 | case IEEE80211_BAND_5GHZ: |
141 | if (r->flags & IEEE80211_RATE_MANDATORY_A) | 141 | if (r->flags & IEEE80211_RATE_MANDATORY_A) |
142 | mrate = r->bitrate; | 142 | mrate = r->bitrate; |
143 | break; | 143 | break; |
144 | case IEEE80211_NUM_BANDS: | 144 | case IEEE80211_NUM_BANDS: |
145 | WARN_ON(1); | 145 | WARN_ON(1); |
146 | break; | 146 | break; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | if (rate == -1) { | 149 | if (rate == -1) { |
150 | /* No matching basic rate found; use highest suitable mandatory | 150 | /* No matching basic rate found; use highest suitable mandatory |
151 | * PHY rate */ | 151 | * PHY rate */ |
152 | rate = mrate; | 152 | rate = mrate; |
153 | } | 153 | } |
154 | 154 | ||
155 | /* Time needed to transmit ACK | 155 | /* Time needed to transmit ACK |
156 | * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up | 156 | * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up |
157 | * to closest integer */ | 157 | * to closest integer */ |
158 | 158 | ||
159 | dur = ieee80211_frame_duration(local, 10, rate, erp, | 159 | dur = ieee80211_frame_duration(local, 10, rate, erp, |
160 | tx->sdata->vif.bss_conf.use_short_preamble); | 160 | tx->sdata->vif.bss_conf.use_short_preamble); |
161 | 161 | ||
162 | if (next_frag_len) { | 162 | if (next_frag_len) { |
163 | /* Frame is fragmented: duration increases with time needed to | 163 | /* Frame is fragmented: duration increases with time needed to |
164 | * transmit next fragment plus ACK and 2 x SIFS. */ | 164 | * transmit next fragment plus ACK and 2 x SIFS. */ |
165 | dur *= 2; /* ACK + SIFS */ | 165 | dur *= 2; /* ACK + SIFS */ |
166 | /* next fragment */ | 166 | /* next fragment */ |
167 | dur += ieee80211_frame_duration(local, next_frag_len, | 167 | dur += ieee80211_frame_duration(local, next_frag_len, |
168 | txrate->bitrate, erp, | 168 | txrate->bitrate, erp, |
169 | tx->sdata->vif.bss_conf.use_short_preamble); | 169 | tx->sdata->vif.bss_conf.use_short_preamble); |
170 | } | 170 | } |
171 | 171 | ||
172 | return cpu_to_le16(dur); | 172 | return cpu_to_le16(dur); |
173 | } | 173 | } |
174 | 174 | ||
175 | static int inline is_ieee80211_device(struct ieee80211_local *local, | 175 | static int inline is_ieee80211_device(struct ieee80211_local *local, |
176 | struct net_device *dev) | 176 | struct net_device *dev) |
177 | { | 177 | { |
178 | return local == wdev_priv(dev->ieee80211_ptr); | 178 | return local == wdev_priv(dev->ieee80211_ptr); |
179 | } | 179 | } |
180 | 180 | ||
181 | /* tx handlers */ | 181 | /* tx handlers */ |
182 | 182 | ||
183 | static ieee80211_tx_result debug_noinline | 183 | static ieee80211_tx_result debug_noinline |
184 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | 184 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) |
185 | { | 185 | { |
186 | 186 | ||
187 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 187 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
188 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 188 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
189 | u32 sta_flags; | 189 | u32 sta_flags; |
190 | 190 | ||
191 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | 191 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
192 | return TX_CONTINUE; | 192 | return TX_CONTINUE; |
193 | 193 | ||
194 | if (unlikely(tx->local->sw_scanning) && | 194 | if (unlikely(tx->local->sw_scanning) && |
195 | !ieee80211_is_probe_req(hdr->frame_control)) | 195 | !ieee80211_is_probe_req(hdr->frame_control)) |
196 | return TX_DROP; | 196 | return TX_DROP; |
197 | 197 | ||
198 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 198 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
199 | return TX_CONTINUE; | 199 | return TX_CONTINUE; |
200 | 200 | ||
201 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) | 201 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) |
202 | return TX_CONTINUE; | 202 | return TX_CONTINUE; |
203 | 203 | ||
204 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; | 204 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; |
205 | 205 | ||
206 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 206 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
207 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && | 207 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && |
208 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 208 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
209 | ieee80211_is_data(hdr->frame_control))) { | 209 | ieee80211_is_data(hdr->frame_control))) { |
210 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 210 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
211 | printk(KERN_DEBUG "%s: dropped data frame to not " | 211 | printk(KERN_DEBUG "%s: dropped data frame to not " |
212 | "associated station %pM\n", | 212 | "associated station %pM\n", |
213 | tx->dev->name, hdr->addr1); | 213 | tx->dev->name, hdr->addr1); |
214 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 214 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
215 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); | 215 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); |
216 | return TX_DROP; | 216 | return TX_DROP; |
217 | } | 217 | } |
218 | } else { | 218 | } else { |
219 | if (unlikely(ieee80211_is_data(hdr->frame_control) && | 219 | if (unlikely(ieee80211_is_data(hdr->frame_control) && |
220 | tx->local->num_sta == 0 && | 220 | tx->local->num_sta == 0 && |
221 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { | 221 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { |
222 | /* | 222 | /* |
223 | * No associated STAs - no need to send multicast | 223 | * No associated STAs - no need to send multicast |
224 | * frames. | 224 | * frames. |
225 | */ | 225 | */ |
226 | return TX_DROP; | 226 | return TX_DROP; |
227 | } | 227 | } |
228 | return TX_CONTINUE; | 228 | return TX_CONTINUE; |
229 | } | 229 | } |
230 | 230 | ||
231 | return TX_CONTINUE; | 231 | return TX_CONTINUE; |
232 | } | 232 | } |
233 | 233 | ||
234 | /* This function is called whenever the AP is about to exceed the maximum limit | 234 | /* This function is called whenever the AP is about to exceed the maximum limit |
235 | * of buffered frames for power saving STAs. This situation should not really | 235 | * of buffered frames for power saving STAs. This situation should not really |
236 | * happen often during normal operation, so dropping the oldest buffered packet | 236 | * happen often during normal operation, so dropping the oldest buffered packet |
237 | * from each queue should be OK to make some room for new frames. */ | 237 | * from each queue should be OK to make some room for new frames. */ |
238 | static void purge_old_ps_buffers(struct ieee80211_local *local) | 238 | static void purge_old_ps_buffers(struct ieee80211_local *local) |
239 | { | 239 | { |
240 | int total = 0, purged = 0; | 240 | int total = 0, purged = 0; |
241 | struct sk_buff *skb; | 241 | struct sk_buff *skb; |
242 | struct ieee80211_sub_if_data *sdata; | 242 | struct ieee80211_sub_if_data *sdata; |
243 | struct sta_info *sta; | 243 | struct sta_info *sta; |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * virtual interfaces are protected by RCU | 246 | * virtual interfaces are protected by RCU |
247 | */ | 247 | */ |
248 | rcu_read_lock(); | 248 | rcu_read_lock(); |
249 | 249 | ||
250 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 250 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
251 | struct ieee80211_if_ap *ap; | 251 | struct ieee80211_if_ap *ap; |
252 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 252 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
253 | continue; | 253 | continue; |
254 | ap = &sdata->u.ap; | 254 | ap = &sdata->u.ap; |
255 | skb = skb_dequeue(&ap->ps_bc_buf); | 255 | skb = skb_dequeue(&ap->ps_bc_buf); |
256 | if (skb) { | 256 | if (skb) { |
257 | purged++; | 257 | purged++; |
258 | dev_kfree_skb(skb); | 258 | dev_kfree_skb(skb); |
259 | } | 259 | } |
260 | total += skb_queue_len(&ap->ps_bc_buf); | 260 | total += skb_queue_len(&ap->ps_bc_buf); |
261 | } | 261 | } |
262 | 262 | ||
263 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 263 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
264 | skb = skb_dequeue(&sta->ps_tx_buf); | 264 | skb = skb_dequeue(&sta->ps_tx_buf); |
265 | if (skb) { | 265 | if (skb) { |
266 | purged++; | 266 | purged++; |
267 | dev_kfree_skb(skb); | 267 | dev_kfree_skb(skb); |
268 | } | 268 | } |
269 | total += skb_queue_len(&sta->ps_tx_buf); | 269 | total += skb_queue_len(&sta->ps_tx_buf); |
270 | } | 270 | } |
271 | 271 | ||
272 | rcu_read_unlock(); | 272 | rcu_read_unlock(); |
273 | 273 | ||
274 | local->total_ps_buffered = total; | 274 | local->total_ps_buffered = total; |
275 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 275 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
276 | printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", | 276 | printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", |
277 | wiphy_name(local->hw.wiphy), purged); | 277 | wiphy_name(local->hw.wiphy), purged); |
278 | #endif | 278 | #endif |
279 | } | 279 | } |
280 | 280 | ||
281 | static ieee80211_tx_result | 281 | static ieee80211_tx_result |
282 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | 282 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) |
283 | { | 283 | { |
284 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 284 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
285 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 285 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
286 | 286 | ||
287 | /* | 287 | /* |
288 | * broadcast/multicast frame | 288 | * broadcast/multicast frame |
289 | * | 289 | * |
290 | * If any of the associated stations is in power save mode, | 290 | * If any of the associated stations is in power save mode, |
291 | * the frame is buffered to be sent after DTIM beacon frame. | 291 | * the frame is buffered to be sent after DTIM beacon frame. |
292 | * This is done either by the hardware or us. | 292 | * This is done either by the hardware or us. |
293 | */ | 293 | */ |
294 | 294 | ||
295 | /* powersaving STAs only in AP/VLAN mode */ | 295 | /* powersaving STAs only in AP/VLAN mode */ |
296 | if (!tx->sdata->bss) | 296 | if (!tx->sdata->bss) |
297 | return TX_CONTINUE; | 297 | return TX_CONTINUE; |
298 | 298 | ||
299 | /* no buffering for ordered frames */ | 299 | /* no buffering for ordered frames */ |
300 | if (ieee80211_has_order(hdr->frame_control)) | 300 | if (ieee80211_has_order(hdr->frame_control)) |
301 | return TX_CONTINUE; | 301 | return TX_CONTINUE; |
302 | 302 | ||
303 | /* no stations in PS mode */ | 303 | /* no stations in PS mode */ |
304 | if (!atomic_read(&tx->sdata->bss->num_sta_ps)) | 304 | if (!atomic_read(&tx->sdata->bss->num_sta_ps)) |
305 | return TX_CONTINUE; | 305 | return TX_CONTINUE; |
306 | 306 | ||
307 | /* buffered in mac80211 */ | 307 | /* buffered in mac80211 */ |
308 | if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) { | 308 | if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) { |
309 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 309 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
310 | purge_old_ps_buffers(tx->local); | 310 | purge_old_ps_buffers(tx->local); |
311 | if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= | 311 | if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= |
312 | AP_MAX_BC_BUFFER) { | 312 | AP_MAX_BC_BUFFER) { |
313 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 313 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
314 | if (net_ratelimit()) { | 314 | if (net_ratelimit()) { |
315 | printk(KERN_DEBUG "%s: BC TX buffer full - " | 315 | printk(KERN_DEBUG "%s: BC TX buffer full - " |
316 | "dropping the oldest frame\n", | 316 | "dropping the oldest frame\n", |
317 | tx->dev->name); | 317 | tx->dev->name); |
318 | } | 318 | } |
319 | #endif | 319 | #endif |
320 | dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); | 320 | dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); |
321 | } else | 321 | } else |
322 | tx->local->total_ps_buffered++; | 322 | tx->local->total_ps_buffered++; |
323 | skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb); | 323 | skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb); |
324 | return TX_QUEUED; | 324 | return TX_QUEUED; |
325 | } | 325 | } |
326 | 326 | ||
327 | /* buffered in hardware */ | 327 | /* buffered in hardware */ |
328 | info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; | 328 | info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; |
329 | 329 | ||
330 | return TX_CONTINUE; | 330 | return TX_CONTINUE; |
331 | } | 331 | } |
332 | 332 | ||
333 | static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, | 333 | static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, |
334 | struct sk_buff *skb) | 334 | struct sk_buff *skb) |
335 | { | 335 | { |
336 | if (!ieee80211_is_mgmt(fc)) | 336 | if (!ieee80211_is_mgmt(fc)) |
337 | return 0; | 337 | return 0; |
338 | 338 | ||
339 | if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) | 339 | if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) |
340 | return 0; | 340 | return 0; |
341 | 341 | ||
342 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) | 342 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) |
343 | skb->data)) | 343 | skb->data)) |
344 | return 0; | 344 | return 0; |
345 | 345 | ||
346 | return 1; | 346 | return 1; |
347 | } | 347 | } |
348 | 348 | ||
349 | static ieee80211_tx_result | 349 | static ieee80211_tx_result |
350 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | 350 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) |
351 | { | 351 | { |
352 | struct sta_info *sta = tx->sta; | 352 | struct sta_info *sta = tx->sta; |
353 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 353 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
354 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 354 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
355 | u32 staflags; | 355 | u32 staflags; |
356 | 356 | ||
357 | if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) | 357 | if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) |
358 | return TX_CONTINUE; | 358 | return TX_CONTINUE; |
359 | 359 | ||
360 | staflags = get_sta_flags(sta); | 360 | staflags = get_sta_flags(sta); |
361 | 361 | ||
362 | if (unlikely((staflags & WLAN_STA_PS) && | 362 | if (unlikely((staflags & WLAN_STA_PS) && |
363 | !(staflags & WLAN_STA_PSPOLL))) { | 363 | !(staflags & WLAN_STA_PSPOLL))) { |
364 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 364 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
365 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " | 365 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " |
366 | "before %d)\n", | 366 | "before %d)\n", |
367 | sta->sta.addr, sta->sta.aid, | 367 | sta->sta.addr, sta->sta.aid, |
368 | skb_queue_len(&sta->ps_tx_buf)); | 368 | skb_queue_len(&sta->ps_tx_buf)); |
369 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 369 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
370 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 370 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
371 | purge_old_ps_buffers(tx->local); | 371 | purge_old_ps_buffers(tx->local); |
372 | if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { | 372 | if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { |
373 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); | 373 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); |
374 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 374 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
375 | if (net_ratelimit()) { | 375 | if (net_ratelimit()) { |
376 | printk(KERN_DEBUG "%s: STA %pM TX " | 376 | printk(KERN_DEBUG "%s: STA %pM TX " |
377 | "buffer full - dropping oldest frame\n", | 377 | "buffer full - dropping oldest frame\n", |
378 | tx->dev->name, sta->sta.addr); | 378 | tx->dev->name, sta->sta.addr); |
379 | } | 379 | } |
380 | #endif | 380 | #endif |
381 | dev_kfree_skb(old); | 381 | dev_kfree_skb(old); |
382 | } else | 382 | } else |
383 | tx->local->total_ps_buffered++; | 383 | tx->local->total_ps_buffered++; |
384 | 384 | ||
385 | /* Queue frame to be sent after STA sends an PS Poll frame */ | 385 | /* Queue frame to be sent after STA sends an PS Poll frame */ |
386 | if (skb_queue_empty(&sta->ps_tx_buf)) | 386 | if (skb_queue_empty(&sta->ps_tx_buf)) |
387 | sta_info_set_tim_bit(sta); | 387 | sta_info_set_tim_bit(sta); |
388 | 388 | ||
389 | info->control.jiffies = jiffies; | 389 | info->control.jiffies = jiffies; |
390 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 390 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); |
391 | return TX_QUEUED; | 391 | return TX_QUEUED; |
392 | } | 392 | } |
393 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 393 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
394 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { | 394 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { |
395 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " | 395 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " |
396 | "set -> send frame\n", tx->dev->name, | 396 | "set -> send frame\n", tx->dev->name, |
397 | sta->sta.addr); | 397 | sta->sta.addr); |
398 | } | 398 | } |
399 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 399 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
400 | clear_sta_flags(sta, WLAN_STA_PSPOLL); | 400 | clear_sta_flags(sta, WLAN_STA_PSPOLL); |
401 | 401 | ||
402 | return TX_CONTINUE; | 402 | return TX_CONTINUE; |
403 | } | 403 | } |
404 | 404 | ||
405 | static ieee80211_tx_result debug_noinline | 405 | static ieee80211_tx_result debug_noinline |
406 | ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) | 406 | ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) |
407 | { | 407 | { |
408 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) | 408 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) |
409 | return TX_CONTINUE; | 409 | return TX_CONTINUE; |
410 | 410 | ||
411 | if (tx->flags & IEEE80211_TX_UNICAST) | 411 | if (tx->flags & IEEE80211_TX_UNICAST) |
412 | return ieee80211_tx_h_unicast_ps_buf(tx); | 412 | return ieee80211_tx_h_unicast_ps_buf(tx); |
413 | else | 413 | else |
414 | return ieee80211_tx_h_multicast_ps_buf(tx); | 414 | return ieee80211_tx_h_multicast_ps_buf(tx); |
415 | } | 415 | } |
416 | 416 | ||
417 | static ieee80211_tx_result debug_noinline | 417 | static ieee80211_tx_result debug_noinline |
418 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | 418 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) |
419 | { | 419 | { |
420 | struct ieee80211_key *key; | 420 | struct ieee80211_key *key; |
421 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 421 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
422 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 422 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
423 | 423 | ||
424 | if (unlikely(tx->skb->do_not_encrypt)) | 424 | if (unlikely(tx->skb->do_not_encrypt)) |
425 | tx->key = NULL; | 425 | tx->key = NULL; |
426 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 426 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
427 | tx->key = key; | 427 | tx->key = key; |
428 | else if (ieee80211_is_mgmt(hdr->frame_control) && | ||
429 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | ||
430 | tx->key = key; | ||
428 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 431 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
429 | tx->key = key; | 432 | tx->key = key; |
430 | else if (tx->sdata->drop_unencrypted && | 433 | else if (tx->sdata->drop_unencrypted && |
431 | (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && | 434 | (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && |
432 | !(info->flags & IEEE80211_TX_CTL_INJECTED)) { | 435 | !(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
433 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 436 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
434 | return TX_DROP; | 437 | return TX_DROP; |
435 | } else | 438 | } else |
436 | tx->key = NULL; | 439 | tx->key = NULL; |
437 | 440 | ||
438 | if (tx->key) { | 441 | if (tx->key) { |
439 | tx->key->tx_rx_count++; | 442 | tx->key->tx_rx_count++; |
440 | /* TODO: add threshold stuff again */ | 443 | /* TODO: add threshold stuff again */ |
441 | 444 | ||
442 | switch (tx->key->conf.alg) { | 445 | switch (tx->key->conf.alg) { |
443 | case ALG_WEP: | 446 | case ALG_WEP: |
444 | if (ieee80211_is_auth(hdr->frame_control)) | 447 | if (ieee80211_is_auth(hdr->frame_control)) |
445 | break; | 448 | break; |
446 | case ALG_TKIP: | 449 | case ALG_TKIP: |
447 | if (!ieee80211_is_data_present(hdr->frame_control)) | 450 | if (!ieee80211_is_data_present(hdr->frame_control)) |
448 | tx->key = NULL; | 451 | tx->key = NULL; |
449 | break; | 452 | break; |
450 | case ALG_CCMP: | 453 | case ALG_CCMP: |
451 | if (!ieee80211_is_data_present(hdr->frame_control) && | 454 | if (!ieee80211_is_data_present(hdr->frame_control) && |
452 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | 455 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, |
453 | tx->skb)) | 456 | tx->skb)) |
454 | tx->key = NULL; | 457 | tx->key = NULL; |
455 | break; | 458 | break; |
459 | case ALG_AES_CMAC: | ||
460 | if (!ieee80211_is_mgmt(hdr->frame_control)) | ||
461 | tx->key = NULL; | ||
462 | break; | ||
456 | } | 463 | } |
457 | } | 464 | } |
458 | 465 | ||
459 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 466 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
460 | tx->skb->do_not_encrypt = 1; | 467 | tx->skb->do_not_encrypt = 1; |
461 | 468 | ||
462 | return TX_CONTINUE; | 469 | return TX_CONTINUE; |
463 | } | 470 | } |
464 | 471 | ||
465 | static ieee80211_tx_result debug_noinline | 472 | static ieee80211_tx_result debug_noinline |
466 | ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | 473 | ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) |
467 | { | 474 | { |
468 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 475 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
469 | struct ieee80211_hdr *hdr = (void *)tx->skb->data; | 476 | struct ieee80211_hdr *hdr = (void *)tx->skb->data; |
470 | struct ieee80211_supported_band *sband; | 477 | struct ieee80211_supported_band *sband; |
471 | struct ieee80211_rate *rate; | 478 | struct ieee80211_rate *rate; |
472 | int i, len; | 479 | int i, len; |
473 | bool inval = false, rts = false, short_preamble = false; | 480 | bool inval = false, rts = false, short_preamble = false; |
474 | struct ieee80211_tx_rate_control txrc; | 481 | struct ieee80211_tx_rate_control txrc; |
475 | 482 | ||
476 | memset(&txrc, 0, sizeof(txrc)); | 483 | memset(&txrc, 0, sizeof(txrc)); |
477 | 484 | ||
478 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 485 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
479 | 486 | ||
480 | len = min_t(int, tx->skb->len + FCS_LEN, | 487 | len = min_t(int, tx->skb->len + FCS_LEN, |
481 | tx->local->fragmentation_threshold); | 488 | tx->local->fragmentation_threshold); |
482 | 489 | ||
483 | /* set up the tx rate control struct we give the RC algo */ | 490 | /* set up the tx rate control struct we give the RC algo */ |
484 | txrc.hw = local_to_hw(tx->local); | 491 | txrc.hw = local_to_hw(tx->local); |
485 | txrc.sband = sband; | 492 | txrc.sband = sband; |
486 | txrc.bss_conf = &tx->sdata->vif.bss_conf; | 493 | txrc.bss_conf = &tx->sdata->vif.bss_conf; |
487 | txrc.skb = tx->skb; | 494 | txrc.skb = tx->skb; |
488 | txrc.reported_rate.idx = -1; | 495 | txrc.reported_rate.idx = -1; |
489 | txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; | 496 | txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; |
490 | 497 | ||
491 | /* set up RTS protection if desired */ | 498 | /* set up RTS protection if desired */ |
492 | if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD && | 499 | if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD && |
493 | len > tx->local->rts_threshold) { | 500 | len > tx->local->rts_threshold) { |
494 | txrc.rts = rts = true; | 501 | txrc.rts = rts = true; |
495 | } | 502 | } |
496 | 503 | ||
497 | /* | 504 | /* |
498 | * Use short preamble if the BSS can handle it, but not for | 505 | * Use short preamble if the BSS can handle it, but not for |
499 | * management frames unless we know the receiver can handle | 506 | * management frames unless we know the receiver can handle |
500 | * that -- the management frame might be to a station that | 507 | * that -- the management frame might be to a station that |
501 | * just wants a probe response. | 508 | * just wants a probe response. |
502 | */ | 509 | */ |
503 | if (tx->sdata->vif.bss_conf.use_short_preamble && | 510 | if (tx->sdata->vif.bss_conf.use_short_preamble && |
504 | (ieee80211_is_data(hdr->frame_control) || | 511 | (ieee80211_is_data(hdr->frame_control) || |
505 | (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) | 512 | (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) |
506 | txrc.short_preamble = short_preamble = true; | 513 | txrc.short_preamble = short_preamble = true; |
507 | 514 | ||
508 | 515 | ||
509 | rate_control_get_rate(tx->sdata, tx->sta, &txrc); | 516 | rate_control_get_rate(tx->sdata, tx->sta, &txrc); |
510 | 517 | ||
511 | if (unlikely(info->control.rates[0].idx < 0)) | 518 | if (unlikely(info->control.rates[0].idx < 0)) |
512 | return TX_DROP; | 519 | return TX_DROP; |
513 | 520 | ||
514 | if (txrc.reported_rate.idx < 0) | 521 | if (txrc.reported_rate.idx < 0) |
515 | txrc.reported_rate = info->control.rates[0]; | 522 | txrc.reported_rate = info->control.rates[0]; |
516 | 523 | ||
517 | if (tx->sta) | 524 | if (tx->sta) |
518 | tx->sta->last_tx_rate = txrc.reported_rate; | 525 | tx->sta->last_tx_rate = txrc.reported_rate; |
519 | 526 | ||
520 | if (unlikely(!info->control.rates[0].count)) | 527 | if (unlikely(!info->control.rates[0].count)) |
521 | info->control.rates[0].count = 1; | 528 | info->control.rates[0].count = 1; |
522 | 529 | ||
523 | if (is_multicast_ether_addr(hdr->addr1)) { | 530 | if (is_multicast_ether_addr(hdr->addr1)) { |
524 | /* | 531 | /* |
525 | * XXX: verify the rate is in the basic rateset | 532 | * XXX: verify the rate is in the basic rateset |
526 | */ | 533 | */ |
527 | return TX_CONTINUE; | 534 | return TX_CONTINUE; |
528 | } | 535 | } |
529 | 536 | ||
530 | /* | 537 | /* |
531 | * set up the RTS/CTS rate as the fastest basic rate | 538 | * set up the RTS/CTS rate as the fastest basic rate |
532 | * that is not faster than the data rate | 539 | * that is not faster than the data rate |
533 | * | 540 | * |
534 | * XXX: Should this check all retry rates? | 541 | * XXX: Should this check all retry rates? |
535 | */ | 542 | */ |
536 | if (!(info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) { | 543 | if (!(info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) { |
537 | s8 baserate = 0; | 544 | s8 baserate = 0; |
538 | 545 | ||
539 | rate = &sband->bitrates[info->control.rates[0].idx]; | 546 | rate = &sband->bitrates[info->control.rates[0].idx]; |
540 | 547 | ||
541 | for (i = 0; i < sband->n_bitrates; i++) { | 548 | for (i = 0; i < sband->n_bitrates; i++) { |
542 | /* must be a basic rate */ | 549 | /* must be a basic rate */ |
543 | if (!(tx->sdata->vif.bss_conf.basic_rates & BIT(i))) | 550 | if (!(tx->sdata->vif.bss_conf.basic_rates & BIT(i))) |
544 | continue; | 551 | continue; |
545 | /* must not be faster than the data rate */ | 552 | /* must not be faster than the data rate */ |
546 | if (sband->bitrates[i].bitrate > rate->bitrate) | 553 | if (sband->bitrates[i].bitrate > rate->bitrate) |
547 | continue; | 554 | continue; |
548 | /* maximum */ | 555 | /* maximum */ |
549 | if (sband->bitrates[baserate].bitrate < | 556 | if (sband->bitrates[baserate].bitrate < |
550 | sband->bitrates[i].bitrate) | 557 | sband->bitrates[i].bitrate) |
551 | baserate = i; | 558 | baserate = i; |
552 | } | 559 | } |
553 | 560 | ||
554 | info->control.rts_cts_rate_idx = baserate; | 561 | info->control.rts_cts_rate_idx = baserate; |
555 | } | 562 | } |
556 | 563 | ||
557 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 564 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
558 | /* | 565 | /* |
559 | * make sure there's no valid rate following | 566 | * make sure there's no valid rate following |
560 | * an invalid one, just in case drivers don't | 567 | * an invalid one, just in case drivers don't |
561 | * take the API seriously to stop at -1. | 568 | * take the API seriously to stop at -1. |
562 | */ | 569 | */ |
563 | if (inval) { | 570 | if (inval) { |
564 | info->control.rates[i].idx = -1; | 571 | info->control.rates[i].idx = -1; |
565 | continue; | 572 | continue; |
566 | } | 573 | } |
567 | if (info->control.rates[i].idx < 0) { | 574 | if (info->control.rates[i].idx < 0) { |
568 | inval = true; | 575 | inval = true; |
569 | continue; | 576 | continue; |
570 | } | 577 | } |
571 | 578 | ||
572 | /* | 579 | /* |
573 | * For now assume MCS is already set up correctly, this | 580 | * For now assume MCS is already set up correctly, this |
574 | * needs to be fixed. | 581 | * needs to be fixed. |
575 | */ | 582 | */ |
576 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) { | 583 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) { |
577 | WARN_ON(info->control.rates[i].idx > 76); | 584 | WARN_ON(info->control.rates[i].idx > 76); |
578 | continue; | 585 | continue; |
579 | } | 586 | } |
580 | 587 | ||
581 | /* set up RTS protection if desired */ | 588 | /* set up RTS protection if desired */ |
582 | if (rts) | 589 | if (rts) |
583 | info->control.rates[i].flags |= | 590 | info->control.rates[i].flags |= |
584 | IEEE80211_TX_RC_USE_RTS_CTS; | 591 | IEEE80211_TX_RC_USE_RTS_CTS; |
585 | 592 | ||
586 | /* RC is busted */ | 593 | /* RC is busted */ |
587 | if (WARN_ON_ONCE(info->control.rates[i].idx >= | 594 | if (WARN_ON_ONCE(info->control.rates[i].idx >= |
588 | sband->n_bitrates)) { | 595 | sband->n_bitrates)) { |
589 | info->control.rates[i].idx = -1; | 596 | info->control.rates[i].idx = -1; |
590 | continue; | 597 | continue; |
591 | } | 598 | } |
592 | 599 | ||
593 | rate = &sband->bitrates[info->control.rates[i].idx]; | 600 | rate = &sband->bitrates[info->control.rates[i].idx]; |
594 | 601 | ||
595 | /* set up short preamble */ | 602 | /* set up short preamble */ |
596 | if (short_preamble && | 603 | if (short_preamble && |
597 | rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) | 604 | rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) |
598 | info->control.rates[i].flags |= | 605 | info->control.rates[i].flags |= |
599 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE; | 606 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE; |
600 | 607 | ||
601 | /* set up G protection */ | 608 | /* set up G protection */ |
602 | if (!rts && tx->sdata->vif.bss_conf.use_cts_prot && | 609 | if (!rts && tx->sdata->vif.bss_conf.use_cts_prot && |
603 | rate->flags & IEEE80211_RATE_ERP_G) | 610 | rate->flags & IEEE80211_RATE_ERP_G) |
604 | info->control.rates[i].flags |= | 611 | info->control.rates[i].flags |= |
605 | IEEE80211_TX_RC_USE_CTS_PROTECT; | 612 | IEEE80211_TX_RC_USE_CTS_PROTECT; |
606 | } | 613 | } |
607 | 614 | ||
608 | return TX_CONTINUE; | 615 | return TX_CONTINUE; |
609 | } | 616 | } |
610 | 617 | ||
611 | static ieee80211_tx_result debug_noinline | 618 | static ieee80211_tx_result debug_noinline |
612 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | 619 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) |
613 | { | 620 | { |
614 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 621 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
615 | 622 | ||
616 | if (tx->sta) | 623 | if (tx->sta) |
617 | info->control.sta = &tx->sta->sta; | 624 | info->control.sta = &tx->sta->sta; |
618 | 625 | ||
619 | return TX_CONTINUE; | 626 | return TX_CONTINUE; |
620 | } | 627 | } |
621 | 628 | ||
622 | static ieee80211_tx_result debug_noinline | 629 | static ieee80211_tx_result debug_noinline |
623 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | 630 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) |
624 | { | 631 | { |
625 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 632 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
626 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 633 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
627 | u16 *seq; | 634 | u16 *seq; |
628 | u8 *qc; | 635 | u8 *qc; |
629 | int tid; | 636 | int tid; |
630 | 637 | ||
631 | /* | 638 | /* |
632 | * Packet injection may want to control the sequence | 639 | * Packet injection may want to control the sequence |
633 | * number, if we have no matching interface then we | 640 | * number, if we have no matching interface then we |
634 | * neither assign one ourselves nor ask the driver to. | 641 | * neither assign one ourselves nor ask the driver to. |
635 | */ | 642 | */ |
636 | if (unlikely(!info->control.vif)) | 643 | if (unlikely(!info->control.vif)) |
637 | return TX_CONTINUE; | 644 | return TX_CONTINUE; |
638 | 645 | ||
639 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) | 646 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) |
640 | return TX_CONTINUE; | 647 | return TX_CONTINUE; |
641 | 648 | ||
642 | if (ieee80211_hdrlen(hdr->frame_control) < 24) | 649 | if (ieee80211_hdrlen(hdr->frame_control) < 24) |
643 | return TX_CONTINUE; | 650 | return TX_CONTINUE; |
644 | 651 | ||
645 | /* | 652 | /* |
646 | * Anything but QoS data that has a sequence number field | 653 | * Anything but QoS data that has a sequence number field |
647 | * (is long enough) gets a sequence number from the global | 654 | * (is long enough) gets a sequence number from the global |
648 | * counter. | 655 | * counter. |
649 | */ | 656 | */ |
650 | if (!ieee80211_is_data_qos(hdr->frame_control)) { | 657 | if (!ieee80211_is_data_qos(hdr->frame_control)) { |
651 | /* driver should assign sequence number */ | 658 | /* driver should assign sequence number */ |
652 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 659 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
653 | /* for pure STA mode without beacons, we can do it */ | 660 | /* for pure STA mode without beacons, we can do it */ |
654 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); | 661 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); |
655 | tx->sdata->sequence_number += 0x10; | 662 | tx->sdata->sequence_number += 0x10; |
656 | tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ; | 663 | tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ; |
657 | return TX_CONTINUE; | 664 | return TX_CONTINUE; |
658 | } | 665 | } |
659 | 666 | ||
660 | /* | 667 | /* |
661 | * This should be true for injected/management frames only, for | 668 | * This should be true for injected/management frames only, for |
662 | * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ | 669 | * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ |
663 | * above since they are not QoS-data frames. | 670 | * above since they are not QoS-data frames. |
664 | */ | 671 | */ |
665 | if (!tx->sta) | 672 | if (!tx->sta) |
666 | return TX_CONTINUE; | 673 | return TX_CONTINUE; |
667 | 674 | ||
668 | /* include per-STA, per-TID sequence counter */ | 675 | /* include per-STA, per-TID sequence counter */ |
669 | 676 | ||
670 | qc = ieee80211_get_qos_ctl(hdr); | 677 | qc = ieee80211_get_qos_ctl(hdr); |
671 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 678 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
672 | seq = &tx->sta->tid_seq[tid]; | 679 | seq = &tx->sta->tid_seq[tid]; |
673 | 680 | ||
674 | hdr->seq_ctrl = cpu_to_le16(*seq); | 681 | hdr->seq_ctrl = cpu_to_le16(*seq); |
675 | 682 | ||
676 | /* Increase the sequence number. */ | 683 | /* Increase the sequence number. */ |
677 | *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; | 684 | *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; |
678 | 685 | ||
679 | return TX_CONTINUE; | 686 | return TX_CONTINUE; |
680 | } | 687 | } |
681 | 688 | ||
682 | static ieee80211_tx_result debug_noinline | 689 | static ieee80211_tx_result debug_noinline |
683 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | 690 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) |
684 | { | 691 | { |
685 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 692 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
686 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 693 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
687 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; | 694 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; |
688 | struct sk_buff **frags, *first, *frag; | 695 | struct sk_buff **frags, *first, *frag; |
689 | int i; | 696 | int i; |
690 | u16 seq; | 697 | u16 seq; |
691 | u8 *pos; | 698 | u8 *pos; |
692 | int frag_threshold = tx->local->fragmentation_threshold; | 699 | int frag_threshold = tx->local->fragmentation_threshold; |
693 | 700 | ||
694 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) | 701 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) |
695 | return TX_CONTINUE; | 702 | return TX_CONTINUE; |
696 | 703 | ||
697 | /* | 704 | /* |
698 | * Warn when submitting a fragmented A-MPDU frame and drop it. | 705 | * Warn when submitting a fragmented A-MPDU frame and drop it. |
699 | * This scenario is handled in __ieee80211_tx_prepare but extra | 706 | * This scenario is handled in __ieee80211_tx_prepare but extra |
700 | * caution taken here as fragmented ampdu may cause Tx stop. | 707 | * caution taken here as fragmented ampdu may cause Tx stop. |
701 | */ | 708 | */ |
702 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) | 709 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
703 | return TX_DROP; | 710 | return TX_DROP; |
704 | 711 | ||
705 | first = tx->skb; | 712 | first = tx->skb; |
706 | 713 | ||
707 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 714 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
708 | payload_len = first->len - hdrlen; | 715 | payload_len = first->len - hdrlen; |
709 | per_fragm = frag_threshold - hdrlen - FCS_LEN; | 716 | per_fragm = frag_threshold - hdrlen - FCS_LEN; |
710 | num_fragm = DIV_ROUND_UP(payload_len, per_fragm); | 717 | num_fragm = DIV_ROUND_UP(payload_len, per_fragm); |
711 | 718 | ||
712 | frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC); | 719 | frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC); |
713 | if (!frags) | 720 | if (!frags) |
714 | goto fail; | 721 | goto fail; |
715 | 722 | ||
716 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); | 723 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); |
717 | seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ; | 724 | seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ; |
718 | pos = first->data + hdrlen + per_fragm; | 725 | pos = first->data + hdrlen + per_fragm; |
719 | left = payload_len - per_fragm; | 726 | left = payload_len - per_fragm; |
720 | for (i = 0; i < num_fragm - 1; i++) { | 727 | for (i = 0; i < num_fragm - 1; i++) { |
721 | struct ieee80211_hdr *fhdr; | 728 | struct ieee80211_hdr *fhdr; |
722 | size_t copylen; | 729 | size_t copylen; |
723 | 730 | ||
724 | if (left <= 0) | 731 | if (left <= 0) |
725 | goto fail; | 732 | goto fail; |
726 | 733 | ||
727 | /* reserve enough extra head and tail room for possible | 734 | /* reserve enough extra head and tail room for possible |
728 | * encryption */ | 735 | * encryption */ |
729 | frag = frags[i] = | 736 | frag = frags[i] = |
730 | dev_alloc_skb(tx->local->tx_headroom + | 737 | dev_alloc_skb(tx->local->tx_headroom + |
731 | frag_threshold + | 738 | frag_threshold + |
732 | IEEE80211_ENCRYPT_HEADROOM + | 739 | IEEE80211_ENCRYPT_HEADROOM + |
733 | IEEE80211_ENCRYPT_TAILROOM); | 740 | IEEE80211_ENCRYPT_TAILROOM); |
734 | if (!frag) | 741 | if (!frag) |
735 | goto fail; | 742 | goto fail; |
736 | 743 | ||
737 | /* Make sure that all fragments use the same priority so | 744 | /* Make sure that all fragments use the same priority so |
738 | * that they end up using the same TX queue */ | 745 | * that they end up using the same TX queue */ |
739 | frag->priority = first->priority; | 746 | frag->priority = first->priority; |
740 | 747 | ||
741 | skb_reserve(frag, tx->local->tx_headroom + | 748 | skb_reserve(frag, tx->local->tx_headroom + |
742 | IEEE80211_ENCRYPT_HEADROOM); | 749 | IEEE80211_ENCRYPT_HEADROOM); |
743 | 750 | ||
744 | /* copy TX information */ | 751 | /* copy TX information */ |
745 | info = IEEE80211_SKB_CB(frag); | 752 | info = IEEE80211_SKB_CB(frag); |
746 | memcpy(info, first->cb, sizeof(frag->cb)); | 753 | memcpy(info, first->cb, sizeof(frag->cb)); |
747 | 754 | ||
748 | /* copy/fill in 802.11 header */ | 755 | /* copy/fill in 802.11 header */ |
749 | fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); | 756 | fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); |
750 | memcpy(fhdr, first->data, hdrlen); | 757 | memcpy(fhdr, first->data, hdrlen); |
751 | fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); | 758 | fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); |
752 | 759 | ||
753 | if (i == num_fragm - 2) { | 760 | if (i == num_fragm - 2) { |
754 | /* clear MOREFRAGS bit for the last fragment */ | 761 | /* clear MOREFRAGS bit for the last fragment */ |
755 | fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); | 762 | fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); |
756 | } else { | 763 | } else { |
757 | /* | 764 | /* |
758 | * No multi-rate retries for fragmented frames, that | 765 | * No multi-rate retries for fragmented frames, that |
759 | * would completely throw off the NAV at other STAs. | 766 | * would completely throw off the NAV at other STAs. |
760 | */ | 767 | */ |
761 | info->control.rates[1].idx = -1; | 768 | info->control.rates[1].idx = -1; |
762 | info->control.rates[2].idx = -1; | 769 | info->control.rates[2].idx = -1; |
763 | info->control.rates[3].idx = -1; | 770 | info->control.rates[3].idx = -1; |
764 | info->control.rates[4].idx = -1; | 771 | info->control.rates[4].idx = -1; |
765 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); | 772 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); |
766 | info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 773 | info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
767 | } | 774 | } |
768 | 775 | ||
769 | /* copy data */ | 776 | /* copy data */ |
770 | copylen = left > per_fragm ? per_fragm : left; | 777 | copylen = left > per_fragm ? per_fragm : left; |
771 | memcpy(skb_put(frag, copylen), pos, copylen); | 778 | memcpy(skb_put(frag, copylen), pos, copylen); |
772 | 779 | ||
773 | skb_copy_queue_mapping(frag, first); | 780 | skb_copy_queue_mapping(frag, first); |
774 | 781 | ||
775 | frag->do_not_encrypt = first->do_not_encrypt; | 782 | frag->do_not_encrypt = first->do_not_encrypt; |
776 | 783 | ||
777 | pos += copylen; | 784 | pos += copylen; |
778 | left -= copylen; | 785 | left -= copylen; |
779 | } | 786 | } |
780 | skb_trim(first, hdrlen + per_fragm); | 787 | skb_trim(first, hdrlen + per_fragm); |
781 | 788 | ||
782 | tx->num_extra_frag = num_fragm - 1; | 789 | tx->num_extra_frag = num_fragm - 1; |
783 | tx->extra_frag = frags; | 790 | tx->extra_frag = frags; |
784 | 791 | ||
785 | return TX_CONTINUE; | 792 | return TX_CONTINUE; |
786 | 793 | ||
787 | fail: | 794 | fail: |
788 | if (frags) { | 795 | if (frags) { |
789 | for (i = 0; i < num_fragm - 1; i++) | 796 | for (i = 0; i < num_fragm - 1; i++) |
790 | if (frags[i]) | 797 | if (frags[i]) |
791 | dev_kfree_skb(frags[i]); | 798 | dev_kfree_skb(frags[i]); |
792 | kfree(frags); | 799 | kfree(frags); |
793 | } | 800 | } |
794 | I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment); | 801 | I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment); |
795 | return TX_DROP; | 802 | return TX_DROP; |
796 | } | 803 | } |
797 | 804 | ||
798 | static ieee80211_tx_result debug_noinline | 805 | static ieee80211_tx_result debug_noinline |
799 | ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | 806 | ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) |
800 | { | 807 | { |
801 | if (!tx->key) | 808 | if (!tx->key) |
802 | return TX_CONTINUE; | 809 | return TX_CONTINUE; |
803 | 810 | ||
804 | switch (tx->key->conf.alg) { | 811 | switch (tx->key->conf.alg) { |
805 | case ALG_WEP: | 812 | case ALG_WEP: |
806 | return ieee80211_crypto_wep_encrypt(tx); | 813 | return ieee80211_crypto_wep_encrypt(tx); |
807 | case ALG_TKIP: | 814 | case ALG_TKIP: |
808 | return ieee80211_crypto_tkip_encrypt(tx); | 815 | return ieee80211_crypto_tkip_encrypt(tx); |
809 | case ALG_CCMP: | 816 | case ALG_CCMP: |
810 | return ieee80211_crypto_ccmp_encrypt(tx); | 817 | return ieee80211_crypto_ccmp_encrypt(tx); |
818 | case ALG_AES_CMAC: | ||
819 | return ieee80211_crypto_aes_cmac_encrypt(tx); | ||
811 | } | 820 | } |
812 | 821 | ||
813 | /* not reached */ | 822 | /* not reached */ |
814 | WARN_ON(1); | 823 | WARN_ON(1); |
815 | return TX_DROP; | 824 | return TX_DROP; |
816 | } | 825 | } |
817 | 826 | ||
818 | static ieee80211_tx_result debug_noinline | 827 | static ieee80211_tx_result debug_noinline |
819 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | 828 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) |
820 | { | 829 | { |
821 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 830 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
822 | int next_len, i; | 831 | int next_len, i; |
823 | int group_addr = is_multicast_ether_addr(hdr->addr1); | 832 | int group_addr = is_multicast_ether_addr(hdr->addr1); |
824 | 833 | ||
825 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { | 834 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { |
826 | hdr->duration_id = ieee80211_duration(tx, group_addr, 0); | 835 | hdr->duration_id = ieee80211_duration(tx, group_addr, 0); |
827 | return TX_CONTINUE; | 836 | return TX_CONTINUE; |
828 | } | 837 | } |
829 | 838 | ||
830 | hdr->duration_id = ieee80211_duration(tx, group_addr, | 839 | hdr->duration_id = ieee80211_duration(tx, group_addr, |
831 | tx->extra_frag[0]->len); | 840 | tx->extra_frag[0]->len); |
832 | 841 | ||
833 | for (i = 0; i < tx->num_extra_frag; i++) { | 842 | for (i = 0; i < tx->num_extra_frag; i++) { |
834 | if (i + 1 < tx->num_extra_frag) | 843 | if (i + 1 < tx->num_extra_frag) |
835 | next_len = tx->extra_frag[i + 1]->len; | 844 | next_len = tx->extra_frag[i + 1]->len; |
836 | else | 845 | else |
837 | next_len = 0; | 846 | next_len = 0; |
838 | 847 | ||
839 | hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; | 848 | hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; |
840 | hdr->duration_id = ieee80211_duration(tx, 0, next_len); | 849 | hdr->duration_id = ieee80211_duration(tx, 0, next_len); |
841 | } | 850 | } |
842 | 851 | ||
843 | return TX_CONTINUE; | 852 | return TX_CONTINUE; |
844 | } | 853 | } |
845 | 854 | ||
846 | static ieee80211_tx_result debug_noinline | 855 | static ieee80211_tx_result debug_noinline |
847 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | 856 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
848 | { | 857 | { |
849 | int i; | 858 | int i; |
850 | 859 | ||
851 | if (!tx->sta) | 860 | if (!tx->sta) |
852 | return TX_CONTINUE; | 861 | return TX_CONTINUE; |
853 | 862 | ||
854 | tx->sta->tx_packets++; | 863 | tx->sta->tx_packets++; |
855 | tx->sta->tx_fragments++; | 864 | tx->sta->tx_fragments++; |
856 | tx->sta->tx_bytes += tx->skb->len; | 865 | tx->sta->tx_bytes += tx->skb->len; |
857 | if (tx->extra_frag) { | 866 | if (tx->extra_frag) { |
858 | tx->sta->tx_fragments += tx->num_extra_frag; | 867 | tx->sta->tx_fragments += tx->num_extra_frag; |
859 | for (i = 0; i < tx->num_extra_frag; i++) | 868 | for (i = 0; i < tx->num_extra_frag; i++) |
860 | tx->sta->tx_bytes += tx->extra_frag[i]->len; | 869 | tx->sta->tx_bytes += tx->extra_frag[i]->len; |
861 | } | 870 | } |
862 | 871 | ||
863 | return TX_CONTINUE; | 872 | return TX_CONTINUE; |
864 | } | 873 | } |
865 | 874 | ||
866 | 875 | ||
867 | /* actual transmit path */ | 876 | /* actual transmit path */ |
868 | 877 | ||
869 | /* | 878 | /* |
870 | * deal with packet injection down monitor interface | 879 | * deal with packet injection down monitor interface |
871 | * with Radiotap Header -- only called for monitor mode interface | 880 | * with Radiotap Header -- only called for monitor mode interface |
872 | */ | 881 | */ |
873 | static ieee80211_tx_result | 882 | static ieee80211_tx_result |
874 | __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | 883 | __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, |
875 | struct sk_buff *skb) | 884 | struct sk_buff *skb) |
876 | { | 885 | { |
877 | /* | 886 | /* |
878 | * this is the moment to interpret and discard the radiotap header that | 887 | * this is the moment to interpret and discard the radiotap header that |
879 | * must be at the start of the packet injected in Monitor mode | 888 | * must be at the start of the packet injected in Monitor mode |
880 | * | 889 | * |
881 | * Need to take some care with endian-ness since radiotap | 890 | * Need to take some care with endian-ness since radiotap |
882 | * args are little-endian | 891 | * args are little-endian |
883 | */ | 892 | */ |
884 | 893 | ||
885 | struct ieee80211_radiotap_iterator iterator; | 894 | struct ieee80211_radiotap_iterator iterator; |
886 | struct ieee80211_radiotap_header *rthdr = | 895 | struct ieee80211_radiotap_header *rthdr = |
887 | (struct ieee80211_radiotap_header *) skb->data; | 896 | (struct ieee80211_radiotap_header *) skb->data; |
888 | struct ieee80211_supported_band *sband; | 897 | struct ieee80211_supported_band *sband; |
889 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | 898 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); |
890 | 899 | ||
891 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 900 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
892 | 901 | ||
893 | skb->do_not_encrypt = 1; | 902 | skb->do_not_encrypt = 1; |
894 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 903 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
895 | 904 | ||
896 | /* | 905 | /* |
897 | * for every radiotap entry that is present | 906 | * for every radiotap entry that is present |
898 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | 907 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more |
899 | * entries present, or -EINVAL on error) | 908 | * entries present, or -EINVAL on error) |
900 | */ | 909 | */ |
901 | 910 | ||
902 | while (!ret) { | 911 | while (!ret) { |
903 | ret = ieee80211_radiotap_iterator_next(&iterator); | 912 | ret = ieee80211_radiotap_iterator_next(&iterator); |
904 | 913 | ||
905 | if (ret) | 914 | if (ret) |
906 | continue; | 915 | continue; |
907 | 916 | ||
908 | /* see if this argument is something we can use */ | 917 | /* see if this argument is something we can use */ |
909 | switch (iterator.this_arg_index) { | 918 | switch (iterator.this_arg_index) { |
910 | /* | 919 | /* |
911 | * You must take care when dereferencing iterator.this_arg | 920 | * You must take care when dereferencing iterator.this_arg |
912 | * for multibyte types... the pointer is not aligned. Use | 921 | * for multibyte types... the pointer is not aligned. Use |
913 | * get_unaligned((type *)iterator.this_arg) to dereference | 922 | * get_unaligned((type *)iterator.this_arg) to dereference |
914 | * iterator.this_arg for type "type" safely on all arches. | 923 | * iterator.this_arg for type "type" safely on all arches. |
915 | */ | 924 | */ |
916 | case IEEE80211_RADIOTAP_FLAGS: | 925 | case IEEE80211_RADIOTAP_FLAGS: |
917 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | 926 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { |
918 | /* | 927 | /* |
919 | * this indicates that the skb we have been | 928 | * this indicates that the skb we have been |
920 | * handed has the 32-bit FCS CRC at the end... | 929 | * handed has the 32-bit FCS CRC at the end... |
921 | * we should react to that by snipping it off | 930 | * we should react to that by snipping it off |
922 | * because it will be recomputed and added | 931 | * because it will be recomputed and added |
923 | * on transmission | 932 | * on transmission |
924 | */ | 933 | */ |
925 | if (skb->len < (iterator.max_length + FCS_LEN)) | 934 | if (skb->len < (iterator.max_length + FCS_LEN)) |
926 | return TX_DROP; | 935 | return TX_DROP; |
927 | 936 | ||
928 | skb_trim(skb, skb->len - FCS_LEN); | 937 | skb_trim(skb, skb->len - FCS_LEN); |
929 | } | 938 | } |
930 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | 939 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) |
931 | tx->skb->do_not_encrypt = 0; | 940 | tx->skb->do_not_encrypt = 0; |
932 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | 941 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) |
933 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 942 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
934 | break; | 943 | break; |
935 | 944 | ||
936 | /* | 945 | /* |
937 | * Please update the file | 946 | * Please update the file |
938 | * Documentation/networking/mac80211-injection.txt | 947 | * Documentation/networking/mac80211-injection.txt |
939 | * when parsing new fields here. | 948 | * when parsing new fields here. |
940 | */ | 949 | */ |
941 | 950 | ||
942 | default: | 951 | default: |
943 | break; | 952 | break; |
944 | } | 953 | } |
945 | } | 954 | } |
946 | 955 | ||
947 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | 956 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ |
948 | return TX_DROP; | 957 | return TX_DROP; |
949 | 958 | ||
950 | /* | 959 | /* |
951 | * remove the radiotap header | 960 | * remove the radiotap header |
952 | * iterator->max_length was sanity-checked against | 961 | * iterator->max_length was sanity-checked against |
953 | * skb->len by iterator init | 962 | * skb->len by iterator init |
954 | */ | 963 | */ |
955 | skb_pull(skb, iterator.max_length); | 964 | skb_pull(skb, iterator.max_length); |
956 | 965 | ||
957 | return TX_CONTINUE; | 966 | return TX_CONTINUE; |
958 | } | 967 | } |
959 | 968 | ||
960 | /* | 969 | /* |
961 | * initialises @tx | 970 | * initialises @tx |
962 | */ | 971 | */ |
963 | static ieee80211_tx_result | 972 | static ieee80211_tx_result |
964 | __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 973 | __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, |
965 | struct sk_buff *skb, | 974 | struct sk_buff *skb, |
966 | struct net_device *dev) | 975 | struct net_device *dev) |
967 | { | 976 | { |
968 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 977 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
969 | struct ieee80211_hdr *hdr; | 978 | struct ieee80211_hdr *hdr; |
970 | struct ieee80211_sub_if_data *sdata; | 979 | struct ieee80211_sub_if_data *sdata; |
971 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 980 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
972 | 981 | ||
973 | int hdrlen, tid; | 982 | int hdrlen, tid; |
974 | u8 *qc, *state; | 983 | u8 *qc, *state; |
975 | 984 | ||
976 | memset(tx, 0, sizeof(*tx)); | 985 | memset(tx, 0, sizeof(*tx)); |
977 | tx->skb = skb; | 986 | tx->skb = skb; |
978 | tx->dev = dev; /* use original interface */ | 987 | tx->dev = dev; /* use original interface */ |
979 | tx->local = local; | 988 | tx->local = local; |
980 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 989 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
981 | tx->channel = local->hw.conf.channel; | 990 | tx->channel = local->hw.conf.channel; |
982 | /* | 991 | /* |
983 | * Set this flag (used below to indicate "automatic fragmentation"), | 992 | * Set this flag (used below to indicate "automatic fragmentation"), |
984 | * it will be cleared/left by radiotap as desired. | 993 | * it will be cleared/left by radiotap as desired. |
985 | */ | 994 | */ |
986 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 995 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
987 | 996 | ||
988 | /* process and remove the injection radiotap header */ | 997 | /* process and remove the injection radiotap header */ |
989 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 998 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
990 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { | 999 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
991 | if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) | 1000 | if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) |
992 | return TX_DROP; | 1001 | return TX_DROP; |
993 | 1002 | ||
994 | /* | 1003 | /* |
995 | * __ieee80211_parse_tx_radiotap has now removed | 1004 | * __ieee80211_parse_tx_radiotap has now removed |
996 | * the radiotap header that was present and pre-filled | 1005 | * the radiotap header that was present and pre-filled |
997 | * 'tx' with tx control information. | 1006 | * 'tx' with tx control information. |
998 | */ | 1007 | */ |
999 | } | 1008 | } |
1000 | 1009 | ||
1001 | hdr = (struct ieee80211_hdr *) skb->data; | 1010 | hdr = (struct ieee80211_hdr *) skb->data; |
1002 | 1011 | ||
1003 | tx->sta = sta_info_get(local, hdr->addr1); | 1012 | tx->sta = sta_info_get(local, hdr->addr1); |
1004 | 1013 | ||
1005 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) { | 1014 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) { |
1006 | qc = ieee80211_get_qos_ctl(hdr); | 1015 | qc = ieee80211_get_qos_ctl(hdr); |
1007 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 1016 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
1008 | 1017 | ||
1009 | state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; | 1018 | state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; |
1010 | if (*state == HT_AGG_STATE_OPERATIONAL) | 1019 | if (*state == HT_AGG_STATE_OPERATIONAL) |
1011 | info->flags |= IEEE80211_TX_CTL_AMPDU; | 1020 | info->flags |= IEEE80211_TX_CTL_AMPDU; |
1012 | } | 1021 | } |
1013 | 1022 | ||
1014 | if (is_multicast_ether_addr(hdr->addr1)) { | 1023 | if (is_multicast_ether_addr(hdr->addr1)) { |
1015 | tx->flags &= ~IEEE80211_TX_UNICAST; | 1024 | tx->flags &= ~IEEE80211_TX_UNICAST; |
1016 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 1025 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
1017 | } else { | 1026 | } else { |
1018 | tx->flags |= IEEE80211_TX_UNICAST; | 1027 | tx->flags |= IEEE80211_TX_UNICAST; |
1019 | info->flags &= ~IEEE80211_TX_CTL_NO_ACK; | 1028 | info->flags &= ~IEEE80211_TX_CTL_NO_ACK; |
1020 | } | 1029 | } |
1021 | 1030 | ||
1022 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { | 1031 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { |
1023 | if ((tx->flags & IEEE80211_TX_UNICAST) && | 1032 | if ((tx->flags & IEEE80211_TX_UNICAST) && |
1024 | skb->len + FCS_LEN > local->fragmentation_threshold && | 1033 | skb->len + FCS_LEN > local->fragmentation_threshold && |
1025 | !(info->flags & IEEE80211_TX_CTL_AMPDU)) | 1034 | !(info->flags & IEEE80211_TX_CTL_AMPDU)) |
1026 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1035 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
1027 | else | 1036 | else |
1028 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 1037 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
1029 | } | 1038 | } |
1030 | 1039 | ||
1031 | if (!tx->sta) | 1040 | if (!tx->sta) |
1032 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1041 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1033 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) | 1042 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) |
1034 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1043 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1035 | 1044 | ||
1036 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1045 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1037 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 1046 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
1038 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | 1047 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; |
1039 | tx->ethertype = (pos[0] << 8) | pos[1]; | 1048 | tx->ethertype = (pos[0] << 8) | pos[1]; |
1040 | } | 1049 | } |
1041 | info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; | 1050 | info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; |
1042 | 1051 | ||
1043 | return TX_CONTINUE; | 1052 | return TX_CONTINUE; |
1044 | } | 1053 | } |
1045 | 1054 | ||
1046 | /* | 1055 | /* |
1047 | * NB: @tx is uninitialised when passed in here | 1056 | * NB: @tx is uninitialised when passed in here |
1048 | */ | 1057 | */ |
1049 | static int ieee80211_tx_prepare(struct ieee80211_local *local, | 1058 | static int ieee80211_tx_prepare(struct ieee80211_local *local, |
1050 | struct ieee80211_tx_data *tx, | 1059 | struct ieee80211_tx_data *tx, |
1051 | struct sk_buff *skb) | 1060 | struct sk_buff *skb) |
1052 | { | 1061 | { |
1053 | struct net_device *dev; | 1062 | struct net_device *dev; |
1054 | 1063 | ||
1055 | dev = dev_get_by_index(&init_net, skb->iif); | 1064 | dev = dev_get_by_index(&init_net, skb->iif); |
1056 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { | 1065 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { |
1057 | dev_put(dev); | 1066 | dev_put(dev); |
1058 | dev = NULL; | 1067 | dev = NULL; |
1059 | } | 1068 | } |
1060 | if (unlikely(!dev)) | 1069 | if (unlikely(!dev)) |
1061 | return -ENODEV; | 1070 | return -ENODEV; |
1062 | /* initialises tx with control */ | 1071 | /* initialises tx with control */ |
1063 | __ieee80211_tx_prepare(tx, skb, dev); | 1072 | __ieee80211_tx_prepare(tx, skb, dev); |
1064 | dev_put(dev); | 1073 | dev_put(dev); |
1065 | return 0; | 1074 | return 0; |
1066 | } | 1075 | } |
1067 | 1076 | ||
1068 | static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | 1077 | static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, |
1069 | struct ieee80211_tx_data *tx) | 1078 | struct ieee80211_tx_data *tx) |
1070 | { | 1079 | { |
1071 | struct ieee80211_tx_info *info; | 1080 | struct ieee80211_tx_info *info; |
1072 | int ret, i; | 1081 | int ret, i; |
1073 | 1082 | ||
1074 | if (skb) { | 1083 | if (skb) { |
1075 | if (netif_subqueue_stopped(local->mdev, skb)) | 1084 | if (netif_subqueue_stopped(local->mdev, skb)) |
1076 | return IEEE80211_TX_AGAIN; | 1085 | return IEEE80211_TX_AGAIN; |
1077 | 1086 | ||
1078 | ret = local->ops->tx(local_to_hw(local), skb); | 1087 | ret = local->ops->tx(local_to_hw(local), skb); |
1079 | if (ret) | 1088 | if (ret) |
1080 | return IEEE80211_TX_AGAIN; | 1089 | return IEEE80211_TX_AGAIN; |
1081 | local->mdev->trans_start = jiffies; | 1090 | local->mdev->trans_start = jiffies; |
1082 | ieee80211_led_tx(local, 1); | 1091 | ieee80211_led_tx(local, 1); |
1083 | } | 1092 | } |
1084 | if (tx->extra_frag) { | 1093 | if (tx->extra_frag) { |
1085 | for (i = 0; i < tx->num_extra_frag; i++) { | 1094 | for (i = 0; i < tx->num_extra_frag; i++) { |
1086 | if (!tx->extra_frag[i]) | 1095 | if (!tx->extra_frag[i]) |
1087 | continue; | 1096 | continue; |
1088 | info = IEEE80211_SKB_CB(tx->extra_frag[i]); | 1097 | info = IEEE80211_SKB_CB(tx->extra_frag[i]); |
1089 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | | 1098 | info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | |
1090 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | 1099 | IEEE80211_TX_CTL_FIRST_FRAGMENT); |
1091 | if (netif_subqueue_stopped(local->mdev, | 1100 | if (netif_subqueue_stopped(local->mdev, |
1092 | tx->extra_frag[i])) | 1101 | tx->extra_frag[i])) |
1093 | return IEEE80211_TX_FRAG_AGAIN; | 1102 | return IEEE80211_TX_FRAG_AGAIN; |
1094 | 1103 | ||
1095 | ret = local->ops->tx(local_to_hw(local), | 1104 | ret = local->ops->tx(local_to_hw(local), |
1096 | tx->extra_frag[i]); | 1105 | tx->extra_frag[i]); |
1097 | if (ret) | 1106 | if (ret) |
1098 | return IEEE80211_TX_FRAG_AGAIN; | 1107 | return IEEE80211_TX_FRAG_AGAIN; |
1099 | local->mdev->trans_start = jiffies; | 1108 | local->mdev->trans_start = jiffies; |
1100 | ieee80211_led_tx(local, 1); | 1109 | ieee80211_led_tx(local, 1); |
1101 | tx->extra_frag[i] = NULL; | 1110 | tx->extra_frag[i] = NULL; |
1102 | } | 1111 | } |
1103 | kfree(tx->extra_frag); | 1112 | kfree(tx->extra_frag); |
1104 | tx->extra_frag = NULL; | 1113 | tx->extra_frag = NULL; |
1105 | } | 1114 | } |
1106 | return IEEE80211_TX_OK; | 1115 | return IEEE80211_TX_OK; |
1107 | } | 1116 | } |
1108 | 1117 | ||
1109 | /* | 1118 | /* |
1110 | * Invoke TX handlers, return 0 on success and non-zero if the | 1119 | * Invoke TX handlers, return 0 on success and non-zero if the |
1111 | * frame was dropped or queued. | 1120 | * frame was dropped or queued. |
1112 | */ | 1121 | */ |
1113 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | 1122 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) |
1114 | { | 1123 | { |
1115 | struct sk_buff *skb = tx->skb; | 1124 | struct sk_buff *skb = tx->skb; |
1116 | ieee80211_tx_result res = TX_DROP; | 1125 | ieee80211_tx_result res = TX_DROP; |
1117 | int i; | 1126 | int i; |
1118 | 1127 | ||
1119 | #define CALL_TXH(txh) \ | 1128 | #define CALL_TXH(txh) \ |
1120 | res = txh(tx); \ | 1129 | res = txh(tx); \ |
1121 | if (res != TX_CONTINUE) \ | 1130 | if (res != TX_CONTINUE) \ |
1122 | goto txh_done; | 1131 | goto txh_done; |
1123 | 1132 | ||
1124 | CALL_TXH(ieee80211_tx_h_check_assoc) | 1133 | CALL_TXH(ieee80211_tx_h_check_assoc) |
1125 | CALL_TXH(ieee80211_tx_h_ps_buf) | 1134 | CALL_TXH(ieee80211_tx_h_ps_buf) |
1126 | CALL_TXH(ieee80211_tx_h_select_key) | 1135 | CALL_TXH(ieee80211_tx_h_select_key) |
1127 | CALL_TXH(ieee80211_tx_h_michael_mic_add) | 1136 | CALL_TXH(ieee80211_tx_h_michael_mic_add) |
1128 | CALL_TXH(ieee80211_tx_h_rate_ctrl) | 1137 | CALL_TXH(ieee80211_tx_h_rate_ctrl) |
1129 | CALL_TXH(ieee80211_tx_h_misc) | 1138 | CALL_TXH(ieee80211_tx_h_misc) |
1130 | CALL_TXH(ieee80211_tx_h_sequence) | 1139 | CALL_TXH(ieee80211_tx_h_sequence) |
1131 | CALL_TXH(ieee80211_tx_h_fragment) | 1140 | CALL_TXH(ieee80211_tx_h_fragment) |
1132 | /* handlers after fragment must be aware of tx info fragmentation! */ | 1141 | /* handlers after fragment must be aware of tx info fragmentation! */ |
1133 | CALL_TXH(ieee80211_tx_h_encrypt) | 1142 | CALL_TXH(ieee80211_tx_h_encrypt) |
1134 | CALL_TXH(ieee80211_tx_h_calculate_duration) | 1143 | CALL_TXH(ieee80211_tx_h_calculate_duration) |
1135 | CALL_TXH(ieee80211_tx_h_stats) | 1144 | CALL_TXH(ieee80211_tx_h_stats) |
1136 | #undef CALL_TXH | 1145 | #undef CALL_TXH |
1137 | 1146 | ||
1138 | txh_done: | 1147 | txh_done: |
1139 | if (unlikely(res == TX_DROP)) { | 1148 | if (unlikely(res == TX_DROP)) { |
1140 | I802_DEBUG_INC(tx->local->tx_handlers_drop); | 1149 | I802_DEBUG_INC(tx->local->tx_handlers_drop); |
1141 | dev_kfree_skb(skb); | 1150 | dev_kfree_skb(skb); |
1142 | for (i = 0; i < tx->num_extra_frag; i++) | 1151 | for (i = 0; i < tx->num_extra_frag; i++) |
1143 | if (tx->extra_frag[i]) | 1152 | if (tx->extra_frag[i]) |
1144 | dev_kfree_skb(tx->extra_frag[i]); | 1153 | dev_kfree_skb(tx->extra_frag[i]); |
1145 | kfree(tx->extra_frag); | 1154 | kfree(tx->extra_frag); |
1146 | return -1; | 1155 | return -1; |
1147 | } else if (unlikely(res == TX_QUEUED)) { | 1156 | } else if (unlikely(res == TX_QUEUED)) { |
1148 | I802_DEBUG_INC(tx->local->tx_handlers_queued); | 1157 | I802_DEBUG_INC(tx->local->tx_handlers_queued); |
1149 | return -1; | 1158 | return -1; |
1150 | } | 1159 | } |
1151 | 1160 | ||
1152 | return 0; | 1161 | return 0; |
1153 | } | 1162 | } |
1154 | 1163 | ||
1155 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | 1164 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) |
1156 | { | 1165 | { |
1157 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1166 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1158 | struct sta_info *sta; | 1167 | struct sta_info *sta; |
1159 | struct ieee80211_tx_data tx; | 1168 | struct ieee80211_tx_data tx; |
1160 | ieee80211_tx_result res_prepare; | 1169 | ieee80211_tx_result res_prepare; |
1161 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1170 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1162 | int ret, i; | 1171 | int ret, i; |
1163 | u16 queue; | 1172 | u16 queue; |
1164 | 1173 | ||
1165 | queue = skb_get_queue_mapping(skb); | 1174 | queue = skb_get_queue_mapping(skb); |
1166 | 1175 | ||
1167 | WARN_ON(test_bit(queue, local->queues_pending)); | 1176 | WARN_ON(test_bit(queue, local->queues_pending)); |
1168 | 1177 | ||
1169 | if (unlikely(skb->len < 10)) { | 1178 | if (unlikely(skb->len < 10)) { |
1170 | dev_kfree_skb(skb); | 1179 | dev_kfree_skb(skb); |
1171 | return 0; | 1180 | return 0; |
1172 | } | 1181 | } |
1173 | 1182 | ||
1174 | rcu_read_lock(); | 1183 | rcu_read_lock(); |
1175 | 1184 | ||
1176 | /* initialises tx */ | 1185 | /* initialises tx */ |
1177 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev); | 1186 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev); |
1178 | 1187 | ||
1179 | if (res_prepare == TX_DROP) { | 1188 | if (res_prepare == TX_DROP) { |
1180 | dev_kfree_skb(skb); | 1189 | dev_kfree_skb(skb); |
1181 | rcu_read_unlock(); | 1190 | rcu_read_unlock(); |
1182 | return 0; | 1191 | return 0; |
1183 | } | 1192 | } |
1184 | 1193 | ||
1185 | sta = tx.sta; | 1194 | sta = tx.sta; |
1186 | tx.channel = local->hw.conf.channel; | 1195 | tx.channel = local->hw.conf.channel; |
1187 | info->band = tx.channel->band; | 1196 | info->band = tx.channel->band; |
1188 | 1197 | ||
1189 | if (invoke_tx_handlers(&tx)) | 1198 | if (invoke_tx_handlers(&tx)) |
1190 | goto out; | 1199 | goto out; |
1191 | 1200 | ||
1192 | retry: | 1201 | retry: |
1193 | ret = __ieee80211_tx(local, skb, &tx); | 1202 | ret = __ieee80211_tx(local, skb, &tx); |
1194 | if (ret) { | 1203 | if (ret) { |
1195 | struct ieee80211_tx_stored_packet *store; | 1204 | struct ieee80211_tx_stored_packet *store; |
1196 | 1205 | ||
1197 | /* | 1206 | /* |
1198 | * Since there are no fragmented frames on A-MPDU | 1207 | * Since there are no fragmented frames on A-MPDU |
1199 | * queues, there's no reason for a driver to reject | 1208 | * queues, there's no reason for a driver to reject |
1200 | * a frame there, warn and drop it. | 1209 | * a frame there, warn and drop it. |
1201 | */ | 1210 | */ |
1202 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) | 1211 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
1203 | goto drop; | 1212 | goto drop; |
1204 | 1213 | ||
1205 | store = &local->pending_packet[queue]; | 1214 | store = &local->pending_packet[queue]; |
1206 | 1215 | ||
1207 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1216 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1208 | skb = NULL; | 1217 | skb = NULL; |
1209 | 1218 | ||
1210 | set_bit(queue, local->queues_pending); | 1219 | set_bit(queue, local->queues_pending); |
1211 | smp_mb(); | 1220 | smp_mb(); |
1212 | /* | 1221 | /* |
1213 | * When the driver gets out of buffers during sending of | 1222 | * When the driver gets out of buffers during sending of |
1214 | * fragments and calls ieee80211_stop_queue, the netif | 1223 | * fragments and calls ieee80211_stop_queue, the netif |
1215 | * subqueue is stopped. There is, however, a small window | 1224 | * subqueue is stopped. There is, however, a small window |
1216 | * in which the PENDING bit is not yet set. If a buffer | 1225 | * in which the PENDING bit is not yet set. If a buffer |
1217 | * gets available in that window (i.e. driver calls | 1226 | * gets available in that window (i.e. driver calls |
1218 | * ieee80211_wake_queue), we would end up with ieee80211_tx | 1227 | * ieee80211_wake_queue), we would end up with ieee80211_tx |
1219 | * called with the PENDING bit still set. Prevent this by | 1228 | * called with the PENDING bit still set. Prevent this by |
1220 | * continuing transmitting here when that situation is | 1229 | * continuing transmitting here when that situation is |
1221 | * possible to have happened. | 1230 | * possible to have happened. |
1222 | */ | 1231 | */ |
1223 | if (!__netif_subqueue_stopped(local->mdev, queue)) { | 1232 | if (!__netif_subqueue_stopped(local->mdev, queue)) { |
1224 | clear_bit(queue, local->queues_pending); | 1233 | clear_bit(queue, local->queues_pending); |
1225 | goto retry; | 1234 | goto retry; |
1226 | } | 1235 | } |
1227 | store->skb = skb; | 1236 | store->skb = skb; |
1228 | store->extra_frag = tx.extra_frag; | 1237 | store->extra_frag = tx.extra_frag; |
1229 | store->num_extra_frag = tx.num_extra_frag; | 1238 | store->num_extra_frag = tx.num_extra_frag; |
1230 | } | 1239 | } |
1231 | out: | 1240 | out: |
1232 | rcu_read_unlock(); | 1241 | rcu_read_unlock(); |
1233 | return 0; | 1242 | return 0; |
1234 | 1243 | ||
1235 | drop: | 1244 | drop: |
1236 | if (skb) | 1245 | if (skb) |
1237 | dev_kfree_skb(skb); | 1246 | dev_kfree_skb(skb); |
1238 | for (i = 0; i < tx.num_extra_frag; i++) | 1247 | for (i = 0; i < tx.num_extra_frag; i++) |
1239 | if (tx.extra_frag[i]) | 1248 | if (tx.extra_frag[i]) |
1240 | dev_kfree_skb(tx.extra_frag[i]); | 1249 | dev_kfree_skb(tx.extra_frag[i]); |
1241 | kfree(tx.extra_frag); | 1250 | kfree(tx.extra_frag); |
1242 | rcu_read_unlock(); | 1251 | rcu_read_unlock(); |
1243 | return 0; | 1252 | return 0; |
1244 | } | 1253 | } |
1245 | 1254 | ||
1246 | /* device xmit handlers */ | 1255 | /* device xmit handlers */ |
1247 | 1256 | ||
1248 | static int ieee80211_skb_resize(struct ieee80211_local *local, | 1257 | static int ieee80211_skb_resize(struct ieee80211_local *local, |
1249 | struct sk_buff *skb, | 1258 | struct sk_buff *skb, |
1250 | int head_need, bool may_encrypt) | 1259 | int head_need, bool may_encrypt) |
1251 | { | 1260 | { |
1252 | int tail_need = 0; | 1261 | int tail_need = 0; |
1253 | 1262 | ||
1254 | /* | 1263 | /* |
1255 | * This could be optimised, devices that do full hardware | 1264 | * This could be optimised, devices that do full hardware |
1256 | * crypto (including TKIP MMIC) need no tailroom... But we | 1265 | * crypto (including TKIP MMIC) need no tailroom... But we |
1257 | * have no drivers for such devices currently. | 1266 | * have no drivers for such devices currently. |
1258 | */ | 1267 | */ |
1259 | if (may_encrypt) { | 1268 | if (may_encrypt) { |
1260 | tail_need = IEEE80211_ENCRYPT_TAILROOM; | 1269 | tail_need = IEEE80211_ENCRYPT_TAILROOM; |
1261 | tail_need -= skb_tailroom(skb); | 1270 | tail_need -= skb_tailroom(skb); |
1262 | tail_need = max_t(int, tail_need, 0); | 1271 | tail_need = max_t(int, tail_need, 0); |
1263 | } | 1272 | } |
1264 | 1273 | ||
1265 | if (head_need || tail_need) { | 1274 | if (head_need || tail_need) { |
1266 | /* Sorry. Can't account for this any more */ | 1275 | /* Sorry. Can't account for this any more */ |
1267 | skb_orphan(skb); | 1276 | skb_orphan(skb); |
1268 | } | 1277 | } |
1269 | 1278 | ||
1270 | if (skb_header_cloned(skb)) | 1279 | if (skb_header_cloned(skb)) |
1271 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1280 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
1272 | else | 1281 | else |
1273 | I802_DEBUG_INC(local->tx_expand_skb_head); | 1282 | I802_DEBUG_INC(local->tx_expand_skb_head); |
1274 | 1283 | ||
1275 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { | 1284 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { |
1276 | printk(KERN_DEBUG "%s: failed to reallocate TX buffer\n", | 1285 | printk(KERN_DEBUG "%s: failed to reallocate TX buffer\n", |
1277 | wiphy_name(local->hw.wiphy)); | 1286 | wiphy_name(local->hw.wiphy)); |
1278 | return -ENOMEM; | 1287 | return -ENOMEM; |
1279 | } | 1288 | } |
1280 | 1289 | ||
1281 | /* update truesize too */ | 1290 | /* update truesize too */ |
1282 | skb->truesize += head_need + tail_need; | 1291 | skb->truesize += head_need + tail_need; |
1283 | 1292 | ||
1284 | return 0; | 1293 | return 0; |
1285 | } | 1294 | } |
1286 | 1295 | ||
1287 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1296 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) |
1288 | { | 1297 | { |
1289 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | 1298 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
1290 | struct ieee80211_local *local = mpriv->local; | 1299 | struct ieee80211_local *local = mpriv->local; |
1291 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1300 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1292 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1301 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1293 | struct net_device *odev = NULL; | 1302 | struct net_device *odev = NULL; |
1294 | struct ieee80211_sub_if_data *osdata; | 1303 | struct ieee80211_sub_if_data *osdata; |
1295 | int headroom; | 1304 | int headroom; |
1296 | bool may_encrypt; | 1305 | bool may_encrypt; |
1297 | enum { | 1306 | enum { |
1298 | NOT_MONITOR, | 1307 | NOT_MONITOR, |
1299 | FOUND_SDATA, | 1308 | FOUND_SDATA, |
1300 | UNKNOWN_ADDRESS, | 1309 | UNKNOWN_ADDRESS, |
1301 | } monitor_iface = NOT_MONITOR; | 1310 | } monitor_iface = NOT_MONITOR; |
1302 | int ret; | 1311 | int ret; |
1303 | 1312 | ||
1304 | if (skb->iif) | 1313 | if (skb->iif) |
1305 | odev = dev_get_by_index(&init_net, skb->iif); | 1314 | odev = dev_get_by_index(&init_net, skb->iif); |
1306 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { | 1315 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { |
1307 | dev_put(odev); | 1316 | dev_put(odev); |
1308 | odev = NULL; | 1317 | odev = NULL; |
1309 | } | 1318 | } |
1310 | if (unlikely(!odev)) { | 1319 | if (unlikely(!odev)) { |
1311 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1320 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1312 | printk(KERN_DEBUG "%s: Discarded packet with nonexistent " | 1321 | printk(KERN_DEBUG "%s: Discarded packet with nonexistent " |
1313 | "originating device\n", dev->name); | 1322 | "originating device\n", dev->name); |
1314 | #endif | 1323 | #endif |
1315 | dev_kfree_skb(skb); | 1324 | dev_kfree_skb(skb); |
1316 | return 0; | 1325 | return 0; |
1317 | } | 1326 | } |
1318 | 1327 | ||
1319 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 1328 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
1320 | local->hw.conf.dynamic_ps_timeout > 0) { | 1329 | local->hw.conf.dynamic_ps_timeout > 0) { |
1321 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 1330 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
1322 | ieee80211_stop_queues_by_reason(&local->hw, | 1331 | ieee80211_stop_queues_by_reason(&local->hw, |
1323 | IEEE80211_QUEUE_STOP_REASON_PS); | 1332 | IEEE80211_QUEUE_STOP_REASON_PS); |
1324 | queue_work(local->hw.workqueue, | 1333 | queue_work(local->hw.workqueue, |
1325 | &local->dynamic_ps_disable_work); | 1334 | &local->dynamic_ps_disable_work); |
1326 | } | 1335 | } |
1327 | 1336 | ||
1328 | mod_timer(&local->dynamic_ps_timer, jiffies + | 1337 | mod_timer(&local->dynamic_ps_timer, jiffies + |
1329 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1338 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1330 | } | 1339 | } |
1331 | 1340 | ||
1332 | memset(info, 0, sizeof(*info)); | 1341 | memset(info, 0, sizeof(*info)); |
1333 | 1342 | ||
1334 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1343 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
1335 | 1344 | ||
1336 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1345 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); |
1337 | 1346 | ||
1338 | if (ieee80211_vif_is_mesh(&osdata->vif) && | 1347 | if (ieee80211_vif_is_mesh(&osdata->vif) && |
1339 | ieee80211_is_data(hdr->frame_control)) { | 1348 | ieee80211_is_data(hdr->frame_control)) { |
1340 | if (is_multicast_ether_addr(hdr->addr3)) | 1349 | if (is_multicast_ether_addr(hdr->addr3)) |
1341 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | 1350 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); |
1342 | else | 1351 | else |
1343 | if (mesh_nexthop_lookup(skb, osdata)) { | 1352 | if (mesh_nexthop_lookup(skb, osdata)) { |
1344 | dev_put(odev); | 1353 | dev_put(odev); |
1345 | return 0; | 1354 | return 0; |
1346 | } | 1355 | } |
1347 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | 1356 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) |
1348 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, | 1357 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, |
1349 | fwded_frames); | 1358 | fwded_frames); |
1350 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { | 1359 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
1351 | struct ieee80211_sub_if_data *sdata; | 1360 | struct ieee80211_sub_if_data *sdata; |
1352 | int hdrlen; | 1361 | int hdrlen; |
1353 | u16 len_rthdr; | 1362 | u16 len_rthdr; |
1354 | 1363 | ||
1355 | info->flags |= IEEE80211_TX_CTL_INJECTED; | 1364 | info->flags |= IEEE80211_TX_CTL_INJECTED; |
1356 | monitor_iface = UNKNOWN_ADDRESS; | 1365 | monitor_iface = UNKNOWN_ADDRESS; |
1357 | 1366 | ||
1358 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | 1367 | len_rthdr = ieee80211_get_radiotap_len(skb->data); |
1359 | hdr = (struct ieee80211_hdr *)skb->data + len_rthdr; | 1368 | hdr = (struct ieee80211_hdr *)skb->data + len_rthdr; |
1360 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1369 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1361 | 1370 | ||
1362 | /* check the header is complete in the frame */ | 1371 | /* check the header is complete in the frame */ |
1363 | if (likely(skb->len >= len_rthdr + hdrlen)) { | 1372 | if (likely(skb->len >= len_rthdr + hdrlen)) { |
1364 | /* | 1373 | /* |
1365 | * We process outgoing injected frames that have a | 1374 | * We process outgoing injected frames that have a |
1366 | * local address we handle as though they are our | 1375 | * local address we handle as though they are our |
1367 | * own frames. | 1376 | * own frames. |
1368 | * This code here isn't entirely correct, the local | 1377 | * This code here isn't entirely correct, the local |
1369 | * MAC address is not necessarily enough to find | 1378 | * MAC address is not necessarily enough to find |
1370 | * the interface to use; for that proper VLAN/WDS | 1379 | * the interface to use; for that proper VLAN/WDS |
1371 | * support we will need a different mechanism. | 1380 | * support we will need a different mechanism. |
1372 | */ | 1381 | */ |
1373 | 1382 | ||
1374 | rcu_read_lock(); | 1383 | rcu_read_lock(); |
1375 | list_for_each_entry_rcu(sdata, &local->interfaces, | 1384 | list_for_each_entry_rcu(sdata, &local->interfaces, |
1376 | list) { | 1385 | list) { |
1377 | if (!netif_running(sdata->dev)) | 1386 | if (!netif_running(sdata->dev)) |
1378 | continue; | 1387 | continue; |
1379 | if (compare_ether_addr(sdata->dev->dev_addr, | 1388 | if (compare_ether_addr(sdata->dev->dev_addr, |
1380 | hdr->addr2)) { | 1389 | hdr->addr2)) { |
1381 | dev_hold(sdata->dev); | 1390 | dev_hold(sdata->dev); |
1382 | dev_put(odev); | 1391 | dev_put(odev); |
1383 | osdata = sdata; | 1392 | osdata = sdata; |
1384 | odev = osdata->dev; | 1393 | odev = osdata->dev; |
1385 | skb->iif = sdata->dev->ifindex; | 1394 | skb->iif = sdata->dev->ifindex; |
1386 | monitor_iface = FOUND_SDATA; | 1395 | monitor_iface = FOUND_SDATA; |
1387 | break; | 1396 | break; |
1388 | } | 1397 | } |
1389 | } | 1398 | } |
1390 | rcu_read_unlock(); | 1399 | rcu_read_unlock(); |
1391 | } | 1400 | } |
1392 | } | 1401 | } |
1393 | 1402 | ||
1394 | may_encrypt = !skb->do_not_encrypt; | 1403 | may_encrypt = !skb->do_not_encrypt; |
1395 | 1404 | ||
1396 | headroom = osdata->local->tx_headroom; | 1405 | headroom = osdata->local->tx_headroom; |
1397 | if (may_encrypt) | 1406 | if (may_encrypt) |
1398 | headroom += IEEE80211_ENCRYPT_HEADROOM; | 1407 | headroom += IEEE80211_ENCRYPT_HEADROOM; |
1399 | headroom -= skb_headroom(skb); | 1408 | headroom -= skb_headroom(skb); |
1400 | headroom = max_t(int, 0, headroom); | 1409 | headroom = max_t(int, 0, headroom); |
1401 | 1410 | ||
1402 | if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) { | 1411 | if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) { |
1403 | dev_kfree_skb(skb); | 1412 | dev_kfree_skb(skb); |
1404 | dev_put(odev); | 1413 | dev_put(odev); |
1405 | return 0; | 1414 | return 0; |
1406 | } | 1415 | } |
1407 | 1416 | ||
1408 | if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1417 | if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1409 | osdata = container_of(osdata->bss, | 1418 | osdata = container_of(osdata->bss, |
1410 | struct ieee80211_sub_if_data, | 1419 | struct ieee80211_sub_if_data, |
1411 | u.ap); | 1420 | u.ap); |
1412 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) | 1421 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) |
1413 | info->control.vif = &osdata->vif; | 1422 | info->control.vif = &osdata->vif; |
1414 | ret = ieee80211_tx(odev, skb); | 1423 | ret = ieee80211_tx(odev, skb); |
1415 | dev_put(odev); | 1424 | dev_put(odev); |
1416 | 1425 | ||
1417 | return ret; | 1426 | return ret; |
1418 | } | 1427 | } |
1419 | 1428 | ||
1420 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, | 1429 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, |
1421 | struct net_device *dev) | 1430 | struct net_device *dev) |
1422 | { | 1431 | { |
1423 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1432 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1424 | struct ieee80211_radiotap_header *prthdr = | 1433 | struct ieee80211_radiotap_header *prthdr = |
1425 | (struct ieee80211_radiotap_header *)skb->data; | 1434 | (struct ieee80211_radiotap_header *)skb->data; |
1426 | u16 len_rthdr; | 1435 | u16 len_rthdr; |
1427 | 1436 | ||
1428 | /* check for not even having the fixed radiotap header part */ | 1437 | /* check for not even having the fixed radiotap header part */ |
1429 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) | 1438 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) |
1430 | goto fail; /* too short to be possibly valid */ | 1439 | goto fail; /* too short to be possibly valid */ |
1431 | 1440 | ||
1432 | /* is it a header version we can trust to find length from? */ | 1441 | /* is it a header version we can trust to find length from? */ |
1433 | if (unlikely(prthdr->it_version)) | 1442 | if (unlikely(prthdr->it_version)) |
1434 | goto fail; /* only version 0 is supported */ | 1443 | goto fail; /* only version 0 is supported */ |
1435 | 1444 | ||
1436 | /* then there must be a radiotap header with a length we can use */ | 1445 | /* then there must be a radiotap header with a length we can use */ |
1437 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | 1446 | len_rthdr = ieee80211_get_radiotap_len(skb->data); |
1438 | 1447 | ||
1439 | /* does the skb contain enough to deliver on the alleged length? */ | 1448 | /* does the skb contain enough to deliver on the alleged length? */ |
1440 | if (unlikely(skb->len < len_rthdr)) | 1449 | if (unlikely(skb->len < len_rthdr)) |
1441 | goto fail; /* skb too short for claimed rt header extent */ | 1450 | goto fail; /* skb too short for claimed rt header extent */ |
1442 | 1451 | ||
1443 | skb->dev = local->mdev; | 1452 | skb->dev = local->mdev; |
1444 | 1453 | ||
1445 | /* needed because we set skb device to master */ | 1454 | /* needed because we set skb device to master */ |
1446 | skb->iif = dev->ifindex; | 1455 | skb->iif = dev->ifindex; |
1447 | 1456 | ||
1448 | /* sometimes we do encrypt injected frames, will be fixed | 1457 | /* sometimes we do encrypt injected frames, will be fixed |
1449 | * up in radiotap parser if not wanted */ | 1458 | * up in radiotap parser if not wanted */ |
1450 | skb->do_not_encrypt = 0; | 1459 | skb->do_not_encrypt = 0; |
1451 | 1460 | ||
1452 | /* | 1461 | /* |
1453 | * fix up the pointers accounting for the radiotap | 1462 | * fix up the pointers accounting for the radiotap |
1454 | * header still being in there. We are being given | 1463 | * header still being in there. We are being given |
1455 | * a precooked IEEE80211 header so no need for | 1464 | * a precooked IEEE80211 header so no need for |
1456 | * normal processing | 1465 | * normal processing |
1457 | */ | 1466 | */ |
1458 | skb_set_mac_header(skb, len_rthdr); | 1467 | skb_set_mac_header(skb, len_rthdr); |
1459 | /* | 1468 | /* |
1460 | * these are just fixed to the end of the rt area since we | 1469 | * these are just fixed to the end of the rt area since we |
1461 | * don't have any better information and at this point, nobody cares | 1470 | * don't have any better information and at this point, nobody cares |
1462 | */ | 1471 | */ |
1463 | skb_set_network_header(skb, len_rthdr); | 1472 | skb_set_network_header(skb, len_rthdr); |
1464 | skb_set_transport_header(skb, len_rthdr); | 1473 | skb_set_transport_header(skb, len_rthdr); |
1465 | 1474 | ||
1466 | /* pass the radiotap header up to the next stage intact */ | 1475 | /* pass the radiotap header up to the next stage intact */ |
1467 | dev_queue_xmit(skb); | 1476 | dev_queue_xmit(skb); |
1468 | return NETDEV_TX_OK; | 1477 | return NETDEV_TX_OK; |
1469 | 1478 | ||
1470 | fail: | 1479 | fail: |
1471 | dev_kfree_skb(skb); | 1480 | dev_kfree_skb(skb); |
1472 | return NETDEV_TX_OK; /* meaning, we dealt with the skb */ | 1481 | return NETDEV_TX_OK; /* meaning, we dealt with the skb */ |
1473 | } | 1482 | } |
1474 | 1483 | ||
1475 | /** | 1484 | /** |
1476 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type | 1485 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type |
1477 | * subinterfaces (wlan#, WDS, and VLAN interfaces) | 1486 | * subinterfaces (wlan#, WDS, and VLAN interfaces) |
1478 | * @skb: packet to be sent | 1487 | * @skb: packet to be sent |
1479 | * @dev: incoming interface | 1488 | * @dev: incoming interface |
1480 | * | 1489 | * |
1481 | * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will | 1490 | * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will |
1482 | * not be freed, and caller is responsible for either retrying later or freeing | 1491 | * not be freed, and caller is responsible for either retrying later or freeing |
1483 | * skb). | 1492 | * skb). |
1484 | * | 1493 | * |
1485 | * This function takes in an Ethernet header and encapsulates it with suitable | 1494 | * This function takes in an Ethernet header and encapsulates it with suitable |
1486 | * IEEE 802.11 header based on which interface the packet is coming in. The | 1495 | * IEEE 802.11 header based on which interface the packet is coming in. The |
1487 | * encapsulated packet will then be passed to master interface, wlan#.11, for | 1496 | * encapsulated packet will then be passed to master interface, wlan#.11, for |
1488 | * transmission (through low-level driver). | 1497 | * transmission (through low-level driver). |
1489 | */ | 1498 | */ |
1490 | int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1499 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1491 | struct net_device *dev) | 1500 | struct net_device *dev) |
1492 | { | 1501 | { |
1493 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1502 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1494 | struct ieee80211_local *local = sdata->local; | 1503 | struct ieee80211_local *local = sdata->local; |
1495 | int ret = 1, head_need; | 1504 | int ret = 1, head_need; |
1496 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1505 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1497 | __le16 fc; | 1506 | __le16 fc; |
1498 | struct ieee80211_hdr hdr; | 1507 | struct ieee80211_hdr hdr; |
1499 | struct ieee80211s_hdr mesh_hdr; | 1508 | struct ieee80211s_hdr mesh_hdr; |
1500 | const u8 *encaps_data; | 1509 | const u8 *encaps_data; |
1501 | int encaps_len, skip_header_bytes; | 1510 | int encaps_len, skip_header_bytes; |
1502 | int nh_pos, h_pos; | 1511 | int nh_pos, h_pos; |
1503 | struct sta_info *sta; | 1512 | struct sta_info *sta; |
1504 | u32 sta_flags = 0; | 1513 | u32 sta_flags = 0; |
1505 | 1514 | ||
1506 | if (unlikely(skb->len < ETH_HLEN)) { | 1515 | if (unlikely(skb->len < ETH_HLEN)) { |
1507 | ret = 0; | 1516 | ret = 0; |
1508 | goto fail; | 1517 | goto fail; |
1509 | } | 1518 | } |
1510 | 1519 | ||
1511 | nh_pos = skb_network_header(skb) - skb->data; | 1520 | nh_pos = skb_network_header(skb) - skb->data; |
1512 | h_pos = skb_transport_header(skb) - skb->data; | 1521 | h_pos = skb_transport_header(skb) - skb->data; |
1513 | 1522 | ||
1514 | /* convert Ethernet header to proper 802.11 header (based on | 1523 | /* convert Ethernet header to proper 802.11 header (based on |
1515 | * operation mode) */ | 1524 | * operation mode) */ |
1516 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1525 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
1517 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | 1526 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); |
1518 | 1527 | ||
1519 | switch (sdata->vif.type) { | 1528 | switch (sdata->vif.type) { |
1520 | case NL80211_IFTYPE_AP: | 1529 | case NL80211_IFTYPE_AP: |
1521 | case NL80211_IFTYPE_AP_VLAN: | 1530 | case NL80211_IFTYPE_AP_VLAN: |
1522 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 1531 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1523 | /* DA BSSID SA */ | 1532 | /* DA BSSID SA */ |
1524 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1533 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1525 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1534 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
1526 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | 1535 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); |
1527 | hdrlen = 24; | 1536 | hdrlen = 24; |
1528 | break; | 1537 | break; |
1529 | case NL80211_IFTYPE_WDS: | 1538 | case NL80211_IFTYPE_WDS: |
1530 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1539 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1531 | /* RA TA DA SA */ | 1540 | /* RA TA DA SA */ |
1532 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); | 1541 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); |
1533 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1542 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
1534 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1543 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1535 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1544 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1536 | hdrlen = 30; | 1545 | hdrlen = 30; |
1537 | break; | 1546 | break; |
1538 | #ifdef CONFIG_MAC80211_MESH | 1547 | #ifdef CONFIG_MAC80211_MESH |
1539 | case NL80211_IFTYPE_MESH_POINT: | 1548 | case NL80211_IFTYPE_MESH_POINT: |
1540 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1549 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1541 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1550 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1542 | /* Do not send frames with mesh_ttl == 0 */ | 1551 | /* Do not send frames with mesh_ttl == 0 */ |
1543 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1552 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1544 | ret = 0; | 1553 | ret = 0; |
1545 | goto fail; | 1554 | goto fail; |
1546 | } | 1555 | } |
1547 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); | 1556 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); |
1548 | 1557 | ||
1549 | if (compare_ether_addr(dev->dev_addr, | 1558 | if (compare_ether_addr(dev->dev_addr, |
1550 | skb->data + ETH_ALEN) == 0) { | 1559 | skb->data + ETH_ALEN) == 0) { |
1551 | /* RA TA DA SA */ | 1560 | /* RA TA DA SA */ |
1552 | memset(hdr.addr1, 0, ETH_ALEN); | 1561 | memset(hdr.addr1, 0, ETH_ALEN); |
1553 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1562 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
1554 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1563 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1555 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1564 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1556 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | 1565 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); |
1557 | } else { | 1566 | } else { |
1558 | /* packet from other interface */ | 1567 | /* packet from other interface */ |
1559 | struct mesh_path *mppath; | 1568 | struct mesh_path *mppath; |
1560 | 1569 | ||
1561 | memset(hdr.addr1, 0, ETH_ALEN); | 1570 | memset(hdr.addr1, 0, ETH_ALEN); |
1562 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1571 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
1563 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | 1572 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); |
1564 | 1573 | ||
1565 | if (is_multicast_ether_addr(skb->data)) | 1574 | if (is_multicast_ether_addr(skb->data)) |
1566 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1575 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1567 | else { | 1576 | else { |
1568 | rcu_read_lock(); | 1577 | rcu_read_lock(); |
1569 | mppath = mpp_path_lookup(skb->data, sdata); | 1578 | mppath = mpp_path_lookup(skb->data, sdata); |
1570 | if (mppath) | 1579 | if (mppath) |
1571 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | 1580 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); |
1572 | else | 1581 | else |
1573 | memset(hdr.addr3, 0xff, ETH_ALEN); | 1582 | memset(hdr.addr3, 0xff, ETH_ALEN); |
1574 | rcu_read_unlock(); | 1583 | rcu_read_unlock(); |
1575 | } | 1584 | } |
1576 | 1585 | ||
1577 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | 1586 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; |
1578 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 1587 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
1579 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | 1588 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); |
1580 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | 1589 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); |
1581 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | 1590 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); |
1582 | sdata->u.mesh.mesh_seqnum++; | 1591 | sdata->u.mesh.mesh_seqnum++; |
1583 | meshhdrlen = 18; | 1592 | meshhdrlen = 18; |
1584 | } | 1593 | } |
1585 | hdrlen = 30; | 1594 | hdrlen = 30; |
1586 | break; | 1595 | break; |
1587 | #endif | 1596 | #endif |
1588 | case NL80211_IFTYPE_STATION: | 1597 | case NL80211_IFTYPE_STATION: |
1589 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | 1598 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
1590 | /* BSSID SA DA */ | 1599 | /* BSSID SA DA */ |
1591 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); | 1600 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); |
1592 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1601 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
1593 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1602 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1594 | hdrlen = 24; | 1603 | hdrlen = 24; |
1595 | break; | 1604 | break; |
1596 | case NL80211_IFTYPE_ADHOC: | 1605 | case NL80211_IFTYPE_ADHOC: |
1597 | /* DA SA BSSID */ | 1606 | /* DA SA BSSID */ |
1598 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1607 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1599 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1608 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
1600 | memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN); | 1609 | memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN); |
1601 | hdrlen = 24; | 1610 | hdrlen = 24; |
1602 | break; | 1611 | break; |
1603 | default: | 1612 | default: |
1604 | ret = 0; | 1613 | ret = 0; |
1605 | goto fail; | 1614 | goto fail; |
1606 | } | 1615 | } |
1607 | 1616 | ||
1608 | /* | 1617 | /* |
1609 | * There's no need to try to look up the destination | 1618 | * There's no need to try to look up the destination |
1610 | * if it is a multicast address (which can only happen | 1619 | * if it is a multicast address (which can only happen |
1611 | * in AP mode) | 1620 | * in AP mode) |
1612 | */ | 1621 | */ |
1613 | if (!is_multicast_ether_addr(hdr.addr1)) { | 1622 | if (!is_multicast_ether_addr(hdr.addr1)) { |
1614 | rcu_read_lock(); | 1623 | rcu_read_lock(); |
1615 | sta = sta_info_get(local, hdr.addr1); | 1624 | sta = sta_info_get(local, hdr.addr1); |
1616 | if (sta) | 1625 | if (sta) |
1617 | sta_flags = get_sta_flags(sta); | 1626 | sta_flags = get_sta_flags(sta); |
1618 | rcu_read_unlock(); | 1627 | rcu_read_unlock(); |
1619 | } | 1628 | } |
1620 | 1629 | ||
1621 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1630 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1622 | if (sta_flags & WLAN_STA_WME && | 1631 | if (sta_flags & WLAN_STA_WME && |
1623 | ieee80211_num_regular_queues(&local->hw) >= 4) { | 1632 | ieee80211_num_regular_queues(&local->hw) >= 4) { |
1624 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | 1633 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1625 | hdrlen += 2; | 1634 | hdrlen += 2; |
1626 | } | 1635 | } |
1627 | 1636 | ||
1628 | /* | 1637 | /* |
1629 | * Drop unicast frames to unauthorised stations unless they are | 1638 | * Drop unicast frames to unauthorised stations unless they are |
1630 | * EAPOL frames from the local station. | 1639 | * EAPOL frames from the local station. |
1631 | */ | 1640 | */ |
1632 | if (!ieee80211_vif_is_mesh(&sdata->vif) && | 1641 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
1633 | unlikely(!is_multicast_ether_addr(hdr.addr1) && | 1642 | unlikely(!is_multicast_ether_addr(hdr.addr1) && |
1634 | !(sta_flags & WLAN_STA_AUTHORIZED) && | 1643 | !(sta_flags & WLAN_STA_AUTHORIZED) && |
1635 | !(ethertype == ETH_P_PAE && | 1644 | !(ethertype == ETH_P_PAE && |
1636 | compare_ether_addr(dev->dev_addr, | 1645 | compare_ether_addr(dev->dev_addr, |
1637 | skb->data + ETH_ALEN) == 0))) { | 1646 | skb->data + ETH_ALEN) == 0))) { |
1638 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1647 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1639 | if (net_ratelimit()) | 1648 | if (net_ratelimit()) |
1640 | printk(KERN_DEBUG "%s: dropped frame to %pM" | 1649 | printk(KERN_DEBUG "%s: dropped frame to %pM" |
1641 | " (unauthorized port)\n", dev->name, | 1650 | " (unauthorized port)\n", dev->name, |
1642 | hdr.addr1); | 1651 | hdr.addr1); |
1643 | #endif | 1652 | #endif |
1644 | 1653 | ||
1645 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); | 1654 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); |
1646 | 1655 | ||
1647 | ret = 0; | 1656 | ret = 0; |
1648 | goto fail; | 1657 | goto fail; |
1649 | } | 1658 | } |
1650 | 1659 | ||
1651 | hdr.frame_control = fc; | 1660 | hdr.frame_control = fc; |
1652 | hdr.duration_id = 0; | 1661 | hdr.duration_id = 0; |
1653 | hdr.seq_ctrl = 0; | 1662 | hdr.seq_ctrl = 0; |
1654 | 1663 | ||
1655 | skip_header_bytes = ETH_HLEN; | 1664 | skip_header_bytes = ETH_HLEN; |
1656 | if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { | 1665 | if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { |
1657 | encaps_data = bridge_tunnel_header; | 1666 | encaps_data = bridge_tunnel_header; |
1658 | encaps_len = sizeof(bridge_tunnel_header); | 1667 | encaps_len = sizeof(bridge_tunnel_header); |
1659 | skip_header_bytes -= 2; | 1668 | skip_header_bytes -= 2; |
1660 | } else if (ethertype >= 0x600) { | 1669 | } else if (ethertype >= 0x600) { |
1661 | encaps_data = rfc1042_header; | 1670 | encaps_data = rfc1042_header; |
1662 | encaps_len = sizeof(rfc1042_header); | 1671 | encaps_len = sizeof(rfc1042_header); |
1663 | skip_header_bytes -= 2; | 1672 | skip_header_bytes -= 2; |
1664 | } else { | 1673 | } else { |
1665 | encaps_data = NULL; | 1674 | encaps_data = NULL; |
1666 | encaps_len = 0; | 1675 | encaps_len = 0; |
1667 | } | 1676 | } |
1668 | 1677 | ||
1669 | skb_pull(skb, skip_header_bytes); | 1678 | skb_pull(skb, skip_header_bytes); |
1670 | nh_pos -= skip_header_bytes; | 1679 | nh_pos -= skip_header_bytes; |
1671 | h_pos -= skip_header_bytes; | 1680 | h_pos -= skip_header_bytes; |
1672 | 1681 | ||
1673 | head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); | 1682 | head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); |
1674 | 1683 | ||
1675 | /* | 1684 | /* |
1676 | * So we need to modify the skb header and hence need a copy of | 1685 | * So we need to modify the skb header and hence need a copy of |
1677 | * that. The head_need variable above doesn't, so far, include | 1686 | * that. The head_need variable above doesn't, so far, include |
1678 | * the needed header space that we don't need right away. If we | 1687 | * the needed header space that we don't need right away. If we |
1679 | * can, then we don't reallocate right now but only after the | 1688 | * can, then we don't reallocate right now but only after the |
1680 | * frame arrives at the master device (if it does...) | 1689 | * frame arrives at the master device (if it does...) |
1681 | * | 1690 | * |
1682 | * If we cannot, however, then we will reallocate to include all | 1691 | * If we cannot, however, then we will reallocate to include all |
1683 | * the ever needed space. Also, if we need to reallocate it anyway, | 1692 | * the ever needed space. Also, if we need to reallocate it anyway, |
1684 | * make it big enough for everything we may ever need. | 1693 | * make it big enough for everything we may ever need. |
1685 | */ | 1694 | */ |
1686 | 1695 | ||
1687 | if (head_need > 0 || skb_cloned(skb)) { | 1696 | if (head_need > 0 || skb_cloned(skb)) { |
1688 | head_need += IEEE80211_ENCRYPT_HEADROOM; | 1697 | head_need += IEEE80211_ENCRYPT_HEADROOM; |
1689 | head_need += local->tx_headroom; | 1698 | head_need += local->tx_headroom; |
1690 | head_need = max_t(int, 0, head_need); | 1699 | head_need = max_t(int, 0, head_need); |
1691 | if (ieee80211_skb_resize(local, skb, head_need, true)) | 1700 | if (ieee80211_skb_resize(local, skb, head_need, true)) |
1692 | goto fail; | 1701 | goto fail; |
1693 | } | 1702 | } |
1694 | 1703 | ||
1695 | if (encaps_data) { | 1704 | if (encaps_data) { |
1696 | memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); | 1705 | memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); |
1697 | nh_pos += encaps_len; | 1706 | nh_pos += encaps_len; |
1698 | h_pos += encaps_len; | 1707 | h_pos += encaps_len; |
1699 | } | 1708 | } |
1700 | 1709 | ||
1701 | if (meshhdrlen > 0) { | 1710 | if (meshhdrlen > 0) { |
1702 | memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen); | 1711 | memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen); |
1703 | nh_pos += meshhdrlen; | 1712 | nh_pos += meshhdrlen; |
1704 | h_pos += meshhdrlen; | 1713 | h_pos += meshhdrlen; |
1705 | } | 1714 | } |
1706 | 1715 | ||
1707 | if (ieee80211_is_data_qos(fc)) { | 1716 | if (ieee80211_is_data_qos(fc)) { |
1708 | __le16 *qos_control; | 1717 | __le16 *qos_control; |
1709 | 1718 | ||
1710 | qos_control = (__le16*) skb_push(skb, 2); | 1719 | qos_control = (__le16*) skb_push(skb, 2); |
1711 | memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2); | 1720 | memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2); |
1712 | /* | 1721 | /* |
1713 | * Maybe we could actually set some fields here, for now just | 1722 | * Maybe we could actually set some fields here, for now just |
1714 | * initialise to zero to indicate no special operation. | 1723 | * initialise to zero to indicate no special operation. |
1715 | */ | 1724 | */ |
1716 | *qos_control = 0; | 1725 | *qos_control = 0; |
1717 | } else | 1726 | } else |
1718 | memcpy(skb_push(skb, hdrlen), &hdr, hdrlen); | 1727 | memcpy(skb_push(skb, hdrlen), &hdr, hdrlen); |
1719 | 1728 | ||
1720 | nh_pos += hdrlen; | 1729 | nh_pos += hdrlen; |
1721 | h_pos += hdrlen; | 1730 | h_pos += hdrlen; |
1722 | 1731 | ||
1723 | skb->iif = dev->ifindex; | 1732 | skb->iif = dev->ifindex; |
1724 | 1733 | ||
1725 | skb->dev = local->mdev; | 1734 | skb->dev = local->mdev; |
1726 | dev->stats.tx_packets++; | 1735 | dev->stats.tx_packets++; |
1727 | dev->stats.tx_bytes += skb->len; | 1736 | dev->stats.tx_bytes += skb->len; |
1728 | 1737 | ||
1729 | /* Update skb pointers to various headers since this modified frame | 1738 | /* Update skb pointers to various headers since this modified frame |
1730 | * is going to go through Linux networking code that may potentially | 1739 | * is going to go through Linux networking code that may potentially |
1731 | * need things like pointer to IP header. */ | 1740 | * need things like pointer to IP header. */ |
1732 | skb_set_mac_header(skb, 0); | 1741 | skb_set_mac_header(skb, 0); |
1733 | skb_set_network_header(skb, nh_pos); | 1742 | skb_set_network_header(skb, nh_pos); |
1734 | skb_set_transport_header(skb, h_pos); | 1743 | skb_set_transport_header(skb, h_pos); |
1735 | 1744 | ||
1736 | dev->trans_start = jiffies; | 1745 | dev->trans_start = jiffies; |
1737 | dev_queue_xmit(skb); | 1746 | dev_queue_xmit(skb); |
1738 | 1747 | ||
1739 | return 0; | 1748 | return 0; |
1740 | 1749 | ||
1741 | fail: | 1750 | fail: |
1742 | if (!ret) | 1751 | if (!ret) |
1743 | dev_kfree_skb(skb); | 1752 | dev_kfree_skb(skb); |
1744 | 1753 | ||
1745 | return ret; | 1754 | return ret; |
1746 | } | 1755 | } |
1747 | 1756 | ||
1748 | 1757 | ||
1749 | /* | 1758 | /* |
1750 | * ieee80211_clear_tx_pending may not be called in a context where | 1759 | * ieee80211_clear_tx_pending may not be called in a context where |
1751 | * it is possible that it packets could come in again. | 1760 | * it is possible that it packets could come in again. |
1752 | */ | 1761 | */ |
1753 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) | 1762 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
1754 | { | 1763 | { |
1755 | int i, j; | 1764 | int i, j; |
1756 | struct ieee80211_tx_stored_packet *store; | 1765 | struct ieee80211_tx_stored_packet *store; |
1757 | 1766 | ||
1758 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { | 1767 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1759 | if (!test_bit(i, local->queues_pending)) | 1768 | if (!test_bit(i, local->queues_pending)) |
1760 | continue; | 1769 | continue; |
1761 | store = &local->pending_packet[i]; | 1770 | store = &local->pending_packet[i]; |
1762 | kfree_skb(store->skb); | 1771 | kfree_skb(store->skb); |
1763 | for (j = 0; j < store->num_extra_frag; j++) | 1772 | for (j = 0; j < store->num_extra_frag; j++) |
1764 | kfree_skb(store->extra_frag[j]); | 1773 | kfree_skb(store->extra_frag[j]); |
1765 | kfree(store->extra_frag); | 1774 | kfree(store->extra_frag); |
1766 | clear_bit(i, local->queues_pending); | 1775 | clear_bit(i, local->queues_pending); |
1767 | } | 1776 | } |
1768 | } | 1777 | } |
1769 | 1778 | ||
1770 | /* | 1779 | /* |
1771 | * Transmit all pending packets. Called from tasklet, locks master device | 1780 | * Transmit all pending packets. Called from tasklet, locks master device |
1772 | * TX lock so that no new packets can come in. | 1781 | * TX lock so that no new packets can come in. |
1773 | */ | 1782 | */ |
1774 | void ieee80211_tx_pending(unsigned long data) | 1783 | void ieee80211_tx_pending(unsigned long data) |
1775 | { | 1784 | { |
1776 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1785 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1777 | struct net_device *dev = local->mdev; | 1786 | struct net_device *dev = local->mdev; |
1778 | struct ieee80211_tx_stored_packet *store; | 1787 | struct ieee80211_tx_stored_packet *store; |
1779 | struct ieee80211_tx_data tx; | 1788 | struct ieee80211_tx_data tx; |
1780 | int i, ret; | 1789 | int i, ret; |
1781 | 1790 | ||
1782 | netif_tx_lock_bh(dev); | 1791 | netif_tx_lock_bh(dev); |
1783 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { | 1792 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1784 | /* Check that this queue is ok */ | 1793 | /* Check that this queue is ok */ |
1785 | if (__netif_subqueue_stopped(local->mdev, i) && | 1794 | if (__netif_subqueue_stopped(local->mdev, i) && |
1786 | !test_bit(i, local->queues_pending_run)) | 1795 | !test_bit(i, local->queues_pending_run)) |
1787 | continue; | 1796 | continue; |
1788 | 1797 | ||
1789 | if (!test_bit(i, local->queues_pending)) { | 1798 | if (!test_bit(i, local->queues_pending)) { |
1790 | clear_bit(i, local->queues_pending_run); | 1799 | clear_bit(i, local->queues_pending_run); |
1791 | ieee80211_wake_queue(&local->hw, i); | 1800 | ieee80211_wake_queue(&local->hw, i); |
1792 | continue; | 1801 | continue; |
1793 | } | 1802 | } |
1794 | 1803 | ||
1795 | clear_bit(i, local->queues_pending_run); | 1804 | clear_bit(i, local->queues_pending_run); |
1796 | netif_start_subqueue(local->mdev, i); | 1805 | netif_start_subqueue(local->mdev, i); |
1797 | 1806 | ||
1798 | store = &local->pending_packet[i]; | 1807 | store = &local->pending_packet[i]; |
1799 | tx.extra_frag = store->extra_frag; | 1808 | tx.extra_frag = store->extra_frag; |
1800 | tx.num_extra_frag = store->num_extra_frag; | 1809 | tx.num_extra_frag = store->num_extra_frag; |
1801 | tx.flags = 0; | 1810 | tx.flags = 0; |
1802 | ret = __ieee80211_tx(local, store->skb, &tx); | 1811 | ret = __ieee80211_tx(local, store->skb, &tx); |
1803 | if (ret) { | 1812 | if (ret) { |
1804 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1813 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1805 | store->skb = NULL; | 1814 | store->skb = NULL; |
1806 | } else { | 1815 | } else { |
1807 | clear_bit(i, local->queues_pending); | 1816 | clear_bit(i, local->queues_pending); |
1808 | ieee80211_wake_queue(&local->hw, i); | 1817 | ieee80211_wake_queue(&local->hw, i); |
1809 | } | 1818 | } |
1810 | } | 1819 | } |
1811 | netif_tx_unlock_bh(dev); | 1820 | netif_tx_unlock_bh(dev); |
1812 | } | 1821 | } |
1813 | 1822 | ||
1814 | /* functions for drivers to get certain frames */ | 1823 | /* functions for drivers to get certain frames */ |
1815 | 1824 | ||
1816 | static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, | 1825 | static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, |
1817 | struct sk_buff *skb, | 1826 | struct sk_buff *skb, |
1818 | struct beacon_data *beacon) | 1827 | struct beacon_data *beacon) |
1819 | { | 1828 | { |
1820 | u8 *pos, *tim; | 1829 | u8 *pos, *tim; |
1821 | int aid0 = 0; | 1830 | int aid0 = 0; |
1822 | int i, have_bits = 0, n1, n2; | 1831 | int i, have_bits = 0, n1, n2; |
1823 | 1832 | ||
1824 | /* Generate bitmap for TIM only if there are any STAs in power save | 1833 | /* Generate bitmap for TIM only if there are any STAs in power save |
1825 | * mode. */ | 1834 | * mode. */ |
1826 | if (atomic_read(&bss->num_sta_ps) > 0) | 1835 | if (atomic_read(&bss->num_sta_ps) > 0) |
1827 | /* in the hope that this is faster than | 1836 | /* in the hope that this is faster than |
1828 | * checking byte-for-byte */ | 1837 | * checking byte-for-byte */ |
1829 | have_bits = !bitmap_empty((unsigned long*)bss->tim, | 1838 | have_bits = !bitmap_empty((unsigned long*)bss->tim, |
1830 | IEEE80211_MAX_AID+1); | 1839 | IEEE80211_MAX_AID+1); |
1831 | 1840 | ||
1832 | if (bss->dtim_count == 0) | 1841 | if (bss->dtim_count == 0) |
1833 | bss->dtim_count = beacon->dtim_period - 1; | 1842 | bss->dtim_count = beacon->dtim_period - 1; |
1834 | else | 1843 | else |
1835 | bss->dtim_count--; | 1844 | bss->dtim_count--; |
1836 | 1845 | ||
1837 | tim = pos = (u8 *) skb_put(skb, 6); | 1846 | tim = pos = (u8 *) skb_put(skb, 6); |
1838 | *pos++ = WLAN_EID_TIM; | 1847 | *pos++ = WLAN_EID_TIM; |
1839 | *pos++ = 4; | 1848 | *pos++ = 4; |
1840 | *pos++ = bss->dtim_count; | 1849 | *pos++ = bss->dtim_count; |
1841 | *pos++ = beacon->dtim_period; | 1850 | *pos++ = beacon->dtim_period; |
1842 | 1851 | ||
1843 | if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) | 1852 | if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) |
1844 | aid0 = 1; | 1853 | aid0 = 1; |
1845 | 1854 | ||
1846 | if (have_bits) { | 1855 | if (have_bits) { |
1847 | /* Find largest even number N1 so that bits numbered 1 through | 1856 | /* Find largest even number N1 so that bits numbered 1 through |
1848 | * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits | 1857 | * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits |
1849 | * (N2 + 1) x 8 through 2007 are 0. */ | 1858 | * (N2 + 1) x 8 through 2007 are 0. */ |
1850 | n1 = 0; | 1859 | n1 = 0; |
1851 | for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) { | 1860 | for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) { |
1852 | if (bss->tim[i]) { | 1861 | if (bss->tim[i]) { |
1853 | n1 = i & 0xfe; | 1862 | n1 = i & 0xfe; |
1854 | break; | 1863 | break; |
1855 | } | 1864 | } |
1856 | } | 1865 | } |
1857 | n2 = n1; | 1866 | n2 = n1; |
1858 | for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) { | 1867 | for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) { |
1859 | if (bss->tim[i]) { | 1868 | if (bss->tim[i]) { |
1860 | n2 = i; | 1869 | n2 = i; |
1861 | break; | 1870 | break; |
1862 | } | 1871 | } |
1863 | } | 1872 | } |
1864 | 1873 | ||
1865 | /* Bitmap control */ | 1874 | /* Bitmap control */ |
1866 | *pos++ = n1 | aid0; | 1875 | *pos++ = n1 | aid0; |
1867 | /* Part Virt Bitmap */ | 1876 | /* Part Virt Bitmap */ |
1868 | memcpy(pos, bss->tim + n1, n2 - n1 + 1); | 1877 | memcpy(pos, bss->tim + n1, n2 - n1 + 1); |
1869 | 1878 | ||
1870 | tim[1] = n2 - n1 + 4; | 1879 | tim[1] = n2 - n1 + 4; |
1871 | skb_put(skb, n2 - n1); | 1880 | skb_put(skb, n2 - n1); |
1872 | } else { | 1881 | } else { |
1873 | *pos++ = aid0; /* Bitmap control */ | 1882 | *pos++ = aid0; /* Bitmap control */ |
1874 | *pos++ = 0; /* Part Virt Bitmap */ | 1883 | *pos++ = 0; /* Part Virt Bitmap */ |
1875 | } | 1884 | } |
1876 | } | 1885 | } |
1877 | 1886 | ||
1878 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | 1887 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, |
1879 | struct ieee80211_vif *vif) | 1888 | struct ieee80211_vif *vif) |
1880 | { | 1889 | { |
1881 | struct ieee80211_local *local = hw_to_local(hw); | 1890 | struct ieee80211_local *local = hw_to_local(hw); |
1882 | struct sk_buff *skb = NULL; | 1891 | struct sk_buff *skb = NULL; |
1883 | struct ieee80211_tx_info *info; | 1892 | struct ieee80211_tx_info *info; |
1884 | struct ieee80211_sub_if_data *sdata = NULL; | 1893 | struct ieee80211_sub_if_data *sdata = NULL; |
1885 | struct ieee80211_if_ap *ap = NULL; | 1894 | struct ieee80211_if_ap *ap = NULL; |
1886 | struct ieee80211_if_sta *ifsta = NULL; | 1895 | struct ieee80211_if_sta *ifsta = NULL; |
1887 | struct beacon_data *beacon; | 1896 | struct beacon_data *beacon; |
1888 | struct ieee80211_supported_band *sband; | 1897 | struct ieee80211_supported_band *sband; |
1889 | enum ieee80211_band band = local->hw.conf.channel->band; | 1898 | enum ieee80211_band band = local->hw.conf.channel->band; |
1890 | 1899 | ||
1891 | sband = local->hw.wiphy->bands[band]; | 1900 | sband = local->hw.wiphy->bands[band]; |
1892 | 1901 | ||
1893 | rcu_read_lock(); | 1902 | rcu_read_lock(); |
1894 | 1903 | ||
1895 | sdata = vif_to_sdata(vif); | 1904 | sdata = vif_to_sdata(vif); |
1896 | 1905 | ||
1897 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 1906 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
1898 | ap = &sdata->u.ap; | 1907 | ap = &sdata->u.ap; |
1899 | beacon = rcu_dereference(ap->beacon); | 1908 | beacon = rcu_dereference(ap->beacon); |
1900 | if (ap && beacon) { | 1909 | if (ap && beacon) { |
1901 | /* | 1910 | /* |
1902 | * headroom, head length, | 1911 | * headroom, head length, |
1903 | * tail length and maximum TIM length | 1912 | * tail length and maximum TIM length |
1904 | */ | 1913 | */ |
1905 | skb = dev_alloc_skb(local->tx_headroom + | 1914 | skb = dev_alloc_skb(local->tx_headroom + |
1906 | beacon->head_len + | 1915 | beacon->head_len + |
1907 | beacon->tail_len + 256); | 1916 | beacon->tail_len + 256); |
1908 | if (!skb) | 1917 | if (!skb) |
1909 | goto out; | 1918 | goto out; |
1910 | 1919 | ||
1911 | skb_reserve(skb, local->tx_headroom); | 1920 | skb_reserve(skb, local->tx_headroom); |
1912 | memcpy(skb_put(skb, beacon->head_len), beacon->head, | 1921 | memcpy(skb_put(skb, beacon->head_len), beacon->head, |
1913 | beacon->head_len); | 1922 | beacon->head_len); |
1914 | 1923 | ||
1915 | /* | 1924 | /* |
1916 | * Not very nice, but we want to allow the driver to call | 1925 | * Not very nice, but we want to allow the driver to call |
1917 | * ieee80211_beacon_get() as a response to the set_tim() | 1926 | * ieee80211_beacon_get() as a response to the set_tim() |
1918 | * callback. That, however, is already invoked under the | 1927 | * callback. That, however, is already invoked under the |
1919 | * sta_lock to guarantee consistent and race-free update | 1928 | * sta_lock to guarantee consistent and race-free update |
1920 | * of the tim bitmap in mac80211 and the driver. | 1929 | * of the tim bitmap in mac80211 and the driver. |
1921 | */ | 1930 | */ |
1922 | if (local->tim_in_locked_section) { | 1931 | if (local->tim_in_locked_section) { |
1923 | ieee80211_beacon_add_tim(ap, skb, beacon); | 1932 | ieee80211_beacon_add_tim(ap, skb, beacon); |
1924 | } else { | 1933 | } else { |
1925 | unsigned long flags; | 1934 | unsigned long flags; |
1926 | 1935 | ||
1927 | spin_lock_irqsave(&local->sta_lock, flags); | 1936 | spin_lock_irqsave(&local->sta_lock, flags); |
1928 | ieee80211_beacon_add_tim(ap, skb, beacon); | 1937 | ieee80211_beacon_add_tim(ap, skb, beacon); |
1929 | spin_unlock_irqrestore(&local->sta_lock, flags); | 1938 | spin_unlock_irqrestore(&local->sta_lock, flags); |
1930 | } | 1939 | } |
1931 | 1940 | ||
1932 | if (beacon->tail) | 1941 | if (beacon->tail) |
1933 | memcpy(skb_put(skb, beacon->tail_len), | 1942 | memcpy(skb_put(skb, beacon->tail_len), |
1934 | beacon->tail, beacon->tail_len); | 1943 | beacon->tail, beacon->tail_len); |
1935 | } else | 1944 | } else |
1936 | goto out; | 1945 | goto out; |
1937 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 1946 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1938 | struct ieee80211_hdr *hdr; | 1947 | struct ieee80211_hdr *hdr; |
1939 | ifsta = &sdata->u.sta; | 1948 | ifsta = &sdata->u.sta; |
1940 | 1949 | ||
1941 | if (!ifsta->probe_resp) | 1950 | if (!ifsta->probe_resp) |
1942 | goto out; | 1951 | goto out; |
1943 | 1952 | ||
1944 | skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC); | 1953 | skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC); |
1945 | if (!skb) | 1954 | if (!skb) |
1946 | goto out; | 1955 | goto out; |
1947 | 1956 | ||
1948 | hdr = (struct ieee80211_hdr *) skb->data; | 1957 | hdr = (struct ieee80211_hdr *) skb->data; |
1949 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 1958 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1950 | IEEE80211_STYPE_BEACON); | 1959 | IEEE80211_STYPE_BEACON); |
1951 | 1960 | ||
1952 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1961 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1953 | struct ieee80211_mgmt *mgmt; | 1962 | struct ieee80211_mgmt *mgmt; |
1954 | u8 *pos; | 1963 | u8 *pos; |
1955 | 1964 | ||
1956 | /* headroom, head length, tail length and maximum TIM length */ | 1965 | /* headroom, head length, tail length and maximum TIM length */ |
1957 | skb = dev_alloc_skb(local->tx_headroom + 400); | 1966 | skb = dev_alloc_skb(local->tx_headroom + 400); |
1958 | if (!skb) | 1967 | if (!skb) |
1959 | goto out; | 1968 | goto out; |
1960 | 1969 | ||
1961 | skb_reserve(skb, local->hw.extra_tx_headroom); | 1970 | skb_reserve(skb, local->hw.extra_tx_headroom); |
1962 | mgmt = (struct ieee80211_mgmt *) | 1971 | mgmt = (struct ieee80211_mgmt *) |
1963 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 1972 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
1964 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 1973 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
1965 | mgmt->frame_control = | 1974 | mgmt->frame_control = |
1966 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 1975 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
1967 | memset(mgmt->da, 0xff, ETH_ALEN); | 1976 | memset(mgmt->da, 0xff, ETH_ALEN); |
1968 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 1977 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
1969 | /* BSSID is left zeroed, wildcard value */ | 1978 | /* BSSID is left zeroed, wildcard value */ |
1970 | mgmt->u.beacon.beacon_int = | 1979 | mgmt->u.beacon.beacon_int = |
1971 | cpu_to_le16(local->hw.conf.beacon_int); | 1980 | cpu_to_le16(local->hw.conf.beacon_int); |
1972 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ | 1981 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ |
1973 | 1982 | ||
1974 | pos = skb_put(skb, 2); | 1983 | pos = skb_put(skb, 2); |
1975 | *pos++ = WLAN_EID_SSID; | 1984 | *pos++ = WLAN_EID_SSID; |
1976 | *pos++ = 0x0; | 1985 | *pos++ = 0x0; |
1977 | 1986 | ||
1978 | mesh_mgmt_ies_add(skb, sdata); | 1987 | mesh_mgmt_ies_add(skb, sdata); |
1979 | } else { | 1988 | } else { |
1980 | WARN_ON(1); | 1989 | WARN_ON(1); |
1981 | goto out; | 1990 | goto out; |
1982 | } | 1991 | } |
1983 | 1992 | ||
1984 | info = IEEE80211_SKB_CB(skb); | 1993 | info = IEEE80211_SKB_CB(skb); |
1985 | 1994 | ||
1986 | skb->do_not_encrypt = 1; | 1995 | skb->do_not_encrypt = 1; |
1987 | 1996 | ||
1988 | info->band = band; | 1997 | info->band = band; |
1989 | /* | 1998 | /* |
1990 | * XXX: For now, always use the lowest rate | 1999 | * XXX: For now, always use the lowest rate |
1991 | */ | 2000 | */ |
1992 | info->control.rates[0].idx = 0; | 2001 | info->control.rates[0].idx = 0; |
1993 | info->control.rates[0].count = 1; | 2002 | info->control.rates[0].count = 1; |
1994 | info->control.rates[1].idx = -1; | 2003 | info->control.rates[1].idx = -1; |
1995 | info->control.rates[2].idx = -1; | 2004 | info->control.rates[2].idx = -1; |
1996 | info->control.rates[3].idx = -1; | 2005 | info->control.rates[3].idx = -1; |
1997 | info->control.rates[4].idx = -1; | 2006 | info->control.rates[4].idx = -1; |
1998 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); | 2007 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); |
1999 | 2008 | ||
2000 | info->control.vif = vif; | 2009 | info->control.vif = vif; |
2001 | 2010 | ||
2002 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 2011 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
2003 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 2012 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
2004 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 2013 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
2005 | out: | 2014 | out: |
2006 | rcu_read_unlock(); | 2015 | rcu_read_unlock(); |
2007 | return skb; | 2016 | return skb; |
2008 | } | 2017 | } |
2009 | EXPORT_SYMBOL(ieee80211_beacon_get); | 2018 | EXPORT_SYMBOL(ieee80211_beacon_get); |
2010 | 2019 | ||
2011 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2020 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2012 | const void *frame, size_t frame_len, | 2021 | const void *frame, size_t frame_len, |
2013 | const struct ieee80211_tx_info *frame_txctl, | 2022 | const struct ieee80211_tx_info *frame_txctl, |
2014 | struct ieee80211_rts *rts) | 2023 | struct ieee80211_rts *rts) |
2015 | { | 2024 | { |
2016 | const struct ieee80211_hdr *hdr = frame; | 2025 | const struct ieee80211_hdr *hdr = frame; |
2017 | 2026 | ||
2018 | rts->frame_control = | 2027 | rts->frame_control = |
2019 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); | 2028 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); |
2020 | rts->duration = ieee80211_rts_duration(hw, vif, frame_len, | 2029 | rts->duration = ieee80211_rts_duration(hw, vif, frame_len, |
2021 | frame_txctl); | 2030 | frame_txctl); |
2022 | memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); | 2031 | memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); |
2023 | memcpy(rts->ta, hdr->addr2, sizeof(rts->ta)); | 2032 | memcpy(rts->ta, hdr->addr2, sizeof(rts->ta)); |
2024 | } | 2033 | } |
2025 | EXPORT_SYMBOL(ieee80211_rts_get); | 2034 | EXPORT_SYMBOL(ieee80211_rts_get); |
2026 | 2035 | ||
2027 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2036 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2028 | const void *frame, size_t frame_len, | 2037 | const void *frame, size_t frame_len, |
2029 | const struct ieee80211_tx_info *frame_txctl, | 2038 | const struct ieee80211_tx_info *frame_txctl, |
2030 | struct ieee80211_cts *cts) | 2039 | struct ieee80211_cts *cts) |
2031 | { | 2040 | { |
2032 | const struct ieee80211_hdr *hdr = frame; | 2041 | const struct ieee80211_hdr *hdr = frame; |
2033 | 2042 | ||
2034 | cts->frame_control = | 2043 | cts->frame_control = |
2035 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); | 2044 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); |
2036 | cts->duration = ieee80211_ctstoself_duration(hw, vif, | 2045 | cts->duration = ieee80211_ctstoself_duration(hw, vif, |
2037 | frame_len, frame_txctl); | 2046 | frame_len, frame_txctl); |
2038 | memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); | 2047 | memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); |
2039 | } | 2048 | } |
2040 | EXPORT_SYMBOL(ieee80211_ctstoself_get); | 2049 | EXPORT_SYMBOL(ieee80211_ctstoself_get); |
2041 | 2050 | ||
2042 | struct sk_buff * | 2051 | struct sk_buff * |
2043 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | 2052 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, |
2044 | struct ieee80211_vif *vif) | 2053 | struct ieee80211_vif *vif) |
2045 | { | 2054 | { |
2046 | struct ieee80211_local *local = hw_to_local(hw); | 2055 | struct ieee80211_local *local = hw_to_local(hw); |
2047 | struct sk_buff *skb = NULL; | 2056 | struct sk_buff *skb = NULL; |
2048 | struct sta_info *sta; | 2057 | struct sta_info *sta; |
2049 | struct ieee80211_tx_data tx; | 2058 | struct ieee80211_tx_data tx; |
2050 | struct ieee80211_sub_if_data *sdata; | 2059 | struct ieee80211_sub_if_data *sdata; |
2051 | struct ieee80211_if_ap *bss = NULL; | 2060 | struct ieee80211_if_ap *bss = NULL; |
2052 | struct beacon_data *beacon; | 2061 | struct beacon_data *beacon; |
2053 | struct ieee80211_tx_info *info; | 2062 | struct ieee80211_tx_info *info; |
2054 | 2063 | ||
2055 | sdata = vif_to_sdata(vif); | 2064 | sdata = vif_to_sdata(vif); |
2056 | bss = &sdata->u.ap; | 2065 | bss = &sdata->u.ap; |
2057 | 2066 | ||
2058 | if (!bss) | 2067 | if (!bss) |
2059 | return NULL; | 2068 | return NULL; |
2060 | 2069 | ||
2061 | rcu_read_lock(); | 2070 | rcu_read_lock(); |
2062 | beacon = rcu_dereference(bss->beacon); | 2071 | beacon = rcu_dereference(bss->beacon); |
2063 | 2072 | ||
2064 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) | 2073 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) |
2065 | goto out; | 2074 | goto out; |
2066 | 2075 | ||
2067 | if (bss->dtim_count != 0) | 2076 | if (bss->dtim_count != 0) |
2068 | goto out; /* send buffered bc/mc only after DTIM beacon */ | 2077 | goto out; /* send buffered bc/mc only after DTIM beacon */ |
2069 | 2078 | ||
2070 | while (1) { | 2079 | while (1) { |
2071 | skb = skb_dequeue(&bss->ps_bc_buf); | 2080 | skb = skb_dequeue(&bss->ps_bc_buf); |
2072 | if (!skb) | 2081 | if (!skb) |
2073 | goto out; | 2082 | goto out; |
2074 | local->total_ps_buffered--; | 2083 | local->total_ps_buffered--; |
2075 | 2084 | ||
2076 | if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) { | 2085 | if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) { |
2077 | struct ieee80211_hdr *hdr = | 2086 | struct ieee80211_hdr *hdr = |
2078 | (struct ieee80211_hdr *) skb->data; | 2087 | (struct ieee80211_hdr *) skb->data; |
2079 | /* more buffered multicast/broadcast frames ==> set | 2088 | /* more buffered multicast/broadcast frames ==> set |
2080 | * MoreData flag in IEEE 802.11 header to inform PS | 2089 | * MoreData flag in IEEE 802.11 header to inform PS |
2081 | * STAs */ | 2090 | * STAs */ |
2082 | hdr->frame_control |= | 2091 | hdr->frame_control |= |
2083 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2092 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2084 | } | 2093 | } |
2085 | 2094 | ||
2086 | if (!ieee80211_tx_prepare(local, &tx, skb)) | 2095 | if (!ieee80211_tx_prepare(local, &tx, skb)) |
2087 | break; | 2096 | break; |
2088 | dev_kfree_skb_any(skb); | 2097 | dev_kfree_skb_any(skb); |
2089 | } | 2098 | } |
2090 | 2099 | ||
2091 | info = IEEE80211_SKB_CB(skb); | 2100 | info = IEEE80211_SKB_CB(skb); |
2092 | 2101 | ||
2093 | sta = tx.sta; | 2102 | sta = tx.sta; |
2094 | tx.flags |= IEEE80211_TX_PS_BUFFERED; | 2103 | tx.flags |= IEEE80211_TX_PS_BUFFERED; |
2095 | tx.channel = local->hw.conf.channel; | 2104 | tx.channel = local->hw.conf.channel; |
2096 | info->band = tx.channel->band; | 2105 | info->band = tx.channel->band; |
2097 | 2106 | ||
2098 | if (invoke_tx_handlers(&tx)) | 2107 | if (invoke_tx_handlers(&tx)) |
2099 | skb = NULL; | 2108 | skb = NULL; |
2100 | out: | 2109 | out: |
2101 | rcu_read_unlock(); | 2110 | rcu_read_unlock(); |
2102 | 2111 | ||
2103 | return skb; | 2112 | return skb; |
2104 | } | 2113 | } |
2105 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); | 2114 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); |
2106 | 2115 |
net/wireless/nl80211.c
1 | /* | 1 | /* |
2 | * This is the new netlink-based wireless configuration interface. | 2 | * This is the new netlink-based wireless configuration interface. |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/if.h> | 7 | #include <linux/if.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/err.h> | 9 | #include <linux/err.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include <linux/if_ether.h> | 12 | #include <linux/if_ether.h> |
13 | #include <linux/ieee80211.h> | 13 | #include <linux/ieee80211.h> |
14 | #include <linux/nl80211.h> | 14 | #include <linux/nl80211.h> |
15 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
16 | #include <linux/netlink.h> | 16 | #include <linux/netlink.h> |
17 | #include <net/genetlink.h> | 17 | #include <net/genetlink.h> |
18 | #include <net/cfg80211.h> | 18 | #include <net/cfg80211.h> |
19 | #include "core.h" | 19 | #include "core.h" |
20 | #include "nl80211.h" | 20 | #include "nl80211.h" |
21 | #include "reg.h" | 21 | #include "reg.h" |
22 | 22 | ||
23 | /* the netlink family */ | 23 | /* the netlink family */ |
24 | static struct genl_family nl80211_fam = { | 24 | static struct genl_family nl80211_fam = { |
25 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ | 25 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ |
26 | .name = "nl80211", /* have users key off the name instead */ | 26 | .name = "nl80211", /* have users key off the name instead */ |
27 | .hdrsize = 0, /* no private header */ | 27 | .hdrsize = 0, /* no private header */ |
28 | .version = 1, /* no particular meaning now */ | 28 | .version = 1, /* no particular meaning now */ |
29 | .maxattr = NL80211_ATTR_MAX, | 29 | .maxattr = NL80211_ATTR_MAX, |
30 | }; | 30 | }; |
31 | 31 | ||
32 | /* internal helper: get drv and dev */ | 32 | /* internal helper: get drv and dev */ |
33 | static int get_drv_dev_by_info_ifindex(struct nlattr **attrs, | 33 | static int get_drv_dev_by_info_ifindex(struct nlattr **attrs, |
34 | struct cfg80211_registered_device **drv, | 34 | struct cfg80211_registered_device **drv, |
35 | struct net_device **dev) | 35 | struct net_device **dev) |
36 | { | 36 | { |
37 | int ifindex; | 37 | int ifindex; |
38 | 38 | ||
39 | if (!attrs[NL80211_ATTR_IFINDEX]) | 39 | if (!attrs[NL80211_ATTR_IFINDEX]) |
40 | return -EINVAL; | 40 | return -EINVAL; |
41 | 41 | ||
42 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); | 42 | ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); |
43 | *dev = dev_get_by_index(&init_net, ifindex); | 43 | *dev = dev_get_by_index(&init_net, ifindex); |
44 | if (!*dev) | 44 | if (!*dev) |
45 | return -ENODEV; | 45 | return -ENODEV; |
46 | 46 | ||
47 | *drv = cfg80211_get_dev_from_ifindex(ifindex); | 47 | *drv = cfg80211_get_dev_from_ifindex(ifindex); |
48 | if (IS_ERR(*drv)) { | 48 | if (IS_ERR(*drv)) { |
49 | dev_put(*dev); | 49 | dev_put(*dev); |
50 | return PTR_ERR(*drv); | 50 | return PTR_ERR(*drv); |
51 | } | 51 | } |
52 | 52 | ||
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | /* policy for the attributes */ | 56 | /* policy for the attributes */ |
57 | static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | 57 | static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { |
58 | [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, | 58 | [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, |
59 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, | 59 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, |
60 | .len = BUS_ID_SIZE-1 }, | 60 | .len = BUS_ID_SIZE-1 }, |
61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | 61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | 62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, |
63 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, | 63 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, |
64 | 64 | ||
65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
67 | [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, | 67 | [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, |
68 | 68 | ||
69 | [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, | 69 | [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, |
70 | 70 | ||
71 | [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, | 71 | [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, |
72 | .len = WLAN_MAX_KEY_LEN }, | 72 | .len = WLAN_MAX_KEY_LEN }, |
73 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, | 73 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, |
74 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, | 74 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, |
75 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, | 75 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, |
76 | 76 | ||
77 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, | 77 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, |
78 | [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, | 78 | [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, |
79 | [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, | 79 | [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, |
80 | .len = IEEE80211_MAX_DATA_LEN }, | 80 | .len = IEEE80211_MAX_DATA_LEN }, |
81 | [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY, | 81 | [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY, |
82 | .len = IEEE80211_MAX_DATA_LEN }, | 82 | .len = IEEE80211_MAX_DATA_LEN }, |
83 | [NL80211_ATTR_STA_AID] = { .type = NLA_U16 }, | 83 | [NL80211_ATTR_STA_AID] = { .type = NLA_U16 }, |
84 | [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED }, | 84 | [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED }, |
85 | [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 }, | 85 | [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 }, |
86 | [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY, | 86 | [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY, |
87 | .len = NL80211_MAX_SUPP_RATES }, | 87 | .len = NL80211_MAX_SUPP_RATES }, |
88 | [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 }, | 88 | [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 }, |
89 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, | 89 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, |
90 | [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, | 90 | [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, |
91 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, | 91 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, |
92 | .len = IEEE80211_MAX_MESH_ID_LEN }, | 92 | .len = IEEE80211_MAX_MESH_ID_LEN }, |
93 | [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, | 93 | [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, |
94 | 94 | ||
95 | [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, | 95 | [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, |
96 | [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED }, | 96 | [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED }, |
97 | 97 | ||
98 | [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, | 98 | [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, |
99 | [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, | 99 | [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, |
100 | [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, | 100 | [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, |
101 | [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY, | 101 | [NL80211_ATTR_BSS_BASIC_RATES] = { .type = NLA_BINARY, |
102 | .len = NL80211_MAX_SUPP_RATES }, | 102 | .len = NL80211_MAX_SUPP_RATES }, |
103 | 103 | ||
104 | [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, | 104 | [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, |
105 | 105 | ||
106 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | 106 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, |
107 | .len = NL80211_HT_CAPABILITY_LEN }, | 107 | .len = NL80211_HT_CAPABILITY_LEN }, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | /* message building helper */ | 110 | /* message building helper */ |
111 | static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, | 111 | static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, |
112 | int flags, u8 cmd) | 112 | int flags, u8 cmd) |
113 | { | 113 | { |
114 | /* since there is no private header just add the generic one */ | 114 | /* since there is no private header just add the generic one */ |
115 | return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); | 115 | return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* netlink command implementations */ | 118 | /* netlink command implementations */ |
119 | 119 | ||
120 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 120 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
121 | struct cfg80211_registered_device *dev) | 121 | struct cfg80211_registered_device *dev) |
122 | { | 122 | { |
123 | void *hdr; | 123 | void *hdr; |
124 | struct nlattr *nl_bands, *nl_band; | 124 | struct nlattr *nl_bands, *nl_band; |
125 | struct nlattr *nl_freqs, *nl_freq; | 125 | struct nlattr *nl_freqs, *nl_freq; |
126 | struct nlattr *nl_rates, *nl_rate; | 126 | struct nlattr *nl_rates, *nl_rate; |
127 | struct nlattr *nl_modes; | 127 | struct nlattr *nl_modes; |
128 | enum ieee80211_band band; | 128 | enum ieee80211_band band; |
129 | struct ieee80211_channel *chan; | 129 | struct ieee80211_channel *chan; |
130 | struct ieee80211_rate *rate; | 130 | struct ieee80211_rate *rate; |
131 | int i; | 131 | int i; |
132 | u16 ifmodes = dev->wiphy.interface_modes; | 132 | u16 ifmodes = dev->wiphy.interface_modes; |
133 | 133 | ||
134 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); | 134 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
135 | if (!hdr) | 135 | if (!hdr) |
136 | return -1; | 136 | return -1; |
137 | 137 | ||
138 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); | 138 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); |
139 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); | 139 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); |
140 | 140 | ||
141 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); | 141 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); |
142 | if (!nl_modes) | 142 | if (!nl_modes) |
143 | goto nla_put_failure; | 143 | goto nla_put_failure; |
144 | 144 | ||
145 | i = 0; | 145 | i = 0; |
146 | while (ifmodes) { | 146 | while (ifmodes) { |
147 | if (ifmodes & 1) | 147 | if (ifmodes & 1) |
148 | NLA_PUT_FLAG(msg, i); | 148 | NLA_PUT_FLAG(msg, i); |
149 | ifmodes >>= 1; | 149 | ifmodes >>= 1; |
150 | i++; | 150 | i++; |
151 | } | 151 | } |
152 | 152 | ||
153 | nla_nest_end(msg, nl_modes); | 153 | nla_nest_end(msg, nl_modes); |
154 | 154 | ||
155 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 155 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); |
156 | if (!nl_bands) | 156 | if (!nl_bands) |
157 | goto nla_put_failure; | 157 | goto nla_put_failure; |
158 | 158 | ||
159 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 159 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
160 | if (!dev->wiphy.bands[band]) | 160 | if (!dev->wiphy.bands[band]) |
161 | continue; | 161 | continue; |
162 | 162 | ||
163 | nl_band = nla_nest_start(msg, band); | 163 | nl_band = nla_nest_start(msg, band); |
164 | if (!nl_band) | 164 | if (!nl_band) |
165 | goto nla_put_failure; | 165 | goto nla_put_failure; |
166 | 166 | ||
167 | /* add HT info */ | 167 | /* add HT info */ |
168 | if (dev->wiphy.bands[band]->ht_cap.ht_supported) { | 168 | if (dev->wiphy.bands[band]->ht_cap.ht_supported) { |
169 | NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET, | 169 | NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET, |
170 | sizeof(dev->wiphy.bands[band]->ht_cap.mcs), | 170 | sizeof(dev->wiphy.bands[band]->ht_cap.mcs), |
171 | &dev->wiphy.bands[band]->ht_cap.mcs); | 171 | &dev->wiphy.bands[band]->ht_cap.mcs); |
172 | NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA, | 172 | NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA, |
173 | dev->wiphy.bands[band]->ht_cap.cap); | 173 | dev->wiphy.bands[band]->ht_cap.cap); |
174 | NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, | 174 | NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, |
175 | dev->wiphy.bands[band]->ht_cap.ampdu_factor); | 175 | dev->wiphy.bands[band]->ht_cap.ampdu_factor); |
176 | NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, | 176 | NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, |
177 | dev->wiphy.bands[band]->ht_cap.ampdu_density); | 177 | dev->wiphy.bands[band]->ht_cap.ampdu_density); |
178 | } | 178 | } |
179 | 179 | ||
180 | /* add frequencies */ | 180 | /* add frequencies */ |
181 | nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); | 181 | nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); |
182 | if (!nl_freqs) | 182 | if (!nl_freqs) |
183 | goto nla_put_failure; | 183 | goto nla_put_failure; |
184 | 184 | ||
185 | for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) { | 185 | for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) { |
186 | nl_freq = nla_nest_start(msg, i); | 186 | nl_freq = nla_nest_start(msg, i); |
187 | if (!nl_freq) | 187 | if (!nl_freq) |
188 | goto nla_put_failure; | 188 | goto nla_put_failure; |
189 | 189 | ||
190 | chan = &dev->wiphy.bands[band]->channels[i]; | 190 | chan = &dev->wiphy.bands[band]->channels[i]; |
191 | NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, | 191 | NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, |
192 | chan->center_freq); | 192 | chan->center_freq); |
193 | 193 | ||
194 | if (chan->flags & IEEE80211_CHAN_DISABLED) | 194 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
195 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); | 195 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); |
196 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 196 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
197 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); | 197 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); |
198 | if (chan->flags & IEEE80211_CHAN_NO_IBSS) | 198 | if (chan->flags & IEEE80211_CHAN_NO_IBSS) |
199 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); | 199 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); |
200 | if (chan->flags & IEEE80211_CHAN_RADAR) | 200 | if (chan->flags & IEEE80211_CHAN_RADAR) |
201 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); | 201 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); |
202 | 202 | ||
203 | NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | 203 | NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, |
204 | DBM_TO_MBM(chan->max_power)); | 204 | DBM_TO_MBM(chan->max_power)); |
205 | 205 | ||
206 | nla_nest_end(msg, nl_freq); | 206 | nla_nest_end(msg, nl_freq); |
207 | } | 207 | } |
208 | 208 | ||
209 | nla_nest_end(msg, nl_freqs); | 209 | nla_nest_end(msg, nl_freqs); |
210 | 210 | ||
211 | /* add bitrates */ | 211 | /* add bitrates */ |
212 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); | 212 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); |
213 | if (!nl_rates) | 213 | if (!nl_rates) |
214 | goto nla_put_failure; | 214 | goto nla_put_failure; |
215 | 215 | ||
216 | for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) { | 216 | for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) { |
217 | nl_rate = nla_nest_start(msg, i); | 217 | nl_rate = nla_nest_start(msg, i); |
218 | if (!nl_rate) | 218 | if (!nl_rate) |
219 | goto nla_put_failure; | 219 | goto nla_put_failure; |
220 | 220 | ||
221 | rate = &dev->wiphy.bands[band]->bitrates[i]; | 221 | rate = &dev->wiphy.bands[band]->bitrates[i]; |
222 | NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE, | 222 | NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE, |
223 | rate->bitrate); | 223 | rate->bitrate); |
224 | if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) | 224 | if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) |
225 | NLA_PUT_FLAG(msg, | 225 | NLA_PUT_FLAG(msg, |
226 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE); | 226 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE); |
227 | 227 | ||
228 | nla_nest_end(msg, nl_rate); | 228 | nla_nest_end(msg, nl_rate); |
229 | } | 229 | } |
230 | 230 | ||
231 | nla_nest_end(msg, nl_rates); | 231 | nla_nest_end(msg, nl_rates); |
232 | 232 | ||
233 | nla_nest_end(msg, nl_band); | 233 | nla_nest_end(msg, nl_band); |
234 | } | 234 | } |
235 | nla_nest_end(msg, nl_bands); | 235 | nla_nest_end(msg, nl_bands); |
236 | 236 | ||
237 | return genlmsg_end(msg, hdr); | 237 | return genlmsg_end(msg, hdr); |
238 | 238 | ||
239 | nla_put_failure: | 239 | nla_put_failure: |
240 | genlmsg_cancel(msg, hdr); | 240 | genlmsg_cancel(msg, hdr); |
241 | return -EMSGSIZE; | 241 | return -EMSGSIZE; |
242 | } | 242 | } |
243 | 243 | ||
244 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | 244 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) |
245 | { | 245 | { |
246 | int idx = 0; | 246 | int idx = 0; |
247 | int start = cb->args[0]; | 247 | int start = cb->args[0]; |
248 | struct cfg80211_registered_device *dev; | 248 | struct cfg80211_registered_device *dev; |
249 | 249 | ||
250 | mutex_lock(&cfg80211_drv_mutex); | 250 | mutex_lock(&cfg80211_drv_mutex); |
251 | list_for_each_entry(dev, &cfg80211_drv_list, list) { | 251 | list_for_each_entry(dev, &cfg80211_drv_list, list) { |
252 | if (++idx <= start) | 252 | if (++idx <= start) |
253 | continue; | 253 | continue; |
254 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, | 254 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, |
255 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 255 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
256 | dev) < 0) { | 256 | dev) < 0) { |
257 | idx--; | 257 | idx--; |
258 | break; | 258 | break; |
259 | } | 259 | } |
260 | } | 260 | } |
261 | mutex_unlock(&cfg80211_drv_mutex); | 261 | mutex_unlock(&cfg80211_drv_mutex); |
262 | 262 | ||
263 | cb->args[0] = idx; | 263 | cb->args[0] = idx; |
264 | 264 | ||
265 | return skb->len; | 265 | return skb->len; |
266 | } | 266 | } |
267 | 267 | ||
268 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | 268 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) |
269 | { | 269 | { |
270 | struct sk_buff *msg; | 270 | struct sk_buff *msg; |
271 | struct cfg80211_registered_device *dev; | 271 | struct cfg80211_registered_device *dev; |
272 | 272 | ||
273 | dev = cfg80211_get_dev_from_info(info); | 273 | dev = cfg80211_get_dev_from_info(info); |
274 | if (IS_ERR(dev)) | 274 | if (IS_ERR(dev)) |
275 | return PTR_ERR(dev); | 275 | return PTR_ERR(dev); |
276 | 276 | ||
277 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 277 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
278 | if (!msg) | 278 | if (!msg) |
279 | goto out_err; | 279 | goto out_err; |
280 | 280 | ||
281 | if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) | 281 | if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) |
282 | goto out_free; | 282 | goto out_free; |
283 | 283 | ||
284 | cfg80211_put_dev(dev); | 284 | cfg80211_put_dev(dev); |
285 | 285 | ||
286 | return genlmsg_unicast(msg, info->snd_pid); | 286 | return genlmsg_unicast(msg, info->snd_pid); |
287 | 287 | ||
288 | out_free: | 288 | out_free: |
289 | nlmsg_free(msg); | 289 | nlmsg_free(msg); |
290 | out_err: | 290 | out_err: |
291 | cfg80211_put_dev(dev); | 291 | cfg80211_put_dev(dev); |
292 | return -ENOBUFS; | 292 | return -ENOBUFS; |
293 | } | 293 | } |
294 | 294 | ||
295 | static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { | 295 | static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { |
296 | [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 }, | 296 | [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 }, |
297 | [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 }, | 297 | [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 }, |
298 | [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 }, | 298 | [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 }, |
299 | [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 }, | 299 | [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 }, |
300 | [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 }, | 300 | [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 }, |
301 | }; | 301 | }; |
302 | 302 | ||
303 | static int parse_txq_params(struct nlattr *tb[], | 303 | static int parse_txq_params(struct nlattr *tb[], |
304 | struct ieee80211_txq_params *txq_params) | 304 | struct ieee80211_txq_params *txq_params) |
305 | { | 305 | { |
306 | if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || | 306 | if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || |
307 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || | 307 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || |
308 | !tb[NL80211_TXQ_ATTR_AIFS]) | 308 | !tb[NL80211_TXQ_ATTR_AIFS]) |
309 | return -EINVAL; | 309 | return -EINVAL; |
310 | 310 | ||
311 | txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); | 311 | txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); |
312 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); | 312 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); |
313 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); | 313 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); |
314 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); | 314 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); |
315 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); | 315 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); |
316 | 316 | ||
317 | return 0; | 317 | return 0; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | 320 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) |
321 | { | 321 | { |
322 | struct cfg80211_registered_device *rdev; | 322 | struct cfg80211_registered_device *rdev; |
323 | int result = 0, rem_txq_params = 0; | 323 | int result = 0, rem_txq_params = 0; |
324 | struct nlattr *nl_txq_params; | 324 | struct nlattr *nl_txq_params; |
325 | 325 | ||
326 | rdev = cfg80211_get_dev_from_info(info); | 326 | rdev = cfg80211_get_dev_from_info(info); |
327 | if (IS_ERR(rdev)) | 327 | if (IS_ERR(rdev)) |
328 | return PTR_ERR(rdev); | 328 | return PTR_ERR(rdev); |
329 | 329 | ||
330 | if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { | 330 | if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { |
331 | result = cfg80211_dev_rename( | 331 | result = cfg80211_dev_rename( |
332 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); | 332 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); |
333 | if (result) | 333 | if (result) |
334 | goto bad_res; | 334 | goto bad_res; |
335 | } | 335 | } |
336 | 336 | ||
337 | if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { | 337 | if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { |
338 | struct ieee80211_txq_params txq_params; | 338 | struct ieee80211_txq_params txq_params; |
339 | struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; | 339 | struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; |
340 | 340 | ||
341 | if (!rdev->ops->set_txq_params) { | 341 | if (!rdev->ops->set_txq_params) { |
342 | result = -EOPNOTSUPP; | 342 | result = -EOPNOTSUPP; |
343 | goto bad_res; | 343 | goto bad_res; |
344 | } | 344 | } |
345 | 345 | ||
346 | nla_for_each_nested(nl_txq_params, | 346 | nla_for_each_nested(nl_txq_params, |
347 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | 347 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], |
348 | rem_txq_params) { | 348 | rem_txq_params) { |
349 | nla_parse(tb, NL80211_TXQ_ATTR_MAX, | 349 | nla_parse(tb, NL80211_TXQ_ATTR_MAX, |
350 | nla_data(nl_txq_params), | 350 | nla_data(nl_txq_params), |
351 | nla_len(nl_txq_params), | 351 | nla_len(nl_txq_params), |
352 | txq_params_policy); | 352 | txq_params_policy); |
353 | result = parse_txq_params(tb, &txq_params); | 353 | result = parse_txq_params(tb, &txq_params); |
354 | if (result) | 354 | if (result) |
355 | goto bad_res; | 355 | goto bad_res; |
356 | 356 | ||
357 | result = rdev->ops->set_txq_params(&rdev->wiphy, | 357 | result = rdev->ops->set_txq_params(&rdev->wiphy, |
358 | &txq_params); | 358 | &txq_params); |
359 | if (result) | 359 | if (result) |
360 | goto bad_res; | 360 | goto bad_res; |
361 | } | 361 | } |
362 | } | 362 | } |
363 | 363 | ||
364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
365 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 365 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
366 | struct ieee80211_channel *chan; | 366 | struct ieee80211_channel *chan; |
367 | struct ieee80211_sta_ht_cap *ht_cap; | 367 | struct ieee80211_sta_ht_cap *ht_cap; |
368 | u32 freq, sec_freq; | 368 | u32 freq, sec_freq; |
369 | 369 | ||
370 | if (!rdev->ops->set_channel) { | 370 | if (!rdev->ops->set_channel) { |
371 | result = -EOPNOTSUPP; | 371 | result = -EOPNOTSUPP; |
372 | goto bad_res; | 372 | goto bad_res; |
373 | } | 373 | } |
374 | 374 | ||
375 | result = -EINVAL; | 375 | result = -EINVAL; |
376 | 376 | ||
377 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 377 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
378 | channel_type = nla_get_u32(info->attrs[ | 378 | channel_type = nla_get_u32(info->attrs[ |
379 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | 379 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); |
380 | if (channel_type != NL80211_CHAN_NO_HT && | 380 | if (channel_type != NL80211_CHAN_NO_HT && |
381 | channel_type != NL80211_CHAN_HT20 && | 381 | channel_type != NL80211_CHAN_HT20 && |
382 | channel_type != NL80211_CHAN_HT40PLUS && | 382 | channel_type != NL80211_CHAN_HT40PLUS && |
383 | channel_type != NL80211_CHAN_HT40MINUS) | 383 | channel_type != NL80211_CHAN_HT40MINUS) |
384 | goto bad_res; | 384 | goto bad_res; |
385 | } | 385 | } |
386 | 386 | ||
387 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 387 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
388 | chan = ieee80211_get_channel(&rdev->wiphy, freq); | 388 | chan = ieee80211_get_channel(&rdev->wiphy, freq); |
389 | 389 | ||
390 | /* Primary channel not allowed */ | 390 | /* Primary channel not allowed */ |
391 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | 391 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) |
392 | goto bad_res; | 392 | goto bad_res; |
393 | 393 | ||
394 | if (channel_type == NL80211_CHAN_HT40MINUS) | 394 | if (channel_type == NL80211_CHAN_HT40MINUS) |
395 | sec_freq = freq - 20; | 395 | sec_freq = freq - 20; |
396 | else if (channel_type == NL80211_CHAN_HT40PLUS) | 396 | else if (channel_type == NL80211_CHAN_HT40PLUS) |
397 | sec_freq = freq + 20; | 397 | sec_freq = freq + 20; |
398 | else | 398 | else |
399 | sec_freq = 0; | 399 | sec_freq = 0; |
400 | 400 | ||
401 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | 401 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; |
402 | 402 | ||
403 | /* no HT capabilities */ | 403 | /* no HT capabilities */ |
404 | if (channel_type != NL80211_CHAN_NO_HT && | 404 | if (channel_type != NL80211_CHAN_NO_HT && |
405 | !ht_cap->ht_supported) | 405 | !ht_cap->ht_supported) |
406 | goto bad_res; | 406 | goto bad_res; |
407 | 407 | ||
408 | if (sec_freq) { | 408 | if (sec_freq) { |
409 | struct ieee80211_channel *schan; | 409 | struct ieee80211_channel *schan; |
410 | 410 | ||
411 | /* no 40 MHz capabilities */ | 411 | /* no 40 MHz capabilities */ |
412 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | 412 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || |
413 | (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) | 413 | (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) |
414 | goto bad_res; | 414 | goto bad_res; |
415 | 415 | ||
416 | schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); | 416 | schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); |
417 | 417 | ||
418 | /* Secondary channel not allowed */ | 418 | /* Secondary channel not allowed */ |
419 | if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) | 419 | if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) |
420 | goto bad_res; | 420 | goto bad_res; |
421 | } | 421 | } |
422 | 422 | ||
423 | result = rdev->ops->set_channel(&rdev->wiphy, chan, | 423 | result = rdev->ops->set_channel(&rdev->wiphy, chan, |
424 | channel_type); | 424 | channel_type); |
425 | if (result) | 425 | if (result) |
426 | goto bad_res; | 426 | goto bad_res; |
427 | } | 427 | } |
428 | 428 | ||
429 | 429 | ||
430 | bad_res: | 430 | bad_res: |
431 | cfg80211_put_dev(rdev); | 431 | cfg80211_put_dev(rdev); |
432 | return result; | 432 | return result; |
433 | } | 433 | } |
434 | 434 | ||
435 | 435 | ||
436 | static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 436 | static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
437 | struct net_device *dev) | 437 | struct net_device *dev) |
438 | { | 438 | { |
439 | void *hdr; | 439 | void *hdr; |
440 | 440 | ||
441 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE); | 441 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE); |
442 | if (!hdr) | 442 | if (!hdr) |
443 | return -1; | 443 | return -1; |
444 | 444 | ||
445 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 445 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
446 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); | 446 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); |
447 | NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); | 447 | NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); |
448 | return genlmsg_end(msg, hdr); | 448 | return genlmsg_end(msg, hdr); |
449 | 449 | ||
450 | nla_put_failure: | 450 | nla_put_failure: |
451 | genlmsg_cancel(msg, hdr); | 451 | genlmsg_cancel(msg, hdr); |
452 | return -EMSGSIZE; | 452 | return -EMSGSIZE; |
453 | } | 453 | } |
454 | 454 | ||
455 | static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb) | 455 | static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb) |
456 | { | 456 | { |
457 | int wp_idx = 0; | 457 | int wp_idx = 0; |
458 | int if_idx = 0; | 458 | int if_idx = 0; |
459 | int wp_start = cb->args[0]; | 459 | int wp_start = cb->args[0]; |
460 | int if_start = cb->args[1]; | 460 | int if_start = cb->args[1]; |
461 | struct cfg80211_registered_device *dev; | 461 | struct cfg80211_registered_device *dev; |
462 | struct wireless_dev *wdev; | 462 | struct wireless_dev *wdev; |
463 | 463 | ||
464 | mutex_lock(&cfg80211_drv_mutex); | 464 | mutex_lock(&cfg80211_drv_mutex); |
465 | list_for_each_entry(dev, &cfg80211_drv_list, list) { | 465 | list_for_each_entry(dev, &cfg80211_drv_list, list) { |
466 | if (wp_idx < wp_start) { | 466 | if (wp_idx < wp_start) { |
467 | wp_idx++; | 467 | wp_idx++; |
468 | continue; | 468 | continue; |
469 | } | 469 | } |
470 | if_idx = 0; | 470 | if_idx = 0; |
471 | 471 | ||
472 | mutex_lock(&dev->devlist_mtx); | 472 | mutex_lock(&dev->devlist_mtx); |
473 | list_for_each_entry(wdev, &dev->netdev_list, list) { | 473 | list_for_each_entry(wdev, &dev->netdev_list, list) { |
474 | if (if_idx < if_start) { | 474 | if (if_idx < if_start) { |
475 | if_idx++; | 475 | if_idx++; |
476 | continue; | 476 | continue; |
477 | } | 477 | } |
478 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, | 478 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, |
479 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 479 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
480 | wdev->netdev) < 0) { | 480 | wdev->netdev) < 0) { |
481 | mutex_unlock(&dev->devlist_mtx); | 481 | mutex_unlock(&dev->devlist_mtx); |
482 | goto out; | 482 | goto out; |
483 | } | 483 | } |
484 | if_idx++; | 484 | if_idx++; |
485 | } | 485 | } |
486 | mutex_unlock(&dev->devlist_mtx); | 486 | mutex_unlock(&dev->devlist_mtx); |
487 | 487 | ||
488 | wp_idx++; | 488 | wp_idx++; |
489 | } | 489 | } |
490 | out: | 490 | out: |
491 | mutex_unlock(&cfg80211_drv_mutex); | 491 | mutex_unlock(&cfg80211_drv_mutex); |
492 | 492 | ||
493 | cb->args[0] = wp_idx; | 493 | cb->args[0] = wp_idx; |
494 | cb->args[1] = if_idx; | 494 | cb->args[1] = if_idx; |
495 | 495 | ||
496 | return skb->len; | 496 | return skb->len; |
497 | } | 497 | } |
498 | 498 | ||
499 | static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) | 499 | static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) |
500 | { | 500 | { |
501 | struct sk_buff *msg; | 501 | struct sk_buff *msg; |
502 | struct cfg80211_registered_device *dev; | 502 | struct cfg80211_registered_device *dev; |
503 | struct net_device *netdev; | 503 | struct net_device *netdev; |
504 | int err; | 504 | int err; |
505 | 505 | ||
506 | err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev); | 506 | err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev); |
507 | if (err) | 507 | if (err) |
508 | return err; | 508 | return err; |
509 | 509 | ||
510 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 510 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
511 | if (!msg) | 511 | if (!msg) |
512 | goto out_err; | 512 | goto out_err; |
513 | 513 | ||
514 | if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0) | 514 | if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0) |
515 | goto out_free; | 515 | goto out_free; |
516 | 516 | ||
517 | dev_put(netdev); | 517 | dev_put(netdev); |
518 | cfg80211_put_dev(dev); | 518 | cfg80211_put_dev(dev); |
519 | 519 | ||
520 | return genlmsg_unicast(msg, info->snd_pid); | 520 | return genlmsg_unicast(msg, info->snd_pid); |
521 | 521 | ||
522 | out_free: | 522 | out_free: |
523 | nlmsg_free(msg); | 523 | nlmsg_free(msg); |
524 | out_err: | 524 | out_err: |
525 | dev_put(netdev); | 525 | dev_put(netdev); |
526 | cfg80211_put_dev(dev); | 526 | cfg80211_put_dev(dev); |
527 | return -ENOBUFS; | 527 | return -ENOBUFS; |
528 | } | 528 | } |
529 | 529 | ||
530 | static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { | 530 | static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { |
531 | [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG }, | 531 | [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG }, |
532 | [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG }, | 532 | [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG }, |
533 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, | 533 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, |
534 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, | 534 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, |
535 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, | 535 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, |
536 | }; | 536 | }; |
537 | 537 | ||
538 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) | 538 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) |
539 | { | 539 | { |
540 | struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1]; | 540 | struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1]; |
541 | int flag; | 541 | int flag; |
542 | 542 | ||
543 | *mntrflags = 0; | 543 | *mntrflags = 0; |
544 | 544 | ||
545 | if (!nla) | 545 | if (!nla) |
546 | return -EINVAL; | 546 | return -EINVAL; |
547 | 547 | ||
548 | if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX, | 548 | if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX, |
549 | nla, mntr_flags_policy)) | 549 | nla, mntr_flags_policy)) |
550 | return -EINVAL; | 550 | return -EINVAL; |
551 | 551 | ||
552 | for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++) | 552 | for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++) |
553 | if (flags[flag]) | 553 | if (flags[flag]) |
554 | *mntrflags |= (1<<flag); | 554 | *mntrflags |= (1<<flag); |
555 | 555 | ||
556 | return 0; | 556 | return 0; |
557 | } | 557 | } |
558 | 558 | ||
559 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | 559 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) |
560 | { | 560 | { |
561 | struct cfg80211_registered_device *drv; | 561 | struct cfg80211_registered_device *drv; |
562 | struct vif_params params; | 562 | struct vif_params params; |
563 | int err, ifindex; | 563 | int err, ifindex; |
564 | enum nl80211_iftype type; | 564 | enum nl80211_iftype type; |
565 | struct net_device *dev; | 565 | struct net_device *dev; |
566 | u32 _flags, *flags = NULL; | 566 | u32 _flags, *flags = NULL; |
567 | 567 | ||
568 | memset(¶ms, 0, sizeof(params)); | 568 | memset(¶ms, 0, sizeof(params)); |
569 | 569 | ||
570 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 570 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
571 | if (err) | 571 | if (err) |
572 | return err; | 572 | return err; |
573 | ifindex = dev->ifindex; | 573 | ifindex = dev->ifindex; |
574 | type = dev->ieee80211_ptr->iftype; | 574 | type = dev->ieee80211_ptr->iftype; |
575 | dev_put(dev); | 575 | dev_put(dev); |
576 | 576 | ||
577 | err = -EINVAL; | 577 | err = -EINVAL; |
578 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | 578 | if (info->attrs[NL80211_ATTR_IFTYPE]) { |
579 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | 579 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); |
580 | if (type > NL80211_IFTYPE_MAX) | 580 | if (type > NL80211_IFTYPE_MAX) |
581 | goto unlock; | 581 | goto unlock; |
582 | } | 582 | } |
583 | 583 | ||
584 | if (!drv->ops->change_virtual_intf || | 584 | if (!drv->ops->change_virtual_intf || |
585 | !(drv->wiphy.interface_modes & (1 << type))) { | 585 | !(drv->wiphy.interface_modes & (1 << type))) { |
586 | err = -EOPNOTSUPP; | 586 | err = -EOPNOTSUPP; |
587 | goto unlock; | 587 | goto unlock; |
588 | } | 588 | } |
589 | 589 | ||
590 | if (info->attrs[NL80211_ATTR_MESH_ID]) { | 590 | if (info->attrs[NL80211_ATTR_MESH_ID]) { |
591 | if (type != NL80211_IFTYPE_MESH_POINT) { | 591 | if (type != NL80211_IFTYPE_MESH_POINT) { |
592 | err = -EINVAL; | 592 | err = -EINVAL; |
593 | goto unlock; | 593 | goto unlock; |
594 | } | 594 | } |
595 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 595 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
596 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 596 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
597 | } | 597 | } |
598 | 598 | ||
599 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | 599 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { |
600 | if (type != NL80211_IFTYPE_MONITOR) { | 600 | if (type != NL80211_IFTYPE_MONITOR) { |
601 | err = -EINVAL; | 601 | err = -EINVAL; |
602 | goto unlock; | 602 | goto unlock; |
603 | } | 603 | } |
604 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | 604 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], |
605 | &_flags); | 605 | &_flags); |
606 | if (!err) | 606 | if (!err) |
607 | flags = &_flags; | 607 | flags = &_flags; |
608 | } | 608 | } |
609 | rtnl_lock(); | 609 | rtnl_lock(); |
610 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, | 610 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, |
611 | type, flags, ¶ms); | 611 | type, flags, ¶ms); |
612 | 612 | ||
613 | dev = __dev_get_by_index(&init_net, ifindex); | 613 | dev = __dev_get_by_index(&init_net, ifindex); |
614 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); | 614 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); |
615 | 615 | ||
616 | rtnl_unlock(); | 616 | rtnl_unlock(); |
617 | 617 | ||
618 | unlock: | 618 | unlock: |
619 | cfg80211_put_dev(drv); | 619 | cfg80211_put_dev(drv); |
620 | return err; | 620 | return err; |
621 | } | 621 | } |
622 | 622 | ||
623 | static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | 623 | static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) |
624 | { | 624 | { |
625 | struct cfg80211_registered_device *drv; | 625 | struct cfg80211_registered_device *drv; |
626 | struct vif_params params; | 626 | struct vif_params params; |
627 | int err; | 627 | int err; |
628 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; | 628 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; |
629 | u32 flags; | 629 | u32 flags; |
630 | 630 | ||
631 | memset(¶ms, 0, sizeof(params)); | 631 | memset(¶ms, 0, sizeof(params)); |
632 | 632 | ||
633 | if (!info->attrs[NL80211_ATTR_IFNAME]) | 633 | if (!info->attrs[NL80211_ATTR_IFNAME]) |
634 | return -EINVAL; | 634 | return -EINVAL; |
635 | 635 | ||
636 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | 636 | if (info->attrs[NL80211_ATTR_IFTYPE]) { |
637 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | 637 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); |
638 | if (type > NL80211_IFTYPE_MAX) | 638 | if (type > NL80211_IFTYPE_MAX) |
639 | return -EINVAL; | 639 | return -EINVAL; |
640 | } | 640 | } |
641 | 641 | ||
642 | drv = cfg80211_get_dev_from_info(info); | 642 | drv = cfg80211_get_dev_from_info(info); |
643 | if (IS_ERR(drv)) | 643 | if (IS_ERR(drv)) |
644 | return PTR_ERR(drv); | 644 | return PTR_ERR(drv); |
645 | 645 | ||
646 | if (!drv->ops->add_virtual_intf || | 646 | if (!drv->ops->add_virtual_intf || |
647 | !(drv->wiphy.interface_modes & (1 << type))) { | 647 | !(drv->wiphy.interface_modes & (1 << type))) { |
648 | err = -EOPNOTSUPP; | 648 | err = -EOPNOTSUPP; |
649 | goto unlock; | 649 | goto unlock; |
650 | } | 650 | } |
651 | 651 | ||
652 | if (type == NL80211_IFTYPE_MESH_POINT && | 652 | if (type == NL80211_IFTYPE_MESH_POINT && |
653 | info->attrs[NL80211_ATTR_MESH_ID]) { | 653 | info->attrs[NL80211_ATTR_MESH_ID]) { |
654 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 654 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
655 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 655 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
656 | } | 656 | } |
657 | 657 | ||
658 | rtnl_lock(); | 658 | rtnl_lock(); |
659 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 659 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
660 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 660 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
661 | &flags); | 661 | &flags); |
662 | err = drv->ops->add_virtual_intf(&drv->wiphy, | 662 | err = drv->ops->add_virtual_intf(&drv->wiphy, |
663 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 663 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
664 | type, err ? NULL : &flags, ¶ms); | 664 | type, err ? NULL : &flags, ¶ms); |
665 | rtnl_unlock(); | 665 | rtnl_unlock(); |
666 | 666 | ||
667 | 667 | ||
668 | unlock: | 668 | unlock: |
669 | cfg80211_put_dev(drv); | 669 | cfg80211_put_dev(drv); |
670 | return err; | 670 | return err; |
671 | } | 671 | } |
672 | 672 | ||
673 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | 673 | static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) |
674 | { | 674 | { |
675 | struct cfg80211_registered_device *drv; | 675 | struct cfg80211_registered_device *drv; |
676 | int ifindex, err; | 676 | int ifindex, err; |
677 | struct net_device *dev; | 677 | struct net_device *dev; |
678 | 678 | ||
679 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 679 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
680 | if (err) | 680 | if (err) |
681 | return err; | 681 | return err; |
682 | ifindex = dev->ifindex; | 682 | ifindex = dev->ifindex; |
683 | dev_put(dev); | 683 | dev_put(dev); |
684 | 684 | ||
685 | if (!drv->ops->del_virtual_intf) { | 685 | if (!drv->ops->del_virtual_intf) { |
686 | err = -EOPNOTSUPP; | 686 | err = -EOPNOTSUPP; |
687 | goto out; | 687 | goto out; |
688 | } | 688 | } |
689 | 689 | ||
690 | rtnl_lock(); | 690 | rtnl_lock(); |
691 | err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); | 691 | err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); |
692 | rtnl_unlock(); | 692 | rtnl_unlock(); |
693 | 693 | ||
694 | out: | 694 | out: |
695 | cfg80211_put_dev(drv); | 695 | cfg80211_put_dev(drv); |
696 | return err; | 696 | return err; |
697 | } | 697 | } |
698 | 698 | ||
699 | struct get_key_cookie { | 699 | struct get_key_cookie { |
700 | struct sk_buff *msg; | 700 | struct sk_buff *msg; |
701 | int error; | 701 | int error; |
702 | }; | 702 | }; |
703 | 703 | ||
704 | static void get_key_callback(void *c, struct key_params *params) | 704 | static void get_key_callback(void *c, struct key_params *params) |
705 | { | 705 | { |
706 | struct get_key_cookie *cookie = c; | 706 | struct get_key_cookie *cookie = c; |
707 | 707 | ||
708 | if (params->key) | 708 | if (params->key) |
709 | NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA, | 709 | NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA, |
710 | params->key_len, params->key); | 710 | params->key_len, params->key); |
711 | 711 | ||
712 | if (params->seq) | 712 | if (params->seq) |
713 | NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ, | 713 | NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ, |
714 | params->seq_len, params->seq); | 714 | params->seq_len, params->seq); |
715 | 715 | ||
716 | if (params->cipher) | 716 | if (params->cipher) |
717 | NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, | 717 | NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, |
718 | params->cipher); | 718 | params->cipher); |
719 | 719 | ||
720 | return; | 720 | return; |
721 | nla_put_failure: | 721 | nla_put_failure: |
722 | cookie->error = 1; | 722 | cookie->error = 1; |
723 | } | 723 | } |
724 | 724 | ||
725 | static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | 725 | static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) |
726 | { | 726 | { |
727 | struct cfg80211_registered_device *drv; | 727 | struct cfg80211_registered_device *drv; |
728 | int err; | 728 | int err; |
729 | struct net_device *dev; | 729 | struct net_device *dev; |
730 | u8 key_idx = 0; | 730 | u8 key_idx = 0; |
731 | u8 *mac_addr = NULL; | 731 | u8 *mac_addr = NULL; |
732 | struct get_key_cookie cookie = { | 732 | struct get_key_cookie cookie = { |
733 | .error = 0, | 733 | .error = 0, |
734 | }; | 734 | }; |
735 | void *hdr; | 735 | void *hdr; |
736 | struct sk_buff *msg; | 736 | struct sk_buff *msg; |
737 | 737 | ||
738 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 738 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
739 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 739 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
740 | 740 | ||
741 | if (key_idx > 3) | 741 | if (key_idx > 5) |
742 | return -EINVAL; | 742 | return -EINVAL; |
743 | 743 | ||
744 | if (info->attrs[NL80211_ATTR_MAC]) | 744 | if (info->attrs[NL80211_ATTR_MAC]) |
745 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 745 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
746 | 746 | ||
747 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 747 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
748 | if (err) | 748 | if (err) |
749 | return err; | 749 | return err; |
750 | 750 | ||
751 | if (!drv->ops->get_key) { | 751 | if (!drv->ops->get_key) { |
752 | err = -EOPNOTSUPP; | 752 | err = -EOPNOTSUPP; |
753 | goto out; | 753 | goto out; |
754 | } | 754 | } |
755 | 755 | ||
756 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 756 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
757 | if (!msg) { | 757 | if (!msg) { |
758 | err = -ENOMEM; | 758 | err = -ENOMEM; |
759 | goto out; | 759 | goto out; |
760 | } | 760 | } |
761 | 761 | ||
762 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 762 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
763 | NL80211_CMD_NEW_KEY); | 763 | NL80211_CMD_NEW_KEY); |
764 | 764 | ||
765 | if (IS_ERR(hdr)) { | 765 | if (IS_ERR(hdr)) { |
766 | err = PTR_ERR(hdr); | 766 | err = PTR_ERR(hdr); |
767 | goto out; | 767 | goto out; |
768 | } | 768 | } |
769 | 769 | ||
770 | cookie.msg = msg; | 770 | cookie.msg = msg; |
771 | 771 | ||
772 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 772 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
773 | NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); | 773 | NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); |
774 | if (mac_addr) | 774 | if (mac_addr) |
775 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); | 775 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); |
776 | 776 | ||
777 | rtnl_lock(); | 777 | rtnl_lock(); |
778 | err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, | 778 | err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, |
779 | &cookie, get_key_callback); | 779 | &cookie, get_key_callback); |
780 | rtnl_unlock(); | 780 | rtnl_unlock(); |
781 | 781 | ||
782 | if (err) | 782 | if (err) |
783 | goto out; | 783 | goto out; |
784 | 784 | ||
785 | if (cookie.error) | 785 | if (cookie.error) |
786 | goto nla_put_failure; | 786 | goto nla_put_failure; |
787 | 787 | ||
788 | genlmsg_end(msg, hdr); | 788 | genlmsg_end(msg, hdr); |
789 | err = genlmsg_unicast(msg, info->snd_pid); | 789 | err = genlmsg_unicast(msg, info->snd_pid); |
790 | goto out; | 790 | goto out; |
791 | 791 | ||
792 | nla_put_failure: | 792 | nla_put_failure: |
793 | err = -ENOBUFS; | 793 | err = -ENOBUFS; |
794 | nlmsg_free(msg); | 794 | nlmsg_free(msg); |
795 | out: | 795 | out: |
796 | cfg80211_put_dev(drv); | 796 | cfg80211_put_dev(drv); |
797 | dev_put(dev); | 797 | dev_put(dev); |
798 | return err; | 798 | return err; |
799 | } | 799 | } |
800 | 800 | ||
801 | static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | 801 | static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) |
802 | { | 802 | { |
803 | struct cfg80211_registered_device *drv; | 803 | struct cfg80211_registered_device *drv; |
804 | int err; | 804 | int err; |
805 | struct net_device *dev; | 805 | struct net_device *dev; |
806 | u8 key_idx; | 806 | u8 key_idx; |
807 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, | ||
808 | u8 key_index); | ||
807 | 809 | ||
808 | if (!info->attrs[NL80211_ATTR_KEY_IDX]) | 810 | if (!info->attrs[NL80211_ATTR_KEY_IDX]) |
809 | return -EINVAL; | 811 | return -EINVAL; |
810 | 812 | ||
811 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 813 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
812 | 814 | ||
813 | if (key_idx > 3) | 815 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) { |
816 | if (key_idx < 4 || key_idx > 5) | ||
817 | return -EINVAL; | ||
818 | } else if (key_idx > 3) | ||
814 | return -EINVAL; | 819 | return -EINVAL; |
815 | 820 | ||
816 | /* currently only support setting default key */ | 821 | /* currently only support setting default key */ |
817 | if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) | 822 | if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] && |
823 | !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) | ||
818 | return -EINVAL; | 824 | return -EINVAL; |
819 | 825 | ||
820 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 826 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
821 | if (err) | 827 | if (err) |
822 | return err; | 828 | return err; |
823 | 829 | ||
824 | if (!drv->ops->set_default_key) { | 830 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) |
831 | func = drv->ops->set_default_key; | ||
832 | else | ||
833 | func = drv->ops->set_default_mgmt_key; | ||
834 | |||
835 | if (!func) { | ||
825 | err = -EOPNOTSUPP; | 836 | err = -EOPNOTSUPP; |
826 | goto out; | 837 | goto out; |
827 | } | 838 | } |
828 | 839 | ||
829 | rtnl_lock(); | 840 | rtnl_lock(); |
830 | err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx); | 841 | err = func(&drv->wiphy, dev, key_idx); |
831 | rtnl_unlock(); | 842 | rtnl_unlock(); |
832 | 843 | ||
833 | out: | 844 | out: |
834 | cfg80211_put_dev(drv); | 845 | cfg80211_put_dev(drv); |
835 | dev_put(dev); | 846 | dev_put(dev); |
836 | return err; | 847 | return err; |
837 | } | 848 | } |
838 | 849 | ||
839 | static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | 850 | static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) |
840 | { | 851 | { |
841 | struct cfg80211_registered_device *drv; | 852 | struct cfg80211_registered_device *drv; |
842 | int err; | 853 | int err; |
843 | struct net_device *dev; | 854 | struct net_device *dev; |
844 | struct key_params params; | 855 | struct key_params params; |
845 | u8 key_idx = 0; | 856 | u8 key_idx = 0; |
846 | u8 *mac_addr = NULL; | 857 | u8 *mac_addr = NULL; |
847 | 858 | ||
848 | memset(¶ms, 0, sizeof(params)); | 859 | memset(¶ms, 0, sizeof(params)); |
849 | 860 | ||
850 | if (!info->attrs[NL80211_ATTR_KEY_CIPHER]) | 861 | if (!info->attrs[NL80211_ATTR_KEY_CIPHER]) |
851 | return -EINVAL; | 862 | return -EINVAL; |
852 | 863 | ||
853 | if (info->attrs[NL80211_ATTR_KEY_DATA]) { | 864 | if (info->attrs[NL80211_ATTR_KEY_DATA]) { |
854 | params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]); | 865 | params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]); |
855 | params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); | 866 | params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); |
856 | } | 867 | } |
857 | 868 | ||
858 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 869 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
859 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 870 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
860 | 871 | ||
861 | params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]); | 872 | params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]); |
862 | 873 | ||
863 | if (info->attrs[NL80211_ATTR_MAC]) | 874 | if (info->attrs[NL80211_ATTR_MAC]) |
864 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 875 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
865 | 876 | ||
866 | if (key_idx > 3) | 877 | if (key_idx > 5) |
867 | return -EINVAL; | 878 | return -EINVAL; |
868 | 879 | ||
869 | /* | 880 | /* |
870 | * Disallow pairwise keys with non-zero index unless it's WEP | 881 | * Disallow pairwise keys with non-zero index unless it's WEP |
871 | * (because current deployments use pairwise WEP keys with | 882 | * (because current deployments use pairwise WEP keys with |
872 | * non-zero indizes but 802.11i clearly specifies to use zero) | 883 | * non-zero indizes but 802.11i clearly specifies to use zero) |
873 | */ | 884 | */ |
874 | if (mac_addr && key_idx && | 885 | if (mac_addr && key_idx && |
875 | params.cipher != WLAN_CIPHER_SUITE_WEP40 && | 886 | params.cipher != WLAN_CIPHER_SUITE_WEP40 && |
876 | params.cipher != WLAN_CIPHER_SUITE_WEP104) | 887 | params.cipher != WLAN_CIPHER_SUITE_WEP104) |
877 | return -EINVAL; | 888 | return -EINVAL; |
878 | 889 | ||
879 | /* TODO: add definitions for the lengths to linux/ieee80211.h */ | 890 | /* TODO: add definitions for the lengths to linux/ieee80211.h */ |
880 | switch (params.cipher) { | 891 | switch (params.cipher) { |
881 | case WLAN_CIPHER_SUITE_WEP40: | 892 | case WLAN_CIPHER_SUITE_WEP40: |
882 | if (params.key_len != 5) | 893 | if (params.key_len != 5) |
883 | return -EINVAL; | 894 | return -EINVAL; |
884 | break; | 895 | break; |
885 | case WLAN_CIPHER_SUITE_TKIP: | 896 | case WLAN_CIPHER_SUITE_TKIP: |
886 | if (params.key_len != 32) | 897 | if (params.key_len != 32) |
887 | return -EINVAL; | 898 | return -EINVAL; |
888 | break; | 899 | break; |
889 | case WLAN_CIPHER_SUITE_CCMP: | 900 | case WLAN_CIPHER_SUITE_CCMP: |
890 | if (params.key_len != 16) | 901 | if (params.key_len != 16) |
891 | return -EINVAL; | 902 | return -EINVAL; |
892 | break; | 903 | break; |
893 | case WLAN_CIPHER_SUITE_WEP104: | 904 | case WLAN_CIPHER_SUITE_WEP104: |
894 | if (params.key_len != 13) | 905 | if (params.key_len != 13) |
895 | return -EINVAL; | 906 | return -EINVAL; |
896 | break; | 907 | break; |
908 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
909 | if (params.key_len != 16) | ||
910 | return -EINVAL; | ||
911 | break; | ||
897 | default: | 912 | default: |
898 | return -EINVAL; | 913 | return -EINVAL; |
899 | } | 914 | } |
900 | 915 | ||
901 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 916 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
902 | if (err) | 917 | if (err) |
903 | return err; | 918 | return err; |
904 | 919 | ||
905 | if (!drv->ops->add_key) { | 920 | if (!drv->ops->add_key) { |
906 | err = -EOPNOTSUPP; | 921 | err = -EOPNOTSUPP; |
907 | goto out; | 922 | goto out; |
908 | } | 923 | } |
909 | 924 | ||
910 | rtnl_lock(); | 925 | rtnl_lock(); |
911 | err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms); | 926 | err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms); |
912 | rtnl_unlock(); | 927 | rtnl_unlock(); |
913 | 928 | ||
914 | out: | 929 | out: |
915 | cfg80211_put_dev(drv); | 930 | cfg80211_put_dev(drv); |
916 | dev_put(dev); | 931 | dev_put(dev); |
917 | return err; | 932 | return err; |
918 | } | 933 | } |
919 | 934 | ||
920 | static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | 935 | static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) |
921 | { | 936 | { |
922 | struct cfg80211_registered_device *drv; | 937 | struct cfg80211_registered_device *drv; |
923 | int err; | 938 | int err; |
924 | struct net_device *dev; | 939 | struct net_device *dev; |
925 | u8 key_idx = 0; | 940 | u8 key_idx = 0; |
926 | u8 *mac_addr = NULL; | 941 | u8 *mac_addr = NULL; |
927 | 942 | ||
928 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 943 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
929 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 944 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
930 | 945 | ||
931 | if (key_idx > 3) | 946 | if (key_idx > 5) |
932 | return -EINVAL; | 947 | return -EINVAL; |
933 | 948 | ||
934 | if (info->attrs[NL80211_ATTR_MAC]) | 949 | if (info->attrs[NL80211_ATTR_MAC]) |
935 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 950 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
936 | 951 | ||
937 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 952 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
938 | if (err) | 953 | if (err) |
939 | return err; | 954 | return err; |
940 | 955 | ||
941 | if (!drv->ops->del_key) { | 956 | if (!drv->ops->del_key) { |
942 | err = -EOPNOTSUPP; | 957 | err = -EOPNOTSUPP; |
943 | goto out; | 958 | goto out; |
944 | } | 959 | } |
945 | 960 | ||
946 | rtnl_lock(); | 961 | rtnl_lock(); |
947 | err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); | 962 | err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); |
948 | rtnl_unlock(); | 963 | rtnl_unlock(); |
949 | 964 | ||
950 | out: | 965 | out: |
951 | cfg80211_put_dev(drv); | 966 | cfg80211_put_dev(drv); |
952 | dev_put(dev); | 967 | dev_put(dev); |
953 | return err; | 968 | return err; |
954 | } | 969 | } |
955 | 970 | ||
956 | static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | 971 | static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) |
957 | { | 972 | { |
958 | int (*call)(struct wiphy *wiphy, struct net_device *dev, | 973 | int (*call)(struct wiphy *wiphy, struct net_device *dev, |
959 | struct beacon_parameters *info); | 974 | struct beacon_parameters *info); |
960 | struct cfg80211_registered_device *drv; | 975 | struct cfg80211_registered_device *drv; |
961 | int err; | 976 | int err; |
962 | struct net_device *dev; | 977 | struct net_device *dev; |
963 | struct beacon_parameters params; | 978 | struct beacon_parameters params; |
964 | int haveinfo = 0; | 979 | int haveinfo = 0; |
965 | 980 | ||
966 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 981 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
967 | if (err) | 982 | if (err) |
968 | return err; | 983 | return err; |
969 | 984 | ||
970 | switch (info->genlhdr->cmd) { | 985 | switch (info->genlhdr->cmd) { |
971 | case NL80211_CMD_NEW_BEACON: | 986 | case NL80211_CMD_NEW_BEACON: |
972 | /* these are required for NEW_BEACON */ | 987 | /* these are required for NEW_BEACON */ |
973 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || | 988 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || |
974 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || | 989 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || |
975 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) { | 990 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) { |
976 | err = -EINVAL; | 991 | err = -EINVAL; |
977 | goto out; | 992 | goto out; |
978 | } | 993 | } |
979 | 994 | ||
980 | call = drv->ops->add_beacon; | 995 | call = drv->ops->add_beacon; |
981 | break; | 996 | break; |
982 | case NL80211_CMD_SET_BEACON: | 997 | case NL80211_CMD_SET_BEACON: |
983 | call = drv->ops->set_beacon; | 998 | call = drv->ops->set_beacon; |
984 | break; | 999 | break; |
985 | default: | 1000 | default: |
986 | WARN_ON(1); | 1001 | WARN_ON(1); |
987 | err = -EOPNOTSUPP; | 1002 | err = -EOPNOTSUPP; |
988 | goto out; | 1003 | goto out; |
989 | } | 1004 | } |
990 | 1005 | ||
991 | if (!call) { | 1006 | if (!call) { |
992 | err = -EOPNOTSUPP; | 1007 | err = -EOPNOTSUPP; |
993 | goto out; | 1008 | goto out; |
994 | } | 1009 | } |
995 | 1010 | ||
996 | memset(¶ms, 0, sizeof(params)); | 1011 | memset(¶ms, 0, sizeof(params)); |
997 | 1012 | ||
998 | if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { | 1013 | if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { |
999 | params.interval = | 1014 | params.interval = |
1000 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); | 1015 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); |
1001 | haveinfo = 1; | 1016 | haveinfo = 1; |
1002 | } | 1017 | } |
1003 | 1018 | ||
1004 | if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) { | 1019 | if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) { |
1005 | params.dtim_period = | 1020 | params.dtim_period = |
1006 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); | 1021 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); |
1007 | haveinfo = 1; | 1022 | haveinfo = 1; |
1008 | } | 1023 | } |
1009 | 1024 | ||
1010 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { | 1025 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { |
1011 | params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); | 1026 | params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); |
1012 | params.head_len = | 1027 | params.head_len = |
1013 | nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); | 1028 | nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); |
1014 | haveinfo = 1; | 1029 | haveinfo = 1; |
1015 | } | 1030 | } |
1016 | 1031 | ||
1017 | if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { | 1032 | if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { |
1018 | params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); | 1033 | params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); |
1019 | params.tail_len = | 1034 | params.tail_len = |
1020 | nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); | 1035 | nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); |
1021 | haveinfo = 1; | 1036 | haveinfo = 1; |
1022 | } | 1037 | } |
1023 | 1038 | ||
1024 | if (!haveinfo) { | 1039 | if (!haveinfo) { |
1025 | err = -EINVAL; | 1040 | err = -EINVAL; |
1026 | goto out; | 1041 | goto out; |
1027 | } | 1042 | } |
1028 | 1043 | ||
1029 | rtnl_lock(); | 1044 | rtnl_lock(); |
1030 | err = call(&drv->wiphy, dev, ¶ms); | 1045 | err = call(&drv->wiphy, dev, ¶ms); |
1031 | rtnl_unlock(); | 1046 | rtnl_unlock(); |
1032 | 1047 | ||
1033 | out: | 1048 | out: |
1034 | cfg80211_put_dev(drv); | 1049 | cfg80211_put_dev(drv); |
1035 | dev_put(dev); | 1050 | dev_put(dev); |
1036 | return err; | 1051 | return err; |
1037 | } | 1052 | } |
1038 | 1053 | ||
1039 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | 1054 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) |
1040 | { | 1055 | { |
1041 | struct cfg80211_registered_device *drv; | 1056 | struct cfg80211_registered_device *drv; |
1042 | int err; | 1057 | int err; |
1043 | struct net_device *dev; | 1058 | struct net_device *dev; |
1044 | 1059 | ||
1045 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1060 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1046 | if (err) | 1061 | if (err) |
1047 | return err; | 1062 | return err; |
1048 | 1063 | ||
1049 | if (!drv->ops->del_beacon) { | 1064 | if (!drv->ops->del_beacon) { |
1050 | err = -EOPNOTSUPP; | 1065 | err = -EOPNOTSUPP; |
1051 | goto out; | 1066 | goto out; |
1052 | } | 1067 | } |
1053 | 1068 | ||
1054 | rtnl_lock(); | 1069 | rtnl_lock(); |
1055 | err = drv->ops->del_beacon(&drv->wiphy, dev); | 1070 | err = drv->ops->del_beacon(&drv->wiphy, dev); |
1056 | rtnl_unlock(); | 1071 | rtnl_unlock(); |
1057 | 1072 | ||
1058 | out: | 1073 | out: |
1059 | cfg80211_put_dev(drv); | 1074 | cfg80211_put_dev(drv); |
1060 | dev_put(dev); | 1075 | dev_put(dev); |
1061 | return err; | 1076 | return err; |
1062 | } | 1077 | } |
1063 | 1078 | ||
1064 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 1079 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { |
1065 | [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG }, | 1080 | [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG }, |
1066 | [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, | 1081 | [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, |
1067 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, | 1082 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, |
1068 | }; | 1083 | }; |
1069 | 1084 | ||
1070 | static int parse_station_flags(struct nlattr *nla, u32 *staflags) | 1085 | static int parse_station_flags(struct nlattr *nla, u32 *staflags) |
1071 | { | 1086 | { |
1072 | struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; | 1087 | struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; |
1073 | int flag; | 1088 | int flag; |
1074 | 1089 | ||
1075 | *staflags = 0; | 1090 | *staflags = 0; |
1076 | 1091 | ||
1077 | if (!nla) | 1092 | if (!nla) |
1078 | return 0; | 1093 | return 0; |
1079 | 1094 | ||
1080 | if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX, | 1095 | if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX, |
1081 | nla, sta_flags_policy)) | 1096 | nla, sta_flags_policy)) |
1082 | return -EINVAL; | 1097 | return -EINVAL; |
1083 | 1098 | ||
1084 | *staflags = STATION_FLAG_CHANGED; | 1099 | *staflags = STATION_FLAG_CHANGED; |
1085 | 1100 | ||
1086 | for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) | 1101 | for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) |
1087 | if (flags[flag]) | 1102 | if (flags[flag]) |
1088 | *staflags |= (1<<flag); | 1103 | *staflags |= (1<<flag); |
1089 | 1104 | ||
1090 | return 0; | 1105 | return 0; |
1091 | } | 1106 | } |
1092 | 1107 | ||
1093 | static u16 nl80211_calculate_bitrate(struct rate_info *rate) | 1108 | static u16 nl80211_calculate_bitrate(struct rate_info *rate) |
1094 | { | 1109 | { |
1095 | int modulation, streams, bitrate; | 1110 | int modulation, streams, bitrate; |
1096 | 1111 | ||
1097 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) | 1112 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) |
1098 | return rate->legacy; | 1113 | return rate->legacy; |
1099 | 1114 | ||
1100 | /* the formula below does only work for MCS values smaller than 32 */ | 1115 | /* the formula below does only work for MCS values smaller than 32 */ |
1101 | if (rate->mcs >= 32) | 1116 | if (rate->mcs >= 32) |
1102 | return 0; | 1117 | return 0; |
1103 | 1118 | ||
1104 | modulation = rate->mcs & 7; | 1119 | modulation = rate->mcs & 7; |
1105 | streams = (rate->mcs >> 3) + 1; | 1120 | streams = (rate->mcs >> 3) + 1; |
1106 | 1121 | ||
1107 | bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? | 1122 | bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? |
1108 | 13500000 : 6500000; | 1123 | 13500000 : 6500000; |
1109 | 1124 | ||
1110 | if (modulation < 4) | 1125 | if (modulation < 4) |
1111 | bitrate *= (modulation + 1); | 1126 | bitrate *= (modulation + 1); |
1112 | else if (modulation == 4) | 1127 | else if (modulation == 4) |
1113 | bitrate *= (modulation + 2); | 1128 | bitrate *= (modulation + 2); |
1114 | else | 1129 | else |
1115 | bitrate *= (modulation + 3); | 1130 | bitrate *= (modulation + 3); |
1116 | 1131 | ||
1117 | bitrate *= streams; | 1132 | bitrate *= streams; |
1118 | 1133 | ||
1119 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) | 1134 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) |
1120 | bitrate = (bitrate / 9) * 10; | 1135 | bitrate = (bitrate / 9) * 10; |
1121 | 1136 | ||
1122 | /* do NOT round down here */ | 1137 | /* do NOT round down here */ |
1123 | return (bitrate + 50000) / 100000; | 1138 | return (bitrate + 50000) / 100000; |
1124 | } | 1139 | } |
1125 | 1140 | ||
1126 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | 1141 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, |
1127 | int flags, struct net_device *dev, | 1142 | int flags, struct net_device *dev, |
1128 | u8 *mac_addr, struct station_info *sinfo) | 1143 | u8 *mac_addr, struct station_info *sinfo) |
1129 | { | 1144 | { |
1130 | void *hdr; | 1145 | void *hdr; |
1131 | struct nlattr *sinfoattr, *txrate; | 1146 | struct nlattr *sinfoattr, *txrate; |
1132 | u16 bitrate; | 1147 | u16 bitrate; |
1133 | 1148 | ||
1134 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); | 1149 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
1135 | if (!hdr) | 1150 | if (!hdr) |
1136 | return -1; | 1151 | return -1; |
1137 | 1152 | ||
1138 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 1153 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
1139 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); | 1154 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); |
1140 | 1155 | ||
1141 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); | 1156 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); |
1142 | if (!sinfoattr) | 1157 | if (!sinfoattr) |
1143 | goto nla_put_failure; | 1158 | goto nla_put_failure; |
1144 | if (sinfo->filled & STATION_INFO_INACTIVE_TIME) | 1159 | if (sinfo->filled & STATION_INFO_INACTIVE_TIME) |
1145 | NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, | 1160 | NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME, |
1146 | sinfo->inactive_time); | 1161 | sinfo->inactive_time); |
1147 | if (sinfo->filled & STATION_INFO_RX_BYTES) | 1162 | if (sinfo->filled & STATION_INFO_RX_BYTES) |
1148 | NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES, | 1163 | NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES, |
1149 | sinfo->rx_bytes); | 1164 | sinfo->rx_bytes); |
1150 | if (sinfo->filled & STATION_INFO_TX_BYTES) | 1165 | if (sinfo->filled & STATION_INFO_TX_BYTES) |
1151 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES, | 1166 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES, |
1152 | sinfo->tx_bytes); | 1167 | sinfo->tx_bytes); |
1153 | if (sinfo->filled & STATION_INFO_LLID) | 1168 | if (sinfo->filled & STATION_INFO_LLID) |
1154 | NLA_PUT_U16(msg, NL80211_STA_INFO_LLID, | 1169 | NLA_PUT_U16(msg, NL80211_STA_INFO_LLID, |
1155 | sinfo->llid); | 1170 | sinfo->llid); |
1156 | if (sinfo->filled & STATION_INFO_PLID) | 1171 | if (sinfo->filled & STATION_INFO_PLID) |
1157 | NLA_PUT_U16(msg, NL80211_STA_INFO_PLID, | 1172 | NLA_PUT_U16(msg, NL80211_STA_INFO_PLID, |
1158 | sinfo->plid); | 1173 | sinfo->plid); |
1159 | if (sinfo->filled & STATION_INFO_PLINK_STATE) | 1174 | if (sinfo->filled & STATION_INFO_PLINK_STATE) |
1160 | NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, | 1175 | NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, |
1161 | sinfo->plink_state); | 1176 | sinfo->plink_state); |
1162 | if (sinfo->filled & STATION_INFO_SIGNAL) | 1177 | if (sinfo->filled & STATION_INFO_SIGNAL) |
1163 | NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, | 1178 | NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, |
1164 | sinfo->signal); | 1179 | sinfo->signal); |
1165 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { | 1180 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { |
1166 | txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); | 1181 | txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); |
1167 | if (!txrate) | 1182 | if (!txrate) |
1168 | goto nla_put_failure; | 1183 | goto nla_put_failure; |
1169 | 1184 | ||
1170 | /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */ | 1185 | /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */ |
1171 | bitrate = nl80211_calculate_bitrate(&sinfo->txrate); | 1186 | bitrate = nl80211_calculate_bitrate(&sinfo->txrate); |
1172 | if (bitrate > 0) | 1187 | if (bitrate > 0) |
1173 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); | 1188 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); |
1174 | 1189 | ||
1175 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS) | 1190 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS) |
1176 | NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, | 1191 | NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, |
1177 | sinfo->txrate.mcs); | 1192 | sinfo->txrate.mcs); |
1178 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) | 1193 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) |
1179 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH); | 1194 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH); |
1180 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI) | 1195 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI) |
1181 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI); | 1196 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI); |
1182 | 1197 | ||
1183 | nla_nest_end(msg, txrate); | 1198 | nla_nest_end(msg, txrate); |
1184 | } | 1199 | } |
1185 | nla_nest_end(msg, sinfoattr); | 1200 | nla_nest_end(msg, sinfoattr); |
1186 | 1201 | ||
1187 | return genlmsg_end(msg, hdr); | 1202 | return genlmsg_end(msg, hdr); |
1188 | 1203 | ||
1189 | nla_put_failure: | 1204 | nla_put_failure: |
1190 | genlmsg_cancel(msg, hdr); | 1205 | genlmsg_cancel(msg, hdr); |
1191 | return -EMSGSIZE; | 1206 | return -EMSGSIZE; |
1192 | } | 1207 | } |
1193 | 1208 | ||
1194 | static int nl80211_dump_station(struct sk_buff *skb, | 1209 | static int nl80211_dump_station(struct sk_buff *skb, |
1195 | struct netlink_callback *cb) | 1210 | struct netlink_callback *cb) |
1196 | { | 1211 | { |
1197 | struct station_info sinfo; | 1212 | struct station_info sinfo; |
1198 | struct cfg80211_registered_device *dev; | 1213 | struct cfg80211_registered_device *dev; |
1199 | struct net_device *netdev; | 1214 | struct net_device *netdev; |
1200 | u8 mac_addr[ETH_ALEN]; | 1215 | u8 mac_addr[ETH_ALEN]; |
1201 | int ifidx = cb->args[0]; | 1216 | int ifidx = cb->args[0]; |
1202 | int sta_idx = cb->args[1]; | 1217 | int sta_idx = cb->args[1]; |
1203 | int err; | 1218 | int err; |
1204 | 1219 | ||
1205 | if (!ifidx) { | 1220 | if (!ifidx) { |
1206 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 1221 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
1207 | nl80211_fam.attrbuf, nl80211_fam.maxattr, | 1222 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
1208 | nl80211_policy); | 1223 | nl80211_policy); |
1209 | if (err) | 1224 | if (err) |
1210 | return err; | 1225 | return err; |
1211 | 1226 | ||
1212 | if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]) | 1227 | if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]) |
1213 | return -EINVAL; | 1228 | return -EINVAL; |
1214 | 1229 | ||
1215 | ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); | 1230 | ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); |
1216 | if (!ifidx) | 1231 | if (!ifidx) |
1217 | return -EINVAL; | 1232 | return -EINVAL; |
1218 | } | 1233 | } |
1219 | 1234 | ||
1220 | netdev = dev_get_by_index(&init_net, ifidx); | 1235 | netdev = dev_get_by_index(&init_net, ifidx); |
1221 | if (!netdev) | 1236 | if (!netdev) |
1222 | return -ENODEV; | 1237 | return -ENODEV; |
1223 | 1238 | ||
1224 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 1239 | dev = cfg80211_get_dev_from_ifindex(ifidx); |
1225 | if (IS_ERR(dev)) { | 1240 | if (IS_ERR(dev)) { |
1226 | err = PTR_ERR(dev); | 1241 | err = PTR_ERR(dev); |
1227 | goto out_put_netdev; | 1242 | goto out_put_netdev; |
1228 | } | 1243 | } |
1229 | 1244 | ||
1230 | if (!dev->ops->dump_station) { | 1245 | if (!dev->ops->dump_station) { |
1231 | err = -ENOSYS; | 1246 | err = -ENOSYS; |
1232 | goto out_err; | 1247 | goto out_err; |
1233 | } | 1248 | } |
1234 | 1249 | ||
1235 | rtnl_lock(); | 1250 | rtnl_lock(); |
1236 | 1251 | ||
1237 | while (1) { | 1252 | while (1) { |
1238 | err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, | 1253 | err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, |
1239 | mac_addr, &sinfo); | 1254 | mac_addr, &sinfo); |
1240 | if (err == -ENOENT) | 1255 | if (err == -ENOENT) |
1241 | break; | 1256 | break; |
1242 | if (err) | 1257 | if (err) |
1243 | goto out_err_rtnl; | 1258 | goto out_err_rtnl; |
1244 | 1259 | ||
1245 | if (nl80211_send_station(skb, | 1260 | if (nl80211_send_station(skb, |
1246 | NETLINK_CB(cb->skb).pid, | 1261 | NETLINK_CB(cb->skb).pid, |
1247 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1262 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
1248 | netdev, mac_addr, | 1263 | netdev, mac_addr, |
1249 | &sinfo) < 0) | 1264 | &sinfo) < 0) |
1250 | goto out; | 1265 | goto out; |
1251 | 1266 | ||
1252 | sta_idx++; | 1267 | sta_idx++; |
1253 | } | 1268 | } |
1254 | 1269 | ||
1255 | 1270 | ||
1256 | out: | 1271 | out: |
1257 | cb->args[1] = sta_idx; | 1272 | cb->args[1] = sta_idx; |
1258 | err = skb->len; | 1273 | err = skb->len; |
1259 | out_err_rtnl: | 1274 | out_err_rtnl: |
1260 | rtnl_unlock(); | 1275 | rtnl_unlock(); |
1261 | out_err: | 1276 | out_err: |
1262 | cfg80211_put_dev(dev); | 1277 | cfg80211_put_dev(dev); |
1263 | out_put_netdev: | 1278 | out_put_netdev: |
1264 | dev_put(netdev); | 1279 | dev_put(netdev); |
1265 | 1280 | ||
1266 | return err; | 1281 | return err; |
1267 | } | 1282 | } |
1268 | 1283 | ||
1269 | static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | 1284 | static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) |
1270 | { | 1285 | { |
1271 | struct cfg80211_registered_device *drv; | 1286 | struct cfg80211_registered_device *drv; |
1272 | int err; | 1287 | int err; |
1273 | struct net_device *dev; | 1288 | struct net_device *dev; |
1274 | struct station_info sinfo; | 1289 | struct station_info sinfo; |
1275 | struct sk_buff *msg; | 1290 | struct sk_buff *msg; |
1276 | u8 *mac_addr = NULL; | 1291 | u8 *mac_addr = NULL; |
1277 | 1292 | ||
1278 | memset(&sinfo, 0, sizeof(sinfo)); | 1293 | memset(&sinfo, 0, sizeof(sinfo)); |
1279 | 1294 | ||
1280 | if (!info->attrs[NL80211_ATTR_MAC]) | 1295 | if (!info->attrs[NL80211_ATTR_MAC]) |
1281 | return -EINVAL; | 1296 | return -EINVAL; |
1282 | 1297 | ||
1283 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1298 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1284 | 1299 | ||
1285 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1300 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1286 | if (err) | 1301 | if (err) |
1287 | return err; | 1302 | return err; |
1288 | 1303 | ||
1289 | if (!drv->ops->get_station) { | 1304 | if (!drv->ops->get_station) { |
1290 | err = -EOPNOTSUPP; | 1305 | err = -EOPNOTSUPP; |
1291 | goto out; | 1306 | goto out; |
1292 | } | 1307 | } |
1293 | 1308 | ||
1294 | rtnl_lock(); | 1309 | rtnl_lock(); |
1295 | err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo); | 1310 | err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo); |
1296 | rtnl_unlock(); | 1311 | rtnl_unlock(); |
1297 | 1312 | ||
1298 | if (err) | 1313 | if (err) |
1299 | goto out; | 1314 | goto out; |
1300 | 1315 | ||
1301 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 1316 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
1302 | if (!msg) | 1317 | if (!msg) |
1303 | goto out; | 1318 | goto out; |
1304 | 1319 | ||
1305 | if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, | 1320 | if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0, |
1306 | dev, mac_addr, &sinfo) < 0) | 1321 | dev, mac_addr, &sinfo) < 0) |
1307 | goto out_free; | 1322 | goto out_free; |
1308 | 1323 | ||
1309 | err = genlmsg_unicast(msg, info->snd_pid); | 1324 | err = genlmsg_unicast(msg, info->snd_pid); |
1310 | goto out; | 1325 | goto out; |
1311 | 1326 | ||
1312 | out_free: | 1327 | out_free: |
1313 | nlmsg_free(msg); | 1328 | nlmsg_free(msg); |
1314 | 1329 | ||
1315 | out: | 1330 | out: |
1316 | cfg80211_put_dev(drv); | 1331 | cfg80211_put_dev(drv); |
1317 | dev_put(dev); | 1332 | dev_put(dev); |
1318 | return err; | 1333 | return err; |
1319 | } | 1334 | } |
1320 | 1335 | ||
1321 | /* | 1336 | /* |
1322 | * Get vlan interface making sure it is on the right wiphy. | 1337 | * Get vlan interface making sure it is on the right wiphy. |
1323 | */ | 1338 | */ |
1324 | static int get_vlan(struct nlattr *vlanattr, | 1339 | static int get_vlan(struct nlattr *vlanattr, |
1325 | struct cfg80211_registered_device *rdev, | 1340 | struct cfg80211_registered_device *rdev, |
1326 | struct net_device **vlan) | 1341 | struct net_device **vlan) |
1327 | { | 1342 | { |
1328 | *vlan = NULL; | 1343 | *vlan = NULL; |
1329 | 1344 | ||
1330 | if (vlanattr) { | 1345 | if (vlanattr) { |
1331 | *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr)); | 1346 | *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr)); |
1332 | if (!*vlan) | 1347 | if (!*vlan) |
1333 | return -ENODEV; | 1348 | return -ENODEV; |
1334 | if (!(*vlan)->ieee80211_ptr) | 1349 | if (!(*vlan)->ieee80211_ptr) |
1335 | return -EINVAL; | 1350 | return -EINVAL; |
1336 | if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy) | 1351 | if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy) |
1337 | return -EINVAL; | 1352 | return -EINVAL; |
1338 | } | 1353 | } |
1339 | return 0; | 1354 | return 0; |
1340 | } | 1355 | } |
1341 | 1356 | ||
1342 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | 1357 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) |
1343 | { | 1358 | { |
1344 | struct cfg80211_registered_device *drv; | 1359 | struct cfg80211_registered_device *drv; |
1345 | int err; | 1360 | int err; |
1346 | struct net_device *dev; | 1361 | struct net_device *dev; |
1347 | struct station_parameters params; | 1362 | struct station_parameters params; |
1348 | u8 *mac_addr = NULL; | 1363 | u8 *mac_addr = NULL; |
1349 | 1364 | ||
1350 | memset(¶ms, 0, sizeof(params)); | 1365 | memset(¶ms, 0, sizeof(params)); |
1351 | 1366 | ||
1352 | params.listen_interval = -1; | 1367 | params.listen_interval = -1; |
1353 | 1368 | ||
1354 | if (info->attrs[NL80211_ATTR_STA_AID]) | 1369 | if (info->attrs[NL80211_ATTR_STA_AID]) |
1355 | return -EINVAL; | 1370 | return -EINVAL; |
1356 | 1371 | ||
1357 | if (!info->attrs[NL80211_ATTR_MAC]) | 1372 | if (!info->attrs[NL80211_ATTR_MAC]) |
1358 | return -EINVAL; | 1373 | return -EINVAL; |
1359 | 1374 | ||
1360 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1375 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1361 | 1376 | ||
1362 | if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) { | 1377 | if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) { |
1363 | params.supported_rates = | 1378 | params.supported_rates = |
1364 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | 1379 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); |
1365 | params.supported_rates_len = | 1380 | params.supported_rates_len = |
1366 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | 1381 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); |
1367 | } | 1382 | } |
1368 | 1383 | ||
1369 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 1384 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) |
1370 | params.listen_interval = | 1385 | params.listen_interval = |
1371 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 1386 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
1372 | 1387 | ||
1373 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 1388 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
1374 | params.ht_capa = | 1389 | params.ht_capa = |
1375 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 1390 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
1376 | 1391 | ||
1377 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | 1392 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], |
1378 | ¶ms.station_flags)) | 1393 | ¶ms.station_flags)) |
1379 | return -EINVAL; | 1394 | return -EINVAL; |
1380 | 1395 | ||
1381 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 1396 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) |
1382 | params.plink_action = | 1397 | params.plink_action = |
1383 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 1398 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
1384 | 1399 | ||
1385 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1400 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1386 | if (err) | 1401 | if (err) |
1387 | return err; | 1402 | return err; |
1388 | 1403 | ||
1389 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | 1404 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1390 | if (err) | 1405 | if (err) |
1391 | goto out; | 1406 | goto out; |
1392 | 1407 | ||
1393 | if (!drv->ops->change_station) { | 1408 | if (!drv->ops->change_station) { |
1394 | err = -EOPNOTSUPP; | 1409 | err = -EOPNOTSUPP; |
1395 | goto out; | 1410 | goto out; |
1396 | } | 1411 | } |
1397 | 1412 | ||
1398 | rtnl_lock(); | 1413 | rtnl_lock(); |
1399 | err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms); | 1414 | err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms); |
1400 | rtnl_unlock(); | 1415 | rtnl_unlock(); |
1401 | 1416 | ||
1402 | out: | 1417 | out: |
1403 | if (params.vlan) | 1418 | if (params.vlan) |
1404 | dev_put(params.vlan); | 1419 | dev_put(params.vlan); |
1405 | cfg80211_put_dev(drv); | 1420 | cfg80211_put_dev(drv); |
1406 | dev_put(dev); | 1421 | dev_put(dev); |
1407 | return err; | 1422 | return err; |
1408 | } | 1423 | } |
1409 | 1424 | ||
1410 | static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | 1425 | static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) |
1411 | { | 1426 | { |
1412 | struct cfg80211_registered_device *drv; | 1427 | struct cfg80211_registered_device *drv; |
1413 | int err; | 1428 | int err; |
1414 | struct net_device *dev; | 1429 | struct net_device *dev; |
1415 | struct station_parameters params; | 1430 | struct station_parameters params; |
1416 | u8 *mac_addr = NULL; | 1431 | u8 *mac_addr = NULL; |
1417 | 1432 | ||
1418 | memset(¶ms, 0, sizeof(params)); | 1433 | memset(¶ms, 0, sizeof(params)); |
1419 | 1434 | ||
1420 | if (!info->attrs[NL80211_ATTR_MAC]) | 1435 | if (!info->attrs[NL80211_ATTR_MAC]) |
1421 | return -EINVAL; | 1436 | return -EINVAL; |
1422 | 1437 | ||
1423 | if (!info->attrs[NL80211_ATTR_STA_AID]) | 1438 | if (!info->attrs[NL80211_ATTR_STA_AID]) |
1424 | return -EINVAL; | 1439 | return -EINVAL; |
1425 | 1440 | ||
1426 | if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 1441 | if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) |
1427 | return -EINVAL; | 1442 | return -EINVAL; |
1428 | 1443 | ||
1429 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) | 1444 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) |
1430 | return -EINVAL; | 1445 | return -EINVAL; |
1431 | 1446 | ||
1432 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1447 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1433 | params.supported_rates = | 1448 | params.supported_rates = |
1434 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | 1449 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); |
1435 | params.supported_rates_len = | 1450 | params.supported_rates_len = |
1436 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | 1451 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); |
1437 | params.listen_interval = | 1452 | params.listen_interval = |
1438 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 1453 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
1439 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 1454 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); |
1440 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 1455 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
1441 | params.ht_capa = | 1456 | params.ht_capa = |
1442 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 1457 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
1443 | 1458 | ||
1444 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | 1459 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], |
1445 | ¶ms.station_flags)) | 1460 | ¶ms.station_flags)) |
1446 | return -EINVAL; | 1461 | return -EINVAL; |
1447 | 1462 | ||
1448 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1463 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1449 | if (err) | 1464 | if (err) |
1450 | return err; | 1465 | return err; |
1451 | 1466 | ||
1452 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | 1467 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1453 | if (err) | 1468 | if (err) |
1454 | goto out; | 1469 | goto out; |
1455 | 1470 | ||
1456 | if (!drv->ops->add_station) { | 1471 | if (!drv->ops->add_station) { |
1457 | err = -EOPNOTSUPP; | 1472 | err = -EOPNOTSUPP; |
1458 | goto out; | 1473 | goto out; |
1459 | } | 1474 | } |
1460 | 1475 | ||
1461 | rtnl_lock(); | 1476 | rtnl_lock(); |
1462 | err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); | 1477 | err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); |
1463 | rtnl_unlock(); | 1478 | rtnl_unlock(); |
1464 | 1479 | ||
1465 | out: | 1480 | out: |
1466 | if (params.vlan) | 1481 | if (params.vlan) |
1467 | dev_put(params.vlan); | 1482 | dev_put(params.vlan); |
1468 | cfg80211_put_dev(drv); | 1483 | cfg80211_put_dev(drv); |
1469 | dev_put(dev); | 1484 | dev_put(dev); |
1470 | return err; | 1485 | return err; |
1471 | } | 1486 | } |
1472 | 1487 | ||
1473 | static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | 1488 | static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) |
1474 | { | 1489 | { |
1475 | struct cfg80211_registered_device *drv; | 1490 | struct cfg80211_registered_device *drv; |
1476 | int err; | 1491 | int err; |
1477 | struct net_device *dev; | 1492 | struct net_device *dev; |
1478 | u8 *mac_addr = NULL; | 1493 | u8 *mac_addr = NULL; |
1479 | 1494 | ||
1480 | if (info->attrs[NL80211_ATTR_MAC]) | 1495 | if (info->attrs[NL80211_ATTR_MAC]) |
1481 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1496 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1482 | 1497 | ||
1483 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1498 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1484 | if (err) | 1499 | if (err) |
1485 | return err; | 1500 | return err; |
1486 | 1501 | ||
1487 | if (!drv->ops->del_station) { | 1502 | if (!drv->ops->del_station) { |
1488 | err = -EOPNOTSUPP; | 1503 | err = -EOPNOTSUPP; |
1489 | goto out; | 1504 | goto out; |
1490 | } | 1505 | } |
1491 | 1506 | ||
1492 | rtnl_lock(); | 1507 | rtnl_lock(); |
1493 | err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); | 1508 | err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); |
1494 | rtnl_unlock(); | 1509 | rtnl_unlock(); |
1495 | 1510 | ||
1496 | out: | 1511 | out: |
1497 | cfg80211_put_dev(drv); | 1512 | cfg80211_put_dev(drv); |
1498 | dev_put(dev); | 1513 | dev_put(dev); |
1499 | return err; | 1514 | return err; |
1500 | } | 1515 | } |
1501 | 1516 | ||
1502 | static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, | 1517 | static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq, |
1503 | int flags, struct net_device *dev, | 1518 | int flags, struct net_device *dev, |
1504 | u8 *dst, u8 *next_hop, | 1519 | u8 *dst, u8 *next_hop, |
1505 | struct mpath_info *pinfo) | 1520 | struct mpath_info *pinfo) |
1506 | { | 1521 | { |
1507 | void *hdr; | 1522 | void *hdr; |
1508 | struct nlattr *pinfoattr; | 1523 | struct nlattr *pinfoattr; |
1509 | 1524 | ||
1510 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); | 1525 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
1511 | if (!hdr) | 1526 | if (!hdr) |
1512 | return -1; | 1527 | return -1; |
1513 | 1528 | ||
1514 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 1529 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
1515 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst); | 1530 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst); |
1516 | NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop); | 1531 | NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop); |
1517 | 1532 | ||
1518 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO); | 1533 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO); |
1519 | if (!pinfoattr) | 1534 | if (!pinfoattr) |
1520 | goto nla_put_failure; | 1535 | goto nla_put_failure; |
1521 | if (pinfo->filled & MPATH_INFO_FRAME_QLEN) | 1536 | if (pinfo->filled & MPATH_INFO_FRAME_QLEN) |
1522 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN, | 1537 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN, |
1523 | pinfo->frame_qlen); | 1538 | pinfo->frame_qlen); |
1524 | if (pinfo->filled & MPATH_INFO_DSN) | 1539 | if (pinfo->filled & MPATH_INFO_DSN) |
1525 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN, | 1540 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN, |
1526 | pinfo->dsn); | 1541 | pinfo->dsn); |
1527 | if (pinfo->filled & MPATH_INFO_METRIC) | 1542 | if (pinfo->filled & MPATH_INFO_METRIC) |
1528 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC, | 1543 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC, |
1529 | pinfo->metric); | 1544 | pinfo->metric); |
1530 | if (pinfo->filled & MPATH_INFO_EXPTIME) | 1545 | if (pinfo->filled & MPATH_INFO_EXPTIME) |
1531 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME, | 1546 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME, |
1532 | pinfo->exptime); | 1547 | pinfo->exptime); |
1533 | if (pinfo->filled & MPATH_INFO_FLAGS) | 1548 | if (pinfo->filled & MPATH_INFO_FLAGS) |
1534 | NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS, | 1549 | NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS, |
1535 | pinfo->flags); | 1550 | pinfo->flags); |
1536 | if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) | 1551 | if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT) |
1537 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, | 1552 | NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, |
1538 | pinfo->discovery_timeout); | 1553 | pinfo->discovery_timeout); |
1539 | if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) | 1554 | if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES) |
1540 | NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES, | 1555 | NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES, |
1541 | pinfo->discovery_retries); | 1556 | pinfo->discovery_retries); |
1542 | 1557 | ||
1543 | nla_nest_end(msg, pinfoattr); | 1558 | nla_nest_end(msg, pinfoattr); |
1544 | 1559 | ||
1545 | return genlmsg_end(msg, hdr); | 1560 | return genlmsg_end(msg, hdr); |
1546 | 1561 | ||
1547 | nla_put_failure: | 1562 | nla_put_failure: |
1548 | genlmsg_cancel(msg, hdr); | 1563 | genlmsg_cancel(msg, hdr); |
1549 | return -EMSGSIZE; | 1564 | return -EMSGSIZE; |
1550 | } | 1565 | } |
1551 | 1566 | ||
1552 | static int nl80211_dump_mpath(struct sk_buff *skb, | 1567 | static int nl80211_dump_mpath(struct sk_buff *skb, |
1553 | struct netlink_callback *cb) | 1568 | struct netlink_callback *cb) |
1554 | { | 1569 | { |
1555 | struct mpath_info pinfo; | 1570 | struct mpath_info pinfo; |
1556 | struct cfg80211_registered_device *dev; | 1571 | struct cfg80211_registered_device *dev; |
1557 | struct net_device *netdev; | 1572 | struct net_device *netdev; |
1558 | u8 dst[ETH_ALEN]; | 1573 | u8 dst[ETH_ALEN]; |
1559 | u8 next_hop[ETH_ALEN]; | 1574 | u8 next_hop[ETH_ALEN]; |
1560 | int ifidx = cb->args[0]; | 1575 | int ifidx = cb->args[0]; |
1561 | int path_idx = cb->args[1]; | 1576 | int path_idx = cb->args[1]; |
1562 | int err; | 1577 | int err; |
1563 | 1578 | ||
1564 | if (!ifidx) { | 1579 | if (!ifidx) { |
1565 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 1580 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
1566 | nl80211_fam.attrbuf, nl80211_fam.maxattr, | 1581 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
1567 | nl80211_policy); | 1582 | nl80211_policy); |
1568 | if (err) | 1583 | if (err) |
1569 | return err; | 1584 | return err; |
1570 | 1585 | ||
1571 | if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]) | 1586 | if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]) |
1572 | return -EINVAL; | 1587 | return -EINVAL; |
1573 | 1588 | ||
1574 | ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); | 1589 | ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); |
1575 | if (!ifidx) | 1590 | if (!ifidx) |
1576 | return -EINVAL; | 1591 | return -EINVAL; |
1577 | } | 1592 | } |
1578 | 1593 | ||
1579 | netdev = dev_get_by_index(&init_net, ifidx); | 1594 | netdev = dev_get_by_index(&init_net, ifidx); |
1580 | if (!netdev) | 1595 | if (!netdev) |
1581 | return -ENODEV; | 1596 | return -ENODEV; |
1582 | 1597 | ||
1583 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 1598 | dev = cfg80211_get_dev_from_ifindex(ifidx); |
1584 | if (IS_ERR(dev)) { | 1599 | if (IS_ERR(dev)) { |
1585 | err = PTR_ERR(dev); | 1600 | err = PTR_ERR(dev); |
1586 | goto out_put_netdev; | 1601 | goto out_put_netdev; |
1587 | } | 1602 | } |
1588 | 1603 | ||
1589 | if (!dev->ops->dump_mpath) { | 1604 | if (!dev->ops->dump_mpath) { |
1590 | err = -ENOSYS; | 1605 | err = -ENOSYS; |
1591 | goto out_err; | 1606 | goto out_err; |
1592 | } | 1607 | } |
1593 | 1608 | ||
1594 | rtnl_lock(); | 1609 | rtnl_lock(); |
1595 | 1610 | ||
1596 | while (1) { | 1611 | while (1) { |
1597 | err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, | 1612 | err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, |
1598 | dst, next_hop, &pinfo); | 1613 | dst, next_hop, &pinfo); |
1599 | if (err == -ENOENT) | 1614 | if (err == -ENOENT) |
1600 | break; | 1615 | break; |
1601 | if (err) | 1616 | if (err) |
1602 | goto out_err_rtnl; | 1617 | goto out_err_rtnl; |
1603 | 1618 | ||
1604 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, | 1619 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, |
1605 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1620 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
1606 | netdev, dst, next_hop, | 1621 | netdev, dst, next_hop, |
1607 | &pinfo) < 0) | 1622 | &pinfo) < 0) |
1608 | goto out; | 1623 | goto out; |
1609 | 1624 | ||
1610 | path_idx++; | 1625 | path_idx++; |
1611 | } | 1626 | } |
1612 | 1627 | ||
1613 | 1628 | ||
1614 | out: | 1629 | out: |
1615 | cb->args[1] = path_idx; | 1630 | cb->args[1] = path_idx; |
1616 | err = skb->len; | 1631 | err = skb->len; |
1617 | out_err_rtnl: | 1632 | out_err_rtnl: |
1618 | rtnl_unlock(); | 1633 | rtnl_unlock(); |
1619 | out_err: | 1634 | out_err: |
1620 | cfg80211_put_dev(dev); | 1635 | cfg80211_put_dev(dev); |
1621 | out_put_netdev: | 1636 | out_put_netdev: |
1622 | dev_put(netdev); | 1637 | dev_put(netdev); |
1623 | 1638 | ||
1624 | return err; | 1639 | return err; |
1625 | } | 1640 | } |
1626 | 1641 | ||
1627 | static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | 1642 | static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) |
1628 | { | 1643 | { |
1629 | struct cfg80211_registered_device *drv; | 1644 | struct cfg80211_registered_device *drv; |
1630 | int err; | 1645 | int err; |
1631 | struct net_device *dev; | 1646 | struct net_device *dev; |
1632 | struct mpath_info pinfo; | 1647 | struct mpath_info pinfo; |
1633 | struct sk_buff *msg; | 1648 | struct sk_buff *msg; |
1634 | u8 *dst = NULL; | 1649 | u8 *dst = NULL; |
1635 | u8 next_hop[ETH_ALEN]; | 1650 | u8 next_hop[ETH_ALEN]; |
1636 | 1651 | ||
1637 | memset(&pinfo, 0, sizeof(pinfo)); | 1652 | memset(&pinfo, 0, sizeof(pinfo)); |
1638 | 1653 | ||
1639 | if (!info->attrs[NL80211_ATTR_MAC]) | 1654 | if (!info->attrs[NL80211_ATTR_MAC]) |
1640 | return -EINVAL; | 1655 | return -EINVAL; |
1641 | 1656 | ||
1642 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1657 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1643 | 1658 | ||
1644 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1659 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1645 | if (err) | 1660 | if (err) |
1646 | return err; | 1661 | return err; |
1647 | 1662 | ||
1648 | if (!drv->ops->get_mpath) { | 1663 | if (!drv->ops->get_mpath) { |
1649 | err = -EOPNOTSUPP; | 1664 | err = -EOPNOTSUPP; |
1650 | goto out; | 1665 | goto out; |
1651 | } | 1666 | } |
1652 | 1667 | ||
1653 | rtnl_lock(); | 1668 | rtnl_lock(); |
1654 | err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); | 1669 | err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); |
1655 | rtnl_unlock(); | 1670 | rtnl_unlock(); |
1656 | 1671 | ||
1657 | if (err) | 1672 | if (err) |
1658 | goto out; | 1673 | goto out; |
1659 | 1674 | ||
1660 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 1675 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
1661 | if (!msg) | 1676 | if (!msg) |
1662 | goto out; | 1677 | goto out; |
1663 | 1678 | ||
1664 | if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0, | 1679 | if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0, |
1665 | dev, dst, next_hop, &pinfo) < 0) | 1680 | dev, dst, next_hop, &pinfo) < 0) |
1666 | goto out_free; | 1681 | goto out_free; |
1667 | 1682 | ||
1668 | err = genlmsg_unicast(msg, info->snd_pid); | 1683 | err = genlmsg_unicast(msg, info->snd_pid); |
1669 | goto out; | 1684 | goto out; |
1670 | 1685 | ||
1671 | out_free: | 1686 | out_free: |
1672 | nlmsg_free(msg); | 1687 | nlmsg_free(msg); |
1673 | 1688 | ||
1674 | out: | 1689 | out: |
1675 | cfg80211_put_dev(drv); | 1690 | cfg80211_put_dev(drv); |
1676 | dev_put(dev); | 1691 | dev_put(dev); |
1677 | return err; | 1692 | return err; |
1678 | } | 1693 | } |
1679 | 1694 | ||
1680 | static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) | 1695 | static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) |
1681 | { | 1696 | { |
1682 | struct cfg80211_registered_device *drv; | 1697 | struct cfg80211_registered_device *drv; |
1683 | int err; | 1698 | int err; |
1684 | struct net_device *dev; | 1699 | struct net_device *dev; |
1685 | u8 *dst = NULL; | 1700 | u8 *dst = NULL; |
1686 | u8 *next_hop = NULL; | 1701 | u8 *next_hop = NULL; |
1687 | 1702 | ||
1688 | if (!info->attrs[NL80211_ATTR_MAC]) | 1703 | if (!info->attrs[NL80211_ATTR_MAC]) |
1689 | return -EINVAL; | 1704 | return -EINVAL; |
1690 | 1705 | ||
1691 | if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]) | 1706 | if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]) |
1692 | return -EINVAL; | 1707 | return -EINVAL; |
1693 | 1708 | ||
1694 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1709 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1695 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 1710 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
1696 | 1711 | ||
1697 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1712 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1698 | if (err) | 1713 | if (err) |
1699 | return err; | 1714 | return err; |
1700 | 1715 | ||
1701 | if (!drv->ops->change_mpath) { | 1716 | if (!drv->ops->change_mpath) { |
1702 | err = -EOPNOTSUPP; | 1717 | err = -EOPNOTSUPP; |
1703 | goto out; | 1718 | goto out; |
1704 | } | 1719 | } |
1705 | 1720 | ||
1706 | rtnl_lock(); | 1721 | rtnl_lock(); |
1707 | err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); | 1722 | err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); |
1708 | rtnl_unlock(); | 1723 | rtnl_unlock(); |
1709 | 1724 | ||
1710 | out: | 1725 | out: |
1711 | cfg80211_put_dev(drv); | 1726 | cfg80211_put_dev(drv); |
1712 | dev_put(dev); | 1727 | dev_put(dev); |
1713 | return err; | 1728 | return err; |
1714 | } | 1729 | } |
1715 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | 1730 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) |
1716 | { | 1731 | { |
1717 | struct cfg80211_registered_device *drv; | 1732 | struct cfg80211_registered_device *drv; |
1718 | int err; | 1733 | int err; |
1719 | struct net_device *dev; | 1734 | struct net_device *dev; |
1720 | u8 *dst = NULL; | 1735 | u8 *dst = NULL; |
1721 | u8 *next_hop = NULL; | 1736 | u8 *next_hop = NULL; |
1722 | 1737 | ||
1723 | if (!info->attrs[NL80211_ATTR_MAC]) | 1738 | if (!info->attrs[NL80211_ATTR_MAC]) |
1724 | return -EINVAL; | 1739 | return -EINVAL; |
1725 | 1740 | ||
1726 | if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]) | 1741 | if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]) |
1727 | return -EINVAL; | 1742 | return -EINVAL; |
1728 | 1743 | ||
1729 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1744 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1730 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 1745 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
1731 | 1746 | ||
1732 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1747 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1733 | if (err) | 1748 | if (err) |
1734 | return err; | 1749 | return err; |
1735 | 1750 | ||
1736 | if (!drv->ops->add_mpath) { | 1751 | if (!drv->ops->add_mpath) { |
1737 | err = -EOPNOTSUPP; | 1752 | err = -EOPNOTSUPP; |
1738 | goto out; | 1753 | goto out; |
1739 | } | 1754 | } |
1740 | 1755 | ||
1741 | rtnl_lock(); | 1756 | rtnl_lock(); |
1742 | err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); | 1757 | err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); |
1743 | rtnl_unlock(); | 1758 | rtnl_unlock(); |
1744 | 1759 | ||
1745 | out: | 1760 | out: |
1746 | cfg80211_put_dev(drv); | 1761 | cfg80211_put_dev(drv); |
1747 | dev_put(dev); | 1762 | dev_put(dev); |
1748 | return err; | 1763 | return err; |
1749 | } | 1764 | } |
1750 | 1765 | ||
1751 | static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | 1766 | static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) |
1752 | { | 1767 | { |
1753 | struct cfg80211_registered_device *drv; | 1768 | struct cfg80211_registered_device *drv; |
1754 | int err; | 1769 | int err; |
1755 | struct net_device *dev; | 1770 | struct net_device *dev; |
1756 | u8 *dst = NULL; | 1771 | u8 *dst = NULL; |
1757 | 1772 | ||
1758 | if (info->attrs[NL80211_ATTR_MAC]) | 1773 | if (info->attrs[NL80211_ATTR_MAC]) |
1759 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1774 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1760 | 1775 | ||
1761 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1776 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1762 | if (err) | 1777 | if (err) |
1763 | return err; | 1778 | return err; |
1764 | 1779 | ||
1765 | if (!drv->ops->del_mpath) { | 1780 | if (!drv->ops->del_mpath) { |
1766 | err = -EOPNOTSUPP; | 1781 | err = -EOPNOTSUPP; |
1767 | goto out; | 1782 | goto out; |
1768 | } | 1783 | } |
1769 | 1784 | ||
1770 | rtnl_lock(); | 1785 | rtnl_lock(); |
1771 | err = drv->ops->del_mpath(&drv->wiphy, dev, dst); | 1786 | err = drv->ops->del_mpath(&drv->wiphy, dev, dst); |
1772 | rtnl_unlock(); | 1787 | rtnl_unlock(); |
1773 | 1788 | ||
1774 | out: | 1789 | out: |
1775 | cfg80211_put_dev(drv); | 1790 | cfg80211_put_dev(drv); |
1776 | dev_put(dev); | 1791 | dev_put(dev); |
1777 | return err; | 1792 | return err; |
1778 | } | 1793 | } |
1779 | 1794 | ||
1780 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | 1795 | static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) |
1781 | { | 1796 | { |
1782 | struct cfg80211_registered_device *drv; | 1797 | struct cfg80211_registered_device *drv; |
1783 | int err; | 1798 | int err; |
1784 | struct net_device *dev; | 1799 | struct net_device *dev; |
1785 | struct bss_parameters params; | 1800 | struct bss_parameters params; |
1786 | 1801 | ||
1787 | memset(¶ms, 0, sizeof(params)); | 1802 | memset(¶ms, 0, sizeof(params)); |
1788 | /* default to not changing parameters */ | 1803 | /* default to not changing parameters */ |
1789 | params.use_cts_prot = -1; | 1804 | params.use_cts_prot = -1; |
1790 | params.use_short_preamble = -1; | 1805 | params.use_short_preamble = -1; |
1791 | params.use_short_slot_time = -1; | 1806 | params.use_short_slot_time = -1; |
1792 | 1807 | ||
1793 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) | 1808 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) |
1794 | params.use_cts_prot = | 1809 | params.use_cts_prot = |
1795 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]); | 1810 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]); |
1796 | if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]) | 1811 | if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]) |
1797 | params.use_short_preamble = | 1812 | params.use_short_preamble = |
1798 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]); | 1813 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]); |
1799 | if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) | 1814 | if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) |
1800 | params.use_short_slot_time = | 1815 | params.use_short_slot_time = |
1801 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); | 1816 | nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); |
1802 | if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { | 1817 | if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { |
1803 | params.basic_rates = | 1818 | params.basic_rates = |
1804 | nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 1819 | nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
1805 | params.basic_rates_len = | 1820 | params.basic_rates_len = |
1806 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 1821 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
1807 | } | 1822 | } |
1808 | 1823 | ||
1809 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1824 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1810 | if (err) | 1825 | if (err) |
1811 | return err; | 1826 | return err; |
1812 | 1827 | ||
1813 | if (!drv->ops->change_bss) { | 1828 | if (!drv->ops->change_bss) { |
1814 | err = -EOPNOTSUPP; | 1829 | err = -EOPNOTSUPP; |
1815 | goto out; | 1830 | goto out; |
1816 | } | 1831 | } |
1817 | 1832 | ||
1818 | rtnl_lock(); | 1833 | rtnl_lock(); |
1819 | err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); | 1834 | err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); |
1820 | rtnl_unlock(); | 1835 | rtnl_unlock(); |
1821 | 1836 | ||
1822 | out: | 1837 | out: |
1823 | cfg80211_put_dev(drv); | 1838 | cfg80211_put_dev(drv); |
1824 | dev_put(dev); | 1839 | dev_put(dev); |
1825 | return err; | 1840 | return err; |
1826 | } | 1841 | } |
1827 | 1842 | ||
1828 | static const struct nla_policy | 1843 | static const struct nla_policy |
1829 | reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { | 1844 | reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { |
1830 | [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, | 1845 | [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, |
1831 | [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, | 1846 | [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, |
1832 | [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, | 1847 | [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, |
1833 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, | 1848 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, |
1834 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, | 1849 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, |
1835 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, | 1850 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, |
1836 | }; | 1851 | }; |
1837 | 1852 | ||
1838 | static int parse_reg_rule(struct nlattr *tb[], | 1853 | static int parse_reg_rule(struct nlattr *tb[], |
1839 | struct ieee80211_reg_rule *reg_rule) | 1854 | struct ieee80211_reg_rule *reg_rule) |
1840 | { | 1855 | { |
1841 | struct ieee80211_freq_range *freq_range = ®_rule->freq_range; | 1856 | struct ieee80211_freq_range *freq_range = ®_rule->freq_range; |
1842 | struct ieee80211_power_rule *power_rule = ®_rule->power_rule; | 1857 | struct ieee80211_power_rule *power_rule = ®_rule->power_rule; |
1843 | 1858 | ||
1844 | if (!tb[NL80211_ATTR_REG_RULE_FLAGS]) | 1859 | if (!tb[NL80211_ATTR_REG_RULE_FLAGS]) |
1845 | return -EINVAL; | 1860 | return -EINVAL; |
1846 | if (!tb[NL80211_ATTR_FREQ_RANGE_START]) | 1861 | if (!tb[NL80211_ATTR_FREQ_RANGE_START]) |
1847 | return -EINVAL; | 1862 | return -EINVAL; |
1848 | if (!tb[NL80211_ATTR_FREQ_RANGE_END]) | 1863 | if (!tb[NL80211_ATTR_FREQ_RANGE_END]) |
1849 | return -EINVAL; | 1864 | return -EINVAL; |
1850 | if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) | 1865 | if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) |
1851 | return -EINVAL; | 1866 | return -EINVAL; |
1852 | if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) | 1867 | if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) |
1853 | return -EINVAL; | 1868 | return -EINVAL; |
1854 | 1869 | ||
1855 | reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]); | 1870 | reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]); |
1856 | 1871 | ||
1857 | freq_range->start_freq_khz = | 1872 | freq_range->start_freq_khz = |
1858 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); | 1873 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); |
1859 | freq_range->end_freq_khz = | 1874 | freq_range->end_freq_khz = |
1860 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]); | 1875 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]); |
1861 | freq_range->max_bandwidth_khz = | 1876 | freq_range->max_bandwidth_khz = |
1862 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]); | 1877 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]); |
1863 | 1878 | ||
1864 | power_rule->max_eirp = | 1879 | power_rule->max_eirp = |
1865 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]); | 1880 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]); |
1866 | 1881 | ||
1867 | if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]) | 1882 | if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]) |
1868 | power_rule->max_antenna_gain = | 1883 | power_rule->max_antenna_gain = |
1869 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); | 1884 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); |
1870 | 1885 | ||
1871 | return 0; | 1886 | return 0; |
1872 | } | 1887 | } |
1873 | 1888 | ||
1874 | static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | 1889 | static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) |
1875 | { | 1890 | { |
1876 | int r; | 1891 | int r; |
1877 | char *data = NULL; | 1892 | char *data = NULL; |
1878 | 1893 | ||
1879 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) | 1894 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) |
1880 | return -EINVAL; | 1895 | return -EINVAL; |
1881 | 1896 | ||
1882 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); | 1897 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); |
1883 | 1898 | ||
1884 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 1899 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY |
1885 | /* We ignore world regdom requests with the old regdom setup */ | 1900 | /* We ignore world regdom requests with the old regdom setup */ |
1886 | if (is_world_regdom(data)) | 1901 | if (is_world_regdom(data)) |
1887 | return -EINVAL; | 1902 | return -EINVAL; |
1888 | #endif | 1903 | #endif |
1889 | mutex_lock(&cfg80211_drv_mutex); | 1904 | mutex_lock(&cfg80211_drv_mutex); |
1890 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); | 1905 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); |
1891 | mutex_unlock(&cfg80211_drv_mutex); | 1906 | mutex_unlock(&cfg80211_drv_mutex); |
1892 | return r; | 1907 | return r; |
1893 | } | 1908 | } |
1894 | 1909 | ||
1895 | static int nl80211_get_mesh_params(struct sk_buff *skb, | 1910 | static int nl80211_get_mesh_params(struct sk_buff *skb, |
1896 | struct genl_info *info) | 1911 | struct genl_info *info) |
1897 | { | 1912 | { |
1898 | struct cfg80211_registered_device *drv; | 1913 | struct cfg80211_registered_device *drv; |
1899 | struct mesh_config cur_params; | 1914 | struct mesh_config cur_params; |
1900 | int err; | 1915 | int err; |
1901 | struct net_device *dev; | 1916 | struct net_device *dev; |
1902 | void *hdr; | 1917 | void *hdr; |
1903 | struct nlattr *pinfoattr; | 1918 | struct nlattr *pinfoattr; |
1904 | struct sk_buff *msg; | 1919 | struct sk_buff *msg; |
1905 | 1920 | ||
1906 | /* Look up our device */ | 1921 | /* Look up our device */ |
1907 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1922 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1908 | if (err) | 1923 | if (err) |
1909 | return err; | 1924 | return err; |
1910 | 1925 | ||
1911 | /* Get the mesh params */ | 1926 | /* Get the mesh params */ |
1912 | rtnl_lock(); | 1927 | rtnl_lock(); |
1913 | err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); | 1928 | err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); |
1914 | rtnl_unlock(); | 1929 | rtnl_unlock(); |
1915 | if (err) | 1930 | if (err) |
1916 | goto out; | 1931 | goto out; |
1917 | 1932 | ||
1918 | /* Draw up a netlink message to send back */ | 1933 | /* Draw up a netlink message to send back */ |
1919 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 1934 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
1920 | if (!msg) { | 1935 | if (!msg) { |
1921 | err = -ENOBUFS; | 1936 | err = -ENOBUFS; |
1922 | goto out; | 1937 | goto out; |
1923 | } | 1938 | } |
1924 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 1939 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
1925 | NL80211_CMD_GET_MESH_PARAMS); | 1940 | NL80211_CMD_GET_MESH_PARAMS); |
1926 | if (!hdr) | 1941 | if (!hdr) |
1927 | goto nla_put_failure; | 1942 | goto nla_put_failure; |
1928 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS); | 1943 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS); |
1929 | if (!pinfoattr) | 1944 | if (!pinfoattr) |
1930 | goto nla_put_failure; | 1945 | goto nla_put_failure; |
1931 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 1946 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
1932 | NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT, | 1947 | NLA_PUT_U16(msg, NL80211_MESHCONF_RETRY_TIMEOUT, |
1933 | cur_params.dot11MeshRetryTimeout); | 1948 | cur_params.dot11MeshRetryTimeout); |
1934 | NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT, | 1949 | NLA_PUT_U16(msg, NL80211_MESHCONF_CONFIRM_TIMEOUT, |
1935 | cur_params.dot11MeshConfirmTimeout); | 1950 | cur_params.dot11MeshConfirmTimeout); |
1936 | NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT, | 1951 | NLA_PUT_U16(msg, NL80211_MESHCONF_HOLDING_TIMEOUT, |
1937 | cur_params.dot11MeshHoldingTimeout); | 1952 | cur_params.dot11MeshHoldingTimeout); |
1938 | NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, | 1953 | NLA_PUT_U16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, |
1939 | cur_params.dot11MeshMaxPeerLinks); | 1954 | cur_params.dot11MeshMaxPeerLinks); |
1940 | NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES, | 1955 | NLA_PUT_U8(msg, NL80211_MESHCONF_MAX_RETRIES, |
1941 | cur_params.dot11MeshMaxRetries); | 1956 | cur_params.dot11MeshMaxRetries); |
1942 | NLA_PUT_U8(msg, NL80211_MESHCONF_TTL, | 1957 | NLA_PUT_U8(msg, NL80211_MESHCONF_TTL, |
1943 | cur_params.dot11MeshTTL); | 1958 | cur_params.dot11MeshTTL); |
1944 | NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, | 1959 | NLA_PUT_U8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, |
1945 | cur_params.auto_open_plinks); | 1960 | cur_params.auto_open_plinks); |
1946 | NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 1961 | NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
1947 | cur_params.dot11MeshHWMPmaxPREQretries); | 1962 | cur_params.dot11MeshHWMPmaxPREQretries); |
1948 | NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, | 1963 | NLA_PUT_U32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, |
1949 | cur_params.path_refresh_time); | 1964 | cur_params.path_refresh_time); |
1950 | NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | 1965 | NLA_PUT_U16(msg, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, |
1951 | cur_params.min_discovery_timeout); | 1966 | cur_params.min_discovery_timeout); |
1952 | NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | 1967 | NLA_PUT_U32(msg, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, |
1953 | cur_params.dot11MeshHWMPactivePathTimeout); | 1968 | cur_params.dot11MeshHWMPactivePathTimeout); |
1954 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | 1969 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, |
1955 | cur_params.dot11MeshHWMPpreqMinInterval); | 1970 | cur_params.dot11MeshHWMPpreqMinInterval); |
1956 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | 1971 | NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
1957 | cur_params.dot11MeshHWMPnetDiameterTraversalTime); | 1972 | cur_params.dot11MeshHWMPnetDiameterTraversalTime); |
1958 | nla_nest_end(msg, pinfoattr); | 1973 | nla_nest_end(msg, pinfoattr); |
1959 | genlmsg_end(msg, hdr); | 1974 | genlmsg_end(msg, hdr); |
1960 | err = genlmsg_unicast(msg, info->snd_pid); | 1975 | err = genlmsg_unicast(msg, info->snd_pid); |
1961 | goto out; | 1976 | goto out; |
1962 | 1977 | ||
1963 | nla_put_failure: | 1978 | nla_put_failure: |
1964 | genlmsg_cancel(msg, hdr); | 1979 | genlmsg_cancel(msg, hdr); |
1965 | err = -EMSGSIZE; | 1980 | err = -EMSGSIZE; |
1966 | out: | 1981 | out: |
1967 | /* Cleanup */ | 1982 | /* Cleanup */ |
1968 | cfg80211_put_dev(drv); | 1983 | cfg80211_put_dev(drv); |
1969 | dev_put(dev); | 1984 | dev_put(dev); |
1970 | return err; | 1985 | return err; |
1971 | } | 1986 | } |
1972 | 1987 | ||
1973 | #define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ | 1988 | #define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ |
1974 | do {\ | 1989 | do {\ |
1975 | if (table[attr_num]) {\ | 1990 | if (table[attr_num]) {\ |
1976 | cfg.param = nla_fn(table[attr_num]); \ | 1991 | cfg.param = nla_fn(table[attr_num]); \ |
1977 | mask |= (1 << (attr_num - 1)); \ | 1992 | mask |= (1 << (attr_num - 1)); \ |
1978 | } \ | 1993 | } \ |
1979 | } while (0);\ | 1994 | } while (0);\ |
1980 | 1995 | ||
1981 | static struct nla_policy | 1996 | static struct nla_policy |
1982 | nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = { | 1997 | nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = { |
1983 | [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, | 1998 | [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, |
1984 | [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 }, | 1999 | [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 }, |
1985 | [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 }, | 2000 | [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 }, |
1986 | [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 }, | 2001 | [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 }, |
1987 | [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 }, | 2002 | [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 }, |
1988 | [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, | 2003 | [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, |
1989 | [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, | 2004 | [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, |
1990 | 2005 | ||
1991 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, | 2006 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, |
1992 | [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, | 2007 | [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, |
1993 | [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 }, | 2008 | [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 }, |
1994 | [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, | 2009 | [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, |
1995 | [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, | 2010 | [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, |
1996 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, | 2011 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, |
1997 | }; | 2012 | }; |
1998 | 2013 | ||
1999 | static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | 2014 | static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) |
2000 | { | 2015 | { |
2001 | int err; | 2016 | int err; |
2002 | u32 mask; | 2017 | u32 mask; |
2003 | struct cfg80211_registered_device *drv; | 2018 | struct cfg80211_registered_device *drv; |
2004 | struct net_device *dev; | 2019 | struct net_device *dev; |
2005 | struct mesh_config cfg; | 2020 | struct mesh_config cfg; |
2006 | struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; | 2021 | struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; |
2007 | struct nlattr *parent_attr; | 2022 | struct nlattr *parent_attr; |
2008 | 2023 | ||
2009 | parent_attr = info->attrs[NL80211_ATTR_MESH_PARAMS]; | 2024 | parent_attr = info->attrs[NL80211_ATTR_MESH_PARAMS]; |
2010 | if (!parent_attr) | 2025 | if (!parent_attr) |
2011 | return -EINVAL; | 2026 | return -EINVAL; |
2012 | if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, | 2027 | if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, |
2013 | parent_attr, nl80211_meshconf_params_policy)) | 2028 | parent_attr, nl80211_meshconf_params_policy)) |
2014 | return -EINVAL; | 2029 | return -EINVAL; |
2015 | 2030 | ||
2016 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 2031 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
2017 | if (err) | 2032 | if (err) |
2018 | return err; | 2033 | return err; |
2019 | 2034 | ||
2020 | /* This makes sure that there aren't more than 32 mesh config | 2035 | /* This makes sure that there aren't more than 32 mesh config |
2021 | * parameters (otherwise our bitfield scheme would not work.) */ | 2036 | * parameters (otherwise our bitfield scheme would not work.) */ |
2022 | BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); | 2037 | BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); |
2023 | 2038 | ||
2024 | /* Fill in the params struct */ | 2039 | /* Fill in the params struct */ |
2025 | mask = 0; | 2040 | mask = 0; |
2026 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, | 2041 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, |
2027 | mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16); | 2042 | mask, NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16); |
2028 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, | 2043 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, |
2029 | mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16); | 2044 | mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, nla_get_u16); |
2030 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, | 2045 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, |
2031 | mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16); | 2046 | mask, NL80211_MESHCONF_HOLDING_TIMEOUT, nla_get_u16); |
2032 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, | 2047 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, |
2033 | mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16); | 2048 | mask, NL80211_MESHCONF_MAX_PEER_LINKS, nla_get_u16); |
2034 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, | 2049 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, |
2035 | mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8); | 2050 | mask, NL80211_MESHCONF_MAX_RETRIES, nla_get_u8); |
2036 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, | 2051 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, |
2037 | mask, NL80211_MESHCONF_TTL, nla_get_u8); | 2052 | mask, NL80211_MESHCONF_TTL, nla_get_u8); |
2038 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, | 2053 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, |
2039 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); | 2054 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); |
2040 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, | 2055 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, |
2041 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 2056 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
2042 | nla_get_u8); | 2057 | nla_get_u8); |
2043 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, | 2058 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, |
2044 | mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32); | 2059 | mask, NL80211_MESHCONF_PATH_REFRESH_TIME, nla_get_u32); |
2045 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, | 2060 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, |
2046 | mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | 2061 | mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, |
2047 | nla_get_u16); | 2062 | nla_get_u16); |
2048 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, | 2063 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, |
2049 | mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | 2064 | mask, NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, |
2050 | nla_get_u32); | 2065 | nla_get_u32); |
2051 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, | 2066 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, |
2052 | mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | 2067 | mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, |
2053 | nla_get_u16); | 2068 | nla_get_u16); |
2054 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | 2069 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
2055 | dot11MeshHWMPnetDiameterTraversalTime, | 2070 | dot11MeshHWMPnetDiameterTraversalTime, |
2056 | mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | 2071 | mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
2057 | nla_get_u16); | 2072 | nla_get_u16); |
2058 | 2073 | ||
2059 | /* Apply changes */ | 2074 | /* Apply changes */ |
2060 | rtnl_lock(); | 2075 | rtnl_lock(); |
2061 | err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); | 2076 | err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); |
2062 | rtnl_unlock(); | 2077 | rtnl_unlock(); |
2063 | 2078 | ||
2064 | /* cleanup */ | 2079 | /* cleanup */ |
2065 | cfg80211_put_dev(drv); | 2080 | cfg80211_put_dev(drv); |
2066 | dev_put(dev); | 2081 | dev_put(dev); |
2067 | return err; | 2082 | return err; |
2068 | } | 2083 | } |
2069 | 2084 | ||
2070 | #undef FILL_IN_MESH_PARAM_IF_SET | 2085 | #undef FILL_IN_MESH_PARAM_IF_SET |
2071 | 2086 | ||
2072 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 2087 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
2073 | { | 2088 | { |
2074 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; | 2089 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; |
2075 | struct nlattr *nl_reg_rule; | 2090 | struct nlattr *nl_reg_rule; |
2076 | char *alpha2 = NULL; | 2091 | char *alpha2 = NULL; |
2077 | int rem_reg_rules = 0, r = 0; | 2092 | int rem_reg_rules = 0, r = 0; |
2078 | u32 num_rules = 0, rule_idx = 0, size_of_regd; | 2093 | u32 num_rules = 0, rule_idx = 0, size_of_regd; |
2079 | struct ieee80211_regdomain *rd = NULL; | 2094 | struct ieee80211_regdomain *rd = NULL; |
2080 | 2095 | ||
2081 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) | 2096 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) |
2082 | return -EINVAL; | 2097 | return -EINVAL; |
2083 | 2098 | ||
2084 | if (!info->attrs[NL80211_ATTR_REG_RULES]) | 2099 | if (!info->attrs[NL80211_ATTR_REG_RULES]) |
2085 | return -EINVAL; | 2100 | return -EINVAL; |
2086 | 2101 | ||
2087 | alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); | 2102 | alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); |
2088 | 2103 | ||
2089 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 2104 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
2090 | rem_reg_rules) { | 2105 | rem_reg_rules) { |
2091 | num_rules++; | 2106 | num_rules++; |
2092 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) | 2107 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) |
2093 | goto bad_reg; | 2108 | goto bad_reg; |
2094 | } | 2109 | } |
2095 | 2110 | ||
2096 | if (!reg_is_valid_request(alpha2)) | 2111 | if (!reg_is_valid_request(alpha2)) |
2097 | return -EINVAL; | 2112 | return -EINVAL; |
2098 | 2113 | ||
2099 | size_of_regd = sizeof(struct ieee80211_regdomain) + | 2114 | size_of_regd = sizeof(struct ieee80211_regdomain) + |
2100 | (num_rules * sizeof(struct ieee80211_reg_rule)); | 2115 | (num_rules * sizeof(struct ieee80211_reg_rule)); |
2101 | 2116 | ||
2102 | rd = kzalloc(size_of_regd, GFP_KERNEL); | 2117 | rd = kzalloc(size_of_regd, GFP_KERNEL); |
2103 | if (!rd) | 2118 | if (!rd) |
2104 | return -ENOMEM; | 2119 | return -ENOMEM; |
2105 | 2120 | ||
2106 | rd->n_reg_rules = num_rules; | 2121 | rd->n_reg_rules = num_rules; |
2107 | rd->alpha2[0] = alpha2[0]; | 2122 | rd->alpha2[0] = alpha2[0]; |
2108 | rd->alpha2[1] = alpha2[1]; | 2123 | rd->alpha2[1] = alpha2[1]; |
2109 | 2124 | ||
2110 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 2125 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
2111 | rem_reg_rules) { | 2126 | rem_reg_rules) { |
2112 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, | 2127 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, |
2113 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), | 2128 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), |
2114 | reg_rule_policy); | 2129 | reg_rule_policy); |
2115 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); | 2130 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); |
2116 | if (r) | 2131 | if (r) |
2117 | goto bad_reg; | 2132 | goto bad_reg; |
2118 | 2133 | ||
2119 | rule_idx++; | 2134 | rule_idx++; |
2120 | 2135 | ||
2121 | if (rule_idx > NL80211_MAX_SUPP_REG_RULES) | 2136 | if (rule_idx > NL80211_MAX_SUPP_REG_RULES) |
2122 | goto bad_reg; | 2137 | goto bad_reg; |
2123 | } | 2138 | } |
2124 | 2139 | ||
2125 | BUG_ON(rule_idx != num_rules); | 2140 | BUG_ON(rule_idx != num_rules); |
2126 | 2141 | ||
2127 | mutex_lock(&cfg80211_drv_mutex); | 2142 | mutex_lock(&cfg80211_drv_mutex); |
2128 | r = set_regdom(rd); | 2143 | r = set_regdom(rd); |
2129 | mutex_unlock(&cfg80211_drv_mutex); | 2144 | mutex_unlock(&cfg80211_drv_mutex); |
2130 | return r; | 2145 | return r; |
2131 | 2146 | ||
2132 | bad_reg: | 2147 | bad_reg: |
2133 | kfree(rd); | 2148 | kfree(rd); |
2134 | return -EINVAL; | 2149 | return -EINVAL; |
2135 | } | 2150 | } |
2136 | 2151 | ||
2137 | static struct genl_ops nl80211_ops[] = { | 2152 | static struct genl_ops nl80211_ops[] = { |
2138 | { | 2153 | { |
2139 | .cmd = NL80211_CMD_GET_WIPHY, | 2154 | .cmd = NL80211_CMD_GET_WIPHY, |
2140 | .doit = nl80211_get_wiphy, | 2155 | .doit = nl80211_get_wiphy, |
2141 | .dumpit = nl80211_dump_wiphy, | 2156 | .dumpit = nl80211_dump_wiphy, |
2142 | .policy = nl80211_policy, | 2157 | .policy = nl80211_policy, |
2143 | /* can be retrieved by unprivileged users */ | 2158 | /* can be retrieved by unprivileged users */ |
2144 | }, | 2159 | }, |
2145 | { | 2160 | { |
2146 | .cmd = NL80211_CMD_SET_WIPHY, | 2161 | .cmd = NL80211_CMD_SET_WIPHY, |
2147 | .doit = nl80211_set_wiphy, | 2162 | .doit = nl80211_set_wiphy, |
2148 | .policy = nl80211_policy, | 2163 | .policy = nl80211_policy, |
2149 | .flags = GENL_ADMIN_PERM, | 2164 | .flags = GENL_ADMIN_PERM, |
2150 | }, | 2165 | }, |
2151 | { | 2166 | { |
2152 | .cmd = NL80211_CMD_GET_INTERFACE, | 2167 | .cmd = NL80211_CMD_GET_INTERFACE, |
2153 | .doit = nl80211_get_interface, | 2168 | .doit = nl80211_get_interface, |
2154 | .dumpit = nl80211_dump_interface, | 2169 | .dumpit = nl80211_dump_interface, |
2155 | .policy = nl80211_policy, | 2170 | .policy = nl80211_policy, |
2156 | /* can be retrieved by unprivileged users */ | 2171 | /* can be retrieved by unprivileged users */ |
2157 | }, | 2172 | }, |
2158 | { | 2173 | { |
2159 | .cmd = NL80211_CMD_SET_INTERFACE, | 2174 | .cmd = NL80211_CMD_SET_INTERFACE, |
2160 | .doit = nl80211_set_interface, | 2175 | .doit = nl80211_set_interface, |
2161 | .policy = nl80211_policy, | 2176 | .policy = nl80211_policy, |
2162 | .flags = GENL_ADMIN_PERM, | 2177 | .flags = GENL_ADMIN_PERM, |
2163 | }, | 2178 | }, |
2164 | { | 2179 | { |
2165 | .cmd = NL80211_CMD_NEW_INTERFACE, | 2180 | .cmd = NL80211_CMD_NEW_INTERFACE, |
2166 | .doit = nl80211_new_interface, | 2181 | .doit = nl80211_new_interface, |
2167 | .policy = nl80211_policy, | 2182 | .policy = nl80211_policy, |
2168 | .flags = GENL_ADMIN_PERM, | 2183 | .flags = GENL_ADMIN_PERM, |
2169 | }, | 2184 | }, |
2170 | { | 2185 | { |
2171 | .cmd = NL80211_CMD_DEL_INTERFACE, | 2186 | .cmd = NL80211_CMD_DEL_INTERFACE, |
2172 | .doit = nl80211_del_interface, | 2187 | .doit = nl80211_del_interface, |
2173 | .policy = nl80211_policy, | 2188 | .policy = nl80211_policy, |
2174 | .flags = GENL_ADMIN_PERM, | 2189 | .flags = GENL_ADMIN_PERM, |
2175 | }, | 2190 | }, |
2176 | { | 2191 | { |
2177 | .cmd = NL80211_CMD_GET_KEY, | 2192 | .cmd = NL80211_CMD_GET_KEY, |
2178 | .doit = nl80211_get_key, | 2193 | .doit = nl80211_get_key, |
2179 | .policy = nl80211_policy, | 2194 | .policy = nl80211_policy, |
2180 | .flags = GENL_ADMIN_PERM, | 2195 | .flags = GENL_ADMIN_PERM, |
2181 | }, | 2196 | }, |
2182 | { | 2197 | { |
2183 | .cmd = NL80211_CMD_SET_KEY, | 2198 | .cmd = NL80211_CMD_SET_KEY, |
2184 | .doit = nl80211_set_key, | 2199 | .doit = nl80211_set_key, |
2185 | .policy = nl80211_policy, | 2200 | .policy = nl80211_policy, |
2186 | .flags = GENL_ADMIN_PERM, | 2201 | .flags = GENL_ADMIN_PERM, |
2187 | }, | 2202 | }, |
2188 | { | 2203 | { |
2189 | .cmd = NL80211_CMD_NEW_KEY, | 2204 | .cmd = NL80211_CMD_NEW_KEY, |
2190 | .doit = nl80211_new_key, | 2205 | .doit = nl80211_new_key, |
2191 | .policy = nl80211_policy, | 2206 | .policy = nl80211_policy, |
2192 | .flags = GENL_ADMIN_PERM, | 2207 | .flags = GENL_ADMIN_PERM, |
2193 | }, | 2208 | }, |
2194 | { | 2209 | { |
2195 | .cmd = NL80211_CMD_DEL_KEY, | 2210 | .cmd = NL80211_CMD_DEL_KEY, |
2196 | .doit = nl80211_del_key, | 2211 | .doit = nl80211_del_key, |
2197 | .policy = nl80211_policy, | 2212 | .policy = nl80211_policy, |
2198 | .flags = GENL_ADMIN_PERM, | 2213 | .flags = GENL_ADMIN_PERM, |
2199 | }, | 2214 | }, |
2200 | { | 2215 | { |
2201 | .cmd = NL80211_CMD_SET_BEACON, | 2216 | .cmd = NL80211_CMD_SET_BEACON, |
2202 | .policy = nl80211_policy, | 2217 | .policy = nl80211_policy, |
2203 | .flags = GENL_ADMIN_PERM, | 2218 | .flags = GENL_ADMIN_PERM, |
2204 | .doit = nl80211_addset_beacon, | 2219 | .doit = nl80211_addset_beacon, |
2205 | }, | 2220 | }, |
2206 | { | 2221 | { |
2207 | .cmd = NL80211_CMD_NEW_BEACON, | 2222 | .cmd = NL80211_CMD_NEW_BEACON, |
2208 | .policy = nl80211_policy, | 2223 | .policy = nl80211_policy, |
2209 | .flags = GENL_ADMIN_PERM, | 2224 | .flags = GENL_ADMIN_PERM, |
2210 | .doit = nl80211_addset_beacon, | 2225 | .doit = nl80211_addset_beacon, |
2211 | }, | 2226 | }, |
2212 | { | 2227 | { |
2213 | .cmd = NL80211_CMD_DEL_BEACON, | 2228 | .cmd = NL80211_CMD_DEL_BEACON, |
2214 | .policy = nl80211_policy, | 2229 | .policy = nl80211_policy, |
2215 | .flags = GENL_ADMIN_PERM, | 2230 | .flags = GENL_ADMIN_PERM, |
2216 | .doit = nl80211_del_beacon, | 2231 | .doit = nl80211_del_beacon, |
2217 | }, | 2232 | }, |
2218 | { | 2233 | { |
2219 | .cmd = NL80211_CMD_GET_STATION, | 2234 | .cmd = NL80211_CMD_GET_STATION, |
2220 | .doit = nl80211_get_station, | 2235 | .doit = nl80211_get_station, |
2221 | .dumpit = nl80211_dump_station, | 2236 | .dumpit = nl80211_dump_station, |
2222 | .policy = nl80211_policy, | 2237 | .policy = nl80211_policy, |
2223 | .flags = GENL_ADMIN_PERM, | 2238 | .flags = GENL_ADMIN_PERM, |
2224 | }, | 2239 | }, |
2225 | { | 2240 | { |
2226 | .cmd = NL80211_CMD_SET_STATION, | 2241 | .cmd = NL80211_CMD_SET_STATION, |
2227 | .doit = nl80211_set_station, | 2242 | .doit = nl80211_set_station, |
2228 | .policy = nl80211_policy, | 2243 | .policy = nl80211_policy, |
2229 | .flags = GENL_ADMIN_PERM, | 2244 | .flags = GENL_ADMIN_PERM, |
2230 | }, | 2245 | }, |
2231 | { | 2246 | { |
2232 | .cmd = NL80211_CMD_NEW_STATION, | 2247 | .cmd = NL80211_CMD_NEW_STATION, |
2233 | .doit = nl80211_new_station, | 2248 | .doit = nl80211_new_station, |
2234 | .policy = nl80211_policy, | 2249 | .policy = nl80211_policy, |
2235 | .flags = GENL_ADMIN_PERM, | 2250 | .flags = GENL_ADMIN_PERM, |
2236 | }, | 2251 | }, |
2237 | { | 2252 | { |
2238 | .cmd = NL80211_CMD_DEL_STATION, | 2253 | .cmd = NL80211_CMD_DEL_STATION, |
2239 | .doit = nl80211_del_station, | 2254 | .doit = nl80211_del_station, |
2240 | .policy = nl80211_policy, | 2255 | .policy = nl80211_policy, |
2241 | .flags = GENL_ADMIN_PERM, | 2256 | .flags = GENL_ADMIN_PERM, |
2242 | }, | 2257 | }, |
2243 | { | 2258 | { |
2244 | .cmd = NL80211_CMD_GET_MPATH, | 2259 | .cmd = NL80211_CMD_GET_MPATH, |
2245 | .doit = nl80211_get_mpath, | 2260 | .doit = nl80211_get_mpath, |
2246 | .dumpit = nl80211_dump_mpath, | 2261 | .dumpit = nl80211_dump_mpath, |
2247 | .policy = nl80211_policy, | 2262 | .policy = nl80211_policy, |
2248 | .flags = GENL_ADMIN_PERM, | 2263 | .flags = GENL_ADMIN_PERM, |
2249 | }, | 2264 | }, |
2250 | { | 2265 | { |
2251 | .cmd = NL80211_CMD_SET_MPATH, | 2266 | .cmd = NL80211_CMD_SET_MPATH, |
2252 | .doit = nl80211_set_mpath, | 2267 | .doit = nl80211_set_mpath, |
2253 | .policy = nl80211_policy, | 2268 | .policy = nl80211_policy, |
2254 | .flags = GENL_ADMIN_PERM, | 2269 | .flags = GENL_ADMIN_PERM, |
2255 | }, | 2270 | }, |
2256 | { | 2271 | { |
2257 | .cmd = NL80211_CMD_NEW_MPATH, | 2272 | .cmd = NL80211_CMD_NEW_MPATH, |
2258 | .doit = nl80211_new_mpath, | 2273 | .doit = nl80211_new_mpath, |
2259 | .policy = nl80211_policy, | 2274 | .policy = nl80211_policy, |
2260 | .flags = GENL_ADMIN_PERM, | 2275 | .flags = GENL_ADMIN_PERM, |
2261 | }, | 2276 | }, |
2262 | { | 2277 | { |
2263 | .cmd = NL80211_CMD_DEL_MPATH, | 2278 | .cmd = NL80211_CMD_DEL_MPATH, |
2264 | .doit = nl80211_del_mpath, | 2279 | .doit = nl80211_del_mpath, |
2265 | .policy = nl80211_policy, | 2280 | .policy = nl80211_policy, |
2266 | .flags = GENL_ADMIN_PERM, | 2281 | .flags = GENL_ADMIN_PERM, |
2267 | }, | 2282 | }, |
2268 | { | 2283 | { |
2269 | .cmd = NL80211_CMD_SET_BSS, | 2284 | .cmd = NL80211_CMD_SET_BSS, |
2270 | .doit = nl80211_set_bss, | 2285 | .doit = nl80211_set_bss, |
2271 | .policy = nl80211_policy, | 2286 | .policy = nl80211_policy, |
2272 | .flags = GENL_ADMIN_PERM, | 2287 | .flags = GENL_ADMIN_PERM, |
2273 | }, | 2288 | }, |
2274 | { | 2289 | { |
2275 | .cmd = NL80211_CMD_SET_REG, | 2290 | .cmd = NL80211_CMD_SET_REG, |
2276 | .doit = nl80211_set_reg, | 2291 | .doit = nl80211_set_reg, |
2277 | .policy = nl80211_policy, | 2292 | .policy = nl80211_policy, |
2278 | .flags = GENL_ADMIN_PERM, | 2293 | .flags = GENL_ADMIN_PERM, |
2279 | }, | 2294 | }, |
2280 | { | 2295 | { |
2281 | .cmd = NL80211_CMD_REQ_SET_REG, | 2296 | .cmd = NL80211_CMD_REQ_SET_REG, |
2282 | .doit = nl80211_req_set_reg, | 2297 | .doit = nl80211_req_set_reg, |
2283 | .policy = nl80211_policy, | 2298 | .policy = nl80211_policy, |
2284 | .flags = GENL_ADMIN_PERM, | 2299 | .flags = GENL_ADMIN_PERM, |
2285 | }, | 2300 | }, |
2286 | { | 2301 | { |
2287 | .cmd = NL80211_CMD_GET_MESH_PARAMS, | 2302 | .cmd = NL80211_CMD_GET_MESH_PARAMS, |
2288 | .doit = nl80211_get_mesh_params, | 2303 | .doit = nl80211_get_mesh_params, |
2289 | .policy = nl80211_policy, | 2304 | .policy = nl80211_policy, |
2290 | /* can be retrieved by unprivileged users */ | 2305 | /* can be retrieved by unprivileged users */ |
2291 | }, | 2306 | }, |
2292 | { | 2307 | { |
2293 | .cmd = NL80211_CMD_SET_MESH_PARAMS, | 2308 | .cmd = NL80211_CMD_SET_MESH_PARAMS, |
2294 | .doit = nl80211_set_mesh_params, | 2309 | .doit = nl80211_set_mesh_params, |
2295 | .policy = nl80211_policy, | 2310 | .policy = nl80211_policy, |
2296 | .flags = GENL_ADMIN_PERM, | 2311 | .flags = GENL_ADMIN_PERM, |
2297 | }, | 2312 | }, |
2298 | }; | 2313 | }; |
2299 | 2314 | ||
2300 | /* multicast groups */ | 2315 | /* multicast groups */ |
2301 | static struct genl_multicast_group nl80211_config_mcgrp = { | 2316 | static struct genl_multicast_group nl80211_config_mcgrp = { |
2302 | .name = "config", | 2317 | .name = "config", |
2303 | }; | 2318 | }; |
2304 | 2319 | ||
2305 | /* notification functions */ | 2320 | /* notification functions */ |
2306 | 2321 | ||
2307 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | 2322 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) |
2308 | { | 2323 | { |
2309 | struct sk_buff *msg; | 2324 | struct sk_buff *msg; |
2310 | 2325 | ||
2311 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 2326 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
2312 | if (!msg) | 2327 | if (!msg) |
2313 | return; | 2328 | return; |
2314 | 2329 | ||
2315 | if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) { | 2330 | if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) { |
2316 | nlmsg_free(msg); | 2331 | nlmsg_free(msg); |
2317 | return; | 2332 | return; |
2318 | } | 2333 | } |
2319 | 2334 | ||
2320 | genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); | 2335 | genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); |
2321 | } | 2336 | } |
2322 | 2337 | ||
2323 | /* initialisation/exit functions */ | 2338 | /* initialisation/exit functions */ |
2324 | 2339 | ||
2325 | int nl80211_init(void) | 2340 | int nl80211_init(void) |
2326 | { | 2341 | { |
2327 | int err, i; | 2342 | int err, i; |
2328 | 2343 | ||
2329 | err = genl_register_family(&nl80211_fam); | 2344 | err = genl_register_family(&nl80211_fam); |
2330 | if (err) | 2345 | if (err) |
2331 | return err; | 2346 | return err; |
2332 | 2347 | ||
2333 | for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) { | 2348 | for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) { |
2334 | err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]); | 2349 | err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]); |
2335 | if (err) | 2350 | if (err) |
2336 | goto err_out; | 2351 | goto err_out; |
2337 | } | 2352 | } |
2338 | 2353 | ||
2339 | err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp); | 2354 | err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp); |
2340 | if (err) | 2355 | if (err) |
2341 | goto err_out; | 2356 | goto err_out; |
2342 | 2357 | ||
2343 | return 0; | 2358 | return 0; |
2344 | err_out: | 2359 | err_out: |
2345 | genl_unregister_family(&nl80211_fam); | 2360 | genl_unregister_family(&nl80211_fam); |
2346 | return err; | 2361 | return err; |
2347 | } | 2362 | } |
2348 | 2363 | ||
2349 | void nl80211_exit(void) | 2364 | void nl80211_exit(void) |
2350 | { | 2365 | { |
2351 | genl_unregister_family(&nl80211_fam); | 2366 | genl_unregister_family(&nl80211_fam); |
2352 | } | 2367 | } |
2353 | 2368 |