123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- // Copyright (c) 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/dns/address_info.h"
- #include <memory>
- #include "base/logging.h"
- #include "base/notreached.h"
- #include "base/sys_byteorder.h"
- #include "build/build_config.h"
- #include "net/base/address_list.h"
- #include "net/base/net_errors.h"
- #include "net/base/sys_addrinfo.h"
- #if BUILDFLAG(IS_ANDROID)
- #include "net/android/network_library.h"
- #endif // BUILDFLAG(IS_ANDROID)
- namespace net {
- namespace {
- const addrinfo* Next(const addrinfo* ai) {
- return ai->ai_next;
- }
- } // namespace
- //// iterator
- AddressInfo::const_iterator::const_iterator(const addrinfo* ai) : ai_(ai) {}
- bool AddressInfo::const_iterator::operator!=(
- const AddressInfo::const_iterator& o) const {
- return ai_ != o.ai_;
- }
- AddressInfo::const_iterator& AddressInfo::const_iterator::operator++() {
- ai_ = Next(ai_);
- return *this;
- }
- const addrinfo* AddressInfo::const_iterator::operator->() const {
- return ai_;
- }
- const addrinfo& AddressInfo::const_iterator::operator*() const {
- return *ai_;
- }
- //// constructors
- AddressInfo::AddressInfoAndResult AddressInfo::Get(
- const std::string& host,
- const addrinfo& hints,
- std::unique_ptr<AddrInfoGetter> getter,
- handles::NetworkHandle network) {
- if (getter == nullptr)
- getter = std::make_unique<AddrInfoGetter>();
- int err = OK;
- int os_error = 0;
- std::unique_ptr<addrinfo, FreeAddrInfoFunc> ai =
- getter->getaddrinfo(host, &hints, &os_error, network);
- if (!ai) {
- err = ERR_NAME_NOT_RESOLVED;
- // If the call to getaddrinfo() failed because of a system error, report
- // it separately from ERR_NAME_NOT_RESOLVED.
- #if BUILDFLAG(IS_WIN)
- if (os_error != WSAHOST_NOT_FOUND && os_error != WSANO_DATA)
- err = ERR_NAME_RESOLUTION_FAILED;
- #elif BUILDFLAG(IS_ANDROID)
- // Workaround for Android's getaddrinfo leaving ai==nullptr without an
- // error.
- // http://crbug.com/134142
- err = ERR_NAME_NOT_RESOLVED;
- #elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_FREEBSD)
- if (os_error != EAI_NONAME && os_error != EAI_NODATA)
- err = ERR_NAME_RESOLUTION_FAILED;
- #endif
- return AddressInfoAndResult(absl::optional<AddressInfo>(), err, os_error);
- }
- return AddressInfoAndResult(absl::optional<AddressInfo>(AddressInfo(
- std::move(ai), std::move(getter))),
- OK, 0);
- }
- AddressInfo::AddressInfo(AddressInfo&& other) = default;
- AddressInfo& AddressInfo::operator=(AddressInfo&& other) = default;
- AddressInfo::~AddressInfo() = default;
- //// public methods
- AddressInfo::const_iterator AddressInfo::begin() const {
- return const_iterator(ai_.get());
- }
- AddressInfo::const_iterator AddressInfo::end() const {
- return const_iterator(nullptr);
- }
- absl::optional<std::string> AddressInfo::GetCanonicalName() const {
- return (ai_->ai_canonname != nullptr)
- ? absl::optional<std::string>(std::string(ai_->ai_canonname))
- : absl::optional<std::string>();
- }
- bool AddressInfo::IsAllLocalhostOfOneFamily() const {
- bool saw_v4_localhost = false;
- bool saw_v6_localhost = false;
- const auto* ai = ai_.get();
- for (; ai != nullptr; ai = Next(ai)) {
- switch (ai->ai_family) {
- case AF_INET: {
- const struct sockaddr_in* addr_in =
- reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
- if ((base::NetToHost32(addr_in->sin_addr.s_addr) & 0xff000000) ==
- 0x7f000000)
- saw_v4_localhost = true;
- else
- return false;
- break;
- }
- case AF_INET6: {
- const struct sockaddr_in6* addr_in6 =
- reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr);
- if (IN6_IS_ADDR_LOOPBACK(&addr_in6->sin6_addr))
- saw_v6_localhost = true;
- else
- return false;
- break;
- }
- default:
- NOTREACHED();
- return false;
- }
- }
- return saw_v4_localhost != saw_v6_localhost;
- }
- AddressList AddressInfo::CreateAddressList() const {
- AddressList list;
- auto canonical_name = GetCanonicalName();
- if (canonical_name) {
- std::vector<std::string> aliases({*canonical_name});
- list.SetDnsAliases(std::move(aliases));
- }
- for (auto&& ai : *this) {
- IPEndPoint ipe;
- // NOTE: Ignoring non-INET* families.
- if (ipe.FromSockAddr(ai.ai_addr, ai.ai_addrlen))
- list.push_back(ipe);
- else
- DLOG(WARNING) << "Unknown family found in addrinfo: " << ai.ai_family;
- }
- return list;
- }
- //// private methods
- AddressInfo::AddressInfo(std::unique_ptr<addrinfo, FreeAddrInfoFunc> ai,
- std::unique_ptr<AddrInfoGetter> getter)
- : ai_(std::move(ai)), getter_(std::move(getter)) {}
- //// AddrInfoGetter
- AddrInfoGetter::AddrInfoGetter() = default;
- AddrInfoGetter::~AddrInfoGetter() = default;
- std::unique_ptr<addrinfo, FreeAddrInfoFunc> AddrInfoGetter::getaddrinfo(
- const std::string& host,
- const addrinfo* hints,
- int* out_os_error,
- handles::NetworkHandle network) {
- addrinfo* ai;
- // We wrap freeaddrinfo() in a lambda just in case some operating systems use
- // a different signature for it.
- FreeAddrInfoFunc deleter = [](addrinfo* ai) { ::freeaddrinfo(ai); };
- std::unique_ptr<addrinfo, FreeAddrInfoFunc> rv = {nullptr, deleter};
- if (network != handles::kInvalidNetworkHandle) {
- // Currently, only Android supports lookups for a specific network.
- #if BUILDFLAG(IS_ANDROID)
- *out_os_error = android::GetAddrInfoForNetwork(network, host.c_str(),
- nullptr, hints, &ai);
- #elif BUILDFLAG(IS_WIN)
- *out_os_error = WSAEOPNOTSUPP;
- return rv;
- #else
- errno = ENOSYS;
- *out_os_error = EAI_SYSTEM;
- return rv;
- #endif // BUILDFLAG(IS_ANDROID)
- } else {
- *out_os_error = ::getaddrinfo(host.c_str(), nullptr, hints, &ai);
- }
- if (*out_os_error) {
- #if BUILDFLAG(IS_WIN)
- *out_os_error = WSAGetLastError();
- #endif
- return rv;
- }
- rv.reset(ai);
- return rv;
- }
- } // namespace net
|