blob: a5d8e57c31980fe70e254d8dbb3885ab5f3be139 [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"
Daniel Cheng522adbb2022-08-29 17:18:5723#include "base/types/optional_util.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"
tfarina77021d62015-10-11 20:19:0332#include "net/dns/dns_util.h"
Benjamin M. Schwartz571353c22021-12-13 16:41:1133#include "net/dns/public/dns_over_https_server_config.h"
Eric Orth069a3c6e2020-01-31 23:14:2434#include "net/dns/resolve_context.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2835#include "testing/gmock/include/gmock/gmock-matchers.h"
[email protected]78eac2a2012-03-14 19:09:2736#include "testing/gtest/include/gtest/gtest.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2837#include "url/scheme_host_port.h"
[email protected]78eac2a2012-03-14 19:09:2738
39namespace net {
40namespace {
41
Eric Orth828bd3ae2018-12-12 17:30:3642const uint8_t kMalformedResponseHeader[] = {
43 // Header
44 0x00, 0x14, // Arbitrary ID
45 0x81, 0x80, // Standard query response, RA, no error
46 0x00, 0x01, // 1 question
47 0x00, 0x01, // 1 RR (answers)
48 0x00, 0x00, // 0 authority RRs
49 0x00, 0x00, // 0 additional RRs
50};
51
52// Create a response containing a valid question (as would normally be validated
53// in DnsTransaction) but completely missing a header-declared answer.
Eric Ortha97f0f72020-10-16 16:10:3254DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) {
Eric Orth828bd3ae2018-12-12 17:30:3655 std::string dns_name;
56 CHECK(DNSDomainFromDot(hostname, &dns_name));
57 DnsQuery query(0x14 /* id */, dns_name, type);
58
59 // Build response to simulate the barebones validation DnsResponse applies to
60 // responses received from the network.
61 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
62 sizeof(kMalformedResponseHeader) + query.question().size());
63 memcpy(buffer->data(), kMalformedResponseHeader,
64 sizeof(kMalformedResponseHeader));
65 memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
66 query.question().data(), query.question().size());
67
Eric Ortha97f0f72020-10-16 16:10:3268 DnsResponse response(buffer, buffer->size());
69 CHECK(response.InitParseWithoutQuery(buffer->size()));
Eric Orth828bd3ae2018-12-12 17:30:3670
71 return response;
72}
73
[email protected]daae1322013-09-05 18:26:5074class MockAddressSorter : public AddressSorter {
75 public:
Chris Watkins68b15032017-12-01 03:07:1376 ~MockAddressSorter() override = default;
Eric Orth48b1b7c2022-01-21 00:21:1677 void Sort(const std::vector<IPEndPoint>& endpoints,
78 CallbackType callback) const override {
[email protected]daae1322013-09-05 18:26:5079 // Do nothing.
Eric Orth48b1b7c2022-01-21 00:21:1680 std::move(callback).Run(true, endpoints);
[email protected]daae1322013-09-05 18:26:5081 }
82};
83
[email protected]daae1322013-09-05 18:26:5084} // namespace
[email protected]78eac2a2012-03-14 19:09:2785
Eric Orth8539e492020-10-19 20:09:5586DnsResourceRecord BuildTestDnsRecord(std::string name,
87 uint16_t type,
88 std::string rdata,
89 base::TimeDelta ttl) {
David Van Cleve34c74c72019-10-31 19:58:0190 DCHECK(!name.empty());
David Van Cleve34c74c72019-10-31 19:58:0191
92 DnsResourceRecord record;
93 record.name = std::move(name);
Eric Orth8539e492020-10-19 20:09:5594 record.type = type;
David Van Cleve34c74c72019-10-31 19:58:0195 record.klass = dns_protocol::kClassIN;
Eric Orth8539e492020-10-19 20:09:5596 record.ttl = ttl.InSeconds();
Eric Orth5d21f152020-10-21 19:15:4397
98 if (!rdata.empty())
99 record.SetOwnedRdata(std::move(rdata));
David Van Cleve34c74c72019-10-31 19:58:01100
101 return record;
102}
103
Eric Orth65fd3e32020-11-18 04:59:17104DnsResourceRecord BuildTestCnameRecord(std::string name,
105 base::StringPiece canonical_name,
106 base::TimeDelta ttl) {
107 DCHECK(!name.empty());
108 DCHECK(!canonical_name.empty());
109
110 std::string rdata;
111 CHECK(DNSDomainFromDot(canonical_name, &rdata));
112
113 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeCNAME,
114 std::move(rdata), ttl);
115}
116
Eric Orth8539e492020-10-19 20:09:55117DnsResourceRecord BuildTestAddressRecord(std::string name,
118 const IPAddress& ip,
119 base::TimeDelta ttl) {
120 DCHECK(!name.empty());
Eric Orth828bd3ae2018-12-12 17:30:36121 DCHECK(ip.IsValid());
122
Eric Orth8539e492020-10-19 20:09:55123 return BuildTestDnsRecord(
124 std::move(name),
125 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA,
126 net::IPAddressToPackedString(ip), ttl);
127}
128
Eric Orth3b26e3ba2020-11-12 22:43:13129DnsResourceRecord BuildTestTextRecord(std::string name,
130 std::vector<std::string> text_strings,
131 base::TimeDelta ttl) {
132 DCHECK(!text_strings.empty());
133
134 std::string rdata;
135 for (const std::string& text_string : text_strings) {
136 DCHECK(!text_string.empty());
137
138 rdata += base::checked_cast<unsigned char>(text_string.size());
139 rdata += text_string;
140 }
141
142 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT,
Eric Orthd16fee6b2020-11-18 06:43:14143 std::move(rdata), ttl);
Eric Orth3b26e3ba2020-11-12 22:43:13144}
145
Eric Orth7139e0552020-11-04 02:41:11146DnsResourceRecord BuildTestHttpsAliasRecord(std::string name,
147 base::StringPiece alias_name,
148 base::TimeDelta ttl) {
149 DCHECK(!name.empty());
150
151 std::string rdata("\000\000", 2);
152
153 std::string alias_domain;
154 CHECK(DNSDomainFromDot(alias_name, &alias_domain));
155 rdata.append(alias_domain);
156
157 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
158 std::move(rdata), ttl);
159}
160
Eric Orth17a07d42022-03-08 22:12:16161std::pair<uint16_t, std::string> BuildTestHttpsServiceAlpnParam(
162 const std::vector<std::string>& alpns) {
163 std::string param_value;
164
165 for (const std::string& alpn : alpns) {
166 CHECK(!alpn.empty());
167 param_value.append(
168 1, static_cast<char>(base::checked_cast<uint8_t>(alpn.size())));
169 param_value.append(alpn);
170 }
171
172 return std::make_pair(dns_protocol::kHttpsServiceParamKeyAlpn,
173 std::move(param_value));
174}
175
176std::pair<uint16_t, std::string> BuildTestHttpsServiceEchConfigParam(
177 base::span<const uint8_t> ech_config_list) {
178 return std::make_pair(
179 dns_protocol::kHttpsServiceParamKeyEchConfig,
180 std::string(reinterpret_cast<const char*>(ech_config_list.data()),
181 ech_config_list.size()));
182}
183
Eric Orth4a2621c2022-02-23 00:45:31184std::pair<uint16_t, std::string> BuildTestHttpsServiceMandatoryParam(
185 std::vector<uint16_t> param_key_list) {
186 base::ranges::sort(param_key_list);
187
188 std::string value;
189 for (uint16_t param_key : param_key_list) {
190 char num_buffer[2];
191 base::WriteBigEndian(num_buffer, param_key);
192 value.append(num_buffer, 2);
193 }
194
195 return std::make_pair(dns_protocol::kHttpsServiceParamKeyMandatory,
196 std::move(value));
197}
198
Eric Orth17a07d42022-03-08 22:12:16199std::pair<uint16_t, std::string> BuildTestHttpsServicePortParam(uint16_t port) {
200 char buffer[2];
201 base::WriteBigEndian(buffer, port);
202
203 return std::make_pair(dns_protocol::kHttpsServiceParamKeyPort,
204 std::string(buffer, 2));
205}
206
Eric Orth7139e0552020-11-04 02:41:11207DnsResourceRecord BuildTestHttpsServiceRecord(
208 std::string name,
209 uint16_t priority,
210 base::StringPiece service_name,
211 const std::map<uint16_t, std::string>& params,
212 base::TimeDelta ttl) {
213 DCHECK(!name.empty());
214 DCHECK_NE(priority, 0);
215
216 std::string rdata;
217
218 char num_buffer[2];
219 base::WriteBigEndian(num_buffer, priority);
220 rdata.append(num_buffer, 2);
221
222 std::string service_domain;
Eric Orthac9aafb2021-07-29 23:03:43223 if (service_name == ".") {
224 // HTTPS records have special behavior for `service_name == "."` (that it
225 // will be treated as if the service name is the same as the record owner
226 // name), so allow such inputs despite normally being disallowed for
227 // Chrome-encoded DNS names.
228 service_domain = '\x00';
229 } else {
230 CHECK(DNSDomainFromDot(service_name, &service_domain));
231 }
Eric Orth7139e0552020-11-04 02:41:11232 rdata.append(service_domain);
233
234 for (auto& param : params) {
235 base::WriteBigEndian(num_buffer, param.first);
236 rdata.append(num_buffer, 2);
237
238 base::WriteBigEndian(num_buffer,
239 base::checked_cast<uint16_t>(param.second.size()));
240 rdata.append(num_buffer, 2);
241
242 rdata.append(param.second);
243 }
244
245 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
246 std::move(rdata), ttl);
247}
248
Eric Orth8539e492020-10-19 20:09:55249DnsResponse BuildTestDnsResponse(
250 std::string name,
251 uint16_t type,
Eric Orth69c25992020-11-10 16:55:12252 const std::vector<DnsResourceRecord>& answers,
253 const std::vector<DnsResourceRecord>& authority,
Eric Orth9cec76f2020-11-17 07:42:42254 const std::vector<DnsResourceRecord>& additional,
255 uint8_t rcode) {
Eric Orth8539e492020-10-19 20:09:55256 DCHECK(!name.empty());
257
Eric Orth828bd3ae2018-12-12 17:30:36258 std::string dns_name;
259 CHECK(DNSDomainFromDot(name, &dns_name));
Eric Orth8539e492020-10-19 20:09:55260
Anton Bikineev068d2912021-05-15 20:43:52261 absl::optional<DnsQuery> query(absl::in_place, 0, std::move(dns_name), type);
Eric Orth8539e492020-10-19 20:09:55262 return DnsResponse(0, true /* is_authoritative */, answers,
Eric Orth69c25992020-11-10 16:55:12263 authority /* authority_records */,
Eric Orth9cec76f2020-11-17 07:42:42264 additional /* additional_records */, query, rcode,
Eric Orthd16fee6b2020-11-18 06:43:14265 false /* validate_records */);
Eric Orth828bd3ae2018-12-12 17:30:36266}
267
Eric Orth8539e492020-10-19 20:09:55268DnsResponse BuildTestDnsAddressResponse(std::string name,
269 const IPAddress& ip,
270 std::string answer_name) {
271 DCHECK(ip.IsValid());
272
273 if (answer_name.empty())
274 answer_name = name;
275
276 std::vector<DnsResourceRecord> answers = {
277 BuildTestAddressRecord(std::move(answer_name), ip)};
278
279 return BuildTestDnsResponse(
280 std::move(name),
281 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
282}
283
Eric Ortha97f0f72020-10-16 16:10:32284DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
285 const IPAddress& ip,
Eric Orth8539e492020-10-19 20:09:55286 std::string cannonname,
287 std::string answer_name) {
Eric Orth828bd3ae2018-12-12 17:30:36288 DCHECK(ip.IsValid());
289 DCHECK(!cannonname.empty());
290
Eric Orth8539e492020-10-19 20:09:55291 if (answer_name.empty())
292 answer_name = name;
293
294 std::string cname_rdata;
295 CHECK(DNSDomainFromDot(cannonname, &cname_rdata));
296
Eric Orth828bd3ae2018-12-12 17:30:36297 std::vector<DnsResourceRecord> answers = {
Eric Orth8539e492020-10-19 20:09:55298 BuildTestDnsRecord(std::move(answer_name), dns_protocol::kTypeCNAME,
299 std::move(cname_rdata)),
300 BuildTestAddressRecord(std::move(cannonname), ip)};
301
302 return BuildTestDnsResponse(
303 std::move(name),
304 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
Eric Orth828bd3ae2018-12-12 17:30:36305}
306
Eric Ortha97f0f72020-10-16 16:10:32307DnsResponse BuildTestDnsTextResponse(
Eric Orth828bd3ae2018-12-12 17:30:36308 std::string name,
309 std::vector<std::vector<std::string>> text_records,
310 std::string answer_name) {
311 if (answer_name.empty())
312 answer_name = name;
313
314 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45315 for (std::vector<std::string>& text_record : text_records) {
Eric Orth3b26e3ba2020-11-12 22:43:13316 answers.push_back(BuildTestTextRecord(answer_name, std::move(text_record)));
Eric Orth828bd3ae2018-12-12 17:30:36317 }
318
Eric Orth8539e492020-10-19 20:09:55319 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeTXT, answers);
Eric Orth828bd3ae2018-12-12 17:30:36320}
321
Eric Ortha97f0f72020-10-16 16:10:32322DnsResponse BuildTestDnsPointerResponse(std::string name,
323 std::vector<std::string> pointer_names,
324 std::string answer_name) {
Eric Orthe9db8d232019-01-14 21:24:45325 if (answer_name.empty())
326 answer_name = name;
327
328 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45329 for (std::string& pointer_name : pointer_names) {
Eric Orth8539e492020-10-19 20:09:55330 std::string rdata;
331 CHECK(DNSDomainFromDot(pointer_name, &rdata));
332
333 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypePTR,
334 std::move(rdata)));
Eric Orthe9db8d232019-01-14 21:24:45335 }
336
Eric Orth8539e492020-10-19 20:09:55337 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers);
Eric Orthe9db8d232019-01-14 21:24:45338}
339
Eric Ortha97f0f72020-10-16 16:10:32340DnsResponse BuildTestDnsServiceResponse(
Eric Ortha625b042019-01-16 01:14:45341 std::string name,
342 std::vector<TestServiceRecord> service_records,
343 std::string answer_name) {
344 if (answer_name.empty())
345 answer_name = name;
346
347 std::vector<DnsResourceRecord> answers;
348 for (TestServiceRecord& service_record : service_records) {
Eric Orth8539e492020-10-19 20:09:55349 std::string rdata;
350 char num_buffer[2];
351 base::WriteBigEndian(num_buffer, service_record.priority);
352 rdata.append(num_buffer, 2);
353 base::WriteBigEndian(num_buffer, service_record.weight);
354 rdata.append(num_buffer, 2);
355 base::WriteBigEndian(num_buffer, service_record.port);
356 rdata.append(num_buffer, 2);
357 std::string dns_name;
358 CHECK(DNSDomainFromDot(service_record.target, &dns_name));
359 rdata += dns_name;
360
361 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV,
Peter Kastinge5a38ed2021-10-02 03:06:35362 std::move(rdata), base::Hours(5)));
Eric Ortha625b042019-01-16 01:14:45363 }
364
Eric Orth8539e492020-10-19 20:09:55365 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers);
Daniel McArdle2daa3ec2020-06-03 16:05:48366}
367
Eric Orth89726dd2020-10-13 20:19:53368MockDnsClientRule::Result::Result(ResultType type,
Eric Orthac9aafb2021-07-29 23:03:43369 absl::optional<DnsResponse> response,
370 absl::optional<int> net_error)
371 : type(type), response(std::move(response)), net_error(net_error) {}
Eric Orth828bd3ae2018-12-12 17:30:36372
Eric Ortha97f0f72020-10-16 16:10:32373MockDnsClientRule::Result::Result(DnsResponse response)
Peter Kastingd039b772021-08-18 00:06:20374 : type(ResultType::kOk),
375 response(std::move(response)),
376 net_error(absl::nullopt) {}
Eric Orth828bd3ae2018-12-12 17:30:36377
Peter Kastingd039b772021-08-18 00:06:20378MockDnsClientRule::Result::Result(Result&&) = default;
379
380MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(Result&&) =
381 default;
Eric Orth828bd3ae2018-12-12 17:30:36382
383MockDnsClientRule::Result::~Result() = default;
384
Eric Orth502d5682019-04-12 00:21:33385MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
386 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13387 bool secure,
Eric Orth502d5682019-04-12 00:21:33388 Result result,
389 bool delay,
390 URLRequestContext* context)
391 : result(std::move(result)),
392 prefix(prefix),
393 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13394 secure(secure),
Eric Orth502d5682019-04-12 00:21:33395 delay(delay),
396 context(context) {}
397
398MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
399
Eric Orth3421db382019-10-20 02:35:52400// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
401class MockDnsTransactionFactory::MockTransaction
402 : public DnsTransaction,
403 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27404 public:
Eric Orth3421db382019-10-20 02:35:52405 MockTransaction(const MockDnsClientRuleList& rules,
Eric Orthc4cca5d2021-07-02 19:59:01406 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52407 uint16_t qtype,
408 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56409 bool force_doh_server_available,
Eric Ortha093b092020-09-24 23:13:02410 SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56411 ResolveContext* resolve_context,
Eric Orth7a85ca52022-03-25 11:04:04412 bool fast_timeout)
Tsuyoshi Horo432981d52022-06-09 09:50:13413 : hostname_(std::move(hostname)), qtype_(qtype) {
Eric Orth7dc18e92020-02-13 20:27:56414 // Do not allow matching any rules if transaction is secure and no DoH
415 // servers are available.
416 if (!secure || force_doh_server_available ||
417 resolve_context->NumAvailableDohServers(
418 resolve_context->current_session_for_testing()) > 0) {
419 // Find the relevant rule which matches |qtype|, |secure|, prefix of
Eric Orthc4cca5d2021-07-02 19:59:01420 // |hostname_|, and |url_request_context| (iff the rule context is not
Eric Orth7dc18e92020-02-13 20:27:56421 // null).
Tsuyoshi Horo17ef47d02022-06-30 10:58:27422 for (const auto& rule : rules) {
423 const std::string& prefix = rule.prefix;
424 if ((rule.qtype == qtype) && (rule.secure == secure) &&
Eric Orthc4cca5d2021-07-02 19:59:01425 (hostname_.size() >= prefix.size()) &&
426 (hostname_.compare(0, prefix.size(), prefix) == 0) &&
Tsuyoshi Horo17ef47d02022-06-30 10:58:27427 (!rule.context ||
428 rule.context == resolve_context->url_request_context())) {
429 const MockDnsClientRule::Result* result = &rule.result;
Eric Orth7dc18e92020-02-13 20:27:56430 result_ = MockDnsClientRule::Result(result->type);
Eric Orthac9aafb2021-07-29 23:03:43431 result_.net_error = result->net_error;
Tsuyoshi Horo17ef47d02022-06-30 10:58:27432 delayed_ = rule.delay;
[email protected]daae1322013-09-05 18:26:50433
Eric Orth7dc18e92020-02-13 20:27:56434 // Generate a DnsResponse when not provided with the rule.
435 std::vector<DnsResourceRecord> authority_records;
436 std::string dns_name;
437 CHECK(DNSDomainFromDot(hostname_, &dns_name));
Anton Bikineev068d2912021-05-15 20:43:52438 absl::optional<DnsQuery> query(absl::in_place, 22 /* id */, dns_name,
Eric Orth7dc18e92020-02-13 20:27:56439 qtype_);
440 switch (result->type) {
Peter Kastingd039b772021-08-18 00:06:20441 case MockDnsClientRule::ResultType::kNoDomain:
442 case MockDnsClientRule::ResultType::kEmpty:
Eric Orth7dc18e92020-02-13 20:27:56443 DCHECK(!result->response); // Not expected to be provided.
Eric Orth8539e492020-10-19 20:09:55444 authority_records = {BuildTestDnsRecord(
445 hostname_, dns_protocol::kTypeSOA, "fake rdata")};
Eric Ortha97f0f72020-10-16 16:10:32446 result_.response = DnsResponse(
Eric Orth7dc18e92020-02-13 20:27:56447 22 /* id */, false /* is_authoritative */,
448 std::vector<DnsResourceRecord>() /* answers */,
449 authority_records,
450 std::vector<DnsResourceRecord>() /* additional_records */,
451 query,
Peter Kastingd039b772021-08-18 00:06:20452 result->type == MockDnsClientRule::ResultType::kNoDomain
Eric Orth7dc18e92020-02-13 20:27:56453 ? dns_protocol::kRcodeNXDOMAIN
454 : 0);
455 break;
Peter Kastingd039b772021-08-18 00:06:20456 case MockDnsClientRule::ResultType::kFail:
Eric Orthac9aafb2021-07-29 23:03:43457 if (result->response)
458 SetResponse(result);
459 break;
Peter Kastingd039b772021-08-18 00:06:20460 case MockDnsClientRule::ResultType::kTimeout:
Eric Orth7dc18e92020-02-13 20:27:56461 DCHECK(!result->response); // Not expected to be provided.
462 break;
Peter Kastingd039b772021-08-18 00:06:20463 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53464 if (!fast_timeout)
465 SetResponse(result);
466 break;
Peter Kastingd039b772021-08-18 00:06:20467 case MockDnsClientRule::ResultType::kOk:
Eric Orth89726dd2020-10-13 20:19:53468 SetResponse(result);
Eric Orth7dc18e92020-02-13 20:27:56469 break;
Peter Kastingd039b772021-08-18 00:06:20470 case MockDnsClientRule::ResultType::kMalformed:
Eric Orth7dc18e92020-02-13 20:27:56471 DCHECK(!result->response); // Not expected to be provided.
472 result_.response = CreateMalformedResponse(hostname_, qtype_);
473 break;
Peter Kastingd039b772021-08-18 00:06:20474 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orth761feee2022-03-31 22:21:35475 if (!delayed_) {
476 // Assume a delayed kUnexpected transaction is only an issue if
477 // allowed to complete.
478 ADD_FAILURE()
479 << "Unexpected DNS transaction created for hostname "
480 << hostname_;
481 }
Eric Orthcf8e00f2021-07-24 00:41:24482 break;
Eric Orth7dc18e92020-02-13 20:27:56483 }
Eric Orth2a61be82020-02-12 17:56:48484
Eric Orth7dc18e92020-02-13 20:27:56485 break;
486 }
Eric Orth3421db382019-10-20 02:35:52487 }
[email protected]daae1322013-09-05 18:26:50488 }
[email protected]0adcb2b2012-08-15 21:30:46489 }
490
Eric Orth3421db382019-10-20 02:35:52491 const std::string& GetHostname() const override { return hostname_; }
[email protected]daae1322013-09-05 18:26:50492
Eric Orth3421db382019-10-20 02:35:52493 uint16_t GetType() const override { return qtype_; }
494
Eric Orth7a85ca52022-03-25 11:04:04495 void Start(ResponseCallback callback) override {
496 CHECK(!callback.is_null());
497 CHECK(callback_.is_null());
Eric Orth3421db382019-10-20 02:35:52498 EXPECT_FALSE(started_);
Eric Orth7a85ca52022-03-25 11:04:04499
500 callback_ = std::move(callback);
Eric Orth3421db382019-10-20 02:35:52501 started_ = true;
502 if (delayed_)
503 return;
504 // Using WeakPtr to cleanly cancel when transaction is destroyed.
505 base::ThreadTaskRunnerHandle::Get()->PostTask(
506 FROM_HERE, base::BindOnce(&MockTransaction::Finish, AsWeakPtr()));
507 }
508
509 void FinishDelayedTransaction() {
510 EXPECT_TRUE(delayed_);
511 delayed_ = false;
512 Finish();
513 }
514
515 bool delayed() const { return delayed_; }
516
517 private:
Eric Orth89726dd2020-10-13 20:19:53518 void SetResponse(const MockDnsClientRule::Result* result) {
519 if (result->response) {
520 // Copy response in case |result| is destroyed before the transaction
521 // completes.
Eric Ortha97f0f72020-10-16 16:10:32522 auto buffer_copy =
523 base::MakeRefCounted<IOBuffer>(result->response->io_buffer_size());
524 memcpy(buffer_copy->data(), result->response->io_buffer()->data(),
525 result->response->io_buffer_size());
526 result_.response = DnsResponse(std::move(buffer_copy),
527 result->response->io_buffer_size());
Eric Orth89726dd2020-10-13 20:19:53528 CHECK(result_.response->InitParseWithoutQuery(
529 result->response->io_buffer_size()));
530 } else {
531 // Generated response only available for address types.
532 DCHECK(qtype_ == dns_protocol::kTypeA ||
533 qtype_ == dns_protocol::kTypeAAAA);
Eric Ortha97f0f72020-10-16 16:10:32534 result_.response = BuildTestDnsAddressResponse(
535 hostname_, qtype_ == dns_protocol::kTypeA
536 ? IPAddress::IPv4Localhost()
537 : IPAddress::IPv6Localhost());
Eric Orth89726dd2020-10-13 20:19:53538 }
539 }
540
Eric Orth3421db382019-10-20 02:35:52541 void Finish() {
542 switch (result_.type) {
Peter Kastingd039b772021-08-18 00:06:20543 case MockDnsClientRule::ResultType::kNoDomain:
544 case MockDnsClientRule::ResultType::kFail: {
Eric Orthac9aafb2021-07-29 23:03:43545 int error = result_.net_error.value_or(ERR_NAME_NOT_RESOLVED);
546 DCHECK_NE(error, OK);
Daniel Cheng522adbb2022-08-29 17:18:57547 std::move(callback_).Run(error, base::OptionalToPtr(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());
Daniel Cheng522adbb2022-08-29 17:18:57554 std::move(callback_).Run(OK, base::OptionalToPtr(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