Cheeze/lib/libtins/include/tins/utils/radiotap_parser.h
2024-02-21 14:52:47 +03:00

192 lines
5.6 KiB
C++

/*
* Copyright (c) 2017, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <tins/config.h>
#if !defined(TINS_RADIOTAP_PARSER_H) && defined(TINS_HAVE_DOT11)
#define TINS_RADIOTAP_PARSER_H
#include <stdint.h>
#include <tins/macros.h>
#include <tins/radiotap.h>
#include <tins/pdu_option.h>
namespace Tins {
namespace Utils {
struct RadioTapFlags;
/**
* \brief Allows parsing RadioTap options
*
* RadioTap is a somehow tricky protocol to be parsed, as it has ordered flags,
* alignment between options, etc. This class allows parsing options in a RadioTap
* header without much trouble.
*/
class RadioTapParser {
public:
/**
* Represents the RadioTap namespace currently being parsed
*/
enum NamespaceType {
RADIOTAP_NS,
VENDOR_NS,
UNKNOWN_NS
};
/**
* Represents the size and alignment of each RadioTap field
*/
struct FieldMetadata {
uint32_t size;
uint32_t alignment;
};
/**
* Contains metadata for each data field in RadioTap
*/
static const FieldMetadata RADIOTAP_METADATA[];
/**
* Represents the maximum bit we have information for
*/
static const uint32_t MAX_RADIOTAP_FIELD;
/**
* \brief Constructs a RadioTap parser around a payload
*
* Note that the payload is not copied, hence it must be kept in
* scope while the parser is still being used.
*
* The buffer should contain an entire RadioTap header, with optionally
* extra data at the end, which will be ignored.
*
* \param buffer The buffer to be parsed
*/
RadioTapParser(const std::vector<uint8_t>& buffer);
/**
* Gets the current namespace being parsed
*/
NamespaceType current_namespace() const;
/**
* \brief Gets a 0 index based namespace index.
*
* This index will be incremented every time a new namespace is found
*/
uint32_t current_namespace_index() const;
/**
* Gets the current field being parsed
*/
RadioTap::PresentFlags current_field() const;
/**
* Gets the option the parsed is currently pointing at
*/
RadioTap::option current_option();
/**
* \brief Gets the pointer at which the current option is located
*
* A past-the-end pointer may be returned in case of malformed input or
* end of data. Its validity must be checked (e.g. using
* \ref RadioTapParser.has_fields) before dereference.
*/
const uint8_t* current_option_ptr() const;
/**
* \brief Advances to the next option
*
* If there's a namespace change, this will handle that as well.
*
* \return true iff advancing was successfull (e.g. false if we reached
* the end of the header)
*/
bool advance_field();
/**
* \brief Advances to the next namespace
*
* \return true iff advancing was successfull (e.g. false if we're currently
* in the last namespace)
*/
bool advance_namespace();
/**
* Gets the current namespace's flags
*/
RadioTap::PresentFlags namespace_flags() const;
/**
* \brief Skips all fields until the provided one is found
*
* This will effectively move the current option pointer until the field is
* found or the end of the options list is reached
*
* \return true iff the field was foudn
*/
bool skip_to_field(RadioTap::PresentFlags flag);
/**
* Indicates whether this RadioTap options buffer contains any fields set
*/
bool has_fields() const;
/**
* \brief Indicates whether the provided field is set.
*
* This will look the field up in all flag sets and not just the current one
*/
bool has_field(RadioTap::PresentFlags flag) const;
private:
const uint8_t* find_options_start() const;
bool advance_to_first_field();
bool advance_to_next_field();
bool skip_current_field();
bool advance_to_next_namespace();
const RadioTapFlags* get_flags_ptr() const;
void load_current_flags();
bool is_field_set(uint32_t bit, const RadioTapFlags* flags) const;
const uint8_t* start_;
const uint8_t* end_;
const uint8_t* current_ptr_;
uint64_t current_bit_;
uint32_t current_flags_;
uint32_t namespace_index_;
NamespaceType current_namespace_;
};
} // Utils
} // Tins
#endif // TINS_RADIOTAP_PARSER_H