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 |