blob: cbbbef574af82dd915cad01b80f9547b8f961e52 [file] [log] [blame]
[email protected]78eac2a2012-03-14 19:09:271// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/dns/dns_test_util.h"
6
Eric Orth3b26e3ba2020-11-12 22:43:137#include <string>
8#include <utility>
9#include <vector>
10
[email protected]d9806a972014-02-26 18:14:5711#include "base/big_endian.h"
[email protected]78eac2a2012-03-14 19:09:2712#include "base/bind.h"
Eric Orth3b26e3ba2020-11-12 22:43:1313#include "base/check.h"
skyostil4891b25b2015-06-11 11:43:4514#include "base/location.h"
Eric Orth828bd3ae2018-12-12 17:30:3615#include "base/numerics/safe_conversions.h"
Benjamin M. Schwartz571353c22021-12-13 16:41:1116#include "base/ranges/algorithm.h"
Eric Orthac9aafb2021-07-29 23:03:4317#include "base/stl_util.h"
Dan McArdle00271b92022-02-11 23:41:1818#include "base/strings/strcat.h"
[email protected]78eac2a2012-03-14 19:09:2719#include "base/sys_byteorder.h"
Patrick Monette643cdf62021-10-15 19:13:4220#include "base/task/single_thread_task_runner.h"
gabf767595f2016-05-11 18:50:3521#include "base/threading/thread_task_runner_handle.h"
Eric Orth3b26e3ba2020-11-12 22:43:1322#include "base/time/time.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2823#include "net/base/address_list.h"
[email protected]78eac2a2012-03-14 19:09:2724#include "net/base/io_buffer.h"
Eric Orth828bd3ae2018-12-12 17:30:3625#include "net/base/ip_address.h"
Eric Orth48b1b7c2022-01-21 00:21:1626#include "net/base/ip_endpoint.h"
[email protected]78eac2a2012-03-14 19:09:2727#include "net/base/net_errors.h"
[email protected]0adcb2b2012-08-15 21:30:4628#include "net/dns/address_sorter.h"
Eric Orth394db1732019-08-27 20:09:3929#include "net/dns/dns_hosts.h"
[email protected]78eac2a2012-03-14 19:09:2730#include "net/dns/dns_query.h"
Eric Orthaf82b49a2020-02-01 01:48:5031#include "net/dns/dns_session.h"
Eric Orth9300cc62020-08-21 00:29:3432#include "net/dns/dns_socket_allocator.h"
tfarina77021d62015-10-11 20:19:0333#include "net/dns/dns_util.h"
Benjamin M. Schwartz571353c22021-12-13 16:41:1134#include "net/dns/public/dns_over_https_server_config.h"
Eric Orth069a3c6e2020-01-31 23:14:2435#include "net/dns/resolve_context.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2836#include "testing/gmock/include/gmock/gmock-matchers.h"
[email protected]78eac2a2012-03-14 19:09:2737#include "testing/gtest/include/gtest/gtest.h"
Benjamin M. Schwartz6f719eb2021-12-15 17:47:2838#include "url/scheme_host_port.h"
[email protected]78eac2a2012-03-14 19:09:2739
40namespace net {
41namespace {
42
Eric Orth828bd3ae2018-12-12 17:30:3643const uint8_t kMalformedResponseHeader[] = {
44 // Header
45 0x00, 0x14, // Arbitrary ID
46 0x81, 0x80, // Standard query response, RA, no error
47 0x00, 0x01, // 1 question
48 0x00, 0x01, // 1 RR (answers)
49 0x00, 0x00, // 0 authority RRs
50 0x00, 0x00, // 0 additional RRs
51};
52
53// Create a response containing a valid question (as would normally be validated
54// in DnsTransaction) but completely missing a header-declared answer.
Eric Ortha97f0f72020-10-16 16:10:3255DnsResponse CreateMalformedResponse(std::string hostname, uint16_t type) {
Eric Orth828bd3ae2018-12-12 17:30:3656 std::string dns_name;
57 CHECK(DNSDomainFromDot(hostname, &dns_name));
58 DnsQuery query(0x14 /* id */, dns_name, type);
59
60 // Build response to simulate the barebones validation DnsResponse applies to
61 // responses received from the network.
62 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
63 sizeof(kMalformedResponseHeader) + query.question().size());
64 memcpy(buffer->data(), kMalformedResponseHeader,
65 sizeof(kMalformedResponseHeader));
66 memcpy(buffer->data() + sizeof(kMalformedResponseHeader),
67 query.question().data(), query.question().size());
68
Eric Ortha97f0f72020-10-16 16:10:3269 DnsResponse response(buffer, buffer->size());
70 CHECK(response.InitParseWithoutQuery(buffer->size()));
Eric Orth828bd3ae2018-12-12 17:30:3671
72 return response;
73}
74
[email protected]daae1322013-09-05 18:26:5075class MockAddressSorter : public AddressSorter {
76 public:
Chris Watkins68b15032017-12-01 03:07:1377 ~MockAddressSorter() override = default;
Eric Orth48b1b7c2022-01-21 00:21:1678 void Sort(const std::vector<IPEndPoint>& endpoints,
79 CallbackType callback) const override {
[email protected]daae1322013-09-05 18:26:5080 // Do nothing.
Eric Orth48b1b7c2022-01-21 00:21:1681 std::move(callback).Run(true, endpoints);
[email protected]daae1322013-09-05 18:26:5082 }
83};
84
[email protected]daae1322013-09-05 18:26:5085} // namespace
[email protected]78eac2a2012-03-14 19:09:2786
Eric Orth8539e492020-10-19 20:09:5587DnsResourceRecord BuildTestDnsRecord(std::string name,
88 uint16_t type,
89 std::string rdata,
90 base::TimeDelta ttl) {
David Van Cleve34c74c72019-10-31 19:58:0191 DCHECK(!name.empty());
David Van Cleve34c74c72019-10-31 19:58:0192
93 DnsResourceRecord record;
94 record.name = std::move(name);
Eric Orth8539e492020-10-19 20:09:5595 record.type = type;
David Van Cleve34c74c72019-10-31 19:58:0196 record.klass = dns_protocol::kClassIN;
Eric Orth8539e492020-10-19 20:09:5597 record.ttl = ttl.InSeconds();
Eric Orth5d21f152020-10-21 19:15:4398
99 if (!rdata.empty())
100 record.SetOwnedRdata(std::move(rdata));
David Van Cleve34c74c72019-10-31 19:58:01101
102 return record;
103}
104
Eric Orth65fd3e32020-11-18 04:59:17105DnsResourceRecord BuildTestCnameRecord(std::string name,
106 base::StringPiece canonical_name,
107 base::TimeDelta ttl) {
108 DCHECK(!name.empty());
109 DCHECK(!canonical_name.empty());
110
111 std::string rdata;
112 CHECK(DNSDomainFromDot(canonical_name, &rdata));
113
114 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeCNAME,
115 std::move(rdata), ttl);
116}
117
Eric Orth8539e492020-10-19 20:09:55118DnsResourceRecord BuildTestAddressRecord(std::string name,
119 const IPAddress& ip,
120 base::TimeDelta ttl) {
121 DCHECK(!name.empty());
Eric Orth828bd3ae2018-12-12 17:30:36122 DCHECK(ip.IsValid());
123
Eric Orth8539e492020-10-19 20:09:55124 return BuildTestDnsRecord(
125 std::move(name),
126 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA,
127 net::IPAddressToPackedString(ip), ttl);
128}
129
Eric Orth3b26e3ba2020-11-12 22:43:13130DnsResourceRecord BuildTestTextRecord(std::string name,
131 std::vector<std::string> text_strings,
132 base::TimeDelta ttl) {
133 DCHECK(!text_strings.empty());
134
135 std::string rdata;
136 for (const std::string& text_string : text_strings) {
137 DCHECK(!text_string.empty());
138
139 rdata += base::checked_cast<unsigned char>(text_string.size());
140 rdata += text_string;
141 }
142
143 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeTXT,
Eric Orthd16fee6b2020-11-18 06:43:14144 std::move(rdata), ttl);
Eric Orth3b26e3ba2020-11-12 22:43:13145}
146
Eric Orth7139e0552020-11-04 02:41:11147DnsResourceRecord BuildTestHttpsAliasRecord(std::string name,
148 base::StringPiece alias_name,
149 base::TimeDelta ttl) {
150 DCHECK(!name.empty());
151
152 std::string rdata("\000\000", 2);
153
154 std::string alias_domain;
155 CHECK(DNSDomainFromDot(alias_name, &alias_domain));
156 rdata.append(alias_domain);
157
158 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
159 std::move(rdata), ttl);
160}
161
Eric Orth17a07d42022-03-08 22:12:16162std::pair<uint16_t, std::string> BuildTestHttpsServiceAlpnParam(
163 const std::vector<std::string>& alpns) {
164 std::string param_value;
165
166 for (const std::string& alpn : alpns) {
167 CHECK(!alpn.empty());
168 param_value.append(
169 1, static_cast<char>(base::checked_cast<uint8_t>(alpn.size())));
170 param_value.append(alpn);
171 }
172
173 return std::make_pair(dns_protocol::kHttpsServiceParamKeyAlpn,
174 std::move(param_value));
175}
176
177std::pair<uint16_t, std::string> BuildTestHttpsServiceEchConfigParam(
178 base::span<const uint8_t> ech_config_list) {
179 return std::make_pair(
180 dns_protocol::kHttpsServiceParamKeyEchConfig,
181 std::string(reinterpret_cast<const char*>(ech_config_list.data()),
182 ech_config_list.size()));
183}
184
Eric Orth4a2621c2022-02-23 00:45:31185std::pair<uint16_t, std::string> BuildTestHttpsServiceMandatoryParam(
186 std::vector<uint16_t> param_key_list) {
187 base::ranges::sort(param_key_list);
188
189 std::string value;
190 for (uint16_t param_key : param_key_list) {
191 char num_buffer[2];
192 base::WriteBigEndian(num_buffer, param_key);
193 value.append(num_buffer, 2);
194 }
195
196 return std::make_pair(dns_protocol::kHttpsServiceParamKeyMandatory,
197 std::move(value));
198}
199
Eric Orth17a07d42022-03-08 22:12:16200std::pair<uint16_t, std::string> BuildTestHttpsServicePortParam(uint16_t port) {
201 char buffer[2];
202 base::WriteBigEndian(buffer, port);
203
204 return std::make_pair(dns_protocol::kHttpsServiceParamKeyPort,
205 std::string(buffer, 2));
206}
207
Eric Orth7139e0552020-11-04 02:41:11208DnsResourceRecord BuildTestHttpsServiceRecord(
209 std::string name,
210 uint16_t priority,
211 base::StringPiece service_name,
212 const std::map<uint16_t, std::string>& params,
213 base::TimeDelta ttl) {
214 DCHECK(!name.empty());
215 DCHECK_NE(priority, 0);
216
217 std::string rdata;
218
219 char num_buffer[2];
220 base::WriteBigEndian(num_buffer, priority);
221 rdata.append(num_buffer, 2);
222
223 std::string service_domain;
Eric Orthac9aafb2021-07-29 23:03:43224 if (service_name == ".") {
225 // HTTPS records have special behavior for `service_name == "."` (that it
226 // will be treated as if the service name is the same as the record owner
227 // name), so allow such inputs despite normally being disallowed for
228 // Chrome-encoded DNS names.
229 service_domain = '\x00';
230 } else {
231 CHECK(DNSDomainFromDot(service_name, &service_domain));
232 }
Eric Orth7139e0552020-11-04 02:41:11233 rdata.append(service_domain);
234
235 for (auto& param : params) {
236 base::WriteBigEndian(num_buffer, param.first);
237 rdata.append(num_buffer, 2);
238
239 base::WriteBigEndian(num_buffer,
240 base::checked_cast<uint16_t>(param.second.size()));
241 rdata.append(num_buffer, 2);
242
243 rdata.append(param.second);
244 }
245
246 return BuildTestDnsRecord(std::move(name), dns_protocol::kTypeHttps,
247 std::move(rdata), ttl);
248}
249
Eric Orth8539e492020-10-19 20:09:55250DnsResponse BuildTestDnsResponse(
251 std::string name,
252 uint16_t type,
Eric Orth69c25992020-11-10 16:55:12253 const std::vector<DnsResourceRecord>& answers,
254 const std::vector<DnsResourceRecord>& authority,
Eric Orth9cec76f2020-11-17 07:42:42255 const std::vector<DnsResourceRecord>& additional,
256 uint8_t rcode) {
Eric Orth8539e492020-10-19 20:09:55257 DCHECK(!name.empty());
258
Eric Orth828bd3ae2018-12-12 17:30:36259 std::string dns_name;
260 CHECK(DNSDomainFromDot(name, &dns_name));
Eric Orth8539e492020-10-19 20:09:55261
Anton Bikineev068d2912021-05-15 20:43:52262 absl::optional<DnsQuery> query(absl::in_place, 0, std::move(dns_name), type);
Eric Orth8539e492020-10-19 20:09:55263 return DnsResponse(0, true /* is_authoritative */, answers,
Eric Orth69c25992020-11-10 16:55:12264 authority /* authority_records */,
Eric Orth9cec76f2020-11-17 07:42:42265 additional /* additional_records */, query, rcode,
Eric Orthd16fee6b2020-11-18 06:43:14266 false /* validate_records */);
Eric Orth828bd3ae2018-12-12 17:30:36267}
268
Eric Orth8539e492020-10-19 20:09:55269DnsResponse BuildTestDnsAddressResponse(std::string name,
270 const IPAddress& ip,
271 std::string answer_name) {
272 DCHECK(ip.IsValid());
273
274 if (answer_name.empty())
275 answer_name = name;
276
277 std::vector<DnsResourceRecord> answers = {
278 BuildTestAddressRecord(std::move(answer_name), ip)};
279
280 return BuildTestDnsResponse(
281 std::move(name),
282 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
283}
284
Eric Ortha97f0f72020-10-16 16:10:32285DnsResponse BuildTestDnsAddressResponseWithCname(std::string name,
286 const IPAddress& ip,
Eric Orth8539e492020-10-19 20:09:55287 std::string cannonname,
288 std::string answer_name) {
Eric Orth828bd3ae2018-12-12 17:30:36289 DCHECK(ip.IsValid());
290 DCHECK(!cannonname.empty());
291
Eric Orth8539e492020-10-19 20:09:55292 if (answer_name.empty())
293 answer_name = name;
294
295 std::string cname_rdata;
296 CHECK(DNSDomainFromDot(cannonname, &cname_rdata));
297
Eric Orth828bd3ae2018-12-12 17:30:36298 std::vector<DnsResourceRecord> answers = {
Eric Orth8539e492020-10-19 20:09:55299 BuildTestDnsRecord(std::move(answer_name), dns_protocol::kTypeCNAME,
300 std::move(cname_rdata)),
301 BuildTestAddressRecord(std::move(cannonname), ip)};
302
303 return BuildTestDnsResponse(
304 std::move(name),
305 ip.IsIPv4() ? dns_protocol::kTypeA : dns_protocol::kTypeAAAA, answers);
Eric Orth828bd3ae2018-12-12 17:30:36306}
307
Eric Ortha97f0f72020-10-16 16:10:32308DnsResponse BuildTestDnsTextResponse(
Eric Orth828bd3ae2018-12-12 17:30:36309 std::string name,
310 std::vector<std::vector<std::string>> text_records,
311 std::string answer_name) {
312 if (answer_name.empty())
313 answer_name = name;
314
315 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45316 for (std::vector<std::string>& text_record : text_records) {
Eric Orth3b26e3ba2020-11-12 22:43:13317 answers.push_back(BuildTestTextRecord(answer_name, std::move(text_record)));
Eric Orth828bd3ae2018-12-12 17:30:36318 }
319
Eric Orth8539e492020-10-19 20:09:55320 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeTXT, answers);
Eric Orth828bd3ae2018-12-12 17:30:36321}
322
Eric Ortha97f0f72020-10-16 16:10:32323DnsResponse BuildTestDnsPointerResponse(std::string name,
324 std::vector<std::string> pointer_names,
325 std::string answer_name) {
Eric Orthe9db8d232019-01-14 21:24:45326 if (answer_name.empty())
327 answer_name = name;
328
329 std::vector<DnsResourceRecord> answers;
Eric Ortha625b042019-01-16 01:14:45330 for (std::string& pointer_name : pointer_names) {
Eric Orth8539e492020-10-19 20:09:55331 std::string rdata;
332 CHECK(DNSDomainFromDot(pointer_name, &rdata));
333
334 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypePTR,
335 std::move(rdata)));
Eric Orthe9db8d232019-01-14 21:24:45336 }
337
Eric Orth8539e492020-10-19 20:09:55338 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypePTR, answers);
Eric Orthe9db8d232019-01-14 21:24:45339}
340
Eric Ortha97f0f72020-10-16 16:10:32341DnsResponse BuildTestDnsServiceResponse(
Eric Ortha625b042019-01-16 01:14:45342 std::string name,
343 std::vector<TestServiceRecord> service_records,
344 std::string answer_name) {
345 if (answer_name.empty())
346 answer_name = name;
347
348 std::vector<DnsResourceRecord> answers;
349 for (TestServiceRecord& service_record : service_records) {
Eric Orth8539e492020-10-19 20:09:55350 std::string rdata;
351 char num_buffer[2];
352 base::WriteBigEndian(num_buffer, service_record.priority);
353 rdata.append(num_buffer, 2);
354 base::WriteBigEndian(num_buffer, service_record.weight);
355 rdata.append(num_buffer, 2);
356 base::WriteBigEndian(num_buffer, service_record.port);
357 rdata.append(num_buffer, 2);
358 std::string dns_name;
359 CHECK(DNSDomainFromDot(service_record.target, &dns_name));
360 rdata += dns_name;
361
362 answers.push_back(BuildTestDnsRecord(answer_name, dns_protocol::kTypeSRV,
Peter Kastinge5a38ed2021-10-02 03:06:35363 std::move(rdata), base::Hours(5)));
Eric Ortha625b042019-01-16 01:14:45364 }
365
Eric Orth8539e492020-10-19 20:09:55366 return BuildTestDnsResponse(std::move(name), dns_protocol::kTypeSRV, answers);
Daniel McArdle2daa3ec2020-06-03 16:05:48367}
368
Eric Orth89726dd2020-10-13 20:19:53369MockDnsClientRule::Result::Result(ResultType type,
Eric Orthac9aafb2021-07-29 23:03:43370 absl::optional<DnsResponse> response,
371 absl::optional<int> net_error)
372 : type(type), response(std::move(response)), net_error(net_error) {}
Eric Orth828bd3ae2018-12-12 17:30:36373
Eric Ortha97f0f72020-10-16 16:10:32374MockDnsClientRule::Result::Result(DnsResponse response)
Peter Kastingd039b772021-08-18 00:06:20375 : type(ResultType::kOk),
376 response(std::move(response)),
377 net_error(absl::nullopt) {}
Eric Orth828bd3ae2018-12-12 17:30:36378
Peter Kastingd039b772021-08-18 00:06:20379MockDnsClientRule::Result::Result(Result&&) = default;
380
381MockDnsClientRule::Result& MockDnsClientRule::Result::operator=(Result&&) =
382 default;
Eric Orth828bd3ae2018-12-12 17:30:36383
384MockDnsClientRule::Result::~Result() = default;
385
Eric Orth502d5682019-04-12 00:21:33386MockDnsClientRule::MockDnsClientRule(const std::string& prefix,
387 uint16_t qtype,
dalyk4f4ac712019-05-31 16:33:13388 bool secure,
Eric Orth502d5682019-04-12 00:21:33389 Result result,
390 bool delay,
391 URLRequestContext* context)
392 : result(std::move(result)),
393 prefix(prefix),
394 qtype(qtype),
dalyk4f4ac712019-05-31 16:33:13395 secure(secure),
Eric Orth502d5682019-04-12 00:21:33396 delay(delay),
397 context(context) {}
398
399MockDnsClientRule::MockDnsClientRule(MockDnsClientRule&& rule) = default;
400
Eric Orth3421db382019-10-20 02:35:52401// A DnsTransaction which uses MockDnsClientRuleList to determine the response.
402class MockDnsTransactionFactory::MockTransaction
403 : public DnsTransaction,
404 public base::SupportsWeakPtr<MockTransaction> {
[email protected]78eac2a2012-03-14 19:09:27405 public:
Eric Orth3421db382019-10-20 02:35:52406 MockTransaction(const MockDnsClientRuleList& rules,
Eric Orthc4cca5d2021-07-02 19:59:01407 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52408 uint16_t qtype,
409 bool secure,
Eric Orth7dc18e92020-02-13 20:27:56410 bool force_doh_server_available,
Eric Ortha093b092020-09-24 23:13:02411 SecureDnsMode secure_dns_mode,
Eric Orth7dc18e92020-02-13 20:27:56412 ResolveContext* resolve_context,
Eric Orth7a85ca52022-03-25 11:04:04413 bool fast_timeout)
Peter Kastingd039b772021-08-18 00:06:20414 : result_(MockDnsClientRule::ResultType::kFail),
Eric Orthc4cca5d2021-07-02 19:59:01415 hostname_(std::move(hostname)),
Eric Orth7a85ca52022-03-25 11:04:04416 qtype_(qtype) {
Eric Orth7dc18e92020-02-13 20:27:56417 // Do not allow matching any rules if transaction is secure and no DoH
418 // servers are available.
419 if (!secure || force_doh_server_available ||
420 resolve_context->NumAvailableDohServers(
421 resolve_context->current_session_for_testing()) > 0) {
422 // Find the relevant rule which matches |qtype|, |secure|, prefix of
Eric Orthc4cca5d2021-07-02 19:59:01423 // |hostname_|, and |url_request_context| (iff the rule context is not
Eric Orth7dc18e92020-02-13 20:27:56424 // null).
425 for (size_t i = 0; i < rules.size(); ++i) {
426 const std::string& prefix = rules[i].prefix;
427 if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
Eric Orthc4cca5d2021-07-02 19:59:01428 (hostname_.size() >= prefix.size()) &&
429 (hostname_.compare(0, prefix.size(), prefix) == 0) &&
Eric Orth7dc18e92020-02-13 20:27:56430 (!rules[i].context ||
431 rules[i].context == resolve_context->url_request_context())) {
432 const MockDnsClientRule::Result* result = &rules[i].result;
433 result_ = MockDnsClientRule::Result(result->type);
Eric Orthac9aafb2021-07-29 23:03:43434 result_.net_error = result->net_error;
Eric Orth7dc18e92020-02-13 20:27:56435 delayed_ = rules[i].delay;
[email protected]daae1322013-09-05 18:26:50436
Eric Orth7dc18e92020-02-13 20:27:56437 // Generate a DnsResponse when not provided with the rule.
438 std::vector<DnsResourceRecord> authority_records;
439 std::string dns_name;
440 CHECK(DNSDomainFromDot(hostname_, &dns_name));
Anton Bikineev068d2912021-05-15 20:43:52441 absl::optional<DnsQuery> query(absl::in_place, 22 /* id */, dns_name,
Eric Orth7dc18e92020-02-13 20:27:56442 qtype_);
443 switch (result->type) {
Peter Kastingd039b772021-08-18 00:06:20444 case MockDnsClientRule::ResultType::kNoDomain:
445 case MockDnsClientRule::ResultType::kEmpty:
Eric Orth7dc18e92020-02-13 20:27:56446 DCHECK(!result->response); // Not expected to be provided.
Eric Orth8539e492020-10-19 20:09:55447 authority_records = {BuildTestDnsRecord(
448 hostname_, dns_protocol::kTypeSOA, "fake rdata")};
Eric Ortha97f0f72020-10-16 16:10:32449 result_.response = DnsResponse(
Eric Orth7dc18e92020-02-13 20:27:56450 22 /* id */, false /* is_authoritative */,
451 std::vector<DnsResourceRecord>() /* answers */,
452 authority_records,
453 std::vector<DnsResourceRecord>() /* additional_records */,
454 query,
Peter Kastingd039b772021-08-18 00:06:20455 result->type == MockDnsClientRule::ResultType::kNoDomain
Eric Orth7dc18e92020-02-13 20:27:56456 ? dns_protocol::kRcodeNXDOMAIN
457 : 0);
458 break;
Peter Kastingd039b772021-08-18 00:06:20459 case MockDnsClientRule::ResultType::kFail:
Eric Orthac9aafb2021-07-29 23:03:43460 if (result->response)
461 SetResponse(result);
462 break;
Peter Kastingd039b772021-08-18 00:06:20463 case MockDnsClientRule::ResultType::kTimeout:
Eric Orth7dc18e92020-02-13 20:27:56464 DCHECK(!result->response); // Not expected to be provided.
465 break;
Peter Kastingd039b772021-08-18 00:06:20466 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53467 if (!fast_timeout)
468 SetResponse(result);
469 break;
Peter Kastingd039b772021-08-18 00:06:20470 case MockDnsClientRule::ResultType::kOk:
Eric Orth89726dd2020-10-13 20:19:53471 SetResponse(result);
Eric Orth7dc18e92020-02-13 20:27:56472 break;
Peter Kastingd039b772021-08-18 00:06:20473 case MockDnsClientRule::ResultType::kMalformed:
Eric Orth7dc18e92020-02-13 20:27:56474 DCHECK(!result->response); // Not expected to be provided.
475 result_.response = CreateMalformedResponse(hostname_, qtype_);
476 break;
Peter Kastingd039b772021-08-18 00:06:20477 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24478 ADD_FAILURE()
479 << "Unexpected DNS transaction created for hostname "
480 << hostname_;
481 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);
Eric Orth7a85ca52022-03-25 11:04:04546 std::move(callback_).Run(
547 error, base::OptionalOrNullptr(result_.response), absl::nullopt);
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());
Eric Orth7a85ca52022-03-25 11:04:04554 std::move(callback_).Run(OK, base::OptionalOrNullptr(result_.response),
555 absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52556 break;
Peter Kastingd039b772021-08-18 00:06:20557 case MockDnsClientRule::ResultType::kTimeout:
Eric Orthac9aafb2021-07-29 23:03:43558 DCHECK(!result_.net_error.has_value());
Eric Orth7a85ca52022-03-25 11:04:04559 std::move(callback_).Run(ERR_DNS_TIMED_OUT, nullptr, absl::nullopt);
Eric Orth3421db382019-10-20 02:35:52560 break;
Peter Kastingd039b772021-08-18 00:06:20561 case MockDnsClientRule::ResultType::kSlow:
Eric Orth89726dd2020-10-13 20:19:53562 if (result_.response) {
Eric Ortha97f0f72020-10-16 16:10:32563 std::move(callback_).Run(
Eric Orth7a85ca52022-03-25 11:04:04564 result_.net_error.value_or(OK),
Eric Orthac9aafb2021-07-29 23:03:43565 result_.response ? &result_.response.value() : nullptr,
Anton Bikineev068d2912021-05-15 20:43:52566 absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53567 } else {
Eric Orthac9aafb2021-07-29 23:03:43568 DCHECK(!result_.net_error.has_value());
Eric Orth7a85ca52022-03-25 11:04:04569 std::move(callback_).Run(ERR_DNS_TIMED_OUT, nullptr, absl::nullopt);
Eric Orth89726dd2020-10-13 20:19:53570 }
Eric Orthcf8e00f2021-07-24 00:41:24571 break;
Peter Kastingd039b772021-08-18 00:06:20572 case MockDnsClientRule::ResultType::kUnexpected:
Eric Orthcf8e00f2021-07-24 00:41:24573 ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
574 << hostname_;
575 break;
Eric Orth3421db382019-10-20 02:35:52576 }
577 }
578
579 void SetRequestPriority(RequestPriority priority) override {}
580
581 MockDnsClientRule::Result result_;
582 const std::string hostname_;
583 const uint16_t qtype_;
Eric Orth7a85ca52022-03-25 11:04:04584 ResponseCallback callback_;
585 bool started_ = false;
586 bool delayed_ = false;
[email protected]0adcb2b2012-08-15 21:30:46587};
588
Eric Orth41b249e02020-01-03 20:21:47589class MockDnsTransactionFactory::MockDohProbeRunner : public DnsProbeRunner {
590 public:
591 explicit MockDohProbeRunner(base::WeakPtr<MockDnsTransactionFactory> factory)
592 : factory_(std::move(factory)) {}
593
594 ~MockDohProbeRunner() override {
595 if (factory_)
596 factory_->running_doh_probe_runners_.erase(this);
597 }
598
Eric Orth020e5fe2020-03-12 17:43:43599 void Start(bool network_change) override {
Eric Orth41b249e02020-01-03 20:21:47600 DCHECK(factory_);
601 factory_->running_doh_probe_runners_.insert(this);
602 }
603
Eric Orth41b249e02020-01-03 20:21:47604 base::TimeDelta GetDelayUntilNextProbeForTest(
605 size_t doh_server_index) const override {
606 NOTREACHED();
607 return base::TimeDelta();
608 }
609
610 private:
611 base::WeakPtr<MockDnsTransactionFactory> factory_;
612};
613
Eric Orth3421db382019-10-20 02:35:52614MockDnsTransactionFactory::MockDnsTransactionFactory(
615 MockDnsClientRuleList rules)
616 : rules_(std::move(rules)) {}
617
618MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
619
620std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
Eric Orthc4cca5d2021-07-02 19:59:01621 std::string hostname,
Eric Orth3421db382019-10-20 02:35:52622 uint16_t qtype,
Eric Orth3421db382019-10-20 02:35:52623 const NetLogWithSource&,
624 bool secure,
Eric Ortha093b092020-09-24 23:13:02625 SecureDnsMode secure_dns_mode,
Eric Orth89726dd2020-10-13 20:19:53626 ResolveContext* resolve_context,
627 bool fast_timeout) {
Eric Orth3421db382019-10-20 02:35:52628 std::unique_ptr<MockTransaction> transaction =
Eric Orthc4cca5d2021-07-02 19:59:01629 std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
630 secure, force_doh_server_available_,
631 secure_dns_mode, resolve_context,
Eric Orth7a85ca52022-03-25 11:04:04632 fast_timeout);
Eric Orth3421db382019-10-20 02:35:52633 if (transaction->delayed())
634 delayed_transactions_.push_back(transaction->AsWeakPtr());
635 return transaction;
636}
637
Eric Orth41b249e02020-01-03 20:21:47638std::unique_ptr<DnsProbeRunner> MockDnsTransactionFactory::CreateDohProbeRunner(
Eric Orth069a3c6e2020-01-31 23:14:24639 ResolveContext* resolve_context) {
Eric Orth41b249e02020-01-03 20:21:47640 return std::make_unique<MockDohProbeRunner>(weak_ptr_factory_.GetWeakPtr());
641}
642
Eric Orth3421db382019-10-20 02:35:52643void MockDnsTransactionFactory::AddEDNSOption(const OptRecordRdata::Opt& opt) {}
644
Eric Ortha093b092020-09-24 23:13:02645SecureDnsMode MockDnsTransactionFactory::GetSecureDnsModeForTest() {
646 return SecureDnsMode::kAutomatic;
Eric Orth3421db382019-10-20 02:35:52647}
648
649void MockDnsTransactionFactory::CompleteDelayedTransactions() {
650 DelayedTransactionList old_delayed_transactions;
651 old_delayed_transactions.swap(delayed_transactions_);
652 for (auto it = old_delayed_transactions.begin();
653 it != old_delayed_transactions.end(); ++it) {
654 if (it->get())
655 (*it)->FinishDelayedTransaction();
656 }
657}
658
David Van Cleve1fb5e8c2019-11-04 16:45:16659bool MockDnsTransactionFactory::CompleteOneDelayedTransactionOfType(
660 DnsQueryType type) {
661 for (base::WeakPtr<MockTransaction>& t : delayed_transactions_) {
662 if (t && t->GetType() == DnsQueryTypeToQtype(type)) {
663 t->FinishDelayedTransaction();
664 t.reset();
665 return true;
666 }
667 }
668 return false;
669}
670
Eric Orth394db1732019-08-27 20:09:39671MockDnsClient::MockDnsClient(DnsConfig config, MockDnsClientRuleList rules)
672 : config_(std::move(config)),
Eric Orth3421db382019-10-20 02:35:52673 factory_(new MockDnsTransactionFactory(std::move(rules))),
Eric Orth394db1732019-08-27 20:09:39674 address_sorter_(new MockAddressSorter()) {
675 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50676 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39677}
[email protected]78eac2a2012-03-14 19:09:27678
Chris Watkins68b15032017-12-01 03:07:13679MockDnsClient::~MockDnsClient() = default;
[email protected]78eac2a2012-03-14 19:09:27680
Eric Orth394db1732019-08-27 20:09:39681bool MockDnsClient::CanUseSecureDnsTransactions() const {
682 const DnsConfig* config = GetEffectiveConfig();
Benjamin M. Schwartz5f948312022-02-16 15:37:37683 return config && config->IsValid() && !config->doh_config.servers().empty();
[email protected]daae1322013-09-05 18:26:50684}
[email protected]78eac2a2012-03-14 19:09:27685
Eric Orth394db1732019-08-27 20:09:39686bool MockDnsClient::CanUseInsecureDnsTransactions() const {
687 const DnsConfig* config = GetEffectiveConfig();
688 return config && config->IsValid() && insecure_enabled_ &&
689 !config->dns_over_tls_active;
690}
691
Eric Orth09746312021-05-05 15:44:58692bool MockDnsClient::CanQueryAdditionalTypesViaInsecureDns() const {
693 DCHECK(CanUseInsecureDnsTransactions());
694 return additional_types_enabled_;
695}
696
697void MockDnsClient::SetInsecureEnabled(bool enabled,
698 bool additional_types_enabled) {
Eric Orth394db1732019-08-27 20:09:39699 insecure_enabled_ = enabled;
Eric Orth09746312021-05-05 15:44:58700 additional_types_enabled_ = additional_types_enabled;
Eric Orth394db1732019-08-27 20:09:39701}
702
Eric Orth069a3c6e2020-01-31 23:14:24703bool MockDnsClient::FallbackFromSecureTransactionPreferred(
704 ResolveContext* context) const {
Eric Orth7dc18e92020-02-13 20:27:56705 bool doh_server_available =
706 force_doh_server_available_ ||
707 context->NumAvailableDohServers(session_.get()) > 0;
708 return !CanUseSecureDnsTransactions() || !doh_server_available;
dalykc2adf182019-09-02 14:31:22709}
710
Eric Orth394db1732019-08-27 20:09:39711bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const {
712 return !CanUseInsecureDnsTransactions() ||
713 fallback_failures_ >= max_fallback_failures_;
714}
715
Anton Bikineev068d2912021-05-15 20:43:52716bool MockDnsClient::SetSystemConfig(absl::optional<DnsConfig> system_config) {
Eric Orth394db1732019-08-27 20:09:39717 if (ignore_system_config_changes_)
718 return false;
719
Anton Bikineev068d2912021-05-15 20:43:52720 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39721 config_ = std::move(system_config);
722 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50723 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39724 return before != effective_config_;
725}
726
727bool MockDnsClient::SetConfigOverrides(DnsConfigOverrides config_overrides) {
Anton Bikineev068d2912021-05-15 20:43:52728 absl::optional<DnsConfig> before = effective_config_;
Eric Orth394db1732019-08-27 20:09:39729 overrides_ = std::move(config_overrides);
730 effective_config_ = BuildEffectiveConfig();
Eric Orthaf82b49a2020-02-01 01:48:50731 session_ = BuildSession();
Eric Orth394db1732019-08-27 20:09:39732 return before != effective_config_;
733}
734
Eric Orth020e5fe2020-03-12 17:43:43735void MockDnsClient::ReplaceCurrentSession() {
736 // Noop if no current effective config.
737 session_ = BuildSession();
738}
739
Eric Orthaf82b49a2020-02-01 01:48:50740DnsSession* MockDnsClient::GetCurrentSession() {
741 return session_.get();
742}
743
Eric Orth394db1732019-08-27 20:09:39744const DnsConfig* MockDnsClient::GetEffectiveConfig() const {
745 return effective_config_.has_value() ? &effective_config_.value() : nullptr;
746}
747
748const DnsHosts* MockDnsClient::GetHosts() const {
749 const DnsConfig* config = GetEffectiveConfig();
750 if (!config)
751 return nullptr;
752
753 return &config->hosts;
[email protected]daae1322013-09-05 18:26:50754}
[email protected]78eac2a2012-03-14 19:09:27755
[email protected]daae1322013-09-05 18:26:50756DnsTransactionFactory* MockDnsClient::GetTransactionFactory() {
Eric Orth394db1732019-08-27 20:09:39757 return GetEffectiveConfig() ? factory_.get() : nullptr;
[email protected]daae1322013-09-05 18:26:50758}
[email protected]78eac2a2012-03-14 19:09:27759
[email protected]daae1322013-09-05 18:26:50760AddressSorter* MockDnsClient::GetAddressSorter() {
Eric Orth394db1732019-08-27 20:09:39761 return GetEffectiveConfig() ? address_sorter_.get() : nullptr;
762}
763
764void MockDnsClient::IncrementInsecureFallbackFailures() {
765 ++fallback_failures_;
766}
767
768void MockDnsClient::ClearInsecureFallbackFailures() {
769 fallback_failures_ = 0;
770}
771
Anton Bikineev068d2912021-05-15 20:43:52772absl::optional<DnsConfig> MockDnsClient::GetSystemConfigForTesting() const {
Eric Orth394db1732019-08-27 20:09:39773 return config_;
774}
775
776DnsConfigOverrides MockDnsClient::GetConfigOverridesForTesting() const {
777 return overrides_;
[email protected]daae1322013-09-05 18:26:50778}
[email protected]0adcb2b2012-08-15 21:30:46779
Eric Orth3421db382019-10-20 02:35:52780void MockDnsClient::SetTransactionFactoryForTesting(
781 std::unique_ptr<DnsTransactionFactory> factory) {
782 NOTREACHED();
783}
784
Benjamin M. Schwartz6f719eb2021-12-15 17:47:28785absl::optional<AddressList> MockDnsClient::GetPresetAddrs(
786 const url::SchemeHostPort& endpoint) const {
787 EXPECT_THAT(preset_endpoint_, testing::Optional(endpoint));
788 return preset_addrs_;
789}
790
[email protected]daae1322013-09-05 18:26:50791void MockDnsClient::CompleteDelayedTransactions() {
792 factory_->CompleteDelayedTransactions();
[email protected]78eac2a2012-03-14 19:09:27793}
794
David Van Cleve1fb5e8c2019-11-04 16:45:16795bool MockDnsClient::CompleteOneDelayedTransactionOfType(DnsQueryType type) {
796 return factory_->CompleteOneDelayedTransactionOfType(type);
797}
798
Eric Orth7dc18e92020-02-13 20:27:56799void MockDnsClient::SetForceDohServerAvailable(bool available) {
800 force_doh_server_available_ = available;
801 factory_->set_force_doh_server_available(available);
802}
803
Anton Bikineev068d2912021-05-15 20:43:52804absl::optional<DnsConfig> MockDnsClient::BuildEffectiveConfig() {
Eric Orth394db1732019-08-27 20:09:39805 if (overrides_.OverridesEverything())
806 return overrides_.ApplyOverrides(DnsConfig());
807 if (!config_ || !config_.value().IsValid())
Anton Bikineev068d2912021-05-15 20:43:52808 return absl::nullopt;
Eric Orth394db1732019-08-27 20:09:39809
810 return overrides_.ApplyOverrides(config_.value());
811}
812
Eric Orthaf82b49a2020-02-01 01:48:50813scoped_refptr<DnsSession> MockDnsClient::BuildSession() {
814 if (!effective_config_)
815 return nullptr;
816
817 // Session not expected to be used for anything that will actually require
818 // random numbers.
819 auto null_random_callback =
820 base::BindRepeating([](int, int) -> int { IMMEDIATE_CRASH(); });
821
Eric Orth9300cc62020-08-21 00:29:34822 auto socket_allocator = std::make_unique<DnsSocketAllocator>(
Eric Orth990a74a92020-08-20 18:41:26823 &socket_factory_, effective_config_.value().nameservers,
824 nullptr /* net_log */);
825
Eric Orthaf82b49a2020-02-01 01:48:50826 return base::MakeRefCounted<DnsSession>(
Eric Orth9300cc62020-08-21 00:29:34827 effective_config_.value(), std::move(socket_allocator),
828 null_random_callback, nullptr /* net_log */);
Eric Orthaf82b49a2020-02-01 01:48:50829}
830
[email protected]78eac2a2012-03-14 19:09:27831} // namespace net