Index: net/base/address_tracker_linux.cc |
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc |
index 367381366954f3280e9171f5d93405f05ed667d7..afed4d56fa674a40ebf2ae9f25362d0f75abda3f 100644 |
--- a/net/base/address_tracker_linux.cc |
+++ b/net/base/address_tracker_linux.cc |
@@ -116,7 +116,7 @@ AddressTrackerLinux::~AddressTrackerLinux() { |
CloseSocket(); |
} |
-void AddressTrackerLinux::Init() { |
+void AddressTrackerLinux::Init(bool track) { |
netlink_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); |
if (netlink_fd_ < 0) { |
PLOG(ERROR) << "Could not create NETLINK socket"; |
@@ -124,20 +124,24 @@ void AddressTrackerLinux::Init() { |
return; |
} |
- // Request notifications. |
- struct sockaddr_nl addr = {}; |
- addr.nl_family = AF_NETLINK; |
- addr.nl_pid = getpid(); |
- // TODO(szym): Track RTMGRP_LINK as well for ifi_type, http://crbug.com/113993 |
- addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | |
- RTMGRP_LINK; |
- int rv = bind(netlink_fd_, |
- reinterpret_cast<struct sockaddr*>(&addr), |
- sizeof(addr)); |
- if (rv < 0) { |
- PLOG(ERROR) << "Could not bind NETLINK socket"; |
- AbortAndForceOnline(); |
- return; |
+ int rv; |
+ |
+ if (track) { |
+ // Request notifications. |
+ struct sockaddr_nl addr = {}; |
+ addr.nl_family = AF_NETLINK; |
+ addr.nl_pid = getpid(); |
+ // TODO(szym): Track RTMGRP_LINK as well for ifi_type, |
+ // http://crbug.com/113993 |
+ addr.nl_groups = |
+ RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | RTMGRP_LINK; |
+ rv = bind( |
+ netlink_fd_, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)); |
+ if (rv < 0) { |
+ PLOG(ERROR) << "Could not bind NETLINK socket"; |
+ AbortAndForceOnline(); |
+ return; |
+ } |
} |
// Request dump of addresses. |
@@ -191,12 +195,14 @@ void AddressTrackerLinux::Init() { |
is_offline_initialized_cv_.Signal(); |
} |
- rv = base::MessageLoopForIO::current()->WatchFileDescriptor( |
- netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this); |
- if (rv < 0) { |
- PLOG(ERROR) << "Could not watch NETLINK socket"; |
- AbortAndForceOnline(); |
- return; |
+ if (track) { |
+ rv = base::MessageLoopForIO::current()->WatchFileDescriptor( |
+ netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this); |
+ if (rv < 0) { |
+ PLOG(ERROR) << "Could not watch NETLINK socket"; |
+ AbortAndForceOnline(); |
+ return; |
+ } |
} |
} |
@@ -213,6 +219,11 @@ AddressTrackerLinux::AddressMap AddressTrackerLinux::GetAddressMap() const { |
return address_map_; |
} |
+base::hash_set<int> AddressTrackerLinux::GetOnlineLinks() const { |
+ base::AutoLock lock(online_links_lock_); |
+ return online_links_; |
+} |
+ |
NetworkChangeNotifier::ConnectionType |
AddressTrackerLinux::GetCurrentConnectionType() { |
// http://crbug.com/125097 |
@@ -254,10 +265,15 @@ void AddressTrackerLinux::ReadMessages(bool* address_changed, |
return; |
} |
HandleMessage(buffer, rv, address_changed, link_changed, tunnel_changed); |
- }; |
+ } |
if (*link_changed) { |
+ bool is_offline; |
+ { |
+ base::AutoLock lock(online_links_lock_); |
+ is_offline = online_links_.empty(); |
+ } |
base::AutoLock lock(is_offline_lock_); |
- is_offline_ = online_links_.empty(); |
+ is_offline_ = is_offline; |
} |
} |
@@ -319,12 +335,14 @@ void AddressTrackerLinux::HandleMessage(char* buffer, |
reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); |
if (!(msg->ifi_flags & IFF_LOOPBACK) && (msg->ifi_flags & IFF_UP) && |
(msg->ifi_flags & IFF_LOWER_UP) && (msg->ifi_flags & IFF_RUNNING)) { |
+ base::AutoLock lock(online_links_lock_); |
if (online_links_.insert(msg->ifi_index).second) { |
*link_changed = true; |
if (IsTunnelInterface(msg)) |
*tunnel_changed = true; |
} |
} else { |
+ base::AutoLock lock(online_links_lock_); |
if (online_links_.erase(msg->ifi_index)) { |
*link_changed = true; |
if (IsTunnelInterface(msg)) |
@@ -335,6 +353,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer, |
case RTM_DELLINK: { |
const struct ifinfomsg* msg = |
reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); |
+ base::AutoLock lock(online_links_lock_); |
if (online_links_.erase(msg->ifi_index)) { |
*link_changed = true; |
if (IsTunnelInterface(msg)) |