BIND 10 trac2187, updated. 1f486ccd690d8267b0a4410d8163298c5f5cf1ef [2187] Throw exception in case of error when opening socket.
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Sep 25 12:10:10 UTC 2012
The branch, trac2187 has been updated
via 1f486ccd690d8267b0a4410d8163298c5f5cf1ef (commit)
from d863d2f26c9e2fb9a866d56de15723cfd5a9e58b (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 1f486ccd690d8267b0a4410d8163298c5f5cf1ef
Author: Marcin Siodelski <marcin at isc.org>
Date: Tue Sep 25 14:09:54 2012 +0200
[2187] Throw exception in case of error when opening socket.
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/iface_mgr.cc | 117 +++++++++++++-----------------
src/lib/dhcp/iface_mgr.h | 34 +++++++++
src/lib/dhcp/tests/iface_mgr_unittest.cc | 40 +++++++---
3 files changed, 116 insertions(+), 75 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index 1965fde..8ee3205 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -132,13 +132,7 @@ IfaceMgr::IfaceMgr()
detectIfaces();
} catch (const std::exception& ex) {
- cout << "IfaceMgr creation failed:" << ex.what() << endl;
-
- // TODO Uncomment this (or call LOG_FATAL) once
- // interface detection is implemented. Otherwise
- // it is not possible to run tests in a portable
- // way (see detectIfaces() method).
- throw;
+ isc_throw(IfaceDetectError, ex.what());
}
}
@@ -164,45 +158,34 @@ void IfaceMgr::stubDetectIfaces() {
// is faked by detecting loopback interface (lo or lo0). It will eventually
// be removed once we have actual implementations for all supported systems.
- try {
- if (if_nametoindex("lo") > 0) {
- ifaceName = "lo";
- // this is Linux-like OS
- } else if (if_nametoindex("lo0") > 0) {
- ifaceName = "lo0";
- // this is BSD-like OS
- } else {
- // we give up. What OS is this, anyway? Solaris? Hurd?
- isc_throw(NotImplemented,
- "Interface detection on this OS is not supported.");
- }
-
- Iface iface(ifaceName, if_nametoindex(ifaceName.c_str()));
- iface.flag_up_ = true;
- iface.flag_running_ = true;
-
- // Note that we claim that this is not a loopback. iface_mgr tries to open a
- // socket on all interaces that are up, running and not loopback. As this is
- // the only interface we were able to detect, let's pretend this is a normal
- // interface.
- iface.flag_loopback_ = false;
- iface.flag_multicast_ = true;
- iface.flag_broadcast_ = true;
- iface.setHWType(HWTYPE_ETHERNET);
-
- iface.addAddress(IOAddress(v4addr));
- iface.addAddress(IOAddress(v6addr));
- addInterface(iface);
- } catch (const std::exception& ex) {
- // TODO: deallocate whatever memory we used
- // not that important, since this function is going to be
- // thrown away as soon as we get proper interface detection
- // implemented
-
- // TODO Do LOG_FATAL here
- std::cerr << "Interface detection failed." << std::endl;
- throw;
+ if (if_nametoindex("lo") > 0) {
+ ifaceName = "lo";
+ // this is Linux-like OS
+ } else if (if_nametoindex("lo0") > 0) {
+ ifaceName = "lo0";
+ // this is BSD-like OS
+ } else {
+ // we give up. What OS is this, anyway? Solaris? Hurd?
+ isc_throw(NotImplemented,
+ "Interface detection on this OS is not supported.");
}
+
+ Iface iface(ifaceName, if_nametoindex(ifaceName.c_str()));
+ iface.flag_up_ = true;
+ iface.flag_running_ = true;
+
+ // Note that we claim that this is not a loopback. iface_mgr tries to open a
+ // socket on all interaces that are up, running and not loopback. As this is
+ // the only interface we were able to detect, let's pretend this is a normal
+ // interface.
+ iface.flag_loopback_ = false;
+ iface.flag_multicast_ = true;
+ iface.flag_broadcast_ = true;
+ iface.setHWType(HWTYPE_ETHERNET);
+
+ iface.addAddress(IOAddress(v4addr));
+ iface.addAddress(IOAddress(v6addr));
+ addInterface(iface);
}
bool IfaceMgr::openSockets4(const uint16_t port) {
@@ -231,15 +214,13 @@ bool IfaceMgr::openSockets4(const uint16_t port) {
sock = openSocket(iface->getName(), *addr, port);
if (sock < 0) {
- cout << "Failed to open unicast socket." << endl;
- return (false);
+ isc_throw(SocketConfigError, "failed to open unicast socket");
}
count++;
}
}
return (count > 0);
-
}
bool IfaceMgr::openSockets6(const uint16_t port) {
@@ -268,8 +249,7 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
sock = openSocket(iface->getName(), *addr, port);
if (sock < 0) {
- cout << "Failed to open unicast socket." << endl;
- return (false);
+ isc_throw(SocketConfigError, "failed to open unicast socket");
}
// Binding socket to unicast address and then joining multicast group
@@ -278,7 +258,8 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
if ( !joinMulticast(sock, iface->getName(),
string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS))) {
close(sock);
- isc_throw(Unexpected, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
+ isc_throw(SocketConfigError, "Failed to join "
+ << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
<< " multicast group.");
}
@@ -293,7 +274,7 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
port);
if (sock2 < 0) {
- isc_throw(Unexpected, "Failed to open multicast socket on "
+ isc_throw(SocketConfigError, "Failed to open multicast socket on "
<< " interface " << iface->getFullName());
iface->delSocket(sock); // delete previously opened socket
}
@@ -406,7 +387,7 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
family_name = "AF_INET6";
}
// We did not find address on the interface.
- isc_throw(BadValue, "There is no address for interface: "
+ isc_throw(SocketConfigError, "There is no address for interface: "
<< ifname << ", port: " << port << ", address "
" family: " << family_name);
}
@@ -448,9 +429,13 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
int IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
const uint16_t port) {
- // Get local address to be used to connect to remote location.
- IOAddress local_address(getLocalAddress(remote_addr, port).getAddress());
- return openSocketFromAddress(local_address, port);
+ try {
+ // Get local address to be used to connect to remote location.
+ IOAddress local_address(getLocalAddress(remote_addr, port).getAddress());
+ return openSocketFromAddress(local_address, port);
+ } catch (const Exception& e) {
+ isc_throw(SocketConfigError, e.what());
+ }
}
isc::asiolink::IOAddress
@@ -494,7 +479,7 @@ IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
if (err_code) {
sock.close();
- isc_throw(Unexpected,"failed to connect to remote endpoint.");
+ isc_throw(Unexpected, "failed to connect to remote endpoint.");
}
// Once we are connected socket object holds local endpoint.
@@ -522,12 +507,12 @@ int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
- isc_throw(Unexpected, "Failed to create UDP6 socket.");
+ isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
close(sock);
- isc_throw(Unexpected, "Failed to bind socket " << sock << " to " << addr.toText()
+ isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
<< "/port=" << port);
}
@@ -537,7 +522,7 @@ int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
int flag = 1;
if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
close(sock);
- isc_throw(Unexpected, "setsockopt: IP_PKTINFO: failed.");
+ isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
}
#endif
@@ -569,7 +554,7 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
// make a socket
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0) {
- isc_throw(Unexpected, "Failed to create UDP6 socket.");
+ isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
// Set the REUSEADDR option so that we don't fail to start if
@@ -578,12 +563,12 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof(flag)) < 0) {
close(sock);
- isc_throw(Unexpected, "Can't set SO_REUSEADDR option on dhcpv6 socket.");
+ isc_throw(SocketConfigError, "Can't set SO_REUSEADDR option on dhcpv6 socket.");
}
if (bind(sock, (struct sockaddr *)&addr6, sizeof(addr6)) < 0) {
close(sock);
- isc_throw(Unexpected, "Failed to bind socket " << sock << " to " << addr.toText()
+ isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
<< "/port=" << port);
}
#ifdef IPV6_RECVPKTINFO
@@ -591,14 +576,14 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
&flag, sizeof(flag)) != 0) {
close(sock);
- isc_throw(Unexpected, "setsockopt: IPV6_RECVPKTINFO failed.");
+ isc_throw(SocketConfigError, "setsockopt: IPV6_RECVPKTINFO failed.");
}
#else
// RFC2292 - an old way
if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
&flag, sizeof(flag)) != 0) {
close(sock);
- isc_throw(Unexpected, "setsockopt: IPV6_PKTINFO: failed.");
+ isc_throw(SocketConfigError, "setsockopt: IPV6_PKTINFO: failed.");
}
#endif
@@ -611,7 +596,7 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
if ( !joinMulticast( sock, iface.getName(),
string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
close(sock);
- isc_throw(Unexpected, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
+ isc_throw(SocketConfigError, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
<< " multicast group.");
}
}
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index 98ce672..ed7b0c2 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -28,6 +28,38 @@
namespace isc {
namespace dhcp {
+
+/// @brief IfaceMgr exception thrown thrown when interface detection fails.
+class IfaceDetectError : public Exception {
+public:
+ IfaceDetectError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief IfaceMgr exception thrown thrown when socket opening
+/// or configuration failed.
+class SocketConfigError : public Exception {
+public:
+ SocketConfigError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief IfaceMgr exception thrown thrown when error occured during
+/// reading data from socket.
+class SocketReadError : public Exception {
+public:
+ SocketReadError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief IfaceMgr exception thrown thrown when error occured during
+/// sedning data through socket.
+class SocketWriteError : public Exception {
+public:
+ SocketWriteError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
/// @brief handles network interfaces, transmission and reception
///
/// IfaceMgr is an interface manager class that detects available network
@@ -460,6 +492,7 @@ public:
///
/// @param port specifies port number (usually DHCP6_SERVER_PORT)
///
+ /// @throw SocketOpenFailure if tried and failed to open socket.
/// @return true if any sockets were open
bool openSockets6(const uint16_t port = DHCP6_SERVER_PORT);
@@ -472,6 +505,7 @@ public:
///
/// @param port specifies port number (usually DHCP4_SERVER_PORT)
///
+ /// @throw SocketOpenFailure if tried and failed to open socket.
/// @return true if any sockets were open
bool openSockets4(const uint16_t port = DHCP4_SERVER_PORT);
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index c78ed83..700dd24 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -419,7 +419,7 @@ TEST_F(IfaceMgrTest, sockets6) {
// testing socket operation in a portable way is tricky
// without interface detection implemented
- NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
+ boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
IOAddress loAddr("::1");
@@ -439,10 +439,20 @@ TEST_F(IfaceMgrTest, sockets6) {
// removed code for binding socket twice to the same address/port
// as it caused problems on some platforms (e.g. Mac OS X)
- close(socket1);
- close(socket2);
+ ifacemgr->closeSockets();
- delete ifacemgr;
+ // Use address that is not assigned to LOOPBACK iface.
+ IOAddress invalidAddr("::2");
+ EXPECT_THROW(
+ ifacemgr->openSocket(LOOPBACK, invalidAddr, 10547),
+ SocketConfigError
+ );
+
+ // Use non-existing interface name.
+ EXPECT_THROW(
+ ifacemgr->openSocket("non_existing_interface", loAddr, 10548),
+ BadValue
+ );
}
TEST_F(IfaceMgrTest, socketsFromIface) {
@@ -466,6 +476,13 @@ TEST_F(IfaceMgrTest, socketsFromIface) {
EXPECT_GT(socket2, 0);
close(socket2);
+ ifacemgr->closeSockets();
+
+ // Use invalid interface name.
+ EXPECT_THROW(
+ ifacemgr->openSocketFromIface("non_existing_interface", PORT1, AF_INET),
+ BadValue
+ );
}
@@ -480,7 +497,6 @@ TEST_F(IfaceMgrTest, socketsFromAddress) {
);
// socket descriptor must be positive integer
EXPECT_GT(socket1, 0);
- close(socket1);
// Open v4 socket on loopback interface and bind to different port
int socket2 = 0;
@@ -490,7 +506,14 @@ TEST_F(IfaceMgrTest, socketsFromAddress) {
);
// socket descriptor must be positive integer
EXPECT_GT(socket2, 0);
- close(socket2);
+
+ ifacemgr->closeSockets();
+
+ // Use non-existing address.
+ IOAddress invalidAddr("1.2.3.4");
+ EXPECT_THROW(
+ ifacemgr->openSocketFromAddress(invalidAddr, PORT1), BadValue
+ );
}
TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
@@ -505,7 +528,6 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
socket1 = ifacemgr->openSocketFromRemoteAddress(loAddr6, PORT1);
);
EXPECT_GT(socket1, 0);
- close(socket1);
// Open v4 socket to connect to remote address.
int socket2 = 0;
@@ -514,7 +536,8 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
);
EXPECT_GT(socket2, 0);
- close(socket2);
+
+ ifacemgr->closeSockets();
// The following test is currently disabled for OSes other than
// Linux because interface detection is not implemented on them.
@@ -528,7 +551,6 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
socket3 = ifacemgr->openSocketFromRemoteAddress(bcastAddr, PORT2);
);
EXPECT_GT(socket3, 0);
- close(socket3);
#endif
}
More information about the bind10-changes
mailing list