diff options
Diffstat (limited to 'net/wireless/radiotap.c')
-rw-r--r-- | net/wireless/radiotap.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index 1332c445d1c7..dbe35e138e94 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * See COPYING for more details. | 14 | * See COPYING for more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
17 | #include <net/cfg80211.h> | 18 | #include <net/cfg80211.h> |
18 | #include <net/ieee80211_radiotap.h> | 19 | #include <net/ieee80211_radiotap.h> |
19 | #include <asm/unaligned.h> | 20 | #include <asm/unaligned.h> |
@@ -45,7 +46,7 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = { | |||
45 | }; | 46 | }; |
46 | 47 | ||
47 | static const struct ieee80211_radiotap_namespace radiotap_ns = { | 48 | static const struct ieee80211_radiotap_namespace radiotap_ns = { |
48 | .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]), | 49 | .n_bits = ARRAY_SIZE(rtap_namespace_sizes), |
49 | .align_size = rtap_namespace_sizes, | 50 | .align_size = rtap_namespace_sizes, |
50 | }; | 51 | }; |
51 | 52 | ||
@@ -200,7 +201,7 @@ int ieee80211_radiotap_iterator_next( | |||
200 | { | 201 | { |
201 | while (1) { | 202 | while (1) { |
202 | int hit = 0; | 203 | int hit = 0; |
203 | int pad, align, size, subns, vnslen; | 204 | int pad, align, size, subns; |
204 | uint32_t oui; | 205 | uint32_t oui; |
205 | 206 | ||
206 | /* if no more EXT bits, that's it */ | 207 | /* if no more EXT bits, that's it */ |
@@ -260,6 +261,27 @@ int ieee80211_radiotap_iterator_next( | |||
260 | if (pad) | 261 | if (pad) |
261 | iterator->_arg += align - pad; | 262 | iterator->_arg += align - pad; |
262 | 263 | ||
264 | if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) { | ||
265 | int vnslen; | ||
266 | |||
267 | if ((unsigned long)iterator->_arg + size - | ||
268 | (unsigned long)iterator->_rtheader > | ||
269 | (unsigned long)iterator->_max_length) | ||
270 | return -EINVAL; | ||
271 | |||
272 | oui = (*iterator->_arg << 16) | | ||
273 | (*(iterator->_arg + 1) << 8) | | ||
274 | *(iterator->_arg + 2); | ||
275 | subns = *(iterator->_arg + 3); | ||
276 | |||
277 | find_ns(iterator, oui, subns); | ||
278 | |||
279 | vnslen = get_unaligned_le16(iterator->_arg + 4); | ||
280 | iterator->_next_ns_data = iterator->_arg + size + vnslen; | ||
281 | if (!iterator->current_namespace) | ||
282 | size += vnslen; | ||
283 | } | ||
284 | |||
263 | /* | 285 | /* |
264 | * this is what we will return to user, but we need to | 286 | * this is what we will return to user, but we need to |
265 | * move on first so next call has something fresh to test | 287 | * move on first so next call has something fresh to test |
@@ -286,40 +308,25 @@ int ieee80211_radiotap_iterator_next( | |||
286 | /* these special ones are valid in each bitmap word */ | 308 | /* these special ones are valid in each bitmap word */ |
287 | switch (iterator->_arg_index % 32) { | 309 | switch (iterator->_arg_index % 32) { |
288 | case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: | 310 | case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: |
289 | iterator->_bitmap_shifter >>= 1; | ||
290 | iterator->_arg_index++; | ||
291 | |||
292 | iterator->_reset_on_ext = 1; | 311 | iterator->_reset_on_ext = 1; |
293 | 312 | ||
294 | vnslen = get_unaligned_le16(iterator->this_arg + 4); | ||
295 | iterator->_next_ns_data = iterator->_arg + vnslen; | ||
296 | oui = (*iterator->this_arg << 16) | | ||
297 | (*(iterator->this_arg + 1) << 8) | | ||
298 | *(iterator->this_arg + 2); | ||
299 | subns = *(iterator->this_arg + 3); | ||
300 | |||
301 | find_ns(iterator, oui, subns); | ||
302 | |||
303 | iterator->is_radiotap_ns = 0; | 313 | iterator->is_radiotap_ns = 0; |
304 | /* allow parsers to show this information */ | 314 | /* |
315 | * If parser didn't register this vendor | ||
316 | * namespace with us, allow it to show it | ||
317 | * as 'raw. Do do that, set argument index | ||
318 | * to vendor namespace. | ||
319 | */ | ||
305 | iterator->this_arg_index = | 320 | iterator->this_arg_index = |
306 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE; | 321 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE; |
307 | iterator->this_arg_size += vnslen; | 322 | if (!iterator->current_namespace) |
308 | if ((unsigned long)iterator->this_arg + | 323 | hit = 1; |
309 | iterator->this_arg_size - | 324 | goto next_entry; |
310 | (unsigned long)iterator->_rtheader > | ||
311 | (unsigned long)(unsigned long)iterator->_max_length) | ||
312 | return -EINVAL; | ||
313 | hit = 1; | ||
314 | break; | ||
315 | case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: | 325 | case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: |
316 | iterator->_bitmap_shifter >>= 1; | ||
317 | iterator->_arg_index++; | ||
318 | |||
319 | iterator->_reset_on_ext = 1; | 326 | iterator->_reset_on_ext = 1; |
320 | iterator->current_namespace = &radiotap_ns; | 327 | iterator->current_namespace = &radiotap_ns; |
321 | iterator->is_radiotap_ns = 1; | 328 | iterator->is_radiotap_ns = 1; |
322 | break; | 329 | goto next_entry; |
323 | case IEEE80211_RADIOTAP_EXT: | 330 | case IEEE80211_RADIOTAP_EXT: |
324 | /* | 331 | /* |
325 | * bit 31 was set, there is more | 332 | * bit 31 was set, there is more |