diff --git a/src/ip.cpp b/src/ip.cpp index 9b011fe..2247b97 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -117,24 +117,31 @@ IP::IP(const uint8_t *buffer, uint32_t total_sz) throw malformed_packet(); total_sz -= head_len() * sizeof(uint32_t); if (total_sz) { - inner_pdu( - Internals::pdu_from_flag( - static_cast(_ip.protocol), - buffer, - total_sz, - false - ) - ); - if(!inner_pdu()) { + // Don't try to decode it if it's fragmented + if(frag_off() == 0 || frag_off() == 0x4000) { inner_pdu( - Internals::allocate( - _ip.protocol, + Internals::pdu_from_flag( + static_cast(_ip.protocol), buffer, - total_sz + total_sz, + false ) ); - if(!inner_pdu()) - inner_pdu(new RawPDU(buffer, total_sz)); + if(!inner_pdu()) { + inner_pdu( + Internals::allocate( + _ip.protocol, + buffer, + total_sz + ) + ); + if(!inner_pdu()) + inner_pdu(new RawPDU(buffer, total_sz)); + } + } + else { + // It's fragmented, just use RawPDU + inner_pdu(new RawPDU(buffer, total_sz)); } } } diff --git a/tests/src/ip.cpp b/tests/src/ip.cpp index d5a1d91..272a5ec 100644 --- a/tests/src/ip.cpp +++ b/tests/src/ip.cpp @@ -14,7 +14,7 @@ using namespace Tins; class IPTest : public testing::Test { public: - static const uint8_t expected_packet[]; + static const uint8_t expected_packet[], fragmented_packet[]; void test_equals(const IP &ip1, const IP &ip2); }; @@ -24,6 +24,12 @@ const uint8_t IPTest::expected_packet[] = { 168, 9, 43, 130, 11, 116, 106, 103, 171, 119, 171, 104, 101, 108, 0 }; +const uint8_t IPTest::fragmented_packet[] = { + 69, 0, 0, 60, 0, 242, 7, 223, 64, 17, 237, 220, 192, 0, 2, 1, 192, + 0, 2, 2, 192, 0, 192, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + TEST_F(IPTest, DefaultConstructor) { IP ip; @@ -63,6 +69,12 @@ TEST_F(IPTest, Constructor) { EXPECT_EQ(ip.id(), 1); } +TEST_F(IPTest, ConstructorFromFragmentedPacket) { + IP ip(fragmented_packet, sizeof(fragmented_packet)); + ASSERT_TRUE(ip.inner_pdu()); + EXPECT_EQ(PDU::RAW, ip.inner_pdu()->pdu_type()); +} + TEST_F(IPTest, TOS) { IP ip; ip.tos(0x7a);