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

Implemented every DHCPv6 option getter/setter, except for those involving DUIDs.

This commit is contained in:
Matias Fontanini
2013-01-22 23:24:10 -03:00
parent e712550cb8
commit 5b2e117347
3 changed files with 1137 additions and 17 deletions

View File

@@ -120,6 +120,109 @@ public:
container_type value_;
};
/**
* The message types.
*/
enum MessageType {
SOLICIT = 1,
ADVERTISE,
REQUEST,
CONFIRM,
RENEW,
REBIND,
REPLY,
RELEASE,
DECLINE,
RECONFIGURE,
INFO_REQUEST,
RELAY_FORWARD,
RELAY_REPLY,
LEASE_QUERY,
LEASE_QUERY_REPLY,
LEASE_QUERY_DONE,
LEASE_QUERY_DATA
};
/**
* The DHCPv6 options.
*/
enum Option {
CLIENTID = 1,
SERVERID,
IA_NA,
IA_TA,
IA_ADDR,
OPTION_REQUEST,
PREFERENCE,
ELAPSED_TIME,
RELAY_MSG,
AUTH = 11,
UNICAST,
STATUS_CODE,
RAPID_COMMIT,
USER_CLASS,
VENDOR_CLASS,
VENDOR_OPTS,
INTERFACE_ID,
RECONF_MSG,
RECONF_ACCEPT,
SIP_SERVER_D,
SIP_SERVER_A,
DNS_SERVERS,
DOMAIN_LIST,
IA_PD,
IAPREFIX,
NIS_SERVERS,
NISP_SERVERS,
NIS_DOMAIN_NAME,
NISP_DOMAIN_NAME,
SNTP_SERVERS,
INFORMATION_REFRESH_TIME,
BCMCS_SERVER_D,
BCMCS_SERVER_A,
GEOCONF_CIVIC = 36,
REMOTE_ID,
SUBSCRIBER_ID,
CLIENT_FQDN,
PANA_AGENT,
NEW_POSIX_TIMEZONE,
NEW_TZDB_TIMEZONE,
ERO,
LQ_QUERY,
CLIENT_DATA,
CLT_TIME,
LQ_RELAY_DATA,
LQ_CLIENT_LINK,
MIP6_HNIDF,
MIP6_VDINF,
V6_LOST,
CAPWAP_AC_V6,
RELAY_ID,
NTP_SERVER,
V6_ACCESS_DOMAIN,
SIP_UA_CS_LIST,
BOOTFILE_URL,
BOOTFILE_PARAM,
CLIENT_ARCH_TYPE,
NII,
GEOLOCATION,
AFTR_NAME,
ERP_LOCAL_DOMAIN_NAME,
RSOO,
PD_EXCLUDE,
VSS,
MIP6_IDINF,
MIP6_UDINF,
MIP6_HNP,
MIP6_HAA,
MIP6_HAF,
RDNSS_SELECTION,
KRB_PRINCIPAL_NAME,
KRB_REALM_NAME,
KRB_DEFAULT_REALM_NAME,
KRB_KDC
};
/**
* The type used to store the DHCPv6 options.
*/
@@ -135,6 +238,136 @@ public:
*/
static const PDU::PDUType pdu_flag = PDU::DHCPv6;
/**
* The type used to store the Identity Association for Non-Temporary
* Addresses option.
*/
struct ia_na_type {
typedef std::vector<uint8_t> options_type;
uint32_t id, t1, t2;
options_type options;
ia_na_type(uint32_t id = 0, uint32_t t1 = 0, uint32_t t2 = 0,
const options_type& options = options_type())
: id(id), t1(t1), t2(t2), options(options) {}
};
/**
* The type used to store the Identity Association for Temporary
* Addresses option.
*/
struct ia_ta_type {
typedef std::vector<uint8_t> options_type;
uint32_t id;
options_type options;
ia_ta_type(uint32_t id = 0,
const options_type& options = options_type())
: id(id), options(options) {}
};
/**
* The type used to store the Identity Association Address option.
*/
struct ia_address_type {
typedef std::vector<uint8_t> options_type;
ipaddress_type address;
uint32_t preferred_lifetime, valid_lifetime;
options_type options;
ia_address_type(ipaddress_type address = ipaddress_type(),
uint32_t preferred_lifetime = 0, uint32_t valid_lifetime = 0,
const options_type& options = options_type())
: address(address), preferred_lifetime(preferred_lifetime),
valid_lifetime(valid_lifetime), options(options) {}
};
/**
* The type used to store the Authentication option.
*/
struct authentication_type {
typedef std::vector<uint8_t> auth_info_type;
uint8_t protocol, algorithm, rdm;
uint64_t replay_detection;
auth_info_type auth_info;
authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0,
uint8_t rdm = 0, uint64_t replay_detection = 0,
const auth_info_type &auth_info = auth_info_type())
: protocol(protocol), algorithm(algorithm), rdm(rdm),
replay_detection(replay_detection), auth_info(auth_info) {}
};
/**
* The type used to store the Status Code option.
*/
struct status_code_type {
uint16_t code;
std::string message;
status_code_type(uint16_t code = 0, const std::string &message = "")
: code(code), message(message) { }
};
/**
* The type used to store the Vendor-specific Information option.
*/
struct vendor_info_type {
typedef std::vector<uint8_t> data_type;
uint32_t enterprise_number;
data_type data;
vendor_info_type(uint32_t enterprise_number = 0,
const data_type &data = data_type())
: enterprise_number(enterprise_number), data(data) { }
};
/**
* The type used to store the User Class option's user class data.
*/
typedef std::vector<uint8_t> class_option_data_type;
/**
* The type used to store the User Class option.
*/
typedef std::vector<class_option_data_type> user_class_type;
/**
* The type used to store the Vendor Class option.
*/
struct vendor_class_type {
typedef std::vector<class_option_data_type> class_data_type;
uint32_t enterprise_number;
class_data_type vendor_class_data;
vendor_class_type(uint32_t enterprise_number = 0,
const class_data_type &vendor_class_data = class_data_type())
: enterprise_number(enterprise_number),
vendor_class_data(vendor_class_data) { }
};
/**
* The type used to store the Option Request option.
*/
typedef std::vector<Option> option_request_type;
/**
* The type used to store the Relay Message option.
*/
typedef std::vector<uint8_t> relay_msg_type;
/**
* The type used to store the Interface-ID option.
*/
typedef std::vector<uint8_t> interface_id_type;
/**
* Default constructor.
*/
@@ -150,12 +383,15 @@ public:
DHCPv6(const uint8_t *buffer, uint32_t total_sz);
// Getters
/**
* \brief Getter for the message type field.
*
* \return The stored message type field.
*/
uint8_t msg_type() const { return header_data[0]; }
MessageType msg_type() const {
return static_cast<MessageType>(header_data[0]);
}
/**
* \brief Getter for the hop count field.
@@ -193,7 +429,7 @@ public:
*
* \param type The new message type.
*/
void msg_type(uint8_t type);
void msg_type(MessageType type);
/**
* \brief Setter for the hop count field.
@@ -223,6 +459,265 @@ public:
*/
void link_address(const ipaddress_type &addr);
// Option getters
/**
* \brief Getter for the Identity Association for Non-Temporary
* Addresses option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_na_type ia_na() const;
/**
* \brief Getter for the Identity Association for Temporary
* Addresses option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_ta_type ia_ta() const;
/**
* \brief Getter for the Identity Association Address option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ia_address_type ia_address() const;
/**
* \brief Getter for the Option Request option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
option_request_type option_request() const;
/**
* \brief Getter for the Preference option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t preference() const;
/**
* \brief Getter for the Elapsed Time option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint16_t elapsed_time() const;
/**
* \brief Getter for the Relay Message option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
relay_msg_type relay_message() const;
/**
* \brief Getter for the Authentication option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
authentication_type authentication() const;
/**
* \brief Getter for the Server Unicast option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
ipaddress_type server_unicast() const;
/**
* \brief Getter for the Server Unicast option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
status_code_type status_code() const;
/**
* \brief Getter for the Rapid Commit option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
bool has_rapid_commit() const;
/**
* \brief Getter for the User Class option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
user_class_type user_class() const;
/**
* \brief Getter for the Vendor Class option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_class_type vendor_class() const;
/**
* \brief Getter for the Vendor-specific Information option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
vendor_info_type vendor_info() const;
/**
* \brief Getter for the Interface ID option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
interface_id_type interface_id() const;
/**
* \brief Getter for the Reconfigure Message option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
uint8_t reconfigure_msg() const;
/**
* \brief Getter for the Reconfigure Accept option.
*
* This method will throw an option_not_found exception if the
* option is not found.
*/
bool has_reconfigure_accept() const;
// Option setters
/**
* \brief Setter for the Identity Association for Non-Temporary
* Addresses option.
*
* \param value The new IA_NA option data.
*/
void ia_na(const ia_na_type &value);
/**
* \brief Setter for the Identity Association for Temporary
* Addresses option.
*
* \param value The new IA_TA option data.
*/
void ia_ta(const ia_ta_type &value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new IA Address option data.
*/
void ia_address(const ia_address_type &value);
/**
* \brief Setter for the Identity Association Address option.
*
* \param value The new Option Request option data.
*/
void option_request(const option_request_type &value);
/**
* \brief Setter for the Preference option.
*
* \param value The new Preference option data.
*/
void preference(uint8_t value);
/**
* \brief Setter for the Elapsed Time option.
*
* \param value The new Elapsed Time option data.
*/
void elapsed_time(uint16_t value);
/**
* \brief Setter for the Relay Message option.
*
* \param value The new Relay Message option data.
*/
void relay_message(const relay_msg_type &value);
/**
* \brief Setter for the Authentication option.
*
* \param value The new Authentication option data.
*/
void authentication(const authentication_type &value);
/**
* \brief Setter for the Server Unicast option.
*
* \param value The new Server Unicast option data.
*/
void server_unicast(const ipaddress_type &value);
/**
* \brief Setter for the Status Code option.
*
* \param value The new Status Code option data.
*/
void status_code(const status_code_type &value);
/**
* \brief Adds a Rapid Commit option.
*/
void rapid_commit();
/**
* \brief Setter for the User Class option.
*
* \param value The new User Class option data.
*/
void user_class(const user_class_type &value);
/**
* \brief Setter for the Vendor Class option.
*
* \param value The new Vendor Class option data.
*/
void vendor_class(const vendor_class_type &value);
/**
* \brief Setter for the Vendor-specific Information option.
*
* \param value The new Vendor-specific Information option data.
*/
void vendor_info(const vendor_info_type &value);
/**
* \brief Setter for the Interface ID option.
*
* \param value The new Interface ID option data.
*/
void interface_id(const interface_id_type &value);
/**
* \brief Setter for the Reconfigure Message option.
*
* \param value The new Reconfigure Message option data.
*/
void reconfigure_msg(uint8_t value);
/**
* \brief Adds a Reconfigure Accept option.
*/
void reconfigure_accept();
// Other stuff
/**
@@ -249,8 +744,8 @@ public:
*
* \param id The option identifier to be searched.
*/
const dhcpv6_option *search_option(uint16_t id) const;
const dhcpv6_option *search_option(Option id) const;
// PDU stuff
/**
@@ -275,6 +770,54 @@ public:
private:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
uint8_t* write_option(const dhcpv6_option &option, uint8_t* buffer) const;
template<template <typename> class Functor>
const dhcpv6_option *safe_search_option(Option opt, uint32_t size) const {
const dhcpv6_option *option = search_option(opt);
if(!option || Functor<uint32_t>()(option->data_size(), size))
throw option_not_found();
return option;
}
template<typename InputIterator>
void class_option_data2option(InputIterator start, InputIterator end,
std::vector<uint8_t>& buffer, size_t start_index = 0)
{
size_t index = start_index;
while(start != end) {
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(start->size());
index += sizeof(uint16_t);
std::copy(start->begin(), start->end(), buffer.begin() + index);
index += start->size();
start++;
}
}
template<typename OutputType>
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz) const
{
typedef typename OutputType::value_type value_type;
OutputType output;
size_t index = 0;
while(index + 2 < total_sz) {
uint16_t size = Endian::be_to_host(
*(const uint16_t*)(ptr + index)
);
index += sizeof(uint16_t);
if(index + size > total_sz)
throw option_not_found();
output.push_back(
value_type(ptr + index, ptr + index + size)
);
index += size;
}
if(index != total_sz)
throw option_not_found();
return output;
}
uint8_t header_data[4];
uint32_t options_size;

View File

@@ -84,9 +84,9 @@ void DHCPv6::add_option(const dhcpv6_option &option) {
options_.push_back(option);
}
const DHCPv6::dhcpv6_option *DHCPv6::search_option(uint16_t id) const {
const DHCPv6::dhcpv6_option *DHCPv6::search_option(Option id) const {
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
if(it->option() == id)
if(it->option() == static_cast<uint16_t>(id))
return &*it;
}
return 0;
@@ -103,8 +103,8 @@ uint8_t* DHCPv6::write_option(const dhcpv6_option &option, uint8_t* buffer) cons
);
}
void DHCPv6::msg_type(uint8_t type) {
header_data[0] = type;
void DHCPv6::msg_type(MessageType type) {
header_data[0] = static_cast<uint8_t>(type);
}
void DHCPv6::hop_count(uint8_t count) {
@@ -144,4 +144,373 @@ void DHCPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it)
buffer = write_option(*it, buffer);
}
// ********************************************************************
// Option getters
// ********************************************************************
DHCPv6::ia_na_type DHCPv6::ia_na() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
IA_NA, sizeof(uint32_t) * 3
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t) * 3;
const uint32_t *ptr_32 = (const uint32_t*)opt->data_ptr();
DHCPv6::ia_na_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.t1 = Endian::be_to_host(*ptr_32++);
output.t2 = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::ia_ta_type DHCPv6::ia_ta() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
IA_TA, sizeof(uint32_t)
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t);
const uint32_t *ptr_32 = (const uint32_t*)opt->data_ptr();
DHCPv6::ia_ta_type output;
output.id = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::ia_address_type DHCPv6::ia_address() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
IA_ADDR, sizeof(uint32_t) * 2 + ipaddress_type::address_size
);
const uint8_t *ptr = opt->data_ptr() + sizeof(uint32_t) * 2 + ipaddress_type::address_size;
const uint32_t *ptr_32 = (const uint32_t*)(opt->data_ptr() + ipaddress_type::address_size);
DHCPv6::ia_address_type output;
output.address = opt->data_ptr();
output.preferred_lifetime = Endian::be_to_host(*ptr_32++);
output.valid_lifetime = Endian::be_to_host(*ptr_32++);
output.options.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::option_request_type DHCPv6::option_request() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
OPTION_REQUEST, 2
);
const uint16_t *ptr = (const uint16_t*)opt->data_ptr(),
*end = (const uint16_t*)(opt->data_ptr() + opt->data_size());
option_request_type output;
while(ptr < end) {
output.push_back(
static_cast<Option>(Endian::be_to_host(*ptr++))
);
}
return output;
}
uint8_t DHCPv6::preference() const {
const dhcpv6_option *opt = safe_search_option<std::not_equal_to>(
PREFERENCE, 1
);
return *opt->data_ptr();
}
uint16_t DHCPv6::elapsed_time() const {
const dhcpv6_option *opt = safe_search_option<std::not_equal_to>(
ELAPSED_TIME, 2
);
return Endian::be_to_host(
*(const uint16_t*)opt->data_ptr()
);
}
DHCPv6::relay_msg_type DHCPv6::relay_message() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
RELAY_MSG, 1
);
return relay_msg_type(
opt->data_ptr(),
opt->data_ptr() + opt->data_size()
);
}
DHCPv6::authentication_type DHCPv6::authentication() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
AUTH, sizeof(uint8_t) * 3 + sizeof(uint64_t)
);
const uint8_t *ptr = opt->data_ptr();
authentication_type output;
output.protocol = *ptr++;
output.algorithm = *ptr++;
output.rdm = *ptr++;
output.replay_detection = Endian::be_to_host(
*(const uint64_t*)ptr
);
ptr += sizeof(uint64_t);
output.auth_info.assign(ptr, opt->data_ptr() + opt->data_size());
return output;
}
DHCPv6::ipaddress_type DHCPv6::server_unicast() const {
const dhcpv6_option *opt = safe_search_option<std::not_equal_to>(
UNICAST, ipaddress_type::address_size
);
return ipaddress_type(opt->data_ptr());
}
DHCPv6::status_code_type DHCPv6::status_code() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
STATUS_CODE, sizeof(uint16_t)
);
status_code_type output;
output.code = Endian::be_to_host(*(const uint16_t*)opt->data_ptr());
output.message.assign(
opt->data_ptr() + sizeof(uint16_t),
opt->data_ptr() + opt->data_size()
);
return output;
}
bool DHCPv6::has_rapid_commit() const {
return search_option(RAPID_COMMIT);
}
DHCPv6::user_class_type DHCPv6::user_class() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
USER_CLASS, sizeof(uint16_t)
);
return option2class_option_data<user_class_type>(
opt->data_ptr(), opt->data_size()
);
}
DHCPv6::vendor_class_type DHCPv6::vendor_class() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
VENDOR_CLASS, sizeof(uint32_t)
);
typedef vendor_class_type::class_data_type data_type;
vendor_class_type output;
output.enterprise_number = Endian::be_to_host(
*(const uint32_t*)opt->data_ptr()
);
output.vendor_class_data = option2class_option_data<data_type>(
opt->data_ptr() + sizeof(uint32_t),
opt->data_size() - sizeof(uint32_t)
);
return output;
}
DHCPv6::vendor_info_type DHCPv6::vendor_info() const {
const dhcpv6_option *opt = safe_search_option<std::less>(
VENDOR_OPTS, sizeof(uint32_t)
);
vendor_info_type output;
output.enterprise_number = Endian::be_to_host(
*(const uint32_t*)opt->data_ptr()
);
output.data.assign(
opt->data_ptr() + sizeof(uint32_t),
opt->data_ptr() + opt->data_size()
);
return output;
}
DHCPv6::interface_id_type DHCPv6::interface_id() const {
const dhcpv6_option *opt = safe_search_option<std::equal_to>(
INTERFACE_ID, 0
);
return interface_id_type(
opt->data_ptr(),
opt->data_ptr() + opt->data_size()
);
}
uint8_t DHCPv6::reconfigure_msg() const {
return *safe_search_option<std::not_equal_to>(
RECONF_MSG, 1
)->data_ptr();
}
bool DHCPv6::has_reconfigure_accept() const {
return search_option(RECONF_ACCEPT);
}
// ********************************************************************
// Option setters
// ********************************************************************
void DHCPv6::ia_na(const ia_na_type &value) {
std::vector<uint8_t> buffer(sizeof(uint32_t) * 3 + value.options.size());
uint32_t *ptr = (uint32_t*)&buffer[0];
*ptr++ = Endian::host_to_be(value.id);
*ptr++ = Endian::host_to_be(value.t1);
*ptr++ = Endian::host_to_be(value.t2);
std::copy(
value.options.begin(),
value.options.end(),
buffer.begin() + sizeof(uint32_t) * 3
);
add_option(
dhcpv6_option(IA_NA, buffer.begin(), buffer.end())
);
}
void DHCPv6::ia_ta(const ia_ta_type &value) {
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.options.size());
uint32_t *ptr = (uint32_t*)&buffer[0];
*ptr++ = Endian::host_to_be(value.id);
std::copy(
value.options.begin(),
value.options.end(),
buffer.begin() + sizeof(uint32_t)
);
add_option(
dhcpv6_option(IA_TA, buffer.begin(), buffer.end())
);
}
void DHCPv6::ia_address(const ia_address_type &value) {
std::vector<uint8_t> buffer(
sizeof(uint32_t) * 2 + ipaddress_type::address_size + value.options.size()
);
uint32_t *ptr = (uint32_t*)&buffer[ipaddress_type::address_size];
value.address.copy(&buffer[0]);
*ptr++ = Endian::host_to_be(value.preferred_lifetime);
*ptr++ = Endian::host_to_be(value.valid_lifetime);
std::copy(
value.options.begin(),
value.options.end(),
buffer.begin() + sizeof(uint32_t) * 2 + ipaddress_type::address_size
);
add_option(
dhcpv6_option(IA_ADDR, buffer.begin(), buffer.end())
);
}
void DHCPv6::option_request(const option_request_type &value) {
typedef option_request_type::const_iterator iterator;
std::vector<uint8_t> buffer(value.size() * sizeof(uint16_t));
size_t index = 0;
for(iterator it = value.begin(); it != value.end(); ++it, index += 2)
*(uint16_t*)&buffer[index] = Endian::host_to_be<uint16_t>(*it);
add_option(
dhcpv6_option(OPTION_REQUEST, buffer.begin(), buffer.end())
);
}
void DHCPv6::preference(uint8_t value) {
add_option(
dhcpv6_option(PREFERENCE, 1, &value)
);
}
void DHCPv6::elapsed_time(uint16_t value) {
value = Endian::host_to_be(value);
add_option(
dhcpv6_option(ELAPSED_TIME, 2, (const uint8_t*)&value)
);
}
void DHCPv6::relay_message(const relay_msg_type &value) {
add_option(
dhcpv6_option(RELAY_MSG, value.begin(), value.end())
);
}
void DHCPv6::authentication(const authentication_type &value) {
std::vector<uint8_t> buffer(
sizeof(uint8_t) * 3 + sizeof(uint64_t) + value.auth_info.size()
);
buffer[0] = value.protocol;
buffer[1] = value.algorithm;
buffer[2] = value.rdm;
*(uint64_t*)&buffer[3] = Endian::host_to_be(value.replay_detection);
std::copy(
value.auth_info.begin(),
value.auth_info.end(),
buffer.begin() + sizeof(uint8_t) * 3 + sizeof(uint64_t)
);
add_option(
dhcpv6_option(AUTH, buffer.begin(), buffer.end())
);
}
void DHCPv6::server_unicast(const ipaddress_type &value) {
add_option(
dhcpv6_option(UNICAST, value.begin(), value.end())
);
}
void DHCPv6::status_code(const status_code_type &value) {
std::vector<uint8_t> buffer(sizeof(uint16_t) + value.message.size());
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.code);
std::copy(
value.message.begin(),
value.message.end(),
buffer.begin() + sizeof(uint16_t)
);
add_option(
dhcpv6_option(STATUS_CODE, buffer.begin(), buffer.end())
);
}
void DHCPv6::rapid_commit() {
add_option(
RAPID_COMMIT
);
}
void DHCPv6::user_class(const user_class_type &value) {
typedef user_class_type::const_iterator iterator;
std::vector<uint8_t> buffer;
class_option_data2option(value.begin(), value.end(), buffer);
add_option(
dhcpv6_option(USER_CLASS, buffer.begin(), buffer.end())
);
}
void DHCPv6::vendor_class(const vendor_class_type &value) {
std::vector<uint8_t> buffer(
sizeof(uint32_t)
);
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
class_option_data2option(
value.vendor_class_data.begin(),
value.vendor_class_data.end(),
buffer,
sizeof(uint32_t)
);
add_option(
dhcpv6_option(VENDOR_CLASS, buffer.begin(), buffer.end())
);
}
void DHCPv6::vendor_info(const vendor_info_type &value) {
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
*(uint32_t*)&buffer[0] = Endian::host_to_be(value.enterprise_number);
std::copy(
value.data.begin(),
value.data.end(),
buffer.begin() + sizeof(uint32_t)
);
add_option(
dhcpv6_option(VENDOR_OPTS, buffer.begin(), buffer.end())
);
}
void DHCPv6::interface_id(const interface_id_type &value) {
add_option(
dhcpv6_option(INTERFACE_ID, value.begin(), value.end())
);
}
void DHCPv6::reconfigure_msg(uint8_t value) {
add_option(
dhcpv6_option(RECONF_MSG, 1, &value)
);
}
void DHCPv6::reconfigure_accept() {
add_option(RECONF_ACCEPT);
}
} // namespace Tins

View File

@@ -24,20 +24,20 @@ const uint8_t DHCPv6Test::expected_packet[] = {
TEST_F(DHCPv6Test, DefaultConstructor) {
DHCPv6 dhcp;
EXPECT_EQ(0, dhcp.msg_type());
EXPECT_EQ(0, (int)dhcp.msg_type());
EXPECT_EQ(0, dhcp.hop_count());
EXPECT_EQ(0, dhcp.transaction_id());
}
TEST_F(DHCPv6Test, ConstructorFromBuffer) {
DHCPv6 dhcp(expected_packet, sizeof(expected_packet));
EXPECT_EQ(1, dhcp.msg_type());
EXPECT_EQ(DHCPv6::SOLICIT, dhcp.msg_type());
EXPECT_EQ(0xe828b9, dhcp.transaction_id());
EXPECT_TRUE(dhcp.search_option(1));
EXPECT_TRUE(dhcp.search_option(3));
EXPECT_TRUE(dhcp.search_option(6));
EXPECT_TRUE(dhcp.search_option(8));
EXPECT_FALSE(dhcp.search_option(2));
EXPECT_TRUE(dhcp.search_option(DHCPv6::CLIENTID));
EXPECT_TRUE(dhcp.search_option(DHCPv6::IA_NA));
EXPECT_TRUE(dhcp.search_option(DHCPv6::ELAPSED_TIME));
EXPECT_TRUE(dhcp.search_option(DHCPv6::OPTION_REQUEST));
EXPECT_FALSE(dhcp.search_option(DHCPv6::SERVERID));
}
TEST_F(DHCPv6Test, Serialize) {
@@ -52,8 +52,8 @@ TEST_F(DHCPv6Test, Serialize) {
TEST_F(DHCPv6Test, MessageType) {
DHCPv6 dhcp;
dhcp.msg_type(0x8a);
EXPECT_EQ(0x8a, dhcp.msg_type());
dhcp.msg_type(DHCPv6::SOLICIT);
EXPECT_EQ(DHCPv6::SOLICIT, dhcp.msg_type());
}
TEST_F(DHCPv6Test, HopCount) {
@@ -67,3 +67,211 @@ TEST_F(DHCPv6Test, TransactionId) {
dhcp.transaction_id(0x8af2ad);
EXPECT_EQ(0x8af2ad, dhcp.transaction_id());
}
// Options
TEST_F(DHCPv6Test, IA_NA) {
DHCPv6 dhcp;
DHCPv6::ia_na_type data, output;
data.id = 0x9283f78a;
data.t1 = 0xaf235212;
data.t2 = 0x9a8293fa;
data.options.push_back(0);
data.options.push_back(1);
data.options.push_back(2);
dhcp.ia_na(data);
output = dhcp.ia_na();
EXPECT_EQ(data.id, output.id);
EXPECT_EQ(data.t1, output.t1);
EXPECT_EQ(data.t2, output.t2);
EXPECT_EQ(data.options, output.options);
}
TEST_F(DHCPv6Test, IA_TA) {
DHCPv6 dhcp;
DHCPv6::ia_ta_type data, output;
data.id = 0x9283f78a;
data.options.push_back(0);
data.options.push_back(1);
data.options.push_back(2);
dhcp.ia_ta(data);
output = dhcp.ia_ta();
EXPECT_EQ(data.id, output.id);
EXPECT_EQ(data.options, output.options);
}
TEST_F(DHCPv6Test, IA_Address) {
DHCPv6 dhcp;
DHCPv6::ia_address_type data, output;
data.address = "fe00:feaa::1";
data.preferred_lifetime = 0x9283f78a;
data.valid_lifetime = 0x938fda32;
data.options.push_back(0);
data.options.push_back(1);
data.options.push_back(2);
dhcp.ia_address(data);
output = dhcp.ia_address();
EXPECT_EQ(data.address, output.address);
EXPECT_EQ(data.preferred_lifetime, output.preferred_lifetime);
EXPECT_EQ(data.valid_lifetime, output.valid_lifetime);
EXPECT_EQ(data.options, output.options);
}
TEST_F(DHCPv6Test, OptionRequest) {
DHCPv6 dhcp;
DHCPv6::option_request_type data, output;
data.push_back(DHCPv6::IA_ADDR);
data.push_back(DHCPv6::IA_NA);
dhcp.option_request(data);
output = dhcp.option_request();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, Preference) {
DHCPv6 dhcp;
dhcp.preference(0x8a);
EXPECT_EQ(0x8a, dhcp.preference());
}
TEST_F(DHCPv6Test, ElapsedTime) {
DHCPv6 dhcp;
dhcp.elapsed_time(0x8a2f);
EXPECT_EQ(0x8a2f, dhcp.elapsed_time());
}
TEST_F(DHCPv6Test, RelayMessage) {
DHCPv6 dhcp;
DHCPv6::relay_msg_type data, output;
data.push_back(1);
data.push_back(156);
data.push_back(12);
dhcp.relay_message(data);
output = dhcp.relay_message();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, Authentication) {
DHCPv6 dhcp;
DHCPv6::authentication_type data, output;
data.protocol = 0x92;
data.algorithm = 0x8f;
data.rdm = 0xa1;
data.replay_detection = 0x78ad6d5290398df7;
data.auth_info.push_back(0);
data.auth_info.push_back(1);
data.auth_info.push_back(2);
dhcp.authentication(data);
output = dhcp.authentication();
EXPECT_EQ(data.protocol, output.protocol);
EXPECT_EQ(data.algorithm, output.algorithm);
EXPECT_EQ(data.rdm, output.rdm);
EXPECT_EQ(data.replay_detection, output.replay_detection);
EXPECT_EQ(data.auth_info, output.auth_info);
}
TEST_F(DHCPv6Test, ServerUnicast) {
const IPv6Address addr("fe00:0a9d:dd23::1");
DHCPv6 dhcp;
dhcp.server_unicast(addr);
EXPECT_EQ(addr, dhcp.server_unicast());
}
TEST_F(DHCPv6Test, StatusCode) {
DHCPv6 dhcp;
DHCPv6::status_code_type data(0x72, "libtins, mah frend"), output;
dhcp.status_code(data);
output = dhcp.status_code();
EXPECT_EQ(data.code, output.code);
EXPECT_EQ(data.message, output.message);
}
TEST_F(DHCPv6Test, RapidCommit) {
DHCPv6 dhcp;
dhcp.rapid_commit();
EXPECT_EQ(true, dhcp.has_rapid_commit());
}
TEST_F(DHCPv6Test, UserClass) {
DHCPv6 dhcp;
DHCPv6::user_class_type data, output;
DHCPv6::class_option_data_type user_data;
user_data.push_back(22);
user_data.push_back(176);
data.push_back(user_data);
user_data.push_back(99);
user_data.push_back(231);
data.push_back(user_data);
dhcp.user_class(data);
output = dhcp.user_class();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, VendorClass) {
DHCPv6 dhcp;
DHCPv6::vendor_class_type data(15), output;
DHCPv6::class_option_data_type user_data;
user_data.push_back(22);
user_data.push_back(176);
data.vendor_class_data.push_back(user_data);
user_data.push_back(99);
user_data.push_back(231);
data.vendor_class_data.push_back(user_data);
dhcp.vendor_class(data);
output = dhcp.vendor_class();
EXPECT_EQ(data.enterprise_number, output.enterprise_number);
EXPECT_EQ(data.vendor_class_data, output.vendor_class_data);
}
TEST_F(DHCPv6Test, VendorInfo) {
DHCPv6 dhcp;
DHCPv6::vendor_info_type data(0x72988fad), output;
data.data.push_back(22);
data.data.push_back(176);
data.data.push_back(99);
data.data.push_back(231);
dhcp.vendor_info(data);
output = dhcp.vendor_info();
EXPECT_EQ(data.enterprise_number, output.enterprise_number);
EXPECT_EQ(data.data, output.data);
}
TEST_F(DHCPv6Test, InterfaceID) {
DHCPv6 dhcp;
DHCPv6::interface_id_type data, output;
data.push_back(1);
data.push_back(156);
data.push_back(12);
dhcp.interface_id(data);
output = dhcp.interface_id();
EXPECT_EQ(data, output);
}
TEST_F(DHCPv6Test, ReconfigureMsg) {
DHCPv6 dhcp;
dhcp.reconfigure_msg(0x8a);
EXPECT_EQ(0x8a, dhcp.reconfigure_msg());
}
TEST_F(DHCPv6Test, ReconfigureAccept) {
DHCPv6 dhcp;
dhcp.reconfigure_accept();
EXPECT_EQ(true, dhcp.has_reconfigure_accept());
}