xref: /aosp_15_r20/external/cronet/net/base/address_tracker_linux_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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 #include "net/base/address_tracker_linux.h"
6 
7 #include <linux/if.h>
8 #include <linux/rtnetlink.h>
9 #include <sched.h>
10 
11 #include <memory>
12 #include <unordered_set>
13 #include <vector>
14 
15 #include "base/command_line.h"
16 #include "base/files/file_util.h"
17 #include "base/functional/bind.h"
18 #include "base/functional/callback_helpers.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/synchronization/waitable_event.h"
22 #include "base/test/bind.h"
23 #include "base/test/multiprocess_test.h"
24 #include "base/test/spin_wait.h"
25 #include "base/test/task_environment.h"
26 #include "base/test/test_simple_task_runner.h"
27 #include "base/threading/simple_thread.h"
28 #include "build/build_config.h"
29 #include "net/base/address_map_cache_linux.h"
30 #include "net/base/address_map_linux.h"
31 #include "net/base/address_tracker_linux_test_util.h"
32 #include "net/base/ip_address.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "testing/multiprocess_func_list.h"
35 
36 #if BUILDFLAG(IS_ANDROID)
37 #include "base/android/build_info.h"
38 #endif
39 
40 #ifndef IFA_F_HOMEADDRESS
41 #define IFA_F_HOMEADDRESS 0x10
42 #endif
43 
44 using net::internal::AddressTrackerLinux;
45 
46 namespace net::test {
47 namespace {
48 
49 const int kTestInterfaceEth = 1;
50 const int kTestInterfaceWifi = 2;
51 const int kTestInterfaceTun = 123;
52 const int kTestInterfaceAp = 456;
53 
54 const char kIgnoredInterfaceName[] = "uap0";
55 
TestGetInterfaceName(int interface_index,char * buf)56 char* TestGetInterfaceName(int interface_index, char* buf) {
57   if (interface_index == kTestInterfaceEth) {
58     snprintf(buf, IFNAMSIZ, "%s", "eth0");
59   } else if (interface_index == kTestInterfaceTun) {
60     snprintf(buf, IFNAMSIZ, "%s", "tun0");
61   } else if (interface_index == kTestInterfaceAp) {
62     snprintf(buf, IFNAMSIZ, "%s", kIgnoredInterfaceName);
63   } else {
64     snprintf(buf, IFNAMSIZ, "%s", "");
65   }
66   return buf;
67 }
68 
69 }  // namespace
70 
71 class AddressTrackerLinuxTest : public testing::Test {
72  protected:
73   AddressTrackerLinuxTest() = default;
74 
InitializeAddressTracker(bool tracking)75   void InitializeAddressTracker(bool tracking) {
76     tracking_ = tracking;
77     if (tracking) {
78       tracker_ = std::make_unique<AddressTrackerLinux>(
79           base::DoNothing(), base::DoNothing(), base::DoNothing(),
80           ignored_interfaces_);
81 #if BUILDFLAG(IS_LINUX)
82       const auto& [address_map, online_links] =
83           tracker_->GetInitialDataAndStartRecordingDiffs();
84       address_map_cache_.SetCachedInfo(address_map, online_links);
85 #endif  // BUILDFLAG(IS_LINUX)
86     } else {
87       tracker_ = std::make_unique<AddressTrackerLinux>();
88     }
89     original_get_interface_name_ = tracker_->get_interface_name_;
90     tracker_->get_interface_name_ = TestGetInterfaceName;
91   }
92 
HandleAddressMessage(const NetlinkBuffer & buf)93   bool HandleAddressMessage(const NetlinkBuffer& buf) {
94     NetlinkBuffer writable_buf = buf;
95     bool address_changed = false;
96     bool link_changed = false;
97     bool tunnel_changed = false;
98     tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed,
99                             &link_changed, &tunnel_changed);
100     UpdateCache();
101     EXPECT_FALSE(link_changed);
102     return address_changed;
103   }
104 
HandleLinkMessage(const NetlinkBuffer & buf)105   bool HandleLinkMessage(const NetlinkBuffer& buf) {
106     NetlinkBuffer writable_buf = buf;
107     bool address_changed = false;
108     bool link_changed = false;
109     bool tunnel_changed = false;
110     tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed,
111                             &link_changed, &tunnel_changed);
112     UpdateCache();
113     EXPECT_FALSE(address_changed);
114     return link_changed;
115   }
116 
HandleTunnelMessage(const NetlinkBuffer & buf)117   bool HandleTunnelMessage(const NetlinkBuffer& buf) {
118     NetlinkBuffer writable_buf = buf;
119     bool address_changed = false;
120     bool link_changed = false;
121     bool tunnel_changed = false;
122     AddressMapOwnerLinux::AddressMapDiff address_map_diff_;
123     AddressMapOwnerLinux::OnlineLinksDiff online_links_diff_;
124     tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed,
125                             &link_changed, &tunnel_changed);
126     UpdateCache();
127     EXPECT_FALSE(address_changed);
128     return tunnel_changed;
129   }
130 
GetAddressMap()131   AddressTrackerLinux::AddressMap GetAddressMap() {
132     return tracker_->GetAddressMap();
133   }
134 
GetOnlineLinks() const135   const std::unordered_set<int> GetOnlineLinks() const {
136     return tracker_->GetOnlineLinks();
137   }
138 
IgnoreInterface(const std::string & interface_name)139   void IgnoreInterface(const std::string& interface_name) {
140     ignored_interfaces_.insert(interface_name);
141   }
142 
GetThreadsWaitingForConnectionTypeInit()143   int GetThreadsWaitingForConnectionTypeInit() {
144     return tracker_->GetThreadsWaitingForConnectionTypeInitForTesting();
145   }
146 
147   std::unordered_set<std::string> ignored_interfaces_;
148   std::unique_ptr<AddressTrackerLinux> tracker_;
149   AddressTrackerLinux::GetInterfaceNameFunction original_get_interface_name_;
150 
151  private:
152   // Checks that applying the generated diff to `address_map_cache_` results in
153   // the same AddressMap and set of online links that `tracker_` maintains.
UpdateCache()154   void UpdateCache() {
155     if (!tracking_) {
156       return;
157     }
158 #if BUILDFLAG(IS_LINUX)
159     address_map_cache_.ApplyDiffs(tracker_->address_map_diff_for_testing(),
160                                   tracker_->online_links_diff_for_testing());
161     EXPECT_EQ(address_map_cache_.GetAddressMap(), tracker_->GetAddressMap());
162     EXPECT_EQ(address_map_cache_.GetOnlineLinks(), tracker_->GetOnlineLinks());
163     tracker_->address_map_diff_for_testing().clear();
164     tracker_->online_links_diff_for_testing().clear();
165 #endif  // BUILDFLAG(IS_LINUX)
166   }
167 
168 #if BUILDFLAG(IS_LINUX)
169   AddressMapCacheLinux address_map_cache_;
170 #endif
171   bool tracking_;
172 };
173 
174 namespace {
175 
176 const unsigned char kAddress0[] = { 127, 0, 0, 1 };
177 const unsigned char kAddress1[] = { 10, 0, 0, 1 };
178 const unsigned char kAddress2[] = { 192, 168, 0, 1 };
179 const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180                                     0, 0, 0, 1 };
181 
TEST_F(AddressTrackerLinuxTest,NewAddress)182 TEST_F(AddressTrackerLinuxTest, NewAddress) {
183   InitializeAddressTracker(true);
184 
185   const IPAddress kEmpty;
186   const IPAddress kAddr0(kAddress0);
187   const IPAddress kAddr1(kAddress1);
188   const IPAddress kAddr2(kAddress2);
189   const IPAddress kAddr3(kAddress3);
190 
191   NetlinkBuffer buffer;
192   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
193                   kAddr0, kEmpty, &buffer);
194   EXPECT_TRUE(HandleAddressMessage(buffer));
195   AddressTrackerLinux::AddressMap map = GetAddressMap();
196   EXPECT_EQ(1u, map.size());
197   EXPECT_EQ(1u, map.count(kAddr0));
198   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
199 
200   buffer.clear();
201   MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth,
202                   kAddr1, kAddr2, &buffer);
203   EXPECT_TRUE(HandleAddressMessage(buffer));
204   map = GetAddressMap();
205   EXPECT_EQ(2u, map.size());
206   EXPECT_EQ(1u, map.count(kAddr0));
207   EXPECT_EQ(1u, map.count(kAddr2));
208   EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr2].ifa_flags);
209 
210   buffer.clear();
211   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, kEmpty, kAddr3,
212                   &buffer);
213   EXPECT_TRUE(HandleAddressMessage(buffer));
214   map = GetAddressMap();
215   EXPECT_EQ(3u, map.size());
216   EXPECT_EQ(1u, map.count(kAddr3));
217 }
218 
TEST_F(AddressTrackerLinuxTest,NewAddressChange)219 TEST_F(AddressTrackerLinuxTest, NewAddressChange) {
220   InitializeAddressTracker(true);
221 
222   const IPAddress kEmpty;
223   const IPAddress kAddr0(kAddress0);
224 
225   NetlinkBuffer buffer;
226   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
227                   kAddr0, kEmpty, &buffer);
228   EXPECT_TRUE(HandleAddressMessage(buffer));
229   AddressTrackerLinux::AddressMap map = GetAddressMap();
230   EXPECT_EQ(1u, map.size());
231   EXPECT_EQ(1u, map.count(kAddr0));
232   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
233 
234   buffer.clear();
235   MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth,
236                   kAddr0, kEmpty, &buffer);
237   EXPECT_TRUE(HandleAddressMessage(buffer));
238   map = GetAddressMap();
239   EXPECT_EQ(1u, map.size());
240   EXPECT_EQ(1u, map.count(kAddr0));
241   EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
242 
243   // Both messages in one buffer.
244   buffer.clear();
245   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
246                   kAddr0, kEmpty, &buffer);
247   MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth,
248                   kAddr0, kEmpty, &buffer);
249   EXPECT_TRUE(HandleAddressMessage(buffer));
250   map = GetAddressMap();
251   EXPECT_EQ(1u, map.size());
252   EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
253 }
254 
TEST_F(AddressTrackerLinuxTest,NewAddressDuplicate)255 TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) {
256   InitializeAddressTracker(true);
257 
258   const IPAddress kAddr0(kAddress0);
259 
260   NetlinkBuffer buffer;
261   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
262                   kAddr0, kAddr0, &buffer);
263   EXPECT_TRUE(HandleAddressMessage(buffer));
264   AddressTrackerLinux::AddressMap map = GetAddressMap();
265   EXPECT_EQ(1u, map.size());
266   EXPECT_EQ(1u, map.count(kAddr0));
267   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
268 
269   EXPECT_FALSE(HandleAddressMessage(buffer));
270   map = GetAddressMap();
271   EXPECT_EQ(1u, map.size());
272   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
273 }
274 
TEST_F(AddressTrackerLinuxTest,DeleteAddress)275 TEST_F(AddressTrackerLinuxTest, DeleteAddress) {
276   InitializeAddressTracker(true);
277 
278   const IPAddress kEmpty;
279   const IPAddress kAddr0(kAddress0);
280   const IPAddress kAddr1(kAddress1);
281   const IPAddress kAddr2(kAddress2);
282 
283   NetlinkBuffer buffer;
284   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kAddr0, kEmpty,
285                   &buffer);
286   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kAddr1, kAddr2,
287                   &buffer);
288   EXPECT_TRUE(HandleAddressMessage(buffer));
289   AddressTrackerLinux::AddressMap map = GetAddressMap();
290   EXPECT_EQ(2u, map.size());
291 
292   buffer.clear();
293   MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kEmpty, kAddr0,
294                   &buffer);
295   EXPECT_TRUE(HandleAddressMessage(buffer));
296   map = GetAddressMap();
297   EXPECT_EQ(1u, map.size());
298   EXPECT_EQ(0u, map.count(kAddr0));
299   EXPECT_EQ(1u, map.count(kAddr2));
300 
301   buffer.clear();
302   MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kAddr2, kAddr1,
303                   &buffer);
304   // kAddr1 does not exist in the map.
305   EXPECT_FALSE(HandleAddressMessage(buffer));
306   map = GetAddressMap();
307   EXPECT_EQ(1u, map.size());
308 
309   buffer.clear();
310   MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kAddr2, kEmpty,
311                   &buffer);
312   EXPECT_TRUE(HandleAddressMessage(buffer));
313   map = GetAddressMap();
314   EXPECT_EQ(0u, map.size());
315 }
316 
TEST_F(AddressTrackerLinuxTest,DeprecatedLifetime)317 TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) {
318   InitializeAddressTracker(true);
319 
320   const IPAddress kEmpty;
321   const IPAddress kAddr3(kAddress3);
322 
323   NetlinkBuffer buffer;
324   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, kEmpty, kAddr3,
325                   &buffer);
326   EXPECT_TRUE(HandleAddressMessage(buffer));
327   AddressTrackerLinux::AddressMap map = GetAddressMap();
328   EXPECT_EQ(1u, map.size());
329   EXPECT_EQ(1u, map.count(kAddr3));
330   EXPECT_EQ(0, map[kAddr3].ifa_flags);
331 
332   // Verify 0 preferred lifetime implies deprecated.
333   buffer.clear();
334   MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth,
335                                kEmpty, kAddr3, 0, &buffer);
336   EXPECT_TRUE(HandleAddressMessage(buffer));
337   map = GetAddressMap();
338   EXPECT_EQ(1u, map.size());
339   EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
340 
341   // Verify properly flagged message doesn't imply change.
342   buffer.clear();
343   MakeAddrMessageWithCacheInfo(RTM_NEWADDR, IFA_F_DEPRECATED, AF_INET6,
344                                kTestInterfaceEth, kEmpty, kAddr3, 0, &buffer);
345   EXPECT_FALSE(HandleAddressMessage(buffer));
346   map = GetAddressMap();
347   EXPECT_EQ(1u, map.size());
348   EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
349 
350   // Verify implied deprecated doesn't imply change.
351   buffer.clear();
352   MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth,
353                                kEmpty, kAddr3, 0, &buffer);
354   EXPECT_FALSE(HandleAddressMessage(buffer));
355   map = GetAddressMap();
356   EXPECT_EQ(1u, map.size());
357   EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
358 }
359 
TEST_F(AddressTrackerLinuxTest,IgnoredMessage)360 TEST_F(AddressTrackerLinuxTest, IgnoredMessage) {
361   InitializeAddressTracker(true);
362 
363   const IPAddress kEmpty;
364   const IPAddress kAddr0(kAddress0);
365   const IPAddress kAddr3(kAddress3);
366 
367   NetlinkBuffer buffer;
368   // Ignored family.
369   MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kTestInterfaceEth, kAddr3, kAddr0,
370                   &buffer);
371   // No address.
372   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kEmpty, kEmpty,
373                   &buffer);
374   // Ignored type.
375   MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kTestInterfaceEth, kAddr3, kEmpty,
376                   &buffer);
377   EXPECT_FALSE(HandleAddressMessage(buffer));
378   EXPECT_TRUE(GetAddressMap().empty());
379 
380   // Valid message after ignored messages.
381   NetlinkMessage nlmsg(RTM_NEWADDR);
382   struct ifaddrmsg msg = {};
383   msg.ifa_family = AF_INET;
384   nlmsg.AddPayload(msg);
385   // Ignored attribute.
386   struct ifa_cacheinfo cache_info = {};
387   nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
388   nlmsg.AddAttribute(IFA_ADDRESS, kAddr0.bytes().data(), kAddr0.size());
389   nlmsg.AppendTo(&buffer);
390 
391   EXPECT_TRUE(HandleAddressMessage(buffer));
392   EXPECT_EQ(1u, GetAddressMap().size());
393 }
394 
TEST_F(AddressTrackerLinuxTest,AddInterface)395 TEST_F(AddressTrackerLinuxTest, AddInterface) {
396   InitializeAddressTracker(true);
397 
398   NetlinkBuffer buffer;
399 
400   // Ignores loopback.
401   MakeLinkMessage(RTM_NEWLINK,
402                   IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
403                   kTestInterfaceEth, &buffer);
404   EXPECT_FALSE(HandleLinkMessage(buffer));
405   EXPECT_TRUE(GetOnlineLinks().empty());
406 
407   // Ignores not IFF_LOWER_UP.
408   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
409                   &buffer);
410   EXPECT_FALSE(HandleLinkMessage(buffer));
411   EXPECT_TRUE(GetOnlineLinks().empty());
412 
413   // Ignores deletion.
414   MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
415                   kTestInterfaceEth, &buffer);
416   EXPECT_FALSE(HandleLinkMessage(buffer));
417   EXPECT_TRUE(GetOnlineLinks().empty());
418 
419   // Verify success.
420   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
421                   kTestInterfaceEth, &buffer);
422   EXPECT_TRUE(HandleLinkMessage(buffer));
423   EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
424   EXPECT_EQ(1u, GetOnlineLinks().size());
425 
426   // Ignores redundant enables.
427   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
428                   kTestInterfaceEth, &buffer);
429   EXPECT_FALSE(HandleLinkMessage(buffer));
430   EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
431   EXPECT_EQ(1u, GetOnlineLinks().size());
432 
433   // Ignores messages from wireless_send_event.
434   MakeWirelessLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
435                           kTestInterfaceWifi, &buffer);
436   EXPECT_FALSE(HandleLinkMessage(buffer));
437   EXPECT_EQ(0u, GetOnlineLinks().count(kTestInterfaceWifi));
438   EXPECT_EQ(1u, GetOnlineLinks().size());
439 
440   // Verify adding another online device (e.g. VPN) is considered a change.
441   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 2, &buffer);
442   EXPECT_TRUE(HandleLinkMessage(buffer));
443   EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
444   EXPECT_EQ(1u, GetOnlineLinks().count(2));
445   EXPECT_EQ(2u, GetOnlineLinks().size());
446 }
447 
TEST_F(AddressTrackerLinuxTest,RemoveInterface)448 TEST_F(AddressTrackerLinuxTest, RemoveInterface) {
449   InitializeAddressTracker(true);
450 
451   NetlinkBuffer buffer;
452 
453   // Should disappear when not IFF_LOWER_UP.
454   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
455                   kTestInterfaceEth, &buffer);
456   EXPECT_TRUE(HandleLinkMessage(buffer));
457   EXPECT_FALSE(GetOnlineLinks().empty());
458   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
459                   &buffer);
460   EXPECT_TRUE(HandleLinkMessage(buffer));
461   EXPECT_TRUE(GetOnlineLinks().empty());
462 
463   // Ignores redundant disables.
464   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
465                   &buffer);
466   EXPECT_FALSE(HandleLinkMessage(buffer));
467   EXPECT_TRUE(GetOnlineLinks().empty());
468 
469   // Ignores deleting down interfaces.
470   MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
471                   &buffer);
472   EXPECT_FALSE(HandleLinkMessage(buffer));
473   EXPECT_TRUE(GetOnlineLinks().empty());
474 
475   // Should disappear when deleted.
476   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
477                   kTestInterfaceEth, &buffer);
478   EXPECT_TRUE(HandleLinkMessage(buffer));
479   EXPECT_FALSE(GetOnlineLinks().empty());
480   MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
481                   kTestInterfaceEth, &buffer);
482   EXPECT_TRUE(HandleLinkMessage(buffer));
483   EXPECT_TRUE(GetOnlineLinks().empty());
484 
485   // Ignores messages from wireless_send_event.
486   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
487                   kTestInterfaceWifi, &buffer);
488   EXPECT_TRUE(HandleLinkMessage(buffer));
489   EXPECT_FALSE(GetOnlineLinks().empty());
490   MakeWirelessLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP,
491                           kTestInterfaceWifi, &buffer);
492   EXPECT_FALSE(HandleLinkMessage(buffer));
493   EXPECT_FALSE(GetOnlineLinks().empty());
494   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceWifi,
495                   &buffer);
496   EXPECT_TRUE(HandleLinkMessage(buffer));
497   EXPECT_TRUE(GetOnlineLinks().empty());
498 }
499 
TEST_F(AddressTrackerLinuxTest,IgnoreInterface)500 TEST_F(AddressTrackerLinuxTest, IgnoreInterface) {
501   IgnoreInterface(kIgnoredInterfaceName);
502   InitializeAddressTracker(true);
503 
504   NetlinkBuffer buffer;
505   const IPAddress kEmpty;
506   const IPAddress kAddr0(kAddress0);
507 
508   // Verify online links and address map has been not been updated
509   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceAp,
510                   kAddr0, kEmpty, &buffer);
511   EXPECT_FALSE(HandleAddressMessage(buffer));
512   AddressTrackerLinux::AddressMap map = GetAddressMap();
513   EXPECT_EQ(0u, map.size());
514   EXPECT_EQ(0u, map.count(kAddr0));
515   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
516                   kTestInterfaceAp, &buffer);
517   EXPECT_FALSE(HandleLinkMessage(buffer));
518   EXPECT_EQ(0u, GetOnlineLinks().count(kTestInterfaceAp));
519   EXPECT_EQ(0u, GetOnlineLinks().size());
520 }
521 
TEST_F(AddressTrackerLinuxTest,IgnoreInterface_NonIgnoredInterface)522 TEST_F(AddressTrackerLinuxTest, IgnoreInterface_NonIgnoredInterface) {
523   IgnoreInterface(kIgnoredInterfaceName);
524   InitializeAddressTracker(true);
525 
526   NetlinkBuffer buffer;
527   const IPAddress kEmpty;
528   const IPAddress kAddr0(kAddress0);
529 
530   // Verify eth0 is not ignored when only uap0 is ignored
531   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
532                   kAddr0, kEmpty, &buffer);
533   EXPECT_TRUE(HandleAddressMessage(buffer));
534   AddressTrackerLinux::AddressMap map = GetAddressMap();
535   EXPECT_EQ(1u, map.size());
536   EXPECT_EQ(1u, map.count(kAddr0));
537   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
538                   kTestInterfaceEth, &buffer);
539   EXPECT_TRUE(HandleLinkMessage(buffer));
540   EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
541   EXPECT_EQ(1u, GetOnlineLinks().size());
542 }
543 
TEST_F(AddressTrackerLinuxTest,TunnelInterface)544 TEST_F(AddressTrackerLinuxTest, TunnelInterface) {
545   InitializeAddressTracker(true);
546 
547   NetlinkBuffer buffer;
548 
549   // Ignores without "tun" prefixed name.
550   MakeLinkMessage(RTM_NEWLINK,
551                   IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
552                   kTestInterfaceEth, &buffer);
553   EXPECT_FALSE(HandleTunnelMessage(buffer));
554 
555   // Verify success.
556   MakeLinkMessage(RTM_NEWLINK,
557                   IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
558                   kTestInterfaceTun, &buffer);
559   EXPECT_TRUE(HandleTunnelMessage(buffer));
560 
561   // Ignores redundant enables.
562   MakeLinkMessage(RTM_NEWLINK,
563                   IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
564                   kTestInterfaceTun, &buffer);
565   EXPECT_FALSE(HandleTunnelMessage(buffer));
566 
567   // Ignores deleting without "tun" prefixed name.
568   MakeLinkMessage(RTM_DELLINK,
569                   IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
570                   0, &buffer);
571   EXPECT_FALSE(HandleTunnelMessage(buffer));
572 
573   // Verify successful deletion
574   MakeLinkMessage(RTM_DELLINK,
575                   IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
576                   kTestInterfaceTun, &buffer);
577   EXPECT_TRUE(HandleTunnelMessage(buffer));
578 
579   // Ignores redundant deletions.
580   MakeLinkMessage(RTM_DELLINK,
581                   IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
582                   kTestInterfaceTun, &buffer);
583   EXPECT_FALSE(HandleTunnelMessage(buffer));
584 }
585 
586 // Check AddressTrackerLinux::get_interface_name_ original implementation
587 // doesn't crash or return NULL.
TEST_F(AddressTrackerLinuxTest,GetInterfaceName)588 TEST_F(AddressTrackerLinuxTest, GetInterfaceName) {
589   InitializeAddressTracker(true);
590 
591   for (int i = 0; i < 10; i++) {
592     char buf[IFNAMSIZ] = {0};
593     EXPECT_NE((const char*)nullptr, original_get_interface_name_(i, buf));
594   }
595 }
596 
TEST_F(AddressTrackerLinuxTest,NonTrackingMode)597 TEST_F(AddressTrackerLinuxTest, NonTrackingMode) {
598   InitializeAddressTracker(false);
599 
600   const IPAddress kEmpty;
601   const IPAddress kAddr0(kAddress0);
602 
603   NetlinkBuffer buffer;
604   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
605                   kAddr0, kEmpty, &buffer);
606   EXPECT_TRUE(HandleAddressMessage(buffer));
607   AddressTrackerLinux::AddressMap map = GetAddressMap();
608   EXPECT_EQ(1u, map.size());
609   EXPECT_EQ(1u, map.count(kAddr0));
610   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
611 
612   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer);
613   EXPECT_TRUE(HandleLinkMessage(buffer));
614   EXPECT_EQ(1u, GetOnlineLinks().count(1));
615   EXPECT_EQ(1u, GetOnlineLinks().size());
616 }
617 
TEST_F(AddressTrackerLinuxTest,NonTrackingModeInit)618 TEST_F(AddressTrackerLinuxTest, NonTrackingModeInit) {
619 #if BUILDFLAG(IS_ANDROID)
620   // Calling Init() on Android P+ isn't supported.
621   if (base::android::BuildInfo::GetInstance()->sdk_int() >=
622       base::android::SDK_VERSION_P)
623     return;
624 #endif
625   AddressTrackerLinux tracker;
626   tracker.Init();
627 }
628 
629 class GetCurrentConnectionTypeRunner
630     : public base::DelegateSimpleThread::Delegate {
631  public:
GetCurrentConnectionTypeRunner(AddressTrackerLinux * tracker,const std::string & thread_name)632   explicit GetCurrentConnectionTypeRunner(AddressTrackerLinux* tracker,
633                                           const std::string& thread_name)
634       : tracker_(tracker),
635         done_(base::WaitableEvent::ResetPolicy::MANUAL,
636               base::WaitableEvent::InitialState::NOT_SIGNALED),
637         thread_(this, thread_name) {}
638   ~GetCurrentConnectionTypeRunner() override = default;
639 
Run()640   void Run() override {
641     tracker_->GetCurrentConnectionType();
642     done_.Signal();
643   }
644 
Start()645   void Start() {
646     thread_.Start();
647   }
648 
VerifyCompletes()649   void VerifyCompletes() {
650     EXPECT_TRUE(done_.TimedWait(base::Seconds(5)));
651     thread_.Join();
652   }
653 
654  private:
655   const raw_ptr<AddressTrackerLinux> tracker_;
656   base::WaitableEvent done_;
657   base::DelegateSimpleThread thread_;
658 };
659 
TEST_F(AddressTrackerLinuxTest,BroadcastInit)660 TEST_F(AddressTrackerLinuxTest, BroadcastInit) {
661 #if BUILDFLAG(IS_ANDROID)
662   // Calling Init() on Android P+ isn't supported.
663   if (base::android::BuildInfo::GetInstance()->sdk_int() >=
664       base::android::SDK_VERSION_P)
665     return;
666 #endif
667   base::test::TaskEnvironment task_environment(
668       base::test::TaskEnvironment::MainThreadType::IO);
669   InitializeAddressTracker(true);
670 
671   GetCurrentConnectionTypeRunner runner1(tracker_.get(), "waiter_thread_1");
672   GetCurrentConnectionTypeRunner runner2(tracker_.get(), "waiter_thread_2");
673 
674   runner1.Start();
675   runner2.Start();
676 
677   SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(
678       GetThreadsWaitingForConnectionTypeInit() == 2);
679 
680   tracker_->Init();
681 
682   runner1.VerifyCompletes();
683   runner2.VerifyCompletes();
684 }
685 
TEST_F(AddressTrackerLinuxTest,TunnelInterfaceName)686 TEST_F(AddressTrackerLinuxTest, TunnelInterfaceName) {
687   EXPECT_TRUE(AddressTrackerLinux::IsTunnelInterfaceName("tun0"));
688   EXPECT_FALSE(AddressTrackerLinux::IsTunnelInterfaceName("wlan0"));
689 }
690 
691 }  // namespace
692 }  // namespace net::test
693 
694 namespace net::internal {
695 
696 // This is a regression test for https://crbug.com/1224428.
697 //
698 // This test initializes two instances of `AddressTrackerLinux` in the same
699 // process. The test will fail if the implementation reuses the value of
700 // `sockaddr_nl::nl_pid`.
701 //
702 // Note: consumers generally should not need to create two tracking instances of
703 // `AddressTrackerLinux` in the same process.
TEST(AddressTrackerLinuxNetlinkTest,TestInitializeTwoTrackers)704 TEST(AddressTrackerLinuxNetlinkTest, TestInitializeTwoTrackers) {
705 #if BUILDFLAG(IS_ANDROID)
706   // Calling Init() on Android P+ isn't supported.
707   if (base::android::BuildInfo::GetInstance()->sdk_int() >=
708       base::android::SDK_VERSION_P)
709     return;
710 #endif
711   base::test::TaskEnvironment task_env(
712       base::test::TaskEnvironment::MainThreadType::IO);
713   AddressTrackerLinux tracker1(base::DoNothing(), base::DoNothing(),
714                                base::DoNothing(), {});
715   AddressTrackerLinux tracker2(base::DoNothing(), base::DoNothing(),
716                                base::DoNothing(), {});
717   tracker1.Init();
718   tracker2.Init();
719   EXPECT_TRUE(tracker1.DidTrackingInitSucceedForTesting());
720   EXPECT_TRUE(tracker2.DidTrackingInitSucceedForTesting());
721 }
722 
723 // These tests use `base::LaunchOptions::clone_flags` for fine-grained control
724 // over the clone syscall, but the field is only defined on Linux and ChromeOS.
725 // Unfortunately, this means these tests do not have coverage on Android.
726 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
727 // These tests require specific flag values defined in <sched.h>.
728 #if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
729 
730 namespace {
731 const char* const kSwitchParentWriteFd = "addresstrackerlinux_parent_write_fd";
732 const char* const kSwitchReadFd = "addresstrackerlinux_read_fd";
733 
734 enum IPCMessage {
735   // Sent from child to parent once the child has initialized its tracker.
736   kChildInitializedAndWaiting,
737   // Sent from child to parent when it was unable to initialize its tracker.
738   kChildFailed,
739   // Sent from parent to child when all children are permitted to exit.
740   kChildMayExit,
741 };
742 
GetSwitchValueFile(const base::CommandLine * command_line,std::string_view name)743 base::File GetSwitchValueFile(const base::CommandLine* command_line,
744                               std::string_view name) {
745   std::string value = command_line->GetSwitchValueASCII(name);
746   int fd;
747   CHECK(base::StringToInt(value, &fd));
748   return base::File(fd);
749 }
750 }  // namespace
751 
752 // This is a regression test for https://crbug.com/1224428.
753 //
754 // This test creates multiple concurrent `AddressTrackerLinux` instances in
755 // separate processes, each in their own PID namespaces.
TEST(AddressTrackerLinuxNetlinkTest,TestInitializeTwoTrackersInPidNamespaces)756 TEST(AddressTrackerLinuxNetlinkTest, TestInitializeTwoTrackersInPidNamespaces) {
757   // This test initializes `kNumChildren` instances of `AddressTrackerLinux` in
758   // tracking mode, each in their own child process running in a PID namespace.
759   // The test will fail if the implementation reuses the value of
760   // `sockaddr_nl::nl_pid`.
761   //
762   // The child processes use pipes to synchronize. Each child initializes a
763   // tracker, sends a message to the parent, and waits for the parent to
764   // respond, indicating that all children are done setting up. This ensures
765   // that the tracker objects have overlapping lifetimes, and thus that the
766   // underlying netlink sockets have overlapping lifetimes. This coexistence is
767   // necessary, but not sufficient, for a `sockaddr_nl::nl_pid` value collision.
768   constexpr size_t kNumChildren = 2;
769 
770   base::ScopedFD parent_read_fd, parent_write_fd;
771   ASSERT_TRUE(base::CreatePipe(&parent_read_fd, &parent_write_fd));
772 
773   struct Child {
774     base::ScopedFD read_fd;
775     base::ScopedFD write_fd;
776     base::Process process;
777   } children[kNumChildren];
778 
779   for (Child& child : children) {
780     ASSERT_TRUE(base::CreatePipe(&child.read_fd, &child.write_fd));
781 
782     // Since the child process will wipe its address space by calling execvp, we
783     // must share the file descriptors via its command line.
784     base::CommandLine command_line(
785         base::GetMultiProcessTestChildBaseCommandLine());
786     command_line.AppendSwitchASCII(kSwitchParentWriteFd,
787                                    base::NumberToString(parent_write_fd.get()));
788     command_line.AppendSwitchASCII(kSwitchReadFd,
789                                    base::NumberToString(child.read_fd.get()));
790 
791     base::LaunchOptions options;
792     // Indicate that the child process requires these file descriptors.
793     // Otherwise, they will be closed. See `base::CloseSuperfluousFds`.
794     options.fds_to_remap = {{child.read_fd.get(), child.read_fd.get()},
795                             {parent_write_fd.get(), parent_write_fd.get()}};
796     // Clone into a new PID namespace. Making it a new user namespace as well to
797     // skirt the CAP_SYS_ADMIN requirement.
798     options.clone_flags = CLONE_NEWPID | CLONE_NEWUSER;
799 
800     child.process = base::SpawnMultiProcessTestChild(
801         "ChildProcessInitializeTrackerForTesting", command_line, options);
802   }
803 
804   // Wait for all children to finish initializing their tracking
805   // AddressTrackerLinuxes.
806   base::File parent_reader(std::move(parent_read_fd));
807   for (const Child& child : children) {
808     ASSERT_TRUE(child.process.IsValid());
809 
810     uint8_t message[] = {0};
811     ASSERT_TRUE(parent_reader.ReadAtCurrentPosAndCheck(message));
812     ASSERT_EQ(message[0], kChildInitializedAndWaiting);
813   }
814 
815   // Tell children to exit and wait for them to exit.
816   for (Child& child : children) {
817     base::File child_writer(std::move(child.write_fd));
818     const uint8_t kMessage[] = {kChildMayExit};
819     ASSERT_TRUE(child_writer.WriteAtCurrentPosAndCheck(kMessage));
820 
821     int exit_code = 0;
822     ASSERT_TRUE(child.process.WaitForExit(&exit_code));
823     ASSERT_EQ(exit_code, 0);
824   }
825 }
826 
MULTIPROCESS_TEST_MAIN(ChildProcessInitializeTrackerForTesting)827 MULTIPROCESS_TEST_MAIN(ChildProcessInitializeTrackerForTesting) {
828   base::test::TaskEnvironment task_env(
829       base::test::TaskEnvironment::MainThreadType::IO);
830 
831   const base::CommandLine* command_line =
832       base::CommandLine::ForCurrentProcess();
833   base::File reader = GetSwitchValueFile(command_line, kSwitchReadFd);
834   base::File parent_writer =
835       GetSwitchValueFile(command_line, kSwitchParentWriteFd);
836 
837   // Initialize an `AddressTrackerLinux` in tracking mode and ensure that it
838   // created a netlink socket.
839   AddressTrackerLinux tracker(base::DoNothing(), base::DoNothing(),
840                               base::DoNothing(), {});
841   tracker.Init();
842   if (!tracker.DidTrackingInitSucceedForTesting()) {
843     const uint8_t kMessage[] = {kChildFailed};
844     parent_writer.WriteAtCurrentPosAndCheck(kMessage);
845     return 1;
846   }
847 
848   // Signal to the parent that we have initialized the tracker.
849   const uint8_t kMessage[] = {kChildInitializedAndWaiting};
850   if (!parent_writer.WriteAtCurrentPosAndCheck(kMessage))
851     return 1;
852 
853   // Block until the parent says all children have initialized their trackers.
854   uint8_t message[] = {0};
855   if (!reader.ReadAtCurrentPosAndCheck(message) || message[0] != kChildMayExit)
856     return 1;
857   return 0;
858 }
859 
860 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
861 #endif  // defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
862 
863 }  // namespace net::internal
864