Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/host_resolver_proc.h" | 5 #include "net/base/host_resolver_proc.h" |
| 6 | 6 |
| 7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 9 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 10 #include <resolv.h> | 10 #include <resolv.h> |
| 11 #endif | 11 #endif |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "net/base/address_list.h" | 14 #include "net/base/address_list.h" |
| 15 #include "net/base/dns_reload_timer.h" | 15 #include "net/base/dns_reload_timer.h" |
| 16 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 17 #include "net/base/sys_addrinfo.h" | 17 #include "net/base/sys_addrinfo.h" |
| 18 | 18 |
| 19 namespace net { | 19 namespace net { |
| 20 | 20 |
| 21 namespace { | |
| 22 | |
| 23 bool IsAllLocalhostOfOneFamily(const struct addrinfo* ai) { | |
| 24 bool saw_v4_localhost = false; | |
| 25 bool saw_v6_localhost = false; | |
| 26 for (; ai != NULL; ai = ai->ai_next) { | |
| 27 switch (ai->ai_family) { | |
| 28 case AF_INET: { | |
| 29 const struct sockaddr_in* addr_in = | |
| 30 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); | |
| 31 if ((ntohl(addr_in->sin_addr.s_addr) & 0xff000000) == 0x7f000000) | |
| 32 saw_v4_localhost = true; | |
| 33 else | |
| 34 return false; | |
| 35 break; | |
| 36 } | |
| 37 case AF_INET6: { | |
| 38 const struct sockaddr_in6* addr_in6 = | |
| 39 reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr); | |
| 40 if (IN6_IS_ADDR_LOOPBACK(&addr_in6->sin6_addr)) | |
| 41 saw_v6_localhost = true; | |
| 42 else | |
| 43 return false; | |
| 44 break; | |
| 45 } | |
| 46 default: | |
| 47 NOTREACHED(); | |
| 48 return false; | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 return saw_v4_localhost != saw_v6_localhost; | |
| 53 } | |
| 54 | |
| 55 } // namespace | |
| 56 | |
| 21 HostResolverProc* HostResolverProc::default_proc_ = NULL; | 57 HostResolverProc* HostResolverProc::default_proc_ = NULL; |
| 22 | 58 |
| 23 HostResolverProc::HostResolverProc(HostResolverProc* previous) { | 59 HostResolverProc::HostResolverProc(HostResolverProc* previous) { |
| 24 SetPreviousProc(previous); | 60 SetPreviousProc(previous); |
| 25 | 61 |
| 26 // Implicitly fall-back to the global default procedure. | 62 // Implicitly fall-back to the global default procedure. |
| 27 if (!previous) | 63 if (!previous) |
| 28 SetPreviousProc(default_proc_); | 64 SetPreviousProc(default_proc_); |
| 29 } | 65 } |
| 30 | 66 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 if (host_resolver_flags & HOST_RESOLVER_LOOPBACK_ONLY) | 190 if (host_resolver_flags & HOST_RESOLVER_LOOPBACK_ONLY) |
| 155 hints.ai_flags &= ~AI_ADDRCONFIG; | 191 hints.ai_flags &= ~AI_ADDRCONFIG; |
| 156 | 192 |
| 157 if (host_resolver_flags & HOST_RESOLVER_CANONNAME) | 193 if (host_resolver_flags & HOST_RESOLVER_CANONNAME) |
| 158 hints.ai_flags |= AI_CANONNAME; | 194 hints.ai_flags |= AI_CANONNAME; |
| 159 | 195 |
| 160 // Restrict result set to only this socket type to avoid duplicates. | 196 // Restrict result set to only this socket type to avoid duplicates. |
| 161 hints.ai_socktype = SOCK_STREAM; | 197 hints.ai_socktype = SOCK_STREAM; |
| 162 | 198 |
| 163 int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); | 199 int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); |
| 200 bool should_retry = false; | |
| 164 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 201 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| 165 // If we fail, re-initialise the resolver just in case there have been any | 202 // If we fail, re-initialise the resolver just in case there have been any |
| 166 // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info. | 203 // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info. |
| 167 if (err && DnsReloadTimerHasExpired()) { | 204 if (err && DnsReloadTimerHasExpired()) { |
| 168 res_nclose(&_res); | 205 res_nclose(&_res); |
| 169 if (!res_ninit(&_res)) | 206 if (!res_ninit(&_res)) |
| 170 err = getaddrinfo(host.c_str(), NULL, &hints, &ai); | 207 should_retry = true; |
| 171 } | 208 } |
| 172 #endif | 209 #endif |
| 210 // If the lookup was restricted (either by address family, or address | |
| 211 // detection), and the results where all localhost of a single family, | |
| 212 // maybe we should retry. There were several bugs related to these | |
| 213 // issues, for example http://crbug.com/42058 and http://crbug.com/49024 | |
| 214 if ((hints.ai_family != AF_UNSPEC || hints.ai_flags & AI_ADDRCONFIG) && | |
| 215 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
| |
| 216 if (host_resolver_flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) { | |
| 217 hints.ai_family = AF_UNSPEC; | |
| 218 should_retry = true; | |
| 219 } | |
| 220 if (hints.ai_flags & AI_ADDRCONFIG) { | |
| 221 hints.ai_flags &= ~AI_ADDRCONFIG; | |
| 222 should_retry = true; | |
| 223 } | |
| 224 } | |
| 225 if (should_retry) { | |
| 226 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.
| |
| 227 ai = NULL; | |
| 228 err = getaddrinfo(host.c_str(), NULL, &hints, &ai); | |
| 229 } | |
| 173 | 230 |
| 174 if (err) { | 231 if (err) { |
| 175 if (os_error) { | 232 if (os_error) { |
| 176 #if defined(OS_WIN) | 233 #if defined(OS_WIN) |
| 177 *os_error = WSAGetLastError(); | 234 *os_error = WSAGetLastError(); |
| 178 #else | 235 #else |
| 179 *os_error = err; | 236 *os_error = err; |
| 180 #endif | 237 #endif |
| 181 } | 238 } |
| 182 return ERR_NAME_NOT_RESOLVED; | 239 return ERR_NAME_NOT_RESOLVED; |
| 183 } | 240 } |
| 184 | 241 |
| 185 addrlist->Adopt(ai); | 242 addrlist->Adopt(ai); |
| 186 return OK; | 243 return OK; |
| 187 } | 244 } |
| 188 | 245 |
| 189 } // namespace net | 246 } // namespace net |
| OLD | NEW |