// 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/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/threading/thread_restrictions.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;
}

// Returns the name for the interface with interface index |interface_index|.
// The return value points to a function-scoped static so it may be changed by
// subsequent calls. This function could be replaced with if_indextoname() but
// net/if.h cannot be mixed with linux/if.h so we'll stick with exclusively
// talking to the kernel and not the C library.
const char* GetInterfaceName(int interface_index) {
  int ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
  if (ioctl_socket < 0)
    return "";
  static struct ifreq ifr;
  memset(&ifr, 0, sizeof(ifr));
  ifr.ifr_ifindex = interface_index;
  int rv = ioctl(ioctl_socket, SIOCGIFNAME, &ifr);
  close(ioctl_socket);
  if (rv != 0)
    return "";
  return ifr.ifr_name;
}

}  // namespace

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),
      is_offline_(true),
      is_offline_initialized_(false),
      is_offline_initialized_cv_(&is_offline_lock_),
      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),
      is_offline_(true),
      is_offline_initialized_(false),
      is_offline_initialized_cv_(&is_offline_lock_),
      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, is_offline_lock_);
    is_offline_initialized_ = true;
    is_offline_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, is_offline_lock_);
  is_offline_ = false;
  is_offline_initialized_ = true;
  is_offline_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, is_offline_lock_);
  // Make sure the initial offline state is set before returning.
  while (!is_offline_initialized_) {
    is_offline_initialized_cv_.Wait();
  }
  // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN.
  // http://crbug.com/160537
  return is_offline_ ? NetworkChangeNotifier::CONNECTION_NONE :
                       NetworkChangeNotifier::CONNECTION_UNKNOWN;
}

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) {
    bool is_offline;
    {
      AddressTrackerAutoLock lock(*this, online_links_lock_);
      is_offline = online_links_.empty();
    }
    AddressTrackerAutoLock lock(*this, is_offline_lock_);
    is_offline_ = is_offline;
  }
}

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))
              *tunnel_changed = true;
          }
        } else {
          AddressTrackerAutoLock lock(*this, online_links_lock_);
          if (online_links_.erase(msg->ifi_index)) {
            *link_changed = true;
            if (IsTunnelInterface(msg))
              *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))
            *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(const struct ifinfomsg* msg) const {
  // Linux kernel drivers/net/tun.c uses "tun" name prefix.
  return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0;
}

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
