mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Added support for ICMP timestamp request/reply packets. ICMP::matches_response now works with these types of packets as well.
This commit is contained in:
@@ -59,8 +59,8 @@ DIST_COMMON = README $(am__configure_deps) $(libtins_HEADERS) \
|
||||
$(libtins_dot11_HEADERS) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/libtins.pc.in \
|
||||
$(top_srcdir)/configure $(top_srcdir)/include/config.h.in \
|
||||
AUTHORS COPYING INSTALL THANKS TODO config.guess config.sub \
|
||||
depcomp install-sh ltmain.sh missing
|
||||
AUTHORS THANKS config.guess config.sub depcomp install-sh \
|
||||
ltmain.sh missing
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace Tins {
|
||||
ECHO_REQUEST = 8,
|
||||
TIME_EXCEEDED = 11,
|
||||
PARAM_PROBLEM = 12,
|
||||
TIMESTAMP_REQUEST = 13,
|
||||
TIMESTAMP_REPLY = 14,
|
||||
INFO_REQUEST = 15,
|
||||
INFO_REPLY = 16
|
||||
};
|
||||
@@ -131,6 +133,27 @@ namespace Tins {
|
||||
*/
|
||||
void pointer(uint8_t new_pointer);
|
||||
|
||||
/**
|
||||
* \brief Setter for the original timestamp field.
|
||||
*
|
||||
* \param new_pointer 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.
|
||||
*/
|
||||
void receive_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transmit timestamp field.
|
||||
*
|
||||
* \param new_pointer the value to be set.
|
||||
*/
|
||||
void transmit_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Sets echo request flag for this PDU.
|
||||
*
|
||||
@@ -239,24 +262,45 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Getter for the gateway field.
|
||||
*
|
||||
* \return Returns the gateways in an unit32_t.
|
||||
* \return Returns the gateway field value.
|
||||
*/
|
||||
uint32_t gateway() const { return Endian::be_to_host(_icmp.un.gateway); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the pointer field.
|
||||
*
|
||||
* \return Returns the pointer value.
|
||||
* \return Returns the pointer field value.
|
||||
*/
|
||||
uint8_t pointer() const { return this->_icmp.un.pointer; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the mtu field.
|
||||
*
|
||||
* \return Returns the mtu value in an uint16_t.
|
||||
* \return Returns the mtu field value.
|
||||
*/
|
||||
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the original timestamp field.
|
||||
*
|
||||
* \return Returns the original timestamp value.
|
||||
*/
|
||||
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the receive timestamp field.
|
||||
*
|
||||
* \return Returns the receive timestamp value.
|
||||
*/
|
||||
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the transmit timestamp field.
|
||||
*
|
||||
* \return Returns the transmit timestamp value.
|
||||
*/
|
||||
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
@@ -317,6 +361,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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
42
src/icmp.cpp
42
src/icmp.cpp
@@ -43,6 +43,7 @@
|
||||
|
||||
namespace Tins {
|
||||
ICMP::ICMP(Flags flag)
|
||||
: _orig_timestamp(), _recv_timestamp(), _trans_timestamp()
|
||||
{
|
||||
std::memset(&_icmp, 0, sizeof(icmphdr));
|
||||
type(flag);
|
||||
@@ -53,9 +54,16 @@ ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz)
|
||||
if(total_sz < sizeof(icmphdr))
|
||||
throw malformed_packet();
|
||||
std::memcpy(&_icmp, buffer, sizeof(icmphdr));
|
||||
buffer += sizeof(icmphdr);
|
||||
total_sz -= sizeof(icmphdr);
|
||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
||||
const uint32_t *ptr = reinterpret_cast<const uint32_t*>(buffer);
|
||||
original_timestamp(*ptr++);
|
||||
receive_timestamp(*ptr++);
|
||||
transmit_timestamp(*ptr++);
|
||||
}
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer + sizeof(icmphdr), total_sz));
|
||||
inner_pdu(new RawPDU(buffer, total_sz));
|
||||
}
|
||||
|
||||
void ICMP::code(uint8_t new_code) {
|
||||
@@ -90,8 +98,23 @@ void ICMP::pointer(uint8_t new_pointer) {
|
||||
_icmp.un.pointer = new_pointer;
|
||||
}
|
||||
|
||||
void ICMP::original_timestamp(uint32_t new_timestamp) {
|
||||
_orig_timestamp = Endian::host_to_be(new_timestamp);
|
||||
}
|
||||
|
||||
void ICMP::receive_timestamp(uint32_t new_timestamp) {
|
||||
_recv_timestamp = Endian::host_to_be(new_timestamp);
|
||||
}
|
||||
|
||||
void ICMP::transmit_timestamp(uint32_t new_timestamp) {
|
||||
_trans_timestamp = Endian::host_to_be(new_timestamp);
|
||||
}
|
||||
|
||||
uint32_t ICMP::header_size() const {
|
||||
return sizeof(icmphdr);
|
||||
uint32_t extra = 0;
|
||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY)
|
||||
extra += sizeof(uint32_t) * 3;
|
||||
return sizeof(icmphdr) + extra;
|
||||
}
|
||||
|
||||
void ICMP::set_echo_request(uint16_t id, uint16_t seq) {
|
||||
@@ -154,10 +177,18 @@ void ICMP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *)
|
||||
assert(total_sz >= sizeof(icmphdr));
|
||||
#endif
|
||||
|
||||
if(type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
||||
uint32_t *ptr = reinterpret_cast<uint32_t*>(buffer + sizeof(icmphdr));
|
||||
*ptr++ = original_timestamp();
|
||||
*ptr++ = receive_timestamp();
|
||||
*ptr++ = transmit_timestamp();
|
||||
}
|
||||
|
||||
// checksum calc
|
||||
_icmp.check = 0;
|
||||
|
||||
uint32_t checksum = Utils::do_checksum(buffer + sizeof(icmphdr), buffer + total_sz) +
|
||||
Utils::do_checksum((uint8_t*)&_icmp, ((uint8_t*)&_icmp) + sizeof(icmphdr));
|
||||
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());
|
||||
while (checksum >> 16)
|
||||
checksum = (checksum & 0xffff) + (checksum >> 16);
|
||||
|
||||
@@ -169,7 +200,8 @@ bool ICMP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
if(total_sz < sizeof(icmphdr))
|
||||
return false;
|
||||
const icmphdr *icmp_ptr = (const icmphdr*)ptr;
|
||||
if(_icmp.type == ECHO_REQUEST && icmp_ptr->type == ECHO_REPLY) {
|
||||
if((_icmp.type == ECHO_REQUEST && icmp_ptr->type == ECHO_REPLY) ||
|
||||
(_icmp.type == TIMESTAMP_REQUEST && icmp_ptr->type == TIMESTAMP_REPLY)) {
|
||||
return icmp_ptr->un.echo.id == _icmp.un.echo.id && icmp_ptr->un.echo.sequence == _icmp.un.echo.sequence;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -11,6 +11,7 @@ using namespace Tins;
|
||||
class ICMPTest : public testing::Test {
|
||||
public:
|
||||
static const uint8_t expected_packets[][8];
|
||||
static const uint8_t ts_request[], ts_reply[];
|
||||
static const uint32_t expected_packet_count;
|
||||
|
||||
void test_equals(const ICMP &icmp1, const ICMP &icmp2);
|
||||
@@ -20,8 +21,17 @@ const uint8_t ICMPTest::expected_packets[][8] = {
|
||||
{ 8, 1, 173, 123, 86, 209, 243, 177 },
|
||||
{ 12, 0, 116, 255, 127, 0, 0, 0 }
|
||||
};
|
||||
|
||||
const uint32_t ICMPTest::expected_packet_count = 1;
|
||||
|
||||
const uint8_t ICMPTest::ts_request[] = {
|
||||
13, 0, 180, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 97, 106, 97, 106
|
||||
};
|
||||
|
||||
const uint8_t ICMPTest::ts_reply[] = {
|
||||
14, 0, 172, 45, 0, 0, 0, 0, 0, 0, 0, 0, 4, 144, 30, 89, 4, 144, 30, 89, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
TEST_F(ICMPTest, DefaultConstructor) {
|
||||
ICMP icmp;
|
||||
@@ -99,6 +109,24 @@ TEST_F(ICMPTest, Pointer) {
|
||||
EXPECT_EQ(icmp.pointer(), 0xf1);
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, OriginalTimestamp) {
|
||||
ICMP icmp;
|
||||
icmp.original_timestamp(0x1f8172da);
|
||||
EXPECT_EQ(0x1f8172da, icmp.original_timestamp());
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, ReceiveTimestamp) {
|
||||
ICMP icmp;
|
||||
icmp.receive_timestamp(0x1f8172da);
|
||||
EXPECT_EQ(0x1f8172da, icmp.receive_timestamp());
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, TransmitTimestamp) {
|
||||
ICMP icmp;
|
||||
icmp.transmit_timestamp(0x1f8172da);
|
||||
EXPECT_EQ(0x1f8172da, icmp.transmit_timestamp());
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, SetEchoRequest) {
|
||||
ICMP icmp;
|
||||
icmp.set_echo_request(0x7af1, 0x123f);
|
||||
@@ -196,6 +224,11 @@ TEST_F(ICMPTest, Serialize) {
|
||||
EXPECT_EQ(buffer, buffer2);
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, TimestampMatchesResponse) {
|
||||
ICMP request(ts_request, sizeof(ts_request));
|
||||
EXPECT_TRUE(request.matches_response(ts_reply, sizeof(ts_reply)));
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, ConstructorFromBuffer) {
|
||||
for(unsigned i(0); i < expected_packet_count; ++i) {
|
||||
ICMP icmp1(expected_packets[i], sizeof(expected_packets[i]));
|
||||
|
||||
Reference in New Issue
Block a user