From 4e95797710065017394f05a0ff84bd7dfdeabe12 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sun, 21 May 2017 13:09:53 -0700 Subject: [PATCH] Allow constructing RadioTapParser from an empty buffer --- include/tins/utils/radiotap_parser.h | 21 +++++---------------- src/utils/radiotap_parser.cpp | 19 ++++++++++++++----- tests/src/radiotap_test.cpp | 10 ++++++++++ 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/include/tins/utils/radiotap_parser.h b/include/tins/utils/radiotap_parser.h index f63ff7d..4afd980 100644 --- a/include/tins/utils/radiotap_parser.h +++ b/include/tins/utils/radiotap_parser.h @@ -60,22 +60,6 @@ public: typedef PDUOption 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); diff --git a/src/utils/radiotap_parser.cpp b/src/utils/radiotap_parser.cpp index 8954af5..677064c 100644 --- a/src/utils/radiotap_parser.cpp +++ b/src/utils/radiotap_parser.cpp @@ -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& 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; } diff --git a/tests/src/radiotap_test.cpp b/tests/src/radiotap_test.cpp index 0166197..59c5a1b 100644 --- a/tests/src/radiotap_test.cpp +++ b/tests/src/radiotap_test.cpp @@ -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 buffer; + RadioTapParser parser(buffer); + EXPECT_FALSE(parser.has_fields()); + EXPECT_FALSE(parser.advance_field()); + EXPECT_FALSE(parser.has_fields()); } #endif // TINS_HAVE_DOT11