|
@@ -158,7 +158,7 @@ public:
|
|
/// @brief Returns the collection of existing interfaces.
|
|
/// @brief Returns the collection of existing interfaces.
|
|
IfaceCollection& getIfacesLst() { return (ifaces_); }
|
|
IfaceCollection& getIfacesLst() { return (ifaces_); }
|
|
|
|
|
|
- /// @brief This function creates fictious interfaces with fictious
|
|
|
|
|
|
+ /// @brief This function creates fictitious interfaces with fictious
|
|
/// addresses.
|
|
/// addresses.
|
|
///
|
|
///
|
|
/// These interfaces can be used in tests that don't actually try
|
|
/// These interfaces can be used in tests that don't actually try
|
|
@@ -195,6 +195,8 @@ public:
|
|
/// - up always true
|
|
/// - up always true
|
|
/// - running always true
|
|
/// - running always true
|
|
/// - inactive always to false
|
|
/// - inactive always to false
|
|
|
|
+ /// - multicast always to true
|
|
|
|
+ /// - broadcast always to true
|
|
///
|
|
///
|
|
/// If one needs to modify the default flag settings, the setIfaceFlags
|
|
/// If one needs to modify the default flag settings, the setIfaceFlags
|
|
/// function should be used.
|
|
/// function should be used.
|
|
@@ -208,9 +210,12 @@ public:
|
|
if (name == "lo") {
|
|
if (name == "lo") {
|
|
iface.flag_loopback_ = true;
|
|
iface.flag_loopback_ = true;
|
|
}
|
|
}
|
|
|
|
+ iface.flag_multicast_ = true;
|
|
|
|
+ iface.flag_broadcast_ = true;
|
|
iface.flag_up_ = true;
|
|
iface.flag_up_ = true;
|
|
iface.flag_running_ = true;
|
|
iface.flag_running_ = true;
|
|
iface.inactive4_ = false;
|
|
iface.inactive4_ = false;
|
|
|
|
+ iface.inactive6_ = false;
|
|
return (iface);
|
|
return (iface);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -288,7 +293,9 @@ public:
|
|
///
|
|
///
|
|
/// @param iface An interface on which sockets are open.
|
|
/// @param iface An interface on which sockets are open.
|
|
/// @param unicast_num A number of unicast addresses bound.
|
|
/// @param unicast_num A number of unicast addresses bound.
|
|
- void checkSocketsCount6(const Iface& iface, const int unicast_num) {
|
|
|
|
|
|
+ /// @param link_local_num A number of link local addresses bound.
|
|
|
|
+ void checkSocketsCount6(const Iface& iface, const int unicast_num,
|
|
|
|
+ const int link_local_num = 1) {
|
|
// On local-loopback interface, there should be no sockets.
|
|
// On local-loopback interface, there should be no sockets.
|
|
if (iface.flag_loopback_) {
|
|
if (iface.flag_loopback_) {
|
|
ASSERT_TRUE(iface.getSockets().empty())
|
|
ASSERT_TRUE(iface.getSockets().empty())
|
|
@@ -297,13 +304,16 @@ public:
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
#if defined OS_LINUX
|
|
#if defined OS_LINUX
|
|
- // On Linux, there is an additional socket bound to ff02::1:2.
|
|
|
|
- ASSERT_EQ(unicast_num + 2, iface.getSockets().size())
|
|
|
|
|
|
+ // On Linux, for each link-local address there may be an
|
|
|
|
+ // additional socket opened and bound to ff02::1:2. This socket
|
|
|
|
+ // is only opened if the interface is multicast-capable.
|
|
|
|
+ ASSERT_EQ(unicast_num + (iface.flag_multicast_ ? link_local_num : 0)
|
|
|
|
+ + link_local_num, iface.getSockets().size())
|
|
<< "invalid number of sockets on interface "
|
|
<< "invalid number of sockets on interface "
|
|
<< iface.getName();
|
|
<< iface.getName();
|
|
#else
|
|
#else
|
|
// On non-Linux, there is no additional socket.
|
|
// On non-Linux, there is no additional socket.
|
|
- ASSERT_EQ(unicast_num + 1, iface.getSockets().size())
|
|
|
|
|
|
+ ASSERT_EQ(unicast_num + link_local_num, iface.getSockets().size())
|
|
<< "invalid number of sockets on interface "
|
|
<< "invalid number of sockets on interface "
|
|
<< iface.getName();
|
|
<< iface.getName();
|
|
|
|
|
|
@@ -1505,6 +1515,92 @@ TEST_F(IfaceMgrTest, openSockets6LinkLocal) {
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// This test checks that socket is not open on the interface which doesn't
|
|
|
|
+// have a link-local address.
|
|
|
|
+TEST_F(IfaceMgrTest, openSockets6NoLinkLocal) {
|
|
|
|
+ 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));
|
|
|
|
+
|
|
|
|
+ // Remove a link local address from eth0. If there is no link-local
|
|
|
|
+ // address, the socket should not open.
|
|
|
|
+ ASSERT_TRUE(ifacemgr.getIface("eth0")->
|
|
|
|
+ delAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));
|
|
|
|
+
|
|
|
|
+ // Simulate opening sockets using the dummy packet filter.
|
|
|
|
+ bool success = false;
|
|
|
|
+ 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);
|
|
|
|
+ // The thrid parameter specifies that the number of link-local
|
|
|
|
+ // addresses for eth0 is equal to 0.
|
|
|
|
+ checkSocketsCount6(*ifacemgr.getIface("eth0"), 0, 0);
|
|
|
|
+ checkSocketsCount6(*ifacemgr.getIface("eth1"), 0, 1);
|
|
|
|
+
|
|
|
|
+ // There should be no sockets open on eth0 because it neither has
|
|
|
|
+ // link-local nor global unicast addresses.
|
|
|
|
+ EXPECT_FALSE(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_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// This test checks that socket is open on the non-muticast-capable
|
|
|
|
+// interface. This socket simply doesn't join multicast group.
|
|
|
|
+TEST_F(IfaceMgrTest, openSockets6NotMulticast) {
|
|
|
|
+ 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));
|
|
|
|
+
|
|
|
|
+ // Make eth0 multicast-incapable.
|
|
|
|
+ ifacemgr.getIface("eth0")->flag_multicast_ = false;
|
|
|
|
+
|
|
|
|
+ // Simulate opening sockets using the dummy packet filter.
|
|
|
|
+ bool success = false;
|
|
|
|
+ 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"));
|
|
|
|
+ // The eth0 is not a multicast-capable interface, so the socket should
|
|
|
|
+ // not be bound to the multicast address.
|
|
|
|
+ EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
|
|
|
|
+ // 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
|
|
|
|
+ // on eth1.
|
|
|
|
+#if defined OS_LINUX
|
|
|
|
+ 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
|
|
// This test checks that the sockets are opened and bound to link local
|
|
// and unicast addresses which have been explicitly specified.
|
|
// and unicast addresses which have been explicitly specified.
|
|
TEST_F(IfaceMgrTest, openSockets6Unicast) {
|
|
TEST_F(IfaceMgrTest, openSockets6Unicast) {
|
|
@@ -1546,6 +1642,52 @@ TEST_F(IfaceMgrTest, openSockets6Unicast) {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// This test checks that the socket is open and bound to a global unicast
|
|
|
|
+// address if the link-local address does not exist for the particular
|
|
|
|
+// interface.
|
|
|
|
+TEST_F(IfaceMgrTest, openSockets6UnicastOnly) {
|
|
|
|
+ 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"));
|
|
|
|
+ // Explicitly remove the link-local address from eth0.
|
|
|
|
+ ASSERT_TRUE(ifacemgr.getIface("eth0")->
|
|
|
|
+ delAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));
|
|
|
|
+
|
|
|
|
+ // Simulate opening sockets using the dummy packet filter.
|
|
|
|
+ bool success = false;
|
|
|
|
+ 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, 0);
|
|
|
|
+ checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
|
|
|
|
+
|
|
|
|
+ // The link-local address is not present on eth0. Therefore, no socket
|
|
|
|
+ // must be bound to this address, nor to multicast address.
|
|
|
|
+ EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
|
|
|
|
+ EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
|
|
|
|
+ // There should be one socket bound to unicast address.
|
|
|
|
+ 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("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
// This test checks that no sockets are open for the interface which is down.
|
|
// This test checks that no sockets are open for the interface which is down.
|
|
TEST_F(IfaceMgrTest, openSockets6IfaceDown) {
|
|
TEST_F(IfaceMgrTest, openSockets6IfaceDown) {
|
|
NakedIfaceMgr ifacemgr;
|
|
NakedIfaceMgr ifacemgr;
|
|
@@ -1645,7 +1787,7 @@ TEST_F(IfaceMgrTest, openSockets6IfaceInactive) {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-// That that the openSockets6 function does not throw if there are no interfaces
|
|
|
|
|
|
+// Test that the openSockets6 function does not throw if there are no interfaces
|
|
// detected. This function is expected to return false.
|
|
// detected. This function is expected to return false.
|
|
TEST_F(IfaceMgrTest, openSockets6NoIfaces) {
|
|
TEST_F(IfaceMgrTest, openSockets6NoIfaces) {
|
|
NakedIfaceMgr ifacemgr;
|
|
NakedIfaceMgr ifacemgr;
|