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

Finished porting ICMPv6.

This commit is contained in:
Matias Fontanini
2013-12-17 19:00:00 -03:00
parent 069ae82b10
commit ca6b603478
3 changed files with 83 additions and 41 deletions

View File

@@ -481,7 +481,39 @@ public:
static timestamp_type from_option(const option &opt);
};
/**
* The type used to store the shortcut limit option.
*/
struct shortcut_limit_type {
uint8_t limit, reserved1;
uint32_t reserved2;
shortcut_limit_type(uint8_t limit = 0)
: limit(limit), reserved1(), reserved2()
{
}
static shortcut_limit_type from_option(const option &opt);
};
/**
* The type used to store new advertisement interval option.
*/
struct new_advert_interval_type {
uint16_t reserved;
uint32_t interval;
new_advert_interval_type(uint32_t interval = 0)
: reserved(), interval(interval)
{
}
static new_advert_interval_type from_option(const option &opt);
};
/**
* \brief Constructs an ICMPv6 object.
*
@@ -883,12 +915,9 @@ public:
/**
* \brief Setter for the redirect header option.
*
* This method appends the 6 reserved bytes and inserts the
* necessary padding at the end.
*
* \param data The redirect header option data.
*/
void redirect_header(PDU::serialization_type data);
void redirect_header(const byte_array &data);
/**
* \brief Setter for the MTU option.
@@ -902,14 +931,14 @@ public:
*
* \param value The shortcut limit option data.
*/
void shortcut_limit(uint8_t value);
void shortcut_limit(const shortcut_limit_type& value);
/**
* \brief Setter for the new advertisement interval option.
*
* \param value The new advertisement interval option data.
*/
void new_advert_interval(uint32_t value);
void new_advert_interval(const new_advert_interval_type &value);
/**
* \brief Setter for the new home agent information option.
@@ -1064,7 +1093,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
PDU::serialization_type redirect_header() const;
byte_array redirect_header() const;
/**
* \brief Getter for the MTU option.
@@ -1080,7 +1109,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t shortcut_limit() const;
shortcut_limit_type shortcut_limit() const;
/**
* \brief Getter for the new advertisement interval option.
@@ -1088,7 +1117,7 @@ public:
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint32_t new_advert_interval() const;
new_advert_interval_type new_advert_interval() const;
/**
* \brief Getter for the new home agent information option.

View File

@@ -294,33 +294,29 @@ void ICMPv6::prefix_info(prefix_info_type info) {
);
}
void ICMPv6::redirect_header(PDU::serialization_type data) {
// Reserved fields
data.insert(data.begin(), 6, 0);
// Padding(if necessary)
uint8_t padding = 8 - (data.size() + sizeof(uint8_t) * 2) % 8;
if(padding == 8)
padding = 0;
data.insert(data.end(), padding, 0);
void ICMPv6::redirect_header(const byte_array& data) {
add_option(option(REDIRECT_HEADER, data.begin(), data.end()));
}
void ICMPv6::mtu(const mtu_type& value) {
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
*(uint32_t*)buffer = Endian::host_to_be(value.first);
*(uint16_t*)buffer = Endian::host_to_be(value.first);
*(uint32_t*)(buffer + sizeof(uint16_t)) = Endian::host_to_be(value.second);
add_option(option(MTU, sizeof(buffer), buffer));
}
void ICMPv6::shortcut_limit(uint8_t value) {
void ICMPv6::shortcut_limit(const shortcut_limit_type &value) {
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
buffer[0] = value;
buffer[0] = value.limit;
buffer[1] = value.reserved1;
*(uint32_t*)&buffer[2] = Endian::host_to_be(value.reserved2);
add_option(option(NBMA_SHORT_LIMIT, sizeof(buffer), buffer));
}
void ICMPv6::new_advert_interval(uint32_t value) {
void ICMPv6::new_advert_interval(const new_advert_interval_type &value) {
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
*((uint32_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value);
*(uint16_t*)buffer = Endian::host_to_be(value.reserved);
*((uint32_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value.interval);
add_option(option(ADVERT_INTERVAL, sizeof(buffer), buffer));
}
@@ -554,30 +550,20 @@ ICMPv6::prefix_info_type ICMPv6::prefix_info() const {
return search_and_convert<prefix_info_type>(PREFIX_INFO);
}
PDU::serialization_type ICMPv6::redirect_header() const {
const option *opt = search_option(REDIRECT_HEADER);
if(!opt || opt->data_size() < 6)
throw option_not_found();
const uint8_t *ptr = opt->data_ptr() + 6;
return serialization_type(ptr, ptr + opt->data_size() - 6);
byte_array ICMPv6::redirect_header() const {
return search_and_convert<PDU::serialization_type>(REDIRECT_HEADER);
}
ICMPv6::mtu_type ICMPv6::mtu() const {
return search_and_convert<mtu_type>(MTU);
}
uint8_t ICMPv6::shortcut_limit() const {
const option *opt = search_option(NBMA_SHORT_LIMIT);
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
throw option_not_found();
return *opt->data_ptr();
ICMPv6::shortcut_limit_type ICMPv6::shortcut_limit() const {
return search_and_convert<shortcut_limit_type>(NBMA_SHORT_LIMIT);
}
uint32_t ICMPv6::new_advert_interval() const {
const option *opt = search_option(ADVERT_INTERVAL);
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
throw option_not_found();
return Endian::be_to_host(*(const uint32_t*)(opt->data_ptr() + sizeof(uint16_t)));
ICMPv6::new_advert_interval_type ICMPv6::new_advert_interval() const {
return search_and_convert<new_advert_interval_type>(ADVERT_INTERVAL);
}
ICMPv6::new_ha_info_type ICMPv6::new_home_agent_info() const {
@@ -867,5 +853,26 @@ ICMPv6::timestamp_type ICMPv6::timestamp_type::from_option(const option &opt)
std::copy(opt.data_ptr(), opt.data_ptr() + 6, output.reserved);
return output;
}
ICMPv6::shortcut_limit_type ICMPv6::shortcut_limit_type::from_option(const option &opt)
{
if(opt.data_size() != 6)
throw malformed_option();
const uint8_t *ptr = opt.data_ptr();
shortcut_limit_type output(*ptr++);
output.reserved1 = *ptr++;
output.reserved2 = Endian::be_to_host(*(uint32_t*)ptr);
return output;
}
ICMPv6::new_advert_interval_type ICMPv6::new_advert_interval_type::from_option(const option &opt)
{
if(opt.data_size() != 6)
throw malformed_option();
new_advert_interval_type output;
output.reserved = Endian::be_to_host(*(uint16_t*)opt.data_ptr());
output.interval = Endian::be_to_host(*(uint32_t*)(opt.data_ptr() + sizeof(uint16_t)));
return output;
}
}

View File

@@ -209,6 +209,7 @@ TEST_F(ICMPv6Test, RedirectHeader) {
ICMPv6 icmp;
IP ip = IP("127.0.0.1") / TCP(22);
PDU::serialization_type buffer = ip.serialize();
buffer.insert(buffer.begin(), 6, 0);
icmp.redirect_header(buffer);
EXPECT_EQ(buffer, icmp.redirect_header());
}
@@ -223,13 +224,18 @@ TEST_F(ICMPv6Test, MTU) {
TEST_F(ICMPv6Test, ShortcutLimit) {
ICMPv6 icmp;
icmp.shortcut_limit(123);
EXPECT_EQ(icmp.shortcut_limit(), 123);
ICMPv6::shortcut_limit_type sl = icmp.shortcut_limit();
EXPECT_EQ(123, sl.limit);
EXPECT_EQ(0, sl.reserved1);
EXPECT_EQ(0, sl.reserved2);
}
TEST_F(ICMPv6Test, NewAdvertisementInterval) {
ICMPv6 icmp;
icmp.new_advert_interval(0x9a8df7);
EXPECT_EQ(icmp.new_advert_interval(), 0x9a8df7U);
ICMPv6::new_advert_interval_type data = icmp.new_advert_interval();
EXPECT_EQ(0x9a8df7U, data.interval);
EXPECT_EQ(0, data.reserved);
}
TEST_F(ICMPv6Test, NewHomeAgentInformation) {