Browse Source

[3874] Use DUIDFactory class in the DHCPV6 server code.

Marcin Siodelski 9 years ago
parent
commit
3c5e3548bd

+ 10 - 13
src/bin/dhcp6/dhcp6_messages.mes

@@ -649,19 +649,16 @@ recommended as existing clients will not recognize the server and may go
 through a rebind phase. However, they should be able to recover without
 losing their leases.
 
-% DHCP6_SERVERID_LOADED server-id %1 has been loaded from file %2
-This debug message indicates that the server loaded its server identifier.
-That value is sent in all server responses and clients use it to
-discriminate between servers. This is a part of normal startup or
-reconfiguration procedure.
-
-% DHCP6_SERVERID_WRITE_FAIL server was not able to write its ID to file %1
-This warning message indicates that server was not able to write its
-server identifier (DUID) to a file. This likely indicates lack of write
-permission to a given file or directory. This is not critical and the
-server will continue to operate, but server will generate different DUID
-during every start and clients will need to go through a rebind phase
-to recover.
+% DHCP6_USING_SERVERID server is using server-id %1 and stores in the the file %2
+This info message is logged when the server reads its server-id from a
+file or generates it. This message is a notification to the administrator
+what server-id will be used and where it is persisted. Typically, there is
+no need to modify the server id. However, it is possible to do it in the
+Kea configuration file. It is important to understand the implications of
+such modification. The clients will remember previous server-id, and will
+use it to extend their leases. As a result, they will have to go through
+a rebinding phase to re-acquire their leases and associate them with a
+new server id.
 
 % DHCP6_SERVER_FAILED server failed: %1
 The IPv6 DHCP server has encountered a fatal error and is terminating.

+ 7 - 143
src/bin/dhcp6/dhcp6_srv.cc

@@ -19,6 +19,7 @@
 #include <dhcp/dhcp6.h>
 #include <dhcp/docsis3_option_defs.h>
 #include <dhcp/duid.h>
+#include <dhcp/duid_factory.h>
 #include <dhcp/iface_mgr.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/option6_addrlst.h>
@@ -199,21 +200,12 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port)
         }
 
         string duid_file = CfgMgr::instance().getDataDir() + "/" + string(SERVER_DUID_FILE);
-        if (loadServerID(duid_file)) {
-            LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_SERVERID_LOADED)
-                .arg(duidToString(getServerID()))
-                .arg(duid_file);
-        } else {
-            generateServerID();
-            LOG_INFO(dhcp6_logger, DHCP6_SERVERID_GENERATED)
-                .arg(duidToString(getServerID()))
-                .arg(duid_file);
-
-            if (!writeServerID(duid_file)) {
-                LOG_WARN(dhcp6_logger, DHCP6_SERVERID_WRITE_FAIL)
-                    .arg(duid_file);
-            }
-        }
+        DUIDFactory duid_factory(duid_file);
+        DuidPtr duid = duid_factory.get();
+        serverid_.reset(new Option(Option::V6, D6O_SERVERID, duid->getDuid()));
+        LOG_INFO(dhcp6_logger, DHCP6_USING_SERVERID)
+            .arg(duidToString(getServerID()))
+            .arg(duid_file);
 
         // Instantiate allocation engine. The number of allocation attempts equal
         // to zero indicates that the allocation engine will use the number of
@@ -717,38 +709,6 @@ bool Dhcpv6Srv::run() {
     return (true);
 }
 
-bool Dhcpv6Srv::loadServerID(const std::string& file_name) {
-
-    // load content of the file into a string
-    fstream f(file_name.c_str(), ios::in);
-    if (!f.is_open()) {
-        return (false);
-    }
-
-    string hex_string;
-    f >> hex_string;
-    f.close();
-
-    // remove any spaces
-    boost::algorithm::erase_all(hex_string, " ");
-
-    // now remove :
-    /// @todo: We should check first if the format is sane.
-    /// Otherwise 1:2:3:4 will be converted to 0x12, 0x34
-    boost::algorithm::erase_all(hex_string, ":");
-
-    std::vector<uint8_t> bin;
-
-    // Decode the hex string and store it in bin (which happens
-    // to be OptionBuffer format)
-    isc::util::encode::decodeHex(hex_string, bin);
-
-    // Now create server-id option
-    serverid_.reset(new Option(Option::V6, D6O_SERVERID, bin));
-
-    return (true);
-}
-
 std::string
 Dhcpv6Srv::duidToString(const OptionPtr& opt) {
     stringstream tmp;
@@ -769,102 +729,6 @@ Dhcpv6Srv::duidToString(const OptionPtr& opt) {
     return tmp.str();
 }
 
-bool
-Dhcpv6Srv::writeServerID(const std::string& file_name) {
-    fstream f(file_name.c_str(), ios::out | ios::trunc);
-    if (!f.good()) {
-        return (false);
-    }
-    f << duidToString(getServerID());
-    f.close();
-    return (true);
-}
-
-void
-Dhcpv6Srv::generateServerID() {
-
-    /// @todo: This code implements support for DUID-LLT (the recommended one).
-    /// We should eventually add support for other DUID types: DUID-LL, DUID-EN
-    /// and DUID-UUID
-
-    const IfaceMgr::IfaceCollection& ifaces = IfaceMgr::instance().getIfaces();
-
-    // Let's find suitable interface.
-    BOOST_FOREACH(IfacePtr iface, ifaces) {
-        // All the following checks could be merged into one multi-condition
-        // statement, but let's keep them separated as perhaps one day
-        // we will grow knobs to selectively turn them on or off. Also,
-        // this code is used only *once* during first start on a new machine
-        // and then server-id is stored. (or at least it will be once
-        // DUID storage is implemented)
-
-        // I wish there was a this_is_a_real_physical_interface flag...
-
-        // 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.
-        if (iface->getMacLen() < MIN_MAC_LEN) {
-            continue;
-        }
-
-        // Let's don't use loopback.
-        if (iface->flag_loopback_) {
-            continue;
-        }
-
-        // Let's skip downed interfaces. It is better to use working ones.
-        if (!iface->flag_up_) {
-            continue;
-        }
-
-        // Some interfaces (like lo on Linux) report 6-bytes long
-        // MAC address 00:00:00:00:00:00. Let's not use such weird interfaces
-        // to generate DUID.
-        if (isRangeZero(iface->getMac(), iface->getMac() + iface->getMacLen())) {
-            continue;
-        }
-
-        // Ok, we have useful MAC. Let's generate DUID-LLT based on
-        // it. See RFC3315, Section 9.2 for details.
-
-        // DUID uses seconds since midnight of 01-01-2000, time() returns
-        // seconds since 01-01-1970. DUID_TIME_EPOCH substitution corrects
-        // that.
-        time_t seconds = time(NULL);
-        seconds -= DUID_TIME_EPOCH;
-
-        OptionBuffer srvid(8 + iface->getMacLen());
-        // We know that the buffer is more than 8 bytes long at this point.
-        writeUint16(DUID::DUID_LLT, &srvid[0], 2);
-        writeUint16(HWTYPE_ETHERNET, &srvid[2], 2);
-        writeUint32(static_cast<uint32_t>(seconds), &srvid[4], 4);
-        memcpy(&srvid[8], iface->getMac(), iface->getMacLen());
-
-        serverid_ = OptionPtr(new Option(Option::V6, D6O_SERVERID,
-                                         srvid.begin(), srvid.end()));
-        return;
-    }
-
-    // If we reached here, there are no suitable interfaces found.
-    // Either interface detection is not supported on this platform or
-    // this is really weird box. Let's use DUID-EN instead.
-    // See Section 9.3 of RFC3315 for details.
-
-    OptionBuffer srvid(12);
-    writeUint16(DUID::DUID_EN, &srvid[0], srvid.size());
-    writeUint32(ENTERPRISE_ID_ISC, &srvid[2], srvid.size() - 2);
-
-    // Length of the identifier is company specific. I hereby declare
-    // ISC "standard" of 6 bytes long pseudo-random numbers.
-    srandom(time(NULL));
-    fillRandom(&srvid[6], &srvid[12]);
-
-    serverid_ = OptionPtr(new Option(Option::V6, D6O_SERVERID,
-                                     srvid.begin(), srvid.end()));
-}
-
 void
 Dhcpv6Srv::copyClientOptions(const Pkt6Ptr& question, Pkt6Ptr& answer) {
     // Add client-id.

+ 0 - 29
src/bin/dhcp6/dhcp6_srv.h

@@ -564,34 +564,6 @@ protected:
     void releaseLeases(const Pkt6Ptr& release, Pkt6Ptr& reply,
                        AllocEngine::ClientContext6& ctx);
 
-    /// @brief Sets server-identifier.
-    ///
-    /// This method attempts to generate server-identifier DUID. It generates a
-    /// new DUID using interface link-layer addresses (EUI-64) + timestamp (DUID
-    /// type duid-llt, see RFC3315, section 9.2). If there are no suitable
-    /// interfaces present, exception it thrown
-    ///
-    /// @throws isc::Unexpected Failed to read DUID file and no suitable
-    ///         interfaces for new DUID generation are detected.
-    void generateServerID();
-
-    /// @brief attempts to load DUID from a file
-    ///
-    /// Tries to load duid from a text file. If the load is successful,
-    /// it creates server-id option and stores it in serverid_ (to be used
-    /// later by getServerID()).
-    ///
-    /// @param file_name name of the DUID file to load
-    /// @return true if load was successful, false otherwise
-    bool loadServerID(const std::string& file_name);
-
-    /// @brief attempts to write DUID to a file
-    /// Tries to write duid content (stored in serverid_) to a text file.
-    ///
-    /// @param file_name name of the DUID file to write
-    /// @return true if write was successful, false otherwise
-    bool writeServerID(const std::string& file_name);
-
     /// @brief converts DUID to text
     /// Converts content of DUID option to a text representation, e.g.
     /// 01:ff:02:03:06:80:90:ab:cd:ef
@@ -600,7 +572,6 @@ protected:
     /// @return string representation
     static std::string duidToString(const OptionPtr& opt);
 
-
     /// @brief dummy wrapper around IfaceMgr::receive6
     ///
     /// This method is useful for testing purposes, where its replacement

+ 0 - 32
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -1432,38 +1432,6 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayInterfaceId) {
     EXPECT_EQ(subnet2, srv.selectSubnet(pkt));
 }
 
-// This test verifies if the server-id disk operations (read, write) are
-// working properly.
-TEST_F(Dhcpv6SrvTest, ServerID) {
-    NakedDhcpv6Srv srv(0);
-
-    string duid1_text = "01:ff:02:03:06:80:90:ab:cd:ef";
-    uint8_t duid1[] = { 0x01, 0xff, 2, 3, 6, 0x80, 0x90, 0xab, 0xcd, 0xef };
-    OptionBuffer expected_duid1(duid1, duid1 + sizeof(duid1));
-
-    fstream file1(DUID_FILE, ios::out | ios::trunc);
-    file1 << duid1_text;
-    file1.close();
-
-    // Test reading from a file
-    EXPECT_TRUE(srv.loadServerID(DUID_FILE));
-    ASSERT_TRUE(srv.getServerID());
-    ASSERT_EQ(sizeof(duid1) + Option::OPTION6_HDR_LEN, srv.getServerID()->len());
-    ASSERT_TRUE(expected_duid1 == srv.getServerID()->getData());
-
-    // Now test writing to a file
-    EXPECT_EQ(0, remove(DUID_FILE));
-    EXPECT_NO_THROW(srv.writeServerID(DUID_FILE));
-
-    fstream file2(DUID_FILE, ios::in);
-    ASSERT_TRUE(file2.good());
-    string text;
-    file2 >> text;
-    file2.close();
-
-    EXPECT_EQ(duid1_text, text);
-}
-
 // Checks if server responses are sent to the proper port.
 TEST_F(Dhcpv6SrvTest, portsDirectTraffic) {
 

+ 0 - 2
src/bin/dhcp6/tests/dhcp6_test_utils.h

@@ -111,8 +111,6 @@ public:
     using Dhcpv6Srv::testUnicast;
     using Dhcpv6Srv::sanityCheck;
     using Dhcpv6Srv::classifyPacket;
-    using Dhcpv6Srv::loadServerID;
-    using Dhcpv6Srv::writeServerID;
     using Dhcpv6Srv::unpackOptions;
     using Dhcpv6Srv::shutdown_;
     using Dhcpv6Srv::name_change_reqs_;