diff --git a/src/icmp.cpp b/src/icmp.cpp index 9b4c9c2..0ce0242 100644 --- a/src/icmp.cpp +++ b/src/icmp.cpp @@ -57,10 +57,14 @@ ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz) buffer += sizeof(icmphdr); total_sz -= sizeof(icmphdr); if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) { + if(total_sz < sizeof(uint32_t) * 3) + throw malformed_packet(); const uint32_t *ptr = reinterpret_cast(buffer); original_timestamp(*ptr++); receive_timestamp(*ptr++); transmit_timestamp(*ptr++); + total_sz -= sizeof(uint32_t) * 3; + buffer += sizeof(uint32_t) * 3; } if(total_sz) inner_pdu(new RawPDU(buffer, total_sz)); @@ -183,17 +187,16 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) *ptr++ = receive_timestamp(); *ptr++ = transmit_timestamp(); } - // checksum calc _icmp.check = 0; - - uint32_t checksum = Utils::do_checksum(buffer + ICMP::header_size(), buffer + total_sz) + - Utils::do_checksum((uint8_t*)&_icmp, ((uint8_t*)&_icmp) + ICMP::header_size()); + memcpy(buffer, &_icmp, sizeof(icmphdr)); + uint32_t checksum = Utils::do_checksum(buffer, buffer + total_sz); + while (checksum >> 16) checksum = (checksum & 0xffff) + (checksum >> 16); _icmp.check = Endian::host_to_be(~checksum); - memcpy(buffer, &_icmp, sizeof(icmphdr)); + ((icmphdr*)buffer)->check = _icmp.check; } bool ICMP::matches_response(const uint8_t *ptr, uint32_t total_sz) const { diff --git a/tests/src/icmp.cpp b/tests/src/icmp.cpp index 7754f20..2b73850 100644 --- a/tests/src/icmp.cpp +++ b/tests/src/icmp.cpp @@ -3,6 +3,8 @@ #include #include #include "icmp.h" +#include "ip.h" +#include "ethernetII.h" #include "utils.h" using namespace std; @@ -67,6 +69,19 @@ TEST_F(ICMPTest, FlagConstructor) { EXPECT_EQ(icmp.type(), ICMP::ECHO_REPLY); } +TEST_F(ICMPTest, ChecksumOnTimestamp) { + const uint8_t raw_pkt[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 69, 0, 0, 45, 0, 1, 0, + 0, 128, 1, 185, 25, 192, 168, 0, 100, 192, 168, 0, 1, 13, 0, 237, + 141, 0, 0, 0, 0, 159, 134, 1, 0, 151, 134, 1, 0, 152, 134, 1, 0, + 98, 111, 105, 110, 103, 0 + }; + EthernetII pkt(raw_pkt, sizeof(raw_pkt)); + pkt.serialize(); + EXPECT_EQ(0xb919, pkt.rfind_pdu().checksum()); + EXPECT_EQ(0xed8d, pkt.rfind_pdu().check()); +} + TEST_F(ICMPTest, Code) { ICMP icmp; icmp.code(0x7a);