1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-30 05:24:26 +01:00

IP now uses PDUOption::to<>. Started porting ICMPv6 to do so as well.

This commit is contained in:
Matias Fontanini
2013-12-16 15:50:17 -03:00
parent 112a357726
commit ea6638c163
8 changed files with 245 additions and 118 deletions

View File

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

View File

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

View File

@@ -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);
};
/**

View File

@@ -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;
}

View File

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