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