Parcourir la source

[3281] Config manager checks for subnet id duplications.

Marcin Siodelski il y a 11 ans
Parent
commit
17282104c6
3 fichiers modifiés avec 89 ajouts et 0 suppressions
  1. 33 0
      src/lib/dhcpsrv/cfgmgr.cc
  2. 21 0
      src/lib/dhcpsrv/cfgmgr.h
  3. 35 0
      src/lib/dhcpsrv/tests/cfgmgr_unittest.cc

+ 33 - 0
src/lib/dhcpsrv/cfgmgr.cc

@@ -219,6 +219,11 @@ void CfgMgr::addSubnet6(const Subnet6Ptr& subnet) {
     /// @todo: Check that this new subnet does not cross boundaries of any
     /// @todo: Check that this new subnet does not cross boundaries of any
     /// other already defined subnet.
     /// other already defined subnet.
     /// @todo: Check that there is no subnet with the same interface-id
     /// @todo: Check that there is no subnet with the same interface-id
+    if (isDuplicate(*subnet)) {
+        isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv6 subnet '"
+                  << subnet->getID() << "' is the same as ID of an existing"
+                  " subnet");
+    }
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET6)
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET6)
               .arg(subnet->toText());
               .arg(subnet->toText());
     subnets6_.push_back(subnet);
     subnets6_.push_back(subnet);
@@ -282,6 +287,11 @@ CfgMgr::getSubnet4(const std::string& iface_name,
 void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {
 void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {
     /// @todo: Check that this new subnet does not cross boundaries of any
     /// @todo: Check that this new subnet does not cross boundaries of any
     /// other already defined subnet.
     /// other already defined subnet.
+    if (isDuplicate(*subnet)) {
+        isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv4 subnet '"
+                  << subnet->getID() << "' is the same as ID of an existing"
+                  " subnet");
+    }
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET4)
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET4)
               .arg(subnet->toText());
               .arg(subnet->toText());
     subnets4_.push_back(subnet);
     subnets4_.push_back(subnet);
@@ -377,6 +387,29 @@ CfgMgr::isIfaceListedActive(const std::string& iface) const {
     return (false);
     return (false);
 }
 }
 
 
+bool
+CfgMgr::isDuplicate(const Subnet4& subnet) const {
+    for (Subnet4Collection::const_iterator subnet_it = subnets4_.begin();
+         subnet_it != subnets4_.end(); ++subnet_it) {
+        if ((*subnet_it)->getID() == subnet.getID()) {
+            return (true);
+        }
+    }
+    return (false);
+}
+
+bool
+CfgMgr::isDuplicate(const Subnet6& subnet) const {
+    for (Subnet6Collection::const_iterator subnet_it = subnets6_.begin();
+         subnet_it != subnets6_.end(); ++subnet_it) {
+        if ((*subnet_it)->getID() == subnet.getID()) {
+            return (true);
+        }
+    }
+    return (false);
+}
+
+
 const isc::asiolink::IOAddress*
 const isc::asiolink::IOAddress*
 CfgMgr::getUnicast(const std::string& iface) const {
 CfgMgr::getUnicast(const std::string& iface) const {
     UnicastIfacesCollection::const_iterator addr = unicast_addrs_.find(iface);
     UnicastIfacesCollection::const_iterator addr = unicast_addrs_.find(iface);

+ 21 - 0
src/lib/dhcpsrv/cfgmgr.h

@@ -47,6 +47,13 @@ public:
         isc::Exception(file, line, what) { };
         isc::Exception(file, line, what) { };
 };
 };
 
 
+/// @brief Exception thrown upon attempt to add subnet with an ID that belongs
+/// to the subnet that already exists.
+class DuplicateSubnetID : public Exception {
+public:
+    DuplicateSubnetID(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
 
 
 /// @brief Configuration Manager
 /// @brief Configuration Manager
 ///
 ///
@@ -458,6 +465,20 @@ private:
     /// @c CfgMgr::active_ifaces_.
     /// @c CfgMgr::active_ifaces_.
     bool isIfaceListedActive(const std::string& iface) const;
     bool isIfaceListedActive(const std::string& iface) const;
 
 
+    /// @brief Checks that the IPv4 subnet with the given id already exists.
+    ///
+    /// @param subnet Subnet for which this function will check if the other
+    /// subnet with equal id already exists.
+    /// @return true if the duplicate subnet exists.
+    bool isDuplicate(const Subnet4& subnet) const;
+
+    /// @brief Checks that the IPv6 subnet with the given id already exists.
+    ///
+    /// @param subnet Subnet for which this function will check if the other
+    /// subnet with equal id already exists.
+    /// @return true if the duplicate subnet exists.
+    bool isDuplicate(const Subnet6& subnet) const;
+
     /// @brief A collection of option definitions.
     /// @brief A collection of option definitions.
     ///
     ///
     /// A collection of option definitions that can be accessed
     /// A collection of option definitions that can be accessed

+ 35 - 0
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc

@@ -1053,6 +1053,41 @@ TEST_F(CfgMgrTest, getSubnet4ForInterface) {
 
 
 }
 }
 
 
+// Checks that detection of duplicated subnet IDs works as expected. It should
+// not be possible to add two IPv4 subnets holding the same ID to the config
+// manager.
+TEST_F(CfgMgrTest, subnet4Duplication) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+
+    Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3, 123));
+    Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3, 124));
+    Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3, 123));
+
+    ASSERT_NO_THROW(cfg_mgr.addSubnet4(subnet1));
+    EXPECT_NO_THROW(cfg_mgr.addSubnet4(subnet2));
+    // Subnet 3 has the same ID as subnet 1. It shouldn't be able to add it.
+    EXPECT_THROW(cfg_mgr.addSubnet4(subnet3), isc::dhcp::DuplicateSubnetID);
+}
+
+// Checks that detection of duplicated subnet IDs works as expected. It should
+// not be possible to add two IPv6 subnets holding the same ID to the config
+// manager.
+TEST_F(CfgMgrTest, subnet6Duplication) {
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+
+    Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 1, 2, 3,
+                                   4, 123));
+    Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 64, 1, 2, 3,
+                                   4, 124));
+    Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 64, 1, 2, 3,
+                                   4, 123));
+
+    ASSERT_NO_THROW(cfg_mgr.addSubnet6(subnet1));
+    EXPECT_NO_THROW(cfg_mgr.addSubnet6(subnet2));
+    // Subnet 3 has the same ID as subnet 1. It shouldn't be able to add it.
+    EXPECT_THROW(cfg_mgr.addSubnet6(subnet3), isc::dhcp::DuplicateSubnetID);
+}
+
 
 
 /// @todo Add unit-tests for testing:
 /// @todo Add unit-tests for testing:
 /// - addActiveIface() with invalid interface name
 /// - addActiveIface() with invalid interface name