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:
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user