summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/android/network_change_notifier_android.cc3
-rw-r--r--net/base/address_tracker_linux.cc32
-rw-r--r--net/base/address_tracker_linux.h15
-rw-r--r--net/base/address_tracker_linux_unittest.cc199
-rw-r--r--net/base/network_change_notifier.cc2
-rw-r--r--net/base/network_change_notifier_linux.cc17
-rw-r--r--net/base/network_change_notifier_linux.h10
-rw-r--r--net/tools/net_watcher/net_watcher.cc28
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(