// Copyright (c) 2020 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 "quiche/quic/qbone/bonnet/tun_device_controller.h"

#include <linux/rtnetlink.h>

#include "absl/time/clock.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/qbone/qbone_constants.h"

ABSL_FLAG(bool, qbone_tun_device_replace_default_routing_rules, true,
          "If true, will define a rule that points packets sourced from the "
          "qbone interface to the qbone table. This is unnecessary in "
          "environments with no other ipv6 route.");

namespace quic {

bool TunDeviceController::UpdateAddress(const IpRange& desired_range) {
  if (!setup_tun_) {
    return true;
  }

  NetlinkInterface::LinkInfo link_info{};
  if (!netlink_->GetLinkInfo(ifname_, &link_info)) {
    return false;
  }

  std::vector<NetlinkInterface::AddressInfo> addresses;
  if (!netlink_->GetAddresses(link_info.index, 0, &addresses, nullptr)) {
    return false;
  }

  QuicIpAddress desired_address = desired_range.FirstAddressInRange();

  for (const auto& address : addresses) {
    if (!netlink_->ChangeLocalAddress(
            link_info.index, NetlinkInterface::Verb::kRemove,
            address.interface_address, address.prefix_length, 0, 0, {})) {
      return false;
    }
  }

  bool address_updated = netlink_->ChangeLocalAddress(
      link_info.index, NetlinkInterface::Verb::kAdd, desired_address,
      desired_range.prefix_length(), IFA_F_PERMANENT | IFA_F_NODAD,
      RT_SCOPE_LINK, {});

  if (address_updated) {
    current_address_ = desired_address;

    for (const auto& cb : address_update_cbs_) {
      cb(current_address_);
    }
  }

  return address_updated;
}

bool TunDeviceController::UpdateRoutes(
    const IpRange& desired_range, const std::vector<IpRange>& desired_routes) {
  if (!setup_tun_) {
    return true;
  }

  NetlinkInterface::LinkInfo link_info{};
  if (!netlink_->GetLinkInfo(ifname_, &link_info)) {
    QUIC_LOG(ERROR) << "Could not get link info for interface <" << ifname_
                    << ">";
    return false;
  }

  std::vector<NetlinkInterface::RoutingRule> routing_rules;
  if (!netlink_->GetRouteInfo(&routing_rules)) {
    QUIC_LOG(ERROR) << "Unable to get route info";
    return false;
  }

  for (const auto& rule : routing_rules) {
    if (rule.out_interface == link_info.index &&
        rule.table == QboneConstants::kQboneRouteTableId) {
      if (!netlink_->ChangeRoute(NetlinkInterface::Verb::kRemove, rule.table,
                                 rule.destination_subnet, rule.scope,
                                 rule.preferred_source, rule.out_interface)) {
        QUIC_LOG(ERROR) << "Unable to remove old route to <"
                        << rule.destination_subnet.ToString() << ">";
        return false;
      }
    }
  }

  if (!UpdateRules(desired_range)) {
    return false;
  }

  QuicIpAddress desired_address = desired_range.FirstAddressInRange();

  std::vector<IpRange> routes(desired_routes.begin(), desired_routes.end());
  routes.emplace_back(*QboneConstants::TerminatorLocalAddressRange());

  for (const auto& route : routes) {
    if (!netlink_->ChangeRoute(NetlinkInterface::Verb::kReplace,
                               QboneConstants::kQboneRouteTableId, route,
                               RT_SCOPE_LINK, desired_address,
                               link_info.index)) {
      QUIC_LOG(ERROR) << "Unable to add route <" << route.ToString() << ">";
      return false;
    }
  }

  return true;
}

bool TunDeviceController::UpdateRoutesWithRetries(
    const IpRange& desired_range, const std::vector<IpRange>& desired_routes,
    int retries) {
  while (retries-- > 0) {
    if (UpdateRoutes(desired_range, desired_routes)) {
      return true;
    }
    absl::SleepFor(absl::Milliseconds(100));
  }
  return false;
}

bool TunDeviceController::UpdateRules(IpRange desired_range) {
  if (!absl::GetFlag(FLAGS_qbone_tun_device_replace_default_routing_rules)) {
    return true;
  }

  std::vector<NetlinkInterface::IpRule> ip_rules;
  if (!netlink_->GetRuleInfo(&ip_rules)) {
    QUIC_LOG(ERROR) << "Unable to get rule info";
    return false;
  }

  for (const auto& rule : ip_rules) {
    if (rule.table == QboneConstants::kQboneRouteTableId) {
      if (!netlink_->ChangeRule(NetlinkInterface::Verb::kRemove, rule.table,
                                rule.source_range)) {
        QUIC_LOG(ERROR) << "Unable to remove old rule for table <" << rule.table
                        << "> from source <" << rule.source_range.ToString()
                        << ">";
        return false;
      }
    }
  }

  if (!netlink_->ChangeRule(NetlinkInterface::Verb::kAdd,
                            QboneConstants::kQboneRouteTableId,
                            desired_range)) {
    QUIC_LOG(ERROR) << "Unable to add rule for <" << desired_range.ToString()
                    << ">";
    return false;
  }

  return true;
}

QuicIpAddress TunDeviceController::current_address() {
  return current_address_;
}

void TunDeviceController::RegisterAddressUpdateCallback(
    const std::function<void(QuicIpAddress)>& cb) {
  address_update_cbs_.push_back(cb);
}

}  // namespace quic
