getLocalAddress(const isc::asiolink::IOAddress& remote_addr,
const uint16_t port);
- /// @brief Checks if there is at least one socket of the specified family
- /// open.
- /// @brief Handles an error which occurs during configuration of a socket.
-- ///
- /// @param family A socket family.
- /// If the handler callback is specified (non-NULL), this handler is
- /// called and the specified error message is passed to it. If the
- /// handler is not specified, the @c isc::dhcpSocketConfigError exception
- /// is thrown with the specified message.
-- ///
- /// @return true if there is at least one socket open, false otherwise.
- bool hasOpenSocket(const uint16_t family) const;
- /// This function should be called to handle errors which occur during
- /// socket opening, binding or configuration (e.g. setting socket options
- /// etc).
- ///
- /// @param errmsg An error message to be passed to a handlder function or
- /// to the @c isc::dhcp::SocketConfigError exception.
- /// @param handler An error handler function or NULL.
- void handleSocketConfigError(const std::string& errmsg,
- IfaceMgrErrorMsgCallback handler);
/// Holds instance of a class derived from PktFilter, used by the
/// IfaceMgr to open sockets and send/receive packets through these
EXPECT_FALSE(socket_open);
}
- // Test that exception is thrown when trying to bind a new socket to the port
- // and address which is already in use by another socket.
- TEST_F(IfaceMgrTest, openSockets6NoErrorHandler) {
- 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));
-
- // Open socket on eth0. The openSockets6 should detect that this
- // socket has been already open and an attempt to open another socket
- // and bind to this address and port should fail.
- ASSERT_NO_THROW(ifacemgr.openSocket("eth0",
- IOAddress("fe80::3a60:77ff:fed5:cdef"),
- DHCP6_SERVER_PORT));
-
- // The function throws an exception when it tries to open a socket
- // and bind it to the address in use.
- EXPECT_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT),
- isc::dhcp::SocketConfigError);
-
- }
-
+// Test that the external error handler is called when trying to bind a new
+// socket to the address and port being in use. The sockets on the other
+// interfaces should open just fine.
+TEST_F(IfaceMgrTest, openSocket6ErrorHandler) {
+ 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));
+
+ // Open socket on eth0.
+ ASSERT_NO_THROW(ifacemgr.openSocket("eth0",
+ IOAddress("fe80::3a60:77ff:fed5:cdef"),
+ DHCP6_SERVER_PORT));
+
+ // Install an error handler before trying to open sockets. This handler
+ // should be called when the IfaceMgr fails to open socket on eth0.
+ isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
+ boost::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, _1);
+ // The openSockets6 should detect that a socket has been already
+ // opened on eth0 and an attempt to open another socket and bind to
+ // the same address and port should fail.
+ ASSERT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, error_handler));
+ // We expect that an error occured when we tried to open a socket on
+ // eth0, but the socket on eth1 should open just fine.
+ EXPECT_EQ(1, errors_count_);
+
+ // Reset errors count.
+ errors_count_ = 0;
+
+ // Now that we have two sockets open, we can try this again but this time
+ // we should get two errors: one when opening a socket on eth0, another one
+ // when opening a socket on eth1.
+ ASSERT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, error_handler));
+ EXPECT_EQ(2, errors_count_);
+
+}
+
+ // This test verifies that the function correctly checks that the v6 socket is
+ // open and bound to a specific address.
+ TEST_F(IfaceMgrTest, hasOpenSocketForAddress6) {
+ 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 = false;
+ ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
+ EXPECT_TRUE(success);
+
+ // Make sure that the sockets are bound as expected.
+ ASSERT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
+ EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
+
+ // There should be v6 sockets only, no v4 sockets.
+ EXPECT_TRUE(ifacemgr.hasOpenSocket(AF_INET6));
+ EXPECT_FALSE(ifacemgr.hasOpenSocket(AF_INET));
+
+ // Check that there are sockets bound to the addresses we have configured
+ // for interfaces.
+ EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:cdef")));
+ EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:abcd")));
+ // Check that there is no socket bound to the address which hasn't been
+ // configured on any interface.
+ EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:feed:1")));
++
+ }
+
// Test the Iface structure itself
TEST_F(IfaceMgrTest, iface) {
boost::scoped_ptr<Iface> iface;