15 #include <boost/foreach.hpp> 28 const size_t DUID_TYPE_LEN = 2;
31 const size_t MIN_MAC_LEN = 6;
34 const size_t ENTERPRISE_ID_LEN = 4;
37 const size_t DUID_EN_IDENTIFIER_LEN = 6;
44 DUIDFactory::DUIDFactory(
const std::string& storage_location)
45 : storage_location_(
trim(storage_location)), duid_() {
50 return (!storage_location_.empty());
55 const std::vector<uint8_t>& ll_identifier) {
62 uint16_t htype_current = 0;
63 uint32_t time_current = 0;
64 std::vector<uint8_t> identifier_current;
68 std::vector<uint8_t> duid_vec = duid_->getDuid();
69 if ((duid_->getType() ==
DUID::DUID_LLT) && (duid_vec.size() > 8)) {
70 htype_current =
readUint16(&duid_vec[2], duid_vec.size() - 2);
71 time_current =
readUint32(&duid_vec[4], duid_vec.size() - 4);
72 identifier_current.assign(duid_vec.begin() + 8, duid_vec.end());
76 uint32_t time_out = time_in;
80 time_out = (time_current != 0 ? time_current :
84 std::vector<uint8_t> ll_identifier_out = ll_identifier;
85 uint16_t htype_out = htype;
90 if (ll_identifier_out.empty()) {
92 if (identifier_current.empty()) {
93 createLinkLayerId(ll_identifier_out, htype_out);
96 ll_identifier_out = identifier_current;
97 htype_out = htype_current;
100 }
else if (htype_out == 0) {
103 htype_out = ((htype_current != 0) ? htype_current :
109 std::vector<uint8_t> duid_out(DUID_TYPE_LEN +
sizeof(time_out) +
114 duid_out.insert(duid_out.end(), ll_identifier_out.begin(),
115 ll_identifier_out.end());
123 const std::vector<uint8_t>& identifier) {
130 uint32_t enterprise_id_current = 0;
131 std::vector<uint8_t> identifier_current;
135 std::vector<uint8_t> duid_vec = duid_->getDuid();
136 if ((duid_->getType() ==
DUID::DUID_EN) && (duid_vec.size() > 6)) {
137 enterprise_id_current =
readUint32(&duid_vec[2], duid_vec.size() - 2);
138 identifier_current.assign(duid_vec.begin() + 6, duid_vec.end());
144 uint32_t enterprise_id_out = enterprise_id;
145 if (enterprise_id_out == 0) {
146 if (enterprise_id_current != 0) {
147 enterprise_id_out = enterprise_id_current;
149 enterprise_id_out = ENTERPRISE_ID_ISC;
154 std::vector<uint8_t> duid_out(DUID_TYPE_LEN + ENTERPRISE_ID_LEN);
156 writeUint32(enterprise_id_out, &duid_out[2], ENTERPRISE_ID_LEN);
160 if (identifier.empty()) {
162 if (identifier_current.empty()) {
165 duid_out.resize(DUID_TYPE_LEN + ENTERPRISE_ID_LEN +
166 DUID_EN_IDENTIFIER_LEN);
169 ::srandom(time(NULL));
170 fillRandom(&duid_out[DUID_TYPE_LEN + ENTERPRISE_ID_LEN],
171 &duid_out[DUID_TYPE_LEN + ENTERPRISE_ID_LEN +
172 DUID_EN_IDENTIFIER_LEN]);
175 duid_out.insert(duid_out.end(), identifier_current.begin(),
176 identifier_current.end());
181 duid_out.insert(duid_out.end(), identifier.begin(), identifier.end());
190 const std::vector<uint8_t>& ll_identifier) {
197 uint16_t htype_current = 0;
198 std::vector<uint8_t> identifier_current;
202 std::vector<uint8_t> duid_vec = duid_->getDuid();
203 if ((duid_->getType() ==
DUID::DUID_LL) && (duid_vec.size() > 4)) {
204 htype_current =
readUint16(&duid_vec[2], duid_vec.size() - 2);
205 identifier_current.assign(duid_vec.begin() + 4, duid_vec.end());
209 std::vector<uint8_t> ll_identifier_out = ll_identifier;
210 uint16_t htype_out = htype;
215 if (ll_identifier_out.empty()) {
217 if (identifier_current.empty()) {
218 createLinkLayerId(ll_identifier_out, htype_out);
221 ll_identifier_out = identifier_current;
222 htype_out = htype_current;
225 }
else if (htype_out == 0) {
228 htype_out = ((htype_current != 0) ? htype_current :
234 std::vector<uint8_t> duid_out(DUID_TYPE_LEN +
sizeof(htype_out));
237 duid_out.insert(duid_out.end(), ll_identifier_out.begin(),
238 ll_identifier_out.end());
245 DUIDFactory::createLinkLayerId(std::vector<uint8_t>& identifier,
246 uint16_t& htype)
const {
250 BOOST_FOREACH(
IfacePtr iface, ifaces) {
266 if (iface->getMacLen() < MIN_MAC_LEN) {
271 if (iface->flag_loopback_) {
276 if (!iface->flag_up_) {
283 if (
isRangeZero(iface->getMac(), iface->getMac() + iface->getMacLen())) {
288 identifier.assign(iface->getMac(), iface->getMac() + iface->getMacLen());
289 htype = iface->getHWType();
292 if ((htype == static_cast<uint16_t>(
HTYPE_ETHER)) &&
293 (iface->getMacLen() == 6)) {
300 if (identifier.empty()) {
301 isc_throw(Unexpected,
"unable to find suitable interface for " 302 " generating a DUID-LLT");
307 DUIDFactory::set(
const std::vector<uint8_t>& duid_vector) {
310 isc_throw(BadValue,
"generated DUID must have at least " 318 ofs.open(storage_location_.c_str(), std::ofstream::out |
319 std::ofstream::trunc);
321 isc_throw(InvalidOperation,
"unable to open DUID file " 322 << storage_location_ <<
" for writing");
326 DUID duid(duid_vector);
329 ofs << duid.toText();
331 isc_throw(InvalidOperation,
"unable to write to DUID file " 332 << storage_location_);
342 duid_.reset(
new DUID(duid_vector));
359 const std::vector<uint8_t> empty_vector;
381 DUIDFactory::readFromFile() {
384 std::ostringstream duid_str;
387 ifs.open(storage_location_.c_str(), std::ifstream::in);
389 std::string read_contents;
390 while (!ifs.eof() && ifs.good()) {
391 ifs >> read_contents;
392 duid_str << read_contents;
399 if (duid_str.tellp() != std::streampos(0)) {
std::list< IfacePtr > IfaceCollection
Type that holds a list of pointers to interfaces.
boost::shared_ptr< DUID > DuidPtr
uint8_t * writeUint32(uint32_t value, uint8_t *buffer, size_t length)
Write Unsigned 32-Bit Integer to Buffer.
void createLLT(const uint16_t htype, const uint32_t time_in, const std::vector< uint8_t > &ll_identifier)
Generates DUID-LLT.
link-layer + time, see RFC3315, section 11.2
boost::shared_ptr< Iface > IfacePtr
static DUID fromText(const std::string &text)
Create DUID from the textual format.
static const size_t MIN_DUID_LEN
minimum duid size The minimal DUID size specified in RFC 8415 is 1.
DuidPtr get()
Returns current DUID.
const IfaceCollection & getIfaces()
Returns container with all interfaces.
bool isRangeZero(Iterator begin, Iterator end)
Checks if specified range in a container contains only zeros.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
uint8_t * writeUint16(uint16_t value, void *buffer, size_t length)
Write Unsigned 16-Bit Integer to Buffer.
void createLL(const uint16_t htype, const std::vector< uint8_t > &ll_identifier)
Generates DUID-LL.
bool isStored() const
Checks if generated DUID will be stored in the file.
link-layer, see RFC3315, section 11.4
uint32_t readUint32(const uint8_t *buffer, size_t length)
Read Unsigned 32-Bit Integer from Buffer.
Defines the logger used by the top-level component of kea-dhcp-ddns.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
void createEN(const uint32_t enterprise_id, const std::vector< uint8_t > &identifier)
Generates DUID-EN.
string trim(const string &instring)
Trim Leading and Trailing Spaces.
enterprise-id, see RFC3315, section 11.3
void fillRandom(Iterator begin, Iterator end)
Fill in specified range with a random data.