Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Unified Diff: net/base/address_tracker_linux.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/address_tracker_linux.h ('k') | net/base/address_tracker_linux_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/address_tracker_linux.cc
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc
deleted file mode 100644
index 731bf4f97785ebf45837c35a4fe4033bd4ffffff..0000000000000000000000000000000000000000
--- a/net/base/address_tracker_linux.cc
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/base/address_tracker_linux.h"
-
-#include <errno.h>
-#include <linux/if.h>
-#include <sys/ioctl.h>
-
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/threading/thread_restrictions.h"
-#include "net/base/net_util_linux.h"
-
-namespace net {
-namespace internal {
-
-namespace {
-
-// Retrieves address from NETLINK address message.
-// Sets |really_deprecated| for IPv6 addresses with preferred lifetimes of 0.
-bool GetAddress(const struct nlmsghdr* header,
- IPAddressNumber* out,
- bool* really_deprecated) {
- if (really_deprecated)
- *really_deprecated = false;
- const struct ifaddrmsg* msg =
- reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header));
- size_t address_length = 0;
- switch (msg->ifa_family) {
- case AF_INET:
- address_length = kIPv4AddressSize;
- break;
- case AF_INET6:
- address_length = kIPv6AddressSize;
- break;
- default:
- // Unknown family.
- return false;
- }
- // Use IFA_ADDRESS unless IFA_LOCAL is present. This behavior here is based on
- // getaddrinfo in glibc (check_pf.c). Judging from kernel implementation of
- // NETLINK, IPv4 addresses have only the IFA_ADDRESS attribute, while IPv6
- // have the IFA_LOCAL attribute.
- unsigned char* address = NULL;
- unsigned char* local = NULL;
- size_t length = IFA_PAYLOAD(header);
- for (const struct rtattr* attr =
- reinterpret_cast<const struct rtattr*>(IFA_RTA(msg));
- RTA_OK(attr, length);
- attr = RTA_NEXT(attr, length)) {
- switch (attr->rta_type) {
- case IFA_ADDRESS:
- DCHECK_GE(RTA_PAYLOAD(attr), address_length);
- address = reinterpret_cast<unsigned char*>(RTA_DATA(attr));
- break;
- case IFA_LOCAL:
- DCHECK_GE(RTA_PAYLOAD(attr), address_length);
- local = reinterpret_cast<unsigned char*>(RTA_DATA(attr));
- break;
- case IFA_CACHEINFO: {
- const struct ifa_cacheinfo *cache_info =
- reinterpret_cast<const struct ifa_cacheinfo*>(RTA_DATA(attr));
- if (really_deprecated)
- *really_deprecated = (cache_info->ifa_prefered == 0);
- } break;
- default:
- break;
- }
- }
- if (local)
- address = local;
- if (!address)
- return false;
- out->assign(address, address + address_length);
- return true;
-}
-
-} // namespace
-
-// static
-char* AddressTrackerLinux::GetInterfaceName(int interface_index, char* buf) {
- memset(buf, 0, IFNAMSIZ);
- base::ScopedFD ioctl_socket(socket(AF_INET, SOCK_DGRAM, 0));
- if (!ioctl_socket.is_valid())
- return buf;
-
- struct ifreq ifr = {};
- ifr.ifr_ifindex = interface_index;
-
- if (ioctl(ioctl_socket.get(), SIOCGIFNAME, &ifr) == 0)
- strncpy(buf, ifr.ifr_name, IFNAMSIZ - 1);
- return buf;
-}
-
-AddressTrackerLinux::AddressTrackerLinux()
- : get_interface_name_(GetInterfaceName),
- address_callback_(base::Bind(&base::DoNothing)),
- link_callback_(base::Bind(&base::DoNothing)),
- tunnel_callback_(base::Bind(&base::DoNothing)),
- netlink_fd_(-1),
- connection_type_initialized_(false),
- connection_type_initialized_cv_(&connection_type_lock_),
- current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE),
- tracking_(false) {
-}
-
-AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback,
- const base::Closure& link_callback,
- const base::Closure& tunnel_callback)
- : get_interface_name_(GetInterfaceName),
- address_callback_(address_callback),
- link_callback_(link_callback),
- tunnel_callback_(tunnel_callback),
- netlink_fd_(-1),
- connection_type_initialized_(false),
- connection_type_initialized_cv_(&connection_type_lock_),
- current_connection_type_(NetworkChangeNotifier::CONNECTION_NONE),
- tracking_(true) {
- DCHECK(!address_callback.is_null());
- DCHECK(!link_callback.is_null());
-}
-
-AddressTrackerLinux::~AddressTrackerLinux() {
- CloseSocket();
-}
-
-void AddressTrackerLinux::Init() {
- netlink_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (netlink_fd_ < 0) {
- PLOG(ERROR) << "Could not create NETLINK socket";
- AbortAndForceOnline();
- return;
- }
-
- int rv;
-
- if (tracking_) {
- // 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.
- struct sockaddr_nl peer = {};
- peer.nl_family = AF_NETLINK;
-
- struct {
- struct nlmsghdr header;
- struct rtgenmsg msg;
- } request = {};
-
- request.header.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg));
- request.header.nlmsg_type = RTM_GETADDR;
- request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- request.header.nlmsg_pid = getpid();
- request.msg.rtgen_family = AF_UNSPEC;
-
- rv = HANDLE_EINTR(sendto(netlink_fd_, &request, request.header.nlmsg_len,
- 0, reinterpret_cast<struct sockaddr*>(&peer),
- sizeof(peer)));
- if (rv < 0) {
- PLOG(ERROR) << "Could not send NETLINK request";
- AbortAndForceOnline();
- return;
- }
-
- // Consume pending message to populate the AddressMap, but don't notify.
- // Sending another request without first reading responses results in EBUSY.
- bool address_changed;
- bool link_changed;
- bool tunnel_changed;
- ReadMessages(&address_changed, &link_changed, &tunnel_changed);
-
- // Request dump of link state
- request.header.nlmsg_type = RTM_GETLINK;
-
- rv = HANDLE_EINTR(sendto(netlink_fd_, &request, request.header.nlmsg_len, 0,
- reinterpret_cast<struct sockaddr*>(&peer),
- sizeof(peer)));
- if (rv < 0) {
- PLOG(ERROR) << "Could not send NETLINK request";
- AbortAndForceOnline();
- return;
- }
-
- // Consume pending message to populate links_online_, but don't notify.
- ReadMessages(&address_changed, &link_changed, &tunnel_changed);
- {
- AddressTrackerAutoLock lock(*this, connection_type_lock_);
- connection_type_initialized_ = true;
- connection_type_initialized_cv_.Signal();
- }
-
- if (tracking_) {
- 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;
- }
- }
-}
-
-void AddressTrackerLinux::AbortAndForceOnline() {
- CloseSocket();
- AddressTrackerAutoLock lock(*this, connection_type_lock_);
- current_connection_type_ = NetworkChangeNotifier::CONNECTION_UNKNOWN;
- connection_type_initialized_ = true;
- connection_type_initialized_cv_.Signal();
-}
-
-AddressTrackerLinux::AddressMap AddressTrackerLinux::GetAddressMap() const {
- AddressTrackerAutoLock lock(*this, address_map_lock_);
- return address_map_;
-}
-
-base::hash_set<int> AddressTrackerLinux::GetOnlineLinks() const {
- AddressTrackerAutoLock lock(*this, online_links_lock_);
- return online_links_;
-}
-
-NetworkChangeNotifier::ConnectionType
-AddressTrackerLinux::GetCurrentConnectionType() {
- // http://crbug.com/125097
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- AddressTrackerAutoLock lock(*this, connection_type_lock_);
- // Make sure the initial connection type is set before returning.
- while (!connection_type_initialized_) {
- connection_type_initialized_cv_.Wait();
- }
- return current_connection_type_;
-}
-
-void AddressTrackerLinux::ReadMessages(bool* address_changed,
- bool* link_changed,
- bool* tunnel_changed) {
- *address_changed = false;
- *link_changed = false;
- *tunnel_changed = false;
- char buffer[4096];
- bool first_loop = true;
- for (;;) {
- int rv = HANDLE_EINTR(recv(netlink_fd_,
- buffer,
- sizeof(buffer),
- // Block the first time through loop.
- first_loop ? 0 : MSG_DONTWAIT));
- first_loop = false;
- if (rv == 0) {
- LOG(ERROR) << "Unexpected shutdown of NETLINK socket.";
- return;
- }
- if (rv < 0) {
- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
- break;
- PLOG(ERROR) << "Failed to recv from netlink socket";
- return;
- }
- HandleMessage(buffer, rv, address_changed, link_changed, tunnel_changed);
- }
- if (*link_changed || *address_changed)
- UpdateCurrentConnectionType();
-}
-
-void AddressTrackerLinux::HandleMessage(char* buffer,
- size_t length,
- bool* address_changed,
- bool* link_changed,
- bool* tunnel_changed) {
- DCHECK(buffer);
- for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer);
- NLMSG_OK(header, length);
- header = NLMSG_NEXT(header, length)) {
- switch (header->nlmsg_type) {
- case NLMSG_DONE:
- return;
- case NLMSG_ERROR: {
- const struct nlmsgerr* msg =
- reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(header));
- LOG(ERROR) << "Unexpected netlink error " << msg->error << ".";
- } return;
- case RTM_NEWADDR: {
- IPAddressNumber address;
- bool really_deprecated;
- 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
- // the deprecated flag but both with preferred lifetimes of 0. Avoid
- // interpretting this as an actual change by canonicalizing the two
- // messages by setting the deprecated flag based on the preferred
- // lifetime also. http://crbug.com/268042
- if (really_deprecated)
- msg->ifa_flags |= IFA_F_DEPRECATED;
- // Only indicate change if the address is new or ifaddrmsg info has
- // changed.
- AddressMap::iterator it = address_map_.find(address);
- if (it == address_map_.end()) {
- address_map_.insert(it, std::make_pair(address, *msg));
- *address_changed = true;
- } else if (memcmp(&it->second, msg, sizeof(*msg))) {
- it->second = *msg;
- *address_changed = true;
- }
- }
- } break;
- case RTM_DELADDR: {
- IPAddressNumber address;
- if (GetAddress(header, &address, NULL)) {
- AddressTrackerAutoLock lock(*this, address_map_lock_);
- if (address_map_.erase(address))
- *address_changed = true;
- }
- } break;
- case RTM_NEWLINK: {
- const struct ifinfomsg* msg =
- 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)) {
- AddressTrackerAutoLock lock(*this, online_links_lock_);
- if (online_links_.insert(msg->ifi_index).second) {
- *link_changed = true;
- if (IsTunnelInterface(msg->ifi_index))
- *tunnel_changed = true;
- }
- } else {
- AddressTrackerAutoLock lock(*this, online_links_lock_);
- if (online_links_.erase(msg->ifi_index)) {
- *link_changed = true;
- if (IsTunnelInterface(msg->ifi_index))
- *tunnel_changed = true;
- }
- }
- } break;
- case RTM_DELLINK: {
- const struct ifinfomsg* msg =
- reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header));
- AddressTrackerAutoLock lock(*this, online_links_lock_);
- if (online_links_.erase(msg->ifi_index)) {
- *link_changed = true;
- if (IsTunnelInterface(msg->ifi_index))
- *tunnel_changed = true;
- }
- } break;
- default:
- break;
- }
- }
-}
-
-void AddressTrackerLinux::OnFileCanReadWithoutBlocking(int fd) {
- DCHECK_EQ(netlink_fd_, fd);
- bool address_changed;
- bool link_changed;
- bool tunnel_changed;
- ReadMessages(&address_changed, &link_changed, &tunnel_changed);
- if (address_changed)
- address_callback_.Run();
- if (link_changed)
- link_callback_.Run();
- if (tunnel_changed)
- tunnel_callback_.Run();
-}
-
-void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {}
-
-void AddressTrackerLinux::CloseSocket() {
- if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0)
- PLOG(ERROR) << "Could not close NETLINK socket.";
- netlink_fd_ = -1;
-}
-
-bool AddressTrackerLinux::IsTunnelInterface(int interface_index) const {
- // Linux kernel drivers/net/tun.c uses "tun" name prefix.
- char buf[IFNAMSIZ] = {0};
- return strncmp(get_interface_name_(interface_index, buf), "tun", 3) == 0;
-}
-
-void AddressTrackerLinux::UpdateCurrentConnectionType() {
- AddressTrackerLinux::AddressMap address_map = GetAddressMap();
- base::hash_set<int> online_links = GetOnlineLinks();
-
- // Strip out tunnel interfaces from online_links
- for (base::hash_set<int>::const_iterator it = online_links.begin();
- it != online_links.end();) {
- if (IsTunnelInterface(*it)) {
- base::hash_set<int>::const_iterator tunnel_it = it;
- ++it;
- online_links.erase(*tunnel_it);
- } else {
- ++it;
- }
- }
-
- NetworkInterfaceList networks;
- NetworkChangeNotifier::ConnectionType type =
- NetworkChangeNotifier::CONNECTION_NONE;
- if (GetNetworkListImpl(&networks, 0, online_links, address_map,
- get_interface_name_)) {
- type = NetworkChangeNotifier::ConnectionTypeFromInterfaceList(networks);
- } else {
- type = online_links.empty() ? NetworkChangeNotifier::CONNECTION_NONE
- : NetworkChangeNotifier::CONNECTION_UNKNOWN;
- }
-
- AddressTrackerAutoLock lock(*this, connection_type_lock_);
- current_connection_type_ = type;
-}
-
-AddressTrackerLinux::AddressTrackerAutoLock::AddressTrackerAutoLock(
- const AddressTrackerLinux& tracker,
- base::Lock& lock)
- : tracker_(tracker), lock_(lock) {
- if (tracker_.tracking_) {
- lock_.Acquire();
- } else {
- DCHECK(tracker_.thread_checker_.CalledOnValidThread());
- }
-}
-
-AddressTrackerLinux::AddressTrackerAutoLock::~AddressTrackerAutoLock() {
- if (tracker_.tracking_) {
- lock_.AssertAcquired();
- lock_.Release();
- }
-}
-
-} // namespace internal
-} // namespace net
« no previous file with comments | « net/base/address_tracker_linux.h ('k') | net/base/address_tracker_linux_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698