xref: /aosp_15_r20/external/cronet/net/dns/loopback_only_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2023 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/loopback_only.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <optional>
8*6777b538SAndroid Build Coastguard Worker #include <unordered_set>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/test/bind.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/test/task_environment.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/base/mock_network_change_notifier.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/base/network_change_notifier.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/base/test_completion_callback.h"
16*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX)
19*6777b538SAndroid Build Coastguard Worker #include <linux/if.h>
20*6777b538SAndroid Build Coastguard Worker #include <linux/netlink.h>
21*6777b538SAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker #include "net/base/address_map_linux.h"
24*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_LINUX)
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker namespace net {
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX)
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker namespace {
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker constexpr uint8_t kIpv4LoopbackBytes[] = {127, 0, 0, 1};
33*6777b538SAndroid Build Coastguard Worker constexpr uint8_t kIpv4PrivateAddressBytes[] = {10, 0, 0, 1};
34*6777b538SAndroid Build Coastguard Worker constexpr uint8_t kIpv6LoopbackBytes[] = {0, 0, 0, 0, 0, 0, 0, 0,
35*6777b538SAndroid Build Coastguard Worker                                           0, 0, 0, 0, 0, 0, 0, 1};
36*6777b538SAndroid Build Coastguard Worker constexpr uint8_t kIpv6AddressBytes[] = {0xFE, 0xDC, 0xBA, 0x98, 0, 0, 0, 0,
37*6777b538SAndroid Build Coastguard Worker                                          0,    0,    0,    0,    0, 0, 0, 0};
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker constexpr uint8_t kIpv4LinkLocalBytes[] = {169, 254, 0, 0};
40*6777b538SAndroid Build Coastguard Worker constexpr uint8_t kIpv4InIpv6LinkLocalBytes[] = {
41*6777b538SAndroid Build Coastguard Worker     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 169, 254, 0, 0};
42*6777b538SAndroid Build Coastguard Worker constexpr uint8_t kIpv6LinkLocalBytes[] = {0xFE, 0x80, 0, 0, 0, 0, 0, 0,
43*6777b538SAndroid Build Coastguard Worker                                            0,    0,    0, 0, 0, 0, 0, 0};
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker class StubAddressMapOwnerLinux : public AddressMapOwnerLinux {
46*6777b538SAndroid Build Coastguard Worker  public:
GetAddressMap() const47*6777b538SAndroid Build Coastguard Worker   AddressMap GetAddressMap() const override { return address_map_; }
GetOnlineLinks() const48*6777b538SAndroid Build Coastguard Worker   std::unordered_set<int> GetOnlineLinks() const override {
49*6777b538SAndroid Build Coastguard Worker     return online_links_;
50*6777b538SAndroid Build Coastguard Worker   }
51*6777b538SAndroid Build Coastguard Worker 
address_map()52*6777b538SAndroid Build Coastguard Worker   AddressMap& address_map() { return address_map_; }
online_links()53*6777b538SAndroid Build Coastguard Worker   std::unordered_set<int>& online_links() { return online_links_; }
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker  private:
56*6777b538SAndroid Build Coastguard Worker   AddressMap address_map_;
57*6777b538SAndroid Build Coastguard Worker   std::unordered_set<int> online_links_;
58*6777b538SAndroid Build Coastguard Worker };
59*6777b538SAndroid Build Coastguard Worker 
GetResultOfRunHaveOnlyLoopbackAddressesJob()60*6777b538SAndroid Build Coastguard Worker bool GetResultOfRunHaveOnlyLoopbackAddressesJob() {
61*6777b538SAndroid Build Coastguard Worker   bool result = false;
62*6777b538SAndroid Build Coastguard Worker   net::TestClosure completion;
63*6777b538SAndroid Build Coastguard Worker   {
64*6777b538SAndroid Build Coastguard Worker     base::ScopedDisallowBlocking disallow_blocking;
65*6777b538SAndroid Build Coastguard Worker     RunHaveOnlyLoopbackAddressesJob(
66*6777b538SAndroid Build Coastguard Worker         base::BindLambdaForTesting([&](bool loopback_result) {
67*6777b538SAndroid Build Coastguard Worker           result = loopback_result;
68*6777b538SAndroid Build Coastguard Worker           completion.closure().Run();
69*6777b538SAndroid Build Coastguard Worker         }));
70*6777b538SAndroid Build Coastguard Worker   }
71*6777b538SAndroid Build Coastguard Worker   completion.WaitForResult();
72*6777b538SAndroid Build Coastguard Worker   return result;
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker }  // namespace
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker class LoopbackOnlyTest : public ::testing::Test {
78*6777b538SAndroid Build Coastguard Worker  public:
79*6777b538SAndroid Build Coastguard Worker   static constexpr int kTestInterfaceEth = 1;
80*6777b538SAndroid Build Coastguard Worker   static constexpr int kTestInterfaceLoopback = 2;
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker   static inline const net::IPAddress kIpv4Loopback{kIpv4LoopbackBytes};
83*6777b538SAndroid Build Coastguard Worker   static inline const net::IPAddress kIpv4PrivateAddress{
84*6777b538SAndroid Build Coastguard Worker       kIpv4PrivateAddressBytes};
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker   static inline const net::IPAddress kIpv6Loopback{kIpv6LoopbackBytes};
87*6777b538SAndroid Build Coastguard Worker   static inline const net::IPAddress kIpv6Address{kIpv6AddressBytes};
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   static inline const net::IPAddress kIpv4LinkLocal{kIpv4LinkLocalBytes};
90*6777b538SAndroid Build Coastguard Worker   static inline const net::IPAddress kIpv4InIpv6LinkLocal{
91*6777b538SAndroid Build Coastguard Worker       kIpv4InIpv6LinkLocalBytes};
92*6777b538SAndroid Build Coastguard Worker   static inline const net::IPAddress kIpv6LinkLocal{kIpv6LinkLocalBytes};
93*6777b538SAndroid Build Coastguard Worker 
LoopbackOnlyTest()94*6777b538SAndroid Build Coastguard Worker   LoopbackOnlyTest() {
95*6777b538SAndroid Build Coastguard Worker     mock_notifier_.mock_network_change_notifier()->SetAddressMapOwnerLinux(
96*6777b538SAndroid Build Coastguard Worker         &stub_address_map_owner_);
97*6777b538SAndroid Build Coastguard Worker   }
98*6777b538SAndroid Build Coastguard Worker   ~LoopbackOnlyTest() override = default;
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker  protected:
101*6777b538SAndroid Build Coastguard Worker   base::test::TaskEnvironment task_environment_;
102*6777b538SAndroid Build Coastguard Worker   test::ScopedMockNetworkChangeNotifier mock_notifier_;
103*6777b538SAndroid Build Coastguard Worker   StubAddressMapOwnerLinux stub_address_map_owner_;
104*6777b538SAndroid Build Coastguard Worker };
105*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,HasOnlyLoopbackIpv4)106*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, HasOnlyLoopbackIpv4) {
107*6777b538SAndroid Build Coastguard Worker   // Include only a loopback interface.
108*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
109*6777b538SAndroid Build Coastguard Worker       {kIpv4Loopback, ifaddrmsg{
110*6777b538SAndroid Build Coastguard Worker                           .ifa_family = AF_INET,
111*6777b538SAndroid Build Coastguard Worker                           .ifa_flags = IFA_F_TEMPORARY,
112*6777b538SAndroid Build Coastguard Worker                           .ifa_index = kTestInterfaceLoopback,
113*6777b538SAndroid Build Coastguard Worker                       }}};
114*6777b538SAndroid Build Coastguard Worker   // AddressTrackerLinux does not insert loopback interfaces into
115*6777b538SAndroid Build Coastguard Worker   // `online_links`.
116*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {};
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,HasActiveIPv4Connection)121*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, HasActiveIPv4Connection) {
122*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
123*6777b538SAndroid Build Coastguard Worker       {kIpv4Loopback, ifaddrmsg{.ifa_family = AF_INET,
124*6777b538SAndroid Build Coastguard Worker                                 .ifa_flags = IFA_F_TEMPORARY,
125*6777b538SAndroid Build Coastguard Worker                                 .ifa_index = kTestInterfaceLoopback}},
126*6777b538SAndroid Build Coastguard Worker       {kIpv4PrivateAddress, ifaddrmsg{.ifa_family = AF_INET,
127*6777b538SAndroid Build Coastguard Worker                                       .ifa_flags = IFA_F_TEMPORARY,
128*6777b538SAndroid Build Coastguard Worker                                       .ifa_index = kTestInterfaceEth}}};
129*6777b538SAndroid Build Coastguard Worker   // `online_links` includes kTestInterfaceEth so that kIpv4PrivateAddress is
130*6777b538SAndroid Build Coastguard Worker   // the active IPv4 connection. Also, AddressTrackerLinux does not insert
131*6777b538SAndroid Build Coastguard Worker   // loopback interfaces into `online_links`.
132*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {kTestInterfaceEth};
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,HasInactiveIPv4Connection)137*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, HasInactiveIPv4Connection) {
138*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
139*6777b538SAndroid Build Coastguard Worker       {kIpv4Loopback, ifaddrmsg{.ifa_family = AF_INET,
140*6777b538SAndroid Build Coastguard Worker                                 .ifa_flags = IFA_F_TEMPORARY,
141*6777b538SAndroid Build Coastguard Worker                                 .ifa_index = kTestInterfaceLoopback}},
142*6777b538SAndroid Build Coastguard Worker       {kIpv4PrivateAddress, ifaddrmsg{.ifa_family = AF_INET,
143*6777b538SAndroid Build Coastguard Worker                                       .ifa_flags = IFA_F_TEMPORARY,
144*6777b538SAndroid Build Coastguard Worker                                       .ifa_index = kTestInterfaceEth}}};
145*6777b538SAndroid Build Coastguard Worker   // `online_links` does not include kTestInterfaceEth so that
146*6777b538SAndroid Build Coastguard Worker   // kIpv4PrivateAddress is the inactive IPv4 connection. Also,
147*6777b538SAndroid Build Coastguard Worker   // AddressTrackerLinux does not insert loopback interfaces into
148*6777b538SAndroid Build Coastguard Worker   // `online_links`.
149*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {};
150*6777b538SAndroid Build Coastguard Worker 
151*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,HasOnlyLoopbackIpv6)154*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, HasOnlyLoopbackIpv6) {
155*6777b538SAndroid Build Coastguard Worker   // Include only a loopback interface.
156*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
157*6777b538SAndroid Build Coastguard Worker       {kIpv6Loopback, ifaddrmsg{
158*6777b538SAndroid Build Coastguard Worker                           .ifa_family = AF_INET6,
159*6777b538SAndroid Build Coastguard Worker                           .ifa_flags = IFA_F_TEMPORARY,
160*6777b538SAndroid Build Coastguard Worker                           .ifa_index = kTestInterfaceLoopback,
161*6777b538SAndroid Build Coastguard Worker                       }}};
162*6777b538SAndroid Build Coastguard Worker   // AddressTrackerLinux does not insert loopback interfaces into
163*6777b538SAndroid Build Coastguard Worker   // `online_links`.
164*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {};
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,HasActiveIPv6Connection)169*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, HasActiveIPv6Connection) {
170*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
171*6777b538SAndroid Build Coastguard Worker       {kIpv6Loopback, ifaddrmsg{.ifa_family = AF_INET6,
172*6777b538SAndroid Build Coastguard Worker                                 .ifa_flags = IFA_F_TEMPORARY,
173*6777b538SAndroid Build Coastguard Worker                                 .ifa_index = kTestInterfaceLoopback}},
174*6777b538SAndroid Build Coastguard Worker       {kIpv6Address, ifaddrmsg{.ifa_family = AF_INET6,
175*6777b538SAndroid Build Coastguard Worker                                .ifa_flags = IFA_F_TEMPORARY,
176*6777b538SAndroid Build Coastguard Worker                                .ifa_index = kTestInterfaceEth}}};
177*6777b538SAndroid Build Coastguard Worker   // `online_links` includes kTestInterfaceEth so that kIpv6Address is the
178*6777b538SAndroid Build Coastguard Worker   // active IPv6 connection. Also, AddressTrackerLinux does not insert loopback
179*6777b538SAndroid Build Coastguard Worker   // interfaces into `online_links`.
180*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {kTestInterfaceEth};
181*6777b538SAndroid Build Coastguard Worker 
182*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,HasInactiveIPv6Connection)185*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, HasInactiveIPv6Connection) {
186*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
187*6777b538SAndroid Build Coastguard Worker       {kIpv6Loopback, ifaddrmsg{.ifa_family = AF_INET6,
188*6777b538SAndroid Build Coastguard Worker                                 .ifa_flags = IFA_F_TEMPORARY,
189*6777b538SAndroid Build Coastguard Worker                                 .ifa_index = kTestInterfaceLoopback}},
190*6777b538SAndroid Build Coastguard Worker       {kIpv6Address, ifaddrmsg{.ifa_family = AF_INET6,
191*6777b538SAndroid Build Coastguard Worker                                .ifa_flags = IFA_F_TEMPORARY,
192*6777b538SAndroid Build Coastguard Worker                                .ifa_index = kTestInterfaceEth}}};
193*6777b538SAndroid Build Coastguard Worker   // `online_links` does not include kTestInterfaceEth so that kIpv6Address is
194*6777b538SAndroid Build Coastguard Worker   // the inactive IPv6 connection. Also, AddressTrackerLinux does not insert
195*6777b538SAndroid Build Coastguard Worker   // loopback interfaces into `online_links`.
196*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {};
197*6777b538SAndroid Build Coastguard Worker 
198*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,IPv6LinkLocal)201*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, IPv6LinkLocal) {
202*6777b538SAndroid Build Coastguard Worker   // Include only IPv6 link-local interfaces.
203*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
204*6777b538SAndroid Build Coastguard Worker       {kIpv6LinkLocal, ifaddrmsg{
205*6777b538SAndroid Build Coastguard Worker                            .ifa_family = AF_INET6,
206*6777b538SAndroid Build Coastguard Worker                            .ifa_flags = IFA_F_TEMPORARY,
207*6777b538SAndroid Build Coastguard Worker                            .ifa_index = 3,
208*6777b538SAndroid Build Coastguard Worker                        }}};
209*6777b538SAndroid Build Coastguard Worker   // Mark the IPv6 link-local interface as online.
210*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {3};
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker 
TEST_F(LoopbackOnlyTest,ExtraOnlineLinks)215*6777b538SAndroid Build Coastguard Worker TEST_F(LoopbackOnlyTest, ExtraOnlineLinks) {
216*6777b538SAndroid Build Coastguard Worker   // Include only IPv6 link-local interfaces.
217*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.address_map() = {
218*6777b538SAndroid Build Coastguard Worker       {kIpv6LinkLocal, ifaddrmsg{
219*6777b538SAndroid Build Coastguard Worker                            .ifa_family = AF_INET6,
220*6777b538SAndroid Build Coastguard Worker                            .ifa_flags = IFA_F_TEMPORARY,
221*6777b538SAndroid Build Coastguard Worker                            .ifa_index = 3,
222*6777b538SAndroid Build Coastguard Worker                        }}};
223*6777b538SAndroid Build Coastguard Worker   // AddressTrackerLinux should not give us online links other than the ones
224*6777b538SAndroid Build Coastguard Worker   // listed in the AddressMap. However, it's better if this code is resilient to
225*6777b538SAndroid Build Coastguard Worker   // a mismatch if there is a bug (for example if the kernel truncates the
226*6777b538SAndroid Build Coastguard Worker   // messages or the buffer the AddressTrackerLinux provides to the kernel is
227*6777b538SAndroid Build Coastguard Worker   // too small). And if this code runs on a different thread from the
228*6777b538SAndroid Build Coastguard Worker   // AddressMapOwnerLinux, AddressMap and online links are updated separately,
229*6777b538SAndroid Build Coastguard Worker   // and so it is possible they can be inconsistent with each other.
230*6777b538SAndroid Build Coastguard Worker   stub_address_map_owner_.online_links() = {1, 2, 3};
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(GetResultOfRunHaveOnlyLoopbackAddressesJob());
233*6777b538SAndroid Build Coastguard Worker }
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1450403): Test HaveOnlyLoopbackAddressesUsingGetifaddrs().
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_LINUX)
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker }  // namespace net
240