mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Allow constructing RadioTapParser from an empty buffer
This commit is contained in:
@@ -60,22 +60,6 @@ public:
|
||||
|
||||
typedef PDUOption<uint8_t, RadioTap> option;
|
||||
|
||||
/**
|
||||
* The RadioTap header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct RadiotapHeader {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t version;
|
||||
uint8_t padding;
|
||||
#else
|
||||
uint8_t padding;
|
||||
uint8_t version;
|
||||
#endif // TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t length;
|
||||
uint32_t flags;
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
* \brief Constructs a RadioTap parser around a payload
|
||||
*
|
||||
@@ -118,6 +102,11 @@ public:
|
||||
* the end of the header)
|
||||
*/
|
||||
bool advance_field();
|
||||
|
||||
/**
|
||||
* Indicates whether this RadioTap options buffer contains any fields set
|
||||
*/
|
||||
bool has_fields() const;
|
||||
private:
|
||||
const uint8_t* find_options_start() const;
|
||||
bool advance_to_next_field(bool start_from_zero);
|
||||
|
||||
@@ -63,7 +63,7 @@ static const FieldMetadata RADIOTAP_METADATA[] = {
|
||||
{ 3, 1 }, // MCS
|
||||
};
|
||||
|
||||
static const uint64_t BIT_LIMIT = sizeof(RADIOTAP_METADATA) / sizeof(FieldMetadata) + 1;
|
||||
static const uint32_t BIT_LIMIT = sizeof(RADIOTAP_METADATA) / sizeof(FieldMetadata) + 1;
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
@@ -141,7 +141,7 @@ void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t
|
||||
}
|
||||
|
||||
RadioTapParser::RadioTapParser(const vector<uint8_t>& buffer)
|
||||
: current_namespace_(RADIOTAP_NS), current_bit_(0), namespace_index_(0) {
|
||||
: current_namespace_(RADIOTAP_NS), current_bit_(BIT_LIMIT), namespace_index_(0) {
|
||||
if (buffer.empty()) {
|
||||
start_ = 0;
|
||||
end_ = 0;
|
||||
@@ -177,19 +177,28 @@ const uint8_t* RadioTapParser::current_option_ptr() const {
|
||||
}
|
||||
|
||||
bool RadioTapParser::advance_field() {
|
||||
// If we have no buffer to parse, then we can't advance
|
||||
if (start_ == 0 || current_bit_ == BIT_LIMIT) {
|
||||
return false;
|
||||
}
|
||||
// If we manage to advance the field, return true
|
||||
if (advance_to_next_field(false /* keep going from current */)) {
|
||||
return true;
|
||||
}
|
||||
// We finished iterating the current namespace (if any). Reset our bit
|
||||
current_bit_ = BIT_LIMIT;
|
||||
// Otherwise, let's try advancing the namespace. If we fail, then we failed
|
||||
if (!advance_to_next_namespace()) {
|
||||
return false;
|
||||
}
|
||||
// Otherwise restart bit and try to find the first field in this namespace
|
||||
current_bit_ = 0;
|
||||
// Try to find the first field in this new namespace
|
||||
return advance_to_next_field(true /* start from 0*/);
|
||||
}
|
||||
|
||||
bool RadioTapParser::has_fields() const {
|
||||
return current_bit_ != BIT_LIMIT;
|
||||
}
|
||||
|
||||
const uint8_t* RadioTapParser::find_options_start() const {
|
||||
uint32_t total_sz = end_ - start_;
|
||||
if (TINS_UNLIKELY(total_sz < sizeof(RadioTapFlags))) {
|
||||
@@ -209,7 +218,7 @@ const uint8_t* RadioTapParser::find_options_start() const {
|
||||
|
||||
bool RadioTapParser::advance_to_next_field(bool start_from_zero) {
|
||||
const RadioTapFlags* flags = get_flags_ptr();
|
||||
uint64_t bit;
|
||||
uint32_t bit;
|
||||
if (start_from_zero) {
|
||||
bit = 0;
|
||||
}
|
||||
|
||||
@@ -446,6 +446,7 @@ TEST_F(RadioTapTest, RadioTapParsingMultipleNamespaces) {
|
||||
}
|
||||
// MCS is the last option in this namespace. After this, we should jump to the next one
|
||||
EXPECT_TRUE(parser.advance_field());
|
||||
EXPECT_TRUE(parser.has_fields());
|
||||
|
||||
// These are on the second namespace
|
||||
EXPECT_EQ(RadioTap::DBM_SIGNAL, parser.current_field());
|
||||
@@ -460,6 +461,15 @@ TEST_F(RadioTapTest, RadioTapParsingMultipleNamespaces) {
|
||||
EXPECT_FALSE(parser.advance_field());
|
||||
EXPECT_FALSE(parser.advance_field());
|
||||
EXPECT_EQ(RadioTapParser::RADIOTAP_NS, parser.current_namespace());
|
||||
EXPECT_FALSE(parser.has_fields());
|
||||
}
|
||||
|
||||
TEST_F(RadioTapTest, RadioTapParsingUsingEmptyBuffer) {
|
||||
vector<uint8_t> buffer;
|
||||
RadioTapParser parser(buffer);
|
||||
EXPECT_FALSE(parser.has_fields());
|
||||
EXPECT_FALSE(parser.advance_field());
|
||||
EXPECT_FALSE(parser.has_fields());
|
||||
}
|
||||
|
||||
#endif // TINS_HAVE_DOT11
|
||||
|
||||
Reference in New Issue
Block a user