blob: c51c713be7d716147cc9ba2240d0c6133a50c010 [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
Eric Orth3b26e3ba2020-11-12 22:43:137#include <string>
8#include <utility>
9#include <vector>
10
[email protected]d9806a972014-02-26 18:14:5711#include "base/big_endian.h"
[email protected]78eac2a2012-03-14 19:09:2712#include "base/bind.h"
Eric Orth3b26e3ba2020-11-12 22:43:1313#include "base/check.h"
skyostil4891b25b2015-06-11 11:43:4514#include "base/location.h"
Eric Orth828bd3ae2018-12-12 17:30:3615#include "base/numerics/safe_conversions.h"
Eric Orthac9aafb2021-07-29 23:03:4316#include "base/stl_util.h"
[email protected]78eac2a2012-03-14 19:09:2717#include "base/sys_byteorder.h"
Patrick Monette643cdf62021-10-15 19:13:4218#include "base/task/single_thread_task_runner.h"
gabf767595f2016-05-11 18:50:3519#include "base/threading/thread_task_runner_handle.h"
Eric Orth3b26e3ba2020-11-12 22:43:1320#include "base/time/time.h"
[email protected]78eac2a2012-03-14 19:09:2721#include "net/base/io_buffer.h"
Eric Orth828bd3ae2018-12-12 17:30:3622#include "net/base/ip_address.h"
[email protected]78eac2a2012-03-14 19:09:2723#include "net/base/net_errors.h"
[email protected]0adcb2b2012-08-15 21:30:4624#include "net/dns/address_sorter.h"
Eric Orth394db1732019-08-27 20:09:3925#include "net/dns/dns_hosts.h"
[email protected]78eac2a2012-03-14 19:09:2726#include "net/dns/dns_query.h"
Eric Orthaf82b49a2020-02-01 01:48:5027#include "net/dns/dns_session.h"
Eric Orth9300cc62020-08-21 00:29:3428#include "net/dns/dns_socket_allocator.h"
tfarina77021d62015-10-11 20:19:0329#include "net/dns/dns_util.h"
Eric Orth069a3c6e2020-01-31 23:14:2430#include "net/dns/resolve_context.h"
[email protected]78eac2a2012-03-14 19:09:2731#include "testing/gtest/include/gtest/gtest.h"
32
33namespace net {
34namespace {
35
Eric Orth828bd3ae2018-12-12 17:30:3636const uint8_t kMalformedResponseHeader[] = {
37 // Header
38 0x00, 0x14, // Arbitrary ID
39 0x81, 0x80, // Standard query response, RA, no error
40 0x00, 0x01, // 1 question
41 0x00, 0x01, // 1 RR (answers)
42 0x00, 0x00, // 0 authority RRs
43 0x00, 0x00, // 0 additional RRs
44};
45
46// Create a response containing a valid question (as would normally be validated
47// in DnsTransaction) but completely missing a header-declared answer.
Eric Ortha97f0f72020-10-16 16:10:3248DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) {
Eric Orth828bd3ae2018-12-12 17:30:3649 std::string dns_name;
50 CHECK(DNSDomainFromDot(hostname, &dns_name));
51 DnsQuery query(0x14 /* id */, dns_name, type);
52
53 // Build response to simulate the barebones validation DnsResponse applies to
54 // responses received from the network.
55 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
56 sizeof(kMalformedResponseHeader) + query.question().size());
57 memcpy(buffer->data(), kMalformedResponseHeader,
58 sizeof(kMalformedResponseHeader));
59 memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
60 query.question().data(), query.question().size());
61
Eric Ortha97f0f72020-10-16 16:10:3262 DnsResponse response(buffer, buffer->size());
63 CHECK(response.InitParseWithoutQuery(buffer->size()));
Eric Orth828bd3ae2018-12-12 17:30:3664
65 return response;
66}
67
[email protected]daae1322013-09-05 18:26:5068class MockAddressSorter : public AddressSorter {
69 public:
Chris Watkins68b15032017-12-01 03:07:1370 ~MockAddressSorter() override = default;
Bence Békyd5e474c2018-08-02 18:45:0871 void Sort(const AddressList& list, CallbackType callback) const override {
[email protected]daae1322013-09-05 18:26:5072 // Do nothing.
Bence Békyd5e474c2018-08-02 18:45:0873 std::move(callback).Run(true, list);
[email protected]daae1322013-09-05 18:26:5074 }
75};
76
[email protected]daae1322013-09-05 18:26:5077} // namespace
[email protected]78eac2a2012-03-14 19:09:2778
Eric Orth8539e492020-10-19 20:09:5579DnsResourceRecord BuildTestDnsRecord(std::string name,
80 uint16_t type,
81 std::string rdata,
82 base::TimeDelta ttl) {
David Van Cleve34c74c72019-10-31 19:58:0183 DCHECK(!name.empty());
David Van Cleve34c74c72019-10-31 19:58:0184
85 DnsResourceRecord record;
86 record.name = std::move(name);
Eric Orth8539e492020-10-19 20:09:5587 record.type = type;
David Van Cleve34c74c72019-10-31 19:58:0188 record.klass = dns_protocol::kClassIN;
Eric Orth8539e492020-10-19 20:09:5589 record.ttl = ttl.InSeconds();
Eric Orth5d21f152020-10-21 19:15:4390
91 if (!rdata.empty())
92 record.SetOwnedRdata(std::move(rdata));
David Van Cleve34c74c72019-10-31 19:58:0193
94 return record;
95}
96
Eric Orth65fd3e32020-11-18 04:59:1797DnsResourceRecord BuildTestCnameRecord(std::string name,
98 base::StringPiece canonical_name,
99 base::TimeDelta ttl) {
100 DCHECK(!name.empty());
101 DCHECK(!canonical_name.empty());
102
103 std::string rdata;
104 CHECK(DNSDomainFromDot(canonical_name, &rdata));
105
106 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeCNAME,
107 std::move(rdata), ttl);
108}
109
Eric Orth8539e492020-10-19 20:09:55110DnsResourceRecord BuildTestAddressRecord(std::string name,
111 const IPAddress& ip,
112 base::TimeDelta ttl) {
113 DCHECK(!name.empty());
Eric Orth828bd3ae2018-12-12 17:30:36114 DCHECK(ip.IsValid());
115
Eric Orth8539e492020-10-19 20:09:55116 return BuildTestDnsRecord(
117 std::move(name),
118 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA,
119 net::IPAddressToPackedString(ip), ttl);
120}
121
Eric Orth3b26e3ba2020-11-12 22:43:13122DnsResourceRecord BuildTestTextRecord(std::string name,
123 std::vector<std::string> text_strings,
124 base::TimeDelta ttl) {
125 DCHECK(!text_strings.empty());
126
127 std::string rdata;
128 for (const std::string& text_string : text_strings) {
129 DCHECK(!text_string.empty());
130
131 rdata += base::checked_cast<unsigned char>(text_string.size());
132 rdata += text_string;
133 }
134
135 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT,
Eric Orthd16fee6b2020-11-18 06:43:14136 std::move(rdata), ttl);
Eric Orth3b26e3ba2020-11-12 22:43:13137}
138
Eric Orth7139e0552020-11-04 02:41:11139DnsResourceRecord BuildTestHttpsAliasRecord(std::string name,
140 base::StringPiece alias_name,
141 base::TimeDelta ttl) {
142 DCHECK(!name.empty());
143
144 std::string rdata("\000\000", 2);
145
146 std::string alias_domain;
147 CHECK(DNSDomainFromDot(alias_name, &alias_domain));
148 rdata.append(alias_domain);
149
150 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
151 std::move(rdata), ttl);
152}
153
154DnsResourceRecord BuildTestHttpsServiceRecord(
155 std::string name,
156 uint16_t priority,
157 base::StringPiece service_name,
158 const std::map<uint16_t, std::string>& params,
159 base::TimeDelta ttl) {
160 DCHECK(!name.empty());
161 DCHECK_NE(priority, 0);
162
163 std::string rdata;
164
165 char num_buffer[2];
166 base::WriteBigEndian(num_buffer, priority);
167 rdata.append(num_buffer, 2);
168
169 std::string service_domain;
Eric Orthac9aafb2021-07-29 23:03:43170 if (service_name == ".") {
171 // HTTPS records have special behavior for `service_name == "."` (that it
172 // will be treated as if the service name is the same as the record owner
173 // name), so allow such inputs despite normally being disallowed for
174 // Chrome-encoded DNS names.
175 service_domain = '\x00';
176 } else {
177 CHECK(DNSDomainFromDot(service_name, &service_domain));
178 }
Eric Orth7139e0552020-11-04 02:41:11179 rdata.append(service_domain);
180
181 for (auto& param : params) {
182 base::WriteBigEndian(num_buffer, param.first);
183 rdata.append(num_buffer, 2);
184
185 base::WriteBigEndian(num_buffer,
186 base::checked_cast<uint16_t>(param.second.size()));
187 rdata.append(num_buffer, 2);
188
189 rdata.append(param.second);
190 }
191
192 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
193 std::move(rdata), ttl);
194}
195
Eric Orth8539e492020-10-19 20:09:55196DnsResponse BuildTestDnsResponse(
197 std::string name,
198 uint16_t type,
Eric Orth69c25992020-11-10 16:55:12199 const std::vector<DnsResourceRecord>& answers,
200 const std::vector<DnsResourceRecord>& authority,
Eric Orth9cec76f2020-11-17 07:42:42201 const std::vector<DnsResourceRecord>& additional,
202 uint8_t rcode) {
Eric Orth8539e492020-10-19 20:09:55203 DCHECK(!name.empty());
204
Eric Orth828bd3ae2018-12-12 17:30:36205 std::string dns_name;
206 CHECK(DNSDomainFromDot(name, &dns_name));
Eric Orth8539e492020-10-19 20:09:55207
Anton Bikineev068d2912021-05-15 20:43:52208 absl::optional<DnsQuery> query(absl::in_place, 0, std::move(dns_name), type);
Eric Orth8539e492020-10-19 20:09:55209 return DnsResponse(0, true /* is_authoritative */, answers,
Eric Orth69c25992020-11-10 16:55:12210 authority /* authority_records */,
Eric Orth9cec76f2020-11-17 07:42:42211 additional /* additional_records */, query, rcode,
Eric Orthd16fee6b2020-11-18 06:43:14212 false /* validate_records */);
Eric Orth828bd3ae2018-12-12 17:30:36213}
214
Eric Orth8539e492020-10-19 20:09:55215DnsResponse BuildTestDnsAddressResponse(std::string name,
216 const IPAddress& ip,
217 std::string answer_name) {
218 DCHECK(ip.IsValid());
219
220 if (answer_name.empty())
221 answer_name = name;
222
223 std::vector<DnsResourceRecord> answers = {
224 BuildTestAddressRecord(std::move(answer_name), ip)};
225
226 return BuildTestDnsResponse(
227 std::move(name),
228 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
229}
230
Eric Ortha97f0f72020-10-16 16:10:32231DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
232 const IPAddress& ip,
Eric Orth8539e492020-10-19 20:09:55233 std::string cannonname,
234 std::string answer_name) {
Eric Orth828bd3ae2018-12-12 17:30:36235 DCHECK(ip.IsValid());
236 DCHECK(!cannonname.empty());
237
Eric Orth8539e492020-10-19 20:09:55238 if (answer_name.empty())
239 answer_name = name;
240
241 std::string cname_rdata;
242 CHECK(DNSDomainFromDot(cannonname, &cname_rdata));
243
Eric Orth828bd3ae2018-12-12 17:30:36244 std::vector<DnsResourceRecord> answers = {
Eric Orth8539e492020-10-19 20:09:55245 BuildTestDnsRecord(std::move(answer_name), dns_protocol::kTypeCNAME,
246 std::move(cname_rdata)),
247 BuildTestAddressRecord(std::move(cannonname), ip)};
248
249 return BuildTestDnsResponse(
250 std::move(name),
251 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
Eric Orth828bd3ae2018-12-12 17:30:36252}
253
Eric Ortha97f0f72020-10-16 16:10:32254DnsResponse BuildTestDnsTextResponse(
Eric Orth828bd3ae2018-12-12 17:30:36255 std::string name,
256 std::vector<std::vector<std::string>> text_records,
257 std::string answer_name) {
258 if (answer_name.empty())
259 answer_name = name;
260
261 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45262 for (std::vector<std::string>& text_record : text_records) {
Eric Orth3b26e3ba2020-11-12 22:43:13263 answers.push_back(BuildTestTextRecord(answer_name, std::move(text_record)));
Eric Orth828bd3ae2018-12-12 17:30:36264 }
265
Eric Orth8539e492020-10-19 20:09:55266 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeTXT, answers);
Eric Orth828bd3ae2018-12-12 17:30:36267}
268
Eric Ortha97f0f72020-10-16 16:10:32269DnsResponse BuildTestDnsPointerResponse(std::string name,
270 std::vector<std::string> pointer_names,
271 std::string answer_name) {
Eric Orthe9db8d232019-01-14 21:24:45272 if (answer_name.empty())
273 answer_name = name;
274
275 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45276 for (std::string& pointer_name : pointer_names) {
Eric Orth8539e492020-10-19 20:09:55277 std::string rdata;
278 CHECK(DNSDomainFromDot(pointer_name, &rdata));
279
280 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypePTR,
281 std::move(rdata)));
Eric Orthe9db8d232019-01-14 21:24:45282 }
283
Eric Orth8539e492020-10-19 20:09:55284 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers);
Eric Orthe9db8d232019-01-14 21:24:45285}
286
Eric Ortha97f0f72020-10-16 16:10:32287DnsResponse BuildTestDnsServiceResponse(
Eric Ortha625b042019-01-16 01:14:45288 std::string name,
289 std::vector<TestServiceRecord> service_records,
290 std::string answer_name) {
291 if (answer_name.empty())
292 answer_name = name;
293
294 std::vector<DnsResourceRecord> answers;
295 for (TestServiceRecord& service_record : service_records) {
Eric Orth8539e492020-10-19 20:09:55296 std::string rdata;
297 char num_buffer[2];
298 base::WriteBigEndian(num_buffer, service_record.priority);
299 rdata.append(num_buffer, 2);
300 base::WriteBigEndian(num_buffer, service_record.weight);
301 rdata.append(num_buffer, 2);
302 base::WriteBigEndian(num_buffer, service_record.port);
303 rdata.append(num_buffer, 2);
304 std::string dns_name;
305 CHECK(DNSDomainFromDot(service_record.target, &dns_name));
306 rdata += dns_name;
307
308 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV,
Peter Kastinge5a38ed2021-10-02 03:06:35309 std::move(rdata), base::Hours(5)));
Eric Ortha625b042019-01-16 01:14:45310 }
311
Eric Orth8539e492020-10-19 20:09:55312 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers);
Daniel McArdle2daa3ec2020-06-03 16:05:48313}
314
Eric Orth89726dd2020-10-13 20:19:53315MockDnsClientRule::Result::Result(ResultType type,
Eric Orthac9aafb2021-07-29 23:03:43316 absl::optional<DnsResponse> response,
317 absl::optional<int> net_error)
318 : type(type), response(std::move(response)), net_error(net_error) {}
Eric Orth828bd3ae2018-12-12 17:30:36319
Eric Ortha97f0f72020-10-16 16:10:32320MockDnsClientRule::Result::Result(DnsResponse response)
Peter Kastingd039b772021-08-18 00:06:20321 : type(ResultType::kOk),
322 response(std::move(response)),
323 net_error(absl::nullopt) {}
Eric Orth828bd3ae2018-12-12 17:30:36324
Peter Kastingd039b772021-08-18 00:06:20325MockDnsClientRule::Result::Result(Result&&) = default;
326
327MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(Result&&) =
328 default;
Eric Orth828bd3ae2018-12-12 17:30:36329
330MockDnsClientRule::Result::~Result() = default;
331
Eric Orth502d5682019-04-12 00:21:33332MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
333 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13334 bool secure,
Eric Orth502d5682019-04-12 00:21:33335 Result result,
336 bool delay,
337 URLRequestContext* context)
338 : result(std::move(result)),
339 prefix(prefix),
340 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13341 secure(secure),
Eric Orth502d5682019-04-12 00:21:33342 delay(delay),
343 context(context) {}
344
345MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
346
Eric Orth3421db382019-10-20 02:35:52347// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
348class MockDnsTransactionFactory::MockTransaction
349 : public DnsTransaction,
350 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27351 public:
Eric Orth3421db382019-10-20 02:35:52352 MockTransaction(const MockDnsClientRuleList& rules,
Eric Orthc4cca5d2021-07-02 19:59:01353 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52354 uint16_t qtype,
355 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56356 bool force_doh_server_available,
Eric Ortha093b092020-09-24 23:13:02357 SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56358 ResolveContext* resolve_context,
Eric Orth89726dd2020-10-13 20:19:53359 bool fast_timeout,
Eric Orth3421db382019-10-20 02:35:52360 DnsTransactionFactory::CallbackType callback)
Peter Kastingd039b772021-08-18 00:06:20361 : result_(MockDnsClientRule::ResultType::kFail),
Eric Orthc4cca5d2021-07-02 19:59:01362 hostname_(std::move(hostname)),
Eric Orth3421db382019-10-20 02:35:52363 qtype_(qtype),
364 callback_(std::move(callback)),
365 started_(false),
366 delayed_(false) {
Eric Orth7dc18e92020-02-13 20:27:56367 // Do not allow matching any rules if transaction is secure and no DoH
368 // servers are available.
369 if (!secure || force_doh_server_available ||
370 resolve_context->NumAvailableDohServers(
371 resolve_context->current_session_for_testing()) > 0) {
372 // Find the relevant rule which matches |qtype|, |secure|, prefix of
Eric Orthc4cca5d2021-07-02 19:59:01373 // |hostname_|, and |url_request_context| (iff the rule context is not
Eric Orth7dc18e92020-02-13 20:27:56374 // null).
375 for (size_t i = 0; i < rules.size(); ++i) {
376 const std::string& prefix = rules[i].prefix;
377 if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
Eric Orthc4cca5d2021-07-02 19:59:01378 (hostname_.size() >= prefix.size()) &&
379 (hostname_.compare(0, prefix.size(), prefix) == 0) &&
Eric Orth7dc18e92020-02-13 20:27:56380 (!rules[i].context ||
381 rules[i].context == resolve_context->url_request_context())) {
382 const MockDnsClientRule::Result* result = &rules[i].result;
383 result_ = MockDnsClientRule::Result(result->type);
Eric Orthac9aafb2021-07-29 23:03:43384 result_.net_error = result->net_error;
Eric Orth7dc18e92020-02-13 20:27:56385 delayed_ = rules[i].delay;
[email protected]daae1322013-09-05 18:26:50386
Eric Orth7dc18e92020-02-13 20:27:56387 // Generate a DnsResponse when not provided with the rule.
388 std::vector<DnsResourceRecord> authority_records;
389 std::string dns_name;
390 CHECK(DNSDomainFromDot(hostname_, &dns_name));
Anton Bikineev068d2912021-05-15 20:43:52391 absl::optional<DnsQuery> query(absl::in_place, 22 /* id */, dns_name,
Eric Orth7dc18e92020-02-13 20:27:56392 qtype_);
393 switch (result->type) {
Peter Kastingd039b772021-08-18 00:06:20394 case MockDnsClientRule::ResultType::kNoDomain:
395 case MockDnsClientRule::ResultType::kEmpty:
Eric Orth7dc18e92020-02-13 20:27:56396 DCHECK(!result->response); // Not expected to be provided.
Eric Orth8539e492020-10-19 20:09:55397 authority_records = {BuildTestDnsRecord(
398 hostname_, dns_protocol::kTypeSOA, "fake rdata")};
Eric Ortha97f0f72020-10-16 16:10:32399 result_.response = DnsResponse(
Eric Orth7dc18e92020-02-13 20:27:56400 22 /* id */, false /* is_authoritative */,
401 std::vector<DnsResourceRecord>() /* answers */,
402 authority_records,
403 std::vector<DnsResourceRecord>() /* additional_records */,
404 query,
Peter Kastingd039b772021-08-18 00:06:20405 result->type == MockDnsClientRule::ResultType::kNoDomain
Eric Orth7dc18e92020-02-13 20:27:56406 ? dns_protocol::kRcodeNXDOMAIN
407 : 0);
408 break;
Peter Kastingd039b772021-08-18 00:06:20409 case MockDnsClientRule::ResultType::kFail:
Eric Orthac9aafb2021-07-29 23:03:43410 if (result->response)
411 SetResponse(result);
412 break;
Peter Kastingd039b772021-08-18 00:06:20413 case MockDnsClientRule::ResultType::kTimeout:
Eric Orth7dc18e92020-02-13 20:27:56414 DCHECK(!result->response); // Not expected to be provided.
415 break;
Peter Kastingd039b772021-08-18 00:06:20416 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53417 if (!fast_timeout)
418 SetResponse(result);
419 break;
Peter Kastingd039b772021-08-18 00:06:20420 case MockDnsClientRule::ResultType::kOk:
Eric Orth89726dd2020-10-13 20:19:53421 SetResponse(result);
Eric Orth7dc18e92020-02-13 20:27:56422 break;
Peter Kastingd039b772021-08-18 00:06:20423 case MockDnsClientRule::ResultType::kMalformed:
Eric Orth7dc18e92020-02-13 20:27:56424 DCHECK(!result->response); // Not expected to be provided.
425 result_.response = CreateMalformedResponse(hostname_, qtype_);
426 break;
Peter Kastingd039b772021-08-18 00:06:20427 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24428 ADD_FAILURE()
429 << "Unexpected DNS transaction created for hostname "
430 << hostname_;
431 break;
Eric Orth7dc18e92020-02-13 20:27:56432 }
Eric Orth2a61be82020-02-12 17:56:48433
Eric Orth7dc18e92020-02-13 20:27:56434 break;
435 }
Eric Orth3421db382019-10-20 02:35:52436 }
[email protected]daae1322013-09-05 18:26:50437 }
[email protected]0adcb2b2012-08-15 21:30:46438 }
439
Eric Orth3421db382019-10-20 02:35:52440 const std::string& GetHostname() const override { return hostname_; }
[email protected]daae1322013-09-05 18:26:50441
Eric Orth3421db382019-10-20 02:35:52442 uint16_t GetType() const override { return qtype_; }
443
444 void Start() override {
445 EXPECT_FALSE(started_);
446 started_ = true;
447 if (delayed_)
448 return;
449 // Using WeakPtr to cleanly cancel when transaction is destroyed.
450 base::ThreadTaskRunnerHandle::Get()->PostTask(
451 FROM_HERE, base::BindOnce(&MockTransaction::Finish, AsWeakPtr()));
452 }
453
454 void FinishDelayedTransaction() {
455 EXPECT_TRUE(delayed_);
456 delayed_ = false;
457 Finish();
458 }
459
460 bool delayed() const { return delayed_; }
461
462 private:
Eric Orth89726dd2020-10-13 20:19:53463 void SetResponse(const MockDnsClientRule::Result* result) {
464 if (result->response) {
465 // Copy response in case |result| is destroyed before the transaction
466 // completes.
Eric Ortha97f0f72020-10-16 16:10:32467 auto buffer_copy =
468 base::MakeRefCounted<IOBuffer>(result->response->io_buffer_size());
469 memcpy(buffer_copy->data(), result->response->io_buffer()->data(),
470 result->response->io_buffer_size());
471 result_.response = DnsResponse(std::move(buffer_copy),
472 result->response->io_buffer_size());
Eric Orth89726dd2020-10-13 20:19:53473 CHECK(result_.response->InitParseWithoutQuery(
474 result->response->io_buffer_size()));
475 } else {
476 // Generated response only available for address types.
477 DCHECK(qtype_ == dns_protocol::kTypeA ||
478 qtype_ == dns_protocol::kTypeAAAA);
Eric Ortha97f0f72020-10-16 16:10:32479 result_.response = BuildTestDnsAddressResponse(
480 hostname_, qtype_ == dns_protocol::kTypeA
481 ? IPAddress::IPv4Localhost()
482 : IPAddress::IPv6Localhost());
Eric Orth89726dd2020-10-13 20:19:53483 }
484 }
485
Eric Orth3421db382019-10-20 02:35:52486 void Finish() {
487 switch (result_.type) {
Peter Kastingd039b772021-08-18 00:06:20488 case MockDnsClientRule::ResultType::kNoDomain:
489 case MockDnsClientRule::ResultType::kFail: {
Eric Orthac9aafb2021-07-29 23:03:43490 int error = result_.net_error.value_or(ERR_NAME_NOT_RESOLVED);
491 DCHECK_NE(error, OK);
492 std::move(callback_).Run(this, error,
493 base::OptionalOrNullptr(result_.response),
494 absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52495 break;
Eric Orthac9aafb2021-07-29 23:03:43496 }
Peter Kastingd039b772021-08-18 00:06:20497 case MockDnsClientRule::ResultType::kEmpty:
498 case MockDnsClientRule::ResultType::kOk:
499 case MockDnsClientRule::ResultType::kMalformed:
Eric Orthac9aafb2021-07-29 23:03:43500 DCHECK(!result_.net_error.has_value());
Eric Ortha97f0f72020-10-16 16:10:32501 std::move(callback_).Run(
Eric Orthac9aafb2021-07-29 23:03:43502 this, OK, base::OptionalOrNullptr(result_.response), absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52503 break;
Peter Kastingd039b772021-08-18 00:06:20504 case MockDnsClientRule::ResultType::kTimeout:
Eric Orthac9aafb2021-07-29 23:03:43505 DCHECK(!result_.net_error.has_value());
Daniel McArdle4e2037e2020-06-11 22:40:51506 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
Anton Bikineev068d2912021-05-15 20:43:52507 absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52508 break;
Peter Kastingd039b772021-08-18 00:06:20509 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53510 if (result_.response) {
Eric Ortha97f0f72020-10-16 16:10:32511 std::move(callback_).Run(
Eric Orthac9aafb2021-07-29 23:03:43512 this, result_.net_error.value_or(OK),
513 result_.response ? &result_.response.value() : nullptr,
Anton Bikineev068d2912021-05-15 20:43:52514 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53515 } else {
Eric Orthac9aafb2021-07-29 23:03:43516 DCHECK(!result_.net_error.has_value());
Eric Orth89726dd2020-10-13 20:19:53517 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
Anton Bikineev068d2912021-05-15 20:43:52518 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53519 }
Eric Orthcf8e00f2021-07-24 00:41:24520 break;
Peter Kastingd039b772021-08-18 00:06:20521 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24522 ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
523 << hostname_;
524 break;
Eric Orth3421db382019-10-20 02:35:52525 }
526 }
527
528 void SetRequestPriority(RequestPriority priority) override {}
529
530 MockDnsClientRule::Result result_;
531 const std::string hostname_;
532 const uint16_t qtype_;
533 DnsTransactionFactory::CallbackType callback_;
534 bool started_;
535 bool delayed_;
[email protected]0adcb2b2012-08-15 21:30:46536};
537
Eric Orth41b249e02020-01-03 20:21:47538class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
539 public:
540 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
541 : factory_(std::move(factory)) {}
542
543 ~MockDohProbeRunner() override {
544 if (factory_)
545 factory_->running_doh_probe_runners_.erase(this);
546 }
547
Eric Orth020e5fe2020-03-12 17:43:43548 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47549 DCHECK(factory_);
550 factory_->running_doh_probe_runners_.insert(this);
551 }
552
Eric Orth41b249e02020-01-03 20:21:47553 base::TimeDelta GetDelayUntilNextProbeForTest(
554 size_t doh_server_index) const override {
555 NOTREACHED();
556 return base::TimeDelta();
557 }
558
559 private:
560 base::WeakPtr<MockDnsTransactionFactory> factory_;
561};
562
Eric Orth3421db382019-10-20 02:35:52563MockDnsTransactionFactory::MockDnsTransactionFactory(
564 MockDnsClientRuleList rules)
565 : rules_(std::move(rules)) {}
566
567MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
568
569std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
Eric Orthc4cca5d2021-07-02 19:59:01570 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52571 uint16_t qtype,
572 DnsTransactionFactory::CallbackType callback,
573 const NetLogWithSource&,
574 bool secure,
Eric Ortha093b092020-09-24 23:13:02575 SecureDnsMode secure_dns_mode,
Eric Orth89726dd2020-10-13 20:19:53576 ResolveContext* resolve_context,
577 bool fast_timeout) {
Eric Orth3421db382019-10-20 02:35:52578 std::unique_ptr<MockTransaction> transaction =
Eric Orthc4cca5d2021-07-02 19:59:01579 std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
580 secure, force_doh_server_available_,
581 secure_dns_mode, resolve_context,
582 fast_timeout, std::move(callback));
Eric Orth3421db382019-10-20 02:35:52583 if (transaction->delayed())
584 delayed_transactions_.push_back(transaction->AsWeakPtr());
585 return transaction;
586}
587
Eric Orth41b249e02020-01-03 20:21:47588std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24589 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47590 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
591}
592
Eric Orth3421db382019-10-20 02:35:52593void MockDnsTransactionFactory::AddEDNSOption(const OptRecordRdata::Opt& opt) {}
594
Eric Ortha093b092020-09-24 23:13:02595SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
596 return SecureDnsMode::kAutomatic;
Eric Orth3421db382019-10-20 02:35:52597}
598
599void MockDnsTransactionFactory::CompleteDelayedTransactions() {
600 DelayedTransactionList old_delayed_transactions;
601 old_delayed_transactions.swap(delayed_transactions_);
602 for (auto it = old_delayed_transactions.begin();
603 it != old_delayed_transactions.end(); ++it) {
604 if (it->get())
605 (*it)->FinishDelayedTransaction();
606 }
607}
608
David Van Cleve1fb5e8c2019-11-04 16:45:16609bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
610 DnsQueryType type) {
611 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
612 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
613 t->FinishDelayedTransaction();
614 t.reset();
615 return true;
616 }
617 }
618 return false;
619}
620
Eric Orth394db1732019-08-27 20:09:39621MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
622 : config_(std::move(config)),
Eric Orth3421db382019-10-20 02:35:52623 factory_(new MockDnsTransactionFactory(std::move(rules))),
Eric Orth394db1732019-08-27 20:09:39624 address_sorter_(new MockAddressSorter()) {
625 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50626 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39627}
[email protected]78eac2a2012-03-14 19:09:27628
Chris Watkins68b15032017-12-01 03:07:13629MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27630
Eric Orth394db1732019-08-27 20:09:39631bool MockDnsClient::CanUseSecureDnsTransactions() const {
632 const DnsConfig* config = GetEffectiveConfig();
633 return config && config->IsValid() && !config->dns_over_https_servers.empty();
[email protected]daae1322013-09-05 18:26:50634}
[email protected]78eac2a2012-03-14 19:09:27635
Eric Orth394db1732019-08-27 20:09:39636bool MockDnsClient::CanUseInsecureDnsTransactions() const {
637 const DnsConfig* config = GetEffectiveConfig();
638 return config && config->IsValid() && insecure_enabled_ &&
639 !config->dns_over_tls_active;
640}
641
Eric Orth09746312021-05-05 15:44:58642bool MockDnsClient::CanQueryAdditionalTypesViaInsecureDns() const {
643 DCHECK(CanUseInsecureDnsTransactions());
644 return additional_types_enabled_;
645}
646
647void MockDnsClient::SetInsecureEnabled(bool enabled,
648 bool additional_types_enabled) {
Eric Orth394db1732019-08-27 20:09:39649 insecure_enabled_ = enabled;
Eric Orth09746312021-05-05 15:44:58650 additional_types_enabled_ = additional_types_enabled;
Eric Orth394db1732019-08-27 20:09:39651}
652
Eric Orth069a3c6e2020-01-31 23:14:24653bool MockDnsClient::FallbackFromSecureTransactionPreferred(
654 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56655 bool doh_server_available =
656 force_doh_server_available_ ||
657 context->NumAvailableDohServers(session_.get()) > 0;
658 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22659}
660
Eric Orth394db1732019-08-27 20:09:39661bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
662 return !CanUseInsecureDnsTransactions() ||
663 fallback_failures_ >= max_fallback_failures_;
664}
665
Anton Bikineev068d2912021-05-15 20:43:52666bool MockDnsClient::SetSystemConfig(absl::optional<DnsConfig> system_config) {
Eric Orth394db1732019-08-27 20:09:39667 if (ignore_system_config_changes_)
668 return false;
669
Anton Bikineev068d2912021-05-15 20:43:52670 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39671 config_ = std::move(system_config);
672 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50673 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39674 return before != effective_config_;
675}
676
677bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
Anton Bikineev068d2912021-05-15 20:43:52678 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39679 overrides_ = std::move(config_overrides);
680 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50681 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39682 return before != effective_config_;
683}
684
Eric Orth020e5fe2020-03-12 17:43:43685void MockDnsClient::ReplaceCurrentSession() {
686 // Noop if no current effective config.
687 session_ = BuildSession();
688}
689
Eric Orthaf82b49a2020-02-01 01:48:50690DnsSession* MockDnsClient::GetCurrentSession() {
691 return session_.get();
692}
693
Eric Orth394db1732019-08-27 20:09:39694const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
695 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
696}
697
698const DnsHosts* MockDnsClient::GetHosts() const {
699 const DnsConfig* config = GetEffectiveConfig();
700 if (!config)
701 return nullptr;
702
703 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50704}
[email protected]78eac2a2012-03-14 19:09:27705
[email protected]daae1322013-09-05 18:26:50706DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39707 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50708}
[email protected]78eac2a2012-03-14 19:09:27709
[email protected]daae1322013-09-05 18:26:50710AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39711 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
712}
713
714void MockDnsClient::IncrementInsecureFallbackFailures() {
715 ++fallback_failures_;
716}
717
718void MockDnsClient::ClearInsecureFallbackFailures() {
719 fallback_failures_ = 0;
720}
721
Anton Bikineev068d2912021-05-15 20:43:52722absl::optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
Eric Orth394db1732019-08-27 20:09:39723 return config_;
724}
725
726DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
727 return overrides_;
[email protected]daae1322013-09-05 18:26:50728}
[email protected]0adcb2b2012-08-15 21:30:46729
Eric Orth3421db382019-10-20 02:35:52730void MockDnsClient::SetTransactionFactoryForTesting(
731 std::unique_ptr<DnsTransactionFactory> factory) {
732 NOTREACHED();
733}
734
[email protected]daae1322013-09-05 18:26:50735void MockDnsClient::CompleteDelayedTransactions() {
736 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27737}
738
David Van Cleve1fb5e8c2019-11-04 16:45:16739bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
740 return factory_->CompleteOneDelayedTransactionOfType(type);
741}
742
Eric Orth7dc18e92020-02-13 20:27:56743void MockDnsClient::SetForceDohServerAvailable(bool available) {
744 force_doh_server_available_ = available;
745 factory_->set_force_doh_server_available(available);
746}
747
Anton Bikineev068d2912021-05-15 20:43:52748absl::optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
Eric Orth394db1732019-08-27 20:09:39749 if (overrides_.OverridesEverything())
750 return overrides_.ApplyOverrides(DnsConfig());
751 if (!config_ || !config_.value().IsValid())
Anton Bikineev068d2912021-05-15 20:43:52752 return absl::nullopt;
Eric Orth394db1732019-08-27 20:09:39753
754 return overrides_.ApplyOverrides(config_.value());
755}
756
Eric Orthaf82b49a2020-02-01 01:48:50757scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
758 if (!effective_config_)
759 return nullptr;
760
761 // Session not expected to be used for anything that will actually require
762 // random numbers.
763 auto null_random_callback =
764 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
765
Eric Orth9300cc62020-08-21 00:29:34766 auto socket_allocator = std::make_unique<DnsSocketAllocator>(
Eric Orth990a74a92020-08-20 18:41:26767 &socket_factory_, effective_config_.value().nameservers,
768 nullptr /* net_log */);
769
Eric Orthaf82b49a2020-02-01 01:48:50770 return base::MakeRefCounted<DnsSession>(
Eric Orth9300cc62020-08-21 00:29:34771 effective_config_.value(), std::move(socket_allocator),
772 null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50773}
774
[email protected]78eac2a2012-03-14 19:09:27775} // namespace net