radiotap.c

Go to the documentation of this file.
00001 
00021 #include "includes.h"
00022 
00023 #include "common.h"
00024 #include "radiotap_iter.h"
00025 
00026 #define le16_to_cpu             le_to_host16
00027 #define le32_to_cpu             le_to_host32
00028 #define __le32                  uint32_t
00029 #define ulong                   unsigned long
00030 #define unlikely(cond)          (cond)
00031 #define get_unaligned(p)                                        \
00032 ({                                                              \
00033         struct packed_dummy_struct {                            \
00034                 typeof(*(p)) __val;                             \
00035         } __attribute__((packed)) *__ptr = (void *) (p);        \
00036                                                                 \
00037         __ptr->__val;                                           \
00038 })
00039 
00040 /* function prototypes and related defs are in radiotap_iter.h */
00041 
00082 int ieee80211_radiotap_iterator_init(
00083     struct ieee80211_radiotap_iterator *iterator,
00084     struct ieee80211_radiotap_header *radiotap_header,
00085     int max_length)
00086 {
00087         /* Linux only supports version 0 radiotap format */
00088         if (radiotap_header->it_version)
00089                 return -EINVAL;
00090 
00091         /* sanity check for allowed length and radiotap length field */
00092         if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
00093                 return -EINVAL;
00094 
00095         iterator->rtheader = radiotap_header;
00096         iterator->max_length = le16_to_cpu(get_unaligned(
00097                                                 &radiotap_header->it_len));
00098         iterator->arg_index = 0;
00099         iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
00100                                                 &radiotap_header->it_present));
00101         iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
00102         iterator->this_arg = NULL;
00103 
00104         /* find payload start allowing for extended bitmap(s) */
00105 
00106         if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
00107                 while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) &
00108                                    (1<<IEEE80211_RADIOTAP_EXT)) {
00109                         iterator->arg += sizeof(u32);
00110 
00111                         /*
00112                          * check for insanity where the present bitmaps
00113                          * keep claiming to extend up to or even beyond the
00114                          * stated radiotap header length
00115                          */
00116 
00117                         if (((ulong)iterator->arg - (ulong)iterator->rtheader)
00118                             > (ulong)iterator->max_length)
00119                                 return -EINVAL;
00120                 }
00121 
00122                 iterator->arg += sizeof(u32);
00123 
00124                 /*
00125                  * no need to check again for blowing past stated radiotap
00126                  * header length, because ieee80211_radiotap_iterator_next
00127                  * checks it before it is dereferenced
00128                  */
00129         }
00130 
00131         /* we are all initialized happily */
00132 
00133         return 0;
00134 }
00135 
00136 
00161 int ieee80211_radiotap_iterator_next(
00162     struct ieee80211_radiotap_iterator *iterator)
00163 {
00164 
00165         /*
00166          * small length lookup table for all radiotap types we heard of
00167          * starting from b0 in the bitmap, so we can walk the payload
00168          * area of the radiotap header
00169          *
00170          * There is a requirement to pad args, so that args
00171          * of a given length must begin at a boundary of that length
00172          * -- but note that compound args are allowed (eg, 2 x u16
00173          * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
00174          * a reliable indicator of alignment requirement.
00175          *
00176          * upper nybble: content alignment for arg
00177          * lower nybble: content length for arg
00178          */
00179 
00180         static const u8 rt_sizes[] = {
00181                 [IEEE80211_RADIOTAP_TSFT] = 0x88,
00182                 [IEEE80211_RADIOTAP_FLAGS] = 0x11,
00183                 [IEEE80211_RADIOTAP_RATE] = 0x11,
00184                 [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
00185                 [IEEE80211_RADIOTAP_FHSS] = 0x22,
00186                 [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
00187                 [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
00188                 [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
00189                 [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
00190                 [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
00191                 [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
00192                 [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
00193                 [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
00194                 [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11,
00195                 [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22,
00196                 [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22,
00197                 [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11,
00198                 [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11,
00199                 /*
00200                  * add more here as they are defined in
00201                  * include/net/ieee80211_radiotap.h
00202                  */
00203         };
00204 
00205         /*
00206          * for every radiotap entry we can at
00207          * least skip (by knowing the length)...
00208          */
00209 
00210         while (iterator->arg_index < (int) sizeof(rt_sizes)) {
00211                 int hit = 0;
00212                 int pad;
00213 
00214                 if (!(iterator->bitmap_shifter & 1))
00215                         goto next_entry; /* arg not present */
00216 
00217                 /*
00218                  * arg is present, account for alignment padding
00219                  *  8-bit args can be at any alignment
00220                  * 16-bit args must start on 16-bit boundary
00221                  * 32-bit args must start on 32-bit boundary
00222                  * 64-bit args must start on 64-bit boundary
00223                  *
00224                  * note that total arg size can differ from alignment of
00225                  * elements inside arg, so we use upper nybble of length
00226                  * table to base alignment on
00227                  *
00228                  * also note: these alignments are ** relative to the
00229                  * start of the radiotap header **.  There is no guarantee
00230                  * that the radiotap header itself is aligned on any
00231                  * kind of boundary.
00232                  *
00233                  * the above is why get_unaligned() is used to dereference
00234                  * multibyte elements from the radiotap area
00235                  */
00236 
00237                 pad = (((ulong)iterator->arg) -
00238                         ((ulong)iterator->rtheader)) &
00239                         ((rt_sizes[iterator->arg_index] >> 4) - 1);
00240 
00241                 if (pad)
00242                         iterator->arg +=
00243                                 (rt_sizes[iterator->arg_index] >> 4) - pad;
00244 
00245                 /*
00246                  * this is what we will return to user, but we need to
00247                  * move on first so next call has something fresh to test
00248                  */
00249                 iterator->this_arg_index = iterator->arg_index;
00250                 iterator->this_arg = iterator->arg;
00251                 hit = 1;
00252 
00253                 /* internally move on the size of this arg */
00254                 iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
00255 
00256                 /*
00257                  * check for insanity where we are given a bitmap that
00258                  * claims to have more arg content than the length of the
00259                  * radiotap section.  We will normally end up equalling this
00260                  * max_length on the last arg, never exceeding it.
00261                  */
00262 
00263                 if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
00264                     (ulong) iterator->max_length)
00265                         return -EINVAL;
00266 
00267         next_entry:
00268                 iterator->arg_index++;
00269                 if (unlikely((iterator->arg_index & 31) == 0)) {
00270                         /* completed current u32 bitmap */
00271                         if (iterator->bitmap_shifter & 1) {
00272                                 /* b31 was set, there is more */
00273                                 /* move to next u32 bitmap */
00274                                 iterator->bitmap_shifter = le32_to_cpu(
00275                                         get_unaligned(iterator->next_bitmap));
00276                                 iterator->next_bitmap++;
00277                         } else
00278                                 /* no more bitmaps: end */
00279                                 iterator->arg_index = sizeof(rt_sizes);
00280                 } else /* just try the next bit */
00281                         iterator->bitmap_shifter >>= 1;
00282 
00283                 /* if we found a valid arg earlier, return it now */
00284                 if (hit)
00285                         return 0;
00286         }
00287 
00288         /* we don't know how to handle any more args, we're done */
00289         return -ENOENT;
00290 }
00291 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:54 2009 for hostapd by  doxygen 1.6.1