}
bool
-DUIDFactory::isPersisted() const {
+DUIDFactory::isStored() const {
return (!storage_location_.empty());
}
// We'll need DUID stored in the file to compare it against the
// new configuration. If the new configuration indicates that some
// bits of the DUID should be generated we'll first try to use the
- // values stored in the file to prvent DUID from changing if possible.
+ // values stored in the file to prevent DUID from changing if possible.
readFromFile();
uint16_t htype_current = 0;
} else if (htype_out == 0) {
// If link layer type unspecified and link layer adddress
- // is specified, use HTYPE_ETHER.
- htype_out = HTYPE_ETHER;
+ // is specified, use current type or HTYPE_ETHER.
+ htype_out = (htype_current != 0) ? htype_current : HTYPE_ETHER;
}
} else if (htype_out == 0) {
// If link layer type unspecified and link layer adddress
- // is specified, use HTYPE_ETHER.
- htype_out = HTYPE_ETHER;
+ // is specified, use current type or HTYPE_ETHER.
+ htype_out = (htype_current != 0) ? htype_current : HTYPE_ETHER;
}
// MAC address should be at least 6 bytes. Although there is no such
// requirement in any RFC, all decent physical interfaces (Ethernet,
- // WiFi, InfiniBand, etc.) have 6 bytes long MAC address. We want to
- // base our DUID on real hardware address, rather than virtual
- // interface that pretends that underlying IP address is its MAC.
+ // WiFi, InfiniBand, etc.) have at least 6 bytes long MAC address.
+ // We want to/ base our DUID on real hardware address, rather than
+ // virtual interface that pretends that underlying IP address is its
+ // MAC.
if (iface->getMacLen() < MIN_MAC_LEN) {
continue;
}
<< DUID::MIN_DUID_LEN << " bytes");
}
- // Persist DUID in a file if file location specified.
- if (isPersisted()) {
+ // Store DUID in a file if file location specified.
+ if (isStored()) {
std::ofstream ofs;
try {
ofs.open(storage_location_.c_str(), std::ofstream::out |
}
// DUID doesn't exist, so we need to create it.
+ const std::vector<uint8_t> empty_vector;
try {
// There is no file with a DUID or the DUID stored in the file is
// invalid. We need to generate a new DUID.
- createLLT(0, 0, std::vector<uint8_t>());
+ createLLT(0, 0, empty_vector);
} catch (...) {
// It is possible that the creation of the DUID-LLT failed if there
// Fall back to creation of DUID enterprise. If that fails we allow
// for propagating exception to indicate a fatal error. This may
// be the case if we failed to write it to a file.
- createEN(0, std::vector<uint8_t>());
+ createEN(0, empty_vector);
}
return (duid_);
duid_.reset();
std::ostringstream duid_str;
- if (isPersisted()) {
+ if (isStored()) {
std::ifstream ifs;
ifs.open(storage_location_.c_str(), std::ifstream::in);
if (ifs.good()) {
///
/// This class is also responsible for storing the generated DUID in a
/// file. The location of this file is specified in the class constructor.
-/// If this location is not specified the DUID is not persisted, i.e. is
+/// If this location is not specified the DUID is not stored, i.e. is
/// lost when the server or client shuts down. However, the DUID may be
/// reconstructed according to the configuration of the client or server
/// when they are back online.
/// stored.
DUIDFactory(const std::string& storage_location = "");
- /// @brief Checks if generated DUID will be persisted in the file.
+ /// @brief Checks if generated DUID will be stored in the file.
///
- /// @return true if generated DUIDs are persisted in a file, false
+ /// @return true if generated DUIDs are stored in a file, false
/// otherwise.
- bool isPersisted() const;
+ bool isStored() const;
/// @brief Generates DUID-LLT.
///
- /// This method generates DUID-LLT.
+ /// This method generates DUID-LLT (Link Layer plus Time).
///
/// @param htype Hardware type. If this is set to 0 and link layer
/// address is empty a value from existing DUID or a default value
/// of @c HTYPE_ETHER is used. Otherwise a link layer type of selected
/// interface is used.
/// @param time_in Explicit value of time for the DUID. If this is
- /// set to 0 a value from existing DUOD or current time is used,
+ /// set to 0 a value from existing DUID or current time is used,
/// otherwise a value specified is used.
/// @param ll_identifier Data to be used as link layer address. If
/// this is an empty vector this method will try to use link layer
/// @brief Generates DUID-EN.
///
+ /// This method generates DUID-EN (DUID Enterprise).
+ ///
/// @param enterprise_id Enterprise id. If this value is 0, a value
/// from existing DUID is used or ISC's enterprise id if there is
/// no DUID yet.
/// @brief Generates DUID-LL.
///
+ /// This method generates DUID-LL (Link Layer).
+ ///
/// @param htype Hardware type. If this is set to 0 and link layer
/// address is empty a value from existing DUID or a default value
/// of @c HTYPE_ETHER is used. Otherwise a link layer type of selected
/// generation of the DUID-LLT may fail, e.g. when there are no interfaces
/// with a suitable link layer address. In this case, this method will
/// generate DUID-EN, with the ISC enterprise id. If this fails, e.g. as a
- /// result of error while persisting the generated DUID-EN, exception
+ /// result of error while storing the generated DUID-EN, exception
/// is thrown.
///
/// @return Instance of the DUID read from file, or generated.
/// @brief Sets a new DUID as current.
///
- /// The generated DUID is persisted in the file, if such file is specified.
+ /// The generated DUID is stored in the file, if such file is specified.
/// The new DUID will be returned when @c DUIDFactory::get is called.
///
/// @param duid_vector New DUID represented as vector of bytes.
/// @brief Returns absolute path to a test DUID storage.
///
/// @param duid_file_name Name of the file holding test DUID.
- std::string absolutePath(const std::string& duid_file_path) const;
+ std::string absolutePath(const std::string& duid_file_name) const;
/// @brief Removes default DUID file used in the tests.
///
///
/// @param expected_enterprise_id Expected enterprise id as string.
/// @param expected_identifier Expected variable length identifier
- /// as string.
+ /// as string. If empty string specified the test method only checks
+ /// that generated identifier consists of some random values.
void testEN(const std::string& expected_enterprise_id,
const std::string& expected_identifier = "");
+ /// @brief Tests creation of a DUID-EN.
+ ///
+ /// @param expected_enterprise_id Expected enterprise id as string.
+ /// @param expected_identifier Expected variable length identifier
+ /// as string. If empty string specified the test method only checks
+ /// that generated identifier consists of some random values.
+ /// @param factory_ref Reference to DUID factory.
+ void testEN(const std::string& expected_enterprise_id,
+ const std::string& expected_identifier,
+ DUIDFactory& factory_ref);
+
/// @brief Tests creation of a DUID-LL.
///
/// @param expected_htype Expected link layer type as string.
void testLL(const std::string& expected_htype,
const std::string& expected_hwaddr);
+ /// @brief Tests creation of a DUID-LL.
+ ///
+ /// @param expected_htype Expected link layer type as string.
+ /// @param expected_hwaddr Expected link layer type as string.
+ /// @param factory_ref Reference to DUID factory.
+ void testLL(const std::string& expected_htype,
+ const std::string& expected_hwaddr,
+ DUIDFactory& factory_ref);
+
/// @brief Returns reference to a default factory.
DUIDFactory& factory() {
return (factory_);
}
std::string
-DUIDFactoryTest::absolutePath(const std::string& duid_file_path) const {
+DUIDFactoryTest::absolutePath(const std::string& duid_file_name) const {
std::ostringstream s;
- s << TEST_DATA_BUILDDIR << "/" << duid_file_path;
+ s << TEST_DATA_BUILDDIR << "/" << duid_file_name;
return (s.str());
}
EXPECT_EQ(duid->toText(), readDefaultFile());
}
-
-
void
DUIDFactoryTest::testEN(const std::string& expected_enterprise_id,
const std::string& expected_identifier) {
- DuidPtr duid = factory().get();
+ testEN(expected_enterprise_id, expected_identifier, factory());
+}
+
+void
+DUIDFactoryTest::testEN(const std::string& expected_enterprise_id,
+ const std::string& expected_identifier,
+ DUIDFactory& factory_ref) {
+ DuidPtr duid = factory_ref.get();
ASSERT_TRUE(duid);
ASSERT_GE(duid->getDuid().size(), 8);
std::string duid_text = toString(duid->getDuid());
// Verify enterprise ID.
EXPECT_EQ(expected_enterprise_id, duid_text.substr(4, 8));
- // If no expecyed identifier, we should at least check that the
+ // If no expected identifier, we should at least check that the
// generated identifier contains some random non-zero digits.
if (expected_identifier.empty()) {
EXPECT_FALSE(isRangeZero(duid->getDuid().begin(),
void
DUIDFactoryTest::testLL(const std::string& expected_htype,
const std::string& expected_hwaddr) {
- DuidPtr duid = factory().get();
+ testLL(expected_htype, expected_hwaddr, factory());
+}
+
+void
+DUIDFactoryTest::testLL(const std::string& expected_htype,
+ const std::string& expected_hwaddr,
+ DUIDFactory& factory_ref) {
+ DuidPtr duid = factory_ref.get();
ASSERT_TRUE(duid);
ASSERT_GE(duid->getDuid().size(), 8);
std::string duid_text = toString(duid->getDuid());
// DUID type LL
EXPECT_EQ("0003", duid_text.substr(0, 4));
- // Link layer type HTYPE_ETHER
+ // Link layer type.
EXPECT_EQ(expected_htype, duid_text.substr(4, 4));
// MAC address of the interface.
// use current time, HTYPE_ETHER and MAC address of one of the
// interfaces.
ASSERT_NO_THROW(factory().createLLT(0, 0, std::vector<uint8_t>()));
- testLLT("0001", timeAsHexString(), false, "010101010101");
+ testLLT("0001", timeAsHexString(), false, "080808080808");
}
// This test verifies that the factory class creates a DUID-LLT from
// generated.
TEST_F(DUIDFactoryTest, createLLTExplicitTime) {
ASSERT_NO_THROW(factory().createLLT(0, 0xABCDEF, std::vector<uint8_t>()));
- testLLT("0001", "00ABCDEF", true, "010101010101");
+ testLLT("0001", "00ABCDEF", true, "080808080808");
}
// This test verifies that the factory class creates DUID-LLT with
// is used to generate the DUID.
TEST_F(DUIDFactoryTest, createLLTExplicitHtype) {
ASSERT_NO_THROW(factory().createLLT(HTYPE_FDDI, 0, std::vector<uint8_t>()));
- testLLT("0001", timeAsHexString(), false, "010101010101");
+ testLLT("0001", timeAsHexString(), false, "080808080808");
}
// This test verifies that the factory class creates DUID-LLT from
// link layer address. The factory function should use the
// values in the existing DUID.
ASSERT_NO_THROW(factory2.createLLT(0, 0, std::vector<uint8_t>()));
- testLLT("0008", "FAFAFAFA", true, "242424242424");
+ testLLT("0008", "FAFAFAFA", true, "242424242424", factory2);
+
+ // Try to reuse only a time value.
+ DUIDFactory factory3(absolutePath(DEFAULT_DUID_FILE));
+ ASSERT_NO_THROW(factory3.createLLT(HTYPE_ETHER, 0,
+ toVector("121212121212")));
+ testLLT("0001", "FAFAFAFA", true, "121212121212", factory3);
+
+ // Reuse only a hardware type.
+ DUIDFactory factory4(absolutePath(DEFAULT_DUID_FILE));
+ ASSERT_NO_THROW(factory4.createLLT(0, 0x23432343,
+ toVector("455445544554")));
+ testLLT("0001", "23432343", true, "455445544554", factory4);
+
+ // Reuse link layer address. Note that in this case the hardware
+ // type is set to the type of the interface from which hardware
+ // address is obtained and the explicit value is ignored.
+ DUIDFactory factory5(absolutePath(DEFAULT_DUID_FILE));
+ ASSERT_NO_THROW(factory5.createLLT(HTYPE_FDDI, 0x11111111,
+ std::vector<uint8_t>()));
+ testLLT("0001", "11111111", true, "455445544554", factory5);
}
// This test verifies that the DUID-EN can be generated entirely. Such
// Create another factory class, which uses the same file.
DUIDFactory factory2(absolutePath(DEFAULT_DUID_FILE));
ASSERT_NO_THROW(factory2.createEN(0, std::vector<uint8_t>()));
- testEN("FAFAFAFA", "242424242424");
+ testEN("FAFAFAFA", "242424242424", factory2);
+
+ // Reuse only enterprise id.
+ DUIDFactory factory3(absolutePath(DEFAULT_DUID_FILE));
+ ASSERT_NO_THROW(factory3.createEN(0, toVector("121212121212")));
+ testEN("FAFAFAFA", "121212121212", factory3);
+
+ // Reuse only variable length identifier.
+ DUIDFactory factory4(absolutePath(DEFAULT_DUID_FILE));
+ ASSERT_NO_THROW(factory4.createEN(0x1234, std::vector<uint8_t>()));
+ testEN("00001234", "121212121212", factory4);
}
// This test verifies that the DUID-LL is generated when neither link layer
// type nor address is specified.
TEST_F(DUIDFactoryTest, createLL) {
ASSERT_NO_THROW(factory().createLL(0, std::vector<uint8_t>()));
- testLL("0001", "010101010101");
+ testLL("0001", "080808080808");
}
// This test verifies that the DUID-LL is generated and the link layer type
// used is taken from the interface used to generate link layer address.
TEST_F(DUIDFactoryTest, createLLExplicitHtype) {
ASSERT_NO_THROW(factory().createLL(HTYPE_FDDI, std::vector<uint8_t>()));
- testLL("0001", "010101010101");
+ testLL("0001", "080808080808");
}
// This test verifies that DUID-LL is created from explicitly provided
// link layer address. The factory function should use the
// values in the existing DUID.
ASSERT_NO_THROW(factory2.createLL(0, std::vector<uint8_t>()));
- testLL("0008", "242424242424");
+ testLL("0008", "242424242424", factory2);
+
+ // Reuse only hardware type
+ DUIDFactory factory3(absolutePath(DEFAULT_DUID_FILE));
+ ASSERT_NO_THROW(factory3.createLL(0, toVector("121212121212")));
+ testLL("0008", "121212121212", factory3);
+
+ // Reuse link layer address. Note that when the link layer address is
+ // reused, the explicit value of hardware type is reused too and the
+ // explicit value of hardware type is ignored.
+ DUIDFactory factory4(absolutePath(DEFAULT_DUID_FILE));
+ ASSERT_NO_THROW(factory4.createLL(HTYPE_ETHER, std::vector<uint8_t>()));
+ testLL("0008", "121212121212", factory4);
}
// This test verifies that it is possible to override a DUID.
TEST_F(DUIDFactoryTest, override) {
// Create default DUID-LLT.
ASSERT_NO_THROW(static_cast<void>(factory().get()));
- testLLT("0001", timeAsHexString(), false, "010101010101");
+ testLLT("0001", timeAsHexString(), false, "080808080808");
ASSERT_NO_THROW(factory().createEN(0, toVector("12131415")));
testEN("000009BF", "12131415");