2 * Copyright (c) 2007, 2008, Andy Green <andy@warmcat.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <sys/types.h>
23 #include "radiotap-parser.h"
27 * Radiotap header iteration
28 * implemented in src/radiotap-parser.c
30 * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
31 * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
32 * then loop calling __ieee80211_radiotap_iterator_next()... it returns -1
33 * if there are no more args in the header, or the next argument type index
34 * that is present. The iterator's this_arg member points to the start of the
35 * argument associated with the current argument index that is present,
36 * which can be found in the iterator's this_arg_index member. This arg
37 * index corresponds to the IEEE80211_RADIOTAP_... defines.
42 ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator,
43 struct ieee80211_radiotap_header
44 *radiotap_header, int max_length)
49 if (radiotap_header == NULL)
51 /* Linux only supports version 0 radiotap format */
53 if (radiotap_header->it_version)
56 /* sanity check for allowed length and radiotap length field */
58 if (max_length < (le16_to_cpu (radiotap_header->it_len)))
61 iterator->rtheader = radiotap_header;
62 iterator->max_length = le16_to_cpu (radiotap_header->it_len);
63 iterator->arg_index = 0;
64 iterator->bitmap_shifter = le32_to_cpu (radiotap_header->it_present);
66 ((u8 *) radiotap_header) + sizeof (struct ieee80211_radiotap_header);
67 iterator->this_arg = 0;
69 /* find payload start allowing for extended bitmap(s) */
72 (iterator->bitmap_shifter & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK))
74 while (le32_to_cpu (*((u32 *) iterator->arg)) &
75 IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK)
77 iterator->arg += sizeof (u32);
80 * check for insanity where the present bitmaps
81 * keep claiming to extend up to or even beyond the
82 * stated radiotap header length
85 if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) >
91 iterator->arg += sizeof (u32);
94 * no need to check again for blowing past stated radiotap
95 * header length, becuase ieee80211_radiotap_iterator_next
96 * checks it before it is dereferenced
101 /* we are all initialized happily */
108 * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
109 * @iterator: radiotap_iterator to move to next arg (if any)
111 * Returns: next present arg index on success or negative if no more or error
113 * This function returns the next radiotap arg index (IEEE80211_RADIOTAP_...)
114 * and sets iterator->this_arg to point to the payload for the arg. It takes
115 * care of alignment handling and extended present fields. interator->this_arg
116 * can be changed by the caller. The args pointed to are in little-endian
121 ieee80211_radiotap_iterator_next (struct ieee80211_radiotap_iterator *iterator)
125 * small length lookup table for all radiotap types we heard of
126 * starting from b0 in the bitmap, so we can walk the payload
127 * area of the radiotap header
129 * There is a requirement to pad args, so that args
130 * of a given length must begin at a boundary of that length
131 * -- but note that compound args are allowed (eg, 2 x u16
132 * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
133 * a reliable indicator of alignment requirement.
135 * upper nybble: content alignment for arg
136 * lower nybble: content length for arg
139 static const u8 rt_sizes[] = {
140 [IEEE80211_RADIOTAP_TSFT] = 0x88,
141 [IEEE80211_RADIOTAP_FLAGS] = 0x11,
142 [IEEE80211_RADIOTAP_RATE] = 0x11,
143 [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
144 [IEEE80211_RADIOTAP_FHSS] = 0x22,
145 [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
146 [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
147 [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
148 [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
149 [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
150 [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
151 [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
152 [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
153 [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11,
154 [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22,
155 [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22,
156 [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11,
157 [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11
159 * add more here as they are defined in
160 * include/net/ieee80211_radiotap.h
165 * for every radiotap entry we can at
166 * least skip (by knowing the length)...
169 while (iterator->arg_index < (int) sizeof (rt_sizes))
173 if (!(iterator->bitmap_shifter & 1))
174 goto next_entry; /* arg not present */
177 * arg is present, account for alignment padding
178 * 8-bit args can be at any alignment
179 * 16-bit args must start on 16-bit boundary
180 * 32-bit args must start on 32-bit boundary
181 * 64-bit args must start on 64-bit boundary
183 * note that total arg size can differ from alignment of
184 * elements inside arg, so we use upper nybble of length
185 * table to base alignment on
187 * also note: these alignments are ** relative to the
188 * start of the radiotap header **. There is no guarantee
189 * that the radiotap header itself is aligned on any
193 if ((((void *) iterator->arg) -
194 ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >> 4)
196 iterator->arg_index +=
197 (rt_sizes[iterator->arg_index] >> 4) -
198 ((((void *) iterator->arg) -
199 ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >>
203 * this is what we will return to user, but we need to
204 * move on first so next call has something fresh to test
207 iterator->this_arg_index = iterator->arg_index;
208 iterator->this_arg = iterator->arg;
211 /* internally move on the size of this arg */
213 iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
216 * check for insanity where we are given a bitmap that
217 * claims to have more arg content than the length of the
218 * radiotap section. We will normally end up equalling this
219 * max_length on the last arg, never exceeding it.
222 if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) >
223 iterator->max_length)
228 iterator->arg_index++;
229 if (unlikely ((iterator->arg_index & 31) == 0))
231 /* completed current u32 bitmap */
232 if (iterator->bitmap_shifter & 1)
234 /* b31 was set, there is more */
235 /* move to next u32 bitmap */
236 iterator->bitmap_shifter = le32_to_cpu (*iterator->next_bitmap);
237 iterator->next_bitmap++;
241 /* no more bitmaps: end */
242 iterator->arg_index = sizeof (rt_sizes);
246 { /* just try the next bit */
247 iterator->bitmap_shifter >>= 1;
250 /* if we found a valid arg earlier, return it now */
253 return (iterator->this_arg_index);
257 /* we don't know how to handle any more args, we're done */