blob: 00ff9eab7aac5b3d151dd1ad4f43f35c8599d08a [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 Orth89726dd2020-10-13 20:19:53336MockDnsClientRule::Result::Result(ResultType type,
337 std::unique_ptr<DnsResponse> response)
338 : type(type), response(std::move(response)) {}
Eric Orth828bd3ae2018-12-12 17:30:36339
340MockDnsClientRule::Result::Result(std::unique_ptr<DnsResponse> response)
341 : type(OK), response(std::move(response)) {}
342
343MockDnsClientRule::Result::Result(Result&& result) = default;
344
345MockDnsClientRule::Result::~Result() = default;
346
347MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(
348 Result&& result) = default;
349
Eric Orth502d5682019-04-12 00:21:33350MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
351 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13352 bool secure,
Eric Orth502d5682019-04-12 00:21:33353 Result result,
354 bool delay,
355 URLRequestContext* context)
356 : result(std::move(result)),
357 prefix(prefix),
358 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13359 secure(secure),
Eric Orth502d5682019-04-12 00:21:33360 delay(delay),
361 context(context) {}
362
363MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
364
Eric Orth3421db382019-10-20 02:35:52365// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
366class MockDnsTransactionFactory::MockTransaction
367 : public DnsTransaction,
368 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27369 public:
Eric Orth3421db382019-10-20 02:35:52370 MockTransaction(const MockDnsClientRuleList& rules,
371 const std::string& hostname,
372 uint16_t qtype,
373 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56374 bool force_doh_server_available,
Eric Ortha093b092020-09-24 23:13:02375 SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56376 ResolveContext* resolve_context,
Eric Orth89726dd2020-10-13 20:19:53377 bool fast_timeout,
Eric Orth3421db382019-10-20 02:35:52378 DnsTransactionFactory::CallbackType callback)
379 : result_(MockDnsClientRule::FAIL),
380 hostname_(hostname),
381 qtype_(qtype),
382 callback_(std::move(callback)),
383 started_(false),
384 delayed_(false) {
Eric Orth7dc18e92020-02-13 20:27:56385 // Do not allow matching any rules if transaction is secure and no DoH
386 // servers are available.
387 if (!secure || force_doh_server_available ||
388 resolve_context->NumAvailableDohServers(
389 resolve_context->current_session_for_testing()) > 0) {
390 // Find the relevant rule which matches |qtype|, |secure|, prefix of
391 // |hostname|, and |url_request_context| (iff the rule context is not
392 // null).
393 for (size_t i = 0; i < rules.size(); ++i) {
394 const std::string& prefix = rules[i].prefix;
395 if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
396 (hostname.size() >= prefix.size()) &&
397 (hostname.compare(0, prefix.size(), prefix) == 0) &&
398 (!rules[i].context ||
399 rules[i].context == resolve_context->url_request_context())) {
400 const MockDnsClientRule::Result* result = &rules[i].result;
401 result_ = MockDnsClientRule::Result(result->type);
402 delayed_ = rules[i].delay;
[email protected]daae1322013-09-05 18:26:50403
Eric Orth7dc18e92020-02-13 20:27:56404 // Generate a DnsResponse when not provided with the rule.
405 std::vector<DnsResourceRecord> authority_records;
406 std::string dns_name;
407 CHECK(DNSDomainFromDot(hostname_, &dns_name));
408 base::Optional<DnsQuery> query(base::in_place, 22 /* id */, dns_name,
409 qtype_);
410 switch (result->type) {
411 case MockDnsClientRule::NODOMAIN:
412 case MockDnsClientRule::EMPTY:
413 DCHECK(!result->response); // Not expected to be provided.
414 authority_records = {BuildSoaRecord(hostname_)};
Eric Orth3421db382019-10-20 02:35:52415 result_.response = std::make_unique<DnsResponse>(
Eric Orth7dc18e92020-02-13 20:27:56416 22 /* id */, false /* is_authoritative */,
417 std::vector<DnsResourceRecord>() /* answers */,
418 authority_records,
419 std::vector<DnsResourceRecord>() /* additional_records */,
420 query,
421 result->type == MockDnsClientRule::NODOMAIN
422 ? dns_protocol::kRcodeNXDOMAIN
423 : 0);
424 break;
425 case MockDnsClientRule::FAIL:
426 case MockDnsClientRule::TIMEOUT:
427 DCHECK(!result->response); // Not expected to be provided.
428 break;
Eric Orth89726dd2020-10-13 20:19:53429 case MockDnsClientRule::SLOW:
430 if (!fast_timeout)
431 SetResponse(result);
432 break;
Eric Orth7dc18e92020-02-13 20:27:56433 case MockDnsClientRule::OK:
Eric Orth89726dd2020-10-13 20:19:53434 SetResponse(result);
Eric Orth7dc18e92020-02-13 20:27:56435 break;
436 case MockDnsClientRule::MALFORMED:
437 DCHECK(!result->response); // Not expected to be provided.
438 result_.response = CreateMalformedResponse(hostname_, qtype_);
439 break;
440 }
Eric Orth2a61be82020-02-12 17:56:48441
Eric Orth7dc18e92020-02-13 20:27:56442 break;
443 }
Eric Orth3421db382019-10-20 02:35:52444 }
[email protected]daae1322013-09-05 18:26:50445 }
[email protected]0adcb2b2012-08-15 21:30:46446 }
447
Eric Orth3421db382019-10-20 02:35:52448 const std::string& GetHostname() const override { return hostname_; }
[email protected]daae1322013-09-05 18:26:50449
Eric Orth3421db382019-10-20 02:35:52450 uint16_t GetType() const override { return qtype_; }
451
452 void Start() override {
453 EXPECT_FALSE(started_);
454 started_ = true;
455 if (delayed_)
456 return;
457 // Using WeakPtr to cleanly cancel when transaction is destroyed.
458 base::ThreadTaskRunnerHandle::Get()->PostTask(
459 FROM_HERE, base::BindOnce(&MockTransaction::Finish, AsWeakPtr()));
460 }
461
462 void FinishDelayedTransaction() {
463 EXPECT_TRUE(delayed_);
464 delayed_ = false;
465 Finish();
466 }
467
468 bool delayed() const { return delayed_; }
469
470 private:
Eric Orth89726dd2020-10-13 20:19:53471 void SetResponse(const MockDnsClientRule::Result* result) {
472 if (result->response) {
473 // Copy response in case |result| is destroyed before the transaction
474 // completes.
475 result_.response = std::make_unique<DnsResponse>(
476 result->response->io_buffer(), result->response->io_buffer_size());
477 CHECK(result_.response->InitParseWithoutQuery(
478 result->response->io_buffer_size()));
479 } else {
480 // Generated response only available for address types.
481 DCHECK(qtype_ == dns_protocol::kTypeA ||
482 qtype_ == dns_protocol::kTypeAAAA);
483 result_.response =
484 BuildTestDnsResponse(hostname_, qtype_ == dns_protocol::kTypeA
485 ? IPAddress::IPv4Localhost()
486 : IPAddress::IPv6Localhost());
487 }
488 }
489
Eric Orth3421db382019-10-20 02:35:52490 void Finish() {
491 switch (result_.type) {
492 case MockDnsClientRule::NODOMAIN:
493 case MockDnsClientRule::FAIL:
494 std::move(callback_).Run(this, ERR_NAME_NOT_RESOLVED,
Daniel McArdle4e2037e2020-06-11 22:40:51495 result_.response.get(), base::nullopt);
Eric Orth3421db382019-10-20 02:35:52496 break;
497 case MockDnsClientRule::EMPTY:
498 case MockDnsClientRule::OK:
499 case MockDnsClientRule::MALFORMED:
Daniel McArdle4e2037e2020-06-11 22:40:51500 std::move(callback_).Run(this, OK, result_.response.get(),
501 base::nullopt);
Eric Orth3421db382019-10-20 02:35:52502 break;
503 case MockDnsClientRule::TIMEOUT:
Daniel McArdle4e2037e2020-06-11 22:40:51504 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
505 base::nullopt);
Eric Orth3421db382019-10-20 02:35:52506 break;
Eric Orth89726dd2020-10-13 20:19:53507 case MockDnsClientRule::SLOW:
508 if (result_.response) {
509 std::move(callback_).Run(this, OK, result_.response.get(),
510 base::nullopt);
511 } else {
512 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
513 base::nullopt);
514 }
Eric Orth3421db382019-10-20 02:35:52515 }
516 }
517
518 void SetRequestPriority(RequestPriority priority) override {}
519
520 MockDnsClientRule::Result result_;
521 const std::string hostname_;
522 const uint16_t qtype_;
523 DnsTransactionFactory::CallbackType callback_;
524 bool started_;
525 bool delayed_;
[email protected]0adcb2b2012-08-15 21:30:46526};
527
Eric Orth41b249e02020-01-03 20:21:47528class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
529 public:
530 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
531 : factory_(std::move(factory)) {}
532
533 ~MockDohProbeRunner() override {
534 if (factory_)
535 factory_->running_doh_probe_runners_.erase(this);
536 }
537
Eric Orth020e5fe2020-03-12 17:43:43538 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47539 DCHECK(factory_);
540 factory_->running_doh_probe_runners_.insert(this);
541 }
542
Eric Orth41b249e02020-01-03 20:21:47543 base::TimeDelta GetDelayUntilNextProbeForTest(
544 size_t doh_server_index) const override {
545 NOTREACHED();
546 return base::TimeDelta();
547 }
548
549 private:
550 base::WeakPtr<MockDnsTransactionFactory> factory_;
551};
552
Eric Orth3421db382019-10-20 02:35:52553MockDnsTransactionFactory::MockDnsTransactionFactory(
554 MockDnsClientRuleList rules)
555 : rules_(std::move(rules)) {}
556
557MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
558
559std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
560 const std::string& hostname,
561 uint16_t qtype,
562 DnsTransactionFactory::CallbackType callback,
563 const NetLogWithSource&,
564 bool secure,
Eric Ortha093b092020-09-24 23:13:02565 SecureDnsMode secure_dns_mode,
Eric Orth89726dd2020-10-13 20:19:53566 ResolveContext* resolve_context,
567 bool fast_timeout) {
Eric Orth3421db382019-10-20 02:35:52568 std::unique_ptr<MockTransaction> transaction =
Eric Orth069a3c6e2020-01-31 23:14:24569 std::make_unique<MockTransaction>(
Eric Orth7dc18e92020-02-13 20:27:56570 rules_, hostname, qtype, secure, force_doh_server_available_,
Eric Orth89726dd2020-10-13 20:19:53571 secure_dns_mode, resolve_context, fast_timeout, std::move(callback));
Eric Orth3421db382019-10-20 02:35:52572 if (transaction->delayed())
573 delayed_transactions_.push_back(transaction->AsWeakPtr());
574 return transaction;
575}
576
Eric Orth41b249e02020-01-03 20:21:47577std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24578 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47579 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
580}
581
Eric Orth3421db382019-10-20 02:35:52582void MockDnsTransactionFactory::AddEDNSOption(const OptRecordRdata::Opt& opt) {}
583
Eric Ortha093b092020-09-24 23:13:02584SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
585 return SecureDnsMode::kAutomatic;
Eric Orth3421db382019-10-20 02:35:52586}
587
588void MockDnsTransactionFactory::CompleteDelayedTransactions() {
589 DelayedTransactionList old_delayed_transactions;
590 old_delayed_transactions.swap(delayed_transactions_);
591 for (auto it = old_delayed_transactions.begin();
592 it != old_delayed_transactions.end(); ++it) {
593 if (it->get())
594 (*it)->FinishDelayedTransaction();
595 }
596}
597
David Van Cleve1fb5e8c2019-11-04 16:45:16598bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
599 DnsQueryType type) {
600 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
601 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
602 t->FinishDelayedTransaction();
603 t.reset();
604 return true;
605 }
606 }
607 return false;
608}
609
Eric Orth394db1732019-08-27 20:09:39610MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
611 : config_(std::move(config)),
Eric Orth3421db382019-10-20 02:35:52612 factory_(new MockDnsTransactionFactory(std::move(rules))),
Eric Orth394db1732019-08-27 20:09:39613 address_sorter_(new MockAddressSorter()) {
614 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50615 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39616}
[email protected]78eac2a2012-03-14 19:09:27617
Chris Watkins68b15032017-12-01 03:07:13618MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27619
Eric Orth394db1732019-08-27 20:09:39620bool MockDnsClient::CanUseSecureDnsTransactions() const {
621 const DnsConfig* config = GetEffectiveConfig();
622 return config && config->IsValid() && !config->dns_over_https_servers.empty();
[email protected]daae1322013-09-05 18:26:50623}
[email protected]78eac2a2012-03-14 19:09:27624
Eric Orth394db1732019-08-27 20:09:39625bool MockDnsClient::CanUseInsecureDnsTransactions() const {
626 const DnsConfig* config = GetEffectiveConfig();
627 return config && config->IsValid() && insecure_enabled_ &&
628 !config->dns_over_tls_active;
629}
630
631void MockDnsClient::SetInsecureEnabled(bool enabled) {
632 insecure_enabled_ = enabled;
633}
634
Eric Orth069a3c6e2020-01-31 23:14:24635bool MockDnsClient::FallbackFromSecureTransactionPreferred(
636 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56637 bool doh_server_available =
638 force_doh_server_available_ ||
639 context->NumAvailableDohServers(session_.get()) > 0;
640 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22641}
642
Eric Orth394db1732019-08-27 20:09:39643bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
644 return !CanUseInsecureDnsTransactions() ||
645 fallback_failures_ >= max_fallback_failures_;
646}
647
648bool MockDnsClient::SetSystemConfig(base::Optional<DnsConfig> system_config) {
649 if (ignore_system_config_changes_)
650 return false;
651
652 base::Optional<DnsConfig> before = effective_config_;
653 config_ = std::move(system_config);
654 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50655 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39656 return before != effective_config_;
657}
658
659bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
660 base::Optional<DnsConfig> before = effective_config_;
661 overrides_ = std::move(config_overrides);
662 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50663 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39664 return before != effective_config_;
665}
666
Eric Orth020e5fe2020-03-12 17:43:43667void MockDnsClient::ReplaceCurrentSession() {
668 // Noop if no current effective config.
669 session_ = BuildSession();
670}
671
Eric Orthaf82b49a2020-02-01 01:48:50672DnsSession* MockDnsClient::GetCurrentSession() {
673 return session_.get();
674}
675
Eric Orth394db1732019-08-27 20:09:39676const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
677 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
678}
679
680const DnsHosts* MockDnsClient::GetHosts() const {
681 const DnsConfig* config = GetEffectiveConfig();
682 if (!config)
683 return nullptr;
684
685 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50686}
[email protected]78eac2a2012-03-14 19:09:27687
[email protected]daae1322013-09-05 18:26:50688DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39689 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50690}
[email protected]78eac2a2012-03-14 19:09:27691
[email protected]daae1322013-09-05 18:26:50692AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39693 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
694}
695
696void MockDnsClient::IncrementInsecureFallbackFailures() {
697 ++fallback_failures_;
698}
699
700void MockDnsClient::ClearInsecureFallbackFailures() {
701 fallback_failures_ = 0;
702}
703
704base::Optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
705 return config_;
706}
707
708DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
709 return overrides_;
[email protected]daae1322013-09-05 18:26:50710}
[email protected]0adcb2b2012-08-15 21:30:46711
Eric Orth3421db382019-10-20 02:35:52712void MockDnsClient::SetTransactionFactoryForTesting(
713 std::unique_ptr<DnsTransactionFactory> factory) {
714 NOTREACHED();
715}
716
[email protected]daae1322013-09-05 18:26:50717void MockDnsClient::CompleteDelayedTransactions() {
718 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27719}
720
David Van Cleve1fb5e8c2019-11-04 16:45:16721bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
722 return factory_->CompleteOneDelayedTransactionOfType(type);
723}
724
Eric Orth7dc18e92020-02-13 20:27:56725void MockDnsClient::SetForceDohServerAvailable(bool available) {
726 force_doh_server_available_ = available;
727 factory_->set_force_doh_server_available(available);
728}
729
Eric Orth394db1732019-08-27 20:09:39730base::Optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
731 if (overrides_.OverridesEverything())
732 return overrides_.ApplyOverrides(DnsConfig());
733 if (!config_ || !config_.value().IsValid())
734 return base::nullopt;
735
736 return overrides_.ApplyOverrides(config_.value());
737}
738
Eric Orthaf82b49a2020-02-01 01:48:50739scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
740 if (!effective_config_)
741 return nullptr;
742
743 // Session not expected to be used for anything that will actually require
744 // random numbers.
745 auto null_random_callback =
746 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
747
Eric Orth9300cc62020-08-21 00:29:34748 auto socket_allocator = std::make_unique<DnsSocketAllocator>(
Eric Orth990a74a92020-08-20 18:41:26749 &socket_factory_, effective_config_.value().nameservers,
750 nullptr /* net_log */);
751
Eric Orthaf82b49a2020-02-01 01:48:50752 return base::MakeRefCounted<DnsSession>(
Eric Orth9300cc62020-08-21 00:29:34753 effective_config_.value(), std::move(socket_allocator),
754 null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50755}
756
[email protected]78eac2a2012-03-14 19:09:27757} // namespace net