blob: 0ced88c66c35ae892e9417cabb9d5723e35458c7 [file] [log] [blame]
[email protected]78eac2a2012-03-14 19:09:271// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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/dns_test_util.h"
6
[email protected]d9806a972014-02-26 18:14:577#include "base/big_endian.h"
[email protected]78eac2a2012-03-14 19:09:278#include "base/bind.h"
skyostil4891b25b2015-06-11 11:43:459#include "base/location.h"
Eric Orth828bd3ae2018-12-12 17:30:3610#include "base/numerics/safe_conversions.h"
skyostil4891b25b2015-06-11 11:43:4511#include "base/single_thread_task_runner.h"
[email protected]78eac2a2012-03-14 19:09:2712#include "base/sys_byteorder.h"
gabf767595f2016-05-11 18:50:3513#include "base/threading/thread_task_runner_handle.h"
[email protected]78eac2a2012-03-14 19:09:2714#include "net/base/io_buffer.h"
Eric Orth828bd3ae2018-12-12 17:30:3615#include "net/base/ip_address.h"
[email protected]78eac2a2012-03-14 19:09:2716#include "net/base/net_errors.h"
[email protected]0adcb2b2012-08-15 21:30:4617#include "net/dns/address_sorter.h"
Eric Orth394db1732019-08-27 20:09:3918#include "net/dns/dns_hosts.h"
[email protected]78eac2a2012-03-14 19:09:2719#include "net/dns/dns_query.h"
Eric Orthaf82b49a2020-02-01 01:48:5020#include "net/dns/dns_session.h"
Eric Orth9300cc62020-08-21 00:29:3421#include "net/dns/dns_socket_allocator.h"
tfarina77021d62015-10-11 20:19:0322#include "net/dns/dns_util.h"
Eric Orth069a3c6e2020-01-31 23:14:2423#include "net/dns/resolve_context.h"
[email protected]78eac2a2012-03-14 19:09:2724#include "testing/gtest/include/gtest/gtest.h"
25
26namespace net {
27namespace {
28
Eric Orth828bd3ae2018-12-12 17:30:3629const uint8_t kMalformedResponseHeader[] = {
30 // Header
31 0x00, 0x14, // Arbitrary ID
32 0x81, 0x80, // Standard query response, RA, no error
33 0x00, 0x01, // 1 question
34 0x00, 0x01, // 1 RR (answers)
35 0x00, 0x00, // 0 authority RRs
36 0x00, 0x00, // 0 additional RRs
37};
38
39// Create a response containing a valid question (as would normally be validated
40// in DnsTransaction) but completely missing a header-declared answer.
41std::unique_ptr<DnsResponse> CreateMalformedResponse(std::string hostname,
42 uint16_t type) {
43 std::string dns_name;
44 CHECK(DNSDomainFromDot(hostname, &dns_name));
45 DnsQuery query(0x14 /* id */, dns_name, type);
46
47 // Build response to simulate the barebones validation DnsResponse applies to
48 // responses received from the network.
49 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
50 sizeof(kMalformedResponseHeader) + query.question().size());
51 memcpy(buffer->data(), kMalformedResponseHeader,
52 sizeof(kMalformedResponseHeader));
53 memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
54 query.question().data(), query.question().size());
55
56 auto response = std::make_unique<DnsResponse>(buffer, buffer->size());
57 CHECK(response->InitParseWithoutQuery(buffer->size()));
58
59 return response;
60}
61
[email protected]daae1322013-09-05 18:26:5062class MockAddressSorter : public AddressSorter {
63 public:
Chris Watkins68b15032017-12-01 03:07:1364 ~MockAddressSorter() override = default;
Bence Békyd5e474c2018-08-02 18:45:0865 void Sort(const AddressList& list, CallbackType callback) const override {
[email protected]daae1322013-09-05 18:26:5066 // Do nothing.
Bence Békyd5e474c2018-08-02 18:45:0867 std::move(callback).Run(true, list);
[email protected]daae1322013-09-05 18:26:5068 }
69};
70
Eric Orth828bd3ae2018-12-12 17:30:3671DnsResourceRecord BuildCannonnameRecord(std::string name,
72 std::string cannonname) {
73 DCHECK(!name.empty());
74 DCHECK(!cannonname.empty());
75
76 DnsResourceRecord record;
77 record.name = std::move(name);
78 record.type = dns_protocol::kTypeCNAME;
79 record.klass = dns_protocol::kClassIN;
80 record.ttl = base::TimeDelta::FromDays(1).InSeconds();
81 CHECK(DNSDomainFromDot(cannonname, &record.owned_rdata));
82 record.rdata = record.owned_rdata;
83
84 return record;
85}
86
87// Note: This is not a fully compliant SOA record, merely the bare amount needed
88// in DnsRecord::ParseToAddressList() processessing. This record will not pass
89// RecordParsed validation.
90DnsResourceRecord BuildSoaRecord(std::string name) {
91 DCHECK(!name.empty());
92
93 DnsResourceRecord record;
94 record.name = std::move(name);
95 record.type = dns_protocol::kTypeSOA;
96 record.klass = dns_protocol::kClassIN;
97 record.ttl = base::TimeDelta::FromDays(1).InSeconds();
98 record.SetOwnedRdata("fake_rdata");
99
100 return record;
101}
102
103DnsResourceRecord BuildTextRecord(std::string name,
104 std::vector<std::string> text_strings) {
105 DCHECK(!name.empty());
106 DCHECK(!text_strings.empty());
107
108 DnsResourceRecord record;
109 record.name = std::move(name);
110 record.type = dns_protocol::kTypeTXT;
111 record.klass = dns_protocol::kClassIN;
112 record.ttl = base::TimeDelta::FromDays(1).InSeconds();
113
114 std::string rdata;
115 for (std::string text_string : text_strings) {
116 DCHECK(!text_string.empty());
117
dalykad3f6c32019-03-06 13:38:33118 rdata += base::checked_cast<unsigned char>(text_string.size());
Eric Orth828bd3ae2018-12-12 17:30:36119 rdata += std::move(text_string);
120 }
121 record.SetOwnedRdata(std::move(rdata));
122
123 return record;
124}
125
Eric Orthe9db8d232019-01-14 21:24:45126DnsResourceRecord BuildPointerRecord(std::string name,
127 std::string pointer_name) {
128 DCHECK(!name.empty());
129 DCHECK(!pointer_name.empty());
130
131 DnsResourceRecord record;
132 record.name = std::move(name);
133 record.type = dns_protocol::kTypePTR;
134 record.klass = dns_protocol::kClassIN;
135 record.ttl = base::TimeDelta::FromDays(1).InSeconds();
136 CHECK(DNSDomainFromDot(pointer_name, &record.owned_rdata));
137 record.rdata = record.owned_rdata;
138
139 return record;
140}
141
Eric Ortha625b042019-01-16 01:14:45142DnsResourceRecord BuildServiceRecord(std::string name,
143 TestServiceRecord service) {
144 DCHECK(!name.empty());
145 DCHECK(!service.target.empty());
146
147 DnsResourceRecord record;
148 record.name = std::move(name);
149 record.type = dns_protocol::kTypeSRV;
150 record.klass = dns_protocol::kClassIN;
151 record.ttl = base::TimeDelta::FromHours(5).InSeconds();
152
153 std::string rdata;
154 char num_buffer[2];
155 base::WriteBigEndian(num_buffer, service.priority);
156 rdata.append(num_buffer, 2);
157 base::WriteBigEndian(num_buffer, service.weight);
158 rdata.append(num_buffer, 2);
159 base::WriteBigEndian(num_buffer, service.port);
160 rdata.append(num_buffer, 2);
161 std::string dns_name;
162 CHECK(DNSDomainFromDot(service.target, &dns_name));
163 rdata += dns_name;
164
165 record.SetOwnedRdata(std::move(rdata));
166
167 return record;
168}
169
David Van Clevec719c882019-11-04 15:47:40170
David Van Clevec719c882019-11-04 15:47:40171
Daniel McArdle2daa3ec2020-06-03 16:05:48172DnsResourceRecord BuildIntegrityRecord(
173 std::string name,
174 const std::vector<uint8_t>& serialized_rdata) {
175 CHECK(!name.empty());
176
177 DnsResourceRecord record;
178 record.name = std::move(name);
179 record.type = dns_protocol::kExperimentalTypeIntegrity;
180 record.klass = dns_protocol::kClassIN;
181 record.ttl = base::TimeDelta::FromDays(1).InSeconds();
182
183 std::string serialized_rdata_str(serialized_rdata.begin(),
184 serialized_rdata.end());
185 record.SetOwnedRdata(std::move(serialized_rdata_str));
186
187 CHECK_EQ(record.rdata.data(), record.owned_rdata.data());
188
189 return record;
190}
191
[email protected]daae1322013-09-05 18:26:50192} // namespace
[email protected]78eac2a2012-03-14 19:09:27193
David Van Cleve34c74c72019-10-31 19:58:01194DnsResourceRecord BuildTestAddressRecord(std::string name,
195 const IPAddress& ip) {
196 DCHECK(!name.empty());
197 DCHECK(ip.IsValid());
198
199 DnsResourceRecord record;
200 record.name = std::move(name);
201 record.type = ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA;
202 record.klass = dns_protocol::kClassIN;
203 record.ttl = base::TimeDelta::FromDays(1).InSeconds();
204 record.SetOwnedRdata(net::IPAddressToPackedString(ip));
205
206 return record;
207}
208
David Van Clevec719c882019-11-04 15:47:40209
Eric Orth828bd3ae2018-12-12 17:30:36210std::unique_ptr<DnsResponse> BuildTestDnsResponse(std::string name,
211 const IPAddress& ip) {
212 DCHECK(ip.IsValid());
213
David Van Cleve34c74c72019-10-31 19:58:01214 std::vector<DnsResourceRecord> answers = {BuildTestAddressRecord(name, ip)};
Eric Orth828bd3ae2018-12-12 17:30:36215 std::string dns_name;
216 CHECK(DNSDomainFromDot(name, &dns_name));
217 base::Optional<DnsQuery> query(
218 base::in_place, 0, dns_name,
219 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA);
220 return std::make_unique<DnsResponse>(
221 0, false, std::move(answers),
222 std::vector<DnsResourceRecord>() /* authority_records */,
223 std::vector<DnsResourceRecord>() /* additional_records */, query);
224}
225
dalykc0ab0722019-03-14 17:00:58226std::unique_ptr<DnsResponse> BuildTestDnsResponseWithCname(
227 std::string name,
228 const IPAddress& ip,
229 std::string cannonname) {
Eric Orth828bd3ae2018-12-12 17:30:36230 DCHECK(ip.IsValid());
231 DCHECK(!cannonname.empty());
232
233 std::vector<DnsResourceRecord> answers = {
234 BuildCannonnameRecord(name, cannonname),
David Van Cleve34c74c72019-10-31 19:58:01235 BuildTestAddressRecord(cannonname, ip)};
Eric Orth828bd3ae2018-12-12 17:30:36236 std::string dns_name;
237 CHECK(DNSDomainFromDot(name, &dns_name));
238 base::Optional<DnsQuery> query(
239 base::in_place, 0, dns_name,
240 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA);
241 return std::make_unique<DnsResponse>(
242 0, false, std::move(answers),
243 std::vector<DnsResourceRecord>() /* authority_records */,
244 std::vector<DnsResourceRecord>() /* additional_records */, query);
245}
246
dalykc0ab0722019-03-14 17:00:58247std::unique_ptr<DnsResponse> BuildTestDnsTextResponse(
Eric Orth828bd3ae2018-12-12 17:30:36248 std::string name,
249 std::vector<std::vector<std::string>> text_records,
250 std::string answer_name) {
251 if (answer_name.empty())
252 answer_name = name;
253
254 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45255 for (std::vector<std::string>& text_record : text_records) {
Eric Orth828bd3ae2018-12-12 17:30:36256 answers.push_back(BuildTextRecord(answer_name, std::move(text_record)));
257 }
258
259 std::string dns_name;
260 CHECK(DNSDomainFromDot(name, &dns_name));
261 base::Optional<DnsQuery> query(base::in_place, 0, dns_name,
262 dns_protocol::kTypeTXT);
263
264 return std::make_unique<DnsResponse>(
265 0, false, std::move(answers),
266 std::vector<DnsResourceRecord>() /* authority_records */,
267 std::vector<DnsResourceRecord>() /* additional_records */, query);
268}
269
Eric Orthe9db8d232019-01-14 21:24:45270std::unique_ptr<DnsResponse> BuildTestDnsPointerResponse(
271 std::string name,
272 std::vector<std::string> pointer_names,
273 std::string answer_name) {
274 if (answer_name.empty())
275 answer_name = name;
276
277 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45278 for (std::string& pointer_name : pointer_names) {
Eric Orthe9db8d232019-01-14 21:24:45279 answers.push_back(BuildPointerRecord(answer_name, std::move(pointer_name)));
280 }
281
282 std::string dns_name;
283 CHECK(DNSDomainFromDot(name, &dns_name));
284 base::Optional<DnsQuery> query(base::in_place, 0, dns_name,
285 dns_protocol::kTypePTR);
286
287 return std::make_unique<DnsResponse>(
288 0, false, std::move(answers),
289 std::vector<DnsResourceRecord>() /* authority_records */,
290 std::vector<DnsResourceRecord>() /* additional_records */, query);
291}
292
dalykc0ab0722019-03-14 17:00:58293std::unique_ptr<DnsResponse> BuildTestDnsServiceResponse(
Eric Ortha625b042019-01-16 01:14:45294 std::string name,
295 std::vector<TestServiceRecord> service_records,
296 std::string answer_name) {
297 if (answer_name.empty())
298 answer_name = name;
299
300 std::vector<DnsResourceRecord> answers;
301 for (TestServiceRecord& service_record : service_records) {
302 answers.push_back(
303 BuildServiceRecord(answer_name, std::move(service_record)));
304 }
305
306 std::string dns_name;
307 CHECK(DNSDomainFromDot(name, &dns_name));
308 base::Optional<DnsQuery> query(base::in_place, 0, dns_name,
309 dns_protocol::kTypeSRV);
310
311 return std::make_unique<DnsResponse>(
312 0, false, std::move(answers),
313 std::vector<DnsResourceRecord>() /* authority_records */,
314 std::vector<DnsResourceRecord>() /* additional_records */, query);
315}
316
Daniel McArdle2daa3ec2020-06-03 16:05:48317std::unique_ptr<DnsResponse> BuildTestDnsIntegrityResponse(
318 std::string hostname,
319 const std::vector<uint8_t>& serialized_rdata) {
320 CHECK(!hostname.empty());
321
322 std::vector<DnsResourceRecord> answers{
323 BuildIntegrityRecord(hostname, serialized_rdata)};
324
325 std::string dns_name;
326 CHECK(DNSDomainFromDot(hostname, &dns_name));
327 base::Optional<DnsQuery> query(base::in_place, 0, dns_name,
328 dns_protocol::kExperimentalTypeIntegrity);
329
330 return std::make_unique<DnsResponse>(
331 0, false, std::move(answers),
332 std::vector<DnsResourceRecord>() /* authority_records */,
333 std::vector<DnsResourceRecord>() /* additional_records */, query);
334}
335
Eric Orth828bd3ae2018-12-12 17:30:36336MockDnsClientRule::Result::Result(ResultType type) : type(type) {}
337
338MockDnsClientRule::Result::Result(std::unique_ptr<DnsResponse> response)
339 : type(OK), response(std::move(response)) {}
340
341MockDnsClientRule::Result::Result(Result&& result) = default;
342
343MockDnsClientRule::Result::~Result() = default;
344
345MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(
346 Result&& result) = default;
347
Eric Orth502d5682019-04-12 00:21:33348MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
349 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13350 bool secure,
Eric Orth502d5682019-04-12 00:21:33351 Result result,
352 bool delay,
353 URLRequestContext* context)
354 : result(std::move(result)),
355 prefix(prefix),
356 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13357 secure(secure),
Eric Orth502d5682019-04-12 00:21:33358 delay(delay),
359 context(context) {}
360
361MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
362
Eric Orth3421db382019-10-20 02:35:52363// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
364class MockDnsTransactionFactory::MockTransaction
365 : public DnsTransaction,
366 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27367 public:
Eric Orth3421db382019-10-20 02:35:52368 MockTransaction(const MockDnsClientRuleList& rules,
369 const std::string& hostname,
370 uint16_t qtype,
371 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56372 bool force_doh_server_available,
Eric Orth3421db382019-10-20 02:35:52373 DnsConfig::SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56374 ResolveContext* resolve_context,
Eric Orth3421db382019-10-20 02:35:52375 DnsTransactionFactory::CallbackType callback)
376 : result_(MockDnsClientRule::FAIL),
377 hostname_(hostname),
378 qtype_(qtype),
379 callback_(std::move(callback)),
380 started_(false),
381 delayed_(false) {
Eric Orth7dc18e92020-02-13 20:27:56382 // Do not allow matching any rules if transaction is secure and no DoH
383 // servers are available.
384 if (!secure || force_doh_server_available ||
385 resolve_context->NumAvailableDohServers(
386 resolve_context->current_session_for_testing()) > 0) {
387 // Find the relevant rule which matches |qtype|, |secure|, prefix of
388 // |hostname|, and |url_request_context| (iff the rule context is not
389 // null).
390 for (size_t i = 0; i < rules.size(); ++i) {
391 const std::string& prefix = rules[i].prefix;
392 if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
393 (hostname.size() >= prefix.size()) &&
394 (hostname.compare(0, prefix.size(), prefix) == 0) &&
395 (!rules[i].context ||
396 rules[i].context == resolve_context->url_request_context())) {
397 const MockDnsClientRule::Result* result = &rules[i].result;
398 result_ = MockDnsClientRule::Result(result->type);
399 delayed_ = rules[i].delay;
[email protected]daae1322013-09-05 18:26:50400
Eric Orth7dc18e92020-02-13 20:27:56401 // Generate a DnsResponse when not provided with the rule.
402 std::vector<DnsResourceRecord> authority_records;
403 std::string dns_name;
404 CHECK(DNSDomainFromDot(hostname_, &dns_name));
405 base::Optional<DnsQuery> query(base::in_place, 22 /* id */, dns_name,
406 qtype_);
407 switch (result->type) {
408 case MockDnsClientRule::NODOMAIN:
409 case MockDnsClientRule::EMPTY:
410 DCHECK(!result->response); // Not expected to be provided.
411 authority_records = {BuildSoaRecord(hostname_)};
Eric Orth3421db382019-10-20 02:35:52412 result_.response = std::make_unique<DnsResponse>(
Eric Orth7dc18e92020-02-13 20:27:56413 22 /* id */, false /* is_authoritative */,
414 std::vector<DnsResourceRecord>() /* answers */,
415 authority_records,
416 std::vector<DnsResourceRecord>() /* additional_records */,
417 query,
418 result->type == MockDnsClientRule::NODOMAIN
419 ? dns_protocol::kRcodeNXDOMAIN
420 : 0);
421 break;
422 case MockDnsClientRule::FAIL:
423 case MockDnsClientRule::TIMEOUT:
424 DCHECK(!result->response); // Not expected to be provided.
425 break;
426 case MockDnsClientRule::OK:
427 if (result->response) {
428 // Copy response in case |rules| are destroyed before the
429 // transaction completes.
430 result_.response = std::make_unique<DnsResponse>(
431 result->response->io_buffer(),
432 result->response->io_buffer_size());
433 CHECK(result_.response->InitParseWithoutQuery(
434 result->response->io_buffer_size()));
435 } else {
436 // Generated response only available for address types.
437 DCHECK(qtype_ == dns_protocol::kTypeA ||
438 qtype_ == dns_protocol::kTypeAAAA);
439 result_.response = BuildTestDnsResponse(
440 hostname_, qtype_ == dns_protocol::kTypeA
441 ? IPAddress::IPv4Localhost()
442 : IPAddress::IPv6Localhost());
443 }
444 break;
445 case MockDnsClientRule::MALFORMED:
446 DCHECK(!result->response); // Not expected to be provided.
447 result_.response = CreateMalformedResponse(hostname_, qtype_);
448 break;
449 }
Eric Orth2a61be82020-02-12 17:56:48450
Eric Orth7dc18e92020-02-13 20:27:56451 break;
452 }
Eric Orth3421db382019-10-20 02:35:52453 }
[email protected]daae1322013-09-05 18:26:50454 }
[email protected]0adcb2b2012-08-15 21:30:46455 }
456
Eric Orth3421db382019-10-20 02:35:52457 const std::string& GetHostname() const override { return hostname_; }
[email protected]daae1322013-09-05 18:26:50458
Eric Orth3421db382019-10-20 02:35:52459 uint16_t GetType() const override { return qtype_; }
460
461 void Start() override {
462 EXPECT_FALSE(started_);
463 started_ = true;
464 if (delayed_)
465 return;
466 // Using WeakPtr to cleanly cancel when transaction is destroyed.
467 base::ThreadTaskRunnerHandle::Get()->PostTask(
468 FROM_HERE, base::BindOnce(&MockTransaction::Finish, AsWeakPtr()));
469 }
470
471 void FinishDelayedTransaction() {
472 EXPECT_TRUE(delayed_);
473 delayed_ = false;
474 Finish();
475 }
476
477 bool delayed() const { return delayed_; }
478
479 private:
480 void Finish() {
481 switch (result_.type) {
482 case MockDnsClientRule::NODOMAIN:
483 case MockDnsClientRule::FAIL:
484 std::move(callback_).Run(this, ERR_NAME_NOT_RESOLVED,
Daniel McArdle4e2037e2020-06-11 22:40:51485 result_.response.get(), base::nullopt);
Eric Orth3421db382019-10-20 02:35:52486 break;
487 case MockDnsClientRule::EMPTY:
488 case MockDnsClientRule::OK:
489 case MockDnsClientRule::MALFORMED:
Daniel McArdle4e2037e2020-06-11 22:40:51490 std::move(callback_).Run(this, OK, result_.response.get(),
491 base::nullopt);
Eric Orth3421db382019-10-20 02:35:52492 break;
493 case MockDnsClientRule::TIMEOUT:
Daniel McArdle4e2037e2020-06-11 22:40:51494 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
495 base::nullopt);
Eric Orth3421db382019-10-20 02:35:52496 break;
497 }
498 }
499
500 void SetRequestPriority(RequestPriority priority) override {}
501
502 MockDnsClientRule::Result result_;
503 const std::string hostname_;
504 const uint16_t qtype_;
505 DnsTransactionFactory::CallbackType callback_;
506 bool started_;
507 bool delayed_;
[email protected]0adcb2b2012-08-15 21:30:46508};
509
Eric Orth41b249e02020-01-03 20:21:47510class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
511 public:
512 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
513 : factory_(std::move(factory)) {}
514
515 ~MockDohProbeRunner() override {
516 if (factory_)
517 factory_->running_doh_probe_runners_.erase(this);
518 }
519
Eric Orth020e5fe2020-03-12 17:43:43520 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47521 DCHECK(factory_);
522 factory_->running_doh_probe_runners_.insert(this);
523 }
524
Eric Orth41b249e02020-01-03 20:21:47525 base::TimeDelta GetDelayUntilNextProbeForTest(
526 size_t doh_server_index) const override {
527 NOTREACHED();
528 return base::TimeDelta();
529 }
530
531 private:
532 base::WeakPtr<MockDnsTransactionFactory> factory_;
533};
534
Eric Orth3421db382019-10-20 02:35:52535MockDnsTransactionFactory::MockDnsTransactionFactory(
536 MockDnsClientRuleList rules)
537 : rules_(std::move(rules)) {}
538
539MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
540
541std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
542 const std::string& hostname,
543 uint16_t qtype,
544 DnsTransactionFactory::CallbackType callback,
545 const NetLogWithSource&,
546 bool secure,
547 DnsConfig::SecureDnsMode secure_dns_mode,
Eric Orth069a3c6e2020-01-31 23:14:24548 ResolveContext* resolve_context) {
Eric Orth3421db382019-10-20 02:35:52549 std::unique_ptr<MockTransaction> transaction =
Eric Orth069a3c6e2020-01-31 23:14:24550 std::make_unique<MockTransaction>(
Eric Orth7dc18e92020-02-13 20:27:56551 rules_, hostname, qtype, secure, force_doh_server_available_,
552 secure_dns_mode, resolve_context, std::move(callback));
Eric Orth3421db382019-10-20 02:35:52553 if (transaction->delayed())
554 delayed_transactions_.push_back(transaction->AsWeakPtr());
555 return transaction;
556}
557
Eric Orth41b249e02020-01-03 20:21:47558std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24559 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47560 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
561}
562
Eric Orth3421db382019-10-20 02:35:52563void MockDnsTransactionFactory::AddEDNSOption(const OptRecordRdata::Opt& opt) {}
564
Eric Orth3421db382019-10-20 02:35:52565DnsConfig::SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
566 return DnsConfig::SecureDnsMode::AUTOMATIC;
567}
568
569void MockDnsTransactionFactory::CompleteDelayedTransactions() {
570 DelayedTransactionList old_delayed_transactions;
571 old_delayed_transactions.swap(delayed_transactions_);
572 for (auto it = old_delayed_transactions.begin();
573 it != old_delayed_transactions.end(); ++it) {
574 if (it->get())
575 (*it)->FinishDelayedTransaction();
576 }
577}
578
David Van Cleve1fb5e8c2019-11-04 16:45:16579bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
580 DnsQueryType type) {
581 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
582 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
583 t->FinishDelayedTransaction();
584 t.reset();
585 return true;
586 }
587 }
588 return false;
589}
590
Eric Orth394db1732019-08-27 20:09:39591MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
592 : config_(std::move(config)),
Eric Orth3421db382019-10-20 02:35:52593 factory_(new MockDnsTransactionFactory(std::move(rules))),
Eric Orth394db1732019-08-27 20:09:39594 address_sorter_(new MockAddressSorter()) {
595 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50596 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39597}
[email protected]78eac2a2012-03-14 19:09:27598
Chris Watkins68b15032017-12-01 03:07:13599MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27600
Eric Orth394db1732019-08-27 20:09:39601bool MockDnsClient::CanUseSecureDnsTransactions() const {
602 const DnsConfig* config = GetEffectiveConfig();
603 return config && config->IsValid() && !config->dns_over_https_servers.empty();
[email protected]daae1322013-09-05 18:26:50604}
[email protected]78eac2a2012-03-14 19:09:27605
Eric Orth394db1732019-08-27 20:09:39606bool MockDnsClient::CanUseInsecureDnsTransactions() const {
607 const DnsConfig* config = GetEffectiveConfig();
608 return config && config->IsValid() && insecure_enabled_ &&
609 !config->dns_over_tls_active;
610}
611
612void MockDnsClient::SetInsecureEnabled(bool enabled) {
613 insecure_enabled_ = enabled;
614}
615
Eric Orth069a3c6e2020-01-31 23:14:24616bool MockDnsClient::FallbackFromSecureTransactionPreferred(
617 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56618 bool doh_server_available =
619 force_doh_server_available_ ||
620 context->NumAvailableDohServers(session_.get()) > 0;
621 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22622}
623
Eric Orth394db1732019-08-27 20:09:39624bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
625 return !CanUseInsecureDnsTransactions() ||
626 fallback_failures_ >= max_fallback_failures_;
627}
628
629bool MockDnsClient::SetSystemConfig(base::Optional<DnsConfig> system_config) {
630 if (ignore_system_config_changes_)
631 return false;
632
633 base::Optional<DnsConfig> before = effective_config_;
634 config_ = std::move(system_config);
635 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50636 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39637 return before != effective_config_;
638}
639
640bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
641 base::Optional<DnsConfig> before = effective_config_;
642 overrides_ = std::move(config_overrides);
643 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50644 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39645 return before != effective_config_;
646}
647
Eric Orth020e5fe2020-03-12 17:43:43648void MockDnsClient::ReplaceCurrentSession() {
649 // Noop if no current effective config.
650 session_ = BuildSession();
651}
652
Eric Orthaf82b49a2020-02-01 01:48:50653DnsSession* MockDnsClient::GetCurrentSession() {
654 return session_.get();
655}
656
Eric Orth394db1732019-08-27 20:09:39657const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
658 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
659}
660
661const DnsHosts* MockDnsClient::GetHosts() const {
662 const DnsConfig* config = GetEffectiveConfig();
663 if (!config)
664 return nullptr;
665
666 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50667}
[email protected]78eac2a2012-03-14 19:09:27668
[email protected]daae1322013-09-05 18:26:50669DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39670 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50671}
[email protected]78eac2a2012-03-14 19:09:27672
[email protected]daae1322013-09-05 18:26:50673AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39674 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
675}
676
677void MockDnsClient::IncrementInsecureFallbackFailures() {
678 ++fallback_failures_;
679}
680
681void MockDnsClient::ClearInsecureFallbackFailures() {
682 fallback_failures_ = 0;
683}
684
685base::Optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
686 return config_;
687}
688
689DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
690 return overrides_;
[email protected]daae1322013-09-05 18:26:50691}
[email protected]0adcb2b2012-08-15 21:30:46692
Eric Orth3421db382019-10-20 02:35:52693void MockDnsClient::SetTransactionFactoryForTesting(
694 std::unique_ptr<DnsTransactionFactory> factory) {
695 NOTREACHED();
696}
697
[email protected]daae1322013-09-05 18:26:50698void MockDnsClient::CompleteDelayedTransactions() {
699 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27700}
701
David Van Cleve1fb5e8c2019-11-04 16:45:16702bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
703 return factory_->CompleteOneDelayedTransactionOfType(type);
704}
705
Eric Orth7dc18e92020-02-13 20:27:56706void MockDnsClient::SetForceDohServerAvailable(bool available) {
707 force_doh_server_available_ = available;
708 factory_->set_force_doh_server_available(available);
709}
710
Eric Orth394db1732019-08-27 20:09:39711base::Optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
712 if (overrides_.OverridesEverything())
713 return overrides_.ApplyOverrides(DnsConfig());
714 if (!config_ || !config_.value().IsValid())
715 return base::nullopt;
716
717 return overrides_.ApplyOverrides(config_.value());
718}
719
Eric Orthaf82b49a2020-02-01 01:48:50720scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
721 if (!effective_config_)
722 return nullptr;
723
724 // Session not expected to be used for anything that will actually require
725 // random numbers.
726 auto null_random_callback =
727 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
728
Eric Orth9300cc62020-08-21 00:29:34729 auto socket_allocator = std::make_unique<DnsSocketAllocator>(
Eric Orth990a74a92020-08-20 18:41:26730 &socket_factory_, effective_config_.value().nameservers,
731 nullptr /* net_log */);
732
Eric Orthaf82b49a2020-02-01 01:48:50733 return base::MakeRefCounted<DnsSession>(
Eric Orth9300cc62020-08-21 00:29:34734 effective_config_.value(), std::move(socket_allocator),
735 null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50736}
737
[email protected]78eac2a2012-03-14 19:09:27738} // namespace net