// 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 "shill/dhcp/dhcpv4_config.h"

#include <arpa/inet.h>

#include <base/files/file_util.h>
#include <base/stl_util.h>
#include <base/strings/string_split.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/dhcp/dhcp_provider.h"
#include "shill/logging.h"
#include "shill/metrics.h"
#include "shill/net/ip_address.h"

using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDHCP;
static string ObjectID(const DHCPv4Config* d) {
  if (d == nullptr)
    return "(DHCPv4_config)";
  else
    return d->device_name();
}
}  // namespace Logging

// static
const char DHCPv4Config::kDHCPCDPathFormatPID[] =
    "var/run/dhcpcd/dhcpcd-%s-4.pid";
const char DHCPv4Config::kConfigurationKeyBroadcastAddress[] =
    "BroadcastAddress";
const char DHCPv4Config::kConfigurationKeyClasslessStaticRoutes[] =
    "ClasslessStaticRoutes";
const char DHCPv4Config::kConfigurationKeyDNS[] = "DomainNameServers";
const char DHCPv4Config::kConfigurationKeyDomainName[] = "DomainName";
const char DHCPv4Config::kConfigurationKeyDomainSearch[] = "DomainSearch";
const char DHCPv4Config::kConfigurationKeyHostname[] = "Hostname";
const char DHCPv4Config::kConfigurationKeyIPAddress[] = "IPAddress";
const char DHCPv4Config::kConfigurationKeyiSNSOptionData[] = "iSNSOptionData";
const char DHCPv4Config::kConfigurationKeyLeaseTime[] = "DHCPLeaseTime";
const char DHCPv4Config::kConfigurationKeyMTU[] = "InterfaceMTU";
const char DHCPv4Config::kConfigurationKeyRouters[] = "Routers";
const char DHCPv4Config::kConfigurationKeySubnetCIDR[] = "SubnetCIDR";
const char DHCPv4Config::kConfigurationKeyVendorEncapsulatedOptions[] =
    "VendorEncapsulatedOptions";
const char DHCPv4Config::kConfigurationKeyWebProxyAutoDiscoveryUrl[] =
    "WebProxyAutoDiscoveryUrl";
const char DHCPv4Config::kReasonBound[] = "BOUND";
const char DHCPv4Config::kReasonFail[] = "FAIL";
const char DHCPv4Config::kReasonGatewayArp[] = "GATEWAY-ARP";
const char DHCPv4Config::kReasonNak[] = "NAK";
const char DHCPv4Config::kReasonRebind[] = "REBIND";
const char DHCPv4Config::kReasonReboot[] = "REBOOT";
const char DHCPv4Config::kReasonRenew[] = "RENEW";
const char DHCPv4Config::kStatusArpGateway[] = "ArpGateway";
const char DHCPv4Config::kStatusArpSelf[] = "ArpSelf";
const char DHCPv4Config::kStatusBound[] = "Bound";
const char DHCPv4Config::kStatusDiscover[] = "Discover";
const char DHCPv4Config::kStatusIgnoreAdditionalOffer[] =
    "IgnoreAdditionalOffer";
const char DHCPv4Config::kStatusIgnoreFailedOffer[] = "IgnoreFailedOffer";
const char DHCPv4Config::kStatusIgnoreInvalidOffer[] = "IgnoreInvalidOffer";
const char DHCPv4Config::kStatusIgnoreNonOffer[] = "IgnoreNonOffer";
const char DHCPv4Config::kStatusInform[] = "Inform";
const char DHCPv4Config::kStatusInit[] = "Init";
const char DHCPv4Config::kStatusNakDefer[] = "NakDefer";
const char DHCPv4Config::kStatusRebind[] = "Rebind";
const char DHCPv4Config::kStatusReboot[] = "Reboot";
const char DHCPv4Config::kStatusRelease[] = "Release";
const char DHCPv4Config::kStatusRenew[] = "Renew";
const char DHCPv4Config::kStatusRequest[] = "Request";
const char DHCPv4Config::kType[] = "dhcp";

DHCPv4Config::DHCPv4Config(ControlInterface* control_interface,
                           EventDispatcher* dispatcher,
                           DHCPProvider* provider,
                           const string& device_name,
                           const string& lease_file_suffix,
                           bool arp_gateway,
                           const DhcpProperties& dhcp_props,
                           Metrics* metrics)
    : DHCPConfig(control_interface,
                 dispatcher,
                 provider,
                 device_name,
                 kType,
                 lease_file_suffix),
      arp_gateway_(arp_gateway),
      is_gateway_arp_active_(false),
      metrics_(metrics) {
  dhcp_props.GetValueForProperty(DhcpProperties::kHostnameProperty, &hostname_);
  dhcp_props.GetValueForProperty(DhcpProperties::kVendorClassProperty,
                                 &vendor_class_);
  SLOG(this, 2) << __func__ << ": " << device_name;
}

DHCPv4Config::~DHCPv4Config() {
  SLOG(this, 2) << __func__ << ": " << device_name();
}

void DHCPv4Config::ProcessEventSignal(const string& reason,
                                      const KeyValueStore& configuration) {
  LOG(INFO) << "Event reason: " << reason;
  if (reason == kReasonFail) {
    LOG(ERROR) << "Received failure event from DHCP client.";
    NotifyFailure();
    return;
  } else if (reason == kReasonNak) {
    // If we got a NAK, this means the DHCP server is active, and any
    // Gateway ARP state we have is no longer sufficient.
    LOG_IF(ERROR, is_gateway_arp_active_)
        << "Received NAK event for our gateway-ARP lease.";
    is_gateway_arp_active_ = false;
    return;
  } else if (reason != kReasonBound && reason != kReasonRebind &&
             reason != kReasonReboot && reason != kReasonRenew &&
             reason != kReasonGatewayArp) {
    LOG(WARNING) << "Event ignored.";
    return;
  }
  IPConfig::Properties properties;
  CHECK(ParseConfiguration(configuration, &properties));

  // This needs to be set before calling UpdateProperties() below since
  // those functions may indirectly call other methods like ReleaseIP that
  // depend on or change this value.
  set_is_lease_active(true);

  if (reason == kReasonGatewayArp) {
    // This is a non-authoritative confirmation that we or on the same
    // network as the one we received a lease on previously.  The DHCP
    // client is still running, so we should not cancel the timeout
    // until that completes.  In the meantime, however, we can tentatively
    // configure our network in anticipation of successful completion.
    IPConfig::UpdateProperties(properties, false);
    is_gateway_arp_active_ = true;
  } else {
    DHCPConfig::UpdateProperties(properties, true);
    is_gateway_arp_active_ = false;
  }
}

void DHCPv4Config::ProcessStatusChangeSignal(const string& status) {
  SLOG(this, 2) << __func__ << ": " << status;

  if (status == kStatusArpGateway) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusArpGateway);
  } else if (status == kStatusArpSelf) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusArpSelf);
  } else if (status == kStatusBound) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusBound);
  } else if (status == kStatusDiscover) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusDiscover);
  } else if (status == kStatusIgnoreAdditionalOffer) {
    metrics_->NotifyDhcpClientStatus(
        Metrics::kDhcpClientStatusIgnoreAdditionalOffer);
  } else if (status == kStatusIgnoreFailedOffer) {
    metrics_->NotifyDhcpClientStatus(
        Metrics::kDhcpClientStatusIgnoreFailedOffer);
  } else if (status == kStatusIgnoreInvalidOffer) {
    metrics_->NotifyDhcpClientStatus(
        Metrics::kDhcpClientStatusIgnoreInvalidOffer);
  } else if (status == kStatusIgnoreNonOffer) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusIgnoreNonOffer);
  } else if (status == kStatusInform) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusInform);
  } else if (status == kStatusInit) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusInit);
  } else if (status == kStatusNakDefer) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusNakDefer);
  } else if (status == kStatusRebind) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusRebind);
  } else if (status == kStatusReboot) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusReboot);
  } else if (status == kStatusRelease) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusRelease);
  } else if (status == kStatusRenew) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusRenew);
  } else if (status == kStatusRequest) {
    metrics_->NotifyDhcpClientStatus(Metrics::kDhcpClientStatusRequest);
  } else {
    LOG(ERROR) << "DHCP client reports unknown status " << status;
  }
}

void DHCPv4Config::CleanupClientState() {
  DHCPConfig::CleanupClientState();

  // Delete lease file if it is ephemeral.
  if (IsEphemeralLease()) {
    base::DeleteFile(
        root().Append(base::StringPrintf(DHCPProvider::kDHCPCDPathFormatLease,
                                         device_name().c_str())),
        false);
  }
  base::DeleteFile(root().Append(base::StringPrintf(kDHCPCDPathFormatPID,
                                                    device_name().c_str())),
                   false);
  is_gateway_arp_active_ = false;
}

bool DHCPv4Config::ShouldFailOnAcquisitionTimeout() {
  // Continue to use previous lease if gateway ARP is active.
  return !is_gateway_arp_active_;
}

bool DHCPv4Config::ShouldKeepLeaseOnDisconnect() {
  // If we are using gateway unicast ARP to speed up re-connect, don't
  // give up our leases when we disconnect.
  return arp_gateway_;
}

vector<string> DHCPv4Config::GetFlags() {
  // Get default flags first.
  vector<string> flags = DHCPConfig::GetFlags();

  flags.push_back("-4");  // IPv4 only.

  // Apply options from DhcpProperties when applicable.
  if (!hostname_.empty()) {
    flags.push_back("-h");  // Request hostname from server
    flags.push_back(hostname_);
  }
  if (!vendor_class_.empty()) {
    flags.push_back("-i");
    flags.push_back(vendor_class_);
  }

  if (arp_gateway_) {
    flags.push_back("-R");  // ARP for default gateway.
    flags.push_back("-P");  // Enable unicast ARP on renew.
  }
  return flags;
}

// static
string DHCPv4Config::GetIPv4AddressString(unsigned int address) {
  char str[INET_ADDRSTRLEN];
  if (inet_ntop(AF_INET, &address, str, base::size(str))) {
    return str;
  }
  LOG(ERROR) << "Unable to convert IPv4 address to string: " << address;
  return "";
}

// static
bool DHCPv4Config::ParseClasslessStaticRoutes(
    const string& classless_routes, IPConfig::Properties* properties) {
  if (classless_routes.empty()) {
    // It is not an error for this string to be empty.
    return true;
  }

  vector<string> route_strings = base::SplitString(
      classless_routes, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (route_strings.size() % 2) {
    LOG(ERROR) << "In " << __func__ << ": Size of route_strings array "
               << "is a non-even number: " << route_strings.size();
    return false;
  }

  vector<IPConfig::Route> routes;
  vector<string>::iterator route_iterator = route_strings.begin();
  // Classless routes are a space-delimited array of
  // "destination/prefix gateway" values.  As such, we iterate twice
  // for each pass of the loop below.
  while (route_iterator != route_strings.end()) {
    const string& destination_as_string(*route_iterator);
    route_iterator++;
    IPAddress destination(IPAddress::kFamilyIPv4);
    if (!destination.SetAddressAndPrefixFromString(destination_as_string)) {
      LOG(ERROR) << "In " << __func__ << ": Expected an IP address/prefix "
                 << "but got an unparsable: " << destination_as_string;
      return false;
    }

    CHECK(route_iterator != route_strings.end());
    const string& gateway_as_string(*route_iterator);
    route_iterator++;
    IPAddress gateway(IPAddress::kFamilyIPv4);
    if (!gateway.SetAddressFromString(gateway_as_string)) {
      LOG(ERROR) << "In " << __func__ << ": Expected a router IP address "
                 << "but got an unparsable: " << gateway_as_string;
      return false;
    }

    if (destination.prefix() == 0 && properties->gateway.empty()) {
      // If a default route is provided in the classless parameters and
      // we don't already have one, apply this as the default route.
      SLOG(nullptr, 2) << "In " << __func__ << ": Setting default gateway to "
                       << gateway_as_string;
      CHECK(gateway.IntoString(&properties->gateway));
    } else {
      IPConfig::Route route;
      CHECK(destination.IntoString(&route.host));
      route.prefix = destination.prefix();
      CHECK(gateway.IntoString(&route.gateway));
      routes.push_back(route);
      SLOG(nullptr, 2) << "In " << __func__ << ": Adding route to to "
                       << destination_as_string << " via " << gateway_as_string;
    }
  }

  if (!routes.empty()) {
    properties->routes.swap(routes);
  }

  return true;
}

// static
bool DHCPv4Config::ParseConfiguration(const KeyValueStore& configuration,
                                      IPConfig::Properties* properties) {
  SLOG(nullptr, 2) << __func__;
  properties->method = kTypeDHCP;
  properties->address_family = IPAddress::kFamilyIPv4;
  string classless_static_routes;
  bool default_gateway_parse_error = false;
  for (const auto& it : configuration.properties()) {
    const string& key = it.first;
    const brillo::Any& value = it.second;
    SLOG(nullptr, 2) << "Processing key: " << key;
    if (key == kConfigurationKeyIPAddress) {
      properties->address = GetIPv4AddressString(value.Get<uint32_t>());
      if (properties->address.empty()) {
        return false;
      }
    } else if (key == kConfigurationKeySubnetCIDR) {
      properties->subnet_prefix = value.Get<uint8_t>();
    } else if (key == kConfigurationKeyBroadcastAddress) {
      properties->broadcast_address =
          GetIPv4AddressString(value.Get<uint32_t>());
      if (properties->broadcast_address.empty()) {
        return false;
      }
    } else if (key == kConfigurationKeyRouters) {
      vector<uint32_t> routers = value.Get<vector<uint32_t>>();
      if (routers.empty()) {
        LOG(ERROR) << "No routers provided.";
        default_gateway_parse_error = true;
      } else {
        properties->gateway = GetIPv4AddressString(routers[0]);
        if (properties->gateway.empty()) {
          LOG(ERROR) << "Failed to parse router parameter provided.";
          default_gateway_parse_error = true;
        }
      }
    } else if (key == kConfigurationKeyDNS) {
      vector<uint32_t> servers = value.Get<vector<uint32_t>>();
      for (vector<unsigned int>::const_iterator it = servers.begin();
           it != servers.end(); ++it) {
        string server = GetIPv4AddressString(*it);
        if (server.empty()) {
          return false;
        }
        properties->dns_servers.push_back(server);
      }
    } else if (key == kConfigurationKeyDomainName) {
      properties->domain_name = value.Get<string>();
    } else if (key == kConfigurationKeyHostname) {
      properties->accepted_hostname = value.Get<string>();
    } else if (key == kConfigurationKeyDomainSearch) {
      properties->domain_search = value.Get<vector<string>>();
    } else if (key == kConfigurationKeyMTU) {
      int mtu = value.Get<uint16_t>();
      metrics_->SendSparseToUMA(Metrics::kMetricDhcpClientMTUValue, mtu);
      if (mtu >= minimum_mtu() && mtu != kMinIPv4MTU) {
        properties->mtu = mtu;
      }
    } else if (key == kConfigurationKeyClasslessStaticRoutes) {
      classless_static_routes = value.Get<string>();
    } else if (key == kConfigurationKeyVendorEncapsulatedOptions) {
      properties->vendor_encapsulated_options = value.Get<ByteArray>();
    } else if (key == kConfigurationKeyWebProxyAutoDiscoveryUrl) {
      properties->web_proxy_auto_discovery = value.Get<string>();
    } else if (key == kConfigurationKeyLeaseTime) {
      properties->lease_duration_seconds = value.Get<uint32_t>();
    } else if (key == kConfigurationKeyiSNSOptionData) {
      properties->isns_option_data = value.Get<ByteArray>();
    } else {
      SLOG(nullptr, 2) << "Key ignored.";
    }
  }
  ParseClasslessStaticRoutes(classless_static_routes, properties);
  if (default_gateway_parse_error && properties->gateway.empty()) {
    return false;
  }
  return true;
}

}  // namespace shill
