1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Add some useful member functions to RadioTapParser

This commit is contained in:
Matias Fontanini
2017-05-23 19:07:49 -07:00
parent 4e95797710
commit 7af1ec0984
2 changed files with 79 additions and 14 deletions

View File

@@ -58,7 +58,25 @@ public:
UNKNOWN_NS UNKNOWN_NS
}; };
typedef PDUOption<uint8_t, RadioTap> option; typedef PDUOption<RadioTap::PresentFlags, RadioTap> option;
/**
* 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 * \brief Constructs a RadioTap parser around a payload
@@ -78,6 +96,13 @@ public:
*/ */
NamespaceType current_namespace() const; 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 * Gets the current field being parsed
*/ */
@@ -103,10 +128,27 @@ public:
*/ */
bool advance_field(); bool advance_field();
/**
* \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 * Indicates whether this RadioTap options buffer contains any fields set
*/ */
bool has_fields() const; 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: private:
const uint8_t* find_options_start() const; const uint8_t* find_options_start() const;
bool advance_to_next_field(bool start_from_zero); bool advance_to_next_field(bool start_from_zero);

View File

@@ -35,12 +35,7 @@ using std::vector;
namespace Tins { namespace Tins {
namespace Utils { namespace Utils {
struct FieldMetadata { const RadioTapParser::FieldMetadata RadioTapParser::RADIOTAP_METADATA[] = {
uint32_t size;
uint32_t alignment;
};
static const FieldMetadata RADIOTAP_METADATA[] = {
{ 8, 8 }, /// TSFT { 8, 8 }, /// TSFT
{ 1, 1 }, // FLAGS { 1, 1 }, // FLAGS
{ 1, 1 }, // RATE { 1, 1 }, // RATE
@@ -63,7 +58,8 @@ static const FieldMetadata RADIOTAP_METADATA[] = {
{ 3, 1 }, // MCS { 3, 1 }, // MCS
}; };
static const uint32_t BIT_LIMIT = sizeof(RADIOTAP_METADATA) / sizeof(FieldMetadata) + 1; const uint32_t RadioTapParser::MAX_RADIOTAP_FIELD = sizeof(RADIOTAP_METADATA) /
sizeof(FieldMetadata) + 1;
#if TINS_IS_LITTLE_ENDIAN #if TINS_IS_LITTLE_ENDIAN
TINS_BEGIN_PACK TINS_BEGIN_PACK
@@ -141,7 +137,7 @@ void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t
} }
RadioTapParser::RadioTapParser(const vector<uint8_t>& buffer) RadioTapParser::RadioTapParser(const vector<uint8_t>& buffer)
: current_namespace_(RADIOTAP_NS), current_bit_(BIT_LIMIT), namespace_index_(0) { : current_namespace_(RADIOTAP_NS), current_bit_(MAX_RADIOTAP_FIELD), namespace_index_(0) {
if (buffer.empty()) { if (buffer.empty()) {
start_ = 0; start_ = 0;
end_ = 0; end_ = 0;
@@ -160,6 +156,10 @@ RadioTapParser::NamespaceType RadioTapParser::current_namespace() const {
return current_namespace_; return current_namespace_;
} }
uint32_t RadioTapParser::current_namespace_index() const {
return namespace_index_;
}
RadioTap::PresentFlags RadioTapParser::current_field() const { RadioTap::PresentFlags RadioTapParser::current_field() const {
return static_cast<RadioTap::PresentFlags>(1 << current_bit_); return static_cast<RadioTap::PresentFlags>(1 << current_bit_);
} }
@@ -178,7 +178,7 @@ const uint8_t* RadioTapParser::current_option_ptr() const {
bool RadioTapParser::advance_field() { bool RadioTapParser::advance_field() {
// If we have no buffer to parse, then we can't advance // If we have no buffer to parse, then we can't advance
if (start_ == 0 || current_bit_ == BIT_LIMIT) { if (start_ == 0 || current_bit_ == MAX_RADIOTAP_FIELD) {
return false; return false;
} }
// If we manage to advance the field, return true // If we manage to advance the field, return true
@@ -186,7 +186,7 @@ bool RadioTapParser::advance_field() {
return true; return true;
} }
// We finished iterating the current namespace (if any). Reset our bit // We finished iterating the current namespace (if any). Reset our bit
current_bit_ = BIT_LIMIT; current_bit_ = MAX_RADIOTAP_FIELD;
// Otherwise, let's try advancing the namespace. If we fail, then we failed // Otherwise, let's try advancing the namespace. If we fail, then we failed
if (!advance_to_next_namespace()) { if (!advance_to_next_namespace()) {
return false; return false;
@@ -195,8 +195,31 @@ bool RadioTapParser::advance_field() {
return advance_to_next_field(true /* start from 0*/); return advance_to_next_field(true /* start from 0*/);
} }
bool RadioTapParser::skip_to_field(RadioTap::PresentFlags flag) {
while (has_fields() && current_field() != flag) {
advance_field();
}
return has_fields();
}
bool RadioTapParser::has_fields() const { bool RadioTapParser::has_fields() const {
return current_bit_ != BIT_LIMIT; return current_bit_ != MAX_RADIOTAP_FIELD;
}
bool RadioTapParser::has_field(RadioTap::PresentFlags flag) const {
const uint8_t* ptr = start_;
while (ptr + sizeof(uint32_t) < end_) {
const RadioTapFlags* flags = (const RadioTapFlags*)ptr;
if (is_field_set(flag, flags)) {
return true;
}
if (!flags->ext) {
break;
}
// Jump to the next flags field
ptr += sizeof(uint32_t);
}
return false;
} }
const uint8_t* RadioTapParser::find_options_start() const { const uint8_t* RadioTapParser::find_options_start() const {
@@ -227,10 +250,10 @@ bool RadioTapParser::advance_to_next_field(bool start_from_zero) {
current_ptr_ += RADIOTAP_METADATA[current_bit_].size; current_ptr_ += RADIOTAP_METADATA[current_bit_].size;
bit = current_bit_ + 1; bit = current_bit_ + 1;
} }
while (!is_field_set(1 << bit, flags) && bit < BIT_LIMIT) { while (!is_field_set(1 << bit, flags) && bit < MAX_RADIOTAP_FIELD) {
bit++; bit++;
} }
if (bit < BIT_LIMIT) { if (bit < MAX_RADIOTAP_FIELD) {
const uint8_t* radiotap_start = start_ - sizeof(uint32_t); const uint8_t* radiotap_start = start_ - sizeof(uint32_t);
// Skip and align the buffer // Skip and align the buffer
align_buffer(radiotap_start, current_ptr_, end_ - radiotap_start, align_buffer(radiotap_start, current_ptr_, end_ - radiotap_start,