blob: fd2e535ef4e9a47ac3edc1e1503b3a0cc9d3db75 [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"
[email protected]78eac2a2012-03-14 19:09:2723#include "net/base/io_buffer.h"
Eric Orth828bd3ae2018-12-12 17:30:3624#include "net/base/ip_address.h"
Eric Orth48b1b7c2022-01-21 00:21:1625#include "net/base/ip_endpoint.h"
[email protected]78eac2a2012-03-14 19:09:2726#include "net/base/net_errors.h"
[email protected]0adcb2b2012-08-15 21:30:4627#include "net/dns/address_sorter.h"
Eric Orth394db1732019-08-27 20:09:3928#include "net/dns/dns_hosts.h"
[email protected]78eac2a2012-03-14 19:09:2729#include "net/dns/dns_query.h"
Eric Orthaf82b49a2020-02-01 01:48:5030#include "net/dns/dns_session.h"
tfarina77021d62015-10-11 20:19:0331#include "net/dns/dns_util.h"
Benjamin M. Schwartz571353c22021-12-13 16:41:1132#include "net/dns/public/dns_over_https_server_config.h"
Eric Orth069a3c6e2020-01-31 23:14:2433#include "net/dns/resolve_context.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2834#include "testing/gmock/include/gmock/gmock-matchers.h"
[email protected]78eac2a2012-03-14 19:09:2735#include "testing/gtest/include/gtest/gtest.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2836#include "url/scheme_host_port.h"
[email protected]78eac2a2012-03-14 19:09:2737
38namespace net {
39namespace {
40
Eric Orth828bd3ae2018-12-12 17:30:3641const uint8_t kMalformedResponseHeader[] = {
42 // Header
43 0x00, 0x14, // Arbitrary ID
44 0x81, 0x80, // Standard query response, RA, no error
45 0x00, 0x01, // 1 question
46 0x00, 0x01, // 1 RR (answers)
47 0x00, 0x00, // 0 authority RRs
48 0x00, 0x00, // 0 additional RRs
49};
50
51// Create a response containing a valid question (as would normally be validated
52// in DnsTransaction) but completely missing a header-declared answer.
Eric Ortha97f0f72020-10-16 16:10:3253DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) {
Eric Orth828bd3ae2018-12-12 17:30:3654 std::string dns_name;
55 CHECK(DNSDomainFromDot(hostname, &dns_name));
56 DnsQuery query(0x14 /* id */, dns_name, type);
57
58 // Build response to simulate the barebones validation DnsResponse applies to
59 // responses received from the network.
60 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
61 sizeof(kMalformedResponseHeader) + query.question().size());
62 memcpy(buffer->data(), kMalformedResponseHeader,
63 sizeof(kMalformedResponseHeader));
64 memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
65 query.question().data(), query.question().size());
66
Eric Ortha97f0f72020-10-16 16:10:3267 DnsResponse response(buffer, buffer->size());
68 CHECK(response.InitParseWithoutQuery(buffer->size()));
Eric Orth828bd3ae2018-12-12 17:30:3669
70 return response;
71}
72
[email protected]daae1322013-09-05 18:26:5073class MockAddressSorter : public AddressSorter {
74 public:
Chris Watkins68b15032017-12-01 03:07:1375 ~MockAddressSorter() override = default;
Eric Orth48b1b7c2022-01-21 00:21:1676 void Sort(const std::vector<IPEndPoint>& endpoints,
77 CallbackType callback) const override {
[email protected]daae1322013-09-05 18:26:5078 // Do nothing.
Eric Orth48b1b7c2022-01-21 00:21:1679 std::move(callback).Run(true, endpoints);
[email protected]daae1322013-09-05 18:26:5080 }
81};
82
[email protected]daae1322013-09-05 18:26:5083} // namespace
[email protected]78eac2a2012-03-14 19:09:2784
Eric Orth8539e492020-10-19 20:09:5585DnsResourceRecord BuildTestDnsRecord(std::string name,
86 uint16_t type,
87 std::string rdata,
88 base::TimeDelta ttl) {
David Van Cleve34c74c72019-10-31 19:58:0189 DCHECK(!name.empty());
David Van Cleve34c74c72019-10-31 19:58:0190
91 DnsResourceRecord record;
92 record.name = std::move(name);
Eric Orth8539e492020-10-19 20:09:5593 record.type = type;
David Van Cleve34c74c72019-10-31 19:58:0194 record.klass = dns_protocol::kClassIN;
Eric Orth8539e492020-10-19 20:09:5595 record.ttl = ttl.InSeconds();
Eric Orth5d21f152020-10-21 19:15:4396
97 if (!rdata.empty())
98 record.SetOwnedRdata(std::move(rdata));
David Van Cleve34c74c72019-10-31 19:58:0199
100 return record;
101}
102
Eric Orth65fd3e32020-11-18 04:59:17103DnsResourceRecord BuildTestCnameRecord(std::string name,
104 base::StringPiece canonical_name,
105 base::TimeDelta ttl) {
106 DCHECK(!name.empty());
107 DCHECK(!canonical_name.empty());
108
109 std::string rdata;
110 CHECK(DNSDomainFromDot(canonical_name, &rdata));
111
112 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeCNAME,
113 std::move(rdata), ttl);
114}
115
Eric Orth8539e492020-10-19 20:09:55116DnsResourceRecord BuildTestAddressRecord(std::string name,
117 const IPAddress& ip,
118 base::TimeDelta ttl) {
119 DCHECK(!name.empty());
Eric Orth828bd3ae2018-12-12 17:30:36120 DCHECK(ip.IsValid());
121
Eric Orth8539e492020-10-19 20:09:55122 return BuildTestDnsRecord(
123 std::move(name),
124 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA,
125 net::IPAddressToPackedString(ip), ttl);
126}
127
Eric Orth3b26e3ba2020-11-12 22:43:13128DnsResourceRecord BuildTestTextRecord(std::string name,
129 std::vector<std::string> text_strings,
130 base::TimeDelta ttl) {
131 DCHECK(!text_strings.empty());
132
133 std::string rdata;
134 for (const std::string& text_string : text_strings) {
135 DCHECK(!text_string.empty());
136
137 rdata += base::checked_cast<unsigned char>(text_string.size());
138 rdata += text_string;
139 }
140
141 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT,
Eric Orthd16fee6b2020-11-18 06:43:14142 std::move(rdata), ttl);
Eric Orth3b26e3ba2020-11-12 22:43:13143}
144
Eric Orth7139e0552020-11-04 02:41:11145DnsResourceRecord BuildTestHttpsAliasRecord(std::string name,
146 base::StringPiece alias_name,
147 base::TimeDelta ttl) {
148 DCHECK(!name.empty());
149
150 std::string rdata("\000\000", 2);
151
152 std::string alias_domain;
153 CHECK(DNSDomainFromDot(alias_name, &alias_domain));
154 rdata.append(alias_domain);
155
156 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
157 std::move(rdata), ttl);
158}
159
Eric Orth17a07d42022-03-08 22:12:16160std::pair<uint16_t, std::string> BuildTestHttpsServiceAlpnParam(
161 const std::vector<std::string>& alpns) {
162 std::string param_value;
163
164 for (const std::string& alpn : alpns) {
165 CHECK(!alpn.empty());
166 param_value.append(
167 1, static_cast<char>(base::checked_cast<uint8_t>(alpn.size())));
168 param_value.append(alpn);
169 }
170
171 return std::make_pair(dns_protocol::kHttpsServiceParamKeyAlpn,
172 std::move(param_value));
173}
174
175std::pair<uint16_t, std::string> BuildTestHttpsServiceEchConfigParam(
176 base::span<const uint8_t> ech_config_list) {
177 return std::make_pair(
178 dns_protocol::kHttpsServiceParamKeyEchConfig,
179 std::string(reinterpret_cast<const char*>(ech_config_list.data()),
180 ech_config_list.size()));
181}
182
Eric Orth4a2621c2022-02-23 00:45:31183std::pair<uint16_t, std::string> BuildTestHttpsServiceMandatoryParam(
184 std::vector<uint16_t> param_key_list) {
185 base::ranges::sort(param_key_list);
186
187 std::string value;
188 for (uint16_t param_key : param_key_list) {
189 char num_buffer[2];
190 base::WriteBigEndian(num_buffer, param_key);
191 value.append(num_buffer, 2);
192 }
193
194 return std::make_pair(dns_protocol::kHttpsServiceParamKeyMandatory,
195 std::move(value));
196}
197
Eric Orth17a07d42022-03-08 22:12:16198std::pair<uint16_t, std::string> BuildTestHttpsServicePortParam(uint16_t port) {
199 char buffer[2];
200 base::WriteBigEndian(buffer, port);
201
202 return std::make_pair(dns_protocol::kHttpsServiceParamKeyPort,
203 std::string(buffer, 2));
204}
205
Eric Orth7139e0552020-11-04 02:41:11206DnsResourceRecord BuildTestHttpsServiceRecord(
207 std::string name,
208 uint16_t priority,
209 base::StringPiece service_name,
210 const std::map<uint16_t, std::string>& params,
211 base::TimeDelta ttl) {
212 DCHECK(!name.empty());
213 DCHECK_NE(priority, 0);
214
215 std::string rdata;
216
217 char num_buffer[2];
218 base::WriteBigEndian(num_buffer, priority);
219 rdata.append(num_buffer, 2);
220
221 std::string service_domain;
Eric Orthac9aafb2021-07-29 23:03:43222 if (service_name == ".") {
223 // HTTPS records have special behavior for `service_name == "."` (that it
224 // will be treated as if the service name is the same as the record owner
225 // name), so allow such inputs despite normally being disallowed for
226 // Chrome-encoded DNS names.
227 service_domain = '\x00';
228 } else {
229 CHECK(DNSDomainFromDot(service_name, &service_domain));
230 }
Eric Orth7139e0552020-11-04 02:41:11231 rdata.append(service_domain);
232
233 for (auto& param : params) {
234 base::WriteBigEndian(num_buffer, param.first);
235 rdata.append(num_buffer, 2);
236
237 base::WriteBigEndian(num_buffer,
238 base::checked_cast<uint16_t>(param.second.size()));
239 rdata.append(num_buffer, 2);
240
241 rdata.append(param.second);
242 }
243
244 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
245 std::move(rdata), ttl);
246}
247
Eric Orth8539e492020-10-19 20:09:55248DnsResponse BuildTestDnsResponse(
249 std::string name,
250 uint16_t type,
Eric Orth69c25992020-11-10 16:55:12251 const std::vector<DnsResourceRecord>& answers,
252 const std::vector<DnsResourceRecord>& authority,
Eric Orth9cec76f2020-11-17 07:42:42253 const std::vector<DnsResourceRecord>& additional,
254 uint8_t rcode) {
Eric Orth8539e492020-10-19 20:09:55255 DCHECK(!name.empty());
256
Eric Orth828bd3ae2018-12-12 17:30:36257 std::string dns_name;
258 CHECK(DNSDomainFromDot(name, &dns_name));
Eric Orth8539e492020-10-19 20:09:55259
Anton Bikineev068d2912021-05-15 20:43:52260 absl::optional<DnsQuery> query(absl::in_place, 0, std::move(dns_name), type);
Eric Orth8539e492020-10-19 20:09:55261 return DnsResponse(0, true /* is_authoritative */, answers,
Eric Orth69c25992020-11-10 16:55:12262 authority /* authority_records */,
Eric Orth9cec76f2020-11-17 07:42:42263 additional /* additional_records */, query, rcode,
Eric Orthd16fee6b2020-11-18 06:43:14264 false /* validate_records */);
Eric Orth828bd3ae2018-12-12 17:30:36265}
266
Eric Orth8539e492020-10-19 20:09:55267DnsResponse BuildTestDnsAddressResponse(std::string name,
268 const IPAddress& ip,
269 std::string answer_name) {
270 DCHECK(ip.IsValid());
271
272 if (answer_name.empty())
273 answer_name = name;
274
275 std::vector<DnsResourceRecord> answers = {
276 BuildTestAddressRecord(std::move(answer_name), ip)};
277
278 return BuildTestDnsResponse(
279 std::move(name),
280 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
281}
282
Eric Ortha97f0f72020-10-16 16:10:32283DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
284 const IPAddress& ip,
Eric Orth8539e492020-10-19 20:09:55285 std::string cannonname,
286 std::string answer_name) {
Eric Orth828bd3ae2018-12-12 17:30:36287 DCHECK(ip.IsValid());
288 DCHECK(!cannonname.empty());
289
Eric Orth8539e492020-10-19 20:09:55290 if (answer_name.empty())
291 answer_name = name;
292
293 std::string cname_rdata;
294 CHECK(DNSDomainFromDot(cannonname, &cname_rdata));
295
Eric Orth828bd3ae2018-12-12 17:30:36296 std::vector<DnsResourceRecord> answers = {
Eric Orth8539e492020-10-19 20:09:55297 BuildTestDnsRecord(std::move(answer_name), dns_protocol::kTypeCNAME,
298 std::move(cname_rdata)),
299 BuildTestAddressRecord(std::move(cannonname), ip)};
300
301 return BuildTestDnsResponse(
302 std::move(name),
303 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
Eric Orth828bd3ae2018-12-12 17:30:36304}
305
Eric Ortha97f0f72020-10-16 16:10:32306DnsResponse BuildTestDnsTextResponse(
Eric Orth828bd3ae2018-12-12 17:30:36307 std::string name,
308 std::vector<std::vector<std::string>> text_records,
309 std::string answer_name) {
310 if (answer_name.empty())
311 answer_name = name;
312
313 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45314 for (std::vector<std::string>& text_record : text_records) {
Eric Orth3b26e3ba2020-11-12 22:43:13315 answers.push_back(BuildTestTextRecord(answer_name, std::move(text_record)));
Eric Orth828bd3ae2018-12-12 17:30:36316 }
317
Eric Orth8539e492020-10-19 20:09:55318 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeTXT, answers);
Eric Orth828bd3ae2018-12-12 17:30:36319}
320
Eric Ortha97f0f72020-10-16 16:10:32321DnsResponse BuildTestDnsPointerResponse(std::string name,
322 std::vector<std::string> pointer_names,
323 std::string answer_name) {
Eric Orthe9db8d232019-01-14 21:24:45324 if (answer_name.empty())
325 answer_name = name;
326
327 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45328 for (std::string& pointer_name : pointer_names) {
Eric Orth8539e492020-10-19 20:09:55329 std::string rdata;
330 CHECK(DNSDomainFromDot(pointer_name, &rdata));
331
332 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypePTR,
333 std::move(rdata)));
Eric Orthe9db8d232019-01-14 21:24:45334 }
335
Eric Orth8539e492020-10-19 20:09:55336 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers);
Eric Orthe9db8d232019-01-14 21:24:45337}
338
Eric Ortha97f0f72020-10-16 16:10:32339DnsResponse BuildTestDnsServiceResponse(
Eric Ortha625b042019-01-16 01:14:45340 std::string name,
341 std::vector<TestServiceRecord> service_records,
342 std::string answer_name) {
343 if (answer_name.empty())
344 answer_name = name;
345
346 std::vector<DnsResourceRecord> answers;
347 for (TestServiceRecord& service_record : service_records) {
Eric Orth8539e492020-10-19 20:09:55348 std::string rdata;
349 char num_buffer[2];
350 base::WriteBigEndian(num_buffer, service_record.priority);
351 rdata.append(num_buffer, 2);
352 base::WriteBigEndian(num_buffer, service_record.weight);
353 rdata.append(num_buffer, 2);
354 base::WriteBigEndian(num_buffer, service_record.port);
355 rdata.append(num_buffer, 2);
356 std::string dns_name;
357 CHECK(DNSDomainFromDot(service_record.target, &dns_name));
358 rdata += dns_name;
359
360 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV,
Peter Kastinge5a38ed2021-10-02 03:06:35361 std::move(rdata), base::Hours(5)));
Eric Ortha625b042019-01-16 01:14:45362 }
363
Eric Orth8539e492020-10-19 20:09:55364 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers);
Daniel McArdle2daa3ec2020-06-03 16:05:48365}
366
Eric Orth89726dd2020-10-13 20:19:53367MockDnsClientRule::Result::Result(ResultType type,
Eric Orthac9aafb2021-07-29 23:03:43368 absl::optional<DnsResponse> response,
369 absl::optional<int> net_error)
370 : type(type), response(std::move(response)), net_error(net_error) {}
Eric Orth828bd3ae2018-12-12 17:30:36371
Eric Ortha97f0f72020-10-16 16:10:32372MockDnsClientRule::Result::Result(DnsResponse response)
Peter Kastingd039b772021-08-18 00:06:20373 : type(ResultType::kOk),
374 response(std::move(response)),
375 net_error(absl::nullopt) {}
Eric Orth828bd3ae2018-12-12 17:30:36376
Peter Kastingd039b772021-08-18 00:06:20377MockDnsClientRule::Result::Result(Result&&) = default;
378
379MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(Result&&) =
380 default;
Eric Orth828bd3ae2018-12-12 17:30:36381
382MockDnsClientRule::Result::~Result() = default;
383
Eric Orth502d5682019-04-12 00:21:33384MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
385 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13386 bool secure,
Eric Orth502d5682019-04-12 00:21:33387 Result result,
388 bool delay,
389 URLRequestContext* context)
390 : result(std::move(result)),
391 prefix(prefix),
392 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13393 secure(secure),
Eric Orth502d5682019-04-12 00:21:33394 delay(delay),
395 context(context) {}
396
397MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
398
Eric Orth3421db382019-10-20 02:35:52399// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
400class MockDnsTransactionFactory::MockTransaction
401 : public DnsTransaction,
402 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27403 public:
Eric Orth3421db382019-10-20 02:35:52404 MockTransaction(const MockDnsClientRuleList& rules,
Eric Orthc4cca5d2021-07-02 19:59:01405 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52406 uint16_t qtype,
407 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56408 bool force_doh_server_available,
Eric Ortha093b092020-09-24 23:13:02409 SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56410 ResolveContext* resolve_context,
Eric Orth7a85ca52022-03-25 11:04:04411 bool fast_timeout)
Tsuyoshi Horo432981d52022-06-09 09:50:13412 : hostname_(std::move(hostname)), qtype_(qtype) {
Eric Orth7dc18e92020-02-13 20:27:56413 // Do not allow matching any rules if transaction is secure and no DoH
414 // servers are available.
415 if (!secure || force_doh_server_available ||
416 resolve_context->NumAvailableDohServers(
417 resolve_context->current_session_for_testing()) > 0) {
418 // Find the relevant rule which matches |qtype|, |secure|, prefix of
Eric Orthc4cca5d2021-07-02 19:59:01419 // |hostname_|, and |url_request_context| (iff the rule context is not
Eric Orth7dc18e92020-02-13 20:27:56420 // null).
Tsuyoshi Horo17ef47d02022-06-30 10:58:27421 for (const auto& rule : rules) {
422 const std::string& prefix = rule.prefix;
423 if ((rule.qtype == qtype) && (rule.secure == secure) &&
Eric Orthc4cca5d2021-07-02 19:59:01424 (hostname_.size() >= prefix.size()) &&
425 (hostname_.compare(0, prefix.size(), prefix) == 0) &&
Tsuyoshi Horo17ef47d02022-06-30 10:58:27426 (!rule.context ||
427 rule.context == resolve_context->url_request_context())) {
428 const MockDnsClientRule::Result* result = &rule.result;
Eric Orth7dc18e92020-02-13 20:27:56429 result_ = MockDnsClientRule::Result(result->type);
Eric Orthac9aafb2021-07-29 23:03:43430 result_.net_error = result->net_error;
Tsuyoshi Horo17ef47d02022-06-30 10:58:27431 delayed_ = rule.delay;
[email protected]daae1322013-09-05 18:26:50432
Eric Orth7dc18e92020-02-13 20:27:56433 // Generate a DnsResponse when not provided with the rule.
434 std::vector<DnsResourceRecord> authority_records;
435 std::string dns_name;
436 CHECK(DNSDomainFromDot(hostname_, &dns_name));
Anton Bikineev068d2912021-05-15 20:43:52437 absl::optional<DnsQuery> query(absl::in_place, 22 /* id */, dns_name,
Eric Orth7dc18e92020-02-13 20:27:56438 qtype_);
439 switch (result->type) {
Peter Kastingd039b772021-08-18 00:06:20440 case MockDnsClientRule::ResultType::kNoDomain:
441 case MockDnsClientRule::ResultType::kEmpty:
Eric Orth7dc18e92020-02-13 20:27:56442 DCHECK(!result->response); // Not expected to be provided.
Eric Orth8539e492020-10-19 20:09:55443 authority_records = {BuildTestDnsRecord(
444 hostname_, dns_protocol::kTypeSOA, "fake rdata")};
Eric Ortha97f0f72020-10-16 16:10:32445 result_.response = DnsResponse(
Eric Orth7dc18e92020-02-13 20:27:56446 22 /* id */, false /* is_authoritative */,
447 std::vector<DnsResourceRecord>() /* answers */,
448 authority_records,
449 std::vector<DnsResourceRecord>() /* additional_records */,
450 query,
Peter Kastingd039b772021-08-18 00:06:20451 result->type == MockDnsClientRule::ResultType::kNoDomain
Eric Orth7dc18e92020-02-13 20:27:56452 ? dns_protocol::kRcodeNXDOMAIN
453 : 0);
454 break;
Peter Kastingd039b772021-08-18 00:06:20455 case MockDnsClientRule::ResultType::kFail:
Eric Orthac9aafb2021-07-29 23:03:43456 if (result->response)
457 SetResponse(result);
458 break;
Peter Kastingd039b772021-08-18 00:06:20459 case MockDnsClientRule::ResultType::kTimeout:
Eric Orth7dc18e92020-02-13 20:27:56460 DCHECK(!result->response); // Not expected to be provided.
461 break;
Peter Kastingd039b772021-08-18 00:06:20462 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53463 if (!fast_timeout)
464 SetResponse(result);
465 break;
Peter Kastingd039b772021-08-18 00:06:20466 case MockDnsClientRule::ResultType::kOk:
Eric Orth89726dd2020-10-13 20:19:53467 SetResponse(result);
Eric Orth7dc18e92020-02-13 20:27:56468 break;
Peter Kastingd039b772021-08-18 00:06:20469 case MockDnsClientRule::ResultType::kMalformed:
Eric Orth7dc18e92020-02-13 20:27:56470 DCHECK(!result->response); // Not expected to be provided.
471 result_.response = CreateMalformedResponse(hostname_, qtype_);
472 break;
Peter Kastingd039b772021-08-18 00:06:20473 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orth761feee2022-03-31 22:21:35474 if (!delayed_) {
475 // Assume a delayed kUnexpected transaction is only an issue if
476 // allowed to complete.
477 ADD_FAILURE()
478 << "Unexpected DNS transaction created for hostname "
479 << hostname_;
480 }
Eric Orthcf8e00f2021-07-24 00:41:24481 break;
Eric Orth7dc18e92020-02-13 20:27:56482 }
Eric Orth2a61be82020-02-12 17:56:48483
Eric Orth7dc18e92020-02-13 20:27:56484 break;
485 }
Eric Orth3421db382019-10-20 02:35:52486 }
[email protected]daae1322013-09-05 18:26:50487 }
[email protected]0adcb2b2012-08-15 21:30:46488 }
489
Eric Orth3421db382019-10-20 02:35:52490 const std::string& GetHostname() const override { return hostname_; }
[email protected]daae1322013-09-05 18:26:50491
Eric Orth3421db382019-10-20 02:35:52492 uint16_t GetType() const override { return qtype_; }
493
Eric Orth7a85ca52022-03-25 11:04:04494 void Start(ResponseCallback callback) override {
495 CHECK(!callback.is_null());
496 CHECK(callback_.is_null());
Eric Orth3421db382019-10-20 02:35:52497 EXPECT_FALSE(started_);
Eric Orth7a85ca52022-03-25 11:04:04498
499 callback_ = std::move(callback);
Eric Orth3421db382019-10-20 02:35:52500 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);
Dan McArdle6cbd4182022-06-13 21:23:54546 std::move(callback_).Run(error,
547 base::OptionalOrNullptr(result_.response));
Eric Orth3421db382019-10-20 02:35:52548 break;
Eric Orthac9aafb2021-07-29 23:03:43549 }
Peter Kastingd039b772021-08-18 00:06:20550 case MockDnsClientRule::ResultType::kEmpty:
551 case MockDnsClientRule::ResultType::kOk:
552 case MockDnsClientRule::ResultType::kMalformed:
Eric Orthac9aafb2021-07-29 23:03:43553 DCHECK(!result_.net_error.has_value());
Dan McArdle6cbd4182022-06-13 21:23:54554 std::move(callback_).Run(OK, base::OptionalOrNullptr(result_.response));
Eric Orth3421db382019-10-20 02:35:52555 break;
Peter Kastingd039b772021-08-18 00:06:20556 case MockDnsClientRule::ResultType::kTimeout:
Eric Orthac9aafb2021-07-29 23:03:43557 DCHECK(!result_.net_error.has_value());
Dan McArdle6cbd4182022-06-13 21:23:54558 std::move(callback_).Run(ERR_DNS_TIMED_OUT, /*response=*/nullptr);
Eric Orth3421db382019-10-20 02:35:52559 break;
Peter Kastingd039b772021-08-18 00:06:20560 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53561 if (result_.response) {
Eric Ortha97f0f72020-10-16 16:10:32562 std::move(callback_).Run(
Eric Orth7a85ca52022-03-25 11:04:04563 result_.net_error.value_or(OK),
Dan McArdle6cbd4182022-06-13 21:23:54564 result_.response ? &result_.response.value() : nullptr);
Eric Orth89726dd2020-10-13 20:19:53565 } else {
Eric Orthac9aafb2021-07-29 23:03:43566 DCHECK(!result_.net_error.has_value());
Dan McArdle6cbd4182022-06-13 21:23:54567 std::move(callback_).Run(ERR_DNS_TIMED_OUT, /*response=*/nullptr);
Eric Orth89726dd2020-10-13 20:19:53568 }
Eric Orthcf8e00f2021-07-24 00:41:24569 break;
Peter Kastingd039b772021-08-18 00:06:20570 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24571 ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
572 << hostname_;
573 break;
Eric Orth3421db382019-10-20 02:35:52574 }
575 }
576
577 void SetRequestPriority(RequestPriority priority) override {}
578
Tsuyoshi Horo432981d52022-06-09 09:50:13579 MockDnsClientRule::Result result_{MockDnsClientRule::ResultType::kFail};
Eric Orth3421db382019-10-20 02:35:52580 const std::string hostname_;
581 const uint16_t qtype_;
Eric Orth7a85ca52022-03-25 11:04:04582 ResponseCallback callback_;
583 bool started_ = false;
584 bool delayed_ = false;
[email protected]0adcb2b2012-08-15 21:30:46585};
586
Eric Orth41b249e02020-01-03 20:21:47587class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
588 public:
589 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
590 : factory_(std::move(factory)) {}
591
592 ~MockDohProbeRunner() override {
593 if (factory_)
594 factory_->running_doh_probe_runners_.erase(this);
595 }
596
Eric Orth020e5fe2020-03-12 17:43:43597 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47598 DCHECK(factory_);
599 factory_->running_doh_probe_runners_.insert(this);
600 }
601
Eric Orth41b249e02020-01-03 20:21:47602 base::TimeDelta GetDelayUntilNextProbeForTest(
603 size_t doh_server_index) const override {
604 NOTREACHED();
605 return base::TimeDelta();
606 }
607
608 private:
609 base::WeakPtr<MockDnsTransactionFactory> factory_;
610};
611
Eric Orth3421db382019-10-20 02:35:52612MockDnsTransactionFactory::MockDnsTransactionFactory(
613 MockDnsClientRuleList rules)
614 : rules_(std::move(rules)) {}
615
616MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
617
618std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
Eric Orthc4cca5d2021-07-02 19:59:01619 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52620 uint16_t qtype,
Eric Orth3421db382019-10-20 02:35:52621 const NetLogWithSource&,
622 bool secure,
Eric Ortha093b092020-09-24 23:13:02623 SecureDnsMode secure_dns_mode,
Eric Orth89726dd2020-10-13 20:19:53624 ResolveContext* resolve_context,
625 bool fast_timeout) {
Eric Orth3421db382019-10-20 02:35:52626 std::unique_ptr<MockTransaction> transaction =
Eric Orthc4cca5d2021-07-02 19:59:01627 std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
628 secure, force_doh_server_available_,
629 secure_dns_mode, resolve_context,
Eric Orth7a85ca52022-03-25 11:04:04630 fast_timeout);
Eric Orth3421db382019-10-20 02:35:52631 if (transaction->delayed())
632 delayed_transactions_.push_back(transaction->AsWeakPtr());
633 return transaction;
634}
635
Eric Orth41b249e02020-01-03 20:21:47636std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24637 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47638 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
639}
640
Sukrit Ganesh432190c2022-08-09 19:14:21641void MockDnsTransactionFactory::AddEDNSOption(
642 std::unique_ptr<OptRecordRdata::Opt> opt) {}
Eric Orth3421db382019-10-20 02:35:52643
Eric Ortha093b092020-09-24 23:13:02644SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
645 return SecureDnsMode::kAutomatic;
Eric Orth3421db382019-10-20 02:35:52646}
647
648void MockDnsTransactionFactory::CompleteDelayedTransactions() {
649 DelayedTransactionList old_delayed_transactions;
650 old_delayed_transactions.swap(delayed_transactions_);
Tsuyoshi Horo17ef47d02022-06-30 10:58:27651 for (auto& old_delayed_transaction : old_delayed_transactions) {
652 if (old_delayed_transaction.get())
653 old_delayed_transaction->FinishDelayedTransaction();
Eric Orth3421db382019-10-20 02:35:52654 }
655}
656
David Van Cleve1fb5e8c2019-11-04 16:45:16657bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
658 DnsQueryType type) {
659 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
660 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
661 t->FinishDelayedTransaction();
662 t.reset();
663 return true;
664 }
665 }
666 return false;
667}
668
Eric Orth394db1732019-08-27 20:09:39669MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
670 : config_(std::move(config)),
Tsuyoshi Horof8861cb2022-07-05 23:50:20671 factory_(std::make_unique<MockDnsTransactionFactory>(std::move(rules))),
672 address_sorter_(std::make_unique<MockAddressSorter>()) {
Eric Orth394db1732019-08-27 20:09:39673 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50674 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39675}
[email protected]78eac2a2012-03-14 19:09:27676
Chris Watkins68b15032017-12-01 03:07:13677MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27678
Eric Orth394db1732019-08-27 20:09:39679bool MockDnsClient::CanUseSecureDnsTransactions() const {
680 const DnsConfig* config = GetEffectiveConfig();
Benjamin M. Schwartz5f948312022-02-16 15:37:37681 return config && config->IsValid() && !config->doh_config.servers().empty();
[email protected]daae1322013-09-05 18:26:50682}
[email protected]78eac2a2012-03-14 19:09:27683
Eric Orth394db1732019-08-27 20:09:39684bool MockDnsClient::CanUseInsecureDnsTransactions() const {
685 const DnsConfig* config = GetEffectiveConfig();
686 return config && config->IsValid() && insecure_enabled_ &&
687 !config->dns_over_tls_active;
688}
689
Eric Orth09746312021-05-05 15:44:58690bool MockDnsClient::CanQueryAdditionalTypesViaInsecureDns() const {
691 DCHECK(CanUseInsecureDnsTransactions());
692 return additional_types_enabled_;
693}
694
695void MockDnsClient::SetInsecureEnabled(bool enabled,
696 bool additional_types_enabled) {
Eric Orth394db1732019-08-27 20:09:39697 insecure_enabled_ = enabled;
Eric Orth09746312021-05-05 15:44:58698 additional_types_enabled_ = additional_types_enabled;
Eric Orth394db1732019-08-27 20:09:39699}
700
Eric Orth069a3c6e2020-01-31 23:14:24701bool MockDnsClient::FallbackFromSecureTransactionPreferred(
702 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56703 bool doh_server_available =
704 force_doh_server_available_ ||
705 context->NumAvailableDohServers(session_.get()) > 0;
706 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22707}
708
Eric Orth394db1732019-08-27 20:09:39709bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
710 return !CanUseInsecureDnsTransactions() ||
711 fallback_failures_ >= max_fallback_failures_;
712}
713
Anton Bikineev068d2912021-05-15 20:43:52714bool MockDnsClient::SetSystemConfig(absl::optional<DnsConfig> system_config) {
Eric Orth394db1732019-08-27 20:09:39715 if (ignore_system_config_changes_)
716 return false;
717
Anton Bikineev068d2912021-05-15 20:43:52718 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39719 config_ = std::move(system_config);
720 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50721 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39722 return before != effective_config_;
723}
724
725bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
Anton Bikineev068d2912021-05-15 20:43:52726 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39727 overrides_ = std::move(config_overrides);
728 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50729 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39730 return before != effective_config_;
731}
732
Eric Orth020e5fe2020-03-12 17:43:43733void MockDnsClient::ReplaceCurrentSession() {
734 // Noop if no current effective config.
735 session_ = BuildSession();
736}
737
Eric Orthaf82b49a2020-02-01 01:48:50738DnsSession* MockDnsClient::GetCurrentSession() {
739 return session_.get();
740}
741
Eric Orth394db1732019-08-27 20:09:39742const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
743 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
744}
745
Dan McArdle312ba6e2022-03-29 18:49:55746base::Value MockDnsClient::GetDnsConfigAsValueForNetLog() const {
747 // This is just a stub implementation that never produces a meaningful value.
748 return base::Value(base::Value::Dict());
749}
750
Eric Orth394db1732019-08-27 20:09:39751const DnsHosts* MockDnsClient::GetHosts() const {
752 const DnsConfig* config = GetEffectiveConfig();
753 if (!config)
754 return nullptr;
755
756 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50757}
[email protected]78eac2a2012-03-14 19:09:27758
[email protected]daae1322013-09-05 18:26:50759DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39760 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50761}
[email protected]78eac2a2012-03-14 19:09:27762
[email protected]daae1322013-09-05 18:26:50763AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39764 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
765}
766
767void MockDnsClient::IncrementInsecureFallbackFailures() {
768 ++fallback_failures_;
769}
770
771void MockDnsClient::ClearInsecureFallbackFailures() {
772 fallback_failures_ = 0;
773}
774
Anton Bikineev068d2912021-05-15 20:43:52775absl::optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
Eric Orth394db1732019-08-27 20:09:39776 return config_;
777}
778
779DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
780 return overrides_;
[email protected]daae1322013-09-05 18:26:50781}
[email protected]0adcb2b2012-08-15 21:30:46782
Eric Orth3421db382019-10-20 02:35:52783void MockDnsClient::SetTransactionFactoryForTesting(
784 std::unique_ptr<DnsTransactionFactory> factory) {
785 NOTREACHED();
786}
787
Tsuyoshi Horodef72e42022-08-05 23:18:17788absl::optional<std::vector<IPEndPoint>> MockDnsClient::GetPresetAddrs(
Benjamin M. Schwartz6f719eb2021-12-15 17:47:28789 const url::SchemeHostPort& endpoint) const {
790 EXPECT_THAT(preset_endpoint_, testing::Optional(endpoint));
791 return preset_addrs_;
792}
793
[email protected]daae1322013-09-05 18:26:50794void MockDnsClient::CompleteDelayedTransactions() {
795 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27796}
797
David Van Cleve1fb5e8c2019-11-04 16:45:16798bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
799 return factory_->CompleteOneDelayedTransactionOfType(type);
800}
801
Eric Orth7dc18e92020-02-13 20:27:56802void MockDnsClient::SetForceDohServerAvailable(bool available) {
803 force_doh_server_available_ = available;
804 factory_->set_force_doh_server_available(available);
805}
806
Anton Bikineev068d2912021-05-15 20:43:52807absl::optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
Eric Orth394db1732019-08-27 20:09:39808 if (overrides_.OverridesEverything())
809 return overrides_.ApplyOverrides(DnsConfig());
810 if (!config_ || !config_.value().IsValid())
Anton Bikineev068d2912021-05-15 20:43:52811 return absl::nullopt;
Eric Orth394db1732019-08-27 20:09:39812
813 return overrides_.ApplyOverrides(config_.value());
814}
815
Eric Orthaf82b49a2020-02-01 01:48:50816scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
817 if (!effective_config_)
818 return nullptr;
819
820 // Session not expected to be used for anything that will actually require
821 // random numbers.
822 auto null_random_callback =
823 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
824
825 return base::MakeRefCounted<DnsSession>(
Liza Burakovab8d8dc02022-04-01 22:10:46826 effective_config_.value(), null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50827}
828
[email protected]78eac2a2012-03-14 19:09:27829} // namespace net