1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Add ICMPExtension class

This commit is contained in:
Matias Fontanini
2015-12-13 19:46:58 -08:00
parent 45546eee39
commit 8aff1b4afe
5 changed files with 163 additions and 0 deletions

View 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

View File

@@ -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
View 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

View File

@@ -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)

View 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
);
}