From 7050bac5925b4888257c1b4af20e0b44a3286c8b Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Mon, 17 Oct 2011 14:24:20 +0200 Subject: [PATCH] Make IP_RANGE::resolve_ip() thread safe --- src/ipfunc.cpp | 28 ++++++++++++++++++++-------- src/ipfunc.hxx | 4 ++-- test/ip_range.cpp | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/ipfunc.cpp b/src/ipfunc.cpp index c54cbde..936844f 100644 --- a/src/ipfunc.cpp +++ b/src/ipfunc.cpp @@ -31,6 +31,7 @@ on this file might be covered by the GNU General Public License. #include #include +#include #include @@ -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); } diff --git a/src/ipfunc.hxx b/src/ipfunc.hxx index a52cae5..f1ce325 100644 --- a/src/ipfunc.hxx +++ b/src/ipfunc.hxx @@ -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 diff --git a/test/ip_range.cpp b/test/ip_range.cpp index cce628b..3f4910c 100644 --- a/test/ip_range.cpp +++ b/test/ip_range.cpp @@ -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() -- 1.7.1