Browse Source

[trac1957] Throwing exception if unable to find address to create socket.

Marcin Siodelski 13 years ago
parent
commit
66d9922628
3 changed files with 50 additions and 40 deletions
  1. 30 26
      src/lib/dhcp/iface_mgr.cc
  2. 4 0
      src/lib/dhcp/iface_mgr.h
  3. 16 14
      src/lib/dhcp/tests/iface_mgr_unittest.cc

+ 30 - 26
src/lib/dhcp/iface_mgr.cc

@@ -397,7 +397,6 @@ int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
 int IfaceMgr::openSocketFromIface(const std::string& ifname,
                                   const uint16_t port,
                                   const uint8_t family) {
-    int sock = 0;
     // Search for specified interface among detected interfaces.
     for (IfaceCollection::iterator iface = ifaces_.begin();
          iface != ifaces_.end();
@@ -411,28 +410,36 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
         // Interface is now detected. Search for address on interface
         // that matches address family (v6 or v4).
         AddressCollection addrs = iface->getAddresses();
-        for (AddressCollection::iterator addr_it = addrs.begin();
-             addr_it != addrs.end();
-             ++addr_it) {
-
-            if (addr_it->getFamily() != family) {
-                continue;
+        AddressCollection::iterator addr_it = addrs.begin();
+        while (addr_it != addrs.end()) {
+            if (addr_it->getFamily() == family) {
+                // We have interface and address so let's open socket.
+                // This may cause isc::Unexpected exception.
+                return (openSocket(iface->getName(), *addr_it, port));
             }
-
-            // We have interface and address so let's open socket.
-            sock = openSocket(iface->getName(), *addr_it, port);
-            if (sock < 0) {
-                isc_throw(Unexpected, "Failed to open socket.");
+            ++addr_it;
+        }
+        // If we are at the end of address collection it means that we found
+        // interface but there is no address for family specified.
+        if (addr_it == addrs.end()) {
+            // Stringify the family value to append it to exception string.
+            std::string family_name("AF_INET");
+            if (family == AF_INET6) {
+                family_name = "AF_INET6";
             }
-            return (sock);
+            // We did not find address on the interface.
+            isc_throw(BadValue, "There is no address for interface: "
+                      << ifname << ", port: " << port << ", address "
+                      " family: " << family_name);
         }
     }
-    return (sock);
+    // If we got here it means that we had not found the specified interface.
+    // Otherwise we would have returned from previous exist points.
+    isc_throw(BadValue, "There is no " << ifname << " interface present.");
 }
 
 int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
                                     const uint16_t port) {
-    int sock = 0;
     // Search through detected interfaces and addresses to match
     // local address we got.
     for (IfaceCollection::iterator iface = ifaces_.begin();
@@ -449,19 +456,16 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
             // on detected interfaces. If it does, we have
             // address and interface detected so we can open
             // socket.
-            if (*addr_it != addr) {
-                continue;
+            if (*addr_it == addr) {
+                // Open socket using local interface, address and port.
+                // This may cause isc::Unexpected exception.
+                return (openSocket(iface->getName(), *addr_it, port));
             }
-
-            // Open socket using local interface, address and port.
-            sock = openSocket(iface->getName(), *addr_it, port);
-            if (sock < 0) {
-                isc_throw(Unexpected, "Failed to open unicast socket.");
-            }
-            return (sock);
         }
     }
-    return (sock);
+    // If we got here it means that we did not find specified address
+    // on any available interface.
+    isc_throw(BadValue, "There is no such address " << addr.toText());
 }
 
 int IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
@@ -474,7 +478,7 @@ int IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
 isc::asiolink::IOAddress
 IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
     // Create remote endpoint, we will be connecting to it.
-    boost::shared_ptr<const UDPEndpoint>
+    boost::scoped_ptr<const UDPEndpoint>
         remote_endpoint(static_cast<const UDPEndpoint*>
                         (UDPEndpoint::create(IPPROTO_UDP, remote_addr, port)));
     if (!remote_endpoint) {

+ 4 - 0
src/lib/dhcp/iface_mgr.h

@@ -389,6 +389,8 @@ public:
     /// @return socket descriptor, if socket creation, binding and multicast
     /// group join were all successful.
     /// @throw isc::Unexpected if failed to create and bind socket.
+    /// @throw isc::BadValue if there is no address on specified interface
+    /// that belongs to given family.
     int openSocketFromIface(const std::string& ifname,
                             const uint16_t port,
                             const uint8_t family);
@@ -403,6 +405,8 @@ public:
     /// @return socket descriptor, if socket creation, binding and multicast
     /// group join were all successful.
     /// @throw isc::Unexpected if failed to create and bind socket
+    /// @throw isc::BadValue if specified address is not available on
+    /// any interface
     int openSocketFromAddress(const isc::asiolink::IOAddress& addr,
                               const uint16_t port);
 

+ 16 - 14
src/lib/dhcp/tests/iface_mgr_unittest.cc

@@ -18,6 +18,7 @@
 #include <sstream>
 
 #include <arpa/inet.h>
+#include <boost/scoped_ptr.hpp>
 #include <gtest/gtest.h>
 
 #include <asiolink/io_address.h>
@@ -241,12 +242,13 @@ TEST_F(IfaceMgrTest, sockets6) {
 }
 
 TEST_F(IfaceMgrTest, socketsFromIface) {
-    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
+    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
 
     // open v6 socket on loopback interface and bind to 10547 port
     int socket1 = 0;
+    const uint16_t port1 = 10547;
     EXPECT_NO_THROW(
-        socket1 = ifacemgr->openSocketFromIface(LOOPBACK, 10547, AF_INET6);
+        socket1 = ifacemgr->openSocketFromIface(LOOPBACK, port1, AF_INET6);
     );
     // socket descriptor must be positive integer
     EXPECT_GT(socket1, 0);
@@ -254,25 +256,26 @@ TEST_F(IfaceMgrTest, socketsFromIface) {
 
     // open v4 sicket on loopback interface and bind to 10548 port
     int socket2 = 0;
+    const uint16_t port2 = 10548;
     EXPECT_NO_THROW(
-        socket2 = ifacemgr->openSocketFromIface(LOOPBACK, 10547, AF_INET);
+        socket2 = ifacemgr->openSocketFromIface(LOOPBACK, port2, AF_INET);
     );
     // socket descriptor must be positive integer
     EXPECT_GT(socket2, 0);
     close(socket2);
 
-    delete ifacemgr;
 }
 
 
 TEST_F(IfaceMgrTest, socketsFromAddress) {
-    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
+    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
 
     // open v6 socket on loopback address and bind to 10547 port
     int socket1 = 0;
+    const uint16_t port1 = 10547;
     IOAddress loAddr6("::1");
     EXPECT_NO_THROW(
-        socket1 = ifacemgr->openSocketFromAddress(loAddr6, 10547);
+        socket1 = ifacemgr->openSocketFromAddress(loAddr6, port1);
     );
     // socket descriptor must be positive integer
     EXPECT_GT(socket1, 0);
@@ -280,41 +283,40 @@ TEST_F(IfaceMgrTest, socketsFromAddress) {
 
     // open v4 socket on loopback address and bind to 10548 port
     int socket2 = 0;
+    const uint16_t port2 = 10548;
     IOAddress loAddr("127.0.0.1");
     EXPECT_NO_THROW(
-        socket2 = ifacemgr->openSocketFromAddress(loAddr, 10548);
+        socket2 = ifacemgr->openSocketFromAddress(loAddr, port2);
     );
     // socket descriptor must be positive integer
     EXPECT_GT(socket2, 0);
     close(socket2);
-
-    delete ifacemgr;
 }
 
 TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
-    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
+    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
 
     // Open v6 socket to connect to remote address.
     // Loopback address is the only one that we know
     // so let's treat it as remote address.
     int socket1 = 0;
+    const uint16_t port1 = 10547;
     IOAddress loAddr6("::1");
     EXPECT_NO_THROW(
-        socket1 = ifacemgr->openSocketFromRemoteAddress(loAddr6, 10547);
+        socket1 = ifacemgr->openSocketFromRemoteAddress(loAddr6, port1);
     );
     EXPECT_GT(socket1, 0);
     close(socket1);
 
     // Open v4 socket to connect to remote address.
     int socket2 = 0;
+    const uint16_t port2 = 10548;
     IOAddress loAddr("127.0.0.1");
     EXPECT_NO_THROW(
-        socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, 10548);
+        socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, port2);
     );
     EXPECT_GT(socket2, 0);
     close(socket2);
-
-    delete ifacemgr;
 }
 
 // TODO: disabled due to other naming on various systems