// 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 "portier/nd_msg.h"

#include <netinet/icmp6.h>

#include <utility>

namespace portier {

// Type aliasing.
using std::vector;
using std::string;
using std::map;

using base::TimeDelta;

using shill::ByteString;
using shill::IPAddress;

using Type = NeighborDiscoveryMessage::Type;
using OptionType = NeighborDiscoveryMessage::OptionType;

// Static contstants.

// ND codes from netinet/icmp6.h, defined in RFC3542.
const Type NeighborDiscoveryMessage::kTypeRouterSolicit = ND_ROUTER_SOLICIT;
const Type NeighborDiscoveryMessage::kTypeRouterAdvert = ND_ROUTER_ADVERT;
const Type NeighborDiscoveryMessage::kTypeNeighborSolicit = ND_NEIGHBOR_SOLICIT;
const Type NeighborDiscoveryMessage::kTypeNeighborAdvert = ND_NEIGHBOR_ADVERT;
const Type NeighborDiscoveryMessage::kTypeRedirect = ND_REDIRECT;

const OptionType NeighborDiscoveryMessage::kOptionTypeSourceLinkLayerAddress =
    ND_OPT_SOURCE_LINKADDR;
const OptionType NeighborDiscoveryMessage::kOptionTypeTargetLinkLayerAddress =
    ND_OPT_TARGET_LINKADDR;
const OptionType NeighborDiscoveryMessage::kOptionTypePrefixInformation =
    ND_OPT_PREFIX_INFORMATION;
const OptionType NeighborDiscoveryMessage::kOptionTypeRedirectHeader =
    ND_OPT_REDIRECTED_HEADER;
const OptionType NeighborDiscoveryMessage::kOptionTypeMTU = ND_OPT_MTU;

// Local constants.
namespace {

constexpr uint32_t kTypeMinLengthRouterSolicit =
    sizeof(struct nd_router_solicit);
constexpr uint32_t kTypeMinLengthRouterAdvert = sizeof(struct nd_router_advert);
constexpr uint32_t kTypeMinLengthNeighborSolicit =
    sizeof(struct nd_neighbor_solicit);
constexpr uint32_t kTypeMinLengthNeighborAdvert =
    sizeof(struct nd_neighbor_advert);
constexpr uint32_t kTypeMinLengthRedirect = sizeof(struct nd_redirect);

// Link layer addresses are variable length.
constexpr uint32_t kOptionTypeMinLengthSourceLinkLayerAddress =
    sizeof(struct nd_opt_hdr);
constexpr uint32_t kOptionTypeMinLengthTargetLinkLayerAddress =
    sizeof(struct nd_opt_hdr);
constexpr uint32_t kOptionTypeMinLengthPrefixInformation =
    sizeof(struct nd_opt_prefix_info);
constexpr uint32_t kOptionTypeMinLengthRedirectHeader =
    sizeof(struct nd_opt_rd_hdr);
constexpr uint32_t kOptionTypeMinLengthMTU = sizeof(struct nd_opt_mtu);

// Option length to byte units.
constexpr uint32_t kBytesPerOptLen = 8;

// Route advertisement flags.
// RFC 4861 - Section 4.2.
constexpr uint8_t kRouterAdvertManagedBit = ND_RA_FLAG_MANAGED;
constexpr uint8_t kRouterAdvertOtherBit = ND_RA_FLAG_OTHER;
// RFC 4389 - Section 3.
constexpr uint8_t kRouterAdvertProxyBit = 0x04;
}  // namespace

// static
string NeighborDiscoveryMessage::GetTypeName(Type type) {
  switch (type) {
    case kTypeRouterSolicit:
      return "Router Solicitation";
    case kTypeRouterAdvert:
      return "Router Advertisement";
    case kTypeNeighborSolicit:
      return "Neighbor Solicitation";
    case kTypeNeighborAdvert:
      return "Neighbor Advertisement";
    case kTypeRedirect:
      return "Redirect";
    default:
      return "Unknown Type";
  }
}

// static
uint32_t NeighborDiscoveryMessage::GetTypeMinimumLength(Type type) {
  switch (type) {
    case kTypeRouterSolicit:
      return kTypeMinLengthRouterSolicit;
    case kTypeRouterAdvert:
      return kTypeMinLengthRouterAdvert;
    case kTypeNeighborSolicit:
      return kTypeMinLengthNeighborSolicit;
    case kTypeNeighborAdvert:
      return kTypeMinLengthNeighborAdvert;
    case kTypeRedirect:
      return kTypeMinLengthRedirect;
    default:
      return 0;
  }
}

// static
string NeighborDiscoveryMessage::GetOptionTypeName(OptionType opt_type) {
  switch (opt_type) {
    case kOptionTypeSourceLinkLayerAddress:
      return "Source Link-Layer-Address";
    case kOptionTypeTargetLinkLayerAddress:
      return "Target Link-Layer-Address";
    case kOptionTypePrefixInformation:
      return "Prefix Information";
    case kOptionTypeRedirectHeader:
      return "Redirect Header";
    case kOptionTypeMTU:
      return "MTU";
    default:
      return "Unknown Option Type";
  }
}

// static
uint32_t NeighborDiscoveryMessage::GetOptionTypeMinimumLength(
    OptionType opt_type) {
  switch (opt_type) {
    case kOptionTypeSourceLinkLayerAddress:
      return kOptionTypeMinLengthSourceLinkLayerAddress;
    case kOptionTypeTargetLinkLayerAddress:
      return kOptionTypeMinLengthTargetLinkLayerAddress;
    case kOptionTypePrefixInformation:
      return kOptionTypeMinLengthPrefixInformation;
    case kOptionTypeRedirectHeader:
      return kOptionTypeMinLengthRedirectHeader;
    case kOptionTypeMTU:
      return kOptionTypeMinLengthMTU;
    default:
      return 0;
  }
}

// Static Constructors.

NeighborDiscoveryMessage NeighborDiscoveryMessage::RouterSolicit() {
  NeighborDiscoveryMessage nd_msg;
  nd_msg.type_ = kTypeRouterSolicit;
  nd_msg.message_.Resize(kTypeMinLengthRouterSolicit);

  // Convert to raw.
  struct nd_router_solicit* nd_rs =
      reinterpret_cast<struct nd_router_solicit*>(nd_msg.GetData());
  memset(nd_rs, 0, kTypeMinLengthRouterSolicit);
  nd_rs->nd_rs_type = nd_msg.type();

  return nd_msg;
}

NeighborDiscoveryMessage NeighborDiscoveryMessage::RouterAdvert(
    uint8_t cur_hop_limit,
    bool managed_flag,
    bool other_flag,
    bool proxy_flag,
    TimeDelta router_lifetime,
    TimeDelta reachable_time,
    TimeDelta retransmit_timer) {
  NeighborDiscoveryMessage nd_msg;
  nd_msg.type_ = kTypeRouterAdvert;
  nd_msg.message_.Resize(kTypeMinLengthRouterAdvert);

  struct nd_router_advert* nd_ra =
      reinterpret_cast<struct nd_router_advert*>(nd_msg.GetData());
  memset(nd_ra, 0, kTypeMinLengthNeighborAdvert);

  // Row 0: ND type.
  nd_ra->nd_ra_type = nd_msg.type();

  // Row 1: Cur Hop Limit, M O flags, Router Lifetime (16-bits).
  nd_ra->nd_ra_curhoplimit = cur_hop_limit;
  nd_ra->nd_ra_flags_reserved =
      (managed_flag ? kRouterAdvertManagedBit : 0x00) |
      (other_flag ? kRouterAdvertOtherBit : 0x00) |
      (proxy_flag ? kRouterAdvertProxyBit : 0x00);
  nd_ra->nd_ra_router_lifetime =
      htons(static_cast<uint16_t>(router_lifetime.InSeconds()));

  // Row 2: Reachable Time (32-bits).
  nd_ra->nd_ra_reachable =
      htonl(static_cast<uint32_t>(reachable_time.InMilliseconds()));

  // Row 3: Retransmit Timer (32-bits).
  nd_ra->nd_ra_retransmit =
      htonl(static_cast<uint32_t>(retransmit_timer.InMilliseconds()));

  return nd_msg;
}

NeighborDiscoveryMessage NeighborDiscoveryMessage::NeighborSolicit(
    const IPAddress& target_address) {
  // Check that IP address is valid.
  if (target_address.family() != IPAddress::kFamilyIPv6) {
    LOG(ERROR) << "Cannot initialize with a non-IPv6 target address: "
               << target_address.ToString();
    return NeighborDiscoveryMessage();
  }

  NeighborDiscoveryMessage nd_msg;
  nd_msg.type_ = kTypeNeighborSolicit;
  nd_msg.message_.Resize(kTypeMinLengthNeighborSolicit);

  struct nd_neighbor_solicit* nd_ns =
      reinterpret_cast<struct nd_neighbor_solicit*>(nd_msg.GetData());
  memset(nd_ns, 0, kTypeMinLengthNeighborSolicit);

  // Row 0: ND type.
  nd_ns->nd_ns_type = nd_msg.type();
  // Row 1: Reserved.
  // Row 2-5: Target address.
  memcpy(&nd_ns->nd_ns_target, target_address.GetConstData(),
         target_address.GetLength());

  return nd_msg;
}

NeighborDiscoveryMessage NeighborDiscoveryMessage::NeighborAdvert(
    bool router_flag,
    bool solicited_flag,
    bool override_flag,
    const IPAddress& target_address) {
  // Check that IP address is valid.
  if (target_address.family() != IPAddress::kFamilyIPv6) {
    LOG(ERROR) << "Cannot initialize with a non-IPv6 target address: "
               << target_address.ToString();
    return NeighborDiscoveryMessage();
  }

  NeighborDiscoveryMessage nd_msg;
  nd_msg.type_ = kTypeNeighborAdvert;
  nd_msg.message_.Resize(kTypeMinLengthNeighborAdvert);

  struct nd_neighbor_advert* nd_na =
      reinterpret_cast<struct nd_neighbor_advert*>(nd_msg.GetData());
  memset(nd_na, 0, kTypeMinLengthNeighborAdvert);

  // Row 0: ND type.
  nd_na->nd_na_type = nd_msg.type();
  // Row 1: R S O flags
  nd_na->nd_na_flags_reserved = (router_flag ? ND_NA_FLAG_ROUTER : 0) |
                                (solicited_flag ? ND_NA_FLAG_SOLICITED : 0) |
                                (override_flag ? ND_NA_FLAG_OVERRIDE : 0);
  // Row 2-5: Target addresss.
  memcpy(&nd_na->nd_na_target, target_address.GetConstData(),
         target_address.GetLength());

  return nd_msg;
}

NeighborDiscoveryMessage NeighborDiscoveryMessage::Redirect(
    const IPAddress& target_address, const IPAddress& destination_address) {
  if (target_address.family() != IPAddress::kFamilyIPv6) {
    LOG(ERROR) << "Cannot initialize with a non-IPv6 target address: "
               << target_address.ToString();
    return NeighborDiscoveryMessage();
  }
  if (destination_address.family() != IPAddress::kFamilyIPv6) {
    LOG(ERROR) << "Cannot initialize with a non-IPv6 destination address: "
               << destination_address.ToString();
    return NeighborDiscoveryMessage();
  }

  NeighborDiscoveryMessage nd_msg;
  nd_msg.type_ = kTypeRedirect;
  nd_msg.message_.Resize(kTypeMinLengthRedirect);

  struct nd_redirect* nd_rd =
      reinterpret_cast<struct nd_redirect*>(nd_msg.GetData());
  memset(nd_rd, 0, kTypeMinLengthRedirect);

  // Row 0: ND type.
  nd_rd->nd_rd_type = nd_msg.type();
  // Row 1: Reserved.
  // Row 2-5: Target address.
  memcpy(&nd_rd->nd_rd_target, target_address.GetConstData(),
         target_address.GetLength());
  // Row 6-9: Destination address.
  memcpy(&nd_rd->nd_rd_dst, destination_address.GetConstData(),
         destination_address.GetLength());

  return nd_msg;
}

// Default constructor, private.

NeighborDiscoveryMessage::NeighborDiscoveryMessage() : type_(0) {}

NeighborDiscoveryMessage::NeighborDiscoveryMessage(const ByteString& raw_packet)
    : type_(0) {
  if (raw_packet.GetLength() == 0) {
    LOG(WARNING) << "ND packet is empty";
    return;
  }

  // Get the type
  Type type = raw_packet.GetConstData()[0];
  uint32_t exp_len = GetTypeMinimumLength(type);
  if (0 == exp_len) {
    LOG(ERROR) << "Unsupported ICMPv6 type " << static_cast<uint32_t>(type);
    return;
  } else if (raw_packet.GetLength() < exp_len) {
    LOG(ERROR) << "Expected length of a " << GetTypeName(type)
               << " ND packet should be at least " << exp_len << ", got "
               << raw_packet.GetLength();
    return;
  }
  type_ = type;

  message_ = raw_packet;
  if (!IndexOptions()) {
    // Issue with options.  Exact error should have been logged by
    // IndexOptions().
    type_ = 0;
    message_.Clear();
  }
}

bool NeighborDiscoveryMessage::IsValid() const {
  switch (type()) {
    case kTypeRouterSolicit:
    case kTypeRouterAdvert:
    case kTypeNeighborSolicit:
    case kTypeNeighborAdvert:
    case kTypeRedirect:
      break;
    default:
      // Not a supported type.
      return false;
  }

  if (GetLength() < GetTypeMinimumLength(type())) {
    // Length is too small.
    return false;
  }

  if ((GetLength() % 8) != 0) {
    // Packet does not align on proper 64-bit boundry.
    return false;
  }

  // TODO(sigquit): Create ND type specific validation.  Options should have
  // been validated upon indexing.

  return true;
}

// Checksum.

bool NeighborDiscoveryMessage::GetChecksum(uint16_t* checksum) const {
  if (!IsValid() || nullptr == checksum) {
    return false;
  }
  const struct icmp6_hdr* icmp6_hdr =
      reinterpret_cast<const struct icmp6_hdr*>(GetConstData());
  *checksum = icmp6_hdr->icmp6_cksum;
  return true;
}

bool NeighborDiscoveryMessage::SetChecksum(uint16_t checksum) {
  if (!IsValid()) {
    return false;
  }
  struct icmp6_hdr* icmp6_hdr = reinterpret_cast<struct icmp6_hdr*>(GetData());
  icmp6_hdr->icmp6_cksum = checksum;
  return true;
}

// RS related.

// RA related.

bool NeighborDiscoveryMessage::GetCurrentHopLimit(
    uint8_t* cur_hop_limit) const {
  if (!IsValid() || type() != kTypeRouterAdvert || nullptr == cur_hop_limit) {
    // Not a router advert.
    return false;
  }
  const struct nd_router_advert* nd_ra =
      reinterpret_cast<const struct nd_router_advert*>(GetConstData());
  *cur_hop_limit = nd_ra->nd_ra_curhoplimit;
  return true;
}

bool NeighborDiscoveryMessage::GetManagedAddressConfigurationFlag(
    bool* managed_flag) const {
  if (!IsValid() || type() != kTypeRouterAdvert || nullptr == managed_flag) {
    // Not a router advert.
    return false;
  }
  const struct nd_router_advert* nd_ra =
      reinterpret_cast<const struct nd_router_advert*>(GetConstData());
  *managed_flag = (nd_ra->nd_ra_flags_reserved & kRouterAdvertManagedBit) != 0;
  return true;
}

bool NeighborDiscoveryMessage::GetOtherConfigurationFlag(
    bool* other_flag) const {
  if (!IsValid() || type() != kTypeRouterAdvert || nullptr == other_flag) {
    // Not a router advert.
    return false;
  }
  const struct nd_router_advert* nd_ra =
      reinterpret_cast<const struct nd_router_advert*>(GetConstData());
  *other_flag = (nd_ra->nd_ra_flags_reserved & kRouterAdvertOtherBit) != 0;
  return true;
}

bool NeighborDiscoveryMessage::GetProxyFlag(bool* proxy_flag) const {
  if (!IsValid() || type() != kTypeRouterAdvert || nullptr == proxy_flag) {
    return false;
  }
  const struct nd_router_advert* nd_ra =
      reinterpret_cast<const struct nd_router_advert*>(GetConstData());
  *proxy_flag = (nd_ra->nd_ra_flags_reserved & kRouterAdvertProxyBit) != 0;
  return true;
}

bool NeighborDiscoveryMessage::SetProxyFlag(bool proxy_flag) {
  if (!IsValid() || type() != kTypeRouterAdvert) {
    return false;
  }
  struct nd_router_advert* nd_ra =
      reinterpret_cast<struct nd_router_advert*>(GetData());
  if (proxy_flag) {
    nd_ra->nd_ra_flags_reserved |= kRouterAdvertProxyBit;
  } else {
    nd_ra->nd_ra_flags_reserved &= ~kRouterAdvertProxyBit;
  }
  return true;
}

bool NeighborDiscoveryMessage::GetRouterLifetime(
    TimeDelta* router_lifetime) const {
  if (!IsValid() || type() != kTypeRouterAdvert || nullptr == router_lifetime) {
    // Not a router advert.
    return false;
  }
  const struct nd_router_advert* nd_ra =
      reinterpret_cast<const struct nd_router_advert*>(GetConstData());
  *router_lifetime =
      TimeDelta::FromSeconds(ntohs(nd_ra->nd_ra_router_lifetime));
  return true;
}

bool NeighborDiscoveryMessage::GetReachableTime(
    TimeDelta* reachable_time) const {
  if (!IsValid() || type() != kTypeRouterAdvert || nullptr == reachable_time) {
    // Not a router advert.
    return false;
  }
  const struct nd_router_advert* nd_ra =
      reinterpret_cast<const struct nd_router_advert*>(GetConstData());
  *reachable_time = TimeDelta::FromMilliseconds(ntohl(nd_ra->nd_ra_reachable));
  return true;
}

bool NeighborDiscoveryMessage::GetRetransmitTimer(
    TimeDelta* retransmit_timer) const {
  if (!IsValid() || type() != kTypeRouterAdvert ||
      nullptr == retransmit_timer) {
    // Not a router advert.
    return false;
  }
  const struct nd_router_advert* nd_ra =
      reinterpret_cast<const struct nd_router_advert*>(GetConstData());
  *retransmit_timer =
      TimeDelta::FromMilliseconds(ntohl(nd_ra->nd_ra_retransmit));
  return true;
}

// NS related.

bool NeighborDiscoveryMessage::GetTargetAddress(
    IPAddress* target_address) const {
  if (!IsValid() ||
      (type() != kTypeNeighborSolicit && type() != kTypeNeighborAdvert &&
       type() != kTypeRedirect) ||
      nullptr == target_address) {
    // Not a NS, NA or R
    return false;
  }

  if (type() == kTypeNeighborSolicit) {
    // Neighbor Solicit.
    const struct nd_neighbor_solicit* nd_ns =
        reinterpret_cast<const struct nd_neighbor_solicit*>(GetConstData());
    *target_address = IPAddress(
        IPAddress::kFamilyIPv6,
        ByteString(reinterpret_cast<const uint8_t*>(&nd_ns->nd_ns_target),
                   sizeof(nd_ns->nd_ns_target)));
    return true;
  }

  if (type() == kTypeNeighborAdvert) {
    // Neighbor Advert.
    const struct nd_neighbor_advert* nd_na =
        reinterpret_cast<const struct nd_neighbor_advert*>(GetConstData());
    *target_address = IPAddress(
        IPAddress::kFamilyIPv6,
        ByteString(reinterpret_cast<const uint8_t*>(&nd_na->nd_na_target),
                   sizeof(nd_na->nd_na_target)));
    return true;
  }

  // Redirect.
  const struct nd_redirect* nd_rd =
      reinterpret_cast<const struct nd_redirect*>(GetConstData());
  *target_address = IPAddress(
      IPAddress::kFamilyIPv6,
      ByteString(reinterpret_cast<const uint8_t*>(&nd_rd->nd_rd_target),
                 sizeof(nd_rd->nd_rd_target)));
  return true;
}

// NA related.

bool NeighborDiscoveryMessage::GetRouterFlag(bool* router_flag) const {
  if (!IsValid() || type() != kTypeNeighborAdvert || nullptr == router_flag) {
    // Not a NA.
    return false;
  }

  const struct nd_neighbor_advert* nd_na =
      reinterpret_cast<const struct nd_neighbor_advert*>(GetConstData());
  *router_flag = (nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER) != 0;
  return true;
}

bool NeighborDiscoveryMessage::GetSolicitedFlag(bool* solicited_flag) const {
  if (!IsValid() || type() != kTypeNeighborAdvert ||
      nullptr == solicited_flag) {
    // Not a NA.
    return false;
  }

  const struct nd_neighbor_advert* nd_na =
      reinterpret_cast<const struct nd_neighbor_advert*>(GetConstData());
  *solicited_flag = (nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED) != 0;
  return true;
}

bool NeighborDiscoveryMessage::GetOverrideFlag(bool* override_flag) const {
  if (!IsValid() || type() != kTypeNeighborAdvert || nullptr == override_flag) {
    // Not a NA.
    return false;
  }

  const struct nd_neighbor_advert* nd_na =
      reinterpret_cast<const struct nd_neighbor_advert*>(GetConstData());
  *override_flag = (nd_na->nd_na_flags_reserved & ND_NA_FLAG_OVERRIDE) != 0;
  return true;
}

// Redirect related.

bool NeighborDiscoveryMessage::GetDestinationAddress(
    IPAddress* destination_address) const {
  if (!IsValid() || type() != kTypeRedirect || nullptr == destination_address) {
    // Not a Redirect.
    return false;
  }

  const struct nd_redirect* nd_rd =
      reinterpret_cast<const struct nd_redirect*>(GetConstData());
  *destination_address =
      IPAddress(IPAddress::kFamilyIPv6,
                ByteString(reinterpret_cast<const uint8_t*>(&nd_rd->nd_rd_dst),
                           sizeof(nd_rd->nd_rd_dst)));
  return true;
}

// Raw accessors.
const uint8_t* NeighborDiscoveryMessage::GetConstData() const {
  return message_.GetConstData();
}

// private
uint8_t* NeighborDiscoveryMessage::GetData() {
  return message_.GetData();
}

size_t NeighborDiscoveryMessage::GetLength() const {
  return message_.GetLength();
}

// Options.

namespace {

// Helpers for options without a well-define structure.
const uint8_t* OptionConstData(const struct nd_opt_hdr* opt_hdr) {
  return &(
      reinterpret_cast<const uint8_t*>(opt_hdr)[sizeof(struct nd_opt_hdr)]);
}

uint8_t* OptionData(struct nd_opt_hdr* opt_hdr) {
  return &(reinterpret_cast<uint8_t*>(opt_hdr)[sizeof(struct nd_opt_hdr)]);
}

uint32_t OptionDataLength(const struct nd_opt_hdr* opt_hdr) {
  return (opt_hdr->nd_opt_len * kBytesPerOptLen) - sizeof(struct nd_opt_hdr);
}

}  // namespace

bool NeighborDiscoveryMessage::HasOption(OptionType opt_type) const {
  if (!IsValid()) {
    return false;
  }
  return OptionCount(opt_type) > 0;
}

uint32_t NeighborDiscoveryMessage::OptionCount(OptionType opt_type) const {
  if (!IsValid()) {
    return 0;
  }

  auto opt_it = options_.find(opt_type);
  if (opt_it == options_.cend()) {
    // No occurance.
    return 0;
  }
  return opt_it->second.size();
}

bool NeighborDiscoveryMessage::GetRawOption(OptionType opt_type,
                                            uint32_t opt_index,
                                            ByteString* raw_option) const {
  if (opt_index >= OptionCount(opt_type) || nullptr == raw_option) {
    return false;
  }

  const uint8_t* opt_ptr = GetConstOptionPointer(opt_type, opt_index);
  CHECK(nullptr != opt_ptr);

  // Determine the length of the option.
  const struct nd_opt_hdr* opt_hdr =
      reinterpret_cast<const struct nd_opt_hdr*>(opt_ptr);
  CHECK(opt_hdr->nd_opt_type == opt_type);
  const uint32_t opt_length = (opt_hdr->nd_opt_len * kBytesPerOptLen);

  *raw_option = ByteString(opt_ptr, opt_length);
  return true;
}

void NeighborDiscoveryMessage::ClearOptions() {
  if (!IsValid()) {
    return;
  }
  // Clear indexes.
  options_.clear();
  // Truncate message.
  message_.Resize(GetTypeMinimumLength(type()));
}

// Internal option accessor.

uint8_t* NeighborDiscoveryMessage::GetOptionPointer(OptionType opt_type,
                                                    uint32_t opt_index) {
  return const_cast<uint8_t*>(GetConstOptionPointer(opt_type, opt_index));
}

const uint8_t* NeighborDiscoveryMessage::GetConstOptionPointer(
    OptionType opt_type, uint32_t opt_index) const {
  // Verify sanity
  CHECK(IsValid());
  CHECK(opt_index < OptionCount(opt_type));

  auto opt_it = options_.find(opt_type);
  uint32_t data_idx = opt_it->second[opt_index];

  CHECK(data_idx < GetLength());
  return &message_.GetConstData()[data_idx];
}

// Option - Source link-layer address.

bool NeighborDiscoveryMessage::HasSourceLinkLayerAddress() const {
  return HasOption(kOptionTypeSourceLinkLayerAddress);
}

bool NeighborDiscoveryMessage::GetSourceLinkLayerAddress(
    uint32_t opt_index, LLAddress* source_ll_address) const {
  return GetLinkLayerAddress(kOptionTypeSourceLinkLayerAddress, opt_index,
                             source_ll_address);
}

bool NeighborDiscoveryMessage::SetSourceLinkLayerAddress(
    uint32_t opt_index, const LLAddress& source_ll_address) {
  return SetLinkLayerAddress(kOptionTypeSourceLinkLayerAddress, opt_index,
                             source_ll_address);
}

bool NeighborDiscoveryMessage::PushSourceLinkLayerAddress(
    const LLAddress& source_ll_address) {
  return PushLinkLayerAddress(kOptionTypeSourceLinkLayerAddress,
                              source_ll_address);
}

// Option - Target link-layer address.

bool NeighborDiscoveryMessage::HasTargetLinkLayerAddress() const {
  return HasOption(kOptionTypeTargetLinkLayerAddress);
}

bool NeighborDiscoveryMessage::GetTargetLinkLayerAddress(
    uint32_t opt_index, LLAddress* target_ll_address) const {
  return GetLinkLayerAddress(kOptionTypeTargetLinkLayerAddress, opt_index,
                             target_ll_address);
}

bool NeighborDiscoveryMessage::SetTargetLinkLayerAddress(
    uint32_t opt_index, const LLAddress& target_ll_address) {
  return SetLinkLayerAddress(kOptionTypeTargetLinkLayerAddress, opt_index,
                             target_ll_address);
}

bool NeighborDiscoveryMessage::PushTargetLinkLayerAddress(
    const LLAddress& target_ll_address) {
  return PushLinkLayerAddress(kOptionTypeTargetLinkLayerAddress,
                              target_ll_address);
}

// Option - Prefix information.

bool NeighborDiscoveryMessage::HasPrefixInformation() const {
  return HasOption(kOptionTypePrefixInformation);
}

uint32_t NeighborDiscoveryMessage::PrefixInformationCount() const {
  return OptionCount(kOptionTypePrefixInformation);
}

bool NeighborDiscoveryMessage::GetPrefixLength(uint32_t opt_index,
                                               uint8_t* prefix_length) const {
  if (opt_index >= PrefixInformationCount() || nullptr == prefix_length) {
    return false;
  }

  const struct nd_opt_prefix_info* opt_prefix_info =
      reinterpret_cast<const struct nd_opt_prefix_info*>(
          GetConstOptionPointer(kOptionTypePrefixInformation, opt_index));

  CHECK_EQ(opt_prefix_info->nd_opt_pi_type, kOptionTypePrefixInformation);

  *prefix_length = opt_prefix_info->nd_opt_pi_prefix_len;
  return true;
}

bool NeighborDiscoveryMessage::GetOnLinkFlag(uint32_t opt_index,
                                             bool* on_link_flag) const {
  if (opt_index >= PrefixInformationCount() || nullptr == on_link_flag) {
    return false;
  }

  const struct nd_opt_prefix_info* opt_prefix_info =
      reinterpret_cast<const struct nd_opt_prefix_info*>(
          GetConstOptionPointer(kOptionTypePrefixInformation, opt_index));

  CHECK_EQ(opt_prefix_info->nd_opt_pi_type, kOptionTypePrefixInformation);

  *on_link_flag = ((opt_prefix_info->nd_opt_pi_flags_reserved &
                    ND_OPT_PI_FLAG_ONLINK) != 0);
  return true;
}

bool NeighborDiscoveryMessage::GetAutonomousAddressConfigurationFlag(
    uint32_t opt_index, bool* autonomous_flag) const {
  if (opt_index >= PrefixInformationCount() || nullptr == autonomous_flag) {
    return false;
  }

  const struct nd_opt_prefix_info* opt_prefix_info =
      reinterpret_cast<const struct nd_opt_prefix_info*>(
          GetConstOptionPointer(kOptionTypePrefixInformation, opt_index));

  CHECK_EQ(opt_prefix_info->nd_opt_pi_type, kOptionTypePrefixInformation);

  *autonomous_flag =
      ((opt_prefix_info->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) != 0);
  return true;
}

bool NeighborDiscoveryMessage::GetPrefixValidLifetime(
    uint32_t opt_index, TimeDelta* valid_lifetime) const {
  if (opt_index >= PrefixInformationCount() || nullptr == valid_lifetime) {
    return false;
  }

  const struct nd_opt_prefix_info* opt_prefix_info =
      reinterpret_cast<const struct nd_opt_prefix_info*>(
          GetConstOptionPointer(kOptionTypePrefixInformation, opt_index));

  CHECK_EQ(opt_prefix_info->nd_opt_pi_type, kOptionTypePrefixInformation);

  *valid_lifetime =
      TimeDelta::FromSeconds(ntohl(opt_prefix_info->nd_opt_pi_valid_time));
  return true;
}

bool NeighborDiscoveryMessage::GetPrefixPreferredLifetime(
    uint32_t opt_index, TimeDelta* preferred_lifetime) const {
  if (opt_index >= PrefixInformationCount() || nullptr == preferred_lifetime) {
    return false;
  }

  const struct nd_opt_prefix_info* opt_prefix_info =
      reinterpret_cast<const struct nd_opt_prefix_info*>(
          GetConstOptionPointer(kOptionTypePrefixInformation, opt_index));

  CHECK_EQ(opt_prefix_info->nd_opt_pi_type, kOptionTypePrefixInformation);

  *preferred_lifetime =
      TimeDelta::FromSeconds(ntohl(opt_prefix_info->nd_opt_pi_preferred_time));
  return true;
}

bool NeighborDiscoveryMessage::GetPrefix(uint32_t opt_index,
                                         IPAddress* prefix) const {
  if (opt_index >= PrefixInformationCount() || nullptr == prefix) {
    return false;
  }

  const struct nd_opt_prefix_info* opt_prefix_info =
      reinterpret_cast<const struct nd_opt_prefix_info*>(
          GetConstOptionPointer(kOptionTypePrefixInformation, opt_index));

  CHECK_EQ(opt_prefix_info->nd_opt_pi_type, kOptionTypePrefixInformation);

  ByteString prefix_bytes(
      reinterpret_cast<const uint8_t*>(&opt_prefix_info->nd_opt_pi_prefix),
      sizeof(opt_prefix_info->nd_opt_pi_prefix));

  // Convert, but validate before returning.
  IPAddress temp_prefix(IPAddress::kFamilyIPv6, prefix_bytes);

  if (!temp_prefix.IsValid()) {
    return false;
  }

  *prefix = temp_prefix;
  return true;
}

bool NeighborDiscoveryMessage::PushPrefixInformation(
    uint8_t prefix_length,
    bool on_link_flag,
    bool autonomous_flag,
    const TimeDelta& valid_lifetime,
    const TimeDelta& preferred_lifetime,
    const IPAddress& prefix) {
  if (!IsValid() || !prefix.IsValid() ||
      prefix.family() != IPAddress::kFamilyIPv6) {
    return false;
  }

  ByteString opt_buf(kOptionTypeMinLengthPrefixInformation);
  memset(opt_buf.GetData(), 0, opt_buf.GetLength());

  struct nd_opt_prefix_info* opt_prefix_info =
      reinterpret_cast<struct nd_opt_prefix_info*>(opt_buf.GetData());

  // Transfer data to struct.
  opt_prefix_info->nd_opt_pi_type = kOptionTypePrefixInformation;

  opt_prefix_info->nd_opt_pi_len =
      kOptionTypeMinLengthPrefixInformation / kBytesPerOptLen;
  CHECK_EQ(opt_prefix_info->nd_opt_pi_len * kBytesPerOptLen,
           kOptionTypeMinLengthPrefixInformation);

  opt_prefix_info->nd_opt_pi_prefix_len = prefix_length;

  opt_prefix_info->nd_opt_pi_flags_reserved =
      (on_link_flag ? ND_OPT_PI_FLAG_ONLINK : 0x00) |
      (autonomous_flag ? ND_OPT_PI_FLAG_AUTO : 0x00);

  opt_prefix_info->nd_opt_pi_valid_time =
      htonl(static_cast<uint32_t>(valid_lifetime.InSeconds()));

  opt_prefix_info->nd_opt_pi_preferred_time =
      htonl(static_cast<uint32_t>(preferred_lifetime.InSeconds()));

  memcpy(reinterpret_cast<uint8_t*>(&opt_prefix_info->nd_opt_pi_prefix),
         prefix.GetConstData(), sizeof(opt_prefix_info->nd_opt_pi_prefix));

  // Add to the current message, and index new option.
  const uint32_t data_index = GetLength();
  message_.Append(opt_buf);
  AddOptionIndex(kOptionTypePrefixInformation, data_index);
  return true;
}

// Option - Redirect header.

bool NeighborDiscoveryMessage::HasRedirectedHeader() const {
  return HasOption(kOptionTypeRedirectHeader);
}

bool NeighborDiscoveryMessage::GetIpHeaderAndData(
    uint32_t opt_index, ByteString* ip_header_and_data) const {
  if (opt_index >= OptionCount(kOptionTypeRedirectHeader) ||
      nullptr == ip_header_and_data) {
    return false;
  }

  const uint8_t* opt_ptr =
      GetConstOptionPointer(kOptionTypeRedirectHeader, opt_index);
  const struct nd_opt_rd_hdr* opt_rd_hdr =
      reinterpret_cast<const struct nd_opt_rd_hdr*>(opt_ptr);

  CHECK_EQ(opt_rd_hdr->nd_opt_rh_type, kOptionTypeRedirectHeader);

  const uint32_t header_length = (opt_rd_hdr->nd_opt_rh_len * kBytesPerOptLen) -
                                 sizeof(struct nd_opt_rd_hdr);

  if (header_length == 0) {
    // Nothing to returns.
    ip_header_and_data->Clear();
    return true;
  }

  *ip_header_and_data =
      ByteString(&opt_ptr[sizeof(struct nd_opt_rd_hdr)], header_length);
  return true;
}

bool NeighborDiscoveryMessage::PushRedirectedHeader(
    const shill::ByteString& ip_header_and_data) {
  if (!IsValid()) {
    return false;
  }

  // Allocate space for the option header.
  ByteString opt_buf(kOptionTypeMinLengthRedirectHeader);
  memset(opt_buf.GetData(), 0, opt_buf.GetLength());
  struct nd_opt_rd_hdr* opt_rd_hdr =
      reinterpret_cast<struct nd_opt_rd_hdr*>(opt_buf.GetData());

  opt_rd_hdr->nd_opt_rh_type = kOptionTypeRedirectHeader;
  opt_rd_hdr->nd_opt_rh_len =
      (kOptionTypeMinLengthRedirectHeader / kBytesPerOptLen) +
      (ip_header_and_data.GetLength() / kBytesPerOptLen) +
      // Possible that there is an incomplete 64-bit block.
      ((ip_header_and_data.GetLength() % kBytesPerOptLen) != 0 ? 1 : 0);

  opt_rd_hdr = nullptr;  // Appending can invalidate the header pointer.
  opt_buf.Append(ip_header_and_data);

  // Add padding as needed.
  if ((opt_buf.GetLength() % kBytesPerOptLen) != 0) {
    ByteString pad(kBytesPerOptLen - (opt_buf.GetLength() % kBytesPerOptLen));
    memset(pad.GetData(), 0, pad.GetLength());
    opt_buf.Append(pad);
  }

  // Append option and index it.
  const uint32_t data_index = GetLength();
  message_.Append(opt_buf);
  AddOptionIndex(kOptionTypeRedirectHeader, data_index);
  return true;
}

// Option - MTU

bool NeighborDiscoveryMessage::HasMTU() const {
  return HasOption(kOptionTypeMTU);
}

bool NeighborDiscoveryMessage::GetMTU(uint32_t opt_index, uint32_t* mtu) const {
  if (opt_index >= OptionCount(kOptionTypeMTU) || nullptr == mtu) {
    return false;
  }

  const struct nd_opt_mtu* opt_mtu = reinterpret_cast<const struct nd_opt_mtu*>(
      GetConstOptionPointer(kOptionTypeMTU, opt_index));

  CHECK_EQ(opt_mtu->nd_opt_mtu_type, kOptionTypeMTU);

  *mtu = ntohl(opt_mtu->nd_opt_mtu_mtu);
  return true;
}

bool NeighborDiscoveryMessage::PushMTU(uint32_t mtu) {
  if (!IsValid()) {
    return false;
  }

  ByteString opt_buf(kOptionTypeMinLengthMTU);
  memset(opt_buf.GetData(), 0, opt_buf.GetLength());
  struct nd_opt_mtu* opt_mtu =
      reinterpret_cast<struct nd_opt_mtu*>(opt_buf.GetData());

  opt_mtu->nd_opt_mtu_type = kOptionTypeMTU;
  opt_mtu->nd_opt_mtu_len = 1;
  opt_mtu->nd_opt_mtu_mtu = htonl(mtu);

  const uint32_t data_index = GetLength();
  message_.Append(opt_buf);
  AddOptionIndex(kOptionTypeMTU, data_index);
  return true;
}

// Option - Generic link-layer address (internal).

bool NeighborDiscoveryMessage::GetLinkLayerAddress(
    OptionType opt_type, uint32_t opt_index, LLAddress* ll_address) const {
  CHECK(kOptionTypeSourceLinkLayerAddress == opt_type ||
        kOptionTypeTargetLinkLayerAddress == opt_type);

  if (nullptr == ll_address || opt_index >= OptionCount(opt_type)) {
    return false;
  }

  const uint8_t* opt_ptr = GetConstOptionPointer(opt_type, opt_index);
  const struct nd_opt_hdr* opt_hdr =
      reinterpret_cast<const struct nd_opt_hdr*>(opt_ptr);

  CHECK_EQ(opt_hdr->nd_opt_type, opt_type);

  ByteString opt_data(OptionConstData(opt_hdr), OptionDataLength(opt_hdr));

  if (opt_data.GetLength() !=
      LLAddress::GetTypeLength(LLAddress::Type::kEui48)) {
    // Unknown length of EUI
    return false;
  }

  *ll_address = LLAddress(LLAddress::Type::kEui48, opt_data);
  return true;
}

// private
bool NeighborDiscoveryMessage::SetLinkLayerAddress(
    OptionType opt_type, uint32_t opt_index, const LLAddress& ll_address) {
  CHECK(kOptionTypeSourceLinkLayerAddress == opt_type ||
        kOptionTypeTargetLinkLayerAddress == opt_type);

  if (opt_index >= OptionCount(opt_type) || !ll_address.IsValid()) {
    return false;
  }
  if (ll_address.type() != LLAddress::Type::kEui48) {
    NOTIMPLEMENTED() << "Current can't handle non-Ethernet link-layer "
                     << "addresses, got "
                     << LLAddress::GetTypeName(ll_address.type());
    return false;
  }

  uint8_t* opt_ptr = GetOptionPointer(opt_type, opt_index);
  struct nd_opt_hdr* opt_hdr = reinterpret_cast<struct nd_opt_hdr*>(opt_ptr);

  if (ll_address.GetLength() != OptionDataLength(opt_hdr)) {
    // Currently cannot handle the case where the stored link-layer
    // address is a different size than the one replacing it.
    return false;
  }

  memcpy(OptionData(opt_hdr), ll_address.GetConstData(),
         ll_address.GetLength());
  return true;
}

// private
bool NeighborDiscoveryMessage::PushLinkLayerAddress(
    OptionType opt_type, const LLAddress& ll_address) {
  CHECK(kOptionTypeSourceLinkLayerAddress == opt_type ||
        kOptionTypeTargetLinkLayerAddress == opt_type);

  if (!IsValid()) {
    return false;
  }
  if (ll_address.type() != LLAddress::Type::kEui48) {
    NOTIMPLEMENTED() << "Current can't handle non-Ethernet link-layer "
                     << "addresses, got "
                     << LLAddress::GetTypeName(ll_address.type());
    return false;
  }

  // Allocate space for the option.
  ByteString opt_buf(kBytesPerOptLen);
  struct nd_opt_hdr* opt_hdr =
      reinterpret_cast<struct nd_opt_hdr*>(opt_buf.GetData());

  // Populate the option.
  opt_hdr->nd_opt_type = opt_type;
  opt_hdr->nd_opt_len = 1;
  memcpy(OptionData(opt_hdr), ll_address.GetConstData(),
         ll_address.GetLength());

  // Append to the current message and update the index.
  const uint32_t data_index = GetLength();
  message_.Append(opt_buf);
  AddOptionIndex(opt_type, data_index);
  return true;
}

// Indexing Options.

bool NeighborDiscoveryMessage::IndexOptions() {
  const uint32_t min_len = GetTypeMinimumLength(type());
  CHECK_GT(min_len, 0);
  CHECK(GetLength() >= min_len);

  // Clear all of the current indexes.
  options_.clear();

  // If there are none, then return.
  if (GetLength() == min_len) {
    // No options, done.
    return true;
  }

  uint32_t bytes_remaining = GetLength() - min_len;
  if ((bytes_remaining % kBytesPerOptLen) != 0) {
    // Packet does not align on 64-bit boundaries.
    return false;
  }

  uint32_t data_index = min_len;
  do {
    const uint8_t* opt_ptr = &GetConstData()[data_index];
    const struct nd_opt_hdr* opt_hdr =
        reinterpret_cast<const struct nd_opt_hdr*>(opt_ptr);
    const uint32_t opt_len = (opt_hdr->nd_opt_len * kBytesPerOptLen);

    // Check if invalid option length.  Packet might have been received using
    // AF_PACKET which does not validate ICMPv6 frames in the kernel before
    // passing up to user-space.
    if (0 == opt_len) {
      // RFC 4861: Nodes MUST silently discard an ND packet that contains an
      // option with length zero.
      LOG(ERROR) << "Received option with zero-length option: "
                 << GetOptionTypeName(opt_hdr->nd_opt_type) << " ("
                 << static_cast<uint32_t>(opt_hdr->nd_opt_type) << ")";
      options_.clear();
      return false;
    }

    if (opt_len > bytes_remaining) {
      // Not possible unless packet was truncated.
      LOG(ERROR) << "Option length is greater than remaining packet size";
      options_.clear();
      return false;
    }

    const OptionType opt_type = opt_hdr->nd_opt_type;
    const uint32_t opt_min_len = GetOptionTypeMinimumLength(opt_type);

    if (opt_min_len == 0) {
      // RFC 4861: Receivers MUST silently ignore any options they do not
      // recognize and continue processing the message.
      LOG(WARNING) << "Indexing unknown option type "
                   << static_cast<uint32_t>(opt_type);
      AddOptionIndex(opt_type, data_index);
    } else {
      switch (opt_type) {
        case kOptionTypeSourceLinkLayerAddress:
        case kOptionTypeTargetLinkLayerAddress:
          // Technically, the LL address can be any length necessary, so
          // it we must assume it is valid.
          AddOptionIndex(opt_type, data_index);
          break;
        case kOptionTypePrefixInformation:
        case kOptionTypeRedirectHeader:
        case kOptionTypeMTU:
          // These options have fixed lengths and are invalid if their size
          // does not match the expected length.  RFC 4861 does not specify
          // how this is to be handled, for now, we silently ignore the option,
          // but we do not index it.
          if (opt_len >= opt_min_len) {
            AddOptionIndex(opt_type, data_index);
          }
          break;
        default:
          // Should not reach this branch.
          CHECK(false);
      }
    }
    data_index += opt_len;
    bytes_remaining -= opt_len;
  } while (bytes_remaining > 0);

  return true;
}

void NeighborDiscoveryMessage::AddOptionIndex(OptionType opt_type,
                                              uint32_t data_index) {
  using OptPair = std::pair<OptionType, vector<uint32_t>>;

  CHECK(GetLength() > GetTypeMinimumLength(type()));

  // If index vector does not exsts, create new index vector for option type.
  if (options_.find(opt_type) == options_.end()) {
    options_.insert(OptPair(opt_type, vector<uint32_t>()));
  }
  options_[opt_type].push_back(data_index);
}

}  // namespace portier
