// Copyright 2021 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 "shill/vpn/wireguard_driver.h"

#include <poll.h>
#include <sys/utsname.h>

#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/base64.h>
#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/files/file_util.h>
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/stl_util.h>
#include <base/strings/strcat.h>
#include <base/strings/string_split.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <base/version.h>
#include <chromeos/dbus/service_constants.h>
#include <crypto/random.h>

#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/process_manager.h"
#include "shill/property_accessor.h"
#include "shill/store_interface.h"
#include "shill/vpn/vpn_util.h"

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kVPN;
static std::string ObjectID(const WireGuardDriver*) {
  return "(wireguard_driver)";
}
}  // namespace Logging

namespace {

constexpr char kWireGuardPath[] = "/usr/sbin/wireguard";
constexpr char kWireGuardToolsPath[] = "/usr/bin/wg";
constexpr char kDefaultInterfaceName[] = "wg0";

// The name of the property which indicates where the key pair comes from. This
// property only appears in storage but not in D-Bus API.
constexpr char kWireGuardKeyPairSource[] = "WireGuard.KeyPairSource";

// Timeout value for spawning the userspace wireguard process and configuring
// the interface via wireguard-tools.
constexpr base::TimeDelta kConnectTimeout = base::TimeDelta::FromSeconds(10);

// Key length of Curve25519.
constexpr int kWgKeyLength = 32;
constexpr int kWgBase64KeyLength = (((kWgKeyLength) + 2) / 3) * 4;

// Properties of a peer.
struct PeerProperty {
  // A name will be used in 1) D-Bus API, 2) profile storage, and 3) config file
  // passed to wireguard-tools.
  const char* const name;
  // Checked only before connecting. We allow a partially configured service
  // from crosh.
  const bool is_required;
};
constexpr PeerProperty kPeerProperties[] = {
    {kWireGuardPeerPublicKey, true},
    {kWireGuardPeerPresharedKey, false},
    {kWireGuardPeerEndpoint, true},
    {kWireGuardPeerAllowedIPs, false},
    {kWireGuardPeerPersistentKeepalive, false},
};

// Checks the given peers object is valid for kept by WireguardDriver (it means
// this peers can be persisted in the storage but may be not ready for
// connecting). Here we checks whether each peer has a unique and non-empty
// public key.
bool ValidatePeersForStorage(const Stringmaps& peers) {
  std::set<std::string> public_keys;
  for (auto& peer : peers) {
    const auto it = peer.find(kWireGuardPeerPublicKey);
    if (it == peer.end()) {
      return false;
    }
    const std::string& this_pubkey = it->second;
    if (this_pubkey.empty()) {
      return false;
    }
    if (public_keys.count(this_pubkey) != 0) {
      return false;
    }
    public_keys.insert(this_pubkey);
  }
  return true;
}

std::string GenerateBase64PrivateKey() {
  uint8_t key[kWgKeyLength];
  crypto::RandBytes(key, kWgKeyLength);

  // Converts the random bytes into a Curve25519 key, as per
  // https://cr.yp.to/ecdh.html
  key[0] &= 248;
  key[31] &= 127;
  key[31] |= 64;

  return base::Base64Encode(base::span<uint8_t>(key, kWgKeyLength));
}

// Invokes wireguard-tools to calculates the public key based on the given
// private key. Returns an empty string on error. Note that the call to
// wireguard-tools is blocking but with a timeout (kPollTimeout below).
std::string CalculateBase64PublicKey(const std::string& base64_private_key,
                                     ProcessManager* process_manager) {
  constexpr auto kPollTimeout = base::TimeDelta::FromMilliseconds(200);

  int stdin_fd = -1;
  int stdout_fd = -1;
  pid_t pid = process_manager->StartProcessInMinijailWithPipes(
      FROM_HERE, base::FilePath(kWireGuardToolsPath), {"pubkey"},
      /*environment=*/{}, VPNUtil::kVPNUser, VPNUtil::kVPNGroup, /*caps=*/0,
      /*inherit_supplementary_groups=*/true, /*close_nonstd_fds=*/true,
      /*exit_callback=*/base::DoNothing(),
      {.stdin_fd = &stdin_fd, .stdout_fd = &stdout_fd});
  if (pid == -1) {
    LOG(ERROR) << "Failed to run 'wireguard-tools pubkey'";
    return "";
  }

  base::ScopedFD scoped_stdin(stdin_fd);
  base::ScopedFD scoped_stdout(stdout_fd);

  if (!base::WriteFileDescriptor(scoped_stdin.get(), base64_private_key)) {
    LOG(ERROR) << "Failed to send private key to wireguard-tools";
    process_manager->StopProcess(pid);
    return "";
  }
  scoped_stdin.reset();

  struct pollfd pollfds[] = {{
      .fd = scoped_stdout.get(),
      .events = POLLIN,
  }};
  int ret = poll(pollfds, 1, kPollTimeout.InMilliseconds());
  if (ret == -1) {
    PLOG(ERROR) << "poll() failed";
    process_manager->StopProcess(pid);
    return "";
  } else if (ret == 0) {
    LOG(ERROR) << "poll() timeout";
    process_manager->StopProcess(pid);
    return "";
  }

  char buf[kWgBase64KeyLength];
  ssize_t read_cnt =
      HANDLE_EINTR(read(scoped_stdout.get(), buf, size_t{kWgBase64KeyLength}));
  if (read_cnt == -1) {
    PLOG(ERROR) << "read() failed";
    process_manager->StopProcess(pid);
    return "";
  } else if (read_cnt != kWgBase64KeyLength) {
    LOG(ERROR) << "Failed to read enough chars for a public key. read_cnt="
               << read_cnt;
    process_manager->StopProcess(pid);
    return "";
  }

  return std::string{buf, std::string::size_type{kWgBase64KeyLength}};
}

// Checks if the input string value for a property contains any invalid
// characters which can pollute the config file. Currently only '\n' is checked,
// which may generate a new parsable line.
bool ValidateInputString(const std::string& value) {
  return value.find('\n') == value.npos;
}

}  // namespace

// static
const VPNDriver::Property WireGuardDriver::kProperties[] = {
    {kProviderHostProperty, 0},
    {kProviderTypeProperty, 0},

    // Properties for the interface. ListenPort is not here since we current
    // only support the "client mode". Local overlay addresses on the interface,
    // DNS servers, and MTU will be set via StaticIPConfig.
    {kWireGuardPrivateKey, Property::kCredential | Property::kWriteOnly},
    // TODO(b/177877860): This field is for software-backed keys only. May need
    // to change this logic when hardware-backed keys come.
    {kWireGuardPublicKey, Property::kReadOnly},
};

WireGuardDriver::WireGuardDriver(Manager* manager,
                                 ProcessManager* process_manager)
    : VPNDriver(manager, process_manager, kProperties, base::size(kProperties)),
      vpn_util_(VPNUtil::New()) {}

WireGuardDriver::~WireGuardDriver() {
  Cleanup();
}

base::TimeDelta WireGuardDriver::ConnectAsync(EventHandler* event_handler) {
  SLOG(this, 2) << __func__;
  event_handler_ = event_handler;
  // To make sure the connect procedure is executed asynchronously.
  dispatcher()->PostTask(
      FROM_HERE,
      base::BindOnce(&WireGuardDriver::CreateKernelWireGuardInterface,
                     weak_factory_.GetWeakPtr()));
  return kConnectTimeout;
}

void WireGuardDriver::Disconnect() {
  SLOG(this, 2) << __func__;
  Cleanup();
  event_handler_ = nullptr;
}

IPConfig::Properties WireGuardDriver::GetIPProperties() const {
  return ip_properties_;
}

std::string WireGuardDriver::GetProviderType() const {
  return kProviderWireGuard;
}

void WireGuardDriver::OnConnectTimeout() {
  FailService(Service::kFailureConnect, "Connect timeout");
}

void WireGuardDriver::InitPropertyStore(PropertyStore* store) {
  VPNDriver::InitPropertyStore(store);
  store->RegisterDerivedStringmaps(
      kWireGuardPeers,
      StringmapsAccessor(
          new CustomWriteOnlyAccessor<WireGuardDriver, Stringmaps>(
              this, &WireGuardDriver::UpdatePeers, &WireGuardDriver::ClearPeers,
              nullptr)));
}

KeyValueStore WireGuardDriver::GetProvider(Error* error) {
  KeyValueStore props = VPNDriver::GetProvider(error);
  Stringmaps copied_peers = peers_;
  for (auto& peer : copied_peers) {
    peer.erase(kWireGuardPeerPresharedKey);
  }
  props.Set<Stringmaps>(kWireGuardPeers, copied_peers);
  return props;
}

bool WireGuardDriver::Load(const StoreInterface* storage,
                           const std::string& storage_id) {
  if (!VPNDriver::Load(storage, storage_id)) {
    return false;
  }

  peers_.clear();

  std::vector<std::string> encoded_peers;
  if (!storage->GetStringList(storage_id, kWireGuardPeers, &encoded_peers)) {
    LOG(WARNING) << "Profile does not contain the " << kWireGuardPeers
                 << " property";
    return true;
  }

  for (const auto& peer_json : encoded_peers) {
    base::Optional<base::Value> val = base::JSONReader::Read(peer_json);
    if (!val || !val->is_dict()) {
      LOG(ERROR) << "Failed to parse a peer. Skipped it.";
      continue;
    }
    Stringmap peer;
    for (const auto& property : kPeerProperties) {
      const std::string key = property.name;
      const auto* value = val->FindStringKey(key);
      if (value != nullptr) {
        peer[key] = *value;
      } else {
        peer[key] = "";
      }
    }
    peers_.push_back(peer);
  }

  if (!ValidatePeersForStorage(peers_)) {
    LOG(ERROR) << "Failed to load peers: missing PublicKey property or the "
                  "value is not unique";
    peers_.clear();
    return false;
  }

  // Loads |key_pair_source_|;
  int stored_value = 0;
  if (!storage->GetInt(storage_id, kWireGuardKeyPairSource, &stored_value)) {
    stored_value = Metrics::kVpnWireguardKeyPairSourceUnknown;
  }
  if (stored_value != Metrics::kVpnWireGuardKeyPairSourceUserInput &&
      stored_value != Metrics::kVpnWireGuardKeyPairSourceSoftwareGenerated) {
    LOG(ERROR) << kWireGuardKeyPairSource
               << " contains an invalid value or does not exist in storage: "
               << stored_value;
    stored_value = Metrics::kVpnWireguardKeyPairSourceUnknown;
  }
  key_pair_source_ =
      static_cast<Metrics::VpnWireGuardKeyPairSource>(stored_value);

  saved_private_key_ = args()->Lookup<std::string>(kWireGuardPrivateKey, "");

  return true;
}

bool WireGuardDriver::Save(StoreInterface* storage,
                           const std::string& storage_id,
                           bool save_credentials) {
  if (!save_credentials) {
    LOG(WARNING) << "save_credentials is false when saving to the storage.";
  }

  // Keys should be processed before calling VPNDriver::Save().
  auto private_key = args()->Lookup<std::string>(kWireGuardPrivateKey, "");
  if (private_key.empty()) {
    private_key = GenerateBase64PrivateKey();
    args()->Set<std::string>(kWireGuardPrivateKey, private_key);
    // The user cleared the private key.
    key_pair_source_ = Metrics::kVpnWireGuardKeyPairSourceSoftwareGenerated;
  } else if (private_key != saved_private_key_) {
    // Note that this branch is different with the if statement below: if the
    // private key in args() is not empty before we fill a random one in it, it
    // must be changed by the user, and this code path is the only way where the
    // user use its own private key.
    key_pair_source_ = Metrics::kVpnWireGuardKeyPairSourceUserInput;
  }
  if (private_key != saved_private_key_) {
    std::string public_key =
        CalculateBase64PublicKey(private_key, process_manager());
    if (public_key.empty()) {
      LOG(ERROR) << "Failed to calculate public key in Save().";
      return false;
    }
    args()->Set<std::string>(kWireGuardPublicKey, public_key);
    saved_private_key_ = private_key;
  }

  // Handles peers.
  std::vector<std::string> encoded_peers;
  for (auto& peer : peers_) {
    base::Value root(base::Value::Type::DICTIONARY);
    for (const auto& property : kPeerProperties) {
      const auto& key = property.name;
      root.SetStringKey(key, peer[key]);
    }
    std::string peer_json;
    if (!base::JSONWriter::Write(root, &peer_json)) {
      LOG(ERROR) << "Failed to write a peer into json";
      return false;
    }
    encoded_peers.push_back(peer_json);
  }

  if (!storage->SetStringList(storage_id, kWireGuardPeers, encoded_peers)) {
    LOG(ERROR) << "Failed to write " << kWireGuardPeers
               << " property into profile";
    return false;
  }

  if (!storage->SetInt(storage_id, kWireGuardKeyPairSource, key_pair_source_)) {
    LOG(ERROR) << "Failed to write " << kWireGuardKeyPairSource
               << " property into profile";
    return false;
  }

  return VPNDriver::Save(storage, storage_id, save_credentials);
}

void WireGuardDriver::UnloadCredentials() {
  VPNDriver::UnloadCredentials();
  for (auto& peer : peers_) {
    // For a peer loaded by Load(), all properties should exist even if they are
    // empty, so we only clear the value here, instead of erasing the key.
    peer[kWireGuardPeerPresharedKey] = "";
  }
}

void WireGuardDriver::CreateKernelWireGuardInterface() {
  auto link_ready_callback = base::BindOnce(
      &WireGuardDriver::ConfigureInterface, weak_factory_.GetWeakPtr(),
      /*created_in_kernel=*/true);
  auto failure_callback =
      base::BindOnce(&WireGuardDriver::StartUserspaceWireGuardTunnel,
                     weak_factory_.GetWeakPtr());
  if (!manager()->device_info()->CreateWireGuardInterface(
          kDefaultInterfaceName, std::move(link_ready_callback),
          std::move(failure_callback))) {
    StartUserspaceWireGuardTunnel();
  }
}

void WireGuardDriver::StartUserspaceWireGuardTunnel() {
  LOG(INFO) << "Failed to create a wireguard interface in the kernel. Fallback "
               "to userspace tunnel.";

  // Claims the interface before the wireguard process creates it.
  // TODO(b/177876632): Actually when the tunnel interface is ready, it cannot
  // guarantee that the wireguard-tools can talk with the userspace wireguard
  // process now. We should also wait for another event that the UAPI socket
  // appears (which is a UNIX-domain socket created by the userspace wireguard
  // process at a fixed path: `/var/run/wireguard/wg0.sock`).
  manager()->device_info()->AddVirtualInterfaceReadyCallback(
      kDefaultInterfaceName,
      base::BindOnce(&WireGuardDriver::ConfigureInterface,
                     weak_factory_.GetWeakPtr(),
                     /*created_in_kernel=*/false));

  if (!SpawnWireGuard()) {
    FailService(Service::kFailureInternal, "Failed to spawn wireguard process");
  }
}

bool WireGuardDriver::SpawnWireGuard() {
  SLOG(this, 2) << __func__;

  // TODO(b/177876632): Change this part after we decide the userspace binary to
  // use. For wireguard-go, we need to change the way to invoke minijail; for
  // wireugard-rs, we need to add `--disable-drop-privileges` or change the
  // capmask.
  std::vector<std::string> args = {
      "--foreground",
      kDefaultInterfaceName,
  };
  constexpr uint64_t kCapMask = CAP_TO_MASK(CAP_NET_ADMIN);
  wireguard_pid_ = process_manager()->StartProcessInMinijail(
      FROM_HERE, base::FilePath(kWireGuardPath), args,
      /*environment=*/{}, VPNUtil::kVPNUser, VPNUtil::kVPNGroup, kCapMask,
      /*inherit_supplementary_groups=*/true, /*close_nonstd_fds=*/true,
      base::BindRepeating(&WireGuardDriver::WireGuardProcessExited,
                          weak_factory_.GetWeakPtr()));
  return wireguard_pid_ > -1;
}

void WireGuardDriver::WireGuardProcessExited(int exit_code) {
  wireguard_pid_ = -1;
  FailService(
      Service::kFailureInternal,
      base::StringPrintf("wireguard process exited unexpectedly with code=%d",
                         exit_code));
}

std::string WireGuardDriver::GenerateConfigFileContents() {
  std::vector<std::string> lines;

  // [Interface] section
  lines.push_back("[Interface]");
  const std::string private_key =
      args()->Lookup<std::string>(kWireGuardPrivateKey, "");
  if (!ValidateInputString(private_key)) {
    LOG(ERROR) << "PrivateKey contains invalid characters.";
    return "";
  }
  if (private_key.empty()) {
    LOG(ERROR) << "PrivateKey is required but is empty or not set.";
    return "";
  }
  lines.push_back(base::StrCat({"PrivateKey", "=", private_key}));
  // 0x4000 for bypass VPN, 0x0500 for source of host VPN.
  // See patchpanel/routing_service.h for their definitions.
  lines.push_back("FwMark=0x4500");

  lines.push_back("");

  // [Peer] sections
  for (auto& peer : peers_) {
    lines.push_back("[Peer]");
    for (const auto& property : kPeerProperties) {
      const std::string val = peer[property.name];
      if (!ValidateInputString(val)) {
        LOG(ERROR) << property.name << " contains invalid characters.";
        return "";
      }
      if (!val.empty()) {
        lines.push_back(base::StrCat({property.name, "=", val}));
      } else if (property.is_required) {
        LOG(ERROR) << property.name
                   << " in a peer is required but is empty or not set.";
        return "";
      }
    }
    lines.push_back("");
  }

  return base::JoinString(lines, "\n");
}

void WireGuardDriver::ConfigureInterface(bool created_in_kernel,
                                         const std::string& interface_name,
                                         int interface_index) {
  LOG(INFO) << "WireGuard interface " << interface_name << " was created "
            << (created_in_kernel ? "in kernel" : "by userspace program")
            << ". Start configuration";
  kernel_interface_open_ = created_in_kernel;

  if (!event_handler_) {
    LOG(ERROR) << "Missing event_handler_";
    Cleanup();
    return;
  }

  interface_index_ = interface_index;

  // Writes config file.
  std::string config_contents = GenerateConfigFileContents();
  if (config_contents.empty()) {
    FailService(Service::kFailureInternal,
                "Failed to generate config file contents");
    return;
  }
  auto [fd, path] = vpn_util_->WriteAnonymousConfigFile(config_contents);
  config_fd_ = std::move(fd);
  if (!config_fd_.is_valid()) {
    FailService(Service::kFailureInternal, "Failed to write config file");
    return;
  }

  // Executes wireguard-tools.
  std::vector<std::string> args = {"setconf", kDefaultInterfaceName,
                                   path.value()};
  constexpr uint64_t kCapMask = CAP_TO_MASK(CAP_NET_ADMIN);
  pid_t pid = process_manager()->StartProcessInMinijail(
      FROM_HERE, base::FilePath(kWireGuardToolsPath), args,
      /*environment=*/{}, VPNUtil::kVPNUser, VPNUtil::kVPNGroup, kCapMask,
      /*inherit_supplementary_groups=*/true, /*close_nonstd_fds=*/false,
      base::BindRepeating(&WireGuardDriver::OnConfigurationDone,
                          weak_factory_.GetWeakPtr()));
  if (pid == -1) {
    FailService(Service::kFailureInternal, "Failed to run `wg setconf`");
    return;
  }
}

void WireGuardDriver::OnConfigurationDone(int exit_code) {
  SLOG(this, 2) << __func__ << ": exit_code=" << exit_code;

  // Closes the config file to remove it.
  config_fd_.reset();

  if (exit_code != 0) {
    FailService(
        Service::kFailureInternal,
        base::StringPrintf("Failed to run `wg setconf`, code=%d", exit_code));
    return;
  }

  if (!PopulateIPProperties()) {
    FailService(Service::kFailureInternal, "Failed to populate ip properties");
    return;
  }

  ReportConnectionMetrics();

  event_handler_->OnDriverConnected(kDefaultInterfaceName, interface_index_);
}

bool WireGuardDriver::PopulateIPProperties() {
  ip_properties_.default_route = false;

  // When we arrive here, the value of AllowedIPs has already been validated
  // by wireguard-tools. AllowedIPs is comma-separated list of CIDR-notation
  // addresses (e.g., "10.8.0.1/16,192.168.1.1/24").
  for (auto& peer : peers_) {
    std::string allowed_ips_str = peer[kWireGuardPeerAllowedIPs];
    std::vector<std::string> allowed_ip_list = base::SplitString(
        allowed_ips_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    for (const auto& allowed_ip_str : allowed_ip_list) {
      IPAddress allowed_ip;
      // Currently only supports IPv4 addresses.
      allowed_ip.set_family(IPAddress::kFamilyIPv4);
      if (!allowed_ip.SetAddressAndPrefixFromString(allowed_ip_str)) {
        LOG(DFATAL) << "Invalid allowed ip: " << allowed_ip_str;
        return false;
      }
      // We don't need a gateway here, so use the "default" address as the
      // gateways, and then RoutingTable will skip RTA_GATEWAY when installing
      // this entry.
      ip_properties_.routes.push_back({allowed_ip.GetNetworkPart().ToString(),
                                       static_cast<int>(allowed_ip.prefix()),
                                       /*gateway=*/"0.0.0.0"});
    }
  }
  ip_properties_.method = kTypeVPN;
  return true;
}

void WireGuardDriver::FailService(Service::ConnectFailure failure,
                                  const std::string& error_details) {
  LOG(ERROR) << "Driver error: " << error_details;
  Cleanup();
  if (event_handler_) {
    event_handler_->OnDriverFailure(failure, error_details);
    event_handler_ = nullptr;
  }
}

void WireGuardDriver::Cleanup() {
  if (wireguard_pid_ != -1) {
    process_manager()->StopProcess(wireguard_pid_);
    wireguard_pid_ = -1;
  }
  if (kernel_interface_open_) {
    manager()->device_info()->DeleteInterface(interface_index_);
    kernel_interface_open_ = false;
  }
  interface_index_ = -1;
  ip_properties_ = {};
  config_fd_.reset();
}

bool WireGuardDriver::UpdatePeers(const Stringmaps& new_peers, Error* error) {
  if (!ValidatePeersForStorage(new_peers)) {
    Error::PopulateAndLog(
        FROM_HERE, error, Error::kInvalidProperty,
        "Invalid peers: missing PublicKey property or the value is not unique");
    return false;
  }

  // If the preshared key of a peer in the new peers is unspecified (the caller
  // doesn't set that key), try to reset it to the old value.
  Stringmap pubkey_to_psk;
  for (auto& peer : peers_) {
    pubkey_to_psk[peer[kWireGuardPeerPublicKey]] =
        peer[kWireGuardPeerPresharedKey];
  }

  peers_ = new_peers;
  for (auto& peer : peers_) {
    if (peer.find(kWireGuardPeerPresharedKey) != peer.end()) {
      continue;
    }
    peer[kWireGuardPeerPresharedKey] =
        pubkey_to_psk[peer[kWireGuardPeerPublicKey]];
  }

  return true;
}

void WireGuardDriver::ClearPeers(Error* error) {
  peers_.clear();
}

void WireGuardDriver::ReportConnectionMetrics() {
  // VPN type.
  metrics()->SendEnumToUMA(Metrics::kMetricVpnDriver,
                           Metrics::kVpnDriverWireGuard,
                           Metrics::kMetricVpnDriverMax);

  // Key pair source.
  metrics()->SendEnumToUMA(Metrics::kMetricVpnWireGuardKeyPairSource,
                           key_pair_source_,
                           Metrics::kMetricVpnWireGuardKeyPairSourceMax);

  // Number of peers.
  metrics()->SendToUMA(Metrics::kMetricVpnWireGuardPeersNum, peers_.size(),
                       Metrics::kMetricVpnWireGuardPeersNumMin,
                       Metrics::kMetricVpnWireGuardPeersNumMax,
                       Metrics::kMetricVpnWireGuardPeersNumNumBuckets);

  // Allowed IPs type.
  // TODO(b/194243702): Collect metrics for IPv6 usages in Allowed IPs.
  auto allowed_ips_type = Metrics::kVpnWireGuardAllowedIPsTypeNoDefaultRoute;
  for (auto peer : peers_) {
    if (peer[kWireGuardPeerAllowedIPs].find("0.0.0.0/0") != std::string::npos) {
      allowed_ips_type = Metrics::kVpnWireGuardAllowedIPsTypeHasDefaultRoute;
      break;
    }
  }
  metrics()->SendEnumToUMA(Metrics::kMetricVpnWireGuardAllowedIPsType,
                           allowed_ips_type,
                           Metrics::kMetricVpnWireGuardAllowedIPsTypeMax);
}

// static
bool WireGuardDriver::IsSupported() {
  // WireGuard is current supported on kernel version >= 5.10
  struct utsname buf;
  if (uname(&buf) != 0) {
    return false;
  }
  // Extract the numeric part of release string
  std::string version = base::SplitString(
      buf.release, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)[0];
  base::Version kernel_version = base::Version(version);
  return kernel_version.IsValid() && kernel_version >= base::Version("5.10");
}

}  // namespace shill
