blob: 4827aabd00a707dff5d9be729e1b038c55d614d4 [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"
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).
422 for (size_t i = 0; i < rules.size(); ++i) {
423 const std::string& prefix = rules[i].prefix;
424 if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
Eric Orthc4cca5d2021-07-02 19:59:01425 (hostname_.size() >= prefix.size()) &&
426 (hostname_.compare(0, prefix.size(), prefix) == 0) &&
Eric Orth7dc18e92020-02-13 20:27:56427 (!rules[i].context ||
428 rules[i].context == resolve_context->url_request_context())) {
429 const MockDnsClientRule::Result* result = &rules[i].result;
430 result_ = MockDnsClientRule::Result(result->type);
Eric Orthac9aafb2021-07-29 23:03:43431 result_.net_error = result->net_error;
Eric Orth7dc18e92020-02-13 20:27:56432 delayed_ = rules[i].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);
Eric Orth7a85ca52022-03-25 11:04:04547 std::move(callback_).Run(
548 error, base::OptionalOrNullptr(result_.response), 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 Orth7a85ca52022-03-25 11:04:04555 std::move(callback_).Run(OK, base::OptionalOrNullptr(result_.response),
556 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());
Eric Orth7a85ca52022-03-25 11:04:04560 std::move(callback_).Run(ERR_DNS_TIMED_OUT, nullptr, absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52561 break;
Peter Kastingd039b772021-08-18 00:06:20562 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53563 if (result_.response) {
Eric Ortha97f0f72020-10-16 16:10:32564 std::move(callback_).Run(
Eric Orth7a85ca52022-03-25 11:04:04565 result_.net_error.value_or(OK),
Eric Orthac9aafb2021-07-29 23:03:43566 result_.response ? &result_.response.value() : nullptr,
Anton Bikineev068d2912021-05-15 20:43:52567 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53568 } else {
Eric Orthac9aafb2021-07-29 23:03:43569 DCHECK(!result_.net_error.has_value());
Eric Orth7a85ca52022-03-25 11:04:04570 std::move(callback_).Run(ERR_DNS_TIMED_OUT, nullptr, absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53571 }
Eric Orthcf8e00f2021-07-24 00:41:24572 break;
Peter Kastingd039b772021-08-18 00:06:20573 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24574 ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
575 << hostname_;
576 break;
Eric Orth3421db382019-10-20 02:35:52577 }
578 }
579
580 void SetRequestPriority(RequestPriority priority) override {}
581
Tsuyoshi Horo432981d52022-06-09 09:50:13582 MockDnsClientRule::Result result_{MockDnsClientRule::ResultType::kFail};
Eric Orth3421db382019-10-20 02:35:52583 const std::string hostname_;
584 const uint16_t qtype_;
Eric Orth7a85ca52022-03-25 11:04:04585 ResponseCallback callback_;
586 bool started_ = false;
587 bool delayed_ = false;
[email protected]0adcb2b2012-08-15 21:30:46588};
589
Eric Orth41b249e02020-01-03 20:21:47590class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
591 public:
592 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
593 : factory_(std::move(factory)) {}
594
595 ~MockDohProbeRunner() override {
596 if (factory_)
597 factory_->running_doh_probe_runners_.erase(this);
598 }
599
Eric Orth020e5fe2020-03-12 17:43:43600 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47601 DCHECK(factory_);
602 factory_->running_doh_probe_runners_.insert(this);
603 }
604
Eric Orth41b249e02020-01-03 20:21:47605 base::TimeDelta GetDelayUntilNextProbeForTest(
606 size_t doh_server_index) const override {
607 NOTREACHED();
608 return base::TimeDelta();
609 }
610
611 private:
612 base::WeakPtr<MockDnsTransactionFactory> factory_;
613};
614
Eric Orth3421db382019-10-20 02:35:52615MockDnsTransactionFactory::MockDnsTransactionFactory(
616 MockDnsClientRuleList rules)
617 : rules_(std::move(rules)) {}
618
619MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
620
621std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
Eric Orthc4cca5d2021-07-02 19:59:01622 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52623 uint16_t qtype,
Eric Orth3421db382019-10-20 02:35:52624 const NetLogWithSource&,
625 bool secure,
Eric Ortha093b092020-09-24 23:13:02626 SecureDnsMode secure_dns_mode,
Eric Orth89726dd2020-10-13 20:19:53627 ResolveContext* resolve_context,
628 bool fast_timeout) {
Eric Orth3421db382019-10-20 02:35:52629 std::unique_ptr<MockTransaction> transaction =
Eric Orthc4cca5d2021-07-02 19:59:01630 std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
631 secure, force_doh_server_available_,
632 secure_dns_mode, resolve_context,
Eric Orth7a85ca52022-03-25 11:04:04633 fast_timeout);
Eric Orth3421db382019-10-20 02:35:52634 if (transaction->delayed())
635 delayed_transactions_.push_back(transaction->AsWeakPtr());
636 return transaction;
637}
638
Eric Orth41b249e02020-01-03 20:21:47639std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24640 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47641 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
642}
643
Eric Orth3421db382019-10-20 02:35:52644void MockDnsTransactionFactory::AddEDNSOption(const OptRecordRdata::Opt& opt) {}
645
Eric Ortha093b092020-09-24 23:13:02646SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
647 return SecureDnsMode::kAutomatic;
Eric Orth3421db382019-10-20 02:35:52648}
649
650void MockDnsTransactionFactory::CompleteDelayedTransactions() {
651 DelayedTransactionList old_delayed_transactions;
652 old_delayed_transactions.swap(delayed_transactions_);
653 for (auto it = old_delayed_transactions.begin();
654 it != old_delayed_transactions.end(); ++it) {
655 if (it->get())
656 (*it)->FinishDelayedTransaction();
657 }
658}
659
David Van Cleve1fb5e8c2019-11-04 16:45:16660bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
661 DnsQueryType type) {
662 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
663 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
664 t->FinishDelayedTransaction();
665 t.reset();
666 return true;
667 }
668 }
669 return false;
670}
671
Eric Orth394db1732019-08-27 20:09:39672MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
673 : config_(std::move(config)),
Eric Orth3421db382019-10-20 02:35:52674 factory_(new MockDnsTransactionFactory(std::move(rules))),
Eric Orth394db1732019-08-27 20:09:39675 address_sorter_(new MockAddressSorter()) {
676 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50677 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39678}
[email protected]78eac2a2012-03-14 19:09:27679
Chris Watkins68b15032017-12-01 03:07:13680MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27681
Eric Orth394db1732019-08-27 20:09:39682bool MockDnsClient::CanUseSecureDnsTransactions() const {
683 const DnsConfig* config = GetEffectiveConfig();
Benjamin M. Schwartz5f948312022-02-16 15:37:37684 return config && config->IsValid() && !config->doh_config.servers().empty();
[email protected]daae1322013-09-05 18:26:50685}
[email protected]78eac2a2012-03-14 19:09:27686
Eric Orth394db1732019-08-27 20:09:39687bool MockDnsClient::CanUseInsecureDnsTransactions() const {
688 const DnsConfig* config = GetEffectiveConfig();
689 return config && config->IsValid() && insecure_enabled_ &&
690 !config->dns_over_tls_active;
691}
692
Eric Orth09746312021-05-05 15:44:58693bool MockDnsClient::CanQueryAdditionalTypesViaInsecureDns() const {
694 DCHECK(CanUseInsecureDnsTransactions());
695 return additional_types_enabled_;
696}
697
698void MockDnsClient::SetInsecureEnabled(bool enabled,
699 bool additional_types_enabled) {
Eric Orth394db1732019-08-27 20:09:39700 insecure_enabled_ = enabled;
Eric Orth09746312021-05-05 15:44:58701 additional_types_enabled_ = additional_types_enabled;
Eric Orth394db1732019-08-27 20:09:39702}
703
Eric Orth069a3c6e2020-01-31 23:14:24704bool MockDnsClient::FallbackFromSecureTransactionPreferred(
705 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56706 bool doh_server_available =
707 force_doh_server_available_ ||
708 context->NumAvailableDohServers(session_.get()) > 0;
709 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22710}
711
Eric Orth394db1732019-08-27 20:09:39712bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
713 return !CanUseInsecureDnsTransactions() ||
714 fallback_failures_ >= max_fallback_failures_;
715}
716
Anton Bikineev068d2912021-05-15 20:43:52717bool MockDnsClient::SetSystemConfig(absl::optional<DnsConfig> system_config) {
Eric Orth394db1732019-08-27 20:09:39718 if (ignore_system_config_changes_)
719 return false;
720
Anton Bikineev068d2912021-05-15 20:43:52721 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39722 config_ = std::move(system_config);
723 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50724 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39725 return before != effective_config_;
726}
727
728bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
Anton Bikineev068d2912021-05-15 20:43:52729 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39730 overrides_ = std::move(config_overrides);
731 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50732 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39733 return before != effective_config_;
734}
735
Eric Orth020e5fe2020-03-12 17:43:43736void MockDnsClient::ReplaceCurrentSession() {
737 // Noop if no current effective config.
738 session_ = BuildSession();
739}
740
Eric Orthaf82b49a2020-02-01 01:48:50741DnsSession* MockDnsClient::GetCurrentSession() {
742 return session_.get();
743}
744
Eric Orth394db1732019-08-27 20:09:39745const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
746 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
747}
748
Dan McArdle312ba6e2022-03-29 18:49:55749base::Value MockDnsClient::GetDnsConfigAsValueForNetLog() const {
750 // This is just a stub implementation that never produces a meaningful value.
751 return base::Value(base::Value::Dict());
752}
753
Eric Orth394db1732019-08-27 20:09:39754const DnsHosts* MockDnsClient::GetHosts() const {
755 const DnsConfig* config = GetEffectiveConfig();
756 if (!config)
757 return nullptr;
758
759 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50760}
[email protected]78eac2a2012-03-14 19:09:27761
[email protected]daae1322013-09-05 18:26:50762DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39763 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50764}
[email protected]78eac2a2012-03-14 19:09:27765
[email protected]daae1322013-09-05 18:26:50766AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39767 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
768}
769
770void MockDnsClient::IncrementInsecureFallbackFailures() {
771 ++fallback_failures_;
772}
773
774void MockDnsClient::ClearInsecureFallbackFailures() {
775 fallback_failures_ = 0;
776}
777
Anton Bikineev068d2912021-05-15 20:43:52778absl::optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
Eric Orth394db1732019-08-27 20:09:39779 return config_;
780}
781
782DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
783 return overrides_;
[email protected]daae1322013-09-05 18:26:50784}
[email protected]0adcb2b2012-08-15 21:30:46785
Eric Orth3421db382019-10-20 02:35:52786void MockDnsClient::SetTransactionFactoryForTesting(
787 std::unique_ptr<DnsTransactionFactory> factory) {
788 NOTREACHED();
789}
790
Benjamin M. Schwartz6f719eb2021-12-15 17:47:28791absl::optional<AddressList> MockDnsClient::GetPresetAddrs(
792 const url::SchemeHostPort& endpoint) const {
793 EXPECT_THAT(preset_endpoint_, testing::Optional(endpoint));
794 return preset_addrs_;
795}
796
[email protected]daae1322013-09-05 18:26:50797void MockDnsClient::CompleteDelayedTransactions() {
798 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27799}
800
David Van Cleve1fb5e8c2019-11-04 16:45:16801bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
802 return factory_->CompleteOneDelayedTransactionOfType(type);
803}
804
Eric Orth7dc18e92020-02-13 20:27:56805void MockDnsClient::SetForceDohServerAvailable(bool available) {
806 force_doh_server_available_ = available;
807 factory_->set_force_doh_server_available(available);
808}
809
Anton Bikineev068d2912021-05-15 20:43:52810absl::optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
Eric Orth394db1732019-08-27 20:09:39811 if (overrides_.OverridesEverything())
812 return overrides_.ApplyOverrides(DnsConfig());
813 if (!config_ || !config_.value().IsValid())
Anton Bikineev068d2912021-05-15 20:43:52814 return absl::nullopt;
Eric Orth394db1732019-08-27 20:09:39815
816 return overrides_.ApplyOverrides(config_.value());
817}
818
Eric Orthaf82b49a2020-02-01 01:48:50819scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
820 if (!effective_config_)
821 return nullptr;
822
823 // Session not expected to be used for anything that will actually require
824 // random numbers.
825 auto null_random_callback =
826 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
827
828 return base::MakeRefCounted<DnsSession>(
Liza Burakovab8d8dc02022-04-01 22:10:46829 effective_config_.value(), null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50830}
831
[email protected]78eac2a2012-03-14 19:09:27832} // namespace net