// Copyright 2018 The Chromium OS 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 "portier/nd_proxy.h"

#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <base/stl_util.h>

#include "portier/ipv6_util.h"

namespace portier {

using std::shared_ptr;
using std::string;

using brillo::MessageLoop;
using shill::ByteString;

using TaskId = brillo::MessageLoop::TaskId;
using Code = Status::Code;

using FdTaskPair = std::pair<const int32_t, TaskId>;
using NameTaskPair = std::pair<const string, TaskId>;
using NameIfPair = std::pair<const string, shared_ptr<ProxyInterface>>;
using NameNamePair = std::pair<const string, string>;

namespace {

// Specified disable time for proxy interfaces which have been disabled
// for loop prevention purposes.  See RFC 4389 section 4.1.3.3.
constexpr base::TimeDelta kInterfaceDisableTime =
    base::TimeDelta::FromMinutes(60);

}  // namespace

std::unique_ptr<NeighborDiscoveryProxy> NeighborDiscoveryProxy::Create(
    bool nested_mode) {
  auto ndp_ptr = std::unique_ptr<NeighborDiscoveryProxy>(
      new NeighborDiscoveryProxy(nested_mode));
  return ndp_ptr;
}

Status NeighborDiscoveryProxy::ManagerInterface(const string& if_name) {
  if (IsManagingInterface(if_name)) {
    return Status(Code::ALREADY_EXISTS)
           << "The interface " << if_name << " is already being managed";
  }

  auto uif = ProxyInterface::Create(if_name);
  if (!uif) {
    return Status(Code::UNEXPECTED_FAILURE)
           << "Failed to create proxy interface " << if_name;
  }

  shared_ptr<ProxyInterface> proxy_if(std::move(uif));
  proxy_ifs_.insert(NameIfPair(if_name, proxy_if));

  // Setup event handler.
  const int nd_fd = proxy_if->GetNDFd();

  auto nd_task = base::FileDescriptorWatcher::WatchReadable(
      nd_fd,
      base::BindRepeating(&NeighborDiscoveryProxy::HandleNeighborDiscoverPacket,
                          base::Unretained(this), if_name));
  fd_tasks_.emplace(nd_fd, std::move(nd_task));

  const int ipv6_fd = proxy_if->GetIPv6Fd();
  auto ipv6_task = base::FileDescriptorWatcher::WatchReadable(
      ipv6_fd, base::BindRepeating(&NeighborDiscoveryProxy::HandleIPv6Packet,
                                   base::Unretained(this), if_name));
  fd_tasks_.emplace(ipv6_fd, std::move(ipv6_task));

  LOG(INFO) << "ND Proxy is now managing interface " << if_name;
  return Status();
}

Status NeighborDiscoveryProxy::ReleaseInterface(const string& if_name) {
  auto it = proxy_ifs_.find(if_name);
  if (it == proxy_ifs_.end()) {
    return Status(Code::DOES_NOT_EXIST)
           << "The interface " << if_name << " is not being managed";
  }

  auto proxy_if = it->second;

  // Remove from proxy group if member.
  if (proxy_if->HasGroup()) {
    auto group = proxy_if->GetGroup();
    group->RemoveMember(proxy_if);
  }

  // Cancel all associated tasks.
  fd_tasks_.erase(proxy_if->GetNDFd());
  fd_tasks_.erase(proxy_if->GetIPv6Fd());
  const auto loop_pair = loop_tasks_.find(if_name);
  if (loop_pair != loop_tasks_.end()) {
    MessageLoop::current()->CancelTask(loop_pair->second);
    loop_tasks_.erase(loop_pair);
  }

  // Remove interface from interface list.
  proxy_ifs_.erase(it);
  DCHECK_EQ(proxy_if.use_count(), 1);
  proxy_if.reset();

  LOG(INFO) << "ND Proxy has stopped managing interface " << if_name;
  return Status();
}

bool NeighborDiscoveryProxy::IsManagingInterface(const string& if_name) const {
  return base::ContainsKey(proxy_ifs_, if_name);
}

Status NeighborDiscoveryProxy::CreateProxyGroup(const string& pg_name) {
  const Status create_status = group_manager_.CreateGroup(pg_name);
  if (create_status) {
    LOG(INFO) << "Created proxy group " << pg_name;
  }
  return create_status;
}

Status NeighborDiscoveryProxy::ReleaseProxyGroup(const string& pg_name) {
  const Status release_status = group_manager_.ReleaseGroup(pg_name);
  if (release_status) {
    LOG(INFO) << "Released proxy group " << pg_name;
  }
  return release_status;
}

bool NeighborDiscoveryProxy::HasProxyGroup(const string& pg_name) const {
  return group_manager_.HasGroup(pg_name);
}

// Membership.
Status NeighborDiscoveryProxy::AddToGroup(const string& if_name,
                                          const string& pg_name,
                                          bool as_upstream) {
  auto proxy_if = GetInterface(if_name);
  if (!proxy_if) {
    return Status(Code::DOES_NOT_EXIST)
           << "Interface " << if_name << " does not exists";
  }
  auto group = group_manager_.GetGroup(pg_name);
  if (!group) {
    return Status(Code::DOES_NOT_EXIST)
           << "Proxy group " << pg_name << " does not exists";
  }
  if (proxy_if->HasGroup()) {
    return Status(Code::ALREADY_EXISTS)
           << "Interface " << if_name << " is already a member of group "
           << proxy_if->GetGroup()->name();
  }
  if (!group->AddMember(proxy_if)) {
    return Status(Code::UNEXPECTED_FAILURE)
           << "Failed to add interface " << if_name << " to proxy group "
           << pg_name;
  }
  if (as_upstream) {
    group->SetUpstream(proxy_if);
  }
  return Status();
}

Status NeighborDiscoveryProxy::RemoveFromGroup(const string& if_name) {
  auto proxy_if = GetInterface(if_name);
  if (!proxy_if) {
    return Status(Code::DOES_NOT_EXIST)
           << "Interface " << if_name << " does not exists";
  }
  auto group = proxy_if->GetGroup();
  if (!group) {
    return Status(Code::DOES_NOT_EXIST)
           << "Interface " << if_name << " is not a member of any group";
  }
  if (!group->RemoveMember(proxy_if)) {
    return Status(Code::UNEXPECTED_FAILURE)
           << "Failed to remove interface " << if_name << " from proxy group "
           << group->name();
  }
  // Clear any loop issue.  Should be done after so that no packet is
  // proxied.
  const auto loop_pair = loop_tasks_.find(if_name);
  if (loop_pair != loop_tasks_.end()) {
    MessageLoop::current()->CancelTask(loop_pair->second);
    loop_tasks_.erase(loop_pair);
  }
  return Status();
}

Status NeighborDiscoveryProxy::SetAsUpstream(const std::string& if_name) {
  auto proxy_if = GetInterface(if_name);
  if (!proxy_if) {
    return Status(Code::DOES_NOT_EXIST)
           << "Interface " << if_name << " does not exists";
  }
  auto group = proxy_if->GetGroup();
  if (!group) {
    return Status(Code::DOES_NOT_EXIST)
           << "Interface " << if_name << " is not a member of any group";
  }
  group->SetUpstream(proxy_if);
  return Status();
}

// private.
shared_ptr<ProxyInterface> NeighborDiscoveryProxy::GetInterface(
    const string& if_name) const {
  auto it = proxy_ifs_.find(if_name);
  if (it != proxy_ifs_.cend()) {
    return it->second;
  }
  return nullptr;
}

// private.
void NeighborDiscoveryProxy::HandleLoopDetection(
    shared_ptr<ProxyInterface> proxy_if) {
  DCHECK(proxy_if);
  DCHECK(proxy_if->HasGroup());
  // Clear old task, might be left over from a previous loop detection.
  const auto loop_pair = loop_tasks_.find(proxy_if->name());
  if (loop_pair != loop_tasks_.end()) {
    MessageLoop::current()->CancelTask(loop_pair->second);
    loop_tasks_.erase(loop_pair);
  }
  proxy_if->MarkLoopDetected();
  const TaskId loop_task_id = MessageLoop::current()->PostDelayedTask(
      base::Bind(&NeighborDiscoveryProxy::LoopTimeOut, base::Unretained(this),
                 proxy_if->name(), proxy_if->GetGroup()->name()),
      kInterfaceDisableTime);
  loop_tasks_.insert(NameTaskPair(proxy_if->name(), loop_task_id));
}

// Packet event handlers.

// private.
void NeighborDiscoveryProxy::HandleNeighborDiscoverPacket(string if_name) {
  auto proxy_if = GetInterface(if_name);
  if (!proxy_if) {
    // Possible that interface was removed while the call back was queued.
    return;
  }
  if (!proxy_if->IsEnabled()) {
    proxy_if->DiscardNeighborDiscoveryInput();
  }
  if (!proxy_if->HasGroup()) {
    LOG(WARNING) << "Proxy interface " << proxy_if->name()
                 << " was enabled, but not part of a group";
    proxy_if->MarkGroupless();
    proxy_if->DiscardNeighborDiscoveryInput();
    return;
  }

  IPv6EtherHeader header_fields;
  NeighborDiscoveryMessage nd_message;
  Status receive_status =
      proxy_if->ReceiveNeighborDiscoveryMessage(&header_fields, &nd_message);

  if (receive_status.code() == Code::RESULT_UNAVAILABLE) {
    // Possible if a zero packet was received.
    return;
  }
  if (!receive_status) {
    receive_status << "Failed to receive ND on if " << proxy_if->name();
    LOG(ERROR) << receive_status;
    return;
  }

  // Check if locally destined.
  if (proxy_if->HasIPv6Address(header_fields.destination_address)) {
    // Don't need to handle locally destined packets.
    return;
  }

  ProxyGroup* group = proxy_if->GetGroup();
  // We already did a check for proxy_if->HasGroup().
  CHECK(group);

  // Loop prevention check.
  const NeighborDiscoveryMessage::Type nd_type = nd_message.type();
  if (nd_type == NeighborDiscoveryMessage::kTypeRouterAdvert) {
    if (!proxy_if->IsUpstream()) {
      // Router advertisements should not be received on a downstream
      // interface.
      LOG(WARNING) << "An RA was received on downstream interface "
                   << proxy_if->name();
      HandleLoopDetection(proxy_if);
      return;
    }
    // else, interface is upstream.

    // Check if there is a potential loop.
    bool proxy_flag = false;
    nd_message.GetProxyFlag(&proxy_flag);
    if (proxy_flag && !IsNested()) {
      // If the daemon is not running in nested mode, than the proxy bit
      // indicates a loop on this interface.
      LOG(WARNING) << "A proxied RA set received on interface "
                   << proxy_if->name();
      HandleLoopDetection(proxy_if);
      return;
    }
  }

  // Handle the case of multicast.
  if (IPv6AddressIsMulticast(header_fields.destination_address)) {
    LLAddress destination_ll_address;
    IPv6GetMulticastLinkLayerAddress(header_fields.destination_address,
                                     &destination_ll_address);
    LOG(INFO) << "Multicast ND Msg (" << nd_message.type() << ") "
              << proxy_if->name() << " from "
              << header_fields.source_address.ToString();
    // Multicast, then forward packet to all interfaces other than
    // the one received on.
    auto group_members = group->GetMembers();
    for (auto& group_if : group_members) {
      if (group_if == proxy_if) {
        // Don't proxy out the same interface.
        continue;
      }
      if (!group_if->IsEnabled()) {
        continue;
      }

      const Status send_status = group_if->ProxyNeighborDiscoveryMessage(
          header_fields, destination_ll_address, nd_message);
      if (!send_status) {
        LOG(ERROR) << send_status;
      }
    }
    return;
  }

  NeighborCacheEntry out_entry;
  if (!neighbor_cache_.GetEntry(header_fields.destination_address,
                                group->name(), &out_entry)) {
    // TODO(siquit): Queue ND packet and perform neighbor discovery.
    LOG(INFO) << "No neighbor for "
              << header_fields.destination_address.ToString();
    return;
  }

  shared_ptr<ProxyInterface> out_if = GetInterface(out_entry.if_name);

  if (!out_if || !out_if->IsEnabled()) {
    return;
  }

  if (out_if->name() == proxy_if->name()) {
    // Don't proxy out the same interface.  Should be silently dropped.
    return;
  }

  LOG(INFO) << "Unicast ND Msg (" << nd_message.type() << ") "
            << proxy_if->name() << " from "
            << header_fields.source_address.ToString() << " out "
            << out_if->name() << " to "
            << header_fields.destination_address.ToString();

  Status send_status = out_if->ProxyNeighborDiscoveryMessage(
      header_fields, out_entry.ll_address, nd_message);
  if (!send_status) {
    send_status << "Failed to proxy from " << proxy_if->name() << " to "
                << out_if->name();
    LOG(ERROR) << send_status;
  }
}

void NeighborDiscoveryProxy::HandleIPv6Packet(string if_name) {
  auto proxy_if = GetInterface(if_name);
  if (!proxy_if) {
    // Possible that interface was removed while the call back was queued.
    return;
  }
  if (!proxy_if->IsEnabled()) {
    proxy_if->DiscardIPv6Input();
  }
  if (!proxy_if->HasGroup()) {
    LOG(WARNING) << "Proxy interface " << proxy_if->name()
                 << " was enabled, but not part of a group";
    proxy_if->MarkGroupless();
    proxy_if->DiscardIPv6Input();
    return;
  }

  IPv6EtherHeader header_fields;
  ByteString payload;
  Status receive_status = proxy_if->ReceiveIPv6Packet(&header_fields, &payload);
  if (receive_status.code() == Code::RESULT_UNAVAILABLE) {
    // Possible if a zero packet was received.
    return;
  }
  if (!receive_status) {
    receive_status << "Failed to receive ND on if " << proxy_if->name();
    LOG(ERROR) << receive_status;
    return;
  }

  // Check if locally destined.
  if (proxy_if->HasIPv6Address(header_fields.destination_address)) {
    // Don't need to handle locally destined packets.
    return;
  }

  ProxyGroup* group = proxy_if->GetGroup();
  // We already did a check for proxy_if->HasGroup().
  CHECK(group);

  // If multicast, then forward packet to all interfaces other than
  // the one received on.
  if (IPv6AddressIsMulticast(header_fields.destination_address)) {
    LLAddress destination_ll_address;
    IPv6GetMulticastLinkLayerAddress(header_fields.destination_address,
                                     &destination_ll_address);

    LOG(INFO) << "Multicast IPv6 Packet " << proxy_if->name() << " from "
              << header_fields.source_address.ToString();
    // Multicast, then forward packet to all interfaces other than
    // the one received on.
    auto group_members = group->GetMembers();
    for (auto& group_if : group_members) {
      if (group_if == proxy_if) {
        // Don't proxy out the same interface.
        continue;
      }
      if (!group_if->IsEnabled()) {
        continue;
      }

      const Status send_status = group_if->SendIPv6Packet(
          header_fields, destination_ll_address, payload);
      if (!send_status) {
        LOG(ERROR) << send_status;
      }
    }
    return;
  }

  NeighborCacheEntry out_entry;
  if (!neighbor_cache_.GetEntry(header_fields.destination_address,
                                group->name(), &out_entry)) {
    // TODO(sigquit): Queue IP packet and perform neighbor discovery.
    return;
  }

  shared_ptr<ProxyInterface> out_if = GetInterface(out_entry.if_name);
  if (!out_if || !out_if->IsEnabled()) {
    return;
  }

  if (out_if->name() == proxy_if->name()) {
    // Don't proxy out the same interface.  Should be silently dropped.
    return;
  }
  LOG(INFO) << "Unicast IPv6 Packet " << proxy_if->name() << " from "
            << header_fields.source_address.ToString() << " out "
            << out_if->name() << " to "
            << header_fields.destination_address.ToString();

  Status send_status =
      out_if->SendIPv6Packet(header_fields, out_entry.ll_address, payload);
  if (!send_status) {
    send_status << "Failed to proxy from " << proxy_if->name() << " to "
                << out_if->name();
    LOG(ERROR) << send_status;
  }
}

void NeighborDiscoveryProxy::LoopTimeOut(string if_name, string pg_name) {
  auto proxy_if = GetInterface(if_name);
  if (!proxy_if || !proxy_if->HasGroup() ||
      proxy_if->GetGroup()->name() != pg_name ||
      !base::ContainsKey(loop_tasks_, if_name)) {
    return;
  }
  proxy_if->ClearLoopDetected();
}

}  // namespace portier
