diff --git a/include/ip.h b/include/ip.h index c23f96a..9c3a653 100644 --- a/include/ip.h +++ b/include/ip.h @@ -364,6 +364,17 @@ namespace Tins { /** * \brief Setter for the protocol field. * + * Note that this protocol will be overwritten using the + * inner_pdu's protocol type during serialization unless the IP + * datagram is fragmented. + * + * If the packet is fragmented and was originally sniffed, the + * original protocol type will be kept when serialized. + * + * If this packet has been crafted manually and the inner_pdu + * is, for example, a RawPDU, then setting the protocol yourself + * is necessary. + * * \param new_protocol The new protocol. */ void protocol(uint8_t new_protocol); diff --git a/src/ip.cpp b/src/ip.cpp index 28a43b8..bd9301e 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -400,8 +400,8 @@ void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* pare Internals::pdu_type_to_id(inner_pdu()->pdu_type()) ); } - protocol(new_flag); - //flag(new_flag); + if(!is_fragmented() || new_flag != 0xff) + protocol(new_flag); } #if __FreeBSD__ || defined(__FreeBSD_kernel__) diff --git a/tests/src/ip.cpp b/tests/src/ip.cpp index 272a5ec..b15e85c 100644 --- a/tests/src/ip.cpp +++ b/tests/src/ip.cpp @@ -8,13 +8,14 @@ #include "icmp.h" #include "ip_address.h" #include "utils.h" +#include "ethernetII.h" using namespace std; using namespace Tins; class IPTest : public testing::Test { public: - static const uint8_t expected_packet[], fragmented_packet[]; + static const uint8_t expected_packet[], fragmented_packet[], fragmented_ether_ip_packet[]; void test_equals(const IP &ip1, const IP &ip2); }; @@ -30,6 +31,13 @@ const uint8_t IPTest::fragmented_packet[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +const uint8_t IPTest::fragmented_ether_ip_packet[] = { + 0, 10, 94, 83, 216, 229, 0, 21, 197, 50, 245, 6, 8, 0, 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; @@ -75,6 +83,18 @@ TEST_F(IPTest, ConstructorFromFragmentedPacket) { EXPECT_EQ(PDU::RAW, ip.inner_pdu()->pdu_type()); } +TEST_F(IPTest, SerializeFragmentedPacket) { + EthernetII pkt(fragmented_ether_ip_packet, sizeof(fragmented_ether_ip_packet)); + PDU::serialization_type buffer = pkt.serialize(); + EXPECT_EQ( + PDU::serialization_type( + fragmented_ether_ip_packet, + fragmented_ether_ip_packet + sizeof(fragmented_ether_ip_packet) + ), + buffer + ); +} + TEST_F(IPTest, TOS) { IP ip; ip.tos(0x7a);