Chromium Code Reviews| Index: net/base/host_resolver_proc.cc |
| diff --git a/net/base/host_resolver_proc.cc b/net/base/host_resolver_proc.cc |
| index fd350dffa998baa4c0c21197e2f7667c311c0cf2..86304dcec2e65d34356d463b983e2ee17dc7d95e 100644 |
| --- a/net/base/host_resolver_proc.cc |
| +++ b/net/base/host_resolver_proc.cc |
| @@ -18,6 +18,42 @@ |
| namespace net { |
| +namespace { |
| + |
| +bool IsAllLocalhostOfOneFamily(const struct addrinfo* ai) { |
| + bool saw_v4_localhost = false; |
| + bool saw_v6_localhost = false; |
| + for (; ai != NULL; ai = ai->ai_next) { |
| + switch (ai->ai_family) { |
| + case AF_INET: { |
| + const struct sockaddr_in* addr_in = |
| + reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); |
| + if ((ntohl(addr_in->sin_addr.s_addr) & 0xff000000) == 0x7f000000) |
| + saw_v4_localhost = true; |
| + else |
| + return false; |
| + break; |
| + } |
| + case AF_INET6: { |
| + const struct sockaddr_in6* addr_in6 = |
| + reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr); |
| + if (IN6_IS_ADDR_LOOPBACK(&addr_in6->sin6_addr)) |
| + saw_v6_localhost = true; |
| + else |
| + return false; |
| + break; |
| + } |
| + default: |
| + NOTREACHED(); |
| + return false; |
| + } |
| + } |
| + |
| + return saw_v4_localhost != saw_v6_localhost; |
| +} |
| + |
| +} // namespace |
| + |
| HostResolverProc* HostResolverProc::default_proc_ = NULL; |
| HostResolverProc::HostResolverProc(HostResolverProc* previous) { |
| @@ -161,15 +197,36 @@ int SystemHostResolverProc(const std::string& host, |
| hints.ai_socktype = SOCK_STREAM; |
| int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); |
| + bool should_retry = false; |
| #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| // If we fail, re-initialise the resolver just in case there have been any |
| // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info. |
| if (err && DnsReloadTimerHasExpired()) { |
| res_nclose(&_res); |
| if (!res_ninit(&_res)) |
| - err = getaddrinfo(host.c_str(), NULL, &hints, &ai); |
| + should_retry = true; |
| } |
| #endif |
| + // If the lookup was restricted (either by address family, or address |
| + // detection), and the results where all localhost of a single family, |
| + // maybe we should retry. There were several bugs related to these |
| + // issues, for example http://crbug.com/42058 and http://crbug.com/49024 |
| + if ((hints.ai_family != AF_UNSPEC || hints.ai_flags & AI_ADDRCONFIG) && |
| + err == 0 && IsAllLocalhostOfOneFamily(ai)) { |
|
willchan no longer on Chromium
2010/09/03 19:36:50
I personally think "err == OK" is more readable, b
vandebo (ex-Chrome)
2010/09/03 19:42:18
err is the result of getaddrinfo, not a chrome net
willchan no longer on Chromium
2010/09/03 20:23:07
Oops, sorry, I thought this was a net::Error. I c
|
| + if (host_resolver_flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) { |
| + hints.ai_family = AF_UNSPEC; |
| + should_retry = true; |
| + } |
| + if (hints.ai_flags & AI_ADDRCONFIG) { |
| + hints.ai_flags &= ~AI_ADDRCONFIG; |
| + should_retry = true; |
| + } |
| + } |
| + if (should_retry) { |
| + freeaddrinfo(ai); |
|
willchan no longer on Chromium
2010/09/03 19:36:50
don't you need a NULL check here? In the line 207
vandebo (ex-Chrome)
2010/09/03 19:42:18
From man 3 free: 'If ptr is NULL, no operation is
willchan no longer on Chromium
2010/09/03 20:23:07
Clearly I haven't done C programming in forever.
|
| + ai = NULL; |
| + err = getaddrinfo(host.c_str(), NULL, &hints, &ai); |
| + } |
| if (err) { |
| if (os_error) { |