Make IP_RANGE::resolve_ip() thread safe
authorThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 17 Oct 2011 12:24:20 +0000 (14:24 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 17 Oct 2011 12:24:20 +0000 (14:24 +0200)
src/ipfunc.cpp
src/ipfunc.hxx
test/ip_range.cpp

index c54cbde..936844f 100644 (file)
@@ -31,6 +31,7 @@ on this file might be covered by the GNU General Public License.
 
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <string.h>
 
 #include <ipfunc.hxx>
 
@@ -634,11 +635,10 @@ std::string IP_RANGE::ip_num_string(unsigned int ip)
     return target;
 }
 
-string IP_RANGE::resolve_ip(const string &iporname)
+string IP_RANGE::resolve_ip(const string &iporname, const bool enable_ipv6)
 {
     struct in_addr ip_adr;
-    struct hostent *dnsdata;
-    
+
     if (inet_aton(iporname.c_str(),&ip_adr) != 0)
     {
         // is already a ip
@@ -646,13 +646,25 @@ string IP_RANGE::resolve_ip(const string &iporname)
     }
 
     // we need dns
-    dnsdata=gethostbyname(iporname.c_str());
+    struct addrinfo hints, *result = NULL;
+    memset(&hints, 0, sizeof(struct addrinfo));
+    if (enable_ipv6)
+        hints.ai_family = AF_UNSPEC;
+    else
+        hints.ai_family = AF_INET;
 
-    if (dnsdata==NULL)
-        throw dns_exception(hstrerror(h_errno));
+    if (getaddrinfo(iporname.c_str(), NULL, &hints, &result) != 0)
+        throw dns_exception("no corresponding ip found for: "+iporname);
 
-    if (dnsdata->h_addr_list == NULL || *(dnsdata->h_addr_list) == NULL)
+    if (result == NULL || result->ai_addrlen == 0 || result->ai_addr == NULL)
         throw dns_exception("no corresponding ip found for: "+iporname);
 
-    return inet_ntoa(*(struct in_addr*)(*dnsdata->h_addr_list));
+    // Convert addr to ip string
+    char str_ip[NI_MAXHOST], dummy_serv[NI_MAXSERV];
+    if (getnameinfo(result->ai_addr, result->ai_addrlen, str_ip, NI_MAXHOST, dummy_serv, NI_MAXSERV, NI_NUMERICHOST) != 0)
+        throw dns_exception("can't convert ip for: "+iporname);
+
+    freeaddrinfo(result);
+
+    return string(str_ip);
 }
index a52cae5..f1ce325 100644 (file)
@@ -1,4 +1,4 @@
- /*
+/*
 The software in this package is distributed under the GNU General
 Public License version 2 (with a special exception described below).
 
@@ -102,7 +102,7 @@ class IP_RANGE
         static unsigned int calc_netmask_from_cidr(unsigned int cidr);
         static std::string ip_string(unsigned int ip);
         static std::string ip_num_string(unsigned int ip);
-        static std::string resolve_ip(const std::string &iporname);
+        static std::string resolve_ip(const std::string &iporname, const bool enable_ipv6=false);
 };
 
 class dns_exception : public std::runtime_error
index cce628b..3f4910c 100644 (file)
@@ -853,4 +853,26 @@ BOOST_AUTO_TEST_CASE(Netmap3)
     BOOST_CHECK_EQUAL(IP_RANGE("192.168.2.0/255.255.255.0"),myip);
 }
 
+BOOST_AUTO_TEST_CASE(ResolveDNS)
+{
+    IP_RANGE test;
+    BOOST_CHECK_EQUAL("127.0.0.1", test.resolve_ip("localhost"));
+}
+
+/*
+// Note: Disabled on the Intranator
+BOOST_AUTO_TEST_CASE(ResolveDNSIPv6)
+{
+    IP_RANGE test;
+    BOOST_CHECK_EQUAL("::1", test.resolve_ip("localhost", true));
+}
+*/
+
+BOOST_AUTO_TEST_CASE(ResolveExistingIP)
+{
+    IP_RANGE test;
+    BOOST_CHECK_EQUAL("192.168.1.254", test.resolve_ip("192.168.1.254"));
+}
+
+
 BOOST_AUTO_TEST_SUITE_END()