// Copyright 2016 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/manager.h"

#include <algorithm>
#include <optional>
#include <utility>

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/functional/bind.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <base/strings/string_number_conversions.h>
#include <base/task/single_thread_task_runner.h>
#include <chromeos/net-base/mac_address.h>
#include <chromeos/net-base/process_manager.h>
#include <chromeos/net-base/technology.h>
#include <patchpanel/proto_bindings/traffic_annotation.pb.h>

#include "patchpanel/address_manager.h"
#include "patchpanel/crostini_service.h"
#include "patchpanel/datapath.h"
#include "patchpanel/downstream_network_info.h"
#include "patchpanel/downstream_network_service.h"
#include "patchpanel/metrics.h"
#include "patchpanel/multicast_metrics.h"
#include "patchpanel/net_util.h"
#include "patchpanel/network/network_applier.h"
#include "patchpanel/proto_utils.h"
#include "patchpanel/qos_service.h"
#include "patchpanel/routing_service.h"
#include "patchpanel/scoped_ns.h"

namespace patchpanel {
namespace {
// Delay to restart IPv6 in a namespace to trigger SLAAC in the kernel.
constexpr int kIPv6RestartDelayMs = 300;

// Types of conntrack events ConntrackMonitor handles. Listeners added to the
// monitor can only listen to types of events included in this list.
constexpr ConntrackMonitor::EventType kConntrackEvents[] = {
    ConntrackMonitor::EventType::kNew};
}  // namespace

MulticastForwardingControlMessage::Direction
GetMulticastControlMessageDirection(MulticastForwarder::Direction dir) {
  switch (dir) {
    case MulticastForwarder::Direction::kInboundOnly:
      return MulticastForwardingControlMessage::INBOUND_ONLY;
    case MulticastForwarder::Direction::kOutboundOnly:
      return MulticastForwardingControlMessage::OUTBOUND_ONLY;
    case MulticastForwarder::Direction::kTwoWays:
      return MulticastForwardingControlMessage::TWO_WAYS;
  }
}

Manager::Manager(const base::FilePath& cmd_path,
                 System* system,
                 net_base::ProcessManager* process_manager,
                 MetricsLibraryInterface* metrics,
                 DbusClientNotifier* dbus_client_notifier,
                 std::unique_ptr<ShillClient> shill_client,
                 std::unique_ptr<RTNLClient> rtnl_client)
    : system_(system),
      metrics_(metrics),
      dbus_client_notifier_(dbus_client_notifier),
      shill_client_(std::move(shill_client)),
      rtnl_client_(std::move(rtnl_client)) {
  DCHECK(rtnl_client_);

  auto conntrack_monitor = ConntrackMonitor::GetInstance();
  conntrack_monitor->Start(kConntrackEvents);

  datapath_ = std::make_unique<Datapath>(system);
  adb_proxy_ = std::make_unique<patchpanel::SubprocessController>(
      system, process_manager, cmd_path, "--adb_proxy_fd");
  mcast_proxy_ = std::make_unique<patchpanel::SubprocessController>(
      system, process_manager, cmd_path, "--mcast_proxy_fd");
  nd_proxy_ = std::make_unique<patchpanel::SubprocessController>(
      system, process_manager, cmd_path, "--nd_proxy_fd");
  socket_service_ = std::make_unique<patchpanel::SubprocessController>(
      system, process_manager, cmd_path, "--socket_service_fd");

  adb_proxy_->Start();
  mcast_proxy_->Start();
  nd_proxy_->Start();
  socket_service_->Start();

  routing_svc_ = std::make_unique<RoutingService>();
  counters_svc_ =
      std::make_unique<CountersService>(datapath_.get(), conntrack_monitor);
  multicast_counters_svc_ =
      std::make_unique<MulticastCountersService>(datapath_.get());
  multicast_metrics_ = std::make_unique<MulticastMetrics>(
      multicast_counters_svc_.get(), metrics);

  datapath_->Start();

  multicast_counters_svc_->Start();
  multicast_metrics_->Start(MulticastMetrics::Type::kTotal);

  qos_svc_ = std::make_unique<QoSService>(datapath_.get(), conntrack_monitor);

  lifeline_fd_svc_ = std::make_unique<LifelineFDService>();

  downstream_network_svc_ = std::make_unique<DownstreamNetworkService>(
      metrics_, system_, datapath_.get(), this, rtnl_client_.get(),
      lifeline_fd_svc_.get(), shill_client_.get(), ipv6_svc_.get(),
      counters_svc_.get());

  constexpr ArcService::ArcType arc_type = []() constexpr {
    if (USE_ARCVM_NIC_HOTPLUG) {
      return ArcService::ArcType::kVMHotplug;
    } else if (USE_ARCVM) {
      return ArcService::ArcType::kVMStatic;
    } else {
      return ArcService::ArcType::kContainer;
    }
  }();
  arc_svc_ =
      std::make_unique<ArcService>(arc_type, datapath_.get(), &addr_mgr_, this,
                                   metrics_, dbus_client_notifier_);
  cros_svc_ = std::make_unique<CrostiniService>(&addr_mgr_, datapath_.get(),
                                                this, dbus_client_notifier_);

  network_monitor_svc_ =
      std::make_unique<NetworkMonitorService>(base::BindRepeating(
          &Manager::OnNeighborReachabilityEvent, weak_factory_.GetWeakPtr()));
  ipv6_svc_ = std::make_unique<GuestIPv6Service>(nd_proxy_.get(),
                                                 datapath_.get(), system);
  clat_svc_ =
      std::make_unique<ClatService>(datapath_.get(), process_manager, system);
  ipv6_svc_->Start();

  // Setups the RTNL socket and listens to neighbor events. This should be
  // called before NetworkMonitorService::Start and NetworkApplier::Start.
  // RTMGRP_NEIGH is needed by NetworkMonitorService.
  net_base::RTNLHandler::GetInstance()->Start(RTMGRP_NEIGH);

  // TODO(b/293997937): NetworkApplier to be a Manager-owned service rather than
  // a singleton.
  NetworkApplier::GetInstance()->Start();

  // Post a delayed task to run the delayed initialization which may take time
  // but not necessary for handling dbus methods. There are two main purposes
  // here:
  // 1) Make patchpanel D-Bus service ready as early as possible.
  // 2) Specifically we want to handle the ConfigureNetwork() request as early
  //    as possible which is critical to basic network connectivity.
  //
  // The delay value (1 second) is selected arbitrarily.
  //
  // Caveats:
  // - It's possible that ConfigureNetwork() request doesn't come in in the
  //   timeout, and thus this logic actually delayed its execution by at most 1
  //   second.
  // - The tasks in RunDelayedInitialization() is just not critical to handling
  //   D-Bus request but still critical to the full connectivity, so we may
  //   waste some time which can be used to set it up.
  //
  // Ideally what we want to do here is to schedule a low-priority task with
  // deadline, which can not be implemented with a very easy way now.
  base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&Manager::RunDelayedInitialization,
                     weak_factory_.GetWeakPtr()),
      base::Seconds(1));
}

Manager::~Manager() {
  network_monitor_svc_.reset();
  cros_svc_.reset();
  arc_svc_.reset();
  clat_svc_.reset();

  // Explicitly reset QoSService before Datapath::Stop() since the former one
  // depends on Datapath.
  qos_svc_.reset();

  downstream_network_svc_.reset();

  // Tear down any remaining ConnectNamespace setup.
  std::vector<int> connected_namespaces_ifnames;
  for (const auto& [id, _] : connected_namespaces_) {
    connected_namespaces_ifnames.push_back(id);
  }
  for (int id : connected_namespaces_ifnames) {
    OnConnectedNamespaceAutoclose(id);
  }

  // Tear down any remaining DNS redirection rule setup.
  std::vector<int> dns_proxy_lifelines_fds;
  for (const auto& [lifeline_fd, _] : dns_redirection_rules_) {
    dns_proxy_lifelines_fds.push_back(lifeline_fd);
  }
  for (int lifeline_fd : dns_proxy_lifelines_fds) {
    OnDnsRedirectionRulesAutoclose(lifeline_fd);
  }

  multicast_counters_svc_->Stop();
  datapath_->Stop();
}

void Manager::RunDelayedInitialization() {
  LOG(INFO) << __func__ << ": start";

  shill_client_->RegisterDevicesChangedHandler(base::BindRepeating(
      &Manager::OnShillDevicesChanged, weak_factory_.GetWeakPtr()));
  shill_client_->RegisterIPConfigsChangedHandler(base::BindRepeating(
      &Manager::OnIPConfigsChanged, weak_factory_.GetWeakPtr()));
  shill_client_->RegisterIPv6NetworkChangedHandler(base::BindRepeating(
      &Manager::OnIPv6NetworkChanged, weak_factory_.GetWeakPtr()));
  shill_client_->RegisterDoHProvidersChangedHandler(base::BindRepeating(
      &Manager::OnDoHProvidersChanged, weak_factory_.GetWeakPtr()));

  // Make sure patchpanel get aware of the Devices created before it starts.
  shill_client_->ScanDevices();

  // Shill client's RegisterDefault*DeviceChangedHandler methods trigger the
  // Manager's callbacks on registration. Call them after everything is set up.
  shill_client_->RegisterDefaultLogicalDeviceChangedHandler(
      base::BindRepeating(&Manager::OnShillDefaultLogicalDeviceChanged,
                          weak_factory_.GetWeakPtr()));
  shill_client_->RegisterDefaultPhysicalDeviceChangedHandler(
      base::BindRepeating(&Manager::OnShillDefaultPhysicalDeviceChanged,
                          weak_factory_.GetWeakPtr()));

  LOG(INFO) << __func__ << ": finished";
}

void Manager::OnShillDefaultLogicalDeviceChanged(
    const ShillClient::Device* new_device,
    const ShillClient::Device* prev_device) {
  // Only take into account interface switches and new Device or removed Device
  // events. Ignore any layer 3 property change.
  if (!prev_device && !new_device) {
    return;
  }
  if (prev_device && new_device && prev_device->ifname == new_device->ifname) {
    return;
  }

  if (prev_device && prev_device->technology == net_base::Technology::kVPN) {
    datapath_->StopVpnRouting(*prev_device);
    counters_svc_->OnVpnDeviceRemoved(prev_device->ifname);
  }

  if (new_device && new_device->technology == net_base::Technology::kVPN) {
    counters_svc_->OnVpnDeviceAdded(new_device->ifname);
    datapath_->StartVpnRouting(*new_device);
  }

  cros_svc_->OnShillDefaultLogicalDeviceChanged(new_device, prev_device);

  // When the default logical network changes, ConnectedNamespaces' devices
  // which follow the logical network must leave their current forwarding group
  // for IPv6 ndproxy and join the forwarding group of the new logical default
  // network. This is marked by empty |outbound_ifname| and |route_on_vpn|
  // with the value of true.
  for (auto& [_, nsinfo] : connected_namespaces_) {
    if (!nsinfo.outbound_ifname.empty() || !nsinfo.route_on_vpn) {
      continue;
    }
    if (prev_device) {
      nsinfo.current_outbound_device = std::nullopt;
    }
    if (new_device) {
      nsinfo.current_outbound_device = *new_device;
    }

    // When IPv6 is configured statically, no need to update forwarding set and
    // restart IPv6 inside the namespace.
    if (nsinfo.static_ipv6_config.has_value()) {
      continue;
    }
    if (prev_device) {
      StopIPv6NDPForwarding(*prev_device, nsinfo.host_ifname);
    }
    if (new_device) {
      StartIPv6NDPForwarding(*new_device, nsinfo.host_ifname);

      // Disable and re-enable IPv6. This is necessary to trigger SLAAC in the
      // kernel to send RS. Add a delay for the forwarding to be set up.
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&Manager::RestartIPv6, weak_factory_.GetWeakPtr(),
                         nsinfo.netns_name),
          base::Milliseconds(kIPv6RestartDelayMs));
    }
  }
  clat_svc_->OnShillDefaultLogicalDeviceChanged(new_device, prev_device);
}

void Manager::OnShillDefaultPhysicalDeviceChanged(
    const ShillClient::Device* new_device,
    const ShillClient::Device* prev_device) {
  // Only take into account interface switches and new Device or removed Device
  // events. Ignore any layer 3 property change.
  if (!prev_device && !new_device) {
    return;
  }
  if (prev_device && new_device && prev_device->ifname == new_device->ifname) {
    return;
  }

  // When the default physical network changes, ConnectedNamespaces' devices
  // which follow the physical network must leave their current forwarding group
  // for IPv6 ndproxy and join the forwarding group of the new physical default
  // network. This is marked by empty |outbound_ifname| and |route_on_vpn|
  // with the value of false.
  for (auto& [_, nsinfo] : connected_namespaces_) {
    if (!nsinfo.outbound_ifname.empty() || nsinfo.route_on_vpn) {
      continue;
    }
    if (prev_device) {
      nsinfo.current_outbound_device = std::nullopt;
    }
    if (new_device) {
      nsinfo.current_outbound_device = *new_device;
    }

    // When IPv6 is configured statically, no need to update forwarding set and
    // restart IPv6 inside the namespace.
    if (nsinfo.static_ipv6_config.has_value()) {
      continue;
    }
    if (prev_device) {
      StopIPv6NDPForwarding(*prev_device, nsinfo.host_ifname);
    }
    if (new_device) {
      StartIPv6NDPForwarding(*new_device, nsinfo.host_ifname);

      // Disable and re-enable IPv6. This is necessary to trigger SLAAC in the
      // kernel to send RS. Add a delay for the forwarding to be set up.
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&Manager::RestartIPv6, weak_factory_.GetWeakPtr(),
                         nsinfo.netns_name),
          base::Milliseconds(kIPv6RestartDelayMs));
    }
  }
}

void Manager::RestartIPv6(std::string_view netns_name) {
  auto ns = ScopedNS::EnterNetworkNS(netns_name);
  if (!ns) {
    LOG(ERROR) << "Invalid namespace name " << netns_name;
    return;
  }

  if (datapath_) {
    datapath_->RestartIPv6();
  }
}

void Manager::OnShillDevicesChanged(
    const std::vector<ShillClient::Device>& added,
    const std::vector<ShillClient::Device>& removed) {
  // Rules for traffic counters should be installed at the first and removed at
  // the last to make sure every packet is counted.
  for (const auto& device : removed) {
    for (auto& [_, nsinfo] : connected_namespaces_) {
      if (nsinfo.outbound_ifname != device.ifname) {
        continue;
      }
      if (nsinfo.static_ipv6_config.has_value()) {
        continue;
      }
      StopIPv6NDPForwarding(device, nsinfo.host_ifname);
    }
    StopIPv6NDPForwarding(device, /*ifname_virtual=*/"");
    StopMulticastForwarding(device, /*ifname_virtual=*/"");
    StopBroadcastForwarding(device, /*ifname_virtual=*/"");
    datapath_->StopConnectionPinning(device);
    datapath_->RemoveRedirectDnsRule(device);
    arc_svc_->RemoveDevice(device);
    multicast_metrics_->OnPhysicalDeviceRemoved(device);
    counters_svc_->OnPhysicalDeviceRemoved(device.ifname);
    multicast_counters_svc_->OnPhysicalDeviceRemoved(device);
    qos_svc_->OnPhysicalDeviceRemoved(device);

    if (device.technology == net_base::Technology::kCellular) {
      datapath_->StopSourceIPv6PrefixEnforcement(device);
    }
  }

  for (const auto& device : added) {
    qos_svc_->OnPhysicalDeviceAdded(device);
    counters_svc_->OnPhysicalDeviceAdded(device.ifname);
    multicast_counters_svc_->OnPhysicalDeviceAdded(device);
    multicast_metrics_->OnPhysicalDeviceAdded(device);
    for (auto& [_, nsinfo] : connected_namespaces_) {
      if (nsinfo.outbound_ifname != device.ifname) {
        continue;
      }
      if (nsinfo.static_ipv6_config.has_value()) {
        continue;
      }
      StartIPv6NDPForwarding(device, nsinfo.host_ifname);
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&Manager::RestartIPv6, weak_factory_.GetWeakPtr(),
                         nsinfo.netns_name),
          base::Milliseconds(kIPv6RestartDelayMs));
    }
    datapath_->StartConnectionPinning(device);

    if (!device.ipconfig.ipv4_dns_addresses.empty()) {
      datapath_->AddRedirectDnsRule(device,
                                    device.ipconfig.ipv4_dns_addresses.front());
    }

    arc_svc_->AddDevice(device);
    if (device.technology == net_base::Technology::kCellular) {
      datapath_->StartSourceIPv6PrefixEnforcement(device);
    }
  }

  network_monitor_svc_->OnShillDevicesChanged(added, removed);
}

void Manager::OnIPConfigsChanged(const ShillClient::Device& shill_device) {
  if (shill_device.ipconfig.ipv4_dns_addresses.empty()) {
    datapath_->RemoveRedirectDnsRule(shill_device);
  } else {
    datapath_->AddRedirectDnsRule(
        shill_device, shill_device.ipconfig.ipv4_dns_addresses.front());
  }
  multicast_metrics_->OnIPConfigsChanged(shill_device);
  ipv6_svc_->UpdateUplinkIPv6DNS(shill_device);

  // Update local copies of the ShillClient::Device to keep IP configuration
  // properties in sync.
  for (auto& [_, nsinfo] : connected_namespaces_) {
    if (!nsinfo.current_outbound_device) {
      continue;
    }
    if (nsinfo.current_outbound_device->ifname == shill_device.ifname) {
      nsinfo.current_outbound_device = shill_device;
    }
  }

  downstream_network_svc_->UpdateDeviceIPConfig(shill_device);
  arc_svc_->UpdateDeviceIPConfig(shill_device);

  const auto* default_logical_device = shill_client_->default_logical_device();
  if (default_logical_device &&
      shill_device.ifname == default_logical_device->ifname) {
    clat_svc_->OnDefaultLogicalDeviceIPConfigChanged(shill_device);
  }

  if (!shill_device.IsConnected()) {
    qos_svc_->OnPhysicalDeviceDisconnected(shill_device);
  }

  network_monitor_svc_->OnIPConfigsChanged(shill_device);
}

void Manager::OnIPv6NetworkChanged(const ShillClient::Device& shill_device) {
  ipv6_svc_->OnUplinkIPv6Changed(shill_device);

  if (!shill_device.ipconfig.ipv6_cidr) {
    if (shill_device.technology == net_base::Technology::kCellular) {
      datapath_->UpdateSourceEnforcementIPv6Prefix(shill_device, std::nullopt);
    }
    return;
  }

  for (auto& [_, nsinfo] : connected_namespaces_) {
    if (nsinfo.outbound_ifname != shill_device.ifname) {
      continue;
    }

    if (nsinfo.static_ipv6_config.has_value()) {
      continue;
    }
    // Disable and re-enable IPv6 inside the namespace. This is necessary to
    // trigger SLAAC in the kernel to send RS.
    RestartIPv6(nsinfo.netns_name);
  }

  if (shill_device.technology == net_base::Technology::kCellular) {
    // TODO(b/279871350): Support prefix shorter than /64.
    const auto prefix = GuestIPv6Service::IPAddressTo64BitPrefix(
        shill_device.ipconfig.ipv6_cidr->address());
    datapath_->UpdateSourceEnforcementIPv6Prefix(shill_device, prefix);
  }
}

void Manager::OnDoHProvidersChanged(
    const ShillClient::DoHProviders& doh_providers) {
  qos_svc_->UpdateDoHProviders(doh_providers);
}

bool Manager::ArcStartup(pid_t pid) {
  if (pid < 0) {
    LOG(ERROR) << "Invalid ARC pid: " << pid;
    return false;
  }

  if (!arc_svc_->Start(static_cast<uint32_t>(pid)))
    return false;

  GuestMessage msg;
  msg.set_event(GuestMessage::START);
  msg.set_type(GuestMessage::ARC);
  msg.set_arc_pid(pid);
  SendGuestMessage(msg);

  multicast_metrics_->OnARCStarted();

  return true;
}

void Manager::ArcShutdown() {
  multicast_metrics_->OnARCStopped();

  GuestMessage msg;
  msg.set_event(GuestMessage::STOP);
  msg.set_type(GuestMessage::ARC);
  SendGuestMessage(msg);

  // After the ARC container has stopped, the pid is not known anymore.
  // The pid argument is ignored by ArcService.
  arc_svc_->Stop(0);
}

std::optional<patchpanel::ArcVmStartupResponse> Manager::ArcVmStartup(
    uint32_t cid) {
  if (!arc_svc_->Start(cid)) {
    return std::nullopt;
  }
  GuestMessage msg;
  msg.set_event(GuestMessage::START);
  msg.set_type(GuestMessage::ARC_VM);
  msg.set_arcvm_vsock_cid(cid);
  SendGuestMessage(msg);

  multicast_metrics_->OnARCStarted();

  patchpanel::ArcVmStartupResponse response;
  if (const auto arc0_addr = arc_svc_->GetArc0IPv4Address()) {
    response.set_arc0_ipv4_address(arc0_addr->ToByteString());
  }
  // Only pass static tap devices before ARCVM starts. Hotplugged devices, if
  // any, are added after VM starts.
  for (const auto& tap : arc_svc_->GetStaticTapDevices()) {
    response.add_tap_device_ifnames(tap);
  }
  return response;
}

void Manager::ArcVmShutdown(uint32_t cid) {
  multicast_metrics_->OnARCStopped();

  GuestMessage msg;
  msg.set_event(GuestMessage::STOP);
  msg.set_type(GuestMessage::ARC_VM);
  msg.set_arcvm_vsock_cid(cid);
  SendGuestMessage(msg);

  arc_svc_->Stop(cid);
}

const CrostiniService::CrostiniDevice* Manager::StartCrosVm(
    uint64_t vm_id, CrostiniService::VMType vm_type, uint32_t subnet_index) {
  const auto* guest_device = cros_svc_->Start(vm_id, vm_type, subnet_index);
  if (!guest_device) {
    return nullptr;
  }
  GuestMessage msg;
  msg.set_event(GuestMessage::START);
  msg.set_type(CrostiniService::GuestMessageTypeFromVMType(vm_type));
  SendGuestMessage(msg);
  return guest_device;
}

void Manager::StopCrosVm(uint64_t vm_id, CrostiniService::VMType vm_type) {
  GuestMessage msg;
  msg.set_event(GuestMessage::STOP);
  msg.set_type(CrostiniService::GuestMessageTypeFromVMType(vm_type));
  SendGuestMessage(msg);
  cros_svc_->Stop(vm_id);
}

GetDevicesResponse Manager::GetDevices() const {
  GetDevicesResponse response;

  for (const auto* arc_device : arc_svc_->GetDevices()) {
    // The legacy "arc0" Device is never exposed in "GetDevices".
    if (!arc_device->shill_device_ifname()) {
      continue;
    }
    auto* dev = response.add_devices();
    arc_device->ConvertToProto(dev);
    FillArcDeviceDnsProxyProto(*arc_device, dev, dns_proxy_ipv4_addrs_,
                               dns_proxy_ipv6_addrs_);
  }

  for (const auto* crostini_device : cros_svc_->GetDevices()) {
    crostini_device->ConvertToProto(response.add_devices());
  }

  return response;
}

const CrostiniService::CrostiniDevice* const Manager::TerminaVmStartup(
    uint64_t cid) {
  const auto* guest_device =
      StartCrosVm(cid, CrostiniService::VMType::kTermina);
  if (!guest_device) {
    LOG(ERROR) << "Failed to start Termina VM network service";
    return nullptr;
  }
  return guest_device;
}

void Manager::TerminaVmShutdown(uint64_t vm_id) {
  StopCrosVm(vm_id, CrostiniService::VMType::kTermina);
}

const CrostiniService::CrostiniDevice* const Manager::ParallelsVmStartup(
    uint64_t vm_id, uint32_t subnet_index) {
  const auto* guest_device =
      StartCrosVm(vm_id, CrostiniService::VMType::kParallels, subnet_index);
  if (!guest_device) {
    LOG(ERROR) << "Failed to start Parallels VM network service";
    return nullptr;
  }
  return guest_device;
}

void Manager::ParallelsVmShutdown(uint64_t vm_id) {
  StopCrosVm(vm_id, CrostiniService::VMType::kParallels);
}

const CrostiniService::CrostiniDevice* const Manager::BruschettaVmStartup(
    uint64_t vm_id) {
  const auto* guest_device =
      StartCrosVm(vm_id, CrostiniService::VMType::kBruschetta);
  if (!guest_device) {
    LOG(ERROR) << "Failed to start Bruschetta VM network service";
    return nullptr;
  }
  return guest_device;
}

void Manager::BruschettaVmShutdown(uint64_t vm_id) {
  StopCrosVm(vm_id, CrostiniService::VMType::kBruschetta);
}

const CrostiniService::CrostiniDevice* const Manager::BorealisVmStartup(
    uint64_t vm_id) {
  const auto* guest_device =
      StartCrosVm(vm_id, CrostiniService::VMType::kBorealis);
  if (!guest_device) {
    LOG(ERROR) << "Failed to start Borealis VM network service";
    return nullptr;
  }
  qos_svc_->OnBorealisVMStarted(guest_device->tap_device_ifname());
  return guest_device;
}

void Manager::BorealisVmShutdown(uint64_t vm_id) {
  const CrostiniService::CrostiniDevice* guest_device =
      cros_svc_->GetDevice(vm_id);
  if (guest_device) {
    qos_svc_->OnBorealisVMStopped(guest_device->tap_device_ifname());
  }
  StopCrosVm(vm_id, CrostiniService::VMType::kBorealis);
}

std::map<CountersService::CounterKey, CountersService::Counter>
Manager::GetTrafficCounters(const std::set<std::string>& shill_devices) const {
  return counters_svc_->GetCounters(shill_devices);
}

bool Manager::ModifyPortRule(const ModifyPortRuleRequest& request) {
  return datapath_->ModifyPortRule(request);
}

void Manager::SetVpnLockdown(bool enable_vpn_lockdown) {
  datapath_->SetVpnLockdown(enable_vpn_lockdown);
}

bool Manager::TagSocket(const patchpanel::TagSocketRequest& request,
                        const base::ScopedFD& socket_fd) {
  std::optional<int> network_id = std::nullopt;
  if (request.has_network_id()) {
    network_id = request.network_id();
  }

  auto policy = VPNRoutingPolicy::kDefault;
  switch (request.vpn_policy()) {
    case TagSocketRequest::DEFAULT_ROUTING:
      policy = VPNRoutingPolicy::kDefault;
      break;
    case TagSocketRequest::ROUTE_ON_VPN:
      policy = VPNRoutingPolicy::kRouteOnVPN;
      break;
    case TagSocketRequest::BYPASS_VPN:
      policy = VPNRoutingPolicy::kBypassVPN;
      break;
    default:
      LOG(ERROR) << __func__ << ": Invalid vpn policy value"
                 << request.vpn_policy();
      return false;
  }

  std::optional<TrafficAnnotationId> annotation_id;
  if (request.has_traffic_annotation()) {
    switch (request.traffic_annotation().host_id()) {
      case traffic_annotation::TrafficAnnotation::UNSPECIFIED:
        annotation_id = TrafficAnnotationId::kUnspecified;
        break;
      case traffic_annotation::TrafficAnnotation::SHILL_PORTAL_DETECTOR:
        annotation_id = TrafficAnnotationId::kShillPortalDetector;
        break;
      case traffic_annotation::TrafficAnnotation::SHILL_CAPPORT_CLIENT:
        annotation_id = TrafficAnnotationId::kShillCapportClient;
        break;
      case traffic_annotation::TrafficAnnotation::SHILL_CARRIER_ENTITLEMENT:
        annotation_id = TrafficAnnotationId::kShillCarrierEntitlement;
        break;
      default:
        LOG(ERROR) << __func__ << ": Invalid traffic annotation id "
                   << request.traffic_annotation().host_id();
        return false;
    }
  }

  return routing_svc_->TagSocket(socket_fd.get(), network_id, policy,
                                 annotation_id);
}

void Manager::OnNeighborReachabilityEvent(
    int ifindex,
    const net_base::IPAddress& ip_addr,
    NeighborLinkMonitor::NeighborRole role,
    NeighborReachabilityEventSignal::EventType event_type) {
  dbus_client_notifier_->OnNeighborReachabilityEvent(ifindex, ip_addr, role,
                                                     event_type);
}

ConnectNamespaceResponse Manager::ConnectNamespace(
    const ConnectNamespaceRequest& request, base::ScopedFD client_fd) {
  ConnectNamespaceResponse response;

  const pid_t pid = request.pid();
  if (pid == 1 || pid == getpid()) {
    LOG(ERROR) << "Privileged namespace pid " << pid;
    return response;
  }
  if (pid != ConnectedNamespace::kNewNetnsPid) {
    auto ns = ScopedNS::EnterNetworkNS(pid);
    if (!ns) {
      LOG(ERROR) << "Invalid namespace pid " << pid;
      return response;
    }
  }

  // Get the ConnectedNamespace outbound shill Device.
  // TODO(b/273744897): Migrate ConnectNamespace to use a patchpanel Network id
  // instead of the interface name of the shill Device.
  const std::string& outbound_ifname = request.outbound_physical_device();
  const ShillClient::Device* current_outbound_device;
  if (!outbound_ifname.empty()) {
    // b/273741099: For multiplexed Cellular interfaces, callers expect
    // patchpanel to accept a shill Device kInterfaceProperty value and swap it
    // with the name of the primary multiplexed interface.
    auto* shill_device =
        shill_client_->GetDeviceByShillDeviceName(outbound_ifname);
    if (!shill_device) {
      LOG(ERROR) << __func__ << ": no shill Device for upstream ifname "
                 << outbound_ifname;
      return response;
    }
    current_outbound_device = shill_device;
  } else if (request.route_on_vpn()) {
    current_outbound_device = shill_client_->default_logical_device();
  } else {
    current_outbound_device = shill_client_->default_physical_device();
  }

  std::unique_ptr<Subnet> ipv4_subnet =
      addr_mgr_.AllocateIPv4Subnet(AddressManager::GuestType::kNetns);
  if (!ipv4_subnet) {
    LOG(ERROR) << "Exhausted IPv4 subnet space";
    return response;
  }

  const auto host_ipv4_cidr = ipv4_subnet->CIDRAtOffset(1);
  const auto peer_ipv4_cidr = ipv4_subnet->CIDRAtOffset(2);
  if (!host_ipv4_cidr || !peer_ipv4_cidr) {
    LOG(ERROR) << "Failed to create CIDR from subnet: "
               << ipv4_subnet->base_cidr();
    return response;
  }

  auto cancel_lifeline_fd = lifeline_fd_svc_->AddLifelineFD(
      std::move(client_fd),
      base::BindOnce(&Manager::OnConnectedNamespaceAutoclose,
                     weak_factory_.GetWeakPtr(),
                     connected_namespaces_next_id_));
  if (!cancel_lifeline_fd) {
    LOG(ERROR) << "Failed to create lifeline fd";
    return response;
  }

  const std::string ifname_id = std::to_string(connected_namespaces_next_id_);
  ConnectedNamespace nsinfo = {};
  nsinfo.pid = request.pid();
  nsinfo.netns_name = "connected_netns_" + ifname_id;
  nsinfo.source = ProtoToTrafficSource(request.traffic_source());
  if (nsinfo.source == TrafficSource::kUnknown) {
    nsinfo.source = TrafficSource::kSystem;
  }
  nsinfo.outbound_ifname = outbound_ifname;
  nsinfo.route_on_vpn = request.route_on_vpn();
  nsinfo.host_ifname = "arc_ns" + ifname_id;
  nsinfo.peer_ifname = "veth" + ifname_id;
  nsinfo.peer_ipv4_subnet = std::move(ipv4_subnet);
  nsinfo.host_ipv4_cidr = *host_ipv4_cidr;
  nsinfo.peer_ipv4_cidr = *peer_ipv4_cidr;
  nsinfo.host_mac_addr = addr_mgr_.GenerateMacAddress();
  nsinfo.peer_mac_addr = addr_mgr_.GenerateMacAddress();
  if (nsinfo.host_mac_addr == nsinfo.peer_mac_addr) {
    LOG(ERROR) << "Failed to generate unique MAC address for connected "
                  "namespace host and peer interface";
  }
  if (current_outbound_device) {
    nsinfo.current_outbound_device = *current_outbound_device;
  }
  if (request.static_ipv6()) {
    auto ipv6_subnet = addr_mgr_.AllocateIPv6Subnet();
    if (ipv6_subnet.prefix_length() >= 127) {
      LOG(ERROR) << "Allocated IPv6 subnet must at least hold 2 addresses and "
                    "1 base address, but got "
                 << ipv6_subnet;
    } else {
      nsinfo.static_ipv6_config = StaticIPv6Config{};
      nsinfo.static_ipv6_config->host_cidr =
          *addr_mgr_.GetRandomizedIPv6Address(ipv6_subnet);
      do {
        nsinfo.static_ipv6_config->peer_cidr =
            *addr_mgr_.GetRandomizedIPv6Address(ipv6_subnet);
      } while (nsinfo.static_ipv6_config->peer_cidr ==
               nsinfo.static_ipv6_config->host_cidr);
    }
  }

  if (!datapath_->StartRoutingNamespace(nsinfo)) {
    LOG(ERROR) << "Failed to setup datapath";
    return response;
  }

  response.set_peer_ifname(nsinfo.peer_ifname);
  response.set_peer_ipv4_address(peer_ipv4_cidr->address().ToInAddr().s_addr);
  response.set_host_ifname(nsinfo.host_ifname);
  response.set_host_ipv4_address(host_ipv4_cidr->address().ToInAddr().s_addr);
  response.set_netns_name(nsinfo.netns_name);
  auto* response_subnet = response.mutable_ipv4_subnet();
  FillSubnetProto(*nsinfo.peer_ipv4_subnet, response_subnet);

  LOG(INFO) << "Connected network namespace " << nsinfo;

  // Start forwarding for IPv6.
  if (!nsinfo.static_ipv6_config.has_value() && current_outbound_device) {
    StartIPv6NDPForwarding(*current_outbound_device, nsinfo.host_ifname);
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&Manager::RestartIPv6, weak_factory_.GetWeakPtr(),
                       nsinfo.netns_name),
        base::Milliseconds(kIPv6RestartDelayMs));
  }

  // Store ConnectedNamespace
  nsinfo.cancel_lifeline_fd = std::move(cancel_lifeline_fd);
  connected_namespaces_.emplace(connected_namespaces_next_id_,
                                std::move(nsinfo));
  connected_namespaces_next_id_++;
  return response;
}

void Manager::OnConnectedNamespaceAutoclose(int connected_namespace_id) {
  // Remove the rules and IP addresses tied to the lifeline fd.
  auto connected_namespace_it =
      connected_namespaces_.find(connected_namespace_id);
  if (connected_namespace_it == connected_namespaces_.end()) {
    return;
  }

  LOG(INFO) << __func__ << ": " << connected_namespace_it->second;

  if (connected_namespace_it->second.current_outbound_device) {
    StopIPv6NDPForwarding(
        *connected_namespace_it->second.current_outbound_device,
        connected_namespace_it->second.host_ifname);
  }
  datapath_->StopRoutingNamespace(connected_namespace_it->second);
  if (connected_namespace_it->second.static_ipv6_config.has_value()) {
    addr_mgr_.ReleaseIPv6Subnet(
        connected_namespace_it->second.static_ipv6_config->host_cidr
            .GetPrefixCIDR());
  }
  // This release the allocated IPv4 subnet.
  connected_namespaces_.erase(connected_namespace_it);
}

void Manager::OnDnsRedirectionRulesAutoclose(int lifeline_fd) {
  auto dns_redirection_it = dns_redirection_rules_.find(lifeline_fd);
  if (dns_redirection_it == dns_redirection_rules_.end()) {
    return;
  }

  auto rule = std::move(dns_redirection_it->second);
  LOG(INFO) << __func__ << ": " << rule;

  datapath_->StopDnsRedirection(rule);
  dns_redirection_rules_.erase(dns_redirection_it);
  // Propagate DNS proxy addresses change.
  if (rule.type == patchpanel::SetDnsRedirectionRuleRequest::ARC) {
    switch (rule.proxy_address.GetFamily()) {
      case net_base::IPFamily::kIPv4:
        dns_proxy_ipv4_addrs_.erase(rule.input_ifname);
        break;
      case net_base::IPFamily::kIPv6:
        dns_proxy_ipv6_addrs_.erase(rule.input_ifname);
        break;
    }
    dbus_client_notifier_->OnNetworkConfigurationChanged();
  }
}

bool Manager::SetDnsRedirectionRule(const SetDnsRedirectionRuleRequest& request,
                                    base::ScopedFD client_fd) {
  int lifeline_fd = client_fd.get();
  auto cancel_lifeline_fd = lifeline_fd_svc_->AddLifelineFD(
      std::move(client_fd),
      base::BindOnce(&Manager::OnDnsRedirectionRulesAutoclose,
                     weak_factory_.GetWeakPtr(), lifeline_fd));
  if (!cancel_lifeline_fd) {
    LOG(ERROR) << __func__ << ": Failed to create lifeline fd";
    return false;
  }

  const auto proxy_address =
      net_base::IPAddress::CreateFromString(request.proxy_address());
  if (!proxy_address) {
    LOG(ERROR) << __func__ << ": proxy_address is invalid IP address: "
               << request.proxy_address();
    return false;
  }
  DnsRedirectionRule rule{.type = request.type(),
                          .input_ifname = request.input_ifname(),
                          .proxy_address = *proxy_address,
                          .host_ifname = request.host_ifname(),
                          .cancel_lifeline_fd = std::move(cancel_lifeline_fd)};

  for (const auto& ns : request.nameservers()) {
    const auto nameserver = net_base::IPAddress::CreateFromString(ns);
    if (!nameserver || nameserver->GetFamily() != proxy_address->GetFamily()) {
      LOG(WARNING) << __func__ << ": Invalid nameserver IP address: " << ns;
    } else {
      rule.nameservers.push_back(*nameserver);
    }
  }

  if (!datapath_->StartDnsRedirection(rule)) {
    LOG(ERROR) << __func__ << ": Failed to setup datapath";
    return false;
  }
  // Notify GuestIPv6Service to add a route for the IPv6 proxy address to the
  // namespace if it did not exist yet, so that the address is reachable.
  if (rule.proxy_address.GetFamily() == net_base::IPFamily::kIPv6) {
    ipv6_svc_->RegisterDownstreamNeighborIP(
        rule.host_ifname, *rule.proxy_address.ToIPv6Address());
  }

  // Propagate DNS proxy addresses change.
  if (rule.type == patchpanel::SetDnsRedirectionRuleRequest::ARC) {
    switch (rule.proxy_address.GetFamily()) {
      case net_base::IPFamily::kIPv4:
        dns_proxy_ipv4_addrs_.emplace(rule.input_ifname,
                                      *rule.proxy_address.ToIPv4Address());
        break;
      case net_base::IPFamily::kIPv6:
        dns_proxy_ipv6_addrs_.emplace(rule.input_ifname,
                                      *rule.proxy_address.ToIPv6Address());
        break;
    }
    dbus_client_notifier_->OnNetworkConfigurationChanged();
  }

  // Store DNS proxy's redirection request.
  dns_redirection_rules_.emplace(lifeline_fd, std::move(rule));
  return true;
}

void Manager::SendGuestMessage(const GuestMessage& msg) {
  ControlMessage cm;
  *cm.mutable_guest_message() = msg;
  adb_proxy_->SendControlMessage(cm);
  mcast_proxy_->SendControlMessage(cm);
}

void Manager::StartIPv6NDPForwarding(const ShillClient::Device& shill_device,
                                     std::string_view ifname_virtual,
                                     std::optional<int> mtu,
                                     std::optional<int> hop_limit) {
  if (shill_device.ifname.empty() || ifname_virtual.empty()) {
    return;
  }

  // TODO(b/325359902): Change GuestIPv6Service interface to take
  // std::string_view and delete conversion here.
  ipv6_svc_->StartForwarding(shill_device, std::string(ifname_virtual), mtu,
                             hop_limit);
}

void Manager::StopIPv6NDPForwarding(const ShillClient::Device& shill_device,
                                    std::string_view ifname_virtual) {
  if (shill_device.ifname.empty()) {
    return;
  }

  if (ifname_virtual.empty()) {
    ipv6_svc_->StopUplink(shill_device);
  } else {
    // TODO(b/325359902): Change GuestIPv6Service interface to take
    // std::string_view and delete conversion here.
    ipv6_svc_->StopForwarding(shill_device, std::string(ifname_virtual));
  }
}

void Manager::StartBroadcastForwarding(const ShillClient::Device& shill_device,
                                       std::string_view ifname_virtual) {
  if (shill_device.ifname.empty() || ifname_virtual.empty()) {
    return;
  }

  LOG(INFO) << "Starting broadcast forwarding from " << shill_device << " to "
            << ifname_virtual;
  ControlMessage cm;
  BroadcastForwardingControlMessage* msg = cm.mutable_bcast_control();
  msg->set_lan_ifname(shill_device.ifname);
  msg->set_int_ifname(ifname_virtual);
  mcast_proxy_->SendControlMessage(cm);
}

void Manager::StopBroadcastForwarding(const ShillClient::Device& shill_device,
                                      std::string_view ifname_virtual) {
  if (shill_device.ifname.empty()) {
    return;
  }

  if (ifname_virtual.empty()) {
    LOG(INFO) << "Stopping broadcast forwarding on " << shill_device;
  } else {
    LOG(INFO) << "Stopping broadcast forwarding from " << shill_device << " to "
              << ifname_virtual;
  }

  ControlMessage cm;
  BroadcastForwardingControlMessage* msg = cm.mutable_bcast_control();
  msg->set_lan_ifname(shill_device.ifname);
  msg->set_teardown(true);
  if (!ifname_virtual.empty()) {
    msg->set_int_ifname(ifname_virtual);
  }
  mcast_proxy_->SendControlMessage(cm);
}

void Manager::StartMulticastForwarding(const ShillClient::Device& shill_device,
                                       std::string_view ifname_virtual,
                                       MulticastForwarder::Direction dir) {
  if (shill_device.ifname.empty() || ifname_virtual.empty()) {
    return;
  }

  if (!IsMulticastInterface(shill_device.ifname)) {
    return;
  }

  LOG(INFO) << "Starting multicast forwarding from " << shill_device << " to "
            << ifname_virtual;
  ControlMessage cm;
  MulticastForwardingControlMessage* msg = cm.mutable_mcast_control();
  msg->set_lan_ifname(shill_device.ifname);
  msg->set_int_ifname(ifname_virtual);
  msg->set_dir(GetMulticastControlMessageDirection(dir));
  mcast_proxy_->SendControlMessage(cm);
}

void Manager::StopMulticastForwarding(const ShillClient::Device& shill_device,
                                      std::string_view ifname_virtual,
                                      MulticastForwarder::Direction dir) {
  if (shill_device.ifname.empty())
    return;

  if (ifname_virtual.empty()) {
    LOG(INFO) << "Stopping multicast forwarding on " << shill_device;
  } else {
    LOG(INFO) << "Stopping multicast forwarding from " << shill_device << " to "
              << ifname_virtual;
  }

  ControlMessage cm;
  MulticastForwardingControlMessage* msg = cm.mutable_mcast_control();
  msg->set_lan_ifname(shill_device.ifname);
  msg->set_teardown(true);
  if (!ifname_virtual.empty()) {
    msg->set_int_ifname(ifname_virtual);
  }
  msg->set_dir(GetMulticastControlMessageDirection(dir));
  mcast_proxy_->SendControlMessage(cm);
}

void Manager::NotifyAndroidWifiMulticastLockChange(bool is_held) {
  auto before = arc_svc_->IsWiFiMulticastForwardingRunning();
  arc_svc_->NotifyAndroidWifiMulticastLockChange(is_held);
  auto after = arc_svc_->IsWiFiMulticastForwardingRunning();
  if (!before && after) {
    multicast_metrics_->OnARCWiFiForwarderStarted();
  } else if (before && !after) {
    multicast_metrics_->OnARCWiFiForwarderStopped();
  }
}

void Manager::NotifyAndroidInteractiveState(bool is_interactive) {
  auto before = arc_svc_->IsWiFiMulticastForwardingRunning();
  arc_svc_->NotifyAndroidInteractiveState(is_interactive);
  auto after = arc_svc_->IsWiFiMulticastForwardingRunning();
  if (!before && after) {
    multicast_metrics_->OnARCWiFiForwarderStarted();
  } else if (before && !after) {
    multicast_metrics_->OnARCWiFiForwarderStopped();
  }

  if (!is_interactive) {
    std::vector<std::string_view> arc_bridge_ifnames;
    for (const auto* arc_device : arc_svc_->GetDevices()) {
      arc_bridge_ifnames.push_back(arc_device->bridge_ifname());
    }
    ipv6_svc_->StartARCPacketFilter(arc_bridge_ifnames);
  } else {
    ipv6_svc_->StopARCPacketFilter();
  }
}

void Manager::NotifySocketConnectionEvent(
    const NotifySocketConnectionEventRequest& request) {
  if (!request.has_msg()) {
    LOG(ERROR) << __func__ << ": no message attached.";
    return;
  }
  qos_svc_->ProcessSocketConnectionEvent(request.msg());
}

void Manager::NotifyARCVPNSocketConnectionEvent(
    const NotifyARCVPNSocketConnectionEventRequest& request) {
  if (!request.has_msg()) {
    LOG(ERROR) << __func__ << ": no message attached.";
    return;
  }
  counters_svc_->HandleARCVPNSocketConnectionEvent(request.msg());
}

bool Manager::SetFeatureFlag(
    patchpanel::SetFeatureFlagRequest::FeatureFlag flag, bool enabled) {
  bool old_flag = false;
  std::string_view feature_name = "Unknown";
  switch (flag) {
    case patchpanel::SetFeatureFlagRequest::FeatureFlag::
        SetFeatureFlagRequest_FeatureFlag_WIFI_QOS:
      feature_name = "WiFi QoS";
      old_flag = qos_svc_->is_enabled();
      if (enabled) {
        qos_svc_->Enable();
      } else {
        qos_svc_->Disable();
      }
      break;
    case patchpanel::SetFeatureFlagRequest::FeatureFlag::
        SetFeatureFlagRequest_FeatureFlag_CLAT:
      feature_name = "CLAT";
      old_flag = clat_svc_->is_enabled();
      if (enabled) {
        clat_svc_->Enable();
      } else {
        clat_svc_->Disable();
      }
      break;
    default:
      LOG(ERROR) << __func__ << "Unknown feature flag: " << flag;
      break;
  }

  LOG(INFO) << __func__ << ": set " << feature_name << " to " << enabled
            << " from " << old_flag;
  return old_flag;
}

}  // namespace patchpanel
