blob: 273b096efe9a273dbd957c29f767e707cfd1b27a [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"
Benjamin M. Schwartz571353c22021-12-13 16:41:1116#include "base/ranges/algorithm.h"
Eric Orthac9aafb2021-07-29 23:03:4317#include "base/stl_util.h"
Dan McArdle00271b92022-02-11 23:41:1818#include "base/strings/strcat.h"
[email protected]78eac2a2012-03-14 19:09:2719#include "base/sys_byteorder.h"
Patrick Monette643cdf62021-10-15 19:13:4220#include "base/task/single_thread_task_runner.h"
gabf767595f2016-05-11 18:50:3521#include "base/threading/thread_task_runner_handle.h"
Eric Orth3b26e3ba2020-11-12 22:43:1322#include "base/time/time.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2823#include "net/base/address_list.h"
[email protected]78eac2a2012-03-14 19:09:2724#include "net/base/io_buffer.h"
Eric Orth828bd3ae2018-12-12 17:30:3625#include "net/base/ip_address.h"
Eric Orth48b1b7c2022-01-21 00:21:1626#include "net/base/ip_endpoint.h"
[email protected]78eac2a2012-03-14 19:09:2727#include "net/base/net_errors.h"
[email protected]0adcb2b2012-08-15 21:30:4628#include "net/dns/address_sorter.h"
Eric Orth394db1732019-08-27 20:09:3929#include "net/dns/dns_hosts.h"
[email protected]78eac2a2012-03-14 19:09:2730#include "net/dns/dns_query.h"
Eric Orthaf82b49a2020-02-01 01:48:5031#include "net/dns/dns_session.h"
Eric Orth9300cc62020-08-21 00:29:3432#include "net/dns/dns_socket_allocator.h"
tfarina77021d62015-10-11 20:19:0333#include "net/dns/dns_util.h"
Benjamin M. Schwartz571353c22021-12-13 16:41:1134#include "net/dns/public/dns_over_https_server_config.h"
Eric Orth069a3c6e2020-01-31 23:14:2435#include "net/dns/resolve_context.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2836#include "testing/gmock/include/gmock/gmock-matchers.h"
[email protected]78eac2a2012-03-14 19:09:2737#include "testing/gtest/include/gtest/gtest.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2838#include "url/scheme_host_port.h"
[email protected]78eac2a2012-03-14 19:09:2739
40namespace net {
41namespace {
42
Eric Orth828bd3ae2018-12-12 17:30:3643const uint8_t kMalformedResponseHeader[] = {
44 // Header
45 0x00, 0x14, // Arbitrary ID
46 0x81, 0x80, // Standard query response, RA, no error
47 0x00, 0x01, // 1 question
48 0x00, 0x01, // 1 RR (answers)
49 0x00, 0x00, // 0 authority RRs
50 0x00, 0x00, // 0 additional RRs
51};
52
53// Create a response containing a valid question (as would normally be validated
54// in DnsTransaction) but completely missing a header-declared answer.
Eric Ortha97f0f72020-10-16 16:10:3255DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) {
Eric Orth828bd3ae2018-12-12 17:30:3656 std::string dns_name;
57 CHECK(DNSDomainFromDot(hostname, &dns_name));
58 DnsQuery query(0x14 /* id */, dns_name, type);
59
60 // Build response to simulate the barebones validation DnsResponse applies to
61 // responses received from the network.
62 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
63 sizeof(kMalformedResponseHeader) + query.question().size());
64 memcpy(buffer->data(), kMalformedResponseHeader,
65 sizeof(kMalformedResponseHeader));
66 memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
67 query.question().data(), query.question().size());
68
Eric Ortha97f0f72020-10-16 16:10:3269 DnsResponse response(buffer, buffer->size());
70 CHECK(response.InitParseWithoutQuery(buffer->size()));
Eric Orth828bd3ae2018-12-12 17:30:3671
72 return response;
73}
74
[email protected]daae1322013-09-05 18:26:5075class MockAddressSorter : public AddressSorter {
76 public:
Chris Watkins68b15032017-12-01 03:07:1377 ~MockAddressSorter() override = default;
Eric Orth48b1b7c2022-01-21 00:21:1678 void Sort(const std::vector<IPEndPoint>& endpoints,
79 CallbackType callback) const override {
[email protected]daae1322013-09-05 18:26:5080 // Do nothing.
Eric Orth48b1b7c2022-01-21 00:21:1681 std::move(callback).Run(true, endpoints);
[email protected]daae1322013-09-05 18:26:5082 }
83};
84
[email protected]daae1322013-09-05 18:26:5085} // namespace
[email protected]78eac2a2012-03-14 19:09:2786
Eric Orth8539e492020-10-19 20:09:5587DnsResourceRecord BuildTestDnsRecord(std::string name,
88 uint16_t type,
89 std::string rdata,
90 base::TimeDelta ttl) {
David Van Cleve34c74c72019-10-31 19:58:0191 DCHECK(!name.empty());
David Van Cleve34c74c72019-10-31 19:58:0192
93 DnsResourceRecord record;
94 record.name = std::move(name);
Eric Orth8539e492020-10-19 20:09:5595 record.type = type;
David Van Cleve34c74c72019-10-31 19:58:0196 record.klass = dns_protocol::kClassIN;
Eric Orth8539e492020-10-19 20:09:5597 record.ttl = ttl.InSeconds();
Eric Orth5d21f152020-10-21 19:15:4398
99 if (!rdata.empty())
100 record.SetOwnedRdata(std::move(rdata));
David Van Cleve34c74c72019-10-31 19:58:01101
102 return record;
103}
104
Eric Orth65fd3e32020-11-18 04:59:17105DnsResourceRecord BuildTestCnameRecord(std::string name,
106 base::StringPiece canonical_name,
107 base::TimeDelta ttl) {
108 DCHECK(!name.empty());
109 DCHECK(!canonical_name.empty());
110
111 std::string rdata;
112 CHECK(DNSDomainFromDot(canonical_name, &rdata));
113
114 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeCNAME,
115 std::move(rdata), ttl);
116}
117
Eric Orth8539e492020-10-19 20:09:55118DnsResourceRecord BuildTestAddressRecord(std::string name,
119 const IPAddress& ip,
120 base::TimeDelta ttl) {
121 DCHECK(!name.empty());
Eric Orth828bd3ae2018-12-12 17:30:36122 DCHECK(ip.IsValid());
123
Eric Orth8539e492020-10-19 20:09:55124 return BuildTestDnsRecord(
125 std::move(name),
126 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA,
127 net::IPAddressToPackedString(ip), ttl);
128}
129
Eric Orth3b26e3ba2020-11-12 22:43:13130DnsResourceRecord BuildTestTextRecord(std::string name,
131 std::vector<std::string> text_strings,
132 base::TimeDelta ttl) {
133 DCHECK(!text_strings.empty());
134
135 std::string rdata;
136 for (const std::string& text_string : text_strings) {
137 DCHECK(!text_string.empty());
138
139 rdata += base::checked_cast<unsigned char>(text_string.size());
140 rdata += text_string;
141 }
142
143 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT,
Eric Orthd16fee6b2020-11-18 06:43:14144 std::move(rdata), ttl);
Eric Orth3b26e3ba2020-11-12 22:43:13145}
146
Eric Orth7139e0552020-11-04 02:41:11147DnsResourceRecord BuildTestHttpsAliasRecord(std::string name,
148 base::StringPiece alias_name,
149 base::TimeDelta ttl) {
150 DCHECK(!name.empty());
151
152 std::string rdata("\000\000", 2);
153
154 std::string alias_domain;
155 CHECK(DNSDomainFromDot(alias_name, &alias_domain));
156 rdata.append(alias_domain);
157
158 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
159 std::move(rdata), ttl);
160}
161
Eric Orth17a07d42022-03-08 22:12:16162std::pair<uint16_t, std::string> BuildTestHttpsServiceAlpnParam(
163 const std::vector<std::string>& alpns) {
164 std::string param_value;
165
166 for (const std::string& alpn : alpns) {
167 CHECK(!alpn.empty());
168 param_value.append(
169 1, static_cast<char>(base::checked_cast<uint8_t>(alpn.size())));
170 param_value.append(alpn);
171 }
172
173 return std::make_pair(dns_protocol::kHttpsServiceParamKeyAlpn,
174 std::move(param_value));
175}
176
177std::pair<uint16_t, std::string> BuildTestHttpsServiceEchConfigParam(
178 base::span<const uint8_t> ech_config_list) {
179 return std::make_pair(
180 dns_protocol::kHttpsServiceParamKeyEchConfig,
181 std::string(reinterpret_cast<const char*>(ech_config_list.data()),
182 ech_config_list.size()));
183}
184
Eric Orth4a2621c2022-02-23 00:45:31185std::pair<uint16_t, std::string> BuildTestHttpsServiceMandatoryParam(
186 std::vector<uint16_t> param_key_list) {
187 base::ranges::sort(param_key_list);
188
189 std::string value;
190 for (uint16_t param_key : param_key_list) {
191 char num_buffer[2];
192 base::WriteBigEndian(num_buffer, param_key);
193 value.append(num_buffer, 2);
194 }
195
196 return std::make_pair(dns_protocol::kHttpsServiceParamKeyMandatory,
197 std::move(value));
198}
199
Eric Orth17a07d42022-03-08 22:12:16200std::pair<uint16_t, std::string> BuildTestHttpsServicePortParam(uint16_t port) {
201 char buffer[2];
202 base::WriteBigEndian(buffer, port);
203
204 return std::make_pair(dns_protocol::kHttpsServiceParamKeyPort,
205 std::string(buffer, 2));
206}
207
Eric Orth7139e0552020-11-04 02:41:11208DnsResourceRecord BuildTestHttpsServiceRecord(
209 std::string name,
210 uint16_t priority,
211 base::StringPiece service_name,
212 const std::map<uint16_t, std::string>& params,
213 base::TimeDelta ttl) {
214 DCHECK(!name.empty());
215 DCHECK_NE(priority, 0);
216
217 std::string rdata;
218
219 char num_buffer[2];
220 base::WriteBigEndian(num_buffer, priority);
221 rdata.append(num_buffer, 2);
222
223 std::string service_domain;
Eric Orthac9aafb2021-07-29 23:03:43224 if (service_name == ".") {
225 // HTTPS records have special behavior for `service_name == "."` (that it
226 // will be treated as if the service name is the same as the record owner
227 // name), so allow such inputs despite normally being disallowed for
228 // Chrome-encoded DNS names.
229 service_domain = '\x00';
230 } else {
231 CHECK(DNSDomainFromDot(service_name, &service_domain));
232 }
Eric Orth7139e0552020-11-04 02:41:11233 rdata.append(service_domain);
234
235 for (auto& param : params) {
236 base::WriteBigEndian(num_buffer, param.first);
237 rdata.append(num_buffer, 2);
238
239 base::WriteBigEndian(num_buffer,
240 base::checked_cast<uint16_t>(param.second.size()));
241 rdata.append(num_buffer, 2);
242
243 rdata.append(param.second);
244 }
245
246 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
247 std::move(rdata), ttl);
248}
249
Eric Orth8539e492020-10-19 20:09:55250DnsResponse BuildTestDnsResponse(
251 std::string name,
252 uint16_t type,
Eric Orth69c25992020-11-10 16:55:12253 const std::vector<DnsResourceRecord>& answers,
254 const std::vector<DnsResourceRecord>& authority,
Eric Orth9cec76f2020-11-17 07:42:42255 const std::vector<DnsResourceRecord>& additional,
256 uint8_t rcode) {
Eric Orth8539e492020-10-19 20:09:55257 DCHECK(!name.empty());
258
Eric Orth828bd3ae2018-12-12 17:30:36259 std::string dns_name;
260 CHECK(DNSDomainFromDot(name, &dns_name));
Eric Orth8539e492020-10-19 20:09:55261
Anton Bikineev068d2912021-05-15 20:43:52262 absl::optional<DnsQuery> query(absl::in_place, 0, std::move(dns_name), type);
Eric Orth8539e492020-10-19 20:09:55263 return DnsResponse(0, true /* is_authoritative */, answers,
Eric Orth69c25992020-11-10 16:55:12264 authority /* authority_records */,
Eric Orth9cec76f2020-11-17 07:42:42265 additional /* additional_records */, query, rcode,
Eric Orthd16fee6b2020-11-18 06:43:14266 false /* validate_records */);
Eric Orth828bd3ae2018-12-12 17:30:36267}
268
Eric Orth8539e492020-10-19 20:09:55269DnsResponse BuildTestDnsAddressResponse(std::string name,
270 const IPAddress& ip,
271 std::string answer_name) {
272 DCHECK(ip.IsValid());
273
274 if (answer_name.empty())
275 answer_name = name;
276
277 std::vector<DnsResourceRecord> answers = {
278 BuildTestAddressRecord(std::move(answer_name), ip)};
279
280 return BuildTestDnsResponse(
281 std::move(name),
282 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
283}
284
Eric Ortha97f0f72020-10-16 16:10:32285DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
286 const IPAddress& ip,
Eric Orth8539e492020-10-19 20:09:55287 std::string cannonname,
288 std::string answer_name) {
Eric Orth828bd3ae2018-12-12 17:30:36289 DCHECK(ip.IsValid());
290 DCHECK(!cannonname.empty());
291
Eric Orth8539e492020-10-19 20:09:55292 if (answer_name.empty())
293 answer_name = name;
294
295 std::string cname_rdata;
296 CHECK(DNSDomainFromDot(cannonname, &cname_rdata));
297
Eric Orth828bd3ae2018-12-12 17:30:36298 std::vector<DnsResourceRecord> answers = {
Eric Orth8539e492020-10-19 20:09:55299 BuildTestDnsRecord(std::move(answer_name), dns_protocol::kTypeCNAME,
300 std::move(cname_rdata)),
301 BuildTestAddressRecord(std::move(cannonname), ip)};
302
303 return BuildTestDnsResponse(
304 std::move(name),
305 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
Eric Orth828bd3ae2018-12-12 17:30:36306}
307
Eric Ortha97f0f72020-10-16 16:10:32308DnsResponse BuildTestDnsTextResponse(
Eric Orth828bd3ae2018-12-12 17:30:36309 std::string name,
310 std::vector<std::vector<std::string>> text_records,
311 std::string answer_name) {
312 if (answer_name.empty())
313 answer_name = name;
314
315 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45316 for (std::vector<std::string>& text_record : text_records) {
Eric Orth3b26e3ba2020-11-12 22:43:13317 answers.push_back(BuildTestTextRecord(answer_name, std::move(text_record)));
Eric Orth828bd3ae2018-12-12 17:30:36318 }
319
Eric Orth8539e492020-10-19 20:09:55320 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeTXT, answers);
Eric Orth828bd3ae2018-12-12 17:30:36321}
322
Eric Ortha97f0f72020-10-16 16:10:32323DnsResponse BuildTestDnsPointerResponse(std::string name,
324 std::vector<std::string> pointer_names,
325 std::string answer_name) {
Eric Orthe9db8d232019-01-14 21:24:45326 if (answer_name.empty())
327 answer_name = name;
328
329 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45330 for (std::string& pointer_name : pointer_names) {
Eric Orth8539e492020-10-19 20:09:55331 std::string rdata;
332 CHECK(DNSDomainFromDot(pointer_name, &rdata));
333
334 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypePTR,
335 std::move(rdata)));
Eric Orthe9db8d232019-01-14 21:24:45336 }
337
Eric Orth8539e492020-10-19 20:09:55338 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers);
Eric Orthe9db8d232019-01-14 21:24:45339}
340
Eric Ortha97f0f72020-10-16 16:10:32341DnsResponse BuildTestDnsServiceResponse(
Eric Ortha625b042019-01-16 01:14:45342 std::string name,
343 std::vector<TestServiceRecord> service_records,
344 std::string answer_name) {
345 if (answer_name.empty())
346 answer_name = name;
347
348 std::vector<DnsResourceRecord> answers;
349 for (TestServiceRecord& service_record : service_records) {
Eric Orth8539e492020-10-19 20:09:55350 std::string rdata;
351 char num_buffer[2];
352 base::WriteBigEndian(num_buffer, service_record.priority);
353 rdata.append(num_buffer, 2);
354 base::WriteBigEndian(num_buffer, service_record.weight);
355 rdata.append(num_buffer, 2);
356 base::WriteBigEndian(num_buffer, service_record.port);
357 rdata.append(num_buffer, 2);
358 std::string dns_name;
359 CHECK(DNSDomainFromDot(service_record.target, &dns_name));
360 rdata += dns_name;
361
362 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV,
Peter Kastinge5a38ed2021-10-02 03:06:35363 std::move(rdata), base::Hours(5)));
Eric Ortha625b042019-01-16 01:14:45364 }
365
Eric Orth8539e492020-10-19 20:09:55366 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers);
Daniel McArdle2daa3ec2020-06-03 16:05:48367}
368
Eric Orth89726dd2020-10-13 20:19:53369MockDnsClientRule::Result::Result(ResultType type,
Eric Orthac9aafb2021-07-29 23:03:43370 absl::optional<DnsResponse> response,
371 absl::optional<int> net_error)
372 : type(type), response(std::move(response)), net_error(net_error) {}
Eric Orth828bd3ae2018-12-12 17:30:36373
Eric Ortha97f0f72020-10-16 16:10:32374MockDnsClientRule::Result::Result(DnsResponse response)
Peter Kastingd039b772021-08-18 00:06:20375 : type(ResultType::kOk),
376 response(std::move(response)),
377 net_error(absl::nullopt) {}
Eric Orth828bd3ae2018-12-12 17:30:36378
Peter Kastingd039b772021-08-18 00:06:20379MockDnsClientRule::Result::Result(Result&&) = default;
380
381MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(Result&&) =
382 default;
Eric Orth828bd3ae2018-12-12 17:30:36383
384MockDnsClientRule::Result::~Result() = default;
385
Eric Orth502d5682019-04-12 00:21:33386MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
387 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13388 bool secure,
Eric Orth502d5682019-04-12 00:21:33389 Result result,
390 bool delay,
391 URLRequestContext* context)
392 : result(std::move(result)),
393 prefix(prefix),
394 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13395 secure(secure),
Eric Orth502d5682019-04-12 00:21:33396 delay(delay),
397 context(context) {}
398
399MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
400
Eric Orth3421db382019-10-20 02:35:52401// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
402class MockDnsTransactionFactory::MockTransaction
403 : public DnsTransaction,
404 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27405 public:
Eric Orth3421db382019-10-20 02:35:52406 MockTransaction(const MockDnsClientRuleList& rules,
Eric Orthc4cca5d2021-07-02 19:59:01407 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52408 uint16_t qtype,
409 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56410 bool force_doh_server_available,
Eric Ortha093b092020-09-24 23:13:02411 SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56412 ResolveContext* resolve_context,
Eric Orth89726dd2020-10-13 20:19:53413 bool fast_timeout,
Eric Orth3421db382019-10-20 02:35:52414 DnsTransactionFactory::CallbackType callback)
Peter Kastingd039b772021-08-18 00:06:20415 : result_(MockDnsClientRule::ResultType::kFail),
Eric Orthc4cca5d2021-07-02 19:59:01416 hostname_(std::move(hostname)),
Eric Orth3421db382019-10-20 02:35:52417 qtype_(qtype),
418 callback_(std::move(callback)),
419 started_(false),
420 delayed_(false) {
Eric Orth7dc18e92020-02-13 20:27:56421 // Do not allow matching any rules if transaction is secure and no DoH
422 // servers are available.
423 if (!secure || force_doh_server_available ||
424 resolve_context->NumAvailableDohServers(
425 resolve_context->current_session_for_testing()) > 0) {
426 // Find the relevant rule which matches |qtype|, |secure|, prefix of
Eric Orthc4cca5d2021-07-02 19:59:01427 // |hostname_|, and |url_request_context| (iff the rule context is not
Eric Orth7dc18e92020-02-13 20:27:56428 // null).
429 for (size_t i = 0; i < rules.size(); ++i) {
430 const std::string& prefix = rules[i].prefix;
431 if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
Eric Orthc4cca5d2021-07-02 19:59:01432 (hostname_.size() >= prefix.size()) &&
433 (hostname_.compare(0, prefix.size(), prefix) == 0) &&
Eric Orth7dc18e92020-02-13 20:27:56434 (!rules[i].context ||
435 rules[i].context == resolve_context->url_request_context())) {
436 const MockDnsClientRule::Result* result = &rules[i].result;
437 result_ = MockDnsClientRule::Result(result->type);
Eric Orthac9aafb2021-07-29 23:03:43438 result_.net_error = result->net_error;
Eric Orth7dc18e92020-02-13 20:27:56439 delayed_ = rules[i].delay;
[email protected]daae1322013-09-05 18:26:50440
Eric Orth7dc18e92020-02-13 20:27:56441 // Generate a DnsResponse when not provided with the rule.
442 std::vector<DnsResourceRecord> authority_records;
443 std::string dns_name;
444 CHECK(DNSDomainFromDot(hostname_, &dns_name));
Anton Bikineev068d2912021-05-15 20:43:52445 absl::optional<DnsQuery> query(absl::in_place, 22 /* id */, dns_name,
Eric Orth7dc18e92020-02-13 20:27:56446 qtype_);
447 switch (result->type) {
Peter Kastingd039b772021-08-18 00:06:20448 case MockDnsClientRule::ResultType::kNoDomain:
449 case MockDnsClientRule::ResultType::kEmpty:
Eric Orth7dc18e92020-02-13 20:27:56450 DCHECK(!result->response); // Not expected to be provided.
Eric Orth8539e492020-10-19 20:09:55451 authority_records = {BuildTestDnsRecord(
452 hostname_, dns_protocol::kTypeSOA, "fake rdata")};
Eric Ortha97f0f72020-10-16 16:10:32453 result_.response = DnsResponse(
Eric Orth7dc18e92020-02-13 20:27:56454 22 /* id */, false /* is_authoritative */,
455 std::vector<DnsResourceRecord>() /* answers */,
456 authority_records,
457 std::vector<DnsResourceRecord>() /* additional_records */,
458 query,
Peter Kastingd039b772021-08-18 00:06:20459 result->type == MockDnsClientRule::ResultType::kNoDomain
Eric Orth7dc18e92020-02-13 20:27:56460 ? dns_protocol::kRcodeNXDOMAIN
461 : 0);
462 break;
Peter Kastingd039b772021-08-18 00:06:20463 case MockDnsClientRule::ResultType::kFail:
Eric Orthac9aafb2021-07-29 23:03:43464 if (result->response)
465 SetResponse(result);
466 break;
Peter Kastingd039b772021-08-18 00:06:20467 case MockDnsClientRule::ResultType::kTimeout:
Eric Orth7dc18e92020-02-13 20:27:56468 DCHECK(!result->response); // Not expected to be provided.
469 break;
Peter Kastingd039b772021-08-18 00:06:20470 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53471 if (!fast_timeout)
472 SetResponse(result);
473 break;
Peter Kastingd039b772021-08-18 00:06:20474 case MockDnsClientRule::ResultType::kOk:
Eric Orth89726dd2020-10-13 20:19:53475 SetResponse(result);
Eric Orth7dc18e92020-02-13 20:27:56476 break;
Peter Kastingd039b772021-08-18 00:06:20477 case MockDnsClientRule::ResultType::kMalformed:
Eric Orth7dc18e92020-02-13 20:27:56478 DCHECK(!result->response); // Not expected to be provided.
479 result_.response = CreateMalformedResponse(hostname_, qtype_);
480 break;
Peter Kastingd039b772021-08-18 00:06:20481 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24482 ADD_FAILURE()
483 << "Unexpected DNS transaction created for hostname "
484 << hostname_;
485 break;
Eric Orth7dc18e92020-02-13 20:27:56486 }
Eric Orth2a61be82020-02-12 17:56:48487
Eric Orth7dc18e92020-02-13 20:27:56488 break;
489 }
Eric Orth3421db382019-10-20 02:35:52490 }
[email protected]daae1322013-09-05 18:26:50491 }
[email protected]0adcb2b2012-08-15 21:30:46492 }
493
Eric Orth3421db382019-10-20 02:35:52494 const std::string& GetHostname() const override { return hostname_; }
[email protected]daae1322013-09-05 18:26:50495
Eric Orth3421db382019-10-20 02:35:52496 uint16_t GetType() const override { return qtype_; }
497
498 void Start() override {
499 EXPECT_FALSE(started_);
500 started_ = true;
501 if (delayed_)
502 return;
503 // Using WeakPtr to cleanly cancel when transaction is destroyed.
504 base::ThreadTaskRunnerHandle::Get()->PostTask(
505 FROM_HERE, base::BindOnce(&MockTransaction::Finish, AsWeakPtr()));
506 }
507
508 void FinishDelayedTransaction() {
509 EXPECT_TRUE(delayed_);
510 delayed_ = false;
511 Finish();
512 }
513
514 bool delayed() const { return delayed_; }
515
516 private:
Eric Orth89726dd2020-10-13 20:19:53517 void SetResponse(const MockDnsClientRule::Result* result) {
518 if (result->response) {
519 // Copy response in case |result| is destroyed before the transaction
520 // completes.
Eric Ortha97f0f72020-10-16 16:10:32521 auto buffer_copy =
522 base::MakeRefCounted<IOBuffer>(result->response->io_buffer_size());
523 memcpy(buffer_copy->data(), result->response->io_buffer()->data(),
524 result->response->io_buffer_size());
525 result_.response = DnsResponse(std::move(buffer_copy),
526 result->response->io_buffer_size());
Eric Orth89726dd2020-10-13 20:19:53527 CHECK(result_.response->InitParseWithoutQuery(
528 result->response->io_buffer_size()));
529 } else {
530 // Generated response only available for address types.
531 DCHECK(qtype_ == dns_protocol::kTypeA ||
532 qtype_ == dns_protocol::kTypeAAAA);
Eric Ortha97f0f72020-10-16 16:10:32533 result_.response = BuildTestDnsAddressResponse(
534 hostname_, qtype_ == dns_protocol::kTypeA
535 ? IPAddress::IPv4Localhost()
536 : IPAddress::IPv6Localhost());
Eric Orth89726dd2020-10-13 20:19:53537 }
538 }
539
Eric Orth3421db382019-10-20 02:35:52540 void Finish() {
541 switch (result_.type) {
Peter Kastingd039b772021-08-18 00:06:20542 case MockDnsClientRule::ResultType::kNoDomain:
543 case MockDnsClientRule::ResultType::kFail: {
Eric Orthac9aafb2021-07-29 23:03:43544 int error = result_.net_error.value_or(ERR_NAME_NOT_RESOLVED);
545 DCHECK_NE(error, OK);
546 std::move(callback_).Run(this, error,
547 base::OptionalOrNullptr(result_.response),
548 absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52549 break;
Eric Orthac9aafb2021-07-29 23:03:43550 }
Peter Kastingd039b772021-08-18 00:06:20551 case MockDnsClientRule::ResultType::kEmpty:
552 case MockDnsClientRule::ResultType::kOk:
553 case MockDnsClientRule::ResultType::kMalformed:
Eric Orthac9aafb2021-07-29 23:03:43554 DCHECK(!result_.net_error.has_value());
Eric Ortha97f0f72020-10-16 16:10:32555 std::move(callback_).Run(
Eric Orthac9aafb2021-07-29 23:03:43556 this, OK, base::OptionalOrNullptr(result_.response), absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52557 break;
Peter Kastingd039b772021-08-18 00:06:20558 case MockDnsClientRule::ResultType::kTimeout:
Eric Orthac9aafb2021-07-29 23:03:43559 DCHECK(!result_.net_error.has_value());
Daniel McArdle4e2037e2020-06-11 22:40:51560 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
Anton Bikineev068d2912021-05-15 20:43:52561 absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52562 break;
Peter Kastingd039b772021-08-18 00:06:20563 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53564 if (result_.response) {
Eric Ortha97f0f72020-10-16 16:10:32565 std::move(callback_).Run(
Eric Orthac9aafb2021-07-29 23:03:43566 this, result_.net_error.value_or(OK),
567 result_.response ? &result_.response.value() : nullptr,
Anton Bikineev068d2912021-05-15 20:43:52568 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53569 } else {
Eric Orthac9aafb2021-07-29 23:03:43570 DCHECK(!result_.net_error.has_value());
Eric Orth89726dd2020-10-13 20:19:53571 std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
Anton Bikineev068d2912021-05-15 20:43:52572 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53573 }
Eric Orthcf8e00f2021-07-24 00:41:24574 break;
Peter Kastingd039b772021-08-18 00:06:20575 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24576 ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
577 << hostname_;
578 break;
Eric Orth3421db382019-10-20 02:35:52579 }
580 }
581
582 void SetRequestPriority(RequestPriority priority) override {}
583
584 MockDnsClientRule::Result result_;
585 const std::string hostname_;
586 const uint16_t qtype_;
587 DnsTransactionFactory::CallbackType callback_;
588 bool started_;
589 bool delayed_;
[email protected]0adcb2b2012-08-15 21:30:46590};
591
Eric Orth41b249e02020-01-03 20:21:47592class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
593 public:
594 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
595 : factory_(std::move(factory)) {}
596
597 ~MockDohProbeRunner() override {
598 if (factory_)
599 factory_->running_doh_probe_runners_.erase(this);
600 }
601
Eric Orth020e5fe2020-03-12 17:43:43602 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47603 DCHECK(factory_);
604 factory_->running_doh_probe_runners_.insert(this);
605 }
606
Eric Orth41b249e02020-01-03 20:21:47607 base::TimeDelta GetDelayUntilNextProbeForTest(
608 size_t doh_server_index) const override {
609 NOTREACHED();
610 return base::TimeDelta();
611 }
612
613 private:
614 base::WeakPtr<MockDnsTransactionFactory> factory_;
615};
616
Eric Orth3421db382019-10-20 02:35:52617MockDnsTransactionFactory::MockDnsTransactionFactory(
618 MockDnsClientRuleList rules)
619 : rules_(std::move(rules)) {}
620
621MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
622
623std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
Eric Orthc4cca5d2021-07-02 19:59:01624 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52625 uint16_t qtype,
626 DnsTransactionFactory::CallbackType callback,
627 const NetLogWithSource&,
628 bool secure,
Eric Ortha093b092020-09-24 23:13:02629 SecureDnsMode secure_dns_mode,
Eric Orth89726dd2020-10-13 20:19:53630 ResolveContext* resolve_context,
631 bool fast_timeout) {
Eric Orth3421db382019-10-20 02:35:52632 std::unique_ptr<MockTransaction> transaction =
Eric Orthc4cca5d2021-07-02 19:59:01633 std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
634 secure, force_doh_server_available_,
635 secure_dns_mode, resolve_context,
636 fast_timeout, std::move(callback));
Eric Orth3421db382019-10-20 02:35:52637 if (transaction->delayed())
638 delayed_transactions_.push_back(transaction->AsWeakPtr());
639 return transaction;
640}
641
Eric Orth41b249e02020-01-03 20:21:47642std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24643 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47644 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
645}
646
Eric Orth3421db382019-10-20 02:35:52647void MockDnsTransactionFactory::AddEDNSOption(const OptRecordRdata::Opt& opt) {}
648
Eric Ortha093b092020-09-24 23:13:02649SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
650 return SecureDnsMode::kAutomatic;
Eric Orth3421db382019-10-20 02:35:52651}
652
653void MockDnsTransactionFactory::CompleteDelayedTransactions() {
654 DelayedTransactionList old_delayed_transactions;
655 old_delayed_transactions.swap(delayed_transactions_);
656 for (auto it = old_delayed_transactions.begin();
657 it != old_delayed_transactions.end(); ++it) {
658 if (it->get())
659 (*it)->FinishDelayedTransaction();
660 }
661}
662
David Van Cleve1fb5e8c2019-11-04 16:45:16663bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
664 DnsQueryType type) {
665 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
666 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
667 t->FinishDelayedTransaction();
668 t.reset();
669 return true;
670 }
671 }
672 return false;
673}
674
Eric Orth394db1732019-08-27 20:09:39675MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
676 : config_(std::move(config)),
Eric Orth3421db382019-10-20 02:35:52677 factory_(new MockDnsTransactionFactory(std::move(rules))),
Eric Orth394db1732019-08-27 20:09:39678 address_sorter_(new MockAddressSorter()) {
679 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50680 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39681}
[email protected]78eac2a2012-03-14 19:09:27682
Chris Watkins68b15032017-12-01 03:07:13683MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27684
Eric Orth394db1732019-08-27 20:09:39685bool MockDnsClient::CanUseSecureDnsTransactions() const {
686 const DnsConfig* config = GetEffectiveConfig();
Benjamin M. Schwartz5f948312022-02-16 15:37:37687 return config && config->IsValid() && !config->doh_config.servers().empty();
[email protected]daae1322013-09-05 18:26:50688}
[email protected]78eac2a2012-03-14 19:09:27689
Eric Orth394db1732019-08-27 20:09:39690bool MockDnsClient::CanUseInsecureDnsTransactions() const {
691 const DnsConfig* config = GetEffectiveConfig();
692 return config && config->IsValid() && insecure_enabled_ &&
693 !config->dns_over_tls_active;
694}
695
Eric Orth09746312021-05-05 15:44:58696bool MockDnsClient::CanQueryAdditionalTypesViaInsecureDns() const {
697 DCHECK(CanUseInsecureDnsTransactions());
698 return additional_types_enabled_;
699}
700
701void MockDnsClient::SetInsecureEnabled(bool enabled,
702 bool additional_types_enabled) {
Eric Orth394db1732019-08-27 20:09:39703 insecure_enabled_ = enabled;
Eric Orth09746312021-05-05 15:44:58704 additional_types_enabled_ = additional_types_enabled;
Eric Orth394db1732019-08-27 20:09:39705}
706
Eric Orth069a3c6e2020-01-31 23:14:24707bool MockDnsClient::FallbackFromSecureTransactionPreferred(
708 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56709 bool doh_server_available =
710 force_doh_server_available_ ||
711 context->NumAvailableDohServers(session_.get()) > 0;
712 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22713}
714
Eric Orth394db1732019-08-27 20:09:39715bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
716 return !CanUseInsecureDnsTransactions() ||
717 fallback_failures_ >= max_fallback_failures_;
718}
719
Anton Bikineev068d2912021-05-15 20:43:52720bool MockDnsClient::SetSystemConfig(absl::optional<DnsConfig> system_config) {
Eric Orth394db1732019-08-27 20:09:39721 if (ignore_system_config_changes_)
722 return false;
723
Anton Bikineev068d2912021-05-15 20:43:52724 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39725 config_ = std::move(system_config);
726 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50727 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39728 return before != effective_config_;
729}
730
731bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
Anton Bikineev068d2912021-05-15 20:43:52732 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39733 overrides_ = std::move(config_overrides);
734 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50735 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39736 return before != effective_config_;
737}
738
Eric Orth020e5fe2020-03-12 17:43:43739void MockDnsClient::ReplaceCurrentSession() {
740 // Noop if no current effective config.
741 session_ = BuildSession();
742}
743
Eric Orthaf82b49a2020-02-01 01:48:50744DnsSession* MockDnsClient::GetCurrentSession() {
745 return session_.get();
746}
747
Eric Orth394db1732019-08-27 20:09:39748const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
749 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
750}
751
752const DnsHosts* MockDnsClient::GetHosts() const {
753 const DnsConfig* config = GetEffectiveConfig();
754 if (!config)
755 return nullptr;
756
757 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50758}
[email protected]78eac2a2012-03-14 19:09:27759
[email protected]daae1322013-09-05 18:26:50760DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39761 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50762}
[email protected]78eac2a2012-03-14 19:09:27763
[email protected]daae1322013-09-05 18:26:50764AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39765 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
766}
767
768void MockDnsClient::IncrementInsecureFallbackFailures() {
769 ++fallback_failures_;
770}
771
772void MockDnsClient::ClearInsecureFallbackFailures() {
773 fallback_failures_ = 0;
774}
775
Anton Bikineev068d2912021-05-15 20:43:52776absl::optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
Eric Orth394db1732019-08-27 20:09:39777 return config_;
778}
779
780DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
781 return overrides_;
[email protected]daae1322013-09-05 18:26:50782}
[email protected]0adcb2b2012-08-15 21:30:46783
Eric Orth3421db382019-10-20 02:35:52784void MockDnsClient::SetTransactionFactoryForTesting(
785 std::unique_ptr<DnsTransactionFactory> factory) {
786 NOTREACHED();
787}
788
Benjamin M. Schwartz6f719eb2021-12-15 17:47:28789absl::optional<AddressList> MockDnsClient::GetPresetAddrs(
790 const url::SchemeHostPort& endpoint) const {
791 EXPECT_THAT(preset_endpoint_, testing::Optional(endpoint));
792 return preset_addrs_;
793}
794
[email protected]daae1322013-09-05 18:26:50795void MockDnsClient::CompleteDelayedTransactions() {
796 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27797}
798
David Van Cleve1fb5e8c2019-11-04 16:45:16799bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
800 return factory_->CompleteOneDelayedTransactionOfType(type);
801}
802
Eric Orth7dc18e92020-02-13 20:27:56803void MockDnsClient::SetForceDohServerAvailable(bool available) {
804 force_doh_server_available_ = available;
805 factory_->set_force_doh_server_available(available);
806}
807
Anton Bikineev068d2912021-05-15 20:43:52808absl::optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
Eric Orth394db1732019-08-27 20:09:39809 if (overrides_.OverridesEverything())
810 return overrides_.ApplyOverrides(DnsConfig());
811 if (!config_ || !config_.value().IsValid())
Anton Bikineev068d2912021-05-15 20:43:52812 return absl::nullopt;
Eric Orth394db1732019-08-27 20:09:39813
814 return overrides_.ApplyOverrides(config_.value());
815}
816
Eric Orthaf82b49a2020-02-01 01:48:50817scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
818 if (!effective_config_)
819 return nullptr;
820
821 // Session not expected to be used for anything that will actually require
822 // random numbers.
823 auto null_random_callback =
824 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
825
Eric Orth9300cc62020-08-21 00:29:34826 auto socket_allocator = std::make_unique<DnsSocketAllocator>(
Eric Orth990a74a92020-08-20 18:41:26827 &socket_factory_, effective_config_.value().nameservers,
828 nullptr /* net_log */);
829
Eric Orthaf82b49a2020-02-01 01:48:50830 return base::MakeRefCounted<DnsSession>(
Eric Orth9300cc62020-08-21 00:29:34831 effective_config_.value(), std::move(socket_allocator),
832 null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50833}
834
[email protected]78eac2a2012-03-14 19:09:27835} // namespace net