mirror of
https://github.com/mfontanini/libtins
synced 2026-01-28 04:34:27 +01:00
Added support for ICMP address mask request/reply.
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
@@ -61,7 +62,9 @@ namespace Tins {
|
||||
TIMESTAMP_REQUEST = 13,
|
||||
TIMESTAMP_REPLY = 14,
|
||||
INFO_REQUEST = 15,
|
||||
INFO_REPLY = 16
|
||||
INFO_REPLY = 16,
|
||||
ADDRESS_MASK_REQUEST = 17,
|
||||
ADDRESS_MASK_REPLY = 18
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -136,24 +139,31 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Setter for the original timestamp field.
|
||||
*
|
||||
* \param new_pointer the value to be set.
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void original_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the receive timestamp field.
|
||||
*
|
||||
* \param new_pointer the value to be set.
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void receive_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transmit timestamp field.
|
||||
*
|
||||
* \param new_pointer the value to be set.
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void transmit_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the address mask field.
|
||||
*
|
||||
* \param new_mask the value to be set.
|
||||
*/
|
||||
void address_mask(IPv4Address new_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets echo request flag for this PDU.
|
||||
*
|
||||
@@ -285,7 +295,7 @@ namespace Tins {
|
||||
*
|
||||
* \return Returns the original timestamp value.
|
||||
*/
|
||||
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp); }
|
||||
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the receive timestamp field.
|
||||
@@ -301,6 +311,15 @@ namespace Tins {
|
||||
*/
|
||||
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the address mask field.
|
||||
*
|
||||
* \return Returns the address mask value.
|
||||
*/
|
||||
IPv4Address address_mask() const {
|
||||
return IPv4Address(Endian::be_to_host(_orig_timestamp_or_address_mask));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
@@ -361,7 +380,7 @@ namespace Tins {
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
icmphdr _icmp;
|
||||
uint32_t _orig_timestamp, _recv_timestamp, _trans_timestamp;
|
||||
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
27
src/icmp.cpp
27
src/icmp.cpp
@@ -43,7 +43,7 @@
|
||||
|
||||
namespace Tins {
|
||||
ICMP::ICMP(Flags flag)
|
||||
: _orig_timestamp(), _recv_timestamp(), _trans_timestamp()
|
||||
: _orig_timestamp_or_address_mask(), _recv_timestamp(), _trans_timestamp()
|
||||
{
|
||||
std::memset(&_icmp, 0, sizeof(icmphdr));
|
||||
type(flag);
|
||||
@@ -66,6 +66,14 @@ ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz)
|
||||
total_sz -= sizeof(uint32_t) * 3;
|
||||
buffer += sizeof(uint32_t) * 3;
|
||||
}
|
||||
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) {
|
||||
if(total_sz < sizeof(uint32_t))
|
||||
throw malformed_packet();
|
||||
const uint32_t *ptr = reinterpret_cast<const uint32_t*>(buffer);
|
||||
address_mask(IPv4Address(*ptr++));
|
||||
total_sz -= sizeof(uint32_t);
|
||||
buffer += sizeof(uint32_t);
|
||||
}
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer, total_sz));
|
||||
}
|
||||
@@ -103,7 +111,7 @@ void ICMP::pointer(uint8_t new_pointer) {
|
||||
}
|
||||
|
||||
void ICMP::original_timestamp(uint32_t new_timestamp) {
|
||||
_orig_timestamp = Endian::host_to_be(new_timestamp);
|
||||
_orig_timestamp_or_address_mask = Endian::host_to_be(new_timestamp);
|
||||
}
|
||||
|
||||
void ICMP::receive_timestamp(uint32_t new_timestamp) {
|
||||
@@ -114,10 +122,16 @@ void ICMP::transmit_timestamp(uint32_t new_timestamp) {
|
||||
_trans_timestamp = Endian::host_to_be(new_timestamp);
|
||||
}
|
||||
|
||||
void ICMP::address_mask(IPv4Address new_mask) {
|
||||
_orig_timestamp_or_address_mask = Endian::host_to_be(static_cast<uint32_t>(new_mask));
|
||||
}
|
||||
|
||||
uint32_t ICMP::header_size() const {
|
||||
uint32_t extra = 0;
|
||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY)
|
||||
extra += sizeof(uint32_t) * 3;
|
||||
extra = sizeof(uint32_t) * 3;
|
||||
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY)
|
||||
extra = sizeof(uint32_t);
|
||||
return sizeof(icmphdr) + extra;
|
||||
}
|
||||
|
||||
@@ -187,6 +201,10 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
||||
*ptr++ = receive_timestamp();
|
||||
*ptr++ = transmit_timestamp();
|
||||
}
|
||||
else if(type() == ADDRESS_MASK_REQUEST || type() == ADDRESS_MASK_REPLY) {
|
||||
uint32_t *ptr = reinterpret_cast<uint32_t*>(buffer + sizeof(icmphdr));
|
||||
*ptr++ = address_mask();
|
||||
}
|
||||
// checksum calc
|
||||
_icmp.check = 0;
|
||||
memcpy(buffer, &_icmp, sizeof(icmphdr));
|
||||
@@ -204,7 +222,8 @@ bool ICMP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
return false;
|
||||
const icmphdr *icmp_ptr = (const icmphdr*)ptr;
|
||||
if((_icmp.type == ECHO_REQUEST && icmp_ptr->type == ECHO_REPLY) ||
|
||||
(_icmp.type == TIMESTAMP_REQUEST && icmp_ptr->type == TIMESTAMP_REPLY)) {
|
||||
(_icmp.type == TIMESTAMP_REQUEST && icmp_ptr->type == TIMESTAMP_REPLY) ||
|
||||
(_icmp.type == ADDRESS_MASK_REQUEST && icmp_ptr->type == ADDRESS_MASK_REPLY)) {
|
||||
return icmp_ptr->un.echo.id == _icmp.un.echo.id && icmp_ptr->un.echo.sequence == _icmp.un.echo.sequence;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -82,6 +82,19 @@ TEST_F(ICMPTest, ChecksumOnTimestamp) {
|
||||
EXPECT_EQ(0xed8d, pkt.rfind_pdu<ICMP>().check());
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, AddressMaskRequest) {
|
||||
const uint8_t raw_pkt[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 69, 0, 0, 32, 0, 1, 0,
|
||||
0, 64, 1, 249, 38, 192, 168, 0, 100, 192, 168, 0, 1, 17, 0, 234,
|
||||
249, 0, 0, 0, 0, 1, 2, 3, 4
|
||||
};
|
||||
EthernetII pkt(raw_pkt, sizeof(raw_pkt));
|
||||
IP::serialization_type buffer = pkt.serialize();
|
||||
EXPECT_EQ(0xf926, pkt.rfind_pdu<IP>().checksum());
|
||||
EXPECT_EQ(0xeaf9, pkt.rfind_pdu<ICMP>().check());
|
||||
EXPECT_EQ(IPv4Address("1.2.3.4"), pkt.rfind_pdu<ICMP>().address_mask());
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, Code) {
|
||||
ICMP icmp;
|
||||
icmp.code(0x7a);
|
||||
@@ -142,6 +155,12 @@ TEST_F(ICMPTest, TransmitTimestamp) {
|
||||
EXPECT_EQ(0x1f8172da, icmp.transmit_timestamp());
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, AddressMask) {
|
||||
ICMP icmp;
|
||||
icmp.address_mask("192.168.0.1");
|
||||
EXPECT_EQ(IPv4Address("192.168.0.1"), icmp.address_mask());
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, SetEchoRequest) {
|
||||
ICMP icmp;
|
||||
icmp.set_echo_request(0x7af1, 0x123f);
|
||||
|
||||
Reference in New Issue
Block a user