Parcourir la source

[3562] Added more tests for HostReservationParser class.

Marcin Siodelski il y a 10 ans
Parent
commit
7d63012c02

+ 21 - 3
src/lib/dhcpsrv/host.cc

@@ -30,7 +30,7 @@ void
 IPv6Resrv::set(const asiolink::IOAddress& prefix, const uint8_t prefix_len) {
     if (!prefix.isV6() || prefix.isV6Multicast()) {
         isc_throw(isc::BadValue, "invalid prefix '" << prefix
-                  << " for new IPv6 reservation");
+                  << "' for new IPv6 reservation");
 
     } else if (prefix_len > 128) {
         isc_throw(isc::BadValue, "invalid prefix length '"
@@ -61,12 +61,16 @@ Host::Host(const uint8_t* identifier, const size_t identifier_len,
            const std::string& dhcp4_client_classes,
            const std::string& dhcp6_client_classes)
     : hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
-      ipv6_subnet_id_(ipv6_subnet_id), ipv4_reservation_(ipv4_reservation),
+      ipv6_subnet_id_(ipv6_subnet_id),
+      ipv4_reservation_(asiolink::IOAddress("0.0.0.0")),
        hostname_(hostname), dhcp4_client_classes_(dhcp4_client_classes),
        dhcp6_client_classes_(dhcp6_client_classes) {
 
     // Initialize HWAddr or DUID
     setIdentifier(identifier, identifier_len, identifier_type);
+
+    // Validate and set IPv4 address reservation.
+    setIPv4Reservation(ipv4_reservation);
 }
 
 Host::Host(const std::string& identifier, const std::string& identifier_name,
@@ -76,12 +80,16 @@ Host::Host(const std::string& identifier, const std::string& identifier_name,
            const std::string& dhcp4_client_classes,
            const std::string& dhcp6_client_classes)
     : hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
-      ipv6_subnet_id_(ipv6_subnet_id), ipv4_reservation_(ipv4_reservation),
+      ipv6_subnet_id_(ipv6_subnet_id),
+      ipv4_reservation_(asiolink::IOAddress("0.0.0.0")),
       hostname_(hostname), dhcp4_client_classes_(dhcp4_client_classes),
       dhcp6_client_classes_(dhcp6_client_classes) {
 
     // Initialize HWAddr or DUID
     setIdentifier(identifier, identifier_name);
+
+    // Validate and set IPv4 address reservation.
+    setIPv4Reservation(ipv4_reservation);
 }
 
 const std::vector<uint8_t>&
@@ -139,6 +147,16 @@ Host::setIdentifier(const std::string& identifier, const std::string& name) {
 }
 
 void
+Host::setIPv4Reservation(const asiolink::IOAddress& address) {
+    if (!address.isV4()) {
+        isc_throw(isc::BadValue, "address '" << address << "' is not a valid"
+                  " IPv4 address");
+    }
+    ipv4_reservation_ = address;
+}
+
+
+void
 Host::addReservation(const IPv6Resrv& reservation) {
     ipv6_reservations_.insert(IPv6ResrvTuple(reservation.getType(),
                                              reservation));

+ 3 - 3
src/lib/dhcpsrv/host.h

@@ -316,9 +316,9 @@ public:
     /// The new reservation removes a previous reservation.
     ///
     /// @param address Address to be reserved for the client.
-    void setIPv4Reservation(const asiolink::IOAddress& address) {
-        ipv4_reservation_ = address;
-    }
+    ///
+    /// @throw isc::BadValue if the provided address is not an IPv4 address.
+    void setIPv4Reservation(const asiolink::IOAddress& address);
 
     /// @brief Returns reserved IPv4 address.
     ///

+ 2 - 1
src/lib/dhcpsrv/host_reservation_parser.cc

@@ -101,7 +101,8 @@ HostReservationParser4::build(isc::data::ConstElementPtr reservation_data) {
     BOOST_FOREACH(ConfigPair element, reservation_data->mapValue()) {
         try {
             if (element.first == "ip-address") {
-                host_->setIPv4Reservation(IOAddress(element.second->stringValue()));
+                host_->setIPv4Reservation(IOAddress(element.second->
+                                                    stringValue()));
             }
         }
         catch (const std::exception& ex) {

+ 20 - 9
src/lib/dhcpsrv/tests/cfg_hosts_unittest.cc

@@ -241,15 +241,21 @@ TEST_F(CfgHostsTest, get6) {
     // Add hosts.
     for (int i = 0; i < 25; ++i) {
         // Add host identified by HW address.
-        cfg.add(HostPtr(new Host(hwaddrs_[i]->toText(false),
-                                 "hw-address",
-                                 SubnetID(10), SubnetID(1 + i % 2),
-                                 increase(IOAddress("2001:db8:1::1"), i))));
+        HostPtr host = HostPtr(new Host(hwaddrs_[i]->toText(false),
+                                        "hw-address",
+                                        SubnetID(10), SubnetID(1 + i % 2),
+                                        IOAddress("0.0.0.0")));
+        host->addReservation(IPv6Resrv(increase(IOAddress("2001:db8:1::1"),
+                                                i)));
+        cfg.add(host);
 
         // Add host identified by DUID.
-        cfg.add(HostPtr(new Host(duids_[i]->toText(), "duid",
-                                 SubnetID(10), SubnetID(1 + i % 2),
-                                 increase(IOAddress("2001:db8:2::1"), i))));
+        host = HostPtr(new Host(duids_[i]->toText(), "duid",
+                                SubnetID(10), SubnetID(1 + i % 2),
+                                IOAddress("0.0.0.0")));
+        host->addReservation(IPv6Resrv(increase(IOAddress("2001:db8:2::1"),
+                                                i)));
+        cfg.add(host);
     }
 
     for (int i = 0; i < 25; ++i) {
@@ -260,8 +266,11 @@ TEST_F(CfgHostsTest, get6) {
                                 hwaddrs_[i]);
         ASSERT_TRUE(host);
         EXPECT_EQ(1 + i % 2, host->getIPv6SubnetID());
+        IPv6ResrvRange reservations =
+            host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
+        ASSERT_EQ(1, std::distance(reservations.first, reservations.second));
         EXPECT_EQ(increase(IOAddress("2001:db8:1::1"), i),
-                  host->getIPv4Reservation());
+                  reservations.first->second.getPrefix());
 
         // Retrieve host by DUID. The HW address is non-null but there is no
         // reservation made for the HW address so the reservation is returned
@@ -269,8 +278,10 @@ TEST_F(CfgHostsTest, get6) {
         host = cfg.get6(SubnetID(1 + i % 2), duids_[i], hwaddrs_[i + 25]);
         ASSERT_TRUE(host);
         EXPECT_EQ(1 + i % 2, host->getIPv6SubnetID());
+        reservations = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
+        ASSERT_EQ(1, std::distance(reservations.first, reservations.second));
         EXPECT_EQ(increase(IOAddress("2001:db8:2::1"), i),
-                  host->getIPv4Reservation());
+                  reservations.first->second.getPrefix());
     }
 
     // Also check that when the get6 finds multiple Host objects that fulfil

+ 53 - 0
src/lib/dhcpsrv/tests/host_reservation_parser_unittest.cc

@@ -62,6 +62,9 @@ protected:
         return (false);
     }
 
+    void
+    expectFailure(const HostReservationParser& parser,
+                  const std::string& config) const;
 
     /// @brief HW Address object used by tests.
     HWAddrPtr hwaddr_;
@@ -138,6 +141,43 @@ TEST_F(HostReservationParserTest, dhcp4DUID) {
     EXPECT_TRUE(hosts[0]->getHostname().empty());
 }
 
+// This test verifies that the configuration parser for host reservations
+// throws an exception when IPv6 address is specified for IPv4 address
+// reservation.
+TEST_F(HostReservationParserTest, dhcp4IPv6Address) {
+    std::string config = "{ \"hw-address\": \"01:02:03:04:05:06\","
+        "\"ip-address\": \"2001:db8:1::1\" }";
+
+    ElementPtr config_element = Element::fromJSON(config);
+
+    HostReservationParser4 parser(SubnetID(10));
+    EXPECT_THROW(parser.build(config_element), DhcpConfigError);
+}
+
+// This test verifies that the configuration parser for host reservations
+// throws an exception when no HW address nor DUID is specified.
+TEST_F(HostReservationParserTest, noIdentifier) {
+    std::string config = "{ \"ip-address\": \"192.0.2.112\","
+        "\"hostname\": \"\" }";
+
+    ElementPtr config_element = Element::fromJSON(config);
+
+    HostReservationParser4 parser(SubnetID(10));
+    EXPECT_THROW(parser.build(config_element), DhcpConfigError);
+}
+
+// This test verifies that the configuration parser for host reservations
+// throws an exception when invalid IP address is specified.
+TEST_F(HostReservationParserTest, malformedAddress) {
+    std::string config = "{ \"hw-address\": \"01:02:03:04:05:06\","
+        "\"ip-address\": \"192.0.2.bogus\" }";
+
+    ElementPtr config_element = Element::fromJSON(config);
+
+    HostReservationParser4 parser(SubnetID(10));
+    EXPECT_THROW(parser.build(config_element), DhcpConfigError);
+}
+
 // This test verfies that the parser can parse the IPv6 reservation entry for
 // which hw-address is a host identifier.
 TEST_F(HostReservationParserTest, dhcp6HWaddr) {
@@ -218,5 +258,18 @@ TEST_F(HostReservationParserTest, dhcp6DUID) {
     ASSERT_EQ(0, std::distance(prefixes.first, prefixes.second));
 }
 
+// This test verifies that the configuration parser throws an exception
+// when IPv4 address is specified for IPv6 reservation.
+TEST_F(HostReservationParserTest, dhcp6IPv4Address) {
+    std::string config = "{ \"duid\": \"01:02:03:04:05:06:07:08:09:0A\","
+        "\"ip-addresses\": [ \"192.0.2.3\", \"2001:db8:1::200\" ],"
+        "\"prefixes\": [ ] }";
+
+    ElementPtr config_element = Element::fromJSON(config);
+
+    HostReservationParser6 parser(SubnetID(12));
+    EXPECT_THROW(parser.build(config_element), DhcpConfigError);
+}
+
 
 } // end of anonymous namespace

+ 4 - 0
src/lib/dhcpsrv/tests/host_unittest.cc

@@ -380,6 +380,10 @@ TEST(HostTest, setValues) {
     EXPECT_EQ(234, host->getIPv6SubnetID());
     EXPECT_EQ("10.0.0.1", host->getIPv4Reservation().toText());
     EXPECT_EQ("other-host.example.org", host->getHostname());
+
+    // An IPv6 address can't be used for IPv4 reservations.
+    EXPECT_THROW(host->setIPv4Reservation(IOAddress("2001:db8:1::1")),
+                 isc::BadValue);
 }
 
 // Test that Host constructors initialize client classes from string.