Browse Source

[4302] Use new functions to retrieve reservations by any identifier.

Marcin Siodelski 9 years ago
parent
commit
497a254512

+ 49 - 22
src/lib/dhcpsrv/cfg_hosts.cc

@@ -227,7 +227,6 @@ CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
         .arg(storage.size());
 }
 
-
 ConstHostPtr
 CfgHosts::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
                const DuidPtr& duid) const {
@@ -367,14 +366,13 @@ CfgHosts::get6(const SubnetID& subnet_id,
 }
 
 ConstHostPtr
-CfgHosts::get6(const IOAddress&, const uint8_t) const {
-    isc_throw(isc::NotImplemented,
-              "get6(prefix, len) const is not implemented");
+CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
+    return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
 }
 
 HostPtr
-CfgHosts::get6(const IOAddress&, const uint8_t) {
-    isc_throw(isc::NotImplemented, "get6(prefix, len) is not implemented");
+CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) {
+    return (getHostInternal6<HostPtr>(prefix, prefix_len));
 }
 
 ConstHostPtr
@@ -425,6 +423,36 @@ CfgHosts::getHostInternal6(const SubnetID& subnet_id,
 
 }
 
+template<typename ReturnType>
+ReturnType
+CfgHosts::getHostInternal6(const asiolink::IOAddress& prefix,
+                           const uint8_t prefix_len) const {
+    LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_PREFIX)
+        .arg(prefix.toText()).arg(static_cast<int>(prefix_len));
+
+    // Let's get all reservations that match subnet_id, address.
+    const HostContainer6Index0& idx = hosts6_.get<0>();
+    HostContainer6Index0Range r = make_pair(idx.lower_bound(prefix),
+                                            idx.upper_bound(prefix));
+    for (HostContainer6Index0::iterator resrv = r.first; resrv != r.second;
+         ++resrv) {
+        if (resrv->resrv_.getPrefixLen() == prefix_len) {
+            LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
+                      HOSTS_CFG_GET_ONE_PREFIX_HOST)
+                .arg(prefix.toText())
+                .arg(static_cast<int>(prefix_len))
+                .arg(resrv->host_->toText());
+            return (resrv->host_);
+        }
+    }
+
+    LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE_DETAIL_DATA,
+              HOSTS_CFG_GET_ONE_PREFIX_NULL)
+        .arg(prefix.toText())
+        .arg(static_cast<int>(prefix_len));
+    return (ReturnType());
+}
+
 template<typename Storage>
 void
 CfgHosts::getAllInternal6(const SubnetID& subnet_id,
@@ -453,7 +481,7 @@ CfgHosts::getAllInternal6(const SubnetID& subnet_id,
                   HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST)
             .arg(subnet_id)
             .arg(address.toText())
-            .arg(resrv->host_);
+            .arg(resrv->host_->toText());
         storage.push_back(resrv->host_);
     }
 
@@ -470,11 +498,10 @@ CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
                           const uint8_t* identifier,
                           const size_t identifier_len) const {
 
-/*    LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID)
+    LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER)
         .arg(subnet6 ? "IPv6" : "IPv4")
         .arg(subnet_id)
-        .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
-        .arg(duid ? duid->toText() : "(no-duid)"); */
+        .arg(Host::getIdentifierAsText(identifier_type, identifier, identifier_len));
 
     // Get all hosts for a specified identifier. This may return multiple hosts
     // for different subnets, but the number of hosts returned should be low
@@ -506,30 +533,30 @@ CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
             } else {
                 isc_throw(DuplicateHost,  "more than one reservation found"
                           " for the host belonging to the subnet with id '"
-                          << subnet_id << "' and using the HW address '"
-//                          << (hwaddr ? hwaddr->toText(false) : "(null)")
-//                          << "' and DUID '"
-//                          << (duid ? duid->toText() : "(null)")
+                          << subnet_id << "' and using the identifier '"
+                          << Host::getIdentifierAsText(identifier_type,
+                                                       identifier,
+                                                       identifier_len)
                           << "'");
             }
         }
     }
 
-/*    if (host) {
+    if (host) {
         LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
-                  HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID)
+                  HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST)
             .arg(subnet_id)
-            .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
-            .arg(duid ? duid->toText() : "(no-duid)")
+            .arg(Host::getIdentifierAsText(identifier_type, identifier,
+                                           identifier_len))
             .arg(host->toText());
 
     } else {
         LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS,
-                  HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID_NULL)
+                  HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL)
             .arg(subnet_id)
-            .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
-            .arg(duid ? duid->toText() : "(no-duid)");
-    } */
+            .arg(Host::getIdentifierAsText(identifier_type, identifier,
+                                           identifier_len));
+    }
 
     return (host);
 }

+ 7 - 2
src/lib/dhcpsrv/cfg_hosts.h

@@ -276,7 +276,7 @@ public:
     /// @param prefix IPv6 prefix for which the @c Host object is searched.
     /// @param prefix_len IPv6 prefix length.
     ///
-    /// @throw isc::NotImplemented
+    /// @return Const @c Host object for which specified prefix is reserved.
     virtual ConstHostPtr
     get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
 
@@ -285,7 +285,8 @@ public:
     /// @param prefix IPv6 prefix for which the @c Host object is searched.
     /// @param prefix_len IPv6 prefix length.
     ///
-    /// @throw isc::NotImplemented
+    /// @return Non-const @c Host object for which specified prefix is
+    /// reserved.
     virtual HostPtr
     get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len);
 
@@ -449,6 +450,10 @@ private:
     ReturnType getHostInternal6(const SubnetID& subnet_id,
                                 const asiolink::IOAddress& adddress) const;
 
+    template<typename ReturnType>
+    ReturnType getHostInternal6(const asiolink::IOAddress& prefix,
+                                const uint8_t prefix_len) const;
+
     /// @brief Adds a new host to the v4 collection.
     ///
     /// This is an internal method called by public @ref add.

+ 35 - 7
src/lib/dhcpsrv/host.cc

@@ -6,6 +6,7 @@
 
 #include <config.h>
 #include <dhcpsrv/host.h>
+#include <util/encode/hex.h>
 #include <util/strutil.h>
 #include <exceptions/exceptions.h>
 #include <sstream>
@@ -137,20 +138,47 @@ std::string
 Host::getIdentifierAsText() const {
     std::string txt;
     if (hw_address_) {
-        txt = "hwaddr=" + hw_address_->toText(false);
+        txt = getIdentifierAsText(IDENT_HWADDR, &hw_address_->hwaddr_[0],
+                                  hw_address_->hwaddr_.size());
+    } else if (duid_) {
+        txt = getIdentifierAsText(IDENT_DUID, &duid_->getDuid()[0],
+                                  duid_->getDuid().size());
     } else {
-        txt = "duid=";
-        if (duid_) {
-            txt += duid_->toText();
-        } else {
-            txt += "(none)";
-        }
+        txt = "(none)";
     }
 
     return (txt);
 
 }
 
+std::string
+Host::getIdentifierAsText(const IdentifierType& type, const uint8_t* value,
+                          const size_t length) {
+    // Length 0 doesn't make sense.
+    if (length == 0) {
+        isc_throw(BadValue, "invalid length 0 of the host identifier while"
+                  " converting the identifier to a textual form");
+    }
+
+    // Convert identifier into <type>=<value> form.
+    std::ostringstream s;
+    switch (type) {
+    case IDENT_HWADDR:
+        s << "hwaddr";
+        break;
+    case IDENT_DUID:
+        s << "duid";
+        break;
+    default:
+        isc_throw(BadValue, "requested conversion of the unsupported"
+                  " identifier into textual form");
+    }
+    std::vector<uint8_t> vec(value, value + length);
+    s << "=" << util::encode::encodeHex(vec);
+    return (s.str());
+}
+
+
 void
 Host::setIdentifier(const uint8_t* identifier, const size_t len,
                     const IdentifierType& type) {

+ 10 - 0
src/lib/dhcpsrv/host.h

@@ -307,6 +307,16 @@ public:
     /// @return text form of the identifier, including (duid= or mac=).
     std::string getIdentifierAsText() const;
 
+    /// @brief Returns host identifier in textual form.
+    ///
+    /// @param type Identifier type.
+    /// @param value Pointer to a buffer holding identifier.
+    /// @param length Length of the identifier.
+    /// @return Identifier in the form of <type>=<value>.
+    static std::string getIdentifierAsText(const IdentifierType& type,
+                                           const uint8_t* value,
+                                           const size_t length);
+
     /// @brief Sets new IPv4 subnet identifier.
     ///
     /// @param ipv4_subnet_id New subnet identifier.

+ 25 - 11
src/lib/dhcpsrv/hosts_messages.mes

@@ -1,4 +1,4 @@
-# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -76,10 +76,24 @@ subnet id and address. The arguments specify subnet id, address and
 found host details respectively.
 
 % HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST using subnet id %1 and address %2, found host: %3
-This debug message include the details of the host found using the
+This debug message includes the details of the host found using the
 subnet id and address. The arguments specify subnet id, address and
 found host details respectively.
 
+% HOSTS_CFG_GET_ONE_PREFIX get one host with reservation for prefix %1/%2
+This debug message is issued when starting to retrieve a host having a
+reservation for a specified prefix. The arguments specify a prefix and
+prefix length.
+
+% HOSTS_CFG_GET_ONE_PREFIX_HOST using prefix %1/%2, found host: %3
+This debug message includes the details of the host found using the
+specific prefix/prefix length. The arguments specify prefix, prefix
+length and host details respectively.
+
+% HOSTS_CFG_GET_ONE_PREFIX_NULL host not found using prefix %1/%2
+This debug messsage is issued when no host was found for a specified
+prefix and prefix length.
+
 % HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4 get one host with reservation for subnet id %1 and IPv4 address %2
 This debug message is issued when starting to retrieve a host connected to the
 specific subnet and having the specific IPv4 address reserved. The
@@ -106,19 +120,19 @@ subnet id and IPv6 address.
 This debug message is issued when no host was found using the specified
 subnet if and IPv6 address.
 
-% HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID get one host with %1 reservation for subnet id %2, HWADDR %3, DUID %4
-This debug message is issued when starting to retrieve the host holding IPv4 or
-IPv6 reservations, which is connected to the specific subnet and is
-identified by the specific HW address or DUID. The first argument
+% HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER get one host with %1 reservation for subnet id %2, identified by %3
+This debug message is issued when starting to retrieve a host holding
+IPv4 or IPv6 reservations, which is connected to a specific subnet and
+is identified by a specific unique identifier. The first argument
 identifies if the IPv4 or IPv6 reservation is desired.
 
-% HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID_HOST using subnet id %1, HWADDR %2 and DUID %3, found host: %4
-This debug message includes the details of the host found using the
-subnet id, HW address and/or DUID.
+% HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST using subnet id %1 and identifier %2, found host: %3
+This debug message includes the details of a host found using a
+subnet id and specific host identifier.
 
-% HOSTS_CFG_GET_ONE_SUBNET_ID_HWADDR_DUID_NULL host not found using subnet id %1, HW address %2 and DUID %3
+% HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL host not found using subnet id %1 and identifier %2
 This debug message is issued when no host was found using the specified
-subnet id, HW address and DUID.
+subnet id and host identifier.
 
 % HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4 trying alternate source for host using subnet id %1 and address %2
 This debug message is issued when the Host Manager doesn't find the

+ 75 - 34
src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc

@@ -105,17 +105,17 @@ HostPtr GenericHostDataSourceTest::initializeHost4(std::string address,
 }
 
 HostPtr GenericHostDataSourceTest::initializeHost6(std::string address,
-                                                   BaseHostDataSource::IdType identifier,
+                                                   Host::IdentifierType identifier,
                                                    bool prefix) {
     string ident;
     string ident_type;
 
     switch (identifier) {
-    case BaseHostDataSource::ID_HWADDR:
+    case Host::IDENT_HWADDR:
         ident = generateHWAddr();
         ident_type = "hw-address";
         break;
-    case BaseHostDataSource::ID_DUID:
+    case Host::IDENT_DUID:
         ident = generateDuid();
         ident_type = "duid";
         break;
@@ -416,8 +416,14 @@ void GenericHostDataSourceTest::testGet4ByHWAddr() {
     SubnetID subnet1 = host1->getIPv4SubnetID();
     SubnetID subnet2 = host2->getIPv4SubnetID();
 
-    ConstHostPtr from_hds1 = hdsptr_->get4(subnet1, host1->getHWAddress());
-    ConstHostPtr from_hds2 = hdsptr_->get4(subnet2, host2->getHWAddress());
+    ConstHostPtr from_hds1 = hdsptr_->get4(subnet1,
+                                           Host::IDENT_HWADDR,
+                                           &host1->getIdentifier()[0],
+                                           host1->getIdentifier().size());
+    ConstHostPtr from_hds2 = hdsptr_->get4(subnet2,
+                                           Host::IDENT_HWADDR,
+                                           &host2->getIdentifier()[0],
+                                           host2->getIdentifier().size());
 
     // Now let's check if we got what we expected.
     ASSERT_TRUE(from_hds1);
@@ -445,8 +451,15 @@ void GenericHostDataSourceTest::testGet4ByClientId() {
     SubnetID subnet1 = host1->getIPv4SubnetID();
     SubnetID subnet2 = host2->getIPv4SubnetID();
 
-    ConstHostPtr from_hds1 = hdsptr_->get4(subnet1, HWAddrPtr(), host1->getDuid());
-    ConstHostPtr from_hds2 = hdsptr_->get4(subnet2, HWAddrPtr(), host2->getDuid());
+    ConstHostPtr from_hds1 = hdsptr_->get4(subnet1,
+                                           Host::IDENT_DUID,
+                                           &host1->getIdentifier()[0],
+                                           host1->getIdentifier().size());
+
+    ConstHostPtr from_hds2 = hdsptr_->get4(subnet2,
+                                           Host::IDENT_DUID,
+                                           &host2->getIdentifier()[0],
+                                           host2->getIdentifier().size());
 
     // Now let's check if we got what we expected.
     ASSERT_TRUE(from_hds1);
@@ -472,10 +485,14 @@ void GenericHostDataSourceTest::testHWAddrNotClientId() {
     DuidPtr duid = HWAddrToDuid(host->getHWAddress());
 
     // Get the host by HW address (should succeed)
-    ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, host->getHWAddress(), DuidPtr());
+    ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, Host::IDENT_HWADDR,
+                                           &host->getIdentifier()[0],
+                                           host->getIdentifier().size());
 
     // Get the host by DUID (should fail)
-    ConstHostPtr by_duid   = hdsptr_->get4(subnet, HWAddrPtr(), duid);
+    ConstHostPtr by_duid   = hdsptr_->get4(subnet, Host::IDENT_DUID,
+                                           &host->getIdentifier()[0],
+                                           host->getIdentifier().size());
 
     // Now let's check if we got what we expected.
     EXPECT_TRUE(by_hwaddr);
@@ -499,10 +516,15 @@ void GenericHostDataSourceTest::testClientIdNotHWAddr() {
     HWAddrPtr hwaddr = DuidToHWAddr(host->getDuid());
 
     // Get the host by DUID (should succeed)
-    ConstHostPtr by_duid   = hdsptr_->get4(subnet, HWAddrPtr(), host->getDuid());
+    ConstHostPtr by_duid   = hdsptr_->get4(subnet, Host::IDENT_DUID,
+                                           &host->getIdentifier()[0],
+                                           host->getIdentifier().size());
+
 
     // Get the host by HW address (should fail)
-    ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, hwaddr, DuidPtr());
+    ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, Host::IDENT_HWADDR,
+                                           &host->getIdentifier()[0],
+                                           host->getIdentifier().size());
 
     // Now let's check if we got what we expected.
     EXPECT_TRUE(by_duid);
@@ -588,7 +610,10 @@ GenericHostDataSourceTest::testMultipleSubnets(int subnets, bool hwaddr) {
         EXPECT_EQ(i + 1000, from_hds->getIPv4SubnetID());
 
         // Try to retrieve the host by either HW address of client-id
-        from_hds = hdsptr_->get4(i + 1000, host->getHWAddress(), host->getDuid());
+        from_hds = hdsptr_->get4(i + 1000,
+                                 hwaddr ? Host::IDENT_HWADDR : Host::IDENT_DUID,
+                                 &host->getIdentifier()[0],
+                                 host->getIdentifier().size());
         ASSERT_TRUE(from_hds);
         EXPECT_EQ(i + 1000, from_hds->getIPv4SubnetID());
     }
@@ -606,8 +631,10 @@ GenericHostDataSourceTest::testMultipleSubnets(int subnets, bool hwaddr) {
     }
 
     // Finally, check that the hosts can be retrived by HW address or DUID
-    ConstHostCollection all_by_id = hdsptr_->getAll(host->getHWAddress(),
-                                                    host->getDuid());
+    ConstHostCollection all_by_id =
+        hdsptr_->getAll(hwaddr ? Host::IDENT_HWADDR : Host::IDENT_DUID,
+                        &host->getIdentifier()[0],
+                        host->getIdentifier().size());
     ASSERT_EQ(subnets, all_by_id.size());
 
     // Check that the returned values are as expected.
@@ -624,8 +651,8 @@ void GenericHostDataSourceTest::testGet6ByHWAddr() {
     ASSERT_TRUE(hdsptr_);
 
     // Create a host reservations.
-    HostPtr host1 = initializeHost6("2001:db8::1", BaseHostDataSource::ID_HWADDR, true);
-    HostPtr host2 = initializeHost6("2001:db8::2", BaseHostDataSource::ID_HWADDR, true);
+    HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_HWADDR, true);
+    HostPtr host2 = initializeHost6("2001:db8::2", Host::IDENT_HWADDR, true);
 
     // Sanity check: make sure the hosts have different HW addresses.
     ASSERT_TRUE(host1->getHWAddress());
@@ -640,8 +667,13 @@ void GenericHostDataSourceTest::testGet6ByHWAddr() {
     SubnetID subnet1 = host1->getIPv6SubnetID();
     SubnetID subnet2 = host2->getIPv6SubnetID();
 
-    ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, DuidPtr(), host1->getHWAddress());
-    ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, DuidPtr(), host2->getHWAddress());
+    ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, Host::IDENT_HWADDR,
+                                           &host1->getIdentifier()[0],
+                                           host1->getIdentifier().size());
+
+    ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, Host::IDENT_HWADDR,
+                                           &host2->getIdentifier()[0],
+                                           host2->getIdentifier().size());
 
     // Now let's check if we got what we expected.
     ASSERT_TRUE(from_hds1);
@@ -655,8 +687,8 @@ void GenericHostDataSourceTest::testGet6ByClientId() {
     ASSERT_TRUE(hdsptr_);
 
     // Create a host reservations.
-    HostPtr host1 = initializeHost6("2001:db8::1", BaseHostDataSource::ID_DUID, true);
-    HostPtr host2 = initializeHost6("2001:db8::2", BaseHostDataSource::ID_DUID, true);
+    HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
+    HostPtr host2 = initializeHost6("2001:db8::2", Host::IDENT_DUID, true);
 
     // Sanity check: make sure the hosts have different HW addresses.
     ASSERT_TRUE(host1->getDuid());
@@ -671,8 +703,13 @@ void GenericHostDataSourceTest::testGet6ByClientId() {
     SubnetID subnet1 = host1->getIPv6SubnetID();
     SubnetID subnet2 = host2->getIPv6SubnetID();
 
-    ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, host1->getDuid(), HWAddrPtr());
-    ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, host2->getDuid(), HWAddrPtr());
+    ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, Host::IDENT_DUID,
+                                           &host1->getIdentifier()[0],
+                                           host1->getIdentifier().size());
+
+    ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, Host::IDENT_DUID,
+                                           &host2->getIdentifier()[0],
+                                           host2->getIdentifier().size());
 
     // Now let's check if we got what we expected.
     ASSERT_TRUE(from_hds1);
@@ -682,7 +719,7 @@ void GenericHostDataSourceTest::testGet6ByClientId() {
 }
 
 void
-GenericHostDataSourceTest::testSubnetId6(int subnets, BaseHostDataSource::IdType id) {
+GenericHostDataSourceTest::testSubnetId6(int subnets, Host::IdentifierType id) {
 
     // Make sure we have a pointer to the host data source.
     ASSERT_TRUE(hdsptr_);
@@ -709,8 +746,8 @@ GenericHostDataSourceTest::testSubnetId6(int subnets, BaseHostDataSource::IdType
     }
 
     // Check that the hosts can all be retrived by HW address or DUID
-    ConstHostCollection all_by_id = hdsptr_->getAll(host->getHWAddress(),
-                                                    host->getDuid());
+    ConstHostCollection all_by_id = hdsptr_->getAll(id, &host->getIdentifier()[0],
+                                                    host->getIdentifier().size());
     ASSERT_EQ(subnets, all_by_id.size());
 
     // Check that the returned values are as expected.
@@ -722,7 +759,7 @@ GenericHostDataSourceTest::testSubnetId6(int subnets, BaseHostDataSource::IdType
     }
 }
 
-void GenericHostDataSourceTest::testGetByIPv6(BaseHostDataSource::IdType id,
+void GenericHostDataSourceTest::testGetByIPv6(Host::IdentifierType id,
                                               bool prefix) {
     // Make sure we have a pointer to the host data source.
     ASSERT_TRUE(hdsptr_);
@@ -770,7 +807,7 @@ void GenericHostDataSourceTest::testAddDuplicate6WithSameDUID() {
     ASSERT_TRUE(hdsptr_);
 
     // Create a host reservations.
-    HostPtr host = initializeHost6("2001:db8::1", BaseHostDataSource::ID_DUID, true);
+    HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
 
     // Add this reservation once.
     ASSERT_NO_THROW(hdsptr_->add(host));
@@ -784,7 +821,7 @@ void GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() {
     ASSERT_TRUE(hdsptr_);
 
     // Create a host reservations.
-    HostPtr host = initializeHost6("2001:db8::1", BaseHostDataSource::ID_HWADDR, true);
+    HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_HWADDR, true);
 
     // Add this reservation once.
     ASSERT_NO_THROW(hdsptr_->add(host));
@@ -812,7 +849,7 @@ void GenericHostDataSourceTest::testAddr6AndPrefix(){
     ASSERT_TRUE(hdsptr_);
 
     // Create a host reservations with prefix reservation (prefix = true)
-    HostPtr host = initializeHost6("2001:db8::1", BaseHostDataSource::ID_DUID, true);
+    HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
 
     // Create IPv6 reservation (for an address) and add it to the host
     IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::2"), 128);
@@ -822,13 +859,17 @@ void GenericHostDataSourceTest::testAddr6AndPrefix(){
     ASSERT_NO_THROW(hdsptr_->add(host));
 
     // Get this host by DUID
-    ConstHostPtr from_hds = hdsptr_->get6(host->getIPv6SubnetID(), host->getDuid(), HWAddrPtr());
+    ConstHostPtr from_hds = hdsptr_->get6(host->getIPv6SubnetID(),
+                                          Host::IDENT_DUID,
+                                          &host->getIdentifier()[0],
+                                          host->getIdentifier().size());
 
     // Make sure we got something back
     ASSERT_TRUE(from_hds);
 
     // Check if reservations are the same
-    compareReservations6(host->getIPv6Reservations(), from_hds->getIPv6Reservations());
+    compareReservations6(host->getIPv6Reservations(),
+                         from_hds->getIPv6Reservations());
 }
 
 void GenericHostDataSourceTest::testMultipleReservations(){
@@ -836,7 +877,7 @@ void GenericHostDataSourceTest::testMultipleReservations(){
     ASSERT_TRUE(hdsptr_);
     uint8_t len = 128;
 
-    HostPtr host = initializeHost6("2001:db8::1", BaseHostDataSource::ID_DUID, false);
+    HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
 
     // Add some reservations
     IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), len);
@@ -866,8 +907,8 @@ void GenericHostDataSourceTest::testMultipleReservationsDifferentOrder(){
     ASSERT_TRUE(hdsptr_);
     uint8_t len = 128;
 
-    HostPtr host1 = initializeHost6("2001:db8::1", BaseHostDataSource::ID_DUID, false);
-    HostPtr host2 = initializeHost6("2001:db8::1", BaseHostDataSource::ID_DUID, false);
+    HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
+    HostPtr host2 = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
 
     // Add some reservations
     IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), len);

+ 7 - 6
src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h

@@ -8,6 +8,7 @@
 #define GENERIC_HOST_DATA_SOURCE_UNITTEST_H
 
 #include <dhcpsrv/base_host_data_source.h>
+#include <dhcpsrv/host.h>
 #include <dhcp/classify.h>
 #include <gtest/gtest.h>
 #include <vector>
@@ -46,11 +47,11 @@ public:
     /// @brief Creates a host reservation for specified IPv6 address.
     ///
     /// @param address IPv6 address to be reserved
-    /// @param id type of identifier (ID_DUID or ID_HWADDR are supported)
+    /// @param id type of identifier (IDENT_DUID or IDENT_HWADDR are supported)
     /// @param prefix reservation type (true = prefix, false = address)
     ///
     /// @return generated Host object
-    HostPtr initializeHost6(std::string address, BaseHostDataSource::IdType id,
+    HostPtr initializeHost6(std::string address, Host::IdentifierType id,
                             bool prefix);
 
     /// @brief Generates a hardware address in text version.
@@ -183,9 +184,9 @@ public:
     ///        checks that they can be retrieved properly.
     ///
     /// Uses gtest macros to report failures.
-    /// @param id type of the identifier to be used (HWAddr or DUID)
+    /// @param id type of the identifier to be used (IDENT_HWADDR or IDENT_DUID)
     /// @param prefix true - reserve IPv6 prefix, false - reserve IPv6 address
-    void testGetByIPv6(BaseHostDataSource::IdType id, bool prefix);
+    void testGetByIPv6(Host::IdentifierType id, bool prefix);
 
     /// @brief Test that hosts can be retrieved by hardware address.
     ///
@@ -216,8 +217,8 @@ public:
     /// Uses gtest macros to report failures.
     ///
     /// @param subnets number of subnets to test
-    /// @param id identifier type (ID_HWADDR or ID_DUID)
-    void testSubnetId6(int subnets, BaseHostDataSource::IdType id);
+    /// @param id identifier type (IDENT_HWADDR or IDENT_DUID)
+    void testSubnetId6(int subnets, Host::IdentifierType id);
 
     /// @brief Test if the duplicate host with same DUID can't be inserted.
     ///

+ 25 - 0
src/lib/dhcpsrv/tests/host_mgr_unittest.cc

@@ -216,17 +216,42 @@ TEST_F(HostMgrTest, get6ByPrefix) {
     ConstHostPtr host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
     ASSERT_FALSE(host);
 
+    // Add a host with a reservation for a prefix 2001:db8:1::/64.
     HostPtr new_host(new Host(duids_[0]->toText(), "duid", SubnetID(1),
                               SubnetID(2), IOAddress("0.0.0.0")));
     new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
                                        IOAddress("2001:db8:1::"), 64));
     getCfgHosts()->add(new_host);
+
+    // Add another host having a reservation for prefix 2001:db8:1:0:6::/72.
+    new_host.reset(new Host(duids_[1]->toText(), "duid", SubnetID(2),
+                            SubnetID(3), IOAddress::IPV4_ZERO_ADDRESS()));
+    new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
+                                       IOAddress("2001:db8:1:0:6::"), 72));
+    getCfgHosts()->add(new_host);
     CfgMgr::instance().commit();
 
+    // Retrieve first reservation.
     host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
     ASSERT_TRUE(host);
     EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
     IOAddress("2001:db8:1::"), 64)));
+
+    // Make sure the first reservation is not retrieved when the prefix
+    // length is incorrect.
+    host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 72);
+    EXPECT_FALSE(host);
+
+    // Retrieve second reservation.
+    host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 72);
+    ASSERT_TRUE(host);
+    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
+    IOAddress("2001:db8:1:0:6::"), 72)));
+
+    // Make sure the second reservation is not retrieved when the prefix
+    // length is incorrect.
+    host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 64);
+    EXPECT_FALSE(host);
 }
 
 } // end of anonymous namespace

+ 9 - 7
src/lib/dhcpsrv/tests/host_unittest.cc

@@ -631,16 +631,18 @@ TEST(HostTest, addOptions6) {
     EXPECT_TRUE(options->empty());
 }
 
+// This test verifies that it is possible to retrieve a textual
+// representation of the host identifier.
 TEST(HostTest, getIdentifierAsText) {
     Host host1("01:02:03:04:05:06", "hw-address",
                SubnetID(1), SubnetID(2),
                IOAddress("192.0.2.3"));
-    EXPECT_EQ("hwaddr=01:02:03:04:05:06", host1.getIdentifierAsText());
+    EXPECT_EQ("hwaddr=010203040506", host1.getIdentifierAsText());
 
     Host host2("0a:0b:0c:0d:0e:0f:ab:cd:ef", "duid",
                SubnetID(1), SubnetID(2),
                IOAddress("192.0.2.3"));
-    EXPECT_EQ("duid=0a:0b:0c:0d:0e:0f:ab:cd:ef",
+    EXPECT_EQ("duid=0A0B0C0D0E0FABCDEF",
               host2.getIdentifierAsText());
 }
 
@@ -666,7 +668,7 @@ TEST(HostTest, toText) {
     );
 
     // Make sure that the output is correct,
-    EXPECT_EQ("hwaddr=01:02:03:04:05:06 ipv4_subnet_id=1 ipv6_subnet_id=2"
+    EXPECT_EQ("hwaddr=010203040506 ipv4_subnet_id=1 ipv6_subnet_id=2"
               " hostname=myhost.example.com"
               " ipv4_reservation=192.0.2.3"
               " ipv6_reservation0=2001:db8:1::cafe"
@@ -680,7 +682,7 @@ TEST(HostTest, toText) {
     host->removeIPv4Reservation();
     host->setIPv4SubnetID(0);
 
-    EXPECT_EQ("hwaddr=01:02:03:04:05:06 ipv6_subnet_id=2"
+    EXPECT_EQ("hwaddr=010203040506 ipv6_subnet_id=2"
               " hostname=(empty) ipv4_reservation=(no)"
               " ipv6_reservation0=2001:db8:1::cafe"
               " ipv6_reservation1=2001:db8:1::1"
@@ -695,14 +697,14 @@ TEST(HostTest, toText) {
                                         IOAddress::IPV4_ZERO_ADDRESS(),
                                         "myhost")));
 
-    EXPECT_EQ("duid=11:12:13:14:15 hostname=myhost ipv4_reservation=(no)"
+    EXPECT_EQ("duid=1112131415 hostname=myhost ipv4_reservation=(no)"
               " ipv6_reservations=(none)", host->toText());
 
     // Add some classes.
     host->addClientClass4("modem");
     host->addClientClass4("router");
 
-    EXPECT_EQ("duid=11:12:13:14:15 hostname=myhost ipv4_reservation=(no)"
+    EXPECT_EQ("duid=1112131415 hostname=myhost ipv4_reservation=(no)"
               " ipv6_reservations=(none)"
               " dhcp4_class0=modem dhcp4_class1=router",
               host->toText());
@@ -710,7 +712,7 @@ TEST(HostTest, toText) {
     host->addClientClass6("hub");
     host->addClientClass6("device");
 
-    EXPECT_EQ("duid=11:12:13:14:15 hostname=myhost ipv4_reservation=(no)"
+    EXPECT_EQ("duid=1112131415 hostname=myhost ipv4_reservation=(no)"
               " ipv6_reservations=(none)"
               " dhcp4_class0=modem dhcp4_class1=router"
               " dhcp6_class0=device dhcp6_class1=hub",

+ 6 - 5
src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc

@@ -9,6 +9,7 @@
 #include <asiolink/io_address.h>
 #include <dhcpsrv/tests/test_utils.h>
 #include <exceptions/exceptions.h>
+#include <dhcpsrv/host.h>
 #include <dhcpsrv/mysql_connection.h>
 #include <dhcpsrv/mysql_host_data_source.h>
 #include <dhcpsrv/tests/generic_host_data_source_unittest.h>
@@ -272,25 +273,25 @@ TEST_F(MySqlHostDataSourceTest, DISABLED_hwaddrOrClientId2) {
 // Test verifies that host with IPv6 address and DUID can be added and
 // later retrieved by IPv6 address.
 TEST_F(MySqlHostDataSourceTest, get6AddrWithDuid) {
-    testGetByIPv6(BaseHostDataSource::ID_DUID, false);
+    testGetByIPv6(Host::IDENT_DUID, false);
 }
 
 // Test verifies that host with IPv6 address and HWAddr can be added and
 // later retrieved by IPv6 address.
 TEST_F(MySqlHostDataSourceTest, get6AddrWithHWAddr) {
-    testGetByIPv6(BaseHostDataSource::ID_HWADDR, false);
+    testGetByIPv6(Host::IDENT_HWADDR, false);
 }
 
 // Test verifies that host with IPv6 prefix and DUID can be added and
 // later retrieved by IPv6 prefix.
 TEST_F(MySqlHostDataSourceTest, get6PrefixWithDuid) {
-    testGetByIPv6(BaseHostDataSource::ID_DUID, true);
+    testGetByIPv6(Host::IDENT_DUID, true);
 }
 
 // Test verifies that host with IPv6 prefix and HWAddr can be added and
 // later retrieved by IPv6 prefix.
 TEST_F(MySqlHostDataSourceTest, get6PrefixWithHWaddr) {
-    testGetByIPv6(BaseHostDataSource::ID_HWADDR, true);
+    testGetByIPv6(Host::IDENT_HWADDR, true);
 }
 
 // Test verifies if a host reservation can be added and later retrieved by
@@ -373,7 +374,7 @@ TEST_F(MySqlHostDataSourceTest, multipleSubnetsClientId) {
 // Insert 10 host reservations for different subnets. Make sure that
 // get6(subnet-id, ...) calls return correct reservation.
 TEST_F(MySqlHostDataSourceTest, subnetId6) {
-    testSubnetId6(10, BaseHostDataSource::ID_HWADDR);
+    testSubnetId6(10, Host::IDENT_HWADDR);
 }
 
 // Test if the duplicate host instances can't be inserted. The test logic is as