mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
IP now uses PDUOption::to<>. Started porting ICMPv6 to do so as well.
This commit is contained in:
@@ -110,6 +110,11 @@ namespace Endian {
|
||||
template<size_t>
|
||||
struct conversion_dispatcher;
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint8_t)>
|
||||
: public conversion_dispatch_helper<uint8_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint16_t)>
|
||||
: public conversion_dispatch_helper<uint16_t>
|
||||
|
||||
@@ -145,30 +145,53 @@ public:
|
||||
/**
|
||||
* \brief The type used to store the new home agent information
|
||||
* option data.
|
||||
*
|
||||
* The first member contains the home agent preference field, while
|
||||
* the second one contains the home agent lifetime.
|
||||
*/
|
||||
typedef std::pair<uint16_t, uint16_t> new_ha_info_type;
|
||||
typedef std::vector<uint16_t> new_ha_info_type;
|
||||
|
||||
/**
|
||||
* The type used to store the source/target address list options.
|
||||
*/
|
||||
typedef std::vector<ipaddress_type> addr_list_type;
|
||||
struct addr_list_type {
|
||||
typedef std::vector<ipaddress_type> addresses_type;
|
||||
|
||||
uint8_t reserved[6];
|
||||
addresses_type addresses;
|
||||
|
||||
addr_list_type(const addresses_type &addresses = addresses_type())
|
||||
: addresses(addresses)
|
||||
{
|
||||
std::fill(reserved, reserved + sizeof(reserved), 0);
|
||||
}
|
||||
|
||||
static addr_list_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the nonce option data.
|
||||
*/
|
||||
typedef std::vector<uint8_t> nonce_type;
|
||||
|
||||
/**
|
||||
* The type used to store the MTU option.
|
||||
*/
|
||||
typedef std::pair<uint16_t, uint32_t> mtu_type;
|
||||
|
||||
/**
|
||||
* \brief The type used to store the neighbour advertisement
|
||||
* acknowledgement option data.
|
||||
*
|
||||
* The first member contains the option code field, while
|
||||
* the second one contains the status.
|
||||
*/
|
||||
typedef std::pair<uint8_t, uint8_t> naack_type;
|
||||
struct naack_type {
|
||||
uint8_t code, status;
|
||||
uint8_t reserved[4];
|
||||
|
||||
naack_type(uint8_t code = 0, uint8_t status = 0)
|
||||
: code(code), status(status)
|
||||
{
|
||||
std::fill(reserved, reserved + 4, 0);
|
||||
}
|
||||
|
||||
static naack_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief The type used to store the link layer address option data.
|
||||
@@ -207,6 +230,8 @@ public:
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static lladdr_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -226,6 +251,8 @@ public:
|
||||
: prefix_len(prefix_len), A(A), L(L),
|
||||
valid_lifetime(valid_lifetime), preferred_lifetime(preferred_lifetime),
|
||||
prefix(prefix) { }
|
||||
|
||||
static prefix_info_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -832,7 +859,7 @@ public:
|
||||
*
|
||||
* \param value The MTU option data.
|
||||
*/
|
||||
void mtu(uint32_t value);
|
||||
void mtu(const mtu_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the shortcut limit option.
|
||||
@@ -1009,7 +1036,7 @@ public:
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
uint32_t mtu() const;
|
||||
mtu_type mtu() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the shortcut limit option.
|
||||
|
||||
@@ -184,6 +184,8 @@ namespace Tins {
|
||||
: security(sec), compartments(comp),
|
||||
handling_restrictions(hand_res), transmission_control(tcc)
|
||||
{}
|
||||
|
||||
static security_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -198,6 +200,8 @@ namespace Tins {
|
||||
generic_route_option_type(uint8_t ptr = 0,
|
||||
routes_type rts = routes_type())
|
||||
: pointer(ptr), routes(rts) {}
|
||||
|
||||
static generic_route_option_type from_option(const option &opt);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "exceptions.h"
|
||||
#include "endianness.h"
|
||||
#include "internals.h"
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
@@ -107,35 +109,73 @@ namespace Internals {
|
||||
if(opt.data_size() % sizeof(T) != 0)
|
||||
throw malformed_option();
|
||||
const T *ptr = (const T*)opt.data_ptr();
|
||||
const T *end = ptr + (opt.data_size() / sizeof(T));
|
||||
const T *end = (const T*)(opt.data_ptr() + opt.data_size());
|
||||
|
||||
std::vector<T> output(std::distance(ptr, end));
|
||||
typename std::vector<T>::iterator it = output.begin();
|
||||
while(ptr < end) {
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
*it++ = Endian::be_to_host(*(ptr++));
|
||||
*it++ = Endian::be_to_host(*ptr++);
|
||||
else
|
||||
*it++ = Endian::le_to_host(*(ptr++));
|
||||
*it++ = Endian::le_to_host(*ptr++);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct converter<std::pair<T, T>, typename enable_if<is_unsigned_integral<T>::value>::type> {
|
||||
template<>
|
||||
struct converter<std::vector<IPv4Address> > {
|
||||
template<typename X, typename PDUType>
|
||||
static std::pair<T, T> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != sizeof(T) * 2)
|
||||
static std::vector<IPv4Address> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % 4 != 0)
|
||||
throw malformed_option();
|
||||
const T *ptr = (const T*)opt.data_ptr();
|
||||
std::pair<T, T> output;
|
||||
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
|
||||
const uint32_t *end = (const uint32_t*)(opt.data_ptr() + opt.data_size());
|
||||
|
||||
std::vector<IPv4Address> output(std::distance(ptr, end));
|
||||
std::vector<IPv4Address>::iterator it = output.begin();
|
||||
while(ptr < end) {
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
*it++ = IPv4Address(*ptr++);
|
||||
else
|
||||
*it++ = Endian::change_endian(*ptr++);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct converter<std::vector<IPv6Address> > {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<IPv6Address> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % IPv6Address::address_size != 0)
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size();
|
||||
std::vector<IPv6Address> output;
|
||||
while(ptr < end) {
|
||||
output.push_back(IPv6Address(ptr));
|
||||
ptr += IPv6Address::address_size;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct converter<std::pair<T, U>, typename enable_if<is_unsigned_integral<T>::value>::type> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::pair<T, U> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != sizeof(T) + sizeof(U))
|
||||
throw malformed_option();
|
||||
std::pair<T, U> output;
|
||||
output.first = *(const T*)opt.data_ptr();
|
||||
output.second = *(const U*)(opt.data_ptr() + sizeof(T));
|
||||
if(PDUType::endianness == PDUType::BE) {
|
||||
output.first = Endian::be_to_host(*ptr++);
|
||||
output.second = Endian::be_to_host(*ptr);
|
||||
output.first = Endian::be_to_host(output.first);
|
||||
output.second = Endian::be_to_host(output.second);
|
||||
}
|
||||
else {
|
||||
output.first = Endian::le_to_host(*ptr++);
|
||||
output.second = Endian::le_to_host(*ptr);
|
||||
output.first = Endian::le_to_host(output.first);
|
||||
output.second = Endian::le_to_host(output.second);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -495,9 +495,6 @@ namespace Tins {
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return opt->to<T>();
|
||||
/*if(option && option->data_size() == sizeof(T))
|
||||
return *(const T*)(&option->data_ptr()[0]);
|
||||
throw option_not_found();*/
|
||||
}
|
||||
|
||||
void internal_add_option(const option &option);
|
||||
|
||||
142
src/icmpv6.cpp
142
src/icmpv6.cpp
@@ -305,9 +305,10 @@ void ICMPv6::redirect_header(PDU::serialization_type data) {
|
||||
add_option(option(REDIRECT_HEADER, data.begin(), data.end()));
|
||||
}
|
||||
|
||||
void ICMPv6::mtu(uint32_t value) {
|
||||
void ICMPv6::mtu(const mtu_type& value) {
|
||||
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
|
||||
*((uint32_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value);
|
||||
*(uint32_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));
|
||||
}
|
||||
|
||||
@@ -324,9 +325,12 @@ void ICMPv6::new_advert_interval(uint32_t value) {
|
||||
}
|
||||
|
||||
void ICMPv6::new_home_agent_info(const new_ha_info_type &value) {
|
||||
if(value.size() != 3)
|
||||
throw malformed_option();
|
||||
uint8_t buffer[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
|
||||
*((uint16_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value.first);
|
||||
*((uint16_t*)(buffer + sizeof(uint16_t) * 2)) = Endian::host_to_be(value.second);
|
||||
*((uint16_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value[0]);
|
||||
*((uint16_t*)(buffer + sizeof(uint16_t))) = Endian::host_to_be(value[1]);
|
||||
*((uint16_t*)(buffer + sizeof(uint16_t) * 2)) = Endian::host_to_be(value[2]);
|
||||
add_option(option(HOME_AGENT_INFO, sizeof(buffer), buffer));
|
||||
}
|
||||
|
||||
@@ -339,10 +343,12 @@ void ICMPv6::target_addr_list(const addr_list_type &value) {
|
||||
}
|
||||
|
||||
void ICMPv6::add_addr_list(uint8_t type, const addr_list_type &value) {
|
||||
typedef addr_list_type::addresses_type::const_iterator iterator;
|
||||
|
||||
std::vector<uint8_t> buffer;
|
||||
buffer.reserve(value.size() + 6);
|
||||
buffer.insert(buffer.end(), 6, 0);
|
||||
for(addr_list_type::const_iterator it(value.begin()); it != value.end(); ++it)
|
||||
buffer.reserve(value.addresses.size() + 6);
|
||||
buffer.insert(buffer.end(), value.reserved, value.reserved + 6);
|
||||
for(iterator it = value.addresses.begin(); it != value.addresses.end(); ++it)
|
||||
buffer.insert(buffer.end(), it->begin(), it->end());
|
||||
add_option(option(type, buffer.begin(), buffer.end()));
|
||||
}
|
||||
@@ -394,8 +400,9 @@ void ICMPv6::link_layer_addr(lladdr_type value) {
|
||||
|
||||
void ICMPv6::naack(const naack_type &value) {
|
||||
uint8_t buffer[6];
|
||||
buffer[0] = value.first;
|
||||
buffer[1] = value.second;
|
||||
buffer[0] = value.code;
|
||||
buffer[1] = value.status;
|
||||
std::copy(value.reserved, value.reserved + 4, buffer + 2);
|
||||
add_option(option(NAACK, buffer, buffer + sizeof(buffer)));
|
||||
}
|
||||
|
||||
@@ -551,18 +558,9 @@ ICMPv6::hwaddress_type ICMPv6::target_link_layer_addr() const {
|
||||
|
||||
ICMPv6::prefix_info_type ICMPv6::prefix_info() const {
|
||||
const option *opt = search_option(PREFIX_INFO);
|
||||
if(!opt || opt->data_size() != 2 + sizeof(uint32_t) * 3 + ipaddress_type::address_size)
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
const uint8_t *ptr = opt->data_ptr();
|
||||
prefix_info_type output;
|
||||
output.prefix_len = *ptr++;
|
||||
output.L = (*ptr >> 7) & 0x1;
|
||||
output.A = (*ptr++ >> 6) & 0x1;
|
||||
output.valid_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
||||
ptr += sizeof(uint32_t);
|
||||
output.preferred_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
||||
output.prefix = ptr + sizeof(uint32_t) * 2;
|
||||
return output;
|
||||
return opt->to<prefix_info_type>();
|
||||
}
|
||||
|
||||
PDU::serialization_type ICMPv6::redirect_header() const {
|
||||
@@ -573,11 +571,11 @@ PDU::serialization_type ICMPv6::redirect_header() const {
|
||||
return serialization_type(ptr, ptr + opt->data_size() - 6);
|
||||
}
|
||||
|
||||
uint32_t ICMPv6::mtu() const {
|
||||
ICMPv6::mtu_type ICMPv6::mtu() const {
|
||||
const option *opt = search_option(MTU);
|
||||
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return Endian::be_to_host(*(const uint32_t*)(opt->data_ptr() + sizeof(uint16_t)));
|
||||
return opt->to<mtu_type>();
|
||||
}
|
||||
|
||||
uint8_t ICMPv6::shortcut_limit() const {
|
||||
@@ -596,12 +594,9 @@ uint32_t ICMPv6::new_advert_interval() const {
|
||||
|
||||
ICMPv6::new_ha_info_type ICMPv6::new_home_agent_info() const {
|
||||
const option *opt = search_option(HOME_AGENT_INFO);
|
||||
if(!opt || opt->data_size() != sizeof(uint16_t) + sizeof(uint32_t))
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return std::make_pair(
|
||||
Endian::be_to_host(*(const uint16_t*)(opt->data_ptr() + sizeof(uint16_t))),
|
||||
Endian::be_to_host(*(const uint16_t*)(opt->data_ptr() + sizeof(uint16_t) * 2))
|
||||
);
|
||||
return opt->to<new_ha_info_type>();
|
||||
}
|
||||
|
||||
ICMPv6::addr_list_type ICMPv6::source_addr_list() const {
|
||||
@@ -614,17 +609,9 @@ ICMPv6::addr_list_type ICMPv6::target_addr_list() const {
|
||||
|
||||
ICMPv6::addr_list_type ICMPv6::search_addr_list(OptionTypes type) const {
|
||||
const option *opt = search_option(type);
|
||||
if(!opt || opt->data_size() < 6 + ipaddress_type::address_size)
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
addr_list_type output;
|
||||
const uint8_t *ptr = opt->data_ptr() + 6, *end = opt->data_ptr() + opt->data_size();
|
||||
while(ptr < end) {
|
||||
if(ptr + ipaddress_type::address_size > end)
|
||||
throw option_not_found();
|
||||
output.push_back(ipaddress_type(ptr));
|
||||
ptr += ipaddress_type::address_size;
|
||||
}
|
||||
return output;
|
||||
return opt->to<addr_list_type>();
|
||||
}
|
||||
|
||||
ICMPv6::rsa_sign_type ICMPv6::rsa_signature() const {
|
||||
@@ -650,10 +637,10 @@ uint64_t ICMPv6::timestamp() const {
|
||||
}
|
||||
|
||||
ICMPv6::nonce_type ICMPv6::nonce() const {
|
||||
const option *opt = safe_search_option<std::equal_to>(
|
||||
NONCE, 0
|
||||
);
|
||||
return nonce_type(opt->data_ptr(), opt->data_ptr() + opt->data_size());
|
||||
const option *opt = search_option(NONCE);
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return opt->to<nonce_type>();
|
||||
}
|
||||
|
||||
ICMPv6::ip_prefix_type ICMPv6::ip_prefix() const {
|
||||
@@ -671,22 +658,17 @@ ICMPv6::ip_prefix_type ICMPv6::ip_prefix() const {
|
||||
}
|
||||
|
||||
ICMPv6::lladdr_type ICMPv6::link_layer_addr() const {
|
||||
// at least the option_code and 1 byte from the link layer address
|
||||
const option *opt = safe_search_option<std::less>(
|
||||
LINK_ADDRESS, 2
|
||||
);
|
||||
const uint8_t *ptr = opt->data_ptr();
|
||||
lladdr_type output(*ptr++);
|
||||
output.address.assign(ptr, opt->data_ptr() + opt->data_size());
|
||||
return output;
|
||||
const option *opt = search_option(LINK_ADDRESS);
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return opt->to<lladdr_type>();
|
||||
}
|
||||
|
||||
ICMPv6::naack_type ICMPv6::naack() const {
|
||||
const option *opt = safe_search_option<std::not_equal_to>(
|
||||
NAACK, 6
|
||||
);
|
||||
const uint8_t *ptr = opt->data_ptr();
|
||||
return naack_type(ptr[0], ptr[1]);
|
||||
const option *opt = search_option(NAACK);
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return opt->to<naack_type>();
|
||||
}
|
||||
|
||||
ICMPv6::map_type ICMPv6::map() const {
|
||||
@@ -815,5 +797,55 @@ ICMPv6::dns_search_list_type ICMPv6::dns_search_list() const {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Options stuff
|
||||
|
||||
ICMPv6::addr_list_type ICMPv6::addr_list_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < 6 + ipaddress_type::address_size || (opt.data_size() - 6) % ipaddress_type::address_size != 0)
|
||||
throw malformed_option();
|
||||
addr_list_type output;
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size();
|
||||
std::copy(ptr, ptr + 6, output.reserved);
|
||||
ptr += 6;
|
||||
while(ptr < end) {
|
||||
output.addresses.push_back(ICMPv6::ipaddress_type(ptr));
|
||||
ptr += ICMPv6::ipaddress_type::address_size;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
ICMPv6::naack_type ICMPv6::naack_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() != 6)
|
||||
throw malformed_option();
|
||||
return naack_type(*opt.data_ptr(), opt.data_ptr()[1]);
|
||||
}
|
||||
|
||||
ICMPv6::lladdr_type ICMPv6::lladdr_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < 2)
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr();
|
||||
lladdr_type output(*ptr++);
|
||||
output.address.assign(ptr, opt.data_ptr() + opt.data_size());
|
||||
return output;
|
||||
}
|
||||
|
||||
ICMPv6::prefix_info_type ICMPv6::prefix_info_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() != 2 + sizeof(uint32_t) * 3 + ICMPv6::ipaddress_type::address_size)
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr();
|
||||
prefix_info_type output;
|
||||
output.prefix_len = *ptr++;
|
||||
output.L = (*ptr >> 7) & 0x1;
|
||||
output.A = (*ptr++ >> 6) & 0x1;
|
||||
output.valid_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
||||
ptr += sizeof(uint32_t);
|
||||
output.preferred_lifetime = Endian::be_to_host(*(uint32_t*)ptr);
|
||||
output.prefix = ptr + sizeof(uint32_t) * 2;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
66
src/ip.cpp
66
src/ip.cpp
@@ -271,40 +271,24 @@ void IP::add_route_option(option_identifier id, const generic_route_option_type
|
||||
}
|
||||
|
||||
IP::generic_route_option_type IP::search_route_option(option_identifier id) const {
|
||||
const option *option = search_option(id);
|
||||
if(!option || option->data_size() < 1 + sizeof(uint32_t) ||
|
||||
((option->data_size() - 1) % sizeof(uint32_t)) != 0)
|
||||
const option *opt = search_option(id);
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
generic_route_option_type output;
|
||||
output.pointer = *option->data_ptr();
|
||||
const uint32_t *route = (const uint32_t*)(option->data_ptr() + 1),
|
||||
*end = route + (option->data_size() - 1) / sizeof(uint32_t);
|
||||
while(route < end)
|
||||
output.routes.push_back(address_type(*route++));
|
||||
return output;
|
||||
return opt->to<generic_route_option_type>();
|
||||
}
|
||||
|
||||
IP::security_type IP::security() const {
|
||||
const option *option = search_option(130);
|
||||
if(!option || option->data_size() < 9)
|
||||
const option *opt = search_option(130);
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
security_type output;
|
||||
const uint16_t *ptr = reinterpret_cast<const uint16_t*>(option->data_ptr());
|
||||
output.security = Endian::be_to_host(*ptr++);
|
||||
output.compartments = Endian::be_to_host(*ptr++);
|
||||
output.handling_restrictions = Endian::be_to_host(*ptr++);
|
||||
uint32_t tcc = option->data_ptr()[6];
|
||||
tcc = (tcc << 8) | option->data_ptr()[7];
|
||||
tcc = (tcc << 8) | option->data_ptr()[8];
|
||||
output.transmission_control = tcc;
|
||||
return output;
|
||||
return opt->to<security_type>();
|
||||
}
|
||||
|
||||
uint16_t IP::stream_identifier() const {
|
||||
const option *option = search_option(136);
|
||||
if(!option || option->data_size() != sizeof(uint16_t))
|
||||
const option *opt = search_option(136);
|
||||
if(!opt)
|
||||
throw option_not_found();
|
||||
return Endian::be_to_host(*(const uint16_t*)option->data_ptr());
|
||||
return opt->to<uint16_t>();
|
||||
}
|
||||
|
||||
void IP::add_option(const option &opt) {
|
||||
@@ -454,4 +438,36 @@ bool IP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Option static constructors from options
|
||||
|
||||
IP::security_type IP::security_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() != 9)
|
||||
throw malformed_option();
|
||||
security_type output;
|
||||
const uint16_t *ptr = reinterpret_cast<const uint16_t*>(opt.data_ptr());
|
||||
output.security = Endian::be_to_host(*ptr++);
|
||||
output.compartments = Endian::be_to_host(*ptr++);
|
||||
output.handling_restrictions = Endian::be_to_host(*ptr++);
|
||||
uint32_t tcc = opt.data_ptr()[6];
|
||||
tcc = (tcc << 8) | opt.data_ptr()[7];
|
||||
tcc = (tcc << 8) | opt.data_ptr()[8];
|
||||
output.transmission_control = tcc;
|
||||
return output;
|
||||
}
|
||||
|
||||
IP::generic_route_option_type IP::generic_route_option_type::from_option(
|
||||
const option &opt)
|
||||
{
|
||||
if(opt.data_size() < 1 + sizeof(uint32_t) || ((opt.data_size() - 1) % sizeof(uint32_t)) != 0)
|
||||
throw malformed_option();
|
||||
generic_route_option_type output;
|
||||
output.pointer = *opt.data_ptr();
|
||||
const uint32_t *route = (const uint32_t*)(opt.data_ptr() + 1),
|
||||
*end = route + (opt.data_size() - 1) / sizeof(uint32_t);
|
||||
while(route < end)
|
||||
output.routes.push_back(address_type(*route++));
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,8 +215,9 @@ TEST_F(ICMPv6Test, RedirectHeader) {
|
||||
|
||||
TEST_F(ICMPv6Test, MTU) {
|
||||
ICMPv6 icmp;
|
||||
icmp.mtu(0x9a8df7);
|
||||
EXPECT_EQ(icmp.mtu(), 0x9a8df7U);
|
||||
ICMPv6::mtu_type data(0, 0x9a8df7);
|
||||
icmp.mtu(data);
|
||||
EXPECT_EQ(data, icmp.mtu());
|
||||
}
|
||||
|
||||
TEST_F(ICMPv6Test, ShortcutLimit) {
|
||||
@@ -233,7 +234,10 @@ TEST_F(ICMPv6Test, NewAdvertisementInterval) {
|
||||
|
||||
TEST_F(ICMPv6Test, NewHomeAgentInformation) {
|
||||
ICMPv6 icmp;
|
||||
ICMPv6::new_ha_info_type data(0x92fa, 0xaab3);
|
||||
ICMPv6::new_ha_info_type data;
|
||||
data.push_back(0);
|
||||
data.push_back(0x92fa);
|
||||
data.push_back(0xaab3);
|
||||
icmp.new_home_agent_info(data);
|
||||
EXPECT_EQ(icmp.new_home_agent_info(), data);
|
||||
}
|
||||
@@ -241,19 +245,19 @@ TEST_F(ICMPv6Test, NewHomeAgentInformation) {
|
||||
TEST_F(ICMPv6Test, SourceAddressList) {
|
||||
ICMPv6 icmp;
|
||||
ICMPv6::addr_list_type data;
|
||||
data.push_back("827d:adae::1");
|
||||
data.push_back("2929:1234:fefe::2");
|
||||
data.addresses.push_back("827d:adae::1");
|
||||
data.addresses.push_back("2929:1234:fefe::2");
|
||||
icmp.source_addr_list(data);
|
||||
EXPECT_EQ(icmp.source_addr_list(), data);
|
||||
EXPECT_EQ(icmp.source_addr_list().addresses, data.addresses);
|
||||
}
|
||||
|
||||
TEST_F(ICMPv6Test, TargetAddressList) {
|
||||
ICMPv6 icmp;
|
||||
ICMPv6::addr_list_type data;
|
||||
data.push_back("827d:adae::1");
|
||||
data.push_back("2929:1234:fefe::2");
|
||||
data.addresses.push_back("827d:adae::1");
|
||||
data.addresses.push_back("2929:1234:fefe::2");
|
||||
icmp.target_addr_list(data);
|
||||
EXPECT_EQ(icmp.target_addr_list(), data);
|
||||
EXPECT_EQ(icmp.target_addr_list().addresses, data.addresses);
|
||||
}
|
||||
|
||||
TEST_F(ICMPv6Test, RSASignature) {
|
||||
@@ -316,9 +320,11 @@ TEST_F(ICMPv6Test, LinkLayerAddress) {
|
||||
|
||||
TEST_F(ICMPv6Test, NAACK) {
|
||||
ICMPv6 icmp;
|
||||
ICMPv6::naack_type data(0x92, 0xb3);
|
||||
ICMPv6::naack_type data(0x92, 0xb3), result;
|
||||
icmp.naack(data);
|
||||
EXPECT_EQ(icmp.naack(), data);
|
||||
result = icmp.naack();
|
||||
EXPECT_EQ(result.code, data.code);
|
||||
EXPECT_EQ(result.status, data.status);
|
||||
}
|
||||
|
||||
TEST_F(ICMPv6Test, MAP) {
|
||||
|
||||
Reference in New Issue
Block a user