diff options
-rw-r--r-- | net/android/network_change_notifier_android.cc | 3 | ||||
-rw-r--r-- | net/base/address_tracker_linux.cc | 32 | ||||
-rw-r--r-- | net/base/address_tracker_linux.h | 15 | ||||
-rw-r--r-- | net/base/address_tracker_linux_unittest.cc | 199 | ||||
-rw-r--r-- | net/base/network_change_notifier.cc | 2 | ||||
-rw-r--r-- | net/base/network_change_notifier_linux.cc | 17 | ||||
-rw-r--r-- | net/base/network_change_notifier_linux.h | 10 | ||||
-rw-r--r-- | net/tools/net_watcher/net_watcher.cc | 28 |
8 files changed, 229 insertions, 77 deletions
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc index 3224c63..9829235 100644 --- a/net/android/network_change_notifier_android.cc +++ b/net/android/network_change_notifier_android.cc @@ -78,7 +78,8 @@ class NetworkChangeNotifierAndroid::DnsConfigServiceThread address_tracker_(base::Bind(base::DoNothing), base::Bind(base::DoNothing), // We're only interested in tunnel interface changes. - base::Bind(NotifyNetworkChangeNotifierObservers)) {} + base::Bind(NotifyNetworkChangeNotifierObservers), + base::hash_set<std::string>()) {} ~DnsConfigServiceThread() override { NetworkChangeNotifier::RemoveNetworkChangeObserver(this); diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc index 731bf4f9..45cd1ae 100644 --- a/net/base/address_tracker_linux.cc +++ b/net/base/address_tracker_linux.cc @@ -107,14 +107,17 @@ AddressTrackerLinux::AddressTrackerLinux() tracking_(false) { } -AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback, - const base::Closure& link_callback, - const base::Closure& tunnel_callback) +AddressTrackerLinux::AddressTrackerLinux( + const base::Closure& address_callback, + const base::Closure& link_callback, + const base::Closure& tunnel_callback, + const base::hash_set<std::string>& ignored_interfaces) : get_interface_name_(GetInterfaceName), address_callback_(address_callback), link_callback_(link_callback), tunnel_callback_(tunnel_callback), netlink_fd_(-1), + ignored_interfaces_(ignored_interfaces), connection_type_initialized_(false), connection_type_initialized_cv_(&connection_type_lock_), current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE), @@ -235,6 +238,15 @@ base::hash_set<int> AddressTrackerLinux::GetOnlineLinks() const { return online_links_; } +bool AddressTrackerLinux::IsInterfaceIgnored(int interface_index) const { + if (ignored_interfaces_.empty()) + return false; + + char buf[IFNAMSIZ] = {0}; + const char* interface_name = get_interface_name_(interface_index, buf); + return ignored_interfaces_.find(interface_name) != ignored_interfaces_.end(); +} + NetworkChangeNotifier::ConnectionType AddressTrackerLinux::GetCurrentConnectionType() { // http://crbug.com/125097 @@ -298,10 +310,12 @@ void AddressTrackerLinux::HandleMessage(char* buffer, case RTM_NEWADDR: { IPAddressNumber address; bool really_deprecated; + struct ifaddrmsg* msg = + reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); + if (IsInterfaceIgnored(msg->ifa_index)) + break; if (GetAddress(header, &address, &really_deprecated)) { AddressTrackerAutoLock lock(*this, address_map_lock_); - struct ifaddrmsg* msg = - reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); // Routers may frequently (every few seconds) output the IPv6 ULA // prefix which can cause the linux kernel to frequently output two // back-to-back messages, one without the deprecated flag and one with @@ -325,6 +339,10 @@ void AddressTrackerLinux::HandleMessage(char* buffer, } break; case RTM_DELADDR: { IPAddressNumber address; + const struct ifaddrmsg* msg = + reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); + if (IsInterfaceIgnored(msg->ifa_index)) + break; if (GetAddress(header, &address, NULL)) { AddressTrackerAutoLock lock(*this, address_map_lock_); if (address_map_.erase(address)) @@ -334,6 +352,8 @@ void AddressTrackerLinux::HandleMessage(char* buffer, case RTM_NEWLINK: { const struct ifinfomsg* msg = reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); + if (IsInterfaceIgnored(msg->ifi_index)) + break; if (!(msg->ifi_flags & IFF_LOOPBACK) && (msg->ifi_flags & IFF_UP) && (msg->ifi_flags & IFF_LOWER_UP) && (msg->ifi_flags & IFF_RUNNING)) { AddressTrackerAutoLock lock(*this, online_links_lock_); @@ -354,6 +374,8 @@ void AddressTrackerLinux::HandleMessage(char* buffer, case RTM_DELLINK: { const struct ifinfomsg* msg = reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); + if (IsInterfaceIgnored(msg->ifi_index)) + break; AddressTrackerAutoLock lock(*this, online_links_lock_); if (online_links_.erase(msg->ifi_index)) { *link_changed = true; diff --git a/net/base/address_tracker_linux.h b/net/base/address_tracker_linux.h index 29cb8c0..1721799 100644 --- a/net/base/address_tracker_linux.h +++ b/net/base/address_tracker_linux.h @@ -44,9 +44,16 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux : // the AddressMap changes, |link_callback| when the list of online // links changes, and |tunnel_callback| when the list of online // tunnels changes. + // |ignored_interfaces| is the list of interfaces to ignore. Changes to an + // ignored interface will not cause any callback to be run. An ignored + // interface will not have entries in GetAddressMap() and GetOnlineLinks(). + // NOTE: Only ignore interfaces not used to connect to the internet. Adding + // interfaces used to connect to the internet can cause critical network + // changed signals to be lost allowing incorrect stale state to persist. AddressTrackerLinux(const base::Closure& address_callback, const base::Closure& link_callback, - const base::Closure& tunnel_callback); + const base::Closure& tunnel_callback, + const base::hash_set<std::string>& ignored_interfaces); ~AddressTrackerLinux() override; // In tracking mode, it starts watching the system configuration for @@ -125,6 +132,9 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux : // Does |interface_index| refer to a tunnel interface? bool IsTunnelInterface(int interface_index) const; + // Is interface with index |interface_index| in list of ignored interfaces? + bool IsInterfaceIgnored(int interface_index) const; + // Updates current_connection_type_ based on the network list. void UpdateCurrentConnectionType(); @@ -147,6 +157,9 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux : mutable base::Lock online_links_lock_; base::hash_set<int> online_links_; + // Set of interface names that should be ignored. + const base::hash_set<std::string> ignored_interfaces_; + base::Lock connection_type_lock_; bool connection_type_initialized_; base::ConditionVariable connection_type_initialized_cv_; diff --git a/net/base/address_tracker_linux_unittest.cc b/net/base/address_tracker_linux_unittest.cc index 1eba58f..2e853ae 100644 --- a/net/base/address_tracker_linux_unittest.cc +++ b/net/base/address_tracker_linux_unittest.cc @@ -20,12 +20,23 @@ namespace net { namespace internal { namespace { +const int kTestInterfaceEth = 1; const int kTestInterfaceTun = 123; +const int kTestInterfaceAp = 456; + +const char kIgnoredInterfaceName[] = "uap0"; char* TestGetInterfaceName(int interface_index, char* buf) { - if (interface_index == kTestInterfaceTun) - return strncpy(buf, "tun0", IFNAMSIZ); - return strncpy(buf, "eth0", IFNAMSIZ); + if (interface_index == kTestInterfaceEth) { + snprintf(buf, IFNAMSIZ, "%s", "eth0"); + } else if (interface_index == kTestInterfaceTun) { + snprintf(buf, IFNAMSIZ, "%s", "tun0"); + } else if (interface_index == kTestInterfaceAp) { + snprintf(buf, IFNAMSIZ, "%s", kIgnoredInterfaceName); + } else { + snprintf(buf, IFNAMSIZ, "%s", ""); + } + return buf; } } // namespace @@ -38,9 +49,9 @@ class AddressTrackerLinuxTest : public testing::Test { void InitializeAddressTracker(bool tracking) { if (tracking) { - tracker_.reset(new AddressTrackerLinux(base::Bind(&base::DoNothing), - base::Bind(&base::DoNothing), - base::Bind(&base::DoNothing))); + tracker_.reset(new AddressTrackerLinux( + base::Bind(&base::DoNothing), base::Bind(&base::DoNothing), + base::Bind(&base::DoNothing), ignored_interfaces_)); } else { tracker_.reset(new AddressTrackerLinux()); } @@ -89,6 +100,11 @@ class AddressTrackerLinuxTest : public testing::Test { return tracker_->GetOnlineLinks(); } + void IgnoreInterface(const std::string& interface_name) { + ignored_interfaces_.insert(interface_name); + } + + base::hash_set<std::string> ignored_interfaces_; scoped_ptr<AddressTrackerLinux> tracker_; AddressTrackerLinux::GetInterfaceNameFunction original_get_interface_name_; }; @@ -150,6 +166,7 @@ class NetlinkMessage { void MakeAddrMessageWithCacheInfo(uint16 type, uint8 flags, uint8 family, + int index, const IPAddressNumber& address, const IPAddressNumber& local, uint32 preferred_lifetime, @@ -158,6 +175,7 @@ void MakeAddrMessageWithCacheInfo(uint16 type, struct ifaddrmsg msg = {}; msg.ifa_family = family; msg.ifa_flags = flags; + msg.ifa_index = index; nlmsg.AddPayload(&msg, sizeof(msg)); if (address.size()) nlmsg.AddAttribute(IFA_ADDRESS, &address[0], address.size()); @@ -173,10 +191,11 @@ void MakeAddrMessageWithCacheInfo(uint16 type, void MakeAddrMessage(uint16 type, uint8 flags, uint8 family, + int index, const IPAddressNumber& address, const IPAddressNumber& local, Buffer* output) { - MakeAddrMessageWithCacheInfo(type, flags, family, address, local, + MakeAddrMessageWithCacheInfo(type, flags, family, index, address, local, INFINITY_LIFE_TIME, output); } @@ -206,8 +225,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddress) { const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); Buffer buffer; - MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, - &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth, + kAddr0, kEmpty, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); AddressTrackerLinux::AddressMap map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -215,8 +234,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddress) { EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); buffer.clear(); - MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr1, kAddr2, - &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth, + kAddr1, kAddr2, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(2u, map.size()); @@ -225,7 +244,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddress) { EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr2].ifa_flags); buffer.clear(); - MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer); + MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, kEmpty, kAddr3, + &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(3u, map.size()); @@ -239,8 +259,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddressChange) { const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); Buffer buffer; - MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, - &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth, + kAddr0, kEmpty, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); AddressTrackerLinux::AddressMap map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -248,8 +268,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddressChange) { EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); buffer.clear(); - MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, - &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth, + kAddr0, kEmpty, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -258,10 +278,10 @@ TEST_F(AddressTrackerLinuxTest, NewAddressChange) { // Both messages in one buffer. buffer.clear(); - MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, - &buffer); - MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, - &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth, + kAddr0, kEmpty, &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth, + kAddr0, kEmpty, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -274,8 +294,8 @@ TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) { const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); Buffer buffer; - MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kAddr0, - &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth, + kAddr0, kAddr0, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); AddressTrackerLinux::AddressMap map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -297,14 +317,17 @@ TEST_F(AddressTrackerLinuxTest, DeleteAddress) { const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2)); Buffer buffer; - MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr0, kEmpty, &buffer); - MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr1, kAddr2, &buffer); + MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kAddr0, kEmpty, + &buffer); + MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kAddr1, kAddr2, + &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); AddressTrackerLinux::AddressMap map = GetAddressMap(); EXPECT_EQ(2u, map.size()); buffer.clear(); - MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kEmpty, kAddr0, &buffer); + MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kEmpty, kAddr0, + &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -312,14 +335,16 @@ TEST_F(AddressTrackerLinuxTest, DeleteAddress) { EXPECT_EQ(1u, map.count(kAddr2)); buffer.clear(); - MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kAddr1, &buffer); + MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kAddr2, kAddr1, + &buffer); // kAddr1 does not exist in the map. EXPECT_FALSE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(1u, map.size()); buffer.clear(); - MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kEmpty, &buffer); + MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kAddr2, kEmpty, + &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(0u, map.size()); @@ -332,7 +357,8 @@ TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) { const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); Buffer buffer; - MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer); + MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, kEmpty, kAddr3, + &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); AddressTrackerLinux::AddressMap map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -341,8 +367,8 @@ TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) { // Verify 0 preferred lifetime implies deprecated. buffer.clear(); - MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, 0, - &buffer); + MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, + kEmpty, kAddr3, 0, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -350,8 +376,8 @@ TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) { // Verify properly flagged message doesn't imply change. buffer.clear(); - MakeAddrMessageWithCacheInfo(RTM_NEWADDR, IFA_F_DEPRECATED, AF_INET6, kEmpty, - kAddr3, 0, &buffer); + MakeAddrMessageWithCacheInfo(RTM_NEWADDR, IFA_F_DEPRECATED, AF_INET6, + kTestInterfaceEth, kEmpty, kAddr3, 0, &buffer); EXPECT_FALSE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -359,8 +385,8 @@ TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) { // Verify implied deprecated doesn't imply change. buffer.clear(); - MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, 0, - &buffer); + MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, + kEmpty, kAddr3, 0, &buffer); EXPECT_FALSE(HandleAddressMessage(buffer)); map = GetAddressMap(); EXPECT_EQ(1u, map.size()); @@ -376,11 +402,14 @@ TEST_F(AddressTrackerLinuxTest, IgnoredMessage) { Buffer buffer; // Ignored family. - MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kAddr3, kAddr0, &buffer); + MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kTestInterfaceEth, kAddr3, kAddr0, + &buffer); // No address. - MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kEmpty, kEmpty, &buffer); + MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kEmpty, kEmpty, + &buffer); // Ignored type. - MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kAddr3, kEmpty, &buffer); + MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kTestInterfaceEth, kAddr3, kEmpty, + &buffer); EXPECT_FALSE(HandleAddressMessage(buffer)); EXPECT_TRUE(GetAddressMap().empty()); @@ -407,37 +436,41 @@ TEST_F(AddressTrackerLinuxTest, AddInterface) { // Ignores loopback. MakeLinkMessage(RTM_NEWLINK, IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING, - 0, &buffer); + kTestInterfaceEth, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores not IFF_LOWER_UP. - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth, + &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores deletion. - MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceEth, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); EXPECT_TRUE(GetOnlineLinks().empty()); // Verify success. - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceEth, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_EQ(1u, GetOnlineLinks().count(0)); + EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth)); EXPECT_EQ(1u, GetOnlineLinks().size()); // Ignores redundant enables. - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceEth, &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); - EXPECT_EQ(1u, GetOnlineLinks().count(0)); + EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth)); EXPECT_EQ(1u, GetOnlineLinks().size()); // Verify adding another online device (e.g. VPN) is considered a change. - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 2, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_EQ(1u, GetOnlineLinks().count(0)); - EXPECT_EQ(1u, GetOnlineLinks().count(1)); + EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth)); + EXPECT_EQ(1u, GetOnlineLinks().count(2)); EXPECT_EQ(2u, GetOnlineLinks().size()); } @@ -447,32 +480,82 @@ TEST_F(AddressTrackerLinuxTest, RemoveInterface) { Buffer buffer; // Should disappear when not IFF_LOWER_UP. - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceEth, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); EXPECT_FALSE(GetOnlineLinks().empty()); - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth, + &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores redundant disables. - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth, + &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); EXPECT_TRUE(GetOnlineLinks().empty()); // Ignores deleting down interfaces. - MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth, + &buffer); EXPECT_FALSE(HandleLinkMessage(buffer)); EXPECT_TRUE(GetOnlineLinks().empty()); // Should disappear when deleted. - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceEth, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); EXPECT_FALSE(GetOnlineLinks().empty()); - MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceEth, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); EXPECT_TRUE(GetOnlineLinks().empty()); } +TEST_F(AddressTrackerLinuxTest, IgnoreInterface) { + IgnoreInterface(kIgnoredInterfaceName); + InitializeAddressTracker(true); + + Buffer buffer; + const IPAddressNumber kEmpty; + const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); + + // Verify online links and address map has been not been updated + MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceAp, + kAddr0, kEmpty, &buffer); + EXPECT_FALSE(HandleAddressMessage(buffer)); + AddressTrackerLinux::AddressMap map = GetAddressMap(); + EXPECT_EQ(0u, map.size()); + EXPECT_EQ(0u, map.count(kAddr0)); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceAp, &buffer); + EXPECT_FALSE(HandleLinkMessage(buffer)); + EXPECT_EQ(0u, GetOnlineLinks().count(kTestInterfaceAp)); + EXPECT_EQ(0u, GetOnlineLinks().size()); +} + +TEST_F(AddressTrackerLinuxTest, IgnoreInterface_NonIgnoredInterface) { + IgnoreInterface(kIgnoredInterfaceName); + InitializeAddressTracker(true); + + Buffer buffer; + const IPAddressNumber kEmpty; + const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); + + // Verify eth0 is not ignored when only uap0 is ignored + MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth, + kAddr0, kEmpty, &buffer); + EXPECT_TRUE(HandleAddressMessage(buffer)); + AddressTrackerLinux::AddressMap map = GetAddressMap(); + EXPECT_EQ(1u, map.size()); + EXPECT_EQ(1u, map.count(kAddr0)); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, + kTestInterfaceEth, &buffer); + EXPECT_TRUE(HandleLinkMessage(buffer)); + EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth)); + EXPECT_EQ(1u, GetOnlineLinks().size()); +} + TEST_F(AddressTrackerLinuxTest, TunnelInterface) { InitializeAddressTracker(true); @@ -481,7 +564,7 @@ TEST_F(AddressTrackerLinuxTest, TunnelInterface) { // Ignores without "tun" prefixed name. MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT, - 0, &buffer); + kTestInterfaceEth, &buffer); EXPECT_FALSE(HandleTunnelMessage(buffer)); // Verify success. @@ -533,17 +616,17 @@ TEST_F(AddressTrackerLinuxTest, NonTrackingMode) { const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); Buffer buffer; - MakeAddrMessage( - RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, &buffer); + MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth, + kAddr0, kEmpty, &buffer); EXPECT_TRUE(HandleAddressMessage(buffer)); AddressTrackerLinux::AddressMap map = GetAddressMap(); EXPECT_EQ(1u, map.size()); EXPECT_EQ(1u, map.count(kAddr0)); EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); - MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer); + MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer); EXPECT_TRUE(HandleLinkMessage(buffer)); - EXPECT_EQ(1u, GetOnlineLinks().count(0)); + EXPECT_EQ(1u, GetOnlineLinks().count(1)); EXPECT_EQ(1u, GetOnlineLinks().size()); } diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 52f348e..7586953 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc @@ -519,7 +519,7 @@ NetworkChangeNotifier* NetworkChangeNotifier::Create() { #endif return NULL; #elif defined(OS_LINUX) - return NetworkChangeNotifierLinux::Create(); + return new NetworkChangeNotifierLinux(base::hash_set<std::string>()); #elif defined(OS_MACOSX) return new NetworkChangeNotifierMac(); #else diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc index 82daf7f..7e47172 100644 --- a/net/base/network_change_notifier_linux.cc +++ b/net/base/network_change_notifier_linux.cc @@ -14,7 +14,7 @@ namespace net { class NetworkChangeNotifierLinux::Thread : public base::Thread { public: - Thread(); + explicit Thread(const base::hash_set<std::string>& ignored_interfaces); ~Thread() override; // Plumbing for NetworkChangeNotifier::GetCurrentConnectionType. @@ -43,14 +43,16 @@ class NetworkChangeNotifierLinux::Thread : public base::Thread { DISALLOW_COPY_AND_ASSIGN(Thread); }; -NetworkChangeNotifierLinux::Thread::Thread() +NetworkChangeNotifierLinux::Thread::Thread( + const base::hash_set<std::string>& ignored_interfaces) : base::Thread("NetworkChangeNotifier"), address_tracker_( base::Bind(&NetworkChangeNotifierLinux::Thread::OnIPAddressChanged, base::Unretained(this)), base::Bind(&NetworkChangeNotifierLinux::Thread::OnLinkChanged, base::Unretained(this)), - base::Bind(base::DoNothing)), + base::Bind(base::DoNothing), + ignored_interfaces), last_type_(NetworkChangeNotifier::CONNECTION_NONE) { } @@ -83,13 +85,10 @@ void NetworkChangeNotifierLinux::Thread::OnLinkChanged() { } } -NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::Create() { - return new NetworkChangeNotifierLinux(); -} - -NetworkChangeNotifierLinux::NetworkChangeNotifierLinux() +NetworkChangeNotifierLinux::NetworkChangeNotifierLinux( + const base::hash_set<std::string>& ignored_interfaces) : NetworkChangeNotifier(NetworkChangeCalculatorParamsLinux()), - notifier_thread_(new Thread()) { + notifier_thread_(new Thread(ignored_interfaces)) { // We create this notifier thread because the notification implementation // needs a MessageLoopForIO, and there's no guarantee that // MessageLoop::current() meets that criterion. diff --git a/net/base/network_change_notifier_linux.h b/net/base/network_change_notifier_linux.h index 5a0f6df..0da7d0c 100644 --- a/net/base/network_change_notifier_linux.h +++ b/net/base/network_change_notifier_linux.h @@ -16,12 +16,18 @@ namespace net { class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux : public NetworkChangeNotifier { public: - static NetworkChangeNotifierLinux* Create(); + // Creates NetworkChangeNotifierLinux with a list of ignored interfaces. + // |ignored_interfaces| is the list of interfaces to ignore. An ignored + // interface will not trigger IP address or connection type notifications. + // NOTE: Only ignore interfaces not used to connect to the internet. Adding + // interfaces used to connect to the internet can cause critical network + // changed signals to be lost allowing incorrect stale state to persist. + explicit NetworkChangeNotifierLinux( + const base::hash_set<std::string>& ignored_interfaces); private: class Thread; - NetworkChangeNotifierLinux(); ~NetworkChangeNotifierLinux() override; static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsLinux(); diff --git a/net/tools/net_watcher/net_watcher.cc b/net/tools/net_watcher/net_watcher.cc index 1643bc4..8d1d056 100644 --- a/net/tools/net_watcher/net_watcher.cc +++ b/net/tools/net_watcher/net_watcher.cc @@ -14,6 +14,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/strings/string_split.h" #include "base/values.h" #include "build/build_config.h" #include "net/base/network_change_notifier.h" @@ -25,12 +26,22 @@ #include <glib-object.h> #endif +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +#include "net/base/network_change_notifier_linux.h" +#endif + #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" #endif namespace { +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +// Flag to specifies which network interfaces to ignore. Interfaces should +// follow as a comma seperated list. +const char kIgnoreNetifFlag[] = "ignore-netif"; +#endif + // Conversions from various network-related types to string. const char* ConnectionTypeToString( @@ -153,8 +164,25 @@ int main(int argc, char* argv[]) { NetWatcher net_watcher; +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + std::string ignored_netifs_str = + command_line->GetSwitchValueASCII(kIgnoreNetifFlag); + base::hash_set<std::string> ignored_interfaces; + if (!ignored_netifs_str.empty()) { + std::vector<std::string> ignored_netifs; + base::SplitString(ignored_netifs_str, ',', &ignored_netifs); + for (const std::string& ignored_netif : ignored_netifs) { + LOG(INFO) << "Ignoring: " << ignored_netif; + ignored_interfaces.insert(ignored_netif); + } + } + scoped_ptr<net::NetworkChangeNotifier> network_change_notifier( + new net::NetworkChangeNotifierLinux(ignored_interfaces)); +#else scoped_ptr<net::NetworkChangeNotifier> network_change_notifier( net::NetworkChangeNotifier::Create()); +#endif // Use the network loop as the file loop also. scoped_ptr<net::ProxyConfigService> proxy_config_service( |