mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Add ICMPExtension class
This commit is contained in:
78
include/tins/icmp_extension.h
Normal file
78
include/tins/icmp_extension.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef TINS_ICMP_EXTENSION_H
|
||||
#define TINS_ICMP_EXTENSION_H
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Class that represents an ICMP extension object
|
||||
*/
|
||||
class ICMPExtension {
|
||||
public:
|
||||
typedef std::vector<uint8_t> payload_type;
|
||||
typedef std::vector<uint8_t> serialization_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP extension from a buffer
|
||||
*
|
||||
* \param buffer The input buffer
|
||||
* \param total_sz The input buffer size
|
||||
*/
|
||||
ICMPExtension(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension class field
|
||||
*
|
||||
* \return The extension class field value
|
||||
*/
|
||||
uint8_t extension_class() const { return extension_class_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension sub-type field
|
||||
*
|
||||
* \return The extension sub-type field value
|
||||
*/
|
||||
uint8_t extension_type() const { return extension_type_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension payload field
|
||||
*
|
||||
* \return The extension payload field value
|
||||
*/
|
||||
const payload_type& payload() const { return payload_; }
|
||||
|
||||
/**
|
||||
* \brief Gets the size of this ICMP extension
|
||||
*
|
||||
* This returns the basic header size + the payload size
|
||||
*
|
||||
* \return The size of this extension
|
||||
*/
|
||||
uint32_t extension_size() const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension into a buffer
|
||||
*
|
||||
* \param buffer The output buffer in which to store the serialization
|
||||
* \param buffer_size The size of the output buffer
|
||||
*/
|
||||
void serialize(uint8_t* buffer, uint32_t buffer_size) const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this ICMP extension object
|
||||
*
|
||||
* \return The serialized ICMP extension
|
||||
*/
|
||||
serialization_type serialize() const;
|
||||
private:
|
||||
static const uint32_t BASE_HEADER_SIZE;
|
||||
|
||||
payload_type payload_;
|
||||
uint8_t extension_class_, extension_type_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ICMP_EXTENSION_H
|
||||
@@ -25,6 +25,7 @@ ADD_LIBRARY(
|
||||
dot1q.cpp
|
||||
eapol.cpp
|
||||
ethernetII.cpp
|
||||
icmp_extension.cpp
|
||||
icmp.cpp
|
||||
icmpv6.cpp
|
||||
internals.cpp
|
||||
|
||||
54
src/icmp_extension.cpp
Normal file
54
src/icmp_extension.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <algorithm>
|
||||
#include "icmp_extension.h"
|
||||
#include "endianness.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
using std::runtime_error;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
const uint32_t ICMPExtension::BASE_HEADER_SIZE = sizeof(uint16_t) + sizeof(uint8_t) * 2;
|
||||
|
||||
ICMPExtension::ICMPExtension(const uint8_t* buffer, uint32_t total_sz) {
|
||||
// Check for the base header (u16 length + u8 clss + u8 type)
|
||||
if (total_sz < BASE_HEADER_SIZE) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
|
||||
uint16_t length = Endian::be_to_host(*(const uint16_t*)buffer);
|
||||
buffer += sizeof(uint16_t);
|
||||
extension_class_ = *buffer++;
|
||||
extension_type_ = *buffer++;
|
||||
total_sz -= BASE_HEADER_SIZE;
|
||||
// Length is BASE_HEADER_SIZE + payload size, make sure it's valid
|
||||
if (length < BASE_HEADER_SIZE || length - BASE_HEADER_SIZE > total_sz) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
length -= BASE_HEADER_SIZE;
|
||||
payload_.assign(buffer, buffer + length);
|
||||
}
|
||||
|
||||
uint32_t ICMPExtension::extension_size() const {
|
||||
return BASE_HEADER_SIZE + payload_.size();
|
||||
}
|
||||
|
||||
void ICMPExtension::serialize(uint8_t* buffer, uint32_t buffer_size) const {
|
||||
if (buffer_size < extension_size()) {
|
||||
throw runtime_error("Serialization buffer is too small");
|
||||
}
|
||||
*(uint16_t*)buffer = Endian::host_to_be<uint16_t>(extension_size());
|
||||
buffer += sizeof(uint16_t);
|
||||
*buffer = extension_class_;
|
||||
buffer += sizeof(uint8_t);
|
||||
*buffer = extension_type_;
|
||||
buffer += sizeof(uint8_t);
|
||||
copy(payload_.begin(), payload_.end(), buffer);
|
||||
}
|
||||
|
||||
ICMPExtension::serialization_type ICMPExtension::serialize() const {
|
||||
serialization_type output(extension_size());
|
||||
serialize(&output[0], output.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
} // Tins
|
||||
@@ -58,6 +58,7 @@ ADD_CUSTOM_TARGET(
|
||||
Dot1QTest
|
||||
EthernetTest
|
||||
HWAddressTest
|
||||
ICMPExtensionTest
|
||||
ICMPTest
|
||||
ICMPv6Test
|
||||
IPTest
|
||||
@@ -100,6 +101,7 @@ ADD_EXECUTABLE(DNSTest EXCLUDE_FROM_ALL dns.cpp)
|
||||
ADD_EXECUTABLE(Dot1QTest EXCLUDE_FROM_ALL dot1q.cpp)
|
||||
ADD_EXECUTABLE(EthernetTest EXCLUDE_FROM_ALL ethernetII.cpp)
|
||||
ADD_EXECUTABLE(HWAddressTest EXCLUDE_FROM_ALL hwaddress.cpp)
|
||||
ADD_EXECUTABLE(ICMPExtensionTest EXCLUDE_FROM_ALL icmp_extension.cpp)
|
||||
ADD_EXECUTABLE(ICMPTest EXCLUDE_FROM_ALL icmp.cpp)
|
||||
ADD_EXECUTABLE(ICMPv6Test EXCLUDE_FROM_ALL icmpv6.cpp)
|
||||
ADD_EXECUTABLE(IPTest EXCLUDE_FROM_ALL ip.cpp)
|
||||
@@ -179,6 +181,7 @@ ADD_TEST(Dot11RTS Dot11RTSTest)
|
||||
ADD_TEST(Dot1Q Dot1QTest)
|
||||
ADD_TEST(Ethernet EthernetTest)
|
||||
ADD_TEST(HWAddress HWAddressTest)
|
||||
ADD_TEST(ICMPExtension ICMPExtensionTest)
|
||||
ADD_TEST(ICMP ICMPTest)
|
||||
ADD_TEST(ICMPv6 ICMPv6Test)
|
||||
ADD_TEST(IP IPTest)
|
||||
|
||||
27
tests/src/icmp_extension.cpp
Normal file
27
tests/src/icmp_extension.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "icmp_extension.h"
|
||||
|
||||
using Tins::ICMPExtension;
|
||||
|
||||
class ICMPExtensionTest : public testing::Test {
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
TEST_F(ICMPExtensionTest, ConstructorFromBuffer) {
|
||||
const uint8_t input[] = { 0, 8, 1, 1, 24, 150, 1, 1 };
|
||||
const uint8_t payload[] = { 24, 150, 1, 1 };
|
||||
ICMPExtension ext(input, sizeof(input));
|
||||
EXPECT_EQ(1, ext.extension_class());
|
||||
EXPECT_EQ(1, ext.extension_type());
|
||||
EXPECT_EQ(
|
||||
ICMPExtension::payload_type(payload, payload + sizeof(payload)),
|
||||
ext.payload()
|
||||
);
|
||||
|
||||
ICMPExtension::serialization_type buffer = ext.serialize();
|
||||
EXPECT_EQ(
|
||||
ICMPExtension::serialization_type(input, input + sizeof(input)),
|
||||
buffer
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user