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)) {