mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Added DHCPv6 client/server id options' getters/setters.
This commit is contained in:
112
include/dhcpv6.h
112
include/dhcpv6.h
@@ -352,6 +352,88 @@ public:
|
||||
: enterprise_number(enterprise_number),
|
||||
vendor_class_data(vendor_class_data) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to represent DUIDs Based on Link-layer Address Plus
|
||||
* Time.
|
||||
*/
|
||||
struct duid_llt {
|
||||
static const uint16_t duid_id = 1;
|
||||
typedef std::vector<uint8_t> lladdress_type;
|
||||
|
||||
uint16_t hw_type;
|
||||
uint32_t time;
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_llt(uint16_t hw_type = 0, uint32_t time = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
: hw_type(hw_type), time(time), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to represent DUIDs Based on Enterprise Number
|
||||
*/
|
||||
struct duid_en {
|
||||
static const uint16_t duid_id = 2;
|
||||
typedef std::vector<uint8_t> identifier_type;
|
||||
|
||||
uint32_t enterprise_number;
|
||||
identifier_type identifier;
|
||||
|
||||
duid_en(uint32_t enterprise_number = 0,
|
||||
const identifier_type &identifier = identifier_type())
|
||||
: enterprise_number(enterprise_number), identifier(identifier) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to represent DUIDs Based on Link-layer Address.
|
||||
*/
|
||||
struct duid_ll {
|
||||
static const uint16_t duid_id = 3;
|
||||
typedef std::vector<uint8_t> lladdress_type;
|
||||
|
||||
uint16_t hw_type;
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_ll(uint16_t hw_type = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
: hw_type(hw_type), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
* Type type used to represent DUIDs. This will be stored as the
|
||||
* value for the Client/Server Identifier options.
|
||||
*/
|
||||
struct duid_type {
|
||||
typedef PDU::serialization_type data_type;
|
||||
|
||||
uint16_t id;
|
||||
data_type data;
|
||||
|
||||
duid_type(uint16_t id = 0, const data_type &data = data_type())
|
||||
: id(id), data(data) {}
|
||||
|
||||
duid_type(const duid_llt &identifier)
|
||||
: id(duid_llt::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_en &identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_ll &identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store the Option Request option.
|
||||
@@ -599,6 +681,22 @@ public:
|
||||
*/
|
||||
bool has_reconfigure_accept() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Client Identifier option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
duid_type client_id() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the Server Identifier option.
|
||||
*
|
||||
* This method will throw an option_not_found exception if the
|
||||
* option is not found.
|
||||
*/
|
||||
duid_type server_id() const;
|
||||
|
||||
// Option setters
|
||||
|
||||
/**
|
||||
@@ -718,6 +816,20 @@ public:
|
||||
*/
|
||||
void reconfigure_accept();
|
||||
|
||||
/**
|
||||
* \brief Setter for the Client Identifier option.
|
||||
*
|
||||
* \param value The new Client Identifier option data.
|
||||
*/
|
||||
void client_id(const duid_type &value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Server Identifier option.
|
||||
*
|
||||
* \param value The new Server Identifier option data.
|
||||
*/
|
||||
void server_id(const duid_type &value);
|
||||
|
||||
// Other stuff
|
||||
|
||||
/**
|
||||
|
||||
131
src/dhcpv6.cpp
131
src/dhcpv6.cpp
@@ -332,6 +332,32 @@ bool DHCPv6::has_reconfigure_accept() const {
|
||||
return search_option(RECONF_ACCEPT);
|
||||
}
|
||||
|
||||
DHCPv6::duid_type DHCPv6::client_id() const {
|
||||
const dhcpv6_option *opt = safe_search_option<std::less>(
|
||||
CLIENTID, sizeof(uint16_t) + 1
|
||||
);
|
||||
return duid_type(
|
||||
Endian::be_to_host(*(const uint16_t*)opt->data_ptr()),
|
||||
serialization_type(
|
||||
opt->data_ptr() + sizeof(uint16_t),
|
||||
opt->data_ptr() + opt->data_size()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
DHCPv6::duid_type DHCPv6::server_id() const {
|
||||
const dhcpv6_option *opt = safe_search_option<std::less>(
|
||||
SERVERID, sizeof(uint16_t) + 1
|
||||
);
|
||||
return duid_type(
|
||||
Endian::be_to_host(*(const uint16_t*)opt->data_ptr()),
|
||||
serialization_type(
|
||||
opt->data_ptr() + sizeof(uint16_t),
|
||||
opt->data_ptr() + opt->data_size()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// ********************************************************************
|
||||
// Option setters
|
||||
// ********************************************************************
|
||||
@@ -512,4 +538,109 @@ void DHCPv6::reconfigure_msg(uint8_t value) {
|
||||
void DHCPv6::reconfigure_accept() {
|
||||
add_option(RECONF_ACCEPT);
|
||||
}
|
||||
|
||||
|
||||
// DUIDs
|
||||
|
||||
DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t *buffer, uint32_t total_sz)
|
||||
{
|
||||
// at least one byte for lladdress
|
||||
if(total_sz < sizeof(uint16_t) + sizeof(uint32_t) + 1)
|
||||
throw std::runtime_error("Not enough size for a DUID_LLT identifier");
|
||||
duid_llt output;
|
||||
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
|
||||
buffer += sizeof(uint16_t);
|
||||
output.time = Endian::be_to_host(*(const uint32_t*)buffer);
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint16_t) + sizeof(uint32_t);
|
||||
output.lladdress.assign(buffer, buffer + total_sz);
|
||||
return output;
|
||||
}
|
||||
|
||||
PDU::serialization_type DHCPv6::duid_llt::serialize() const {
|
||||
serialization_type output(sizeof(uint16_t) + sizeof(uint32_t) + lladdress.size());
|
||||
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
|
||||
*(uint32_t*)&output[sizeof(uint16_t)] = Endian::host_to_be(time);
|
||||
std::copy(
|
||||
lladdress.begin(),
|
||||
lladdress.end(),
|
||||
output.begin() + sizeof(uint16_t) + sizeof(uint32_t)
|
||||
);
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t *buffer, uint32_t total_sz)
|
||||
{
|
||||
// at least one byte for identifier
|
||||
if(total_sz < sizeof(uint32_t) + 1)
|
||||
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
||||
duid_en output;
|
||||
output.enterprise_number = Endian::be_to_host(*(const uint32_t*)buffer);
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint32_t);
|
||||
output.identifier.assign(buffer, buffer + total_sz);
|
||||
return output;
|
||||
}
|
||||
|
||||
PDU::serialization_type DHCPv6::duid_en::serialize() const {
|
||||
serialization_type output(sizeof(uint32_t) + identifier.size());
|
||||
*(uint32_t*)&output[0] = Endian::host_to_be(enterprise_number);
|
||||
std::copy(
|
||||
identifier.begin(),
|
||||
identifier.end(),
|
||||
output.begin() + sizeof(uint32_t)
|
||||
);
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t *buffer, uint32_t total_sz)
|
||||
{
|
||||
// at least one byte for lladdress
|
||||
if(total_sz < sizeof(uint16_t) + 1)
|
||||
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
||||
duid_ll output;
|
||||
output.hw_type = Endian::be_to_host(*(const uint16_t*)buffer);
|
||||
buffer += sizeof(uint16_t);
|
||||
total_sz -= sizeof(uint16_t);
|
||||
output.lladdress.assign(buffer, buffer + total_sz);
|
||||
return output;
|
||||
}
|
||||
|
||||
PDU::serialization_type DHCPv6::duid_ll::serialize() const {
|
||||
serialization_type output(sizeof(uint16_t) + lladdress.size());
|
||||
*(uint16_t*)&output[0] = Endian::host_to_be(hw_type);
|
||||
std::copy(
|
||||
lladdress.begin(),
|
||||
lladdress.end(),
|
||||
output.begin() + sizeof(uint16_t)
|
||||
);
|
||||
return output;
|
||||
}
|
||||
|
||||
void DHCPv6::client_id(const duid_type &value) {
|
||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
|
||||
std::copy(
|
||||
value.data.begin(),
|
||||
value.data.end(),
|
||||
buffer.begin() + sizeof(uint16_t)
|
||||
);
|
||||
add_option(
|
||||
dhcpv6_option(CLIENTID, buffer.begin(), buffer.end())
|
||||
);
|
||||
}
|
||||
|
||||
void DHCPv6::server_id(const duid_type &value) {
|
||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||
*(uint16_t*)&buffer[0] = Endian::host_to_be(value.id);
|
||||
std::copy(
|
||||
value.data.begin(),
|
||||
value.data.end(),
|
||||
buffer.begin() + sizeof(uint16_t)
|
||||
);
|
||||
add_option(
|
||||
dhcpv6_option(SERVERID, buffer.begin(), buffer.end())
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
#include "llc.h"
|
||||
#include "rawpdu.h"
|
||||
|
||||
#if defined(BSD) && !defined(PF_LLC)
|
||||
// compilation fix, check if it works xD
|
||||
#if !defined(PF_LLC)
|
||||
// compilation fix, nasty but at least works on BSD
|
||||
#define PF_LLC 26
|
||||
#endif
|
||||
|
||||
|
||||
@@ -275,3 +275,65 @@ TEST_F(DHCPv6Test, ReconfigureAccept) {
|
||||
dhcp.reconfigure_accept();
|
||||
EXPECT_EQ(true, dhcp.has_reconfigure_accept());
|
||||
}
|
||||
|
||||
TEST_F(DHCPv6Test, Client_Server_ID_DUIDLL) {
|
||||
DHCPv6 dhcp;
|
||||
DHCPv6::duid_ll data, output;
|
||||
DHCPv6::duid_type tmp, tmp2;
|
||||
data.hw_type = 0x5f;
|
||||
data.lladdress.push_back(78);
|
||||
data.lladdress.push_back(66);
|
||||
data.lladdress.push_back(209);
|
||||
dhcp.client_id(data);
|
||||
tmp = dhcp.client_id();
|
||||
output = DHCPv6::duid_ll::from_bytes(&tmp.data[0], tmp.data.size());
|
||||
EXPECT_EQ(data.hw_type, output.hw_type);
|
||||
EXPECT_EQ(data.lladdress, output.lladdress);
|
||||
|
||||
dhcp.server_id(data);
|
||||
tmp2 = dhcp.server_id();
|
||||
EXPECT_EQ(tmp.id, tmp2.id);
|
||||
EXPECT_EQ(tmp.data, tmp2.data);
|
||||
}
|
||||
|
||||
TEST_F(DHCPv6Test, Client_Server_ID_DUIDLLT) {
|
||||
DHCPv6 dhcp;
|
||||
DHCPv6::duid_llt data, output;
|
||||
DHCPv6::duid_type tmp, tmp2;
|
||||
data.hw_type = 0x5f;
|
||||
data.time = 0x92837af;
|
||||
data.lladdress.push_back(78);
|
||||
data.lladdress.push_back(66);
|
||||
data.lladdress.push_back(209);
|
||||
dhcp.client_id(data);
|
||||
tmp = dhcp.client_id();
|
||||
output = DHCPv6::duid_llt::from_bytes(&tmp.data[0], tmp.data.size());
|
||||
EXPECT_EQ(data.hw_type, output.hw_type);
|
||||
EXPECT_EQ(data.time, output.time);
|
||||
EXPECT_EQ(data.lladdress, output.lladdress);
|
||||
|
||||
dhcp.server_id(data);
|
||||
tmp2 = dhcp.server_id();
|
||||
EXPECT_EQ(tmp.id, tmp2.id);
|
||||
EXPECT_EQ(tmp.data, tmp2.data);
|
||||
}
|
||||
|
||||
TEST_F(DHCPv6Test, Client_Server_ID_DUIDEN) {
|
||||
DHCPv6 dhcp;
|
||||
DHCPv6::duid_en data, output;
|
||||
DHCPv6::duid_type tmp, tmp2;
|
||||
data.enterprise_number = 0x5faa23da;
|
||||
data.identifier.push_back(78);
|
||||
data.identifier.push_back(66);
|
||||
data.identifier.push_back(209);
|
||||
dhcp.client_id(data);
|
||||
tmp = dhcp.client_id();
|
||||
output = DHCPv6::duid_en::from_bytes(&tmp.data[0], tmp.data.size());
|
||||
EXPECT_EQ(data.enterprise_number, output.enterprise_number);
|
||||
EXPECT_EQ(data.identifier, output.identifier);
|
||||
|
||||
dhcp.server_id(data);
|
||||
tmp2 = dhcp.server_id();
|
||||
EXPECT_EQ(tmp.id, tmp2.id);
|
||||
EXPECT_EQ(tmp.data, tmp2.data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user