xref: /aosp_15_r20/external/cronet/net/dns/address_info.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/dns/address_info.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <optional>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/sys_byteorder.h"
13*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/base/address_list.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/sys_addrinfo.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
19*6777b538SAndroid Build Coastguard Worker #include "net/android/network_library.h"
20*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_ANDROID)
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace net {
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace {
25*6777b538SAndroid Build Coastguard Worker 
Next(const addrinfo * ai)26*6777b538SAndroid Build Coastguard Worker const addrinfo* Next(const addrinfo* ai) {
27*6777b538SAndroid Build Coastguard Worker   return ai->ai_next;
28*6777b538SAndroid Build Coastguard Worker }
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker }  // namespace
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker //// iterator
33*6777b538SAndroid Build Coastguard Worker 
const_iterator(const addrinfo * ai)34*6777b538SAndroid Build Coastguard Worker AddressInfo::const_iterator::const_iterator(const addrinfo* ai) : ai_(ai) {}
35*6777b538SAndroid Build Coastguard Worker 
operator !=(const AddressInfo::const_iterator & o) const36*6777b538SAndroid Build Coastguard Worker bool AddressInfo::const_iterator::operator!=(
37*6777b538SAndroid Build Coastguard Worker     const AddressInfo::const_iterator& o) const {
38*6777b538SAndroid Build Coastguard Worker   return ai_ != o.ai_;
39*6777b538SAndroid Build Coastguard Worker }
40*6777b538SAndroid Build Coastguard Worker 
operator ++()41*6777b538SAndroid Build Coastguard Worker AddressInfo::const_iterator& AddressInfo::const_iterator::operator++() {
42*6777b538SAndroid Build Coastguard Worker   ai_ = Next(ai_);
43*6777b538SAndroid Build Coastguard Worker   return *this;
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker 
operator ->() const46*6777b538SAndroid Build Coastguard Worker const addrinfo* AddressInfo::const_iterator::operator->() const {
47*6777b538SAndroid Build Coastguard Worker   return ai_;
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker 
operator *() const50*6777b538SAndroid Build Coastguard Worker const addrinfo& AddressInfo::const_iterator::operator*() const {
51*6777b538SAndroid Build Coastguard Worker   return *ai_;
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker //// constructors
55*6777b538SAndroid Build Coastguard Worker 
Get(const std::string & host,const addrinfo & hints,std::unique_ptr<AddrInfoGetter> getter,handles::NetworkHandle network)56*6777b538SAndroid Build Coastguard Worker AddressInfo::AddressInfoAndResult AddressInfo::Get(
57*6777b538SAndroid Build Coastguard Worker     const std::string& host,
58*6777b538SAndroid Build Coastguard Worker     const addrinfo& hints,
59*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<AddrInfoGetter> getter,
60*6777b538SAndroid Build Coastguard Worker     handles::NetworkHandle network) {
61*6777b538SAndroid Build Coastguard Worker   if (getter == nullptr)
62*6777b538SAndroid Build Coastguard Worker     getter = std::make_unique<AddrInfoGetter>();
63*6777b538SAndroid Build Coastguard Worker   int err = OK;
64*6777b538SAndroid Build Coastguard Worker   int os_error = 0;
65*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<addrinfo, FreeAddrInfoFunc> ai =
66*6777b538SAndroid Build Coastguard Worker       getter->getaddrinfo(host, &hints, &os_error, network);
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   if (!ai) {
69*6777b538SAndroid Build Coastguard Worker     err = ERR_NAME_NOT_RESOLVED;
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker     // If the call to getaddrinfo() failed because of a system error, report
72*6777b538SAndroid Build Coastguard Worker     // it separately from ERR_NAME_NOT_RESOLVED.
73*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
74*6777b538SAndroid Build Coastguard Worker     if (os_error != WSAHOST_NOT_FOUND && os_error != WSANO_DATA)
75*6777b538SAndroid Build Coastguard Worker       err = ERR_NAME_RESOLUTION_FAILED;
76*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID)
77*6777b538SAndroid Build Coastguard Worker     // Workaround for Android's getaddrinfo leaving ai==nullptr without an
78*6777b538SAndroid Build Coastguard Worker     // error.
79*6777b538SAndroid Build Coastguard Worker     // http://crbug.com/134142
80*6777b538SAndroid Build Coastguard Worker     err = ERR_NAME_NOT_RESOLVED;
81*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_FREEBSD)
82*6777b538SAndroid Build Coastguard Worker     if (os_error != EAI_NONAME && os_error != EAI_NODATA)
83*6777b538SAndroid Build Coastguard Worker       err = ERR_NAME_RESOLUTION_FAILED;
84*6777b538SAndroid Build Coastguard Worker #endif
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker     return AddressInfoAndResult(std::optional<AddressInfo>(), err, os_error);
87*6777b538SAndroid Build Coastguard Worker   }
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   return AddressInfoAndResult(
90*6777b538SAndroid Build Coastguard Worker       std::optional<AddressInfo>(AddressInfo(std::move(ai), std::move(getter))),
91*6777b538SAndroid Build Coastguard Worker       OK, 0);
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker AddressInfo::AddressInfo(AddressInfo&& other) = default;
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker AddressInfo& AddressInfo::operator=(AddressInfo&& other) = default;
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker AddressInfo::~AddressInfo() = default;
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker //// public methods
101*6777b538SAndroid Build Coastguard Worker 
begin() const102*6777b538SAndroid Build Coastguard Worker AddressInfo::const_iterator AddressInfo::begin() const {
103*6777b538SAndroid Build Coastguard Worker   return const_iterator(ai_.get());
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker 
end() const106*6777b538SAndroid Build Coastguard Worker AddressInfo::const_iterator AddressInfo::end() const {
107*6777b538SAndroid Build Coastguard Worker   return const_iterator(nullptr);
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker 
GetCanonicalName() const110*6777b538SAndroid Build Coastguard Worker std::optional<std::string> AddressInfo::GetCanonicalName() const {
111*6777b538SAndroid Build Coastguard Worker   return (ai_->ai_canonname != nullptr)
112*6777b538SAndroid Build Coastguard Worker              ? std::optional<std::string>(std::string(ai_->ai_canonname))
113*6777b538SAndroid Build Coastguard Worker              : std::optional<std::string>();
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker 
IsAllLocalhostOfOneFamily() const116*6777b538SAndroid Build Coastguard Worker bool AddressInfo::IsAllLocalhostOfOneFamily() const {
117*6777b538SAndroid Build Coastguard Worker   bool saw_v4_localhost = false;
118*6777b538SAndroid Build Coastguard Worker   bool saw_v6_localhost = false;
119*6777b538SAndroid Build Coastguard Worker   const auto* ai = ai_.get();
120*6777b538SAndroid Build Coastguard Worker   for (; ai != nullptr; ai = Next(ai)) {
121*6777b538SAndroid Build Coastguard Worker     switch (ai->ai_family) {
122*6777b538SAndroid Build Coastguard Worker       case AF_INET: {
123*6777b538SAndroid Build Coastguard Worker         const struct sockaddr_in* addr_in =
124*6777b538SAndroid Build Coastguard Worker             reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
125*6777b538SAndroid Build Coastguard Worker         if ((base::NetToHost32(addr_in->sin_addr.s_addr) & 0xff000000) ==
126*6777b538SAndroid Build Coastguard Worker             0x7f000000)
127*6777b538SAndroid Build Coastguard Worker           saw_v4_localhost = true;
128*6777b538SAndroid Build Coastguard Worker         else
129*6777b538SAndroid Build Coastguard Worker           return false;
130*6777b538SAndroid Build Coastguard Worker         break;
131*6777b538SAndroid Build Coastguard Worker       }
132*6777b538SAndroid Build Coastguard Worker       case AF_INET6: {
133*6777b538SAndroid Build Coastguard Worker         const struct sockaddr_in6* addr_in6 =
134*6777b538SAndroid Build Coastguard Worker             reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr);
135*6777b538SAndroid Build Coastguard Worker         if (IN6_IS_ADDR_LOOPBACK(&addr_in6->sin6_addr))
136*6777b538SAndroid Build Coastguard Worker           saw_v6_localhost = true;
137*6777b538SAndroid Build Coastguard Worker         else
138*6777b538SAndroid Build Coastguard Worker           return false;
139*6777b538SAndroid Build Coastguard Worker         break;
140*6777b538SAndroid Build Coastguard Worker       }
141*6777b538SAndroid Build Coastguard Worker       default:
142*6777b538SAndroid Build Coastguard Worker         return false;
143*6777b538SAndroid Build Coastguard Worker     }
144*6777b538SAndroid Build Coastguard Worker   }
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   return saw_v4_localhost != saw_v6_localhost;
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker 
CreateAddressList() const149*6777b538SAndroid Build Coastguard Worker AddressList AddressInfo::CreateAddressList() const {
150*6777b538SAndroid Build Coastguard Worker   AddressList list;
151*6777b538SAndroid Build Coastguard Worker   auto canonical_name = GetCanonicalName();
152*6777b538SAndroid Build Coastguard Worker   if (canonical_name) {
153*6777b538SAndroid Build Coastguard Worker     std::vector<std::string> aliases({*canonical_name});
154*6777b538SAndroid Build Coastguard Worker     list.SetDnsAliases(std::move(aliases));
155*6777b538SAndroid Build Coastguard Worker   }
156*6777b538SAndroid Build Coastguard Worker   for (auto&& ai : *this) {
157*6777b538SAndroid Build Coastguard Worker     IPEndPoint ipe;
158*6777b538SAndroid Build Coastguard Worker     // NOTE: Ignoring non-INET* families.
159*6777b538SAndroid Build Coastguard Worker     if (ipe.FromSockAddr(ai.ai_addr, ai.ai_addrlen))
160*6777b538SAndroid Build Coastguard Worker       list.push_back(ipe);
161*6777b538SAndroid Build Coastguard Worker     else
162*6777b538SAndroid Build Coastguard Worker       DLOG(WARNING) << "Unknown family found in addrinfo: " << ai.ai_family;
163*6777b538SAndroid Build Coastguard Worker   }
164*6777b538SAndroid Build Coastguard Worker   return list;
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker //// private methods
168*6777b538SAndroid Build Coastguard Worker 
AddressInfo(std::unique_ptr<addrinfo,FreeAddrInfoFunc> ai,std::unique_ptr<AddrInfoGetter> getter)169*6777b538SAndroid Build Coastguard Worker AddressInfo::AddressInfo(std::unique_ptr<addrinfo, FreeAddrInfoFunc> ai,
170*6777b538SAndroid Build Coastguard Worker                          std::unique_ptr<AddrInfoGetter> getter)
171*6777b538SAndroid Build Coastguard Worker     : ai_(std::move(ai)), getter_(std::move(getter)) {}
172*6777b538SAndroid Build Coastguard Worker 
173*6777b538SAndroid Build Coastguard Worker //// AddrInfoGetter
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker AddrInfoGetter::AddrInfoGetter() = default;
176*6777b538SAndroid Build Coastguard Worker AddrInfoGetter::~AddrInfoGetter() = default;
177*6777b538SAndroid Build Coastguard Worker 
getaddrinfo(const std::string & host,const addrinfo * hints,int * out_os_error,handles::NetworkHandle network)178*6777b538SAndroid Build Coastguard Worker std::unique_ptr<addrinfo, FreeAddrInfoFunc> AddrInfoGetter::getaddrinfo(
179*6777b538SAndroid Build Coastguard Worker     const std::string& host,
180*6777b538SAndroid Build Coastguard Worker     const addrinfo* hints,
181*6777b538SAndroid Build Coastguard Worker     int* out_os_error,
182*6777b538SAndroid Build Coastguard Worker     handles::NetworkHandle network) {
183*6777b538SAndroid Build Coastguard Worker   addrinfo* ai;
184*6777b538SAndroid Build Coastguard Worker   // We wrap freeaddrinfo() in a lambda just in case some operating systems use
185*6777b538SAndroid Build Coastguard Worker   // a different signature for it.
186*6777b538SAndroid Build Coastguard Worker   FreeAddrInfoFunc deleter = [](addrinfo* ai) { ::freeaddrinfo(ai); };
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<addrinfo, FreeAddrInfoFunc> rv = {nullptr, deleter};
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker   if (network != handles::kInvalidNetworkHandle) {
191*6777b538SAndroid Build Coastguard Worker     // Currently, only Android supports lookups for a specific network.
192*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
193*6777b538SAndroid Build Coastguard Worker     *out_os_error = android::GetAddrInfoForNetwork(network, host.c_str(),
194*6777b538SAndroid Build Coastguard Worker                                                    nullptr, hints, &ai);
195*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_WIN)
196*6777b538SAndroid Build Coastguard Worker     *out_os_error = WSAEOPNOTSUPP;
197*6777b538SAndroid Build Coastguard Worker     return rv;
198*6777b538SAndroid Build Coastguard Worker #else
199*6777b538SAndroid Build Coastguard Worker     errno = ENOSYS;
200*6777b538SAndroid Build Coastguard Worker     *out_os_error = EAI_SYSTEM;
201*6777b538SAndroid Build Coastguard Worker     return rv;
202*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_ANDROID)
203*6777b538SAndroid Build Coastguard Worker   } else {
204*6777b538SAndroid Build Coastguard Worker     *out_os_error = ::getaddrinfo(host.c_str(), nullptr, hints, &ai);
205*6777b538SAndroid Build Coastguard Worker   }
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker   if (*out_os_error) {
208*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
209*6777b538SAndroid Build Coastguard Worker     *out_os_error = WSAGetLastError();
210*6777b538SAndroid Build Coastguard Worker #endif
211*6777b538SAndroid Build Coastguard Worker     return rv;
212*6777b538SAndroid Build Coastguard Worker   }
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker   rv.reset(ai);
215*6777b538SAndroid Build Coastguard Worker   return rv;
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker 
218*6777b538SAndroid Build Coastguard Worker }  // namespace net
219