BIND 10 trac3251, updated. 4276b45afad091f2022b690effd2711d6a587c79 [3251] Implemented basic tests for IfaceMgr::openSockets6.

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Dec 13 06:28:24 UTC 2013


The branch, trac3251 has been updated
       via  4276b45afad091f2022b690effd2711d6a587c79 (commit)
      from  0ae10a533c27a489ec4bb434ca54c40e2f92f9dc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4276b45afad091f2022b690effd2711d6a587c79
Author: Marcin Siodelski <marcin at isc.org>
Date:   Fri Dec 13 07:28:16 2013 +0100

    [3251] Implemented basic tests for IfaceMgr::openSockets6.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dhcp/iface_mgr.cc                |    4 +-
 src/lib/dhcp/tests/iface_mgr_unittest.cc |  269 ++++++++++++++++++++++++++++--
 2 files changed, 257 insertions(+), 16 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index d491530..5d64fdb 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -485,7 +485,7 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
                           << iface->getName() << ", reason: " << errstr);
             }
 
-            // Binding socket to unicast address and then joining multicast group
+            /*            // Binding socket to unicast address and then joining multicast group
             // works well on Mac OS (and possibly other BSDs), but does not work
             // on Linux.
             if ( !PktFilter6::joinMulticast(sock, iface->getName(),
@@ -494,7 +494,7 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
                 isc_throw(SocketConfigError, "Failed to join "
                           << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
                           << " multicast group.");
-            }
+                          } */
 
             count++;
 
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index 2eacd03..d81f9be 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -36,6 +36,7 @@ using namespace std;
 using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::dhcp;
+using namespace isc::dhcp::test;
 using boost::scoped_ptr;
 
 namespace {
@@ -169,11 +170,21 @@ public:
         ifaces_.clear();
 
         // local loopback
-        ifaces_.push_back(createIface("lo", 0, "127.0.0.1"));
+        Iface lo = createIface("lo", 0);
+        lo.addAddress(IOAddress("127.0.0.1"));
+        lo.addAddress(IOAddress("::1"));
+        ifaces_.push_back(lo);
         // eth0
-        ifaces_.push_back(createIface("eth0", 1, "10.0.0.1"));
+        Iface eth0 = createIface("eth0", 1);
+        eth0.addAddress(IOAddress("10.0.0.1"));
+        eth0.addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+        eth0.addAddress(IOAddress("2001:db8:1::1"));
+        ifaces_.push_back(eth0);
         // eth1
-        ifaces_.push_back(createIface("eth1", 2, "192.0.2.3"));
+        Iface eth1 = createIface("eth1", 2);
+        eth1.addAddress(IOAddress("192.0.2.3"));
+        eth1.addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+        ifaces_.push_back(eth1);
     }
 
     /// @brief Create an object representing interface.
@@ -190,13 +201,10 @@ public:
     ///
     /// @param name A name of the interface to be created.
     /// @param ifindex An index of the interface to be created.
-    /// @param addr An IP address to be assigned to the interface.
     ///
     /// @return An object representing interface.
-    static Iface createIface(const std::string& name, const int ifindex,
-                             const std::string& addr) {
+    static Iface createIface(const std::string& name, const int ifindex) {
         Iface iface(name, ifindex);
-        iface.addAddress(IOAddress(addr));
         if (name == "lo") {
             iface.flag_loopback_ = true;
         }
@@ -206,7 +214,30 @@ public:
         return (iface);
     }
 
-    /// @brief Modified flags on the interface.
+    /// @brief Checks if the specified interface has a socket bound to a
+    /// specified adddress.
+    ///
+    /// @param iface_name A name of the interface.
+    /// @param addr An address to be checked for binding.
+    ///
+    /// @return true if there is a socket bound to the specified address.
+    bool isBound(const std::string& iface_name, const std::string& addr) {
+        Iface* iface = getIface(iface_name);
+        if (iface == NULL) {
+            ADD_FAILURE() << "the interface " << iface_name << " doesn't exist";
+            return (false);
+        }
+        const Iface::SocketCollection& sockets = iface->getSockets();
+        for (Iface::SocketCollection::const_iterator sock = sockets.begin();
+             sock != sockets.end(); ++sock) {
+            if (sock->addr_ == IOAddress(addr)) {
+                return (true);
+            }
+        }
+        return (false);
+    }
+
+    /// @brief Modify flags on the interface.
     ///
     /// @param name A name of the interface.
     /// @param loopback A new value of the loopback flag.
@@ -215,14 +246,16 @@ public:
     /// @param inactive A new value of the inactive flag.
     void setIfaceFlags(const std::string& name, const bool loopback,
                        const bool up, const bool running,
-                       const bool inactive) {
+                       const bool inactive4,
+                       const bool inactive6) {
         for (IfaceMgr::IfaceCollection::iterator iface = ifaces_.begin();
              iface != ifaces_.end(); ++iface) {
             if (iface->getName() == name) {
                 iface->flag_loopback_ = loopback;
                 iface->flag_up_ = up;
                 iface->flag_running_ = running;
-                iface->inactive4_ = inactive;
+                iface->inactive4_ = inactive4;
+                iface->inactive6_ = inactive6;
             }
         }
     }
@@ -245,6 +278,38 @@ public:
     ~IfaceMgrTest() {
     }
 
+    /// @brief Tests the number of IPv6 sockets on interface
+    ///
+    /// This function checks the expected number of open IPv6 sockets on the
+    /// specified interface. On non-Linux systems, sockets are bound to a
+    /// link-local address and the number of unicast addresses specified.
+    /// On Linux systems, there is one more socket bound to a ff02::1:2
+    /// multicast address.
+    ///
+    /// @param iface An interface on which sockets are open.
+    /// @param unicast_num A number of unicast addresses bound.
+    void checkSocketsCount6(const Iface& iface, const int unicast_num) {
+        // On local-loopback interface, there should be no sockets.
+        if (iface.flag_loopback_) {
+            ASSERT_TRUE(iface.getSockets().empty())
+                << "expected empty socket set on loopback interface "
+                << iface.getName();
+            return;
+        }
+#if defined OS_LINUX
+        // On Linux, there is an additional socket bound to ff02::1:2.
+        ASSERT_EQ(unicast_num + 2, iface.getSockets().size())
+            << "invalid number of sockets on interface "
+            << iface.getName();
+#else
+        // On non-Linux, there is no additional socket.
+        ASSERT_EQ(unicast_num + 1, iface.getSockets().size())
+            << "invalid number of sockets on interface "
+            << iface.getName();
+
+#endif
+    }
+
     // Get ther number of IPv4 or IPv6 sockets on the loopback interface
     int getOpenSocketsCount(const Iface& iface, uint16_t family) const {
         // Get all sockets.
@@ -1082,12 +1147,12 @@ TEST_F(IfaceMgrTest, setPacketFilter6) {
     ASSERT_TRUE(iface_mgr);
 
     // Try to set NULL packet filter object and make sure it is rejected.
-    boost::shared_ptr<test::PktFilter6Stub> custom_packet_filter;
+    boost::shared_ptr<PktFilter6Stub> custom_packet_filter;
     EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
                  isc::dhcp::InvalidPacketFilter);
 
     // Create valid object and check if it can be set.
-    custom_packet_filter.reset(new test::PktFilter6Stub());
+    custom_packet_filter.reset(new PktFilter6Stub());
     ASSERT_TRUE(custom_packet_filter);
     ASSERT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
 
@@ -1295,7 +1360,7 @@ TEST_F(IfaceMgrTest, openSockets4IfaceDown) {
     // - is "down" (not up)
     // - is not running
     // - is active (is not inactive)
-    ifacemgr.setIfaceFlags("eth0", false, false, true, false);
+    ifacemgr.setIfaceFlags("eth0", false, false, true, false, false);
     ASSERT_FALSE(ifacemgr.getIface("eth0")->flag_up_);
     ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, NULL));
 
@@ -1326,7 +1391,7 @@ TEST_F(IfaceMgrTest, openSockets4IfaceInactive) {
     // - is up
     // - is running
     // - is inactive
-    ifacemgr.setIfaceFlags("eth1", false, true, true, true);
+    ifacemgr.setIfaceFlags("eth1", false, true, true, true, false);
     ASSERT_TRUE(ifacemgr.getIface("eth1")->inactive4_);
     ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, NULL));
 
@@ -1403,6 +1468,182 @@ TEST_F(IfaceMgrTest, openSocket4ErrorHandler) {
 
 }
 
+// This test checks that the sockets are open and bound to link local addresses
+// only, if unicast addresses are not specified.
+TEST_F(IfaceMgrTest, openSockets6LinkLocal) {
+    NakedIfaceMgr ifacemgr;
+
+    // Remove all real interfaces and create a set of dummy interfaces.
+    ifacemgr.createIfaces();
+
+    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
+    ASSERT_TRUE(filter);
+    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
+
+    // Simulate opening sockets using the dummy packet filter.
+    bool success;
+    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
+    EXPECT_TRUE(success);
+
+    // Check that the number of sockets is correct on each interface.
+    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+    checkSocketsCount6(*ifacemgr.getIface("eth0"), 0);
+    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+
+    // Sockets on eth0 should be bound to link-local and should not be bound
+    // to global unicast address, even though this address is configured on
+    // the eth0.
+    EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
+    EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
+    // Socket on eth1 should be bound to link local only.
+    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
+
+    // If we are on Linux, there is one more socket bound to ff02::1:2
+#if defined OS_LINUX
+    EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+#endif
+}
+
+// This test checks that the sockets are opened and bound to link local
+// and unicast addresses which have been explicitly specified.
+TEST_F(IfaceMgrTest, openSockets6Unicast) {
+    NakedIfaceMgr ifacemgr;
+
+    // Remove all real interfaces and create a set of dummy interfaces.
+    ifacemgr.createIfaces();
+
+    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
+    ASSERT_TRUE(filter);
+    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
+
+    // Configure the eth0 to open socket on the unicast address, apart
+    // from link-local address.
+    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
+
+    // Simulate opening sockets using the dummy packet filter.
+    bool success;
+    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
+    EXPECT_TRUE(success);
+
+    // Check that we have correct number of sockets on each interface.
+    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+    checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address.
+    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+
+    // eth0 should have two sockets, one bound to link-local, another one
+    // bound to unicast address.
+    EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
+    EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
+    // eth1 should have one socket, bound to link-local address.
+    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
+
+    // If we are on Linux, there is one more socket bound to ff02::1:2
+#if defined OS_LINUX
+    EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+#endif
+
+}
+
+// This test checks that no sockets are open for the interface which is down.
+TEST_F(IfaceMgrTest, openSockets6IfaceDown) {
+    NakedIfaceMgr ifacemgr;
+
+    // Remove all real interfaces and create a set of dummy interfaces.
+    ifacemgr.createIfaces();
+
+    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
+    ASSERT_TRUE(filter);
+    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
+
+    // Configure the eth0 to open socket on the unicast address, apart
+    // from link-local address.
+    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
+
+    // Boolean parameters specify that eth0 is:
+    // - not a loopback
+    // - is "down" (not up)
+    // - is not running
+    // - is active for both v4 and v6
+    ifacemgr.setIfaceFlags("eth0", false, false, false, false, false);
+
+    // Simulate opening sockets using the dummy packet filter.
+    bool success;
+    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
+    EXPECT_TRUE(success);
+
+    // Check that we have correct number of sockets on each interface.
+    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+    // There should be no sockets on eth0 because interface is down.
+    ASSERT_TRUE(ifacemgr.getIface("eth0")->getSockets().empty());
+    checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
+
+    // eth0 should have no sockets because the interface is down.
+    EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
+    EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
+    EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+    // eth1 should have one socket, bound to link-local address.
+    EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
+
+    // If we are on Linux, there is one more socket bound to ff02::1:2
+#if defined OS_LINUX
+    EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+#endif
+
+}
+
+// This test checks that no sockets are open for the interface which is
+// inactive.
+TEST_F(IfaceMgrTest, openSockets6IfaceInactive) {
+    NakedIfaceMgr ifacemgr;
+
+    // Remove all real interfaces and create a set of dummy interfaces.
+    ifacemgr.createIfaces();
+
+    boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
+    ASSERT_TRUE(filter);
+    ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
+
+    // Configure the eth0 to open socket on the unicast address, apart
+    // from link-local address.
+    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
+
+    // Boolean parameters specify that eth1 is:
+    // - not a loopback
+    // - is up
+    // - is running
+    // - is active for v4
+    // - is inactive for v6
+    ifacemgr.setIfaceFlags("eth1", false, true, true, false, true);
+
+    // Simulate opening sockets using the dummy packet filter.
+    bool success;
+    ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
+    EXPECT_TRUE(success);
+
+    // Check that we have correct number of sockets on each interface.
+    checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
+    checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address
+    // There should be no sockets on eth1 because interface is inactive
+    ASSERT_TRUE(ifacemgr.getIface("eth1")->getSockets().empty());
+
+    // eth0 should have one socket bound to a link-local address, another one
+    // bound to unicast address.
+    EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
+    EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
+
+    // eth1 shouldn't have a socket bound to link local address because
+    // interface is inactive.
+    EXPECT_FALSE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
+    EXPECT_FALSE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+
+    // If we are on Linux, there is one more socket bound to ff02::1:2
+#if defined OS_LINUX
+    EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
+#endif
+
+}
 
 // Test the Iface structure itself
 TEST_F(IfaceMgrTest, iface) {



More information about the bind10-changes mailing list