//
// 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/filter.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.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 "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 {
// UDP port numbers for DHCP.
const uint16_t kDHCPServerPort = 67;
const uint16_t kDHCPClientPort = 68;
// 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;

// Socket filter for dhcp packet.
const sock_filter dhcp_bpf_filter[] = {
  BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23 - ETH_HLEN),
  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
  BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 - ETH_HLEN),
  BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
  BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14 - ETH_HLEN),
  BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16 - ETH_HLEN),
  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, kDHCPClientPort, 0, 1),
  BPF_STMT(BPF_RET + BPF_K, 0x0fffffff),
  BPF_STMT(BPF_RET + BPF_K, 0),
};

const int dhcp_bpf_filter_len =
    sizeof(dhcp_bpf_filter) / sizeof(dhcp_bpf_filter[0]);

// 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()),
      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 (!CreateRawSocket()) {
    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();
}

bool DHCPV4::CreateRawSocket() {
  int fd = sockets_->Socket(PF_PACKET,
                            SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                            htons(ETHERTYPE_IP));
  if (fd == kInvalidSocketDescriptor) {
    PLOG(ERROR) << "Failed to create socket";
    return false;
  }
  shill::ScopedSocketCloser socket_closer(sockets_.get(), fd);

  // Apply the socket filter.
  sock_fprog pf;
  memset(&pf, 0, sizeof(pf));
  pf.filter = const_cast<sock_filter*>(dhcp_bpf_filter);
  pf.len = dhcp_bpf_filter_len;

  if (sockets_->AttachFilter(fd, &pf) != 0) {
    PLOG(ERROR) << "Failed to attach filter";
    return false;
  }

  if (sockets_->ReuseAddress(fd) == -1) {
    PLOG(ERROR) << "Failed to reuse socket address";
    return false;
  }

  if (sockets_->BindToDevice(fd, interface_name_) < 0) {
    PLOG(ERROR) << "Failed to bind socket to device";
    return false;
  }

  struct sockaddr_ll local;
  memset(&local, 0, sizeof(local));
  local.sll_family = PF_PACKET;
  local.sll_protocol = htons(ETHERTYPE_IP);
  local.sll_ifindex = static_cast<int>(interface_index_);

  if (sockets_->Bind(fd,
                     reinterpret_cast<struct sockaddr*>(&local),
                     sizeof(local)) < 0) {
    PLOG(ERROR) << "Failed to bind to address";
    return false;
  }

  raw_socket_ = socket_closer.Release();
  return true;
}

bool DHCPV4::CreateUdpSocket() {
  // Close previous Udp Socket.
  if (udp_socket_ != kInvalidSocketDescriptor) {
    sockets_->Close(udp_socket_);
    udp_socket_ = kInvalidSocketDescriptor;
  }

  int fd = sockets_->Socket(PF_INET,
                            SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                            IPPROTO_IP);
  if (fd == kInvalidSocketDescriptor) {
    PLOG(ERROR) << "Failed to create socket";
    return false;
  }
  shill::ScopedSocketCloser socket_closer(sockets_.get(), fd);

  if (sockets_->ReuseAddress(fd) == -1) {
    PLOG(ERROR) << "Failed to reuse socket address";
    return false;
  }

  if (sockets_->BindToDevice(fd, interface_name_) < 0) {
    PLOG(ERROR) << "Failed to bind socket to device";
    return false;
  }

  struct sockaddr_in local;
  memset(&local, 0, sizeof(local));
  local.sin_family = PF_INET;
  // We do not receive packet from this socket.
  // At this time the ip address may not be setup by shill yet.
  // It is a safe choice to use INADDR_ANY.
  local.sin_addr.s_addr = htonl(INADDR_ANY);
  local.sin_port = htons(kDHCPClientPort);

  if (sockets_->Bind(fd,
                     reinterpret_cast<struct sockaddr*>(&local),
                     sizeof(local)) < 0) {
    PLOG(ERROR) << "Failed to bind to address";
    return false;
  }

  udp_socket_ = socket_closer.Release();
  return true;
}

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);
  CreateUdpSocket();
}

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 (!SendBroadcastPacket(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 (!SendUnicastPacket(packet)) {
      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 (!SendBroadcastPacket(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 (!SendUnicastPacket(packet)) {
    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::SendBroadcastPacket(const ByteString& packet) {
  LOG(INFO) << __func__;
  struct sockaddr_ll remote;
  memset(&remote, 0, sizeof(remote));
  remote.sll_family = AF_PACKET;
  remote.sll_protocol = htons(ETHERTYPE_IP);
  remote.sll_ifindex = interface_index_;
  remote.sll_hatype = htons(ARPHRD_ETHER);
  // Use broadcast hardware address.
  remote.sll_halen = IFHWADDRLEN;
  memset(remote.sll_addr, 0xff, IFHWADDRLEN);

  size_t result = sockets_->SendTo(raw_socket_,
                                   packet.GetConstData(),
                                   packet.GetLength(),
                                   0,
                                   reinterpret_cast<struct sockaddr *>(&remote),
                                   sizeof(remote));

  if (result != packet.GetLength()) {
    PLOG(ERROR) << "Socket sento failed";
    return false;
  }
  return true;
}

bool DHCPV4::SendUnicastPacket(const ByteString& packet) {
  LOG(INFO) << __func__;
  struct sockaddr_in remote;
  memset(&remote, 0, sizeof(remote));
  remote.sin_family = AF_INET;
  remote.sin_port = htons(kDHCPServerPort);
  remote.sin_addr.s_addr = htonl(server_ip_);

  size_t result = sockets_->SendTo(udp_socket_,
                                   packet.GetConstData(),
                                   packet.GetLength(),
                                   0,
                                   reinterpret_cast<struct sockaddr *>(&remote),
                                   sizeof(remote));

  if (result != packet.GetLength()) {
    PLOG(ERROR) << "Socket sento failed";
    return false;
  }
  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

