1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/dns/host_resolver_system_task.h"
6
7 #include <memory>
8 #include <optional>
9 #include <utility>
10 #include <vector>
11
12 #include "base/check.h"
13 #include "base/dcheck_is_on.h"
14 #include "base/feature_list.h"
15 #include "base/functional/bind.h"
16 #include "base/functional/callback.h"
17 #include "base/memory/raw_ref.h"
18 #include "base/metrics/field_trial_params.h"
19 #include "base/no_destructor.h"
20 #include "base/notreached.h"
21 #include "base/sequence_checker.h"
22 #include "base/sequence_checker_impl.h"
23 #include "base/task/sequenced_task_runner.h"
24 #include "base/task/task_traits.h"
25 #include "base/task/thread_pool.h"
26 #include "base/threading/scoped_blocking_call.h"
27 #include "base/time/time.h"
28 #include "base/types/pass_key.h"
29 #include "dns_reloader.h"
30 #include "net/base/address_family.h"
31 #include "net/base/address_list.h"
32 #include "net/base/features.h"
33 #include "net/base/ip_endpoint.h"
34 #include "net/base/net_errors.h"
35 #include "net/base/network_anonymization_key.h"
36 #include "net/base/network_interfaces.h"
37 #include "net/base/sys_addrinfo.h"
38 #include "net/base/trace_constants.h"
39 #include "net/base/tracing.h"
40 #include "net/dns/address_info.h"
41 #include "net/dns/dns_names_util.h"
42 #include "net/dns/host_resolver_cache.h"
43 #include "net/dns/host_resolver_internal_result.h"
44 #include "net/dns/public/host_resolver_source.h"
45
46 #if BUILDFLAG(IS_WIN)
47 #include "net/base/winsock_init.h"
48 #endif
49
50 namespace net {
51
52 namespace {
53
54 // System resolver results give no TTL, so a default caching time is needed.
55 // Pick 1 minute to match the minimum cache time for built-in resolver results
56 // because this is only serving as a secondary cache to the caching done by the
57 // system. Additionally, this matches the long-standing historical behavior from
58 // previous implementations of HostResolver caching.
59 constexpr base::TimeDelta kTtl = base::Minutes(1);
60
61 // Returns nullptr in the common case, or a task runner if the default has
62 // been overridden.
GetSystemDnsResolutionTaskRunnerOverride()63 scoped_refptr<base::TaskRunner>& GetSystemDnsResolutionTaskRunnerOverride() {
64 static base::NoDestructor<scoped_refptr<base::TaskRunner>>
65 system_dns_resolution_task_runner(nullptr);
66 return *system_dns_resolution_task_runner;
67 }
68
69 // Posts a synchronous callback to a thread pool task runner created with
70 // MayBlock, USER_BLOCKING, and CONTINUE_ON_SHUTDOWN. This task runner can be
71 // overridden by assigning to GetSystemDnsResolutionTaskRunnerOverride().
72 // `results_cb` will be called later on the current sequence with the results of
73 // the DNS resolution.
PostSystemDnsResolutionTaskAndReply(base::OnceCallback<int (AddressList * addrlist,int * os_error)> system_dns_resolution_callback,SystemDnsResultsCallback results_cb)74 void PostSystemDnsResolutionTaskAndReply(
75 base::OnceCallback<int(AddressList* addrlist, int* os_error)>
76 system_dns_resolution_callback,
77 SystemDnsResultsCallback results_cb) {
78 auto addr_list = std::make_unique<net::AddressList>();
79 net::AddressList* addr_list_ptr = addr_list.get();
80 auto os_error = std::make_unique<int>();
81 int* os_error_ptr = os_error.get();
82
83 // This callback owns |addr_list| and |os_error| and just calls |results_cb|
84 // with the results.
85 auto call_with_results_cb = base::BindOnce(
86 [](SystemDnsResultsCallback results_cb,
87 std::unique_ptr<net::AddressList> addr_list,
88 std::unique_ptr<int> os_error, int net_error) {
89 std::move(results_cb).Run(std::move(*addr_list), *os_error, net_error);
90 },
91 std::move(results_cb), std::move(addr_list), std::move(os_error));
92
93 scoped_refptr<base::TaskRunner> system_dns_resolution_task_runner =
94 GetSystemDnsResolutionTaskRunnerOverride();
95 if (!system_dns_resolution_task_runner) {
96 // In production this will run on every call, otherwise some tests will
97 // leave a stale task runner around after tearing down their task
98 // environment. This should not be less performant than the regular
99 // base::ThreadPool::PostTask().
100 system_dns_resolution_task_runner = base::ThreadPool::CreateTaskRunner(
101 {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
102 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
103 }
104 system_dns_resolution_task_runner->PostTaskAndReplyWithResult(
105 FROM_HERE,
106 base::BindOnce(std::move(system_dns_resolution_callback), addr_list_ptr,
107 os_error_ptr),
108 std::move(call_with_results_cb));
109 }
110
ResolveOnWorkerThread(scoped_refptr<HostResolverProc> resolver_proc,std::optional<std::string> hostname,AddressFamily address_family,HostResolverFlags flags,handles::NetworkHandle network,AddressList * addrlist,int * os_error)111 int ResolveOnWorkerThread(scoped_refptr<HostResolverProc> resolver_proc,
112 std::optional<std::string> hostname,
113 AddressFamily address_family,
114 HostResolverFlags flags,
115 handles::NetworkHandle network,
116 AddressList* addrlist,
117 int* os_error) {
118 std::string hostname_str = hostname ? *std::move(hostname) : GetHostName();
119 if (resolver_proc) {
120 return resolver_proc->Resolve(hostname_str, address_family, flags, addrlist,
121 os_error, network);
122 } else {
123 return SystemHostResolverCall(hostname_str, address_family, flags, addrlist,
124 os_error, network);
125 }
126 }
127
128 // Creates NetLog parameters when the resolve failed.
NetLogHostResolverSystemTaskFailedParams(uint32_t attempt_number,int net_error,int os_error)129 base::Value::Dict NetLogHostResolverSystemTaskFailedParams(
130 uint32_t attempt_number,
131 int net_error,
132 int os_error) {
133 base::Value::Dict dict;
134 if (attempt_number)
135 dict.Set("attempt_number", base::saturated_cast<int>(attempt_number));
136
137 dict.Set("net_error", net_error);
138
139 if (os_error) {
140 dict.Set("os_error", os_error);
141 #if BUILDFLAG(IS_WIN)
142 // Map the error code to a human-readable string.
143 LPWSTR error_string = nullptr;
144 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
145 nullptr, // Use the internal message table.
146 os_error,
147 0, // Use default language.
148 (LPWSTR)&error_string,
149 0, // Buffer size.
150 nullptr); // Arguments (unused).
151 dict.Set("os_error_string", base::WideToUTF8(error_string));
152 LocalFree(error_string);
153 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
154 dict.Set("os_error_string", gai_strerror(os_error));
155 #endif
156 }
157
158 return dict;
159 }
160
161 using SystemDnsResolverOverrideCallback =
162 base::RepeatingCallback<void(const std::optional<std::string>& host,
163 AddressFamily address_family,
164 HostResolverFlags host_resolver_flags,
165 SystemDnsResultsCallback results_cb,
166 handles::NetworkHandle network)>;
167
GetSystemDnsResolverOverride()168 SystemDnsResolverOverrideCallback& GetSystemDnsResolverOverride() {
169 static base::NoDestructor<SystemDnsResolverOverrideCallback> dns_override;
170
171 #if DCHECK_IS_ON()
172 if (*dns_override) {
173 // This should only be called on the main thread, so DCHECK that it is.
174 // However, in unittests this may be called on different task environments
175 // in the same process so only bother sequence checking if an override
176 // exists.
177 static base::NoDestructor<base::SequenceCheckerImpl> sequence_checker;
178 base::ScopedValidateSequenceChecker scoped_validated_sequence_checker(
179 *sequence_checker);
180 }
181 #endif
182
183 return *dns_override;
184 }
185
186 } // namespace
187
SetSystemDnsResolverOverride(SystemDnsResolverOverrideCallback dns_override)188 void SetSystemDnsResolverOverride(
189 SystemDnsResolverOverrideCallback dns_override) {
190 GetSystemDnsResolverOverride() = std::move(dns_override);
191 }
192
Params(scoped_refptr<HostResolverProc> resolver_proc,size_t in_max_retry_attempts)193 HostResolverSystemTask::Params::Params(
194 scoped_refptr<HostResolverProc> resolver_proc,
195 size_t in_max_retry_attempts)
196 : resolver_proc(std::move(resolver_proc)),
197 max_retry_attempts(in_max_retry_attempts),
198 unresponsive_delay(kDnsDefaultUnresponsiveDelay) {
199 // Maximum of 4 retry attempts for host resolution.
200 static const size_t kDefaultMaxRetryAttempts = 4u;
201 if (max_retry_attempts == kDefaultRetryAttempts)
202 max_retry_attempts = kDefaultMaxRetryAttempts;
203 }
204
205 HostResolverSystemTask::Params::Params(const Params& other) = default;
206
207 HostResolverSystemTask::Params::~Params() = default;
208
CacheParams(HostResolverCache & cache,NetworkAnonymizationKey network_anonymization_key)209 HostResolverSystemTask::CacheParams::CacheParams(
210 HostResolverCache& cache,
211 NetworkAnonymizationKey network_anonymization_key)
212 : cache(base::raw_ref(cache)),
213 network_anonymization_key(std::move(network_anonymization_key)) {}
214
215 HostResolverSystemTask::CacheParams::CacheParams(const CacheParams&) = default;
216
217 HostResolverSystemTask::CacheParams::CacheParams(CacheParams&&) = default;
218
219 HostResolverSystemTask::CacheParams::~CacheParams() = default;
220
221 // static
Create(std::string hostname,AddressFamily address_family,HostResolverFlags flags,const Params & params,const NetLogWithSource & job_net_log,handles::NetworkHandle network,std::optional<CacheParams> cache_params)222 std::unique_ptr<HostResolverSystemTask> HostResolverSystemTask::Create(
223 std::string hostname,
224 AddressFamily address_family,
225 HostResolverFlags flags,
226 const Params& params,
227 const NetLogWithSource& job_net_log,
228 handles::NetworkHandle network,
229 std::optional<CacheParams> cache_params) {
230 return std::make_unique<HostResolverSystemTask>(
231 std::move(hostname), address_family, flags, params, job_net_log, network,
232 std::move(cache_params));
233 }
234
235 // static
236 std::unique_ptr<HostResolverSystemTask>
CreateForOwnHostname(AddressFamily address_family,HostResolverFlags flags,const Params & params,const NetLogWithSource & job_net_log,handles::NetworkHandle network)237 HostResolverSystemTask::CreateForOwnHostname(
238 AddressFamily address_family,
239 HostResolverFlags flags,
240 const Params& params,
241 const NetLogWithSource& job_net_log,
242 handles::NetworkHandle network) {
243 return std::make_unique<HostResolverSystemTask>(
244 std::nullopt, address_family, flags, params, job_net_log, network,
245 /*cache_params=*/std::nullopt);
246 }
247
HostResolverSystemTask(std::optional<std::string> hostname,AddressFamily address_family,HostResolverFlags flags,const Params & params,const NetLogWithSource & job_net_log,handles::NetworkHandle network,std::optional<CacheParams> cache_params)248 HostResolverSystemTask::HostResolverSystemTask(
249 std::optional<std::string> hostname,
250 AddressFamily address_family,
251 HostResolverFlags flags,
252 const Params& params,
253 const NetLogWithSource& job_net_log,
254 handles::NetworkHandle network,
255 std::optional<CacheParams> cache_params)
256 : hostname_(std::move(hostname)),
257 address_family_(address_family),
258 flags_(flags),
259 params_(params),
260 net_log_(job_net_log),
261 network_(network),
262 cache_params_(std::move(cache_params)) {
263 // Must have hostname if results are to be cached.
264 CHECK(!cache_params_.has_value() || hostname_.has_value());
265
266 if (hostname_) {
267 // `hostname` should be a valid domain name. HostResolverManager has checks
268 // to fail early if this is not the case.
269 DCHECK(dns_names_util::IsValidDnsName(*hostname_))
270 << "Invalid hostname: " << *hostname_;
271 }
272 // If a resolver_proc has not been specified, try to use a default if one is
273 // set, as it may be in tests.
274 if (!params_.resolver_proc.get())
275 params_.resolver_proc = HostResolverProc::GetDefault();
276 }
277
278 // Cancels this HostResolverSystemTask. Any outstanding resolve attempts cannot
279 // be cancelled, but they will post back to the current thread before checking
280 // their WeakPtrs to find that this task is cancelled.
~HostResolverSystemTask()281 HostResolverSystemTask::~HostResolverSystemTask() {
282 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
283
284 // If this is cancellation, log the EndEvent (otherwise this was logged in
285 // OnLookupComplete()).
286 if (!was_completed())
287 net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_SYSTEM_TASK);
288 }
289
Start(SystemDnsResultsCallback results_cb)290 void HostResolverSystemTask::Start(SystemDnsResultsCallback results_cb) {
291 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
292 DCHECK(results_cb);
293 DCHECK(!results_cb_);
294 results_cb_ = std::move(results_cb);
295 net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_SYSTEM_TASK);
296 StartLookupAttempt();
297 }
298
StartLookupAttempt()299 void HostResolverSystemTask::StartLookupAttempt() {
300 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
301 DCHECK(!was_completed());
302 ++attempt_number_;
303
304 net_log_.AddEventWithIntParams(
305 NetLogEventType::HOST_RESOLVER_MANAGER_ATTEMPT_STARTED, "attempt_number",
306 attempt_number_);
307
308 // If the results aren't received within a given time, RetryIfNotComplete
309 // will start a new attempt if none of the outstanding attempts have
310 // completed yet.
311 // Use a WeakPtr to avoid keeping the HostResolverSystemTask alive after
312 // completion or cancellation.
313 if (attempt_number_ <= params_.max_retry_attempts) {
314 base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
315 FROM_HERE,
316 base::BindOnce(&HostResolverSystemTask::StartLookupAttempt,
317 weak_ptr_factory_.GetWeakPtr()),
318 params_.unresponsive_delay *
319 std::pow(params_.retry_factor, attempt_number_ - 1));
320 }
321
322 auto lookup_complete_cb =
323 base::BindOnce(&HostResolverSystemTask::OnLookupComplete,
324 weak_ptr_factory_.GetWeakPtr(), attempt_number_);
325
326 // If a hook has been installed, call it instead of posting a resolution task
327 // to a worker thread.
328 if (GetSystemDnsResolverOverride()) {
329 GetSystemDnsResolverOverride().Run(hostname_, address_family_, flags_,
330 std::move(lookup_complete_cb), network_);
331 // Do not add code below. `lookup_complete_cb` may have already deleted
332 // `this`.
333 } else {
334 base::OnceCallback<int(AddressList * addrlist, int* os_error)> resolve_cb =
335 base::BindOnce(&ResolveOnWorkerThread, params_.resolver_proc, hostname_,
336 address_family_, flags_, network_);
337 PostSystemDnsResolutionTaskAndReply(std::move(resolve_cb),
338 std::move(lookup_complete_cb));
339 }
340 }
341
342 // Callback for when DoLookup() completes.
OnLookupComplete(const uint32_t attempt_number,const AddressList & results,const int os_error,int error)343 void HostResolverSystemTask::OnLookupComplete(const uint32_t attempt_number,
344 const AddressList& results,
345 const int os_error,
346 int error) {
347 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
348 DCHECK(!was_completed());
349
350 TRACE_EVENT0(NetTracingCategory(),
351 "HostResolverSystemTask::OnLookupComplete");
352
353 // Invalidate WeakPtrs to cancel handling of all outstanding lookup attempts
354 // and retries.
355 weak_ptr_factory_.InvalidateWeakPtrs();
356
357 // If results are empty, we should return an error.
358 bool empty_list_on_ok = (error == OK && results.empty());
359 if (empty_list_on_ok)
360 error = ERR_NAME_NOT_RESOLVED;
361
362 if (error != OK && NetworkChangeNotifier::IsOffline())
363 error = ERR_INTERNET_DISCONNECTED;
364
365 if (error != OK) {
366 net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_SYSTEM_TASK, [&] {
367 return NetLogHostResolverSystemTaskFailedParams(0, error, os_error);
368 });
369 net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_ATTEMPT_FINISHED,
370 [&] {
371 return NetLogHostResolverSystemTaskFailedParams(
372 attempt_number, error, os_error);
373 });
374 } else {
375 net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_SYSTEM_TASK,
376 [&] { return results.NetLogParams(); });
377 net_log_.AddEventWithIntParams(
378 NetLogEventType::HOST_RESOLVER_MANAGER_ATTEMPT_FINISHED,
379 "attempt_number", attempt_number);
380 }
381
382 MaybeCacheResults(results);
383
384 std::move(results_cb_).Run(results, os_error, error);
385 // Running |results_cb_| can delete |this|.
386 }
387
MaybeCacheResults(const AddressList & address_list)388 void HostResolverSystemTask::MaybeCacheResults(
389 const AddressList& address_list) {
390 if (address_list.empty() || !cache_params_.has_value() ||
391 !base::FeatureList::IsEnabled(features::kUseHostResolverCache)) {
392 return;
393 }
394 CHECK(hostname_.has_value());
395
396 // Split out IPv4 and IPv6 endpoints while keeping them in the received order.
397 std::vector<IPEndPoint> ipv4;
398 std::vector<IPEndPoint> ipv6;
399 for (const IPEndPoint& endpoint : address_list) {
400 switch (endpoint.GetFamily()) {
401 case ADDRESS_FAMILY_IPV4:
402 ipv4.push_back(endpoint);
403 break;
404 case ADDRESS_FAMILY_IPV6:
405 ipv6.push_back(endpoint);
406 break;
407 default:
408 // Expect only IPv4 and IPv6 endpoints from system resolver.
409 NOTREACHED();
410 }
411 }
412 CHECK(!ipv4.empty() || !ipv6.empty());
413
414 std::string_view domain_name = hostname_.value();
415 if (!address_list.dns_aliases().empty()) {
416 // Expect at most one alias from system resolver.
417 CHECK_EQ(address_list.dns_aliases().size(), 1u);
418
419 // Save one alias cache entry for each query type.
420 CacheAlias(std::string(domain_name), DnsQueryType::A,
421 address_list.dns_aliases().front());
422 CacheAlias(std::string(domain_name), DnsQueryType::AAAA,
423 address_list.dns_aliases().front());
424
425 domain_name = address_list.dns_aliases().front();
426 }
427
428 CacheEndpoints(std::string(domain_name), std::move(ipv4), DnsQueryType::A);
429 CacheEndpoints(std::string(domain_name), std::move(ipv6), DnsQueryType::AAAA);
430 }
431
CacheEndpoints(std::string domain_name,std::vector<IPEndPoint> endpoints,DnsQueryType query_type)432 void HostResolverSystemTask::CacheEndpoints(std::string domain_name,
433 std::vector<IPEndPoint> endpoints,
434 DnsQueryType query_type) {
435 if (endpoints.empty()) {
436 cache_params_.value().cache->Set(
437 std::make_unique<HostResolverInternalErrorResult>(
438 std::move(domain_name), query_type, base::TimeTicks::Now() + kTtl,
439 base::Time::Now() + kTtl,
440 HostResolverInternalResult::Source::kUnknown,
441 ERR_NAME_NOT_RESOLVED),
442 cache_params_.value().network_anonymization_key,
443 HostResolverSource::SYSTEM, /*secure=*/false);
444 } else {
445 cache_params_.value().cache->Set(
446 std::make_unique<HostResolverInternalDataResult>(
447 std::move(domain_name), query_type, base::TimeTicks::Now() + kTtl,
448 base::Time::Now() + kTtl,
449 HostResolverInternalResult::Source::kUnknown, std::move(endpoints),
450 std::vector<std::string>{}, std::vector<HostPortPair>{}),
451 cache_params_.value().network_anonymization_key,
452 HostResolverSource::SYSTEM, /*secure=*/false);
453 }
454 }
455
CacheAlias(std::string domain_name,DnsQueryType query_type,std::string target_name)456 void HostResolverSystemTask::CacheAlias(std::string domain_name,
457 DnsQueryType query_type,
458 std::string target_name) {
459 cache_params_.value().cache->Set(
460 std::make_unique<HostResolverInternalAliasResult>(
461 std::move(domain_name), query_type, base::TimeTicks::Now() + kTtl,
462 base::Time::Now() + kTtl,
463 HostResolverInternalResult::Source::kUnknown, std::move(target_name)),
464 cache_params_.value().network_anonymization_key,
465 HostResolverSource::SYSTEM, /*secure=*/false);
466 }
467
EnsureSystemHostResolverCallReady()468 void EnsureSystemHostResolverCallReady() {
469 EnsureDnsReloaderInit();
470 #if BUILDFLAG(IS_WIN)
471 EnsureWinsockInit();
472 #endif
473 }
474
475 namespace {
476
AddressFamilyToAF(AddressFamily address_family)477 int AddressFamilyToAF(AddressFamily address_family) {
478 switch (address_family) {
479 case ADDRESS_FAMILY_IPV4:
480 return AF_INET;
481 case ADDRESS_FAMILY_IPV6:
482 return AF_INET6;
483 case ADDRESS_FAMILY_UNSPECIFIED:
484 return AF_UNSPEC;
485 }
486 }
487
488 } // namespace
489
SystemHostResolverCall(const std::string & host,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error_opt,handles::NetworkHandle network)490 int SystemHostResolverCall(const std::string& host,
491 AddressFamily address_family,
492 HostResolverFlags host_resolver_flags,
493 AddressList* addrlist,
494 int* os_error_opt,
495 handles::NetworkHandle network) {
496 struct addrinfo hints = {0};
497 hints.ai_family = AddressFamilyToAF(address_family);
498
499 #if BUILDFLAG(IS_WIN)
500 // DO NOT USE AI_ADDRCONFIG ON WINDOWS.
501 //
502 // The following comment in <winsock2.h> is the best documentation I found
503 // on AI_ADDRCONFIG for Windows:
504 // Flags used in "hints" argument to getaddrinfo()
505 // - AI_ADDRCONFIG is supported starting with Vista
506 // - default is AI_ADDRCONFIG ON whether the flag is set or not
507 // because the performance penalty in not having ADDRCONFIG in
508 // the multi-protocol stack environment is severe;
509 // this defaulting may be disabled by specifying the AI_ALL flag,
510 // in that case AI_ADDRCONFIG must be EXPLICITLY specified to
511 // enable ADDRCONFIG behavior
512 //
513 // Not only is AI_ADDRCONFIG unnecessary, but it can be harmful. If the
514 // computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo
515 // to fail with WSANO_DATA (11004) for "localhost", probably because of the
516 // following note on AI_ADDRCONFIG in the MSDN getaddrinfo page:
517 // The IPv4 or IPv6 loopback address is not considered a valid global
518 // address.
519 // See http://crbug.com/5234.
520 //
521 // OpenBSD does not support it, either.
522 hints.ai_flags = 0;
523 #else
524 // On other operating systems, AI_ADDRCONFIG may reduce the amount of
525 // unnecessary DNS lookups, e.g. getaddrinfo() will not send a request for
526 // AAAA records if the current machine has no IPv6 addresses configured and
527 // therefore could not use the resulting AAAA record anyway. On some ancient
528 // routers, AAAA DNS queries won't be handled correctly and will cause
529 // multiple retransmitions and large latency spikes.
530 hints.ai_flags = AI_ADDRCONFIG;
531 #endif
532
533 // On Linux AI_ADDRCONFIG doesn't consider loopback addresses, even if only
534 // loopback addresses are configured. So don't use it when there are only
535 // loopback addresses. See loopback_only.h and
536 // https://fedoraproject.org/wiki/QA/Networking/NameResolution/ADDRCONFIG for
537 // a description of some of the issues AI_ADDRCONFIG can cause.
538 if (host_resolver_flags & HOST_RESOLVER_LOOPBACK_ONLY) {
539 hints.ai_flags &= ~AI_ADDRCONFIG;
540 }
541
542 if (host_resolver_flags & HOST_RESOLVER_CANONNAME)
543 hints.ai_flags |= AI_CANONNAME;
544
545 #if BUILDFLAG(IS_WIN)
546 // See crbug.com/1176970. Flag not documented (other than the declaration
547 // comment in ws2def.h) but confirmed by Microsoft to work for this purpose
548 // and be safe.
549 if (host_resolver_flags & HOST_RESOLVER_AVOID_MULTICAST)
550 hints.ai_flags |= AI_DNS_ONLY;
551 #endif // BUILDFLAG(IS_WIN)
552
553 // Restrict result set to only this socket type to avoid duplicates.
554 hints.ai_socktype = SOCK_STREAM;
555
556 // This function can block for a long time. Use ScopedBlockingCall to increase
557 // the current thread pool's capacity and thus avoid reducing CPU usage by the
558 // current process during that time.
559 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
560 base::BlockingType::WILL_BLOCK);
561 DnsReloaderMaybeReload();
562
563 auto [ai, err, os_error] = AddressInfo::Get(host, hints, nullptr, network);
564 bool should_retry = false;
565 // If the lookup was restricted (either by address family, or address
566 // detection), and the results where all localhost of a single family,
567 // maybe we should retry. There were several bugs related to these
568 // issues, for example http://crbug.com/42058 and http://crbug.com/49024
569 if ((hints.ai_family != AF_UNSPEC || hints.ai_flags & AI_ADDRCONFIG) && ai &&
570 ai->IsAllLocalhostOfOneFamily()) {
571 if (host_resolver_flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) {
572 hints.ai_family = AF_UNSPEC;
573 should_retry = true;
574 }
575 if (hints.ai_flags & AI_ADDRCONFIG) {
576 hints.ai_flags &= ~AI_ADDRCONFIG;
577 should_retry = true;
578 }
579 }
580 if (should_retry) {
581 std::tie(ai, err, os_error) =
582 AddressInfo::Get(host, hints, nullptr, network);
583 }
584
585 if (os_error_opt)
586 *os_error_opt = os_error;
587
588 if (!ai)
589 return err;
590
591 *addrlist = ai->CreateAddressList();
592 return OK;
593 }
594
SetSystemDnsResolutionTaskRunnerForTesting(scoped_refptr<base::TaskRunner> task_runner)595 void SetSystemDnsResolutionTaskRunnerForTesting( // IN-TEST
596 scoped_refptr<base::TaskRunner> task_runner) {
597 GetSystemDnsResolutionTaskRunnerOverride() = task_runner;
598 }
599
600 } // namespace net
601