Author: astitcher
Date: Fri May 18 22:05:37 2012
New Revision: 1340279

URL: http://svn.apache.org/viewvc?rev=1340279&view=rev
Log:
QPID-4011: TestIsLocalHost unit_test fails with if machine name resolves to 
loopback address
QPID-3404 - This change also adds support for IPv6 interface addresses to 
getLocalIpAddresses

Modified:
    qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp
    qpid/trunk/qpid/cpp/src/tests/SystemInfo.cpp

Modified: qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp?rev=1340279&r1=1340278&r2=1340279&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp Fri May 18 22:05:37 
2012
@@ -60,19 +60,41 @@ bool SystemInfo::getLocalHostname (Addre
     return true;
 }
 
-static const string LOCALHOST("127.0.0.1");
+static const string LOOPBACK("127.0.0.1");
 static const string TCP("tcp");
 
+// Test IPv4 address for loopback
+inline bool IN_IS_ADDR_LOOPBACK(const ::in_addr* a) {
+    return ((::ntohl(a->s_addr) & 0xff000000) == 0x7f000000);
+}
+
+inline bool isLoopback(const ::sockaddr* addr) {
+    switch (addr->sa_family) {
+        case AF_INET: return IN_IS_ADDR_LOOPBACK(&((const 
::sockaddr_in*)(const void*)addr)->sin_addr);
+        case AF_INET6: return IN6_IS_ADDR_LOOPBACK(&((const 
::sockaddr_in6*)(const void*)addr)->sin6_addr);
+        default: return false;
+    }
+}
+
 void SystemInfo::getLocalIpAddresses (uint16_t port,
                                       std::vector<Address> &addrList) {
     ::ifaddrs* ifaddr = 0;
     QPID_POSIX_CHECK(::getifaddrs(&ifaddr));
     for (::ifaddrs* ifap = ifaddr; ifap != 0; ifap = ifap->ifa_next) {
         if (ifap->ifa_addr == 0) continue;
-
+        if (isLoopback(ifap->ifa_addr)) continue;
         int family = ifap->ifa_addr->sa_family;
         switch (family) {
-          case AF_INET: {
+            case AF_INET6: {
+                // Ignore link local addresses as:
+                // * The scope id is illegal in URL syntax
+                // * Clients won't be able to use a link local address
+                //   without adding their own (potentially different) scope id
+                sockaddr_in6* sa6 = (sockaddr_in6*)(ifap->ifa_addr);
+                if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) break;
+                // Fallthrough
+            }
+            case AF_INET: {
               char dispName[NI_MAXHOST];
               int rc = ::getnameinfo(
                   ifap->ifa_addr,
@@ -85,14 +107,9 @@ void SystemInfo::getLocalIpAddresses (ui
                   throw QPID_POSIX_ERROR(rc);
               }
               string addr(dispName);
-              if (addr != LOCALHOST) {
-                  addrList.push_back(Address(TCP, addr, port));
-              }
+              addrList.push_back(Address(TCP, addr, port));
               break;
           }
-            // TODO: Url parsing currently can't cope with IPv6 addresses so 
don't return them
-            // when it can cope move this line to above "case AF_INET:"
-          case AF_INET6:
           default:
             continue;
         }
@@ -100,7 +117,7 @@ void SystemInfo::getLocalIpAddresses (ui
     ::freeifaddrs(ifaddr);
 
     if (addrList.empty()) {
-        addrList.push_back(Address(TCP, LOCALHOST, port));
+        addrList.push_back(Address(TCP, LOOPBACK, port));
     }
 }
 
@@ -116,7 +133,6 @@ struct AddrInfo {
 }
 
 bool SystemInfo::isLocalHost(const std::string& host) {
-    if (host == LOCALHOST) return true;
     std::vector<Address> myAddrs;
     getLocalIpAddresses(0, myAddrs);
     std::set<string> localHosts;
@@ -126,6 +142,7 @@ bool SystemInfo::isLocalHost(const std::
     AddrInfo ai(host);
     if (!ai.ptr) return false;
     for (struct addrinfo *res = ai.ptr; res != NULL; res = res->ai_next) {
+        if (isLoopback(res->ai_addr)) return true;
         // Get string form of IP addr
         char addr[NI_MAXHOST] = "";
         int error = ::getnameinfo(res->ai_addr, res->ai_addrlen, addr, 
NI_MAXHOST, NULL, 0,

Modified: qpid/trunk/qpid/cpp/src/tests/SystemInfo.cpp
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/SystemInfo.cpp?rev=1340279&r1=1340278&r2=1340279&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/SystemInfo.cpp (original)
+++ qpid/trunk/qpid/cpp/src/tests/SystemInfo.cpp Fri May 18 22:05:37 2012
@@ -37,12 +37,14 @@ QPID_AUTO_TEST_CASE(TestIsLocalHost) {
     BOOST_ASSERT(SystemInfo::getLocalHostname(a));
     BOOST_ASSERT(SystemInfo::isLocalHost(a.host));
     std::vector<Address> addrs;
+    SystemInfo::getLocalIpAddresses(0, addrs);
     for (std::vector<Address>::iterator i = addrs.begin(); i != addrs.end(); 
++i)
         BOOST_ASSERT(SystemInfo::isLocalHost(i->host));
     // Check some non-local addresses
     BOOST_ASSERT(!SystemInfo::isLocalHost("123.4.5.6"));
     BOOST_ASSERT(!SystemInfo::isLocalHost("nosuchhost"));
     BOOST_ASSERT(SystemInfo::isLocalHost("127.0.0.1"));
+    BOOST_ASSERT(SystemInfo::isLocalHost("::1"));
 }
 
 QPID_AUTO_TEST_SUITE_END()



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to