1 // Copyright 2023 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/loopback_only.h"
11
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/logging.h"
15 #include "base/task/sequenced_task_runner.h"
16 #include "base/task/task_traits.h"
17 #include "base/task/thread_pool.h"
18 #include "base/threading/scoped_blocking_call.h"
19 #include "build/build_config.h"
20 #include "net/base/network_change_notifier.h"
21 #include "net/base/network_interfaces.h"
22 #include "net/base/sys_addrinfo.h"
23
24 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
25 #include <net/if.h>
26 #if BUILDFLAG(IS_ANDROID)
27 #include "net/android/network_library.h"
28 #else // BUILDFLAG(IS_ANDROID)
29 #include <ifaddrs.h>
30 #endif // BUILDFLAG(IS_ANDROID)
31 #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
32
33 #if BUILDFLAG(IS_LINUX)
34 #include <linux/rtnetlink.h>
35 #include "net/base/address_map_linux.h"
36 #include "net/base/address_tracker_linux.h"
37 #include "net/base/network_interfaces_linux.h"
38 #endif
39
40 namespace net {
41
42 namespace {
43
44 #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)) || BUILDFLAG(IS_FUCHSIA)
HaveOnlyLoopbackAddressesUsingGetifaddrs()45 bool HaveOnlyLoopbackAddressesUsingGetifaddrs() {
46 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
47 base::BlockingType::MAY_BLOCK);
48 struct ifaddrs* interface_addr = nullptr;
49 int rv = getifaddrs(&interface_addr);
50 if (rv != 0) {
51 DVPLOG(1) << "getifaddrs() failed";
52 return false;
53 }
54
55 bool result = true;
56 for (struct ifaddrs* interface = interface_addr; interface != nullptr;
57 interface = interface->ifa_next) {
58 if (!(IFF_UP & interface->ifa_flags)) {
59 continue;
60 }
61 if (IFF_LOOPBACK & interface->ifa_flags) {
62 continue;
63 }
64 const struct sockaddr* addr = interface->ifa_addr;
65 if (!addr) {
66 continue;
67 }
68 if (addr->sa_family == AF_INET6) {
69 // Safe cast since this is AF_INET6.
70 const struct sockaddr_in6* addr_in6 =
71 reinterpret_cast<const struct sockaddr_in6*>(addr);
72 const struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
73 if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) {
74 continue;
75 }
76 }
77 if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET) {
78 continue;
79 }
80
81 result = false;
82 break;
83 }
84 freeifaddrs(interface_addr);
85 return result;
86 }
87 #endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)) ||
88 // BUILDFLAG(IS_FUCHSIA)
89
90 // This implementation will always be posted to a thread pool.
HaveOnlyLoopbackAddressesSlow()91 bool HaveOnlyLoopbackAddressesSlow() {
92 #if BUILDFLAG(IS_WIN)
93 // TODO(wtc): implement with the GetAdaptersAddresses function.
94 NOTIMPLEMENTED();
95 return false;
96 #elif BUILDFLAG(IS_ANDROID)
97 return android::HaveOnlyLoopbackAddresses();
98 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
99 return HaveOnlyLoopbackAddressesUsingGetifaddrs();
100 #endif // defined(various platforms)
101 }
102
103 #if BUILDFLAG(IS_LINUX)
104 // This implementation can run on the main thread as it will not block.
HaveOnlyLoopbackAddressesFast(AddressMapOwnerLinux * address_map_owner)105 bool HaveOnlyLoopbackAddressesFast(AddressMapOwnerLinux* address_map_owner) {
106 // The AddressMapOwnerLinux has already cached all the information necessary
107 // to determine if only loopback addresses exist.
108 AddressMapOwnerLinux::AddressMap address_map =
109 address_map_owner->GetAddressMap();
110 std::unordered_set<int> online_links = address_map_owner->GetOnlineLinks();
111 for (const auto& [address, ifaddrmsg] : address_map) {
112 // If there is an online link that isn't loopback or IPv6 link-local, return
113 // false.
114 // `online_links` shouldn't ever contain a loopback address, but keep the
115 // check as it is clearer and harmless.
116 //
117 // NOTE(2023-05-26): `online_links` only contains links with *both*
118 // IFF_LOWER_UP and IFF_UP, which is stricter than the
119 // HaveOnlyLoopbackAddressesUsingGetifaddrs() check above. LOWER_UP means
120 // the physical link layer is up and IFF_UP means the interface is
121 // administratively up. This new behavior might even be desirable, but if
122 // this causes issues it will need to be reverted.
123 if (online_links.contains(ifaddrmsg.ifa_index) && !address.IsLoopback() &&
124 !(address.IsIPv6() && address.IsLinkLocal())) {
125 return false;
126 }
127 }
128
129 return true;
130 }
131 #endif // BUILDFLAG(IS_LINUX)
132
133 } // namespace
134
RunHaveOnlyLoopbackAddressesJob(base::OnceCallback<void (bool)> finished_cb)135 void RunHaveOnlyLoopbackAddressesJob(
136 base::OnceCallback<void(bool)> finished_cb) {
137 #if BUILDFLAG(IS_LINUX)
138 // On Linux, this check can be fast if it accesses only network information
139 // that's cached by NetworkChangeNotifier, so there's no need to post this
140 // task to a thread pool. If HaveOnlyLoopbackAddressesFast() *is* posted to a
141 // different thread, it can cause a TSAN error when also setting a mock
142 // NetworkChangeNotifier in tests. So it's important to not run off the main
143 // thread if using cached, global information.
144 AddressMapOwnerLinux* address_map_owner =
145 NetworkChangeNotifier::GetAddressMapOwner();
146 if (address_map_owner) {
147 // Post `finished_cb` to avoid the bug-prone sometimes-synchronous behavior,
148 // which is only useful in latency-sensitive situations.
149 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
150 FROM_HERE,
151 base::BindOnce(std::move(finished_cb),
152 HaveOnlyLoopbackAddressesFast(address_map_owner)));
153 return;
154 }
155 #endif // BUILDFLAG(IS_LINUX)
156
157 base::ThreadPool::PostTaskAndReplyWithResult(
158 FROM_HERE,
159 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
160 base::BindOnce(&HaveOnlyLoopbackAddressesSlow), std::move(finished_cb));
161 }
162
163 } // namespace net
164