27const size_t DUID_TYPE_LEN = 2;
 
   30const size_t MIN_MAC_LEN = 6;
 
   33const size_t ENTERPRISE_ID_LEN = 4;
 
   36const size_t DUID_EN_IDENTIFIER_LEN = 6;
 
   44    : storage_location_(
trim(storage_location)), duid_() {
 
 
   49    return (!storage_location_.empty());
 
 
   54                       const std::vector<uint8_t>& ll_identifier) {
 
   61    uint16_t htype_current = 0;
 
   62    uint32_t time_current = 0;
 
   63    std::vector<uint8_t> identifier_current;
 
   67        std::vector<uint8_t> duid_vec = duid_->getDuid();
 
   68        if ((duid_->getType() == 
DUID::DUID_LLT) && (duid_vec.size() > 8)) {
 
   69            htype_current = 
readUint16(&duid_vec[2], duid_vec.size() - 2);
 
   70            time_current = 
readUint32(&duid_vec[4], duid_vec.size() - 4);
 
   71            identifier_current.assign(duid_vec.begin() + 8, duid_vec.end());
 
   75    uint32_t time_out = time_in;
 
   79        time_out = (time_current != 0 ? time_current :
 
   83    std::vector<uint8_t> ll_identifier_out = ll_identifier;
 
   84    uint16_t htype_out = htype;
 
   89    if (ll_identifier_out.empty()) {
 
   91        if (identifier_current.empty()) {
 
   92            createLinkLayerId(ll_identifier_out, htype_out);
 
   95            ll_identifier_out = identifier_current;
 
   96            htype_out = htype_current;
 
   99    } 
else if (htype_out == 0) {
 
  102        htype_out = ((htype_current != 0) ? htype_current :
 
  108    std::vector<uint8_t> duid_out(DUID_TYPE_LEN + 
sizeof(time_out) +
 
  113    duid_out.insert(duid_out.end(), ll_identifier_out.begin(),
 
  114                    ll_identifier_out.end());
 
 
  122                      const std::vector<uint8_t>& identifier) {
 
  129    uint32_t enterprise_id_current = 0;
 
  130    std::vector<uint8_t> identifier_current;
 
  134        std::vector<uint8_t> duid_vec = duid_->getDuid();
 
  135        if ((duid_->getType() == 
DUID::DUID_EN) && (duid_vec.size() > 6)) {
 
  136            enterprise_id_current = 
readUint32(&duid_vec[2], duid_vec.size() - 2);
 
  137            identifier_current.assign(duid_vec.begin() + 6, duid_vec.end());
 
  143    uint32_t enterprise_id_out = enterprise_id;
 
  144    if (enterprise_id_out == 0) {
 
  145        if (enterprise_id_current != 0) {
 
  146            enterprise_id_out = enterprise_id_current;
 
  148            enterprise_id_out = ENTERPRISE_ID_ISC;
 
  153    std::vector<uint8_t> duid_out(DUID_TYPE_LEN + ENTERPRISE_ID_LEN);
 
  155    writeUint32(enterprise_id_out, &duid_out[2], ENTERPRISE_ID_LEN);
 
  159    if (identifier.empty()) {
 
  161        if (identifier_current.empty()) {
 
  164            duid_out.resize(DUID_TYPE_LEN + ENTERPRISE_ID_LEN +
 
  165                            DUID_EN_IDENTIFIER_LEN);
 
  168            ::srandom(time(NULL));
 
  169            fillRandom(duid_out.begin() + DUID_TYPE_LEN + ENTERPRISE_ID_LEN,
 
  174            duid_out.insert(duid_out.end(), identifier_current.begin(),
 
  175                            identifier_current.end());
 
  180        duid_out.insert(duid_out.end(), identifier.begin(), identifier.end());
 
 
  189                      const std::vector<uint8_t>& ll_identifier) {
 
  196    uint16_t htype_current = 0;
 
  197    std::vector<uint8_t> identifier_current;
 
  201        std::vector<uint8_t> duid_vec = duid_->getDuid();
 
  202        if ((duid_->getType() == 
DUID::DUID_LL) && (duid_vec.size() > 4)) {
 
  203            htype_current = 
readUint16(&duid_vec[2], duid_vec.size() - 2);
 
  204            identifier_current.assign(duid_vec.begin() + 4, duid_vec.end());
 
  208    std::vector<uint8_t> ll_identifier_out = ll_identifier;
 
  209    uint16_t htype_out = htype;
 
  214    if (ll_identifier_out.empty()) {
 
  216        if (identifier_current.empty()) {
 
  217            createLinkLayerId(ll_identifier_out, htype_out);
 
  220            ll_identifier_out = identifier_current;
 
  221            htype_out = htype_current;
 
  224    } 
else if (htype_out == 0) {
 
  227        htype_out = ((htype_current != 0) ? htype_current :
 
  233    std::vector<uint8_t> duid_out(DUID_TYPE_LEN + 
sizeof(htype_out));
 
  236    duid_out.insert(duid_out.end(), ll_identifier_out.begin(),
 
  237                    ll_identifier_out.end());
 
 
  244DUIDFactory::createLinkLayerId(std::vector<uint8_t>& identifier,
 
  245                               uint16_t& htype)
 const {
 
  263        if (iface->getMacLen() < MIN_MAC_LEN) {
 
  268        if (iface->flag_loopback_) {
 
  273        if (!iface->flag_up_) {
 
  280        if (
isRangeZero(iface->getMac(), iface->getMac() + iface->getMacLen())) {
 
  285        identifier.assign(iface->getMac(), iface->getMac() + iface->getMacLen());
 
  286        htype = iface->getHWType();
 
  289        if ((htype == 
static_cast<uint16_t
>(
HTYPE_ETHER)) &&
 
  290            (iface->getMacLen() == 6)) {
 
  297    if (identifier.empty()) {
 
  298        isc_throw(Unexpected, 
"unable to find suitable interface for " 
  299                  "generating a DUID-LLT");
 
  304DUIDFactory::set(
const std::vector<uint8_t>& duid_vector) {
 
  307        isc_throw(BadValue, 
"generated DUID must have at least " 
  315            ofs.open(storage_location_.c_str(), std::ofstream::out |
 
  316                     std::ofstream::trunc);
 
  318                isc_throw(InvalidOperation, 
"unable to open DUID file " 
  319                          << storage_location_ << 
" for writing");
 
  323            DUID duid(duid_vector);
 
  326            ofs << duid.toText();
 
  328                isc_throw(InvalidOperation, 
"unable to write to DUID file " 
  329                          << storage_location_);
 
  339    duid_.reset(
new DUID(duid_vector));
 
  356    const std::vector<uint8_t> empty_vector;
 
 
  378DUIDFactory::readFromFile() {
 
  381    std::ostringstream duid_str;
 
  384        ifs.open(storage_location_.c_str(), std::ifstream::in);
 
  386            std::string read_contents;
 
  387            while (!ifs.eof() && ifs.good()) {
 
  388                ifs >> read_contents;
 
  389                duid_str << read_contents;
 
  396        if (duid_str.tellp() != std::streampos(0)) {
 
Holds DUID (DHCPv6 Unique Identifier)
static DUID fromText(const std::string &text)
Create DUID from the textual format.
bool isStored() const
Checks if generated DUID will be stored in the file.
DUIDFactory(const std::string &storage_location="")
Constructor.
void createLLT(const uint16_t htype, const uint32_t time_in, const std::vector< uint8_t > &ll_identifier)
Generates DUID-LLT.
void createEN(const uint32_t enterprise_id, const std::vector< uint8_t > &identifier)
Generates DUID-EN.
DuidPtr get()
Returns current DUID.
void createLL(const uint16_t htype, const std::vector< uint8_t > &ll_identifier)
Generates DUID-LL.
static constexpr size_t MIN_DUID_LEN
minimum duid size
@ DUID_LL
link-layer, see RFC3315, section 11.4
@ DUID_LLT
link-layer + time, see RFC3315, section 11.2
@ DUID_EN
enterprise-id, see RFC3315, section 11.3
static IfaceMgr & instance()
IfaceMgr is a singleton class.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< DUID > DuidPtr
@ HTYPE_ETHER
Ethernet 10Mbps.
string trim(const string &input)
Trim leading and trailing spaces.
void fillRandom(Iterator begin, Iterator end)
Fill in specified range with a random data.
uint8_t * writeUint32(uint32_t const value, void *const buffer, size_t const length)
uint32_t wrapper over writeUint.
uint16_t readUint16(void const *const buffer, size_t const length)
uint16_t wrapper over readUint.
bool isRangeZero(Iterator begin, Iterator end)
Checks if specified range in a container contains only zeros.
uint8_t * writeUint16(uint16_t const value, void *const buffer, size_t const length)
uint16_t wrapper over writeUint.
uint32_t readUint32(void const *const buffer, size_t const length)
uint32_t wrapper over readUint.
Defines the logger used by the top-level component of kea-lfc.