Browse Source

[3242] Implement function which returns subnet for the interface.

This function replaces the one that checked whether there is a subnet for
an interface and returns boolean value.
Marcin Siodelski 11 years ago
parent
commit
f4548b2768
3 changed files with 48 additions and 31 deletions
  1. 14 16
      src/lib/dhcpsrv/cfgmgr.cc
  2. 8 8
      src/lib/dhcpsrv/cfgmgr.h
  3. 26 7
      src/lib/dhcpsrv/tests/cfgmgr_unittest.cc

+ 14 - 16
src/lib/dhcpsrv/cfgmgr.cc

@@ -208,9 +208,9 @@ void CfgMgr::addSubnet6(const Subnet6Ptr& subnet) {
 }
 }
 
 
 Subnet4Ptr
 Subnet4Ptr
-CfgMgr::getSubnet4(const isc::asiolink::IOAddress& hint) {
+CfgMgr::getSubnet4(const isc::asiolink::IOAddress& hint) const {
 
 
-    // If there's only one subnet configured, let's just use it
+    /*    // If there's only one subnet configured, let's just use it
     // The idea is to keep small deployments easy. In a small network - one
     // The idea is to keep small deployments easy. In a small network - one
     // router that also runs DHCPv6 server. Users specifies a single pool and
     // router that also runs DHCPv6 server. Users specifies a single pool and
     // expects it to just work. Without this, the server would complain that it
     // expects it to just work. Without this, the server would complain that it
@@ -223,10 +223,10 @@ CfgMgr::getSubnet4(const isc::asiolink::IOAddress& hint) {
                   DHCPSRV_CFGMGR_ONLY_SUBNET4)
                   DHCPSRV_CFGMGR_ONLY_SUBNET4)
                   .arg(subnets4_[0]->toText()).arg(hint.toText());
                   .arg(subnets4_[0]->toText()).arg(hint.toText());
         return (subnets4_[0]);
         return (subnets4_[0]);
-    }
+        }*/
 
 
     // If there is more than one, we need to choose the proper one
     // If there is more than one, we need to choose the proper one
-    for (Subnet4Collection::iterator subnet = subnets4_.begin();
+    for (Subnet4Collection::const_iterator subnet = subnets4_.begin();
          subnet != subnets4_.end(); ++subnet) {
          subnet != subnets4_.end(); ++subnet) {
         if ((*subnet)->inRange(hint)) {
         if ((*subnet)->inRange(hint)) {
             LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
             LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
@@ -242,22 +242,20 @@ CfgMgr::getSubnet4(const isc::asiolink::IOAddress& hint) {
     return (Subnet4Ptr());
     return (Subnet4Ptr());
 }
 }
 
 
-bool
-CfgMgr::belongsToSubnet4(const std::string& iface_name) const {
+Subnet4Ptr
+CfgMgr::getSubnet4(const std::string& iface_name) const {
     Iface* iface = IfaceMgr::instance().getIface(iface_name);
     Iface* iface = IfaceMgr::instance().getIface(iface_name);
+    // This should never happen in the real life. Hence we throw an exception.
     if (iface == NULL) {
     if (iface == NULL) {
-        isc_throw(isc::BadValue, "interface " << iface_name << " doesn't exist");
+        isc_throw(isc::BadValue, "interface " << iface_name <<
+                  " doesn't exist and therefore it is impossible"
+                  " to find a suitable subnet for its IPv4 address");
     }
     }
     IOAddress addr("::1");
     IOAddress addr("::1");
-    if (iface->getAddress4(addr)) {
-        for (Subnet4Collection::const_iterator subnet = subnets4_.begin();
-             subnet != subnets4_.end(); ++subnet) {
-            if ((*subnet)->inRange(addr)) {
-                return (true);
-            }
-        }
-    }
-    return (false);
+    // If IPv4 address assigned to the interface exists, find a suitable
+    // subnet for it, else return NULL pointer to indicate that no subnet
+    // could be found.
+    return (iface->getAddress4(addr) ? getSubnet4(addr) : Subnet4Ptr());
 }
 }
 
 
 void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {
 void CfgMgr::addSubnet4(const Subnet4Ptr& subnet) {

+ 8 - 8
src/lib/dhcpsrv/cfgmgr.h

@@ -219,7 +219,7 @@ public:
     /// to choose a different subnet. Server code has to offer a list
     /// to choose a different subnet. Server code has to offer a list
     /// of possible choices (i.e. all subnets).
     /// of possible choices (i.e. all subnets).
     /// @return a pointer to const Subnet6 collection
     /// @return a pointer to const Subnet6 collection
-    const Subnet4Collection* getSubnets4() {
+    const Subnet4Collection* getSubnets4() const {
         return (&subnets4_);
         return (&subnets4_);
     }
     }
 
 
@@ -244,19 +244,19 @@ public:
     /// @param hint an address that belongs to a searched subnet
     /// @param hint an address that belongs to a searched subnet
     ///
     ///
     /// @return a subnet object
     /// @return a subnet object
-    Subnet4Ptr getSubnet4(const isc::asiolink::IOAddress& hint);
+    Subnet4Ptr getSubnet4(const isc::asiolink::IOAddress& hint) const;
 
 
-    /// @brief Checks that the IP address assigned to an interface belongs to
-    /// any subnet.
+    /// @brief Returns a subnet for the specified local interface.
     ///
     ///
     /// This function checks that the IP address assigned to the specified
     /// This function checks that the IP address assigned to the specified
-    /// interface belongs to any IPv4 subnet configured.
+    /// interface belongs to any IPv4 subnet configured, and returns this
+    /// subnet.
     ///
     ///
     /// @param iface Short name of the interface which is being checked.
     /// @param iface Short name of the interface which is being checked.
     ///
     ///
-    /// @return Boolean value which indicates that the IP address belons to any
-    /// subnet (if true), false otherwise.
-    bool belongsToSubnet4(const std::string& iface) const;
+    /// @return Pointer to the subnet matching interface specified or NULL
+    /// pointer if IPv4 address on the interface doesn't match any subnet.
+    Subnet4Ptr getSubnet4(const std::string& iface) const;
 
 
     /// @brief adds a subnet4
     /// @brief adds a subnet4
     void addSubnet4(const Subnet4Ptr& subnet);
     void addSubnet4(const Subnet4Ptr& subnet);

+ 26 - 7
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc

@@ -713,23 +713,42 @@ TEST_F(CfgMgrTest, d2ClientConfig) {
 
 
 // This test verfies that CfgMgr correctly determines that the address of the
 // This test verfies that CfgMgr correctly determines that the address of the
 // interface belongs to existing IPv4 subnet.
 // interface belongs to existing IPv4 subnet.
-TEST_F(CfgMgrTest, belongsToSubnet4) {
+TEST_F(CfgMgrTest, getSubnet4ForInterface) {
     IfaceMgrTestConfig config(true);
     IfaceMgrTestConfig config(true);
 
 
-    ASSERT_FALSE(CfgMgr::instance().belongsToSubnet4("eth0"));
-    ASSERT_FALSE(CfgMgr::instance().belongsToSubnet4("eth1"));
+    // Initially, there are no subnets configured, so none of the IPv4
+    // addresses assigned to eth0 and eth1 can match with any subnet.
+    ASSERT_FALSE(CfgMgr::instance().getSubnet4("eth0"));
+    ASSERT_FALSE(CfgMgr::instance().getSubnet4("eth1"));
 
 
+    // Configure first subnet which address on eth0 corresponds to.
     Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.1"), 24, 1, 2, 3));
     Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.1"), 24, 1, 2, 3));
     CfgMgr::instance().addSubnet4(subnet1);
     CfgMgr::instance().addSubnet4(subnet1);
 
 
-    EXPECT_TRUE(CfgMgr::instance().belongsToSubnet4("eth0"));
-    EXPECT_FALSE(CfgMgr::instance().belongsToSubnet4("eth1"));
+    // The address on eth0 should match the existing subnet.
+    Subnet4Ptr subnet1_ret;
+    subnet1_ret = CfgMgr::instance().getSubnet4("eth0");
+    ASSERT_TRUE(subnet1_ret);
+    EXPECT_EQ(subnet1->get().first, subnet1_ret->get().first);
+    // There should still be no match for eth1.
+    EXPECT_FALSE(CfgMgr::instance().getSubnet4("eth1"));
 
 
+    // Configure a second subnet.
     Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.1"), 24, 1, 2, 3));
     Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.1"), 24, 1, 2, 3));
     CfgMgr::instance().addSubnet4(subnet2);
     CfgMgr::instance().addSubnet4(subnet2);
 
 
-    EXPECT_TRUE(CfgMgr::instance().belongsToSubnet4("eth0"));
-    EXPECT_TRUE(CfgMgr::instance().belongsToSubnet4("eth1"));
+    // There should be match between eth0 and subnet1 and between eth1 and
+    // subnet 2.
+    subnet1_ret = CfgMgr::instance().getSubnet4("eth0");
+    ASSERT_TRUE(subnet1_ret);
+    EXPECT_EQ(subnet1->get().first, subnet1_ret->get().first);
+    Subnet4Ptr subnet2_ret = CfgMgr::instance().getSubnet4("eth1");
+    ASSERT_TRUE(subnet2_ret);
+    EXPECT_EQ(subnet2->get().first, subnet2_ret->get().first);
+
+    // This function throws an exception if the name of the interface is wrong.
+    EXPECT_THROW(CfgMgr::instance().getSubnet4("bogus-interface"),
+                 isc::BadValue);
 
 
 }
 }