Browse Source

[3688] Host reservation parser doesn't allow for 0 or bcast address.

Marcin Siodelski 10 years ago
parent
commit
9650ed49bb

+ 17 - 6
src/lib/dhcpsrv/host.cc

@@ -83,15 +83,17 @@ Host::Host(const uint8_t* identifier, const size_t identifier_len,
            const std::string& dhcp6_client_classes)
     : hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
       ipv6_subnet_id_(ipv6_subnet_id),
-      ipv4_reservation_(asiolink::IOAddress("0.0.0.0")),
+      ipv4_reservation_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
        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);
+    if (!ipv4_reservation.isV4Zero()) {
+        // Validate and set IPv4 address reservation.
+        setIPv4Reservation(ipv4_reservation);
+    }
 }
 
 Host::Host(const std::string& identifier, const std::string& identifier_name,
@@ -102,15 +104,17 @@ Host::Host(const std::string& identifier, const std::string& identifier_name,
            const std::string& dhcp6_client_classes)
     : hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
       ipv6_subnet_id_(ipv6_subnet_id),
-      ipv4_reservation_(asiolink::IOAddress("0.0.0.0")),
+      ipv4_reservation_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
       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);
+    if (!ipv4_reservation.isV4Zero()) {
+        // Validate and set IPv4 address reservation.
+        setIPv4Reservation(ipv4_reservation);
+    }
 }
 
 const std::vector<uint8_t>&
@@ -172,10 +176,17 @@ Host::setIPv4Reservation(const asiolink::IOAddress& address) {
     if (!address.isV4()) {
         isc_throw(isc::BadValue, "address '" << address << "' is not a valid"
                   " IPv4 address");
+    } else if (address.isV4Zero() || address.isV4Bcast()) {
+        isc_throw(isc::BadValue, "must not make reservation for the '"
+                  << address << "' address");
     }
     ipv4_reservation_ = address;
 }
 
+void
+Host::removeIPv4Reservation() {
+    ipv4_reservation_ = asiolink::IOAddress::IPV4_ZERO_ADDRESS();
+}
 
 void
 Host::addReservation(const IPv6Resrv& reservation) {

+ 7 - 1
src/lib/dhcpsrv/host.h

@@ -337,9 +337,15 @@ public:
     ///
     /// @param address Address to be reserved for the client.
     ///
-    /// @throw isc::BadValue if the provided address is not an IPv4 address.
+    /// @throw isc::BadValue if the provided address is not an IPv4 address,
+    /// is a 0 address or broadcast address.
     void setIPv4Reservation(const asiolink::IOAddress& address);
 
+    /// @brief Removes the IPv4 reservation.
+    ///
+    /// Sets the IPv4 reserved address to 0.
+    void removeIPv4Reservation();
+
     /// @brief Returns reserved IPv4 address.
     ///
     /// @return IPv4 address or 0.0.0.0 if no IPv4 reservation specified.

+ 25 - 1
src/lib/dhcpsrv/tests/host_reservation_parser_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -249,6 +249,30 @@ TEST_F(HostReservationParserTest, malformedAddress) {
     EXPECT_THROW(parser.build(config_element), DhcpConfigError);
 }
 
+// This test verifies that the configuration parser for host reservations
+// throws an exception when zero IP address is specified.
+TEST_F(HostReservationParserTest, zeroAddress) {
+    std::string config = "{ \"hw-address\": \"01:02:03:04:05:06\","
+        "\"ip-address\": \"0.0.0.0\" }";
+
+    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 broadcast IP address is specified.
+TEST_F(HostReservationParserTest, bcastAddress) {
+    std::string config = "{ \"hw-address\": \"01:02:03:04:05:06\","
+        "\"ip-address\": \"255.255.255.255\" }";
+
+    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) {

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

@@ -427,9 +427,20 @@ TEST(HostTest, setValues) {
     EXPECT_EQ("10.0.0.1", host->getIPv4Reservation().toText());
     EXPECT_EQ("other-host.example.org", host->getHostname());
 
+    // Remove IPv4 reservation.
+    host->removeIPv4Reservation();
+    EXPECT_EQ(IOAddress::IPV4_ZERO_ADDRESS(), host->getIPv4Reservation());
+
     // An IPv6 address can't be used for IPv4 reservations.
     EXPECT_THROW(host->setIPv4Reservation(IOAddress("2001:db8:1::1")),
                  isc::BadValue);
+    // Zero address can't be set, the removeIPv4Reservation should be
+    // used intead.
+    EXPECT_THROW(host->setIPv4Reservation(IOAddress::IPV4_ZERO_ADDRESS()),
+                 isc::BadValue);
+    // Broadcast address can't be set.
+    EXPECT_THROW(host->setIPv4Reservation(IOAddress::IPV4_BCAST_ADDRESS()),
+                 isc::BadValue);
 }
 
 // Test that Host constructors initialize client classes from string.