blob: 2d957e1fb1ed9606334a6611282b04b5cf816abe [file] [log] [blame]
Momoka Yamamotof1accfce2022-10-13 10:00:191// Copyright 2022 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/host_resolver_nat64_task.h"
6
7#include <algorithm>
8#include <utility>
9
10#include "base/bind.h"
11#include "base/check_op.h"
12#include "base/functional/callback.h"
13#include "base/location.h"
14#include "base/memory/raw_ptr.h"
15#include "base/notreached.h"
16#include "base/strings/string_util.h"
Sean Maher52fa5a72022-11-14 15:53:2517#include "base/task/sequenced_task_runner.h"
Momoka Yamamotof1accfce2022-10-13 10:00:1918#include "net/base/address_list.h"
19#include "net/base/ip_endpoint.h"
20#include "net/base/net_errors.h"
21#include "net/dns/host_resolver.h"
22#include "net/dns/host_resolver_manager.h"
23#include "net/dns/public/dns_query_type.h"
24
25namespace net {
26
27HostResolverNat64Task::HostResolverNat64Task(
28 base::StringPiece hostname,
29 NetworkAnonymizationKey network_anonymization_key,
30 NetLogWithSource net_log,
31 ResolveContext* resolve_context,
32 HostCache* host_cache,
33 base::WeakPtr<HostResolverManager> resolver)
34 : hostname_(hostname),
35 network_anonymization_key_(std::move(network_anonymization_key)),
36 net_log_(std::move(net_log)),
37 resolve_context_(resolve_context),
38 host_cache_(host_cache),
39 resolver_(std::move(resolver)) {}
40
41HostResolverNat64Task::~HostResolverNat64Task() {
42 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
43}
44
45void HostResolverNat64Task::Start(base::OnceClosure completion_closure) {
46 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
47 DCHECK(!completion_closure_);
48
49 completion_closure_ = std::move(completion_closure);
50
51 next_state_ = State::kResolve;
52 int rv = DoLoop(OK);
53 if (rv != ERR_IO_PENDING) {
Sean Maher52fa5a72022-11-14 15:53:2554 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Momoka Yamamotof1accfce2022-10-13 10:00:1955 FROM_HERE, std::move(completion_closure_));
56 }
57}
58
59HostCache::Entry HostResolverNat64Task::GetResults() const {
60 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
61 DCHECK(!completion_closure_);
62 return results_;
63}
64
65int HostResolverNat64Task::DoLoop(int result) {
66 DCHECK_NE(next_state_, State::kStateNone);
67 int rv = result;
68 do {
69 State state = next_state_;
70 next_state_ = State::kStateNone;
71 switch (state) {
72 case State::kResolve:
73 DCHECK_EQ(OK, rv);
74 rv = DoResolve();
75 break;
76 case State::kResolveComplete:
77 rv = DoResolveComplete(rv);
78 break;
79 case State::kSynthesizeToIpv6:
80 DCHECK_EQ(OK, rv);
81 rv = DoSynthesizeToIpv6();
82 break;
83 default:
84 NOTREACHED();
85 rv = ERR_FAILED;
86 break;
87 }
88 } while (rv != ERR_IO_PENDING && next_state_ != State::kStateNone);
89 return rv;
90}
91
92int HostResolverNat64Task::DoResolve() {
93 next_state_ = State::kResolveComplete;
94 HostResolver::ResolveHostParameters parameters;
95 parameters.dns_query_type = DnsQueryType::AAAA;
96
97 if (!resolver_) {
98 return ERR_FAILED;
99 }
100
101 request_ipv4onlyarpa_ = resolver_->CreateRequest(
102 HostPortPair("ipv4only.arpa", 80), network_anonymization_key_, net_log_,
103 parameters, resolve_context_, host_cache_);
104
105 return request_ipv4onlyarpa_->Start(base::BindOnce(
106 &HostResolverNat64Task::OnIOComplete, weak_ptr_factory_.GetWeakPtr()));
107}
108
109int HostResolverNat64Task::DoResolveComplete(int result) {
110 // If not under DNS64 and resolving ipv4only.arpa fails, return the original
111 // IPv4 address.
112 if (result != OK || request_ipv4onlyarpa_->GetEndpointResults()->empty()) {
113 IPAddress ipv4_address;
114 bool is_ip = ipv4_address.AssignFromIPLiteral(hostname_);
115 DCHECK(is_ip);
116 std::set<std::string> aliases;
117 results_ =
118 HostCache::Entry(OK, {IPEndPoint(ipv4_address, 0)}, std::move(aliases),
119 HostCache::Entry::SOURCE_UNKNOWN);
120 return OK;
121 }
122
123 next_state_ = State::kSynthesizeToIpv6;
124 return OK;
125}
126
127int HostResolverNat64Task::DoSynthesizeToIpv6() {
128 IPAddress ipv4_address;
129 bool is_ip = ipv4_address.AssignFromIPLiteral(hostname_);
130 DCHECK(is_ip);
131
132 IPAddress ipv4onlyarpa_AAAA_address;
133
134 std::vector<IPEndPoint> converted_addresses;
135
136 for (const auto& endpoints : *request_ipv4onlyarpa_->GetEndpointResults()) {
137 for (const auto& ip_endpoint : endpoints.ip_endpoints) {
138 ipv4onlyarpa_AAAA_address = ip_endpoint.address();
139
140 Dns64PrefixLength pref64_length =
141 ExtractPref64FromIpv4onlyArpaAAAA(ipv4onlyarpa_AAAA_address);
142
143 IPAddress converted_address = ConvertIPv4ToIPv4EmbeddedIPv6(
144 ipv4_address, ipv4onlyarpa_AAAA_address, pref64_length);
145
146 IPEndPoint converted_ip_endpoint(converted_address, 0);
147 if (std::find(converted_addresses.begin(), converted_addresses.end(),
148 converted_ip_endpoint) == converted_addresses.end()) {
149 converted_addresses.push_back(std::move(converted_ip_endpoint));
150 }
151 }
152 }
153
154 std::set<std::string> aliases;
155
156 if (converted_addresses.empty()) {
157 converted_addresses = {IPEndPoint(ipv4_address, 0)};
158 }
159
160 results_ = HostCache::Entry(OK, converted_addresses, std::move(aliases),
161 HostCache::Entry::SOURCE_UNKNOWN);
162 return OK;
163}
164
165void HostResolverNat64Task::OnIOComplete(int result) {
166 result = DoLoop(result);
167 if (result != ERR_IO_PENDING)
168 std::move(completion_closure_).Run();
169}
170
171} // namespace net