Codebase list radiotap-library / a80b041
New upstream version 0~20200622 Sophie Brun 3 years ago
30 changed file(s) with 981 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 *.o
1 *~
2 parse
3 build
4 *.so
5 CMakeCache.txt
6 CMakeFiles
7 cmake_install.cmake
0 cmake_minimum_required(VERSION 2.6)
1 project(radiotap)
2
3 add_definitions("-D_BSD_SOURCE -DRADIOTAP_SUPPORT_OVERRIDES")
4
5 add_library(radiotap SHARED radiotap.c)
6 set_target_properties(radiotap PROPERTIES
7 COMPILE_FLAGS "-Wall -Wextra")
8
9 install(TARGETS radiotap DESTINATION lib)
10 install(FILES radiotap.h radiotap_iter.h DESTINATION include)
11
12 add_executable(parse parse.c)
13 set_target_properties(parse PROPERTIES
14 COMPILE_FLAGS "-Wall -Wextra")
15 target_link_libraries(parse radiotap)
16
17
18 add_custom_target(radiotap_check ALL
19 COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/check/check.sh ${CMAKE_CURRENT_BINARY_DIR}
20 DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/check/*
21 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/check/
22 COMMENT "Check examples")
23 add_dependencies(radiotap_check parse)
0 Copyright (c) 2007-2009 Andy Green <[email protected]>
1 Copyright (c) 2007-2009 Johannes Berg <[email protected]>
2
3 Permission to use, copy, modify, and/or distribute this software for any
4 purpose with or without fee is hereby granted, provided that the above
5 copyright notice and this permission notice appear in all copies.
6
7 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Binary diff not shown
0 TSFT: 9833440827789222417
Binary diff not shown
0 TSFT: 9833440827789222417
1 TSFT: 1225260500033256362
0 --fcshdr
Binary diff not shown
0 TSFT: 9833440827789222417
1 FCS in header: ddccbbaa
Binary diff not shown
0 TSFT: 9833440827789222417
1 TSFT: 1225260500033256362
Binary diff not shown
0 TSFT: 9833440827789222417
1 vendor NS (00-00-00:1, 4 bytes)
2 ff ee dd cc
3 TSFT: 1225260500033256362
Binary diff not shown
0 TSFT: 9833440827789222417
1 00:00:00-00|52: ff/ee/dd/cc
2 TSFT: 1225260500033256362
Binary diff not shown
0 TSFT: 9833440827789222417
1 00:00:00-00|0: ff/ee/dd/cc
2 TSFT: 1225260500033256362
Binary diff not shown
0 flags: 33
0 #!/bin/sh
1
2 bin="$1/parse"
3
4 for t in *.bin ; do
5 echo -n "Checking $t: "
6 args=""
7 base="$(basename "$t" .bin)"
8 if [ -f "$base.args" ] ; then
9 args="$(cat "$base.args")"
10 fi
11 "$bin" $args $t | diff "$base.out" - && echo "OK" || echo "FAIL"
12 done
Binary diff not shown
0 flags: 10
1 rate: 1.000000
2 RX flags: 0000
3 malformed radiotap data
Binary diff not shown
0 flags: 10
1 rate: 1.000000
2 RX flags: 0000
3 vendor NS (ff-ff-ff:255, 2 bytes)
4 de ad
5 rate: 2.000000
0 #include <sys/types.h>
1 #include <sys/stat.h>
2 #include <sys/mman.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #if defined(__APPLE__)
9 #include <machine/endian.h>
10 #else
11 #include <endian.h>
12 #endif
13
14 #include "radiotap_iter.h"
15
16 static int fcshdr = 0;
17
18 static const struct radiotap_align_size align_size_000000_00[] = {
19 [0] = { .align = 1, .size = 4, },
20 [52] = { .align = 1, .size = 4, },
21 };
22
23 static const struct ieee80211_radiotap_namespace vns_array[] = {
24 {
25 .oui = 0x000000,
26 .subns = 0,
27 .n_bits = sizeof(align_size_000000_00),
28 .align_size = align_size_000000_00,
29 },
30 };
31
32 static const struct ieee80211_radiotap_vendor_namespaces vns = {
33 .ns = vns_array,
34 .n_ns = sizeof(vns_array)/sizeof(vns_array[0]),
35 };
36
37 static void print_radiotap_namespace(struct ieee80211_radiotap_iterator *iter)
38 {
39 switch (iter->this_arg_index) {
40 case IEEE80211_RADIOTAP_TSFT:
41 printf("\tTSFT: %llu\n", le64toh(*(unsigned long long *)iter->this_arg));
42 break;
43 case IEEE80211_RADIOTAP_FLAGS:
44 printf("\tflags: %02x\n", *iter->this_arg);
45 break;
46 case IEEE80211_RADIOTAP_RATE:
47 printf("\trate: %lf\n", (double)*iter->this_arg/2);
48 break;
49 case IEEE80211_RADIOTAP_CHANNEL:
50 case IEEE80211_RADIOTAP_FHSS:
51 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
52 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
53 case IEEE80211_RADIOTAP_LOCK_QUALITY:
54 case IEEE80211_RADIOTAP_TX_ATTENUATION:
55 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
56 case IEEE80211_RADIOTAP_DBM_TX_POWER:
57 case IEEE80211_RADIOTAP_ANTENNA:
58 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
59 case IEEE80211_RADIOTAP_DB_ANTNOISE:
60 case IEEE80211_RADIOTAP_TX_FLAGS:
61 break;
62 case IEEE80211_RADIOTAP_RX_FLAGS:
63 if (fcshdr) {
64 printf("\tFCS in header: %.8x\n",
65 le32toh(*(uint32_t *)iter->this_arg));
66 break;
67 }
68 printf("\tRX flags: %#.4x\n",
69 le16toh(*(uint16_t *)iter->this_arg));
70 break;
71 case IEEE80211_RADIOTAP_RTS_RETRIES:
72 case IEEE80211_RADIOTAP_DATA_RETRIES:
73 break;
74 default:
75 printf("\tBOGUS DATA\n");
76 break;
77 }
78 }
79
80 static void print_test_namespace(struct ieee80211_radiotap_iterator *iter)
81 {
82 switch (iter->this_arg_index) {
83 case 0:
84 case 52:
85 printf("\t00:00:00-00|%d: %.2x/%.2x/%.2x/%.2x\n",
86 iter->this_arg_index,
87 *iter->this_arg, *(iter->this_arg + 1),
88 *(iter->this_arg + 2), *(iter->this_arg + 3));
89 break;
90 default:
91 printf("\tBOGUS DATA - vendor ns %d\n", iter->this_arg_index);
92 break;
93 }
94 }
95
96 static const struct radiotap_override overrides[] = {
97 { .field = 14, .align = 4, .size = 4, }
98 };
99
100 int main(int argc, char *argv[])
101 {
102 struct ieee80211_radiotap_iterator iter;
103 struct stat statbuf;
104 int fd, err, fnidx = 1, i;
105 void *data;
106
107 if (argc != 2 && argc != 3) {
108 fprintf(stderr, "usage: parse [--fcshdr] <file>\n");
109 fprintf(stderr, " --fcshdr: read bit 14 as FCS\n");
110 return 2;
111 }
112
113 if (strcmp(argv[1], "--fcshdr") == 0) {
114 fcshdr = 1;
115 fnidx++;
116 }
117
118 fd = open(argv[fnidx], O_RDONLY);
119 if (fd < 0) {
120 fprintf(stderr, "cannot open file %s\n", argv[fnidx]);
121 return 2;
122 }
123
124 if (fstat(fd, &statbuf)) {
125 perror("fstat");
126 return 2;
127 }
128
129 data = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
130
131 err = ieee80211_radiotap_iterator_init(&iter, data, statbuf.st_size, &vns);
132 if (err) {
133 printf("malformed radiotap header (init returns %d)\n", err);
134 return 3;
135 }
136
137 if (fcshdr) {
138 iter.overrides = overrides;
139 iter.n_overrides = sizeof(overrides)/sizeof(overrides[0]);
140 }
141
142 while (!(err = ieee80211_radiotap_iterator_next(&iter))) {
143 if (iter.this_arg_index == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
144 printf("\tvendor NS (%.2x-%.2x-%.2x:%d, %d bytes)\n",
145 iter.this_arg[0], iter.this_arg[1],
146 iter.this_arg[2], iter.this_arg[3],
147 iter.this_arg_size - 6);
148 for (i = 6; i < iter.this_arg_size; i++) {
149 if (i % 8 == 6)
150 printf("\t\t");
151 else
152 printf(" ");
153 printf("%.2x", iter.this_arg[i]);
154 }
155 printf("\n");
156 } else if (iter.is_radiotap_ns)
157 print_radiotap_namespace(&iter);
158 else if (iter.current_namespace == &vns_array[0])
159 print_test_namespace(&iter);
160 }
161
162 if (err != -ENOENT) {
163 printf("malformed radiotap data\n");
164 return 3;
165 }
166
167 return 0;
168 }
0 #include <stddef.h>
1 #include <errno.h>
2 #if defined(__APPLE__)
3 #include <machine/endian.h>
4 #else
5 #include <endian.h>
6 #endif
7
8 #define le16_to_cpu le16toh
9 #define le32_to_cpu le32toh
10 #define get_unaligned(p) \
11 ({ \
12 struct packed_dummy_struct { \
13 typeof(*(p)) __val; \
14 } __attribute__((packed)) *__ptr = (void *) (p); \
15 \
16 __ptr->__val; \
17 })
18 #define get_unaligned_le16(p) le16_to_cpu(get_unaligned((uint16_t *)(p)))
19 #define get_unaligned_le32(p) le32_to_cpu(get_unaligned((uint32_t *)(p)))
0 /*
1 * Radiotap parser
2 *
3 * Copyright 2007 Andy Green <[email protected]>
4 * Copyright 2009 Johannes Berg <[email protected]>
5 *
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
8 * published by the Free Software Foundation.
9 *
10 * Alternatively, this software may be distributed under the terms of ISC
11 * license, see COPYING for more details.
12 */
13 #include "radiotap_iter.h"
14 #include "platform.h"
15
16 /* function prototypes and related defs are in radiotap_iter.h */
17
18 static const struct radiotap_align_size rtap_namespace_sizes[] = {
19 [IEEE80211_RADIOTAP_TSFT] = { .align = 8, .size = 8, },
20 [IEEE80211_RADIOTAP_FLAGS] = { .align = 1, .size = 1, },
21 [IEEE80211_RADIOTAP_RATE] = { .align = 1, .size = 1, },
22 [IEEE80211_RADIOTAP_CHANNEL] = { .align = 2, .size = 4, },
23 [IEEE80211_RADIOTAP_FHSS] = { .align = 2, .size = 2, },
24 [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = { .align = 1, .size = 1, },
25 [IEEE80211_RADIOTAP_DBM_ANTNOISE] = { .align = 1, .size = 1, },
26 [IEEE80211_RADIOTAP_LOCK_QUALITY] = { .align = 2, .size = 2, },
27 [IEEE80211_RADIOTAP_TX_ATTENUATION] = { .align = 2, .size = 2, },
28 [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = { .align = 2, .size = 2, },
29 [IEEE80211_RADIOTAP_DBM_TX_POWER] = { .align = 1, .size = 1, },
30 [IEEE80211_RADIOTAP_ANTENNA] = { .align = 1, .size = 1, },
31 [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = { .align = 1, .size = 1, },
32 [IEEE80211_RADIOTAP_DB_ANTNOISE] = { .align = 1, .size = 1, },
33 [IEEE80211_RADIOTAP_RX_FLAGS] = { .align = 2, .size = 2, },
34 [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, },
35 [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, },
36 [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
37 [IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, },
38 [IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, },
39 [IEEE80211_RADIOTAP_VHT] = { .align = 2, .size = 12, },
40 [IEEE80211_RADIOTAP_TIMESTAMP] = { .align = 8, .size = 12, },
41 /*
42 * add more here as they are defined in radiotap.h
43 */
44 };
45
46 static const struct ieee80211_radiotap_namespace radiotap_ns = {
47 .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]),
48 .align_size = rtap_namespace_sizes,
49 };
50
51 /**
52 * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
53 * @iterator: radiotap_iterator to initialize
54 * @radiotap_header: radiotap header to parse
55 * @max_length: total length we can parse into (eg, whole packet length)
56 *
57 * Returns: 0 or a negative error code if there is a problem.
58 *
59 * This function initializes an opaque iterator struct which can then
60 * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
61 * argument which is present in the header. It knows about extended
62 * present headers and handles them.
63 *
64 * How to use:
65 * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
66 * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
67 * checking for a good 0 return code. Then loop calling
68 * __ieee80211_radiotap_iterator_next()... it returns either 0,
69 * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
70 * The iterator's @this_arg member points to the start of the argument
71 * associated with the current argument index that is present, which can be
72 * found in the iterator's @this_arg_index member. This arg index corresponds
73 * to the IEEE80211_RADIOTAP_... defines.
74 *
75 * Radiotap header length:
76 * You can find the CPU-endian total radiotap header length in
77 * iterator->max_length after executing ieee80211_radiotap_iterator_init()
78 * successfully.
79 *
80 * Alignment Gotcha:
81 * You must take care when dereferencing iterator.this_arg
82 * for multibyte types... the pointer is not aligned. Use
83 * get_unaligned((type *)iterator.this_arg) to dereference
84 * iterator.this_arg for type "type" safely on all arches.
85 *
86 * Example code: parse.c
87 */
88
89 int ieee80211_radiotap_iterator_init(
90 struct ieee80211_radiotap_iterator *iterator,
91 struct ieee80211_radiotap_header *radiotap_header,
92 int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
93 {
94 /* must at least have the radiotap header */
95 if (max_length < (int)sizeof(struct ieee80211_radiotap_header))
96 return -EINVAL;
97
98 /* Linux only supports version 0 radiotap format */
99 if (radiotap_header->it_version)
100 return -EINVAL;
101
102 /* sanity check for allowed length and radiotap length field */
103 if (max_length < get_unaligned_le16(&radiotap_header->it_len))
104 return -EINVAL;
105
106 iterator->_rtheader = radiotap_header;
107 iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
108 iterator->_arg_index = 0;
109 iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
110 iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header);
111 iterator->_reset_on_ext = 0;
112 iterator->_next_bitmap = &radiotap_header->it_present;
113 iterator->_next_bitmap++;
114 iterator->_vns = vns;
115 iterator->current_namespace = &radiotap_ns;
116 iterator->is_radiotap_ns = 1;
117 #ifdef RADIOTAP_SUPPORT_OVERRIDES
118 iterator->n_overrides = 0;
119 iterator->overrides = NULL;
120 #endif
121
122 /* find payload start allowing for extended bitmap(s) */
123
124 if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
125 if ((unsigned long)iterator->_arg -
126 (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
127 (unsigned long)iterator->_max_length)
128 return -EINVAL;
129 while (get_unaligned_le32(iterator->_arg) &
130 (1 << IEEE80211_RADIOTAP_EXT)) {
131 iterator->_arg += sizeof(uint32_t);
132
133 /*
134 * check for insanity where the present bitmaps
135 * keep claiming to extend up to or even beyond the
136 * stated radiotap header length
137 */
138
139 if ((unsigned long)iterator->_arg -
140 (unsigned long)iterator->_rtheader +
141 sizeof(uint32_t) >
142 (unsigned long)iterator->_max_length)
143 return -EINVAL;
144 }
145
146 iterator->_arg += sizeof(uint32_t);
147
148 /*
149 * no need to check again for blowing past stated radiotap
150 * header length, because ieee80211_radiotap_iterator_next
151 * checks it before it is dereferenced
152 */
153 }
154
155 iterator->this_arg = iterator->_arg;
156
157 /* we are all initialized happily */
158
159 return 0;
160 }
161
162 static void find_ns(struct ieee80211_radiotap_iterator *iterator,
163 uint32_t oui, uint8_t subns)
164 {
165 int i;
166
167 iterator->current_namespace = NULL;
168
169 if (!iterator->_vns)
170 return;
171
172 for (i = 0; i < iterator->_vns->n_ns; i++) {
173 if (iterator->_vns->ns[i].oui != oui)
174 continue;
175 if (iterator->_vns->ns[i].subns != subns)
176 continue;
177
178 iterator->current_namespace = &iterator->_vns->ns[i];
179 break;
180 }
181 }
182
183 #ifdef RADIOTAP_SUPPORT_OVERRIDES
184 static int find_override(struct ieee80211_radiotap_iterator *iterator,
185 int *align, int *size)
186 {
187 int i;
188
189 if (!iterator->overrides)
190 return 0;
191
192 for (i = 0; i < iterator->n_overrides; i++) {
193 if (iterator->_arg_index == iterator->overrides[i].field) {
194 *align = iterator->overrides[i].align;
195 *size = iterator->overrides[i].size;
196 if (!*align) /* erroneous override */
197 return 0;
198 return 1;
199 }
200 }
201
202 return 0;
203 }
204 #endif
205
206
207 /**
208 * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
209 * @iterator: radiotap_iterator to move to next arg (if any)
210 *
211 * Returns: 0 if there is an argument to handle,
212 * -ENOENT if there are no more args or -EINVAL
213 * if there is something else wrong.
214 *
215 * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
216 * in @this_arg_index and sets @this_arg to point to the
217 * payload for the field. It takes care of alignment handling and extended
218 * present fields. @this_arg can be changed by the caller (eg,
219 * incremented to move inside a compound argument like
220 * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in
221 * little-endian format whatever the endianness of your CPU.
222 *
223 * Alignment Gotcha:
224 * You must take care when dereferencing iterator.this_arg
225 * for multibyte types... the pointer is not aligned. Use
226 * get_unaligned((type *)iterator.this_arg) to dereference
227 * iterator.this_arg for type "type" safely on all arches.
228 */
229
230 int ieee80211_radiotap_iterator_next(
231 struct ieee80211_radiotap_iterator *iterator)
232 {
233 while (1) {
234 int hit = 0;
235 int pad, align, size, subns;
236 uint32_t oui;
237
238 /* if no more EXT bits, that's it */
239 if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT &&
240 !(iterator->_bitmap_shifter & 1))
241 return -ENOENT;
242
243 if (!(iterator->_bitmap_shifter & 1))
244 goto next_entry; /* arg not present */
245
246 /* get alignment/size of data */
247 switch (iterator->_arg_index % 32) {
248 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
249 case IEEE80211_RADIOTAP_EXT:
250 align = 1;
251 size = 0;
252 break;
253 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
254 align = 2;
255 size = 6;
256 break;
257 default:
258 #ifdef RADIOTAP_SUPPORT_OVERRIDES
259 if (find_override(iterator, &align, &size)) {
260 /* all set */
261 } else
262 #endif
263 if (!iterator->current_namespace ||
264 iterator->_arg_index >= iterator->current_namespace->n_bits) {
265 if (iterator->current_namespace == &radiotap_ns)
266 return -ENOENT;
267 align = 0;
268 } else {
269 align = iterator->current_namespace->align_size[iterator->_arg_index].align;
270 size = iterator->current_namespace->align_size[iterator->_arg_index].size;
271 }
272 if (!align) {
273 /* skip all subsequent data */
274 iterator->_arg = iterator->_next_ns_data;
275 /* give up on this namespace */
276 iterator->current_namespace = NULL;
277 goto next_entry;
278 }
279 break;
280 }
281
282 /*
283 * arg is present, account for alignment padding
284 *
285 * Note that these alignments are relative to the start
286 * of the radiotap header. There is no guarantee
287 * that the radiotap header itself is aligned on any
288 * kind of boundary.
289 *
290 * The above is why get_unaligned() is used to dereference
291 * multibyte elements from the radiotap area.
292 */
293
294 pad = ((unsigned long)iterator->_arg -
295 (unsigned long)iterator->_rtheader) & (align - 1);
296
297 if (pad)
298 iterator->_arg += align - pad;
299
300 if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
301 int vnslen;
302
303 if ((unsigned long)iterator->_arg + size -
304 (unsigned long)iterator->_rtheader >
305 (unsigned long)iterator->_max_length)
306 return -EINVAL;
307
308 oui = (*iterator->_arg << 16) |
309 (*(iterator->_arg + 1) << 8) |
310 *(iterator->_arg + 2);
311 subns = *(iterator->_arg + 3);
312
313 find_ns(iterator, oui, subns);
314
315 vnslen = get_unaligned_le16(iterator->_arg + 4);
316 iterator->_next_ns_data = iterator->_arg + size + vnslen;
317 if (!iterator->current_namespace)
318 size += vnslen;
319 }
320
321 /*
322 * this is what we will return to user, but we need to
323 * move on first so next call has something fresh to test
324 */
325 iterator->this_arg_index = iterator->_arg_index;
326 iterator->this_arg = iterator->_arg;
327 iterator->this_arg_size = size;
328
329 /* internally move on the size of this arg */
330 iterator->_arg += size;
331
332 /*
333 * check for insanity where we are given a bitmap that
334 * claims to have more arg content than the length of the
335 * radiotap section. We will normally end up equalling this
336 * max_length on the last arg, never exceeding it.
337 */
338
339 if ((unsigned long)iterator->_arg -
340 (unsigned long)iterator->_rtheader >
341 (unsigned long)iterator->_max_length)
342 return -EINVAL;
343
344 /* these special ones are valid in each bitmap word */
345 switch (iterator->_arg_index % 32) {
346 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
347 iterator->_reset_on_ext = 1;
348
349 iterator->is_radiotap_ns = 0;
350 /*
351 * If parser didn't register this vendor
352 * namespace with us, allow it to show it
353 * as 'raw. Do do that, set argument index
354 * to vendor namespace.
355 */
356 iterator->this_arg_index =
357 IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
358 if (!iterator->current_namespace)
359 hit = 1;
360 goto next_entry;
361 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
362 iterator->_reset_on_ext = 1;
363 iterator->current_namespace = &radiotap_ns;
364 iterator->is_radiotap_ns = 1;
365 goto next_entry;
366 case IEEE80211_RADIOTAP_EXT:
367 /*
368 * bit 31 was set, there is more
369 * -- move to next u32 bitmap
370 */
371 iterator->_bitmap_shifter =
372 get_unaligned_le32(iterator->_next_bitmap);
373 iterator->_next_bitmap++;
374 if (iterator->_reset_on_ext)
375 iterator->_arg_index = 0;
376 else
377 iterator->_arg_index++;
378 iterator->_reset_on_ext = 0;
379 break;
380 default:
381 /* we've got a hit! */
382 hit = 1;
383 next_entry:
384 iterator->_bitmap_shifter >>= 1;
385 iterator->_arg_index++;
386 }
387
388 /* if we found a valid arg earlier, return it now */
389 if (hit)
390 return 0;
391 }
392 }
0 /*
1 * Copyright (c) 2017 Intel Deutschland GmbH
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15 #ifndef __RADIOTAP_H
16 #define __RADIOTAP_H
17
18 #if defined(__APPLE__)
19 #include <libkern/OSByteOrder.h>
20 #define bswap_16 OSSwapInt16
21 #define bswap_32 OSSwapInt32
22 #define bswap_64 OSSwapInt64
23 #include <machine/endian.h>
24 #define le16toh(x) OSSwapLittleToHostInt16(x)
25 #define le32toh(x) OSSwapLittleToHostInt32(x)
26 #define le64toh(x) OSSwapLittleToHostInt64(x)
27 #endif
28
29 /**
30 * struct ieee82011_radiotap_header - base radiotap header
31 */
32 struct ieee80211_radiotap_header {
33 /**
34 * @it_version: radiotap version, always 0
35 */
36 uint8_t it_version;
37
38 /**
39 * @it_pad: padding (or alignment)
40 */
41 uint8_t it_pad;
42
43 /**
44 * @it_len: overall radiotap header length
45 */
46 uint16_t it_len;
47
48 /**
49 * @it_present: (first) present word
50 */
51 uint32_t it_present;
52 } __attribute__((__packed__));
53
54 /* version is always 0 */
55 #define PKTHDR_RADIOTAP_VERSION 0
56
57 /* see the radiotap website for the descriptions */
58 enum ieee80211_radiotap_presence {
59 IEEE80211_RADIOTAP_TSFT = 0,
60 IEEE80211_RADIOTAP_FLAGS = 1,
61 IEEE80211_RADIOTAP_RATE = 2,
62 IEEE80211_RADIOTAP_CHANNEL = 3,
63 IEEE80211_RADIOTAP_FHSS = 4,
64 IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
65 IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
66 IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
67 IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
68 IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
69 IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
70 IEEE80211_RADIOTAP_ANTENNA = 11,
71 IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
72 IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
73 IEEE80211_RADIOTAP_RX_FLAGS = 14,
74 IEEE80211_RADIOTAP_TX_FLAGS = 15,
75 IEEE80211_RADIOTAP_RTS_RETRIES = 16,
76 IEEE80211_RADIOTAP_DATA_RETRIES = 17,
77 /* 18 is XChannel, but it's not defined yet */
78 IEEE80211_RADIOTAP_MCS = 19,
79 IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
80 IEEE80211_RADIOTAP_VHT = 21,
81 IEEE80211_RADIOTAP_TIMESTAMP = 22,
82
83 /* valid in every it_present bitmap, even vendor namespaces */
84 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
85 IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
86 IEEE80211_RADIOTAP_EXT = 31
87 };
88
89 /* for IEEE80211_RADIOTAP_FLAGS */
90 enum ieee80211_radiotap_flags {
91 IEEE80211_RADIOTAP_F_CFP = 0x01,
92 IEEE80211_RADIOTAP_F_SHORTPRE = 0x02,
93 IEEE80211_RADIOTAP_F_WEP = 0x04,
94 IEEE80211_RADIOTAP_F_FRAG = 0x08,
95 IEEE80211_RADIOTAP_F_FCS = 0x10,
96 IEEE80211_RADIOTAP_F_DATAPAD = 0x20,
97 IEEE80211_RADIOTAP_F_BADFCS = 0x40,
98 };
99
100 /* for IEEE80211_RADIOTAP_CHANNEL */
101 enum ieee80211_radiotap_channel_flags {
102 IEEE80211_CHAN_CCK = 0x0020,
103 IEEE80211_CHAN_OFDM = 0x0040,
104 IEEE80211_CHAN_2GHZ = 0x0080,
105 IEEE80211_CHAN_5GHZ = 0x0100,
106 IEEE80211_CHAN_DYN = 0x0400,
107 IEEE80211_CHAN_HALF = 0x4000,
108 IEEE80211_CHAN_QUARTER = 0x8000,
109 };
110
111 /* for IEEE80211_RADIOTAP_RX_FLAGS */
112 enum ieee80211_radiotap_rx_flags {
113 IEEE80211_RADIOTAP_F_RX_BADPLCP = 0x0002,
114 };
115
116 /* for IEEE80211_RADIOTAP_TX_FLAGS */
117 enum ieee80211_radiotap_tx_flags {
118 IEEE80211_RADIOTAP_F_TX_FAIL = 0x0001,
119 IEEE80211_RADIOTAP_F_TX_CTS = 0x0002,
120 IEEE80211_RADIOTAP_F_TX_RTS = 0x0004,
121 IEEE80211_RADIOTAP_F_TX_NOACK = 0x0008,
122 };
123
124 /* for IEEE80211_RADIOTAP_MCS "have" flags */
125 enum ieee80211_radiotap_mcs_have {
126 IEEE80211_RADIOTAP_MCS_HAVE_BW = 0x01,
127 IEEE80211_RADIOTAP_MCS_HAVE_MCS = 0x02,
128 IEEE80211_RADIOTAP_MCS_HAVE_GI = 0x04,
129 IEEE80211_RADIOTAP_MCS_HAVE_FMT = 0x08,
130 IEEE80211_RADIOTAP_MCS_HAVE_FEC = 0x10,
131 IEEE80211_RADIOTAP_MCS_HAVE_STBC = 0x20,
132 };
133
134 enum ieee80211_radiotap_mcs_flags {
135 IEEE80211_RADIOTAP_MCS_BW_MASK = 0x03,
136 IEEE80211_RADIOTAP_MCS_BW_20 = 0,
137 IEEE80211_RADIOTAP_MCS_BW_40 = 1,
138 IEEE80211_RADIOTAP_MCS_BW_20L = 2,
139 IEEE80211_RADIOTAP_MCS_BW_20U = 3,
140
141 IEEE80211_RADIOTAP_MCS_SGI = 0x04,
142 IEEE80211_RADIOTAP_MCS_FMT_GF = 0x08,
143 IEEE80211_RADIOTAP_MCS_FEC_LDPC = 0x10,
144 IEEE80211_RADIOTAP_MCS_STBC_MASK = 0x60,
145 IEEE80211_RADIOTAP_MCS_STBC_1 = 1,
146 IEEE80211_RADIOTAP_MCS_STBC_2 = 2,
147 IEEE80211_RADIOTAP_MCS_STBC_3 = 3,
148 IEEE80211_RADIOTAP_MCS_STBC_SHIFT = 5,
149 };
150
151 /* for IEEE80211_RADIOTAP_AMPDU_STATUS */
152 enum ieee80211_radiotap_ampdu_flags {
153 IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN = 0x0001,
154 IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN = 0x0002,
155 IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN = 0x0004,
156 IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008,
157 IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010,
158 IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020,
159 };
160
161 /* for IEEE80211_RADIOTAP_VHT */
162 enum ieee80211_radiotap_vht_known {
163 IEEE80211_RADIOTAP_VHT_KNOWN_STBC = 0x0001,
164 IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA = 0x0002,
165 IEEE80211_RADIOTAP_VHT_KNOWN_GI = 0x0004,
166 IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS = 0x0008,
167 IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM = 0x0010,
168 IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED = 0x0020,
169 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH = 0x0040,
170 IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID = 0x0080,
171 IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID = 0x0100,
172 };
173
174 enum ieee80211_radiotap_vht_flags {
175 IEEE80211_RADIOTAP_VHT_FLAG_STBC = 0x01,
176 IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA = 0x02,
177 IEEE80211_RADIOTAP_VHT_FLAG_SGI = 0x04,
178 IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 = 0x08,
179 IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM = 0x10,
180 IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED = 0x20,
181 };
182
183 enum ieee80211_radiotap_vht_coding {
184 IEEE80211_RADIOTAP_CODING_LDPC_USER0 = 0x01,
185 IEEE80211_RADIOTAP_CODING_LDPC_USER1 = 0x02,
186 IEEE80211_RADIOTAP_CODING_LDPC_USER2 = 0x04,
187 IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08,
188 };
189
190 /* for IEEE80211_RADIOTAP_TIMESTAMP */
191 enum ieee80211_radiotap_timestamp_unit_spos {
192 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F,
193 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS = 0x0000,
194 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US = 0x0001,
195 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS = 0x0003,
196 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK = 0x00F0,
197 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU = 0x0000,
198 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ = 0x0010,
199 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU = 0x0020,
200 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU = 0x0030,
201 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN = 0x00F0,
202 };
203
204 enum ieee80211_radiotap_timestamp_flags {
205 IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT = 0x00,
206 IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT = 0x01,
207 IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02,
208 };
209
210 #endif /* __RADIOTAP_H */
0 #ifndef __RADIOTAP_ITER_H
1 #define __RADIOTAP_ITER_H
2
3 #include <stdint.h>
4 #include "radiotap.h"
5
6 /* Radiotap header iteration
7 * implemented in radiotap.c
8 */
9
10 struct radiotap_override {
11 uint8_t field;
12 uint8_t align:4, size:4;
13 };
14
15 struct radiotap_align_size {
16 uint8_t align:4, size:4;
17 };
18
19 struct ieee80211_radiotap_namespace {
20 const struct radiotap_align_size *align_size;
21 int n_bits;
22 uint32_t oui;
23 uint8_t subns;
24 };
25
26 struct ieee80211_radiotap_vendor_namespaces {
27 const struct ieee80211_radiotap_namespace *ns;
28 int n_ns;
29 };
30
31 /**
32 * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
33 * @this_arg_index: index of current arg, valid after each successful call
34 * to ieee80211_radiotap_iterator_next()
35 * @this_arg: pointer to current radiotap arg; it is valid after each
36 * call to ieee80211_radiotap_iterator_next() but also after
37 * ieee80211_radiotap_iterator_init() where it will point to
38 * the beginning of the actual data portion
39 * @this_arg_size: length of the current arg, for convenience
40 * @current_namespace: pointer to the current namespace definition
41 * (or internally %NULL if the current namespace is unknown)
42 * @is_radiotap_ns: indicates whether the current namespace is the default
43 * radiotap namespace or not
44 *
45 * @overrides: override standard radiotap fields
46 * @n_overrides: number of overrides
47 *
48 * @_rtheader: pointer to the radiotap header we are walking through
49 * @_max_length: length of radiotap header in cpu byte ordering
50 * @_arg_index: next argument index
51 * @_arg: next argument pointer
52 * @_next_bitmap: internal pointer to next present u32
53 * @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
54 * @_vns: vendor namespace definitions
55 * @_next_ns_data: beginning of the next namespace's data
56 * @_reset_on_ext: internal; reset the arg index to 0 when going to the
57 * next bitmap word
58 *
59 * Describes the radiotap parser state. Fields prefixed with an underscore
60 * must not be used by users of the parser, only by the parser internally.
61 */
62
63 struct ieee80211_radiotap_iterator {
64 struct ieee80211_radiotap_header *_rtheader;
65 const struct ieee80211_radiotap_vendor_namespaces *_vns;
66 const struct ieee80211_radiotap_namespace *current_namespace;
67
68 unsigned char *_arg, *_next_ns_data;
69 uint32_t *_next_bitmap;
70
71 unsigned char *this_arg;
72 const struct radiotap_override *overrides; /* Only for RADIOTAP_SUPPORT_OVERRIDES */
73 int n_overrides; /* Only for RADIOTAP_SUPPORT_OVERRIDES */
74 int this_arg_index;
75 int this_arg_size;
76
77 int is_radiotap_ns;
78
79 int _max_length;
80 int _arg_index;
81 uint32_t _bitmap_shifter;
82 int _reset_on_ext;
83 };
84
85 #ifdef __cplusplus
86 #define CALLING_CONVENTION "C"
87 #else
88 #define CALLING_CONVENTION
89 #endif
90
91 extern CALLING_CONVENTION int ieee80211_radiotap_iterator_init(
92 struct ieee80211_radiotap_iterator *iterator,
93 struct ieee80211_radiotap_header *radiotap_header,
94 int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns);
95
96 extern CALLING_CONVENTION int ieee80211_radiotap_iterator_next(
97 struct ieee80211_radiotap_iterator *iterator);
98
99 #endif /* __RADIOTAP_ITER_H */