18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Radiotap parser
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright 2007		Andy Green <andy@warmcat.com>
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Modified for userspace by Johannes Berg <johannes@sipsolutions.net>
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * I only modified some things on top to ease syncing should bugs be found.
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radiotap_iter.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define le16_to_cpu		le_to_host16
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define le32_to_cpu		le_to_host32
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define __le32			uint32_t
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ulong			unsigned long
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define unlikely(cond)		(cond)
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define get_unaligned(p)					\
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt({								\
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct packed_dummy_struct {				\
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		typeof(*(p)) __val;				\
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} __attribute__((packed)) *__ptr = (void *) (p);	\
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt								\
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	__ptr->__val;						\
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt})
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* function prototypes and related defs are in radiotap_iter.h */
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @iterator: radiotap_iterator to initialize
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radiotap_header: radiotap header to parse
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @max_length: total length we can parse into (eg, whole packet length)
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 or a negative error code if there is a problem.
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function initializes an opaque iterator struct which can then
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * argument which is present in the header.  It knows about extended
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * present headers and handles them.
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * How to use:
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * checking for a good 0 return code.  Then loop calling
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * __ieee80211_radiotap_iterator_next()... it returns either 0,
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The iterator's @this_arg member points to the start of the argument
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * associated with the current argument index that is present, which can be
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * found in the iterator's @this_arg_index member.  This arg index corresponds
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the IEEE80211_RADIOTAP_... defines.
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Radiotap header length:
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * You can find the CPU-endian total radiotap header length in
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iterator->max_length after executing ieee80211_radiotap_iterator_init()
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successfully.
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alignment Gotcha:
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * You must take care when dereferencing iterator.this_arg
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for multibyte types... the pointer is not aligned.  Use
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_unaligned((type *)iterator.this_arg) to dereference
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iterator.this_arg for type "type" safely on all arches.
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Example code:
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See Documentation/networking/radiotap-headers.txt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee80211_radiotap_iterator_init(
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    struct ieee80211_radiotap_iterator *iterator,
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    struct ieee80211_radiotap_header *radiotap_header,
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    int max_length)
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Linux only supports version 0 radiotap format */
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (radiotap_header->it_version)
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -EINVAL;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* sanity check for allowed length and radiotap length field */
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -EINVAL;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iterator->rtheader = radiotap_header;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iterator->max_length = le16_to_cpu(get_unaligned(
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						&radiotap_header->it_len));
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iterator->arg_index = 0;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						&radiotap_header->it_present));
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	iterator->this_arg = NULL;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* find payload start allowing for extended bitmap(s) */
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) &
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (1<<IEEE80211_RADIOTAP_EXT)) {
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iterator->arg += sizeof(u32);
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * check for insanity where the present bitmaps
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * keep claiming to extend up to or even beyond the
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * stated radiotap header length
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (((ulong)iterator->arg - (ulong)iterator->rtheader)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    > (ulong)iterator->max_length)
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -EINVAL;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iterator->arg += sizeof(u32);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * no need to check again for blowing past stated radiotap
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * header length, because ieee80211_radiotap_iterator_next
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * checks it before it is dereferenced
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* we are all initialized happily */
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @iterator: radiotap_iterator to move to next arg (if any)
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if there is an argument to handle,
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -ENOENT if there are no more args or -EINVAL
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * if there is something else wrong.
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in @this_arg_index and sets @this_arg to point to the
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * payload for the field.  It takes care of alignment handling and extended
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * present fields.  @this_arg can be changed by the caller (eg,
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * incremented to move inside a compound argument like
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * little-endian format whatever the endianess of your CPU.
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alignment Gotcha:
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * You must take care when dereferencing iterator.this_arg
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for multibyte types... the pointer is not aligned.  Use
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * get_unaligned((type *)iterator.this_arg) to dereference
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iterator.this_arg for type "type" safely on all arches.
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee80211_radiotap_iterator_next(
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt    struct ieee80211_radiotap_iterator *iterator)
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * small length lookup table for all radiotap types we heard of
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * starting from b0 in the bitmap, so we can walk the payload
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * area of the radiotap header
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * There is a requirement to pad args, so that args
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * of a given length must begin at a boundary of that length
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * -- but note that compound args are allowed (eg, 2 x u16
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * a reliable indicator of alignment requirement.
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * upper nybble: content alignment for arg
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * lower nybble: content length for arg
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u8 rt_sizes[] = {
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_TSFT] = 0x88,
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_FLAGS] = 0x11,
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_RATE] = 0x11,
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_CHANNEL] = 0x24,
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_FHSS] = 0x22,
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_ANTENNA] = 0x11,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11,
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_RX_FLAGS] = 0x22,
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_TX_FLAGS] = 0x22,
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11,
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		[IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11,
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * add more here as they are defined in
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * include/net/ieee80211_radiotap.h
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for every radiotap entry we can at
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * least skip (by knowing the length)...
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (iterator->arg_index < (int) sizeof(rt_sizes)) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int hit = 0;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int pad;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(iterator->bitmap_shifter & 1))
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto next_entry; /* arg not present */
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * arg is present, account for alignment padding
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *  8-bit args can be at any alignment
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * 16-bit args must start on 16-bit boundary
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * 32-bit args must start on 32-bit boundary
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * 64-bit args must start on 64-bit boundary
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * note that total arg size can differ from alignment of
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * elements inside arg, so we use upper nybble of length
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * table to base alignment on
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * also note: these alignments are ** relative to the
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * start of the radiotap header **.  There is no guarantee
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * that the radiotap header itself is aligned on any
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * kind of boundary.
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the above is why get_unaligned() is used to dereference
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * multibyte elements from the radiotap area
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pad = (((ulong)iterator->arg) -
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			((ulong)iterator->rtheader)) &
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			((rt_sizes[iterator->arg_index] >> 4) - 1);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pad)
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iterator->arg +=
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(rt_sizes[iterator->arg_index] >> 4) - pad;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * this is what we will return to user, but we need to
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * move on first so next call has something fresh to test
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iterator->this_arg_index = iterator->arg_index;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iterator->this_arg = iterator->arg;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hit = 1;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* internally move on the size of this arg */
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * check for insanity where we are given a bitmap that
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * claims to have more arg content than the length of the
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * radiotap section.  We will normally end up equalling this
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * max_length on the last arg, never exceeding it.
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (ulong) iterator->max_length)
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -EINVAL;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	next_entry:
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		iterator->arg_index++;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (unlikely((iterator->arg_index & 31) == 0)) {
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* completed current u32 bitmap */
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (iterator->bitmap_shifter & 1) {
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* b31 was set, there is more */
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* move to next u32 bitmap */
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				iterator->bitmap_shifter = le32_to_cpu(
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					get_unaligned(iterator->next_bitmap));
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				iterator->next_bitmap++;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* no more bitmaps: end */
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				iterator->arg_index = sizeof(rt_sizes);
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else /* just try the next bit */
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			iterator->bitmap_shifter >>= 1;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* if we found a valid arg earlier, return it now */
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hit)
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* we don't know how to handle any more args, we're done */
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -ENOENT;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
288