//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "dhcp_client/dhcpv4.h"

#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

#include <random>
#include <vector>

#include <base/bind.h>
#include <base/logging.h>
#include <brillo/variant_dictionary.h>

#include "dhcp_client/dhcp_message.h"
#include "dhcp_client/dhcp_options.h"
#include "dhcp_client/file_io.h"
#include "dhcp_client/service_adaptor_interface.h"
#include "dhcp_client/socket_util.h"
#include "shill/net/arp_packet.h"
#include "shill/net/ip_address.h"

using base::Bind;
using base::Unretained;
using shill::ByteString;
using shill::IOHandlerFactoryContainer;

namespace dhcp_client {

namespace {
// Max length of a DHCP message.
const size_t kDHCPMessageMaxLength = 548;
// Renewal time in terms of lease duration percentage.
const uint32_t kRenewalTimePercentage = 50;
// Rebinding time in terms of lease duration percentage.
const uint32_t kRebindTimePercentage = 87;
const int kInvalidSocketDescriptor = shill::Sockets::kInvalidFileDescriptor;
// RFC 791: the minimum value for a correct header is 20 octets.
// The maximum value is 60 octets.
const size_t kIPHeaderMinLength = 20;
const size_t kIPHeaderMaxLength = 60;
// DHCP parameters we request from server.
const uint8_t kDefaultParameterRequestList[] = {
    kDHCPOptionSubnetMask,
    kDHCPOptionInterfaceMTU,
    kDHCPOptionBroadcastAddr,
    kDHCPOptionRouter,
    kDHCPOptionDNSServer,
    kDHCPOptionDomainName,
    kDHCPOptionLeaseTime,
    kDHCPOptionRenewalTime,
    kDHCPOptionRebindingTime
};
const uint8_t kZeroHardwareAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const int kArpProbeReplyTimeoutSeconds = 1;

// TODO(nywang): find a place for the lease file.
const char kIPV4LeaseFilePathFormat[] =
      "/tmp/lease-ipv4-%s.conf";

// TODO(nywang): These constant will be moved to:
// <dbus/dhcp_client/dbus-constants.h>
// In this way shill can include this header and parse
// the messages.

const char kConfigurationKeyBroadcastAddress[] =
    "BroadcastAddress";
const char kConfigurationKeyDNS[] = "DomainNameServers";
const char kConfigurationKeyDomainName[] = "DomainName";
const char kConfigurationKeyIPAddress[] = "IPAddress";
const char kConfigurationKeyMTU[] = "InterfaceMTU";
const char kConfigurationKeyRouters[] = "Routers";
const char kConfigurationKeyVendorEncapsulatedOptions[] =
    "VendorEncapsulatedOptions";
const char kConfigurationKeySubnetCIDR[] = "SubnetCIDR";
const char kReasonBound[] = "BOUND";
const char kReasonFail[] = "FAIL";
const char kReasonNak[] = "NAK";
}  // namespace

DHCPV4::DHCPV4(ServiceAdaptorInterface* adaptor,
               const std::string& interface_name,
               const ByteString& hardware_address,
               unsigned int interface_index,
               const std::string& network_id,
               bool request_hostname,
               bool arp_gateway,
               bool unicast_arp,
               EventDispatcherInterface* event_dispatcher)
    : adaptor_(adaptor),
      interface_name_(interface_name),
      hardware_address_(hardware_address),
      interface_index_(interface_index),
      network_id_(network_id),
      request_hostname_(request_hostname),
      arp_gateway_(arp_gateway),
      unicast_arp_(unicast_arp),
      arp_client_(new shill::ArpClient(interface_index)),
      event_dispatcher_(event_dispatcher),
      io_handler_factory_(
          IOHandlerFactoryContainer::GetInstance()->GetIOHandlerFactory()),
      weak_ptr_factory_(this),
      state_(State::INIT),
      raw_socket_(kInvalidSocketDescriptor),
      udp_socket_(kInvalidSocketDescriptor),
      sockets_(new shill::Sockets()),
      socket_util_(new SocketUtil(interface_name_, interface_index_)),
      random_engine_(time(nullptr)) {
  ResetState();
}

DHCPV4::~DHCPV4() {
    Stop();
}

void DHCPV4::ResetState() {
  state_ = State::INIT;
  server_identifier_ = 0;
  transaction_id_ = 0;
  offered_ip_address_ = 0;
  client_ip_ = INADDR_ANY;
  server_ip_ = INADDR_BROADCAST;
  renewal_task_callback_.Cancel();
  rebind_task_callback_.Cancel();
  arp_probe_reply_timeout_task_callback_.Cancel();
}

void DHCPV4::ParseRawPacket(shill::InputData* data) {
  LOG(INFO) << __func__;
  if (data->len < sizeof(iphdr)) {
    LOG(ERROR) << "Invalid packet length from buffer";
    return;
  }
  // The socket filter has finished part the header validation.
  // This function will perform the remaining part.
  int header_len = ValidatePacketHeader(data->buf, data->len);
  if (header_len == -1) {
    return;
  }
  unsigned char* buffer = data->buf + header_len;
  DHCPMessage msg;
  if (!DHCPMessage::InitFromBuffer(buffer, data->len - header_len, &msg)) {
    LOG(ERROR) << "Failed to initialize DHCP message from buffer";
    return;
  }
  // In INIT state the client ignores all messages from server.
  if (state_ == State::INIT) {
    return;
  }
  // Check transaction id with the existing one.
  if (msg.transaction_id() != transaction_id_) {
    LOG(ERROR) << "Transaction id(xid) doesn't match";
    return;
  }
  uint8_t message_type = msg.message_type();
  switch (message_type) {
    case kDHCPMessageTypeOffer:
      HandleOffer(msg);
      break;
    case kDHCPMessageTypeAck:
      HandleAck(msg);
      break;
    case kDHCPMessageTypeNak:
      HandleNak(msg);
      break;
    default:
      LOG(ERROR) << "Invalid message type: "
                 << static_cast<int>(message_type);
  }
}

bool DHCPV4::WriteLease() {
    std::string lease_file =
        base::StringPrintf(kIPV4LeaseFilePathFormat, network_id_.c_str());
    LOG(INFO) << "Write lease to file";
    shill::ByteString lease =
        ByteString(reinterpret_cast<unsigned char*>(&offered_ip_address_),
                   sizeof(uint32_t));
    if (!FileIO::GetInstance()->Write(lease_file, lease)) {
      LOG(ERROR) << "Failed to write lease to file";
      return false;
    }
    return true;
}

void DHCPV4::OnReadError(const std::string& error_msg) {
  LOG(INFO) << __func__;
}

bool DHCPV4::Start() {
  if (!socket_util_->CreateRawSocket(&raw_socket_)) {
    return false;
  }
  input_handler_.reset(io_handler_factory_->CreateIOInputHandler(
      raw_socket_,
      Bind(&DHCPV4::ParseRawPacket, Unretained(this)),
      Bind(&DHCPV4::OnReadError, Unretained(this))));
  if (!network_id_.empty() && ReadLease()) {
    state_ = State::INIT_REBOOT;
    LOG(INFO) << "Start from INIT_REBOOT state";
    if (!SendRequest()) {
      ResetState();
      EmitEvent(kReasonFail);
      return false;
    }
    state_ = State::REBOOT;
    return true;
  }
  if (!SendDiscover()) {
    return false;
  }
  return true;
}

bool DHCPV4::ReadLease() {
  std::string lease_file =
      base::StringPrintf(kIPV4LeaseFilePathFormat, network_id_.c_str());
  if (!FileIO::GetInstance()->PathExists(lease_file)) {
    LOG(INFO) << "Lease file does not exist";
    return false;
  }
  ByteString config;
  if (!FileIO::GetInstance()->Read(lease_file, &config)) {
    LOG(ERROR) << "Failed to read lease file";
  }
  transaction_id_ = static_cast<uint32_t>(
      std::uniform_int_distribution<unsigned int>()
      (random_engine_) % UINT32_MAX + 1);
  offered_ip_address_ =
      *reinterpret_cast<const uint32_t*>(config.GetConstData());
  return true;
}

void DHCPV4::Stop() {
  input_handler_.reset();
  if (HasALease()) {
    if (!SendRelease()) {
      LOG(ERROR) << "Failed to send DHCP release message";
    }
    ResetState();
  }
  if (raw_socket_ != kInvalidSocketDescriptor) {
    sockets_->Close(raw_socket_);
    raw_socket_ = kInvalidSocketDescriptor;
  }
  if (udp_socket_ != kInvalidSocketDescriptor) {
    sockets_->Close(udp_socket_);
    udp_socket_ = kInvalidSocketDescriptor;
  }
  arp_client_->Stop();
}

void DHCPV4::HandleOffer(const DHCPMessage& msg) {
  LOG(INFO) << __func__;
  if (state_ != State::SELECT) {
    LOG(WARNING) << "Ignore DHCP Offer message";
    return;
  }
  if (msg.server_identifier() == 0) {
    LOG(ERROR) << "Option server identifier is missing";
    return;
  }
  LOG(INFO) << "Server IP: " << IPtoString(msg.server_identifier());

  uint32_t your_ip_address = msg.your_ip_address();
  if (your_ip_address == INADDR_ANY ||
      your_ip_address == INADDR_BROADCAST) {
    LOG(ERROR) << "Reject invalid IP address from server";
    return;
  }
  LOG(INFO) << "Lease IP: " << IPtoString(your_ip_address);

  if (!ValidateOptions(msg)) {
    return;
  }

  // Accept this offer.
  LOG(INFO) << "Accept offer with ip: " << IPtoString(your_ip_address);
  // Set states variables
  offered_ip_address_ = your_ip_address;
  server_identifier_ = msg.server_identifier();
  transaction_id_ = msg.transaction_id();

  if (!SendRequest()) {
    return;
  }
  // Set state upon success.
  state_ = State::REQUEST;
}

void DHCPV4::HandleAck(const DHCPMessage& msg) {
  LOG(INFO) << __func__;
  if (state_ != State::REQUEST &&
      state_ != State::RENEW &&
      state_ != State::REBIND &&
      state_ != State::REBOOT) {
    LOG(WARNING) << "Ignore DHCP Ack message";
    return;
  }
  if (msg.server_identifier() == 0) {
    LOG(ERROR) << "Option server identifier is missing";
    return;
  }
  if (state_ == State::REBOOT) {
    server_identifier_ = msg.server_identifier();
  }
  if (msg.server_identifier() != server_identifier_) {
    LOG(ERROR) << "Option server doesn't match";
    return;
  }
  LOG(INFO) << "Server IP: " << IPtoString(server_identifier_);

  uint32_t your_ip_address = msg.your_ip_address();
  // In case that this offered ip is different from we got from DHCP offer.
  if (offered_ip_address_ != msg.your_ip_address()) {
    LOG(ERROR) << "Reject invalid IP address from server";
    return;
  }
  LOG(INFO) << "Lease IP: " << IPtoString(your_ip_address);

  if (!ValidateOptions(msg)) {
    return;
  }

  CheckIpCollision();

  // TODO(nywang): Validate the gateway address using ARP.
  // Accept the ACK.
  uint32_t lease_time = msg.lease_time();
  uint32_t renewal_time = lease_time * kRenewalTimePercentage / 100;
  uint32_t rebinding_time = lease_time * kRebindTimePercentage / 100;
  // Override the renewal time or rebinding time if ACK specifies the value.
  if (msg.renewal_time() != 0) {
    renewal_time = msg.renewal_time();
  }
  if (msg.rebinding_time() != 0) {
    rebinding_time = msg.rebinding_time();
  }
  renewal_task_callback_.Reset(
      Bind(&DHCPV4::RenewalTask, weak_ptr_factory_.GetWeakPtr()));
  rebind_task_callback_.Reset(
      Bind(&DHCPV4::RebindTask, weak_ptr_factory_.GetWeakPtr()));

  event_dispatcher_->PostDelayedTask(renewal_task_callback_.callback(),
                                     1000 * renewal_time);
  event_dispatcher_->PostDelayedTask(rebind_task_callback_.callback(),
                                     1000 * rebinding_time);
  // Set state variables upon a valid Ack.
  state_ = State::BOUND;
  client_ip_ = offered_ip_address_;
  server_ip_ = server_identifier_;
  // Set the option parameters.
  subnet_mask_ = msg.subnet_mask();
  interface_mtu_ = msg.interface_mtu();
  broadcast_address_ = msg.broadcast_address();
  router_ = msg.router();
  dns_server_ = msg.dns_server();
  vendor_specific_info_ = msg.vendor_specific_info();
  domain_name_ = msg.domain_name();
  // Write lease to persistent stotrage.
  if (!network_id_.empty()) {
    WriteLease();
  }
  // Send the DHCP configuration to Shill.
  EmitEvent(kReasonBound);
  socket_util_->CreateUdpSocket(&udp_socket_);
}

void DHCPV4::HandleNak(const DHCPMessage& msg) {
  LOG(INFO) << __func__;
  if (state_ != State::REBIND &&
      state_ != State::RENEW &&
      state_ != State::REQUEST &&
      state_ != State::REBOOT) {
    LOG(WARNING) << "Ignore DHCP Nak message";
    return;
  }
  if (msg.server_identifier() == 0) {
    LOG(ERROR) << "Option server identifier is missing";
    return;
  }
  if (msg.server_identifier() != server_identifier_) {
    LOG(ERROR) << "Option server doesn't match";
    return;
  }
  if (msg.transaction_id() != transaction_id_) {
    LOG(ERROR) << "transaction id doesn't match";
    return;
  }
  // A Nak message should contain the error message.
  if (msg.error_message().size()) {
    LOG(INFO) << "Received DHCP NAK message with the following error message: "
              << msg.error_message();
  }

  // Set state variables upon receiving a valid Nak.
  ResetState();

  EmitEvent(kReasonNak);
}

bool DHCPV4::SendDiscover() {
  LOG(INFO) << __func__;
  DHCPMessage message;
  DHCPMessage::InitRequest(&message);
  message.SetMessageType(kDHCPMessageTypeDiscover);
  message.SetClientHardwareAddress(hardware_address_);
  uint32_t transaction_id =
      static_cast<uint32_t>(
      std::uniform_int_distribution<unsigned int>()(
          random_engine_) % UINT32_MAX + 1);

  message.SetTransactionID(transaction_id);
  message.SetParameterRequestList(
      std::vector<uint8_t>(kDefaultParameterRequestList,
                           kDefaultParameterRequestList +
                               sizeof(kDefaultParameterRequestList)));
  ByteString packet;
  if (!MakeRawPacket(message, &packet)) {
    LOG(ERROR) << "Failed to serialize a DHCP discover message";
    return false;
  }
  if (!socket_util_->SendBroadcastPacket(raw_socket_, packet)) {
    LOG(ERROR) << "Failed to send a DHCP discover packet";
    return false;
  }

  // Set state variables upon success.
  state_ = State::SELECT;
  transaction_id_ = transaction_id;
  return true;
}

void DHCPV4::CheckIpCollision() {
  if (!arp_client_->StartReplyListener()) {
    LOG(ERROR) << "Failed to start ARP client";
    return;
  }
  receive_arp_response_handler_.reset(
      io_handler_factory_->CreateIOReadyHandler(
          arp_client_->socket(),
          shill::IOHandler::kModeInput,
          Bind(&DHCPV4::ArpProbeReplyReceivedTask,
               weak_ptr_factory_.GetWeakPtr())));

  // According to RFC 5227, ARP Probe uses all-zero 'sender address' to avoid
  // polluting ARP caches. The 'target address' should be set to address being
  // probed.
  // RFC 5227 also states that target MAC address should be all-zero.
  shill::ArpPacket request(shill::IPAddress(IPtoString(INADDR_ANY)),
                           shill::IPAddress(IPtoString(offered_ip_address_)),
                           hardware_address_,
                           ByteString(kZeroHardwareAddress, IFHWADDRLEN));
  LOG(INFO) << "Probing expected ip address: "
            << IPtoString(offered_ip_address_);
  if (!arp_client_->TransmitRequest(request)) {
    LOG(ERROR) << "Failed to send ARP Probe request";
    arp_client_->Stop();
    receive_arp_response_handler_.reset();
    return;
  }
  // We succeeded to send ARP probe:
  arp_probe_reply_timeout_task_callback_.Reset(
      Bind(&DHCPV4::ArpProbeReplyTimeoutTask, weak_ptr_factory_.GetWeakPtr()));
  event_dispatcher_->PostDelayedTask(
      arp_probe_reply_timeout_task_callback_.callback(),
      1000 * kArpProbeReplyTimeoutSeconds);
}

void DHCPV4::ArpProbeReplyReceivedTask(int fd) {
  shill::ArpPacket packet;
  shill::ByteString sender;
  if (!arp_client_->ReceivePacket(&packet, &sender)) {
    return;
  }
  // According to RFC 5227, we only check the sender's ip address.
  shill::IPAddress offered_ip_address =
      shill::IPAddress(IPtoString(offered_ip_address_));
  if (!offered_ip_address.Equals(packet.local_ip_address())) {
    LOG(ERROR) << "Response is not for the expecte IP address.";
    return;
  }

  // Collision is found:
  LOG(ERROR) << "IP Collision found. Discard the lease.";
  arp_client_->Stop();
  receive_arp_response_handler_.reset();
  arp_probe_reply_timeout_task_callback_.Cancel();
  // TODO(nywang): send DHCP_DECLINE to server.
  ResetState();
}

void DHCPV4::ArpProbeReplyTimeoutTask() {
  // TODO(nywang): Broadcast ARP announcement.
  arp_client_->Stop();
  receive_arp_response_handler_.reset();
  arp_probe_reply_timeout_task_callback_.Cancel();
}

bool DHCPV4::SendRequest() {
  LOG(INFO) << __func__;
  DHCPMessage message;
  DHCPMessage::InitRequest(&message);
  message.SetMessageType(kDHCPMessageTypeRequest);
  message.SetClientHardwareAddress(hardware_address_);
  if (HasALease()) {
    message.SetClientIPAddress(client_ip_);
  }
  if (state_ == State::SELECT || state_ == State::INIT_REBOOT) {
    message.SetRequestedIpAddress(offered_ip_address_);
  }
  message.SetTransactionID(transaction_id_);
  if (state_ == State::SELECT) {
    message.SetServerIdentifier(server_identifier_);
  }
  message.SetParameterRequestList(
      std::vector<uint8_t>(kDefaultParameterRequestList,
                           kDefaultParameterRequestList +
                               sizeof(kDefaultParameterRequestList)));
  ByteString packet;

  // Use unicast for renewal.
  if (state_ == State::BOUND && udp_socket_ != kInvalidSocketDescriptor) {
    if (!MakePacket(message, &packet)) {
      LOG(ERROR) << "Failed to make a DHCP request packet";
      return false;
    }
    if (!socket_util_->SendUnicastPacket(udp_socket_, packet, server_ip_)) {
      LOG(ERROR) << "Failed to send a DHCP request packet";
      return false;
    }
  } else {
    // Use broadcast for other cases.
    if (!MakeRawPacket(message, &packet)) {
      LOG(ERROR) << "Failed to make a DHCP request raw packet";
      return false;
    }
    if (!socket_util_->SendBroadcastPacket(raw_socket_, packet)) {
      LOG(ERROR) << "Failed to send a DHCP request packet";
      return false;
    }
  }
  return true;
}

bool DHCPV4::SendRelease() {
  LOG(INFO) << __func__;
  DHCPMessage message;
  DHCPMessage::InitRequest(&message);
  message.SetMessageType(kDHCPMessageTypeRelease);
  message.SetClientHardwareAddress(hardware_address_);
  uint32_t transaction_id =
      static_cast<uint32_t>(
      std::uniform_int_distribution<unsigned int>()(
          random_engine_) % UINT32_MAX + 1);

  message.SetTransactionID(transaction_id);
  message.SetServerIdentifier(server_identifier_);
  ByteString packet;
  if (!MakePacket(message, &packet)) {
    LOG(ERROR) << "Failed to make a DHCP release packet";
    return false;
  }
  // Use unicast for release.
  if (udp_socket_ == kInvalidSocketDescriptor) {
    LOG(ERROR) << "Failed to send a DHCP release message becasuse "
                  "there is no socket for unicast";
    return false;
  }
  if (!socket_util_->SendUnicastPacket(udp_socket_, packet, server_ip_)) {
    LOG(ERROR) << "Failed to send a DHCP release packet";
    return false;
  }
  // Set state variables upon success.
  ResetState();
  return true;
}

bool DHCPV4::MakePacket(const DHCPMessage& message, ByteString* output) {
  ByteString payload;
  if (!message.Serialize(&payload)) {
    LOG(ERROR) << "Failed to serialzie dhcp message";
    return false;
  }
  *output = payload;
  return true;
}

bool DHCPV4::MakeRawPacket(const DHCPMessage& message, ByteString* output) {
  ByteString payload;
  if (!message.Serialize(&payload)) {
    LOG(ERROR) << "Failed to serialzie dhcp message";
    return false;
  }
  const size_t header_len = sizeof(struct iphdr) + sizeof(struct udphdr);
  const size_t payload_len = payload.GetLength();

  char buffer[header_len + payload_len];
  memset(buffer, 0, header_len + payload_len);
  struct iphdr* ip = reinterpret_cast<struct iphdr*>(buffer);
  struct udphdr* udp = reinterpret_cast<struct udphdr*>(buffer + sizeof(*ip));

  if (!payload.CopyData(payload_len, buffer + header_len)) {
    LOG(ERROR) << "Failed to copy data from payload";
    return false;
  }
  udp->uh_sport = htons(kDHCPClientPort);
  udp->uh_dport = htons(kDHCPServerPort);
  udp->uh_ulen =
      htons(static_cast<uint16_t>(sizeof(*udp) + payload.GetLength()));

  // Fill pseudo header (for UDP checksum computing):
  // Protocol.
  ip->protocol = IPPROTO_UDP;
  // Source IP address.
  ip->saddr = htonl(client_ip_);
  // Destination IP address.
  ip->daddr = htonl(server_ip_);
  // Total length, use udp packet length for pseudo header.
  ip->tot_len = udp->uh_ulen;
  // Calculate udp checksum based on:
  // IPV4 pseudo header, UDP header, and payload.
  udp->uh_sum = htons(DHCPMessage::ComputeChecksum(
      reinterpret_cast<const uint8_t*>(buffer),
      header_len + payload_len));

  // IP version.
  ip->version = IPVERSION;
  // IP header length.
  ip->ihl = sizeof(*ip) >> 2;
  // Fragment offset field.
  // The DHCP packet is always smaller than MTU,
  // so fragmentation is not needed.
  ip->frag_off = 0;
  // Identification.
  ip->id = static_cast<uint16_t>(
      std::uniform_int_distribution<unsigned int>()(
          random_engine_) % UINT16_MAX + 1);
  // Time to live.
  ip->ttl = IPDEFTTL;
  // Total length.
  ip->tot_len = htons(static_cast<uint16_t>(header_len+ payload.GetLength()));
  // Calculate IP Checksum only based on IP header.
  ip->check = htons(DHCPMessage::ComputeChecksum(
      reinterpret_cast<const uint8_t*>(ip),
      sizeof(*ip)));

  *output = ByteString(buffer, header_len + payload_len);
  return true;
}


bool DHCPV4::ValidateOptions(const DHCPMessage& msg) {
  uint32_t lease_time = msg.lease_time();
  if (lease_time == 0) {
    LOG(ERROR) << "Reject invalid lease time";
    return false;
  }
  LOG(INFO) << "Lease Time: " << lease_time;

  if (msg.subnet_mask() == 0) {
    LOG(ERROR) << "Reject invalid subnet mask";
    return false;
  }
  LOG(INFO) << "Subnet Mask: " << IPtoString(msg.subnet_mask());

  if (msg.interface_mtu() == 0) {
    LOG(WARNING) << "Failed to get a valid Interface MTU";
    // Shill will use a default MTU
    // in case no MTU is provided by DHCP.
  }
  DLOG(INFO) << "Interface MTU: " << msg.interface_mtu();

  if (msg.broadcast_address() == 0) {
    LOG(WARNING) << "Failed to get a valid Broadcast Address";
    // Shill will use a default broadcast address
    // in case no broadcast address is provided by DHCP.
  }
  DLOG(INFO) << "Broadcast Address: " << IPtoString(msg.broadcast_address());

  std::vector<uint32_t> router = msg.router();
  if (router.size() == 0) {
    LOG(ERROR) << "Failed to get default gateway address";
    return false;
  }
  DLOG(INFO) << "Routers:";
  for (uint32_t ip : router) {
    DLOG(INFO) << IPtoString(ip);
  }

  std::vector<uint32_t> dns_server = msg.dns_server();
  if (dns_server.size() == 0) {
    LOG(WARNING) << "Failed to get DNS server address";
    // Shill will use Google DNS server
    // in case no DNS server is provided by DHCP.
  } else {
    DLOG(INFO) << "DNS Server:";
    for (uint32_t ip : dns_server) {
      DLOG(INFO) << IPtoString(ip);
    }
  }
  return true;
}

int DHCPV4::ValidatePacketHeader(const unsigned char* buffer, size_t len) {
  const struct iphdr* ip =
      reinterpret_cast<const struct iphdr*>(buffer);
  const size_t ip_header_len = static_cast<size_t>(ip->ihl) << 2;
  if (ip_header_len < kIPHeaderMinLength ||
      ip_header_len > kIPHeaderMaxLength) {
    LOG(ERROR) << "Invalid internet header length: "
               << ip_header_len << " bytes";
    return -1;
  }
  if (ntohs(ip->tot_len) != len) {
    LOG(ERROR) << "Invalid IP total length: " << ntohs(ip->tot_len)
               << " Real packet length: " << len;
    return -1;
  }
  // TODO(nywang): Validate other ip header fields.

  const struct udphdr* udp =
      reinterpret_cast<const struct udphdr*>(buffer + ip_header_len);
  if (ntohs(udp->uh_sport) != kDHCPServerPort ||
      ntohs(udp->uh_dport) != kDHCPClientPort) {
    LOG(ERROR) << "Invlaid UDP ports";
    return -1;
  }
  if (ntohs(udp->uh_ulen) != len - ip_header_len) {
    LOG(ERROR) << "Invalid UDP total length";
    return -1;
  }
  // TODO(nywang): Validate UDP checksum.

  return ip_header_len + sizeof(*udp);
}

void DHCPV4::RenewalTask() {
  LOG(INFO) << __func__;
  if (state_ != State::BOUND) {
    LOG(ERROR) << "Ingore renewal task";
  }
  SendRequest();
  state_ = State::RENEW;
}

void DHCPV4::RebindTask() {
  LOG(INFO) << __func__;
  if (state_ != State::RENEW) {
    LOG(ERROR) << "Ingore rebind task";
  }
  SendRequest();
  state_ = State::REBIND;
}

void DHCPV4::EmitEvent(const std::string& reason) {
  brillo::VariantDictionary configs;
  if (reason == kReasonBound) {
    configs.emplace(kConfigurationKeyIPAddress, client_ip_);
    configs.emplace(kConfigurationKeyMTU, interface_mtu_);
    configs.emplace(kConfigurationKeyBroadcastAddress, broadcast_address_);
    configs.emplace(kConfigurationKeyRouters, router_);
    configs.emplace(kConfigurationKeyDNS, dns_server_);
    configs.emplace(kConfigurationKeyVendorEncapsulatedOptions,
                    vendor_specific_info_);
    configs.emplace(kConfigurationKeyDomainName, domain_name_);
    uint32_t subnet_cidr = MasktoCIDR(subnet_mask_);
    configs.emplace(kConfigurationKeySubnetCIDR, subnet_cidr);
  }
  adaptor_->EmitEvent(reason, configs);
}

bool DHCPV4::HasALease() {
  if (state_ == State::BOUND ||
      state_ == State::RENEW ||
      state_ == State::REBIND) {
    return true;
  }
  return false;
}

uint32_t DHCPV4::MasktoCIDR(uint32_t subnet_mask) {
  subnet_mask = ~subnet_mask;
  uint32_t count = 0;
  while (subnet_mask & 1) {
    count++;
    subnet_mask = subnet_mask >> 1;
  }
  return 32 - count;
}

const std::string DHCPV4::IPtoString(uint32_t ip) {
  char buffer[INET_ADDRSTRLEN];
  ip = htonl(ip);
  const char* ip_str = inet_ntop(AF_INET, &ip, buffer, sizeof(buffer));
  if (ip_str == NULL) {
    return std::string("invalid ip address");
  }
  return std::string(ip_str);
}

}  // namespace dhcp_client
