/*
 * Radiotap parser
 *
 * Copyright 2007		Andy Green <andy@warmcat.com>
 * Copyright 2009		Johannes Berg <johannes@sipsolutions.net>
 *
 * SPDX-License-Identifier: (ISC OR GPL-2.0-only)
 */

#ifndef __RADIOTAP_ITER_H
#define __RADIOTAP_ITER_H

#define RADIOTAP_SUPPORT_OVERRIDES

#include "packet-ieee80211-radiotap-defs.h"

/* Radiotap header iteration
 *   implemented in radiotap.c
 */

struct radiotap_override {
	uint8_t field;
	unsigned align:4, size:4;
};

struct radiotap_align_size {
	unsigned align:4, size:4;
};

struct ieee80211_radiotap_namespace {
	const struct radiotap_align_size *align_size;
	int n_bits;
	uint32_t oui;
	uint8_t subns;
};

struct ieee80211_radiotap_vendor_namespaces {
	const struct ieee80211_radiotap_namespace *ns;
	int n_ns;
};

/**
 * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
 *
 * Describes the radiotap parser state. Fields prefixed with an underscore
 * must not be used by users of the parser, only by the parser internally.
 */

struct ieee80211_radiotap_iterator {
	struct ieee80211_radiotap_header *_rtheader;				/**< pointer to the radiotap header we are walking through */
	const struct ieee80211_radiotap_vendor_namespaces *_vns;		/**< vendor namespace definitions*/
	const struct ieee80211_radiotap_namespace *current_namespace;		/**< pointer to the current namespace definition (or internally
											%NULL if the current namespace is unknown)*/

	unsigned char *_arg, *_next_ns_data;					/**< beginning of the next namespace's data */
	uint32_t *_next_bitmap;							/**< internal pointer to next present u32 */

	unsigned char *this_arg;						/**< pointer to current radiotap arg; it is valid after each call
											to ieee80211_radiotap_iterator_next() but also after
											ieee80211_radiotap_iterator_init() where it will point to
											the beginning of the actual data portion */
#ifdef RADIOTAP_SUPPORT_OVERRIDES
	const struct radiotap_override *overrides;				/**< override standard radiotap fields */
	int n_overrides;							/**< number of overrides */
#endif
	int this_arg_index;							/**< index of current arg, valid after each successful call to
										ieee80211_radiotap_iterator_next() */
	int this_arg_size;							/**< length of the current arg, for convenience*/

	int is_radiotap_ns;
	int tlv_mode;

	int _max_length;							/**< length of radiotap header in cpu byte ordering */
	int _arg_index;								/**< next argument index */
	uint32_t _bitmap_shifter;						/**< internal shifter for curr u32 bitmap, b0 set == arg present */
	int _reset_on_ext;							/**< internal; reset the arg index to 0 when going to the next bitmap word */
};

extern int ieee80211_radiotap_iterator_init(
	struct ieee80211_radiotap_iterator *iterator,
	struct ieee80211_radiotap_header *radiotap_header,
	int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns);

extern int ieee80211_radiotap_iterator_next(
	struct ieee80211_radiotap_iterator *iterator);

#endif /* __RADIOTAP_ITER_H */
