diff --git a/include/tins/ppi.h b/include/tins/ppi.h index 00b35e8..fe9c961 100644 --- a/include/tins/ppi.h +++ b/include/tins/ppi.h @@ -120,6 +120,7 @@ public: } private: void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *); + void parse_80211(const uint8_t* buffer, uint32_t total_sz); struct header { uint8_t version, flags; diff --git a/src/ppi.cpp b/src/ppi.cpp index e752e0c..967db71 100644 --- a/src/ppi.cpp +++ b/src/ppi.cpp @@ -63,7 +63,7 @@ PPI::PPI(const uint8_t *buffer, uint32_t total_sz) { switch(dlt()) { case DLT_IEEE802_11: #ifdef HAVE_DOT11 - inner_pdu(Dot11::from_bytes(buffer, total_sz)); + parse_80211(buffer, total_sz); #else throw protocol_disabled(); #endif @@ -99,4 +99,18 @@ void PPI::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { throw std::runtime_error("PPI serialization not supported"); } +void PPI::parse_80211(const uint8_t* buffer, uint32_t total_sz) { + if (_data.size() >= 13) { + // Is FCS-at-end on? + if ((_data[12] & 1) == 1) { + // We need to reduce the total size since we're skipping the FCS + if (total_sz < sizeof(uint32_t)) { + throw malformed_packet(); + } + total_sz -= sizeof(uint32_t); + } + } + inner_pdu(Dot11::from_bytes(buffer, total_sz)); } + +} // Tins diff --git a/tests/src/ppi.cpp b/tests/src/ppi.cpp index e3f39f4..a5bb550 100644 --- a/tests/src/ppi.cpp +++ b/tests/src/ppi.cpp @@ -1,4 +1,5 @@ #include "dot11/dot11_data.h" +#include "dot11/dot11_beacon.h" #ifdef HAVE_DOT11 @@ -13,7 +14,7 @@ using namespace Tins; class PPITest : public testing::Test { public: - static const uint8_t packet1[]; + static const uint8_t packet1[], dot11_with_options[]; }; const uint8_t PPITest::packet1[] = { @@ -30,6 +31,10 @@ const uint8_t PPITest::packet1[] = { 1, 0, 1, 120, 128, 89, 55 }; +const uint8_t PPITest::dot11_with_options[] = { + 0, 0, 32, 0, 105, 0, 0, 0, 2, 0, 20, 0, 128, 101, 85, 181, 14, 0, 0, 0, 1, 0, 2, 0, 113, 9, 160, 0, 0, 0, 205, 0, 128, 0, 0, 0, 255, 255, 255, 255, 255, 255, 6, 24, 10, 127, 79, 208, 6, 24, 10, 127, 79, 208, 240, 139, 128, 101, 85, 181, 14, 0, 0, 0, 100, 0, 49, 20, 0, 0, 1, 8, 130, 132, 139, 150, 12, 18, 24, 36, 3, 1, 1, 5, 4, 0, 1, 0, 0, 7, 6, 85, 83, 32, 1, 11, 30, 42, 1, 0, 48, 24, 1, 0, 0, 15, 172, 2, 2, 0, 0, 15, 172, 4, 0, 15, 172, 2, 1, 0, 0, 15, 172, 2, 0, 0, 50, 4, 48, 72, 96, 108, 51, 4, 12, 1, 6, 11, 70, 5, 115, 192, 1, 0, 0, 45, 26, 173, 17, 3, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 22, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 26, 0, 80, 242, 1, 1, 0, 0, 80, 242, 2, 2, 0, 0, 80, 242, 4, 0, 80, 242, 2, 1, 0, 0, 80, 242, 2, 221, 24, 0, 80, 242, 2, 1, 1, 138, 0, 3, 164, 0, 0, 39, 164, 0, 0, 66, 67, 94, 0, 98, 50, 47, 0, 221, 9, 0, 3, 127, 1, 1, 0, 0, 255, 127, 221, 13, 0, 24, 10, 7, 0, 0, 0, 0, 1, 0, 20, 63, 198, 54, 63, 126, 205 +}; + TEST_F(PPITest, ConstructorFromBuffer) { PPI pdu(packet1, sizeof(packet1)); EXPECT_EQ(0, pdu.version()); @@ -40,4 +45,12 @@ TEST_F(PPITest, ConstructorFromBuffer) { EXPECT_TRUE(pdu.find_pdu() != NULL); } +TEST_F(PPITest, ConstructorFromBufferUsingEncapsulatedDot11WithOptions) { + PPI pdu(dot11_with_options, sizeof(dot11_with_options)); + EXPECT_EQ(105U, pdu.dlt()); + Dot11Beacon* dot11 = pdu.find_pdu(); + ASSERT_TRUE(dot11 != NULL); + EXPECT_TRUE(dot11->search_option(static_cast(61)) != NULL); +} + #endif // HAVE_DOT11