Rename the NetMon 802.11 radio header and radiotap 802.11 radio header
[metze/wireshark/wip.git] / epan / dissectors / packet-ieee80211-radiotap-iter.c
1 /*
2  * Radiotap parser
3  *
4  * Copyright 2007               Andy Green <andy@warmcat.com>
5  * Copyright 2009               Johannes Berg <johannes@sipsolutions.net>
6  *
7  * $Id$
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  * Alternatively, this software may be distributed under the terms of BSD
14  * license.
15  *
16  * See COPYING for more details.
17  */
18
19 #include <stddef.h>
20 #include <errno.h>
21 #include <glib.h>
22 #include "pint.h"
23
24 #define le16_to_cpu             GINT16_FROM_LE
25 #define le32_to_cpu             GINT32_FROM_LE
26 #define get_unaligned_le16      pletohs
27 #define get_unaligned_le32      pletohl
28
29 #include "packet-ieee80211-radiotap-iter.h"
30
31 /* function prototypes and related defs are in radiotap_iter.h */
32
33 static const struct radiotap_align_size rtap_namespace_sizes[] = {
34         /* [IEEE80211_RADIOTAP_TSFT] = 0 */                     { 8, 8 },
35         /* [IEEE80211_RADIOTAP_FLAGS] = 1 */                    { 1, 1 },
36         /* [IEEE80211_RADIOTAP_RATE] = 2 */                     { 1, 1 },
37         /* [IEEE80211_RADIOTAP_CHANNEL] = 3 */                  { 2, 4 },
38         /* [IEEE80211_RADIOTAP_FHSS] = 4 */                     { 2, 2 },
39         /* [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 5 */            { 1, 1 },
40         /* [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 6 */             { 1, 1 },
41         /* [IEEE80211_RADIOTAP_LOCK_QUALITY] = 7 */             { 2, 2 },
42         /* [IEEE80211_RADIOTAP_TX_ATTENUATION] = 8 */           { 2, 2 },
43         /* [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 9 */        { 2, 2 },
44         /* [IEEE80211_RADIOTAP_DBM_TX_POWER] = 10 */            { 1, 1 },
45         /* [IEEE80211_RADIOTAP_ANTENNA] = 11 */                 { 1, 1 },
46         /* [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 12 */            { 1, 1 },
47         /* [IEEE80211_RADIOTAP_DB_ANTNOISE] = 13 */             { 1, 1 },
48         /* [IEEE80211_RADIOTAP_RX_FLAGS] = 14 */                { 2, 2 },
49         /* [IEEE80211_RADIOTAP_TX_FLAGS] = 15 */                { 2, 2 },
50         /* [IEEE80211_RADIOTAP_RTS_RETRIES] = 16 */             { 1, 1 },
51         /* [IEEE80211_RADIOTAP_DATA_RETRIES] = 17 */            { 1, 1 },
52         /* [IEEE80211_RADIOTAP_XCHANNEL] = 18 */                { 0, 0 }, /* Unofficial, used by FreeBSD */
53         /* [IEEE80211_RADIOTAP_MCS] = 19 */                     { 1, 3 }
54         /*
55          * add more here as they are defined in
56          * include/net/ieee80211_radiotap.h
57          */
58 };
59
60 static const struct ieee80211_radiotap_namespace radiotap_ns = {
61         rtap_namespace_sizes,
62         (int)(sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0])),
63         0,
64         0
65 };
66
67 /**
68  * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
69  * @iterator: radiotap_iterator to initialize
70  * @radiotap_header: radiotap header to parse
71  * @max_length: total length we can parse into (eg, whole packet length)
72  *
73  * Returns: 0 or a negative error code if there is a problem.
74  *
75  * This function initializes an opaque iterator struct which can then
76  * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
77  * argument which is present in the header.  It knows about extended
78  * present headers and handles them.
79  *
80  * How to use:
81  * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
82  * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
83  * checking for a good 0 return code.  Then loop calling
84  * __ieee80211_radiotap_iterator_next()... it returns either 0,
85  * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
86  * The iterator's @this_arg member points to the start of the argument
87  * associated with the current argument index that is present, which can be
88  * found in the iterator's @this_arg_index member.  This arg index corresponds
89  * to the IEEE80211_RADIOTAP_... defines.
90  *
91  * Radiotap header length:
92  * You can find the CPU-endian total radiotap header length in
93  * iterator->max_length after executing ieee80211_radiotap_iterator_init()
94  * successfully.
95  *
96  * Alignment Gotcha:
97  * You must take care when dereferencing iterator.this_arg
98  * for multibyte types... the pointer is not aligned.  Use
99  * get_unaligned((type *)iterator.this_arg) to dereference
100  * iterator.this_arg for type "type" safely on all arches.
101  *
102  * Example code:
103  * See Documentation/networking/radiotap-headers.txt
104  */
105
106 int ieee80211_radiotap_iterator_init(
107         struct ieee80211_radiotap_iterator *iterator,
108         struct ieee80211_radiotap_header *radiotap_header,
109         int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
110 {
111         /* Linux only supports version 0 radiotap format */
112         if (radiotap_header->it_version)
113                 return -EINVAL;
114
115         /* sanity check for allowed length and radiotap length field */
116         if (max_length < get_unaligned_le16(&radiotap_header->it_len))
117                 return -EINVAL;
118
119         iterator->_rtheader = radiotap_header;
120         iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
121         iterator->_arg_index = 0;
122         iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
123         iterator->_arg = (guint8 *)radiotap_header + sizeof(*radiotap_header);
124         iterator->_reset_on_ext = 0;
125         iterator->_next_bitmap = &radiotap_header->it_present;
126         iterator->_next_bitmap++;
127         iterator->_vns = vns;
128         iterator->current_namespace = &radiotap_ns;
129         iterator->is_radiotap_ns = 1;
130 #ifdef RADIOTAP_SUPPORT_OVERRIDES
131         iterator->n_overrides = 0;
132         iterator->overrides = NULL;
133 #endif
134
135         /* find payload start allowing for extended bitmap(s) */
136
137         if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
138                 while (get_unaligned_le32(iterator->_arg) &
139                                         (1 << IEEE80211_RADIOTAP_EXT)) {
140                         iterator->_arg += sizeof(guint32);
141
142                         /*
143                          * check for insanity where the present bitmaps
144                          * keep claiming to extend up to or even beyond the
145                          * stated radiotap header length
146                          */
147
148                         if ((unsigned long)iterator->_arg -
149                             (unsigned long)iterator->_rtheader >
150                             (unsigned long)iterator->_max_length)
151                                 return -EINVAL;
152                 }
153
154                 iterator->_arg += sizeof(guint32);
155
156                 /*
157                  * no need to check again for blowing past stated radiotap
158                  * header length, because ieee80211_radiotap_iterator_next
159                  * checks it before it is dereferenced
160                  */
161         }
162
163         iterator->this_arg = iterator->_arg;
164
165         /* we are all initialized happily */
166
167         return 0;
168 }
169
170 static void find_ns(struct ieee80211_radiotap_iterator *iterator,
171                     guint32 oui, guint8 subns)
172 {
173         int i;
174
175         iterator->current_namespace = NULL;
176
177         if (!iterator->_vns)
178                 return;
179
180         for (i = 0; i < iterator->_vns->n_ns; i++) {
181                 if (iterator->_vns->ns[i].oui != oui)
182                         continue;
183                 if (iterator->_vns->ns[i].subns != subns)
184                         continue;
185
186                 iterator->current_namespace = &iterator->_vns->ns[i];
187                 break;
188         }
189 }
190
191 #ifdef RADIOTAP_SUPPORT_OVERRIDES
192 static int find_override(struct ieee80211_radiotap_iterator *iterator,
193                          int *align, int *size)
194 {
195         int i;
196
197         if (!iterator->overrides)
198                 return 0;
199
200         for (i = 0; i < iterator->n_overrides; i++) {
201                 if (iterator->_arg_index == iterator->overrides[i].field) {
202                         *align = iterator->overrides[i].align;
203                         *size = iterator->overrides[i].size;
204                         if (!*align) /* erroneous override */
205                                 return 0;
206                         return 1;
207                 }
208         }
209
210         return 0;
211 }
212 #endif
213
214
215 /**
216  * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
217  * @iterator: radiotap_iterator to move to next arg (if any)
218  *
219  * Returns: 0 if there is an argument to handle,
220  * -ENOENT if there are no more args or -EINVAL
221  * if there is something else wrong.
222  *
223  * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
224  * in @this_arg_index and sets @this_arg to point to the
225  * payload for the field.  It takes care of alignment handling and extended
226  * present fields.  @this_arg can be changed by the caller (eg,
227  * incremented to move inside a compound argument like
228  * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
229  * little-endian format whatever the endianess of your CPU.
230  *
231  * Alignment Gotcha:
232  * You must take care when dereferencing iterator.this_arg
233  * for multibyte types... the pointer is not aligned.  Use
234  * get_unaligned((type *)iterator.this_arg) to dereference
235  * iterator.this_arg for type "type" safely on all arches.
236  */
237
238 int ieee80211_radiotap_iterator_next(
239         struct ieee80211_radiotap_iterator *iterator)
240 {
241         while (1) {
242                 int hit = 0;
243                 int pad, align, size, subns;
244                 guint32 oui;
245
246                 /* if no more EXT bits, that's it */
247                 if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT &&
248                     !(iterator->_bitmap_shifter & 1))
249                         return -ENOENT;
250
251                 if (!(iterator->_bitmap_shifter & 1))
252                         goto next_entry; /* arg not present */
253
254                 /* get alignment/size of data */
255                 switch (iterator->_arg_index % 32) {
256                 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
257                 case IEEE80211_RADIOTAP_EXT:
258                         align = 1;
259                         size = 0;
260                         break;
261                 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
262                         align = 2;
263                         size = 6;
264                         break;
265                 default:
266 #ifdef RADIOTAP_SUPPORT_OVERRIDES
267                         if (find_override(iterator, &align, &size)) {
268                                 /* all set */
269                         } else
270 #endif
271                         if (!iterator->current_namespace ||
272                             iterator->_arg_index >= iterator->current_namespace->n_bits) {
273                                 if (iterator->current_namespace == &radiotap_ns)
274                                         return -ENOENT;
275                                 align = 0;
276                         } else {
277                                 align = iterator->current_namespace->align_size[iterator->_arg_index].align;
278                                 size = iterator->current_namespace->align_size[iterator->_arg_index].size;
279                         }
280                         if (!align) {
281                                 /* skip all subsequent data */
282                                 iterator->_arg = iterator->_next_ns_data;
283                                 /* give up on this namespace */
284                                 iterator->current_namespace = NULL;
285                                 goto next_entry;
286                         }
287                         break;
288                 }
289
290                 /*
291                  * arg is present, account for alignment padding
292                  *
293                  * Note that these alignments are relative to the start
294                  * of the radiotap header.  There is no guarantee
295                  * that the radiotap header itself is aligned on any
296                  * kind of boundary.
297                  *
298                  * The above is why get_unaligned() is used to dereference
299                  * multibyte elements from the radiotap area.
300                  */
301
302                 pad = ((unsigned long)iterator->_arg -
303                        (unsigned long)iterator->_rtheader) & (align - 1);
304
305                 if (pad)
306                         iterator->_arg += align - pad;
307
308                 if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
309                         int vnslen;
310
311                         if ((unsigned long)iterator->_arg + size -
312                             (unsigned long)iterator->_rtheader >
313                             (unsigned long)iterator->_max_length)
314                                 return -EINVAL;
315
316                         oui = (*iterator->_arg << 16) |
317                                 (*(iterator->_arg + 1) << 8) |
318                                 *(iterator->_arg + 2);
319                         subns = *(iterator->_arg + 3);
320
321                         find_ns(iterator, oui, subns);
322
323                         vnslen = get_unaligned_le16(iterator->_arg + 4);
324                         iterator->_next_ns_data = iterator->_arg + size + vnslen;
325                         if (!iterator->current_namespace)
326                                 size += vnslen;
327                 }
328
329                 /*
330                  * this is what we will return to user, but we need to
331                  * move on first so next call has something fresh to test
332                  */
333                 iterator->this_arg_index = iterator->_arg_index;
334                 iterator->this_arg = iterator->_arg;
335                 iterator->this_arg_size = size;
336
337                 /* internally move on the size of this arg */
338                 iterator->_arg += size;
339
340                 /*
341                  * check for insanity where we are given a bitmap that
342                  * claims to have more arg content than the length of the
343                  * radiotap section.  We will normally end up equalling this
344                  * max_length on the last arg, never exceeding it.
345                  */
346
347                 if ((unsigned long)iterator->_arg -
348                     (unsigned long)iterator->_rtheader >
349                     (unsigned long)iterator->_max_length)
350                         return -EINVAL;
351
352                 /* these special ones are valid in each bitmap word */
353                 switch (iterator->_arg_index % 32) {
354                 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
355                         iterator->_reset_on_ext = 1;
356
357                         iterator->is_radiotap_ns = 0;
358                         /*
359                          * If parser didn't register this vendor
360                          * namespace with us, allow it to show it
361                          * as 'raw. Do do that, set argument index
362                          * to vendor namespace.
363                          */
364                         iterator->this_arg_index =
365                                 IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
366                         if (!iterator->current_namespace)
367                                 hit = 1;
368                         goto next_entry;
369                 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
370                         iterator->_reset_on_ext = 1;
371                         iterator->current_namespace = &radiotap_ns;
372                         iterator->is_radiotap_ns = 1;
373                         goto next_entry;
374                 case IEEE80211_RADIOTAP_EXT:
375                         /*
376                          * bit 31 was set, there is more
377                          * -- move to next u32 bitmap
378                          */
379                         iterator->_bitmap_shifter =
380                                 get_unaligned_le32(iterator->_next_bitmap);
381                         iterator->_next_bitmap++;
382                         if (iterator->_reset_on_ext)
383                                 iterator->_arg_index = 0;
384                         else
385                                 iterator->_arg_index++;
386                         iterator->_reset_on_ext = 0;
387                         break;
388                 default:
389                         /* we've got a hit! */
390                         hit = 1;
391  next_entry:
392                         iterator->_bitmap_shifter >>= 1;
393                         iterator->_arg_index++;
394                 }
395
396                 /* if we found a valid arg earlier, return it now */
397                 if (hit)
398                         return 0;
399         }
400 }