// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "patchpanel/clat_service.h"

#include <sys/types.h>

#include <optional>
#include <string>
#include <vector>

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/functional/callback_helpers.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/rand_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/files/file_util.h>
#include <brillo/process/process.h>
#include <chromeos/net-base/ipv4_address.h>
#include <chromeos/net-base/ipv6_address.h>
#include <chromeos/net-base/process_manager.h>
#include <chromeos/net-base/technology.h>

#include "patchpanel/address_manager.h"
#include "patchpanel/datapath.h"
#include "patchpanel/iptables.h"
#include "patchpanel/shill_client.h"
#include "patchpanel/system.h"

namespace patchpanel {

namespace {
constexpr char kTaygaBinaryPath[] = "/usr/sbin/tayga";
constexpr char kTaygaConfigFilePath[] = "/run/tayga/tayga.conf";
// Proposd in RFC 6052.
const net_base::IPv6CIDR kWellKnownNAT64Prefix =
    *net_base::IPv6CIDR::CreateFromStringAndPrefix("64:ff9b::", 96);
// Proposed in RFC 7335. This address is assigned to the tun device and used by
// IPv4-only applications to communicate with external IPv4 hosts.
const net_base::IPv4CIDR kTunnelDeviceIPv4CIDR =
    *net_base::IPv4CIDR::CreateFromStringAndPrefix("192.0.0.1", 29);
// Proposed in RFC 7335. This address is assigned to the TAYGA process and used
// for emitting ICMPv4 errors back to the host.
const net_base::IPv4CIDR kTaygaIPv4CIDR =
    *net_base::IPv4CIDR::CreateFromStringAndPrefix("192.0.0.2", 29);

constexpr char kTunnelDeviceIfName[] = "tun_nat64";
constexpr char kTaygaConfigTemplate[] = R"(tun-device $1
ipv4-addr $2
prefix $3
map $4 $5
)";

// ID for the routing table used for CLAT default routes. This is a contracted
// value with shill.
// c.f. shill/network/network_applier.cc
constexpr int kClatRoutingTableId = 249;

bool RemoveConfigFileIfExists(const base::FilePath& conf_file_path) {
  if (!base::PathExists(conf_file_path)) {
    return true;
  }
  if (!brillo::DeletePathRecursively(conf_file_path)) {
    PLOG(ERROR) << "Failed to delete file " << conf_file_path;
    return false;
  }
  return true;
}

bool NeedsClat(const ShillClient::Device& device) {
  return device.IsIPv6Only() &&
         device.technology != net_base::Technology::kVPN &&
         device.technology != net_base::Technology::kWiFiDirect;
}

}  // namespace

ClatService::ClatService(Datapath* datapath,
                         net_base::ProcessManager* process_manager,
                         System* system)
    : datapath_(datapath), process_manager_(process_manager), system_(system) {
  DCHECK(datapath);
  DCHECK(process_manager);
  DCHECK(system);
}

ClatService::~ClatService() {
  StopClat();
}

void ClatService::Enable() {
  if (is_enabled_) {
    return;
  }

  is_enabled_ = true;
  // Starts CLAT immediately, if the default network is CLAT-eligible when it
  // gets enabled.
  if (clat_running_device_) {
    StartClat(clat_running_device_.value());
  }
}

void ClatService::Disable() {
  if (!is_enabled_) {
    return;
  }
  // We keep `clat_running_device_` here because we want to start CLAT
  // immediately after the feature is enabled again.
  StopClat(/*clear_running_device=*/false);

  is_enabled_ = false;
}

void ClatService::OnShillDefaultLogicalDeviceChanged(
    const ShillClient::Device* new_device,
    const ShillClient::Device* prev_device) {
  bool need_stop =
      clat_running_device_ && !(new_device && IsClatRunningDevice(*new_device));

  if (need_stop) {
    StopClat();
  }

  // CLAT should be started when CLAT is not running and the new default logical
  // device is IPv6-only.
  bool need_start =
      new_device && !clat_running_device_ && NeedsClat(*new_device);

  if (need_start) {
    StartClat(*new_device);
  }

  return;
}

// TODO(b/278970851): Add delay between the occurrence of this event and the
// execution of StartClat().
// https://chromium-review.googlesource.com/c/chromiumos/platform2/+/4803285/comment/ff1aa754_26e63d28/
void ClatService::OnDefaultLogicalDeviceIPConfigChanged(
    const ShillClient::Device& default_logical_device) {
  if (!clat_running_device_) {
    if (NeedsClat(default_logical_device)) {
      StartClat(default_logical_device);
    }
    return;
  }

  // It is unexpected that CLAT is running on the device other than the default
  // logical device.
  if (!IsClatRunningDevice(default_logical_device)) {
    LOG(ERROR) << "CLAT is running on the device " << clat_running_device_
               << " although the default logical device is "
               << default_logical_device.ifname;
    StopClat();
    return;
  }

  // CLAT is running on the default logical device.

  DCHECK(!clat_running_device_->ipconfig.ipv4_cidr.has_value());
  DCHECK(clat_running_device_->ipconfig.ipv6_cidr.has_value());

  if (!NeedsClat(default_logical_device)) {
    StopClat();
    return;
  }

  if (clat_running_device_->ipconfig.ipv6_cidr !=
      default_logical_device.ipconfig.ipv6_cidr) {
    // TODO(b/278970851): Optimize the restart process of CLAT. Resources
    // such as the tun device can be reused.
    StopClat();

    StartClat(default_logical_device);
  }
}

void ClatService::StartClat(const ShillClient::Device& shill_device) {
  // Even if CLAT is disabled, we keep track of the device on which CLAT
  // should be running so that we can start CLAT immediately after it's
  // enabled.
  clat_running_device_ = shill_device;

  if (!is_enabled_) {
    return;
  }

  if (!shill_device.ipconfig.ipv6_cidr) {
    LOG(ERROR) << shill_device << " doesn't have an IPv6 address";
    return;
  }

  auto clat_ipv6_cidr = AddressManager::GetRandomizedIPv6Address(
      shill_device.ipconfig.ipv6_cidr->GetPrefixCIDR());
  if (!clat_ipv6_cidr) {
    LOG(ERROR) << "Failed to get randomized IPv6 address from " << shill_device;
    return;
  }
  clat_ipv6_addr_ = clat_ipv6_cidr->address();

  if (!CreateConfigFile(clat_ipv6_addr_.value())) {
    LOG(ERROR) << "Failed to create " << kTaygaConfigFilePath;
    StopClat();
    return;
  }

  if (datapath_->AddTunTap(kTunnelDeviceIfName, std::nullopt,
                           kTunnelDeviceIPv4CIDR, "",
                           DeviceMode::kTun) != kTunnelDeviceIfName) {
    LOG(ERROR) << "Failed to create a tun device for CLAT";
    StopClat();
    return;
  }

  if (!StartTayga()) {
    LOG(ERROR) << "Failed to start TAYGA on " << shill_device;
    StopClat();
    return;
  }

  if (!datapath_->ModifyClatAcceptRules(Iptables::Command::kA,
                                        kTunnelDeviceIfName)) {
    LOG(ERROR) << "Failed to add rules for CLAT in ip6tables";
    StopClat();
    return;
  }

  // The prefix length has to be /128 to add a route for only one IPv6 address.
  if (!datapath_->AddIPv6HostRoute(
          kTunnelDeviceIfName, *net_base::IPv6CIDR::CreateFromAddressAndPrefix(
                                   clat_ipv6_addr_.value(), 128))) {
    LOG(ERROR) << "Failed to add a route to " << kTunnelDeviceIfName;
    StopClat();
    return;
  }

  if (!datapath_->AddIPv6NeighborProxy(clat_running_device_->ifname,
                                       clat_ipv6_addr_.value())) {
    LOG(ERROR) << "Failed to add a ND proxy with interface "
               << kTunnelDeviceIfName << " and IPv6 address "
               << clat_ipv6_addr_.value();
    StopClat();
    return;
  }

  if (!datapath_->AddIPv4RouteToTable(kTunnelDeviceIfName, net_base::IPv4CIDR(),
                                      kClatRoutingTableId)) {
    LOG(ERROR) << "Failed to add a default route to table "
               << kClatRoutingTableId;
    StopClat();
    return;
  }

  LOG(INFO) << "CLAT has started on the device " << clat_running_device_.value()
            << " and with the IPv6 address " << clat_ipv6_addr_->ToString();
}

void ClatService::StopClat(bool clear_running_device) {
  if (!is_enabled_) {
    if (clear_running_device) {
      clat_running_device_.reset();
    }
    clat_ipv6_addr_.reset();
    return;
  }

  if (!(clat_running_device_ && clat_ipv6_addr_)) {
    LOG(INFO) << "No need to clean up CLAT configurations";
    return;
  }

  datapath_->DeleteIPv4RouteFromTable(kTunnelDeviceIfName, net_base::IPv4CIDR(),
                                      kClatRoutingTableId);

  datapath_->RemoveIPv6NeighborProxy(clat_running_device_->ifname,
                                     clat_ipv6_addr_.value());

  datapath_->ModifyClatAcceptRules(Iptables::Command::kD, kTunnelDeviceIfName);

  StopTayga();

  // The prefix length has to be /128 to remove a route for only one IPv6
  // address.
  datapath_->RemoveIPv6HostRoute(
      *net_base::IPv6CIDR::CreateFromAddressAndPrefix(clat_ipv6_addr_.value(),
                                                      128));

  datapath_->RemoveTunTap(kTunnelDeviceIfName, DeviceMode::kTun);

  RemoveConfigFileIfExists(base::FilePath(kTaygaConfigFilePath));

  LOG(INFO) << "CLAT has stopped on the device " << clat_running_device_.value()
            << " and with the IPv6 address " << clat_ipv6_addr_->ToString();

  if (clear_running_device) {
    clat_running_device_.reset();
  }
  clat_ipv6_addr_.reset();
}

void ClatService::SetClatRunningDeviceForTest(
    const ShillClient::Device& shill_device) {
  clat_running_device_ = shill_device;
}

void ClatService::ResetClatRunningDeviceForTest() {
  clat_running_device_.reset();
}

bool ClatService::IsClatRunningDevice(const ShillClient::Device& shill_device) {
  if (!clat_running_device_) {
    return false;
  }

  return shill_device.ifname == clat_running_device_->ifname;
}

bool ClatService::CreateConfigFile(
    const net_base::IPv6Address& clat_ipv6_addr) {
  const std::string contents = base::ReplaceStringPlaceholders(
      kTaygaConfigTemplate,
      {
          /*$1=*/std::string(kTunnelDeviceIfName),
          /*$2=*/kTaygaIPv4CIDR.address().ToString(),
          /*$3=*/kWellKnownNAT64Prefix.ToString(),
          /*$4=*/kTunnelDeviceIPv4CIDR.address().ToString(),
          /*$5=*/clat_ipv6_addr.ToString(),
      },
      nullptr);

  return system_->WriteConfigFile(base::FilePath(kTaygaConfigFilePath),
                                  contents);
}

bool ClatService::StartTayga() {
  std::vector<std::string> args = {
      "-n",
      "-c",
      kTaygaConfigFilePath,
  };

  net_base::ProcessManager::MinijailOptions minijail_options;
  minijail_options.user = kPatchpaneldUser;
  minijail_options.group = kPatchpaneldGroup;
  minijail_options.capmask = CAP_TO_MASK(CAP_NET_RAW);
  // This gives TAYGA permissions of grou tun, which is necessary for it to open
  // /dev/net/tun and configure the tun device.
  minijail_options.inherit_supplementary_groups = true;

  tayga_pid_ = process_manager_->StartProcessInMinijail(
      FROM_HERE, base::FilePath(kTaygaBinaryPath), args, {}, minijail_options,
      base::DoNothing());

  return tayga_pid_ >= 0;
}

void ClatService::StopTayga() {
  if (tayga_pid_ == -1) {
    return;
  }

  if (!brillo::Process::ProcessExists(tayga_pid_)) {
    LOG(WARNING) << "TAYGA[" << tayga_pid_ << "] already stopped";
    tayga_pid_ = -1;
    return;
  }

  process_manager_->StopProcessAndBlock(tayga_pid_);
  tayga_pid_ = -1;
}

}  // namespace patchpanel
