// Copyright 2019 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 "patchpanel/ndproxy.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>

#include <arpa/inet.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <linux/in6.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <fstream>
#include <string>
#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>

#include "patchpanel/minijailed_process_runner.h"
#include "patchpanel/net_util.h"

namespace patchpanel {
namespace {
const unsigned char kBroadcastMacAddress[] = {0xff, 0xff, 0xff,
                                              0xff, 0xff, 0xff};

sock_filter kNDFrameBpfInstructions[] = {
    // Load ethernet type.
    BPF_STMT(BPF_LD | BPF_H | BPF_ABS, offsetof(ether_header, ether_type)),
    // Check if it equals IPv6, if not, then goto return 0.
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_IPV6, 0, 9),
    // Move index to start of IPv6 header.
    BPF_STMT(BPF_LDX | BPF_IMM, sizeof(ether_header)),
    // Load IPv6 next header.
    BPF_STMT(BPF_LD | BPF_B | BPF_IND, offsetof(ip6_hdr, ip6_nxt)),
    // Check if equals ICMPv6, if not, then goto return 0.
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 6),
    // Move index to start of ICMPv6 header.
    BPF_STMT(BPF_LDX | BPF_IMM, sizeof(ether_header) + sizeof(ip6_hdr)),
    // Load ICMPv6 type.
    BPF_STMT(BPF_LD | BPF_B | BPF_IND, offsetof(icmp6_hdr, icmp6_type)),
    // Check if is ND ICMPv6 message.
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_ROUTER_SOLICIT, 4, 0),
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_ROUTER_ADVERT, 3, 0),
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_SOLICIT, 2, 0),
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_ADVERT, 1, 0),
    // Return 0.
    BPF_STMT(BPF_RET | BPF_K, 0),
    // Return MAX.
    BPF_STMT(BPF_RET | BPF_K, IP_MAXPACKET),
};
const sock_fprog kNDFrameBpfProgram = {
    .len = sizeof(kNDFrameBpfInstructions) / sizeof(sock_filter),
    .filter = kNDFrameBpfInstructions};

}  // namespace

constexpr ssize_t NDProxy::kTranslateErrorNotICMPv6Frame;
constexpr ssize_t NDProxy::kTranslateErrorNotNDFrame;
constexpr ssize_t NDProxy::kTranslateErrorInsufficientLength;
constexpr ssize_t NDProxy::kTranslateErrorBufferMisaligned;

NDProxy::NDProxy()
    : in_frame_buffer_(AlignFrameBuffer(in_frame_buffer_extended_)),
      out_frame_buffer_(AlignFrameBuffer(out_frame_buffer_extended_)) {}

base::ScopedFD NDProxy::PreparePacketSocket() {
  base::ScopedFD fd(
      socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, htons(ETH_P_IPV6)));
  if (!fd.is_valid()) {
    PLOG(ERROR) << "socket() failed";
    return base::ScopedFD();
  }
  if (setsockopt(fd.get(), SOL_SOCKET, SO_ATTACH_FILTER, &kNDFrameBpfProgram,
                 sizeof(kNDFrameBpfProgram))) {
    PLOG(ERROR) << "setsockopt(SO_ATTACH_FILTER) failed";
    return base::ScopedFD();
  }
  return fd;
}

bool NDProxy::Init() {
  rtnl_fd_ = base::ScopedFD(
      socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE));
  if (!rtnl_fd_.is_valid()) {
    PLOG(ERROR) << "socket() failed for rtnetlink socket";
    return false;
  }
  sockaddr_nl local = {
      .nl_family = AF_NETLINK,
      .nl_groups = 0,
  };
  if (bind(rtnl_fd_.get(), reinterpret_cast<sockaddr*>(&local), sizeof(local)) <
      0) {
    PLOG(ERROR) << "bind() failed on rtnetlink socket";
    return false;
  }

  dummy_fd_ = base::ScopedFD(socket(AF_INET6, SOCK_DGRAM, 0));
  if (!dummy_fd_.is_valid()) {
    PLOG(ERROR) << "socket() failed for dummy socket";
    return false;
  }
  return true;
}

// In an ICMPv6 Ethernet Frame *frame with length frame_len, replace the mac
// address in option opt_type into *target_mac. nd_hdr_len indicates the length
// of ICMPv6 ND message headers (so the first option starts after nd_hdr_len.)
void NDProxy::ReplaceMacInIcmpOption(uint8_t* frame,
                                     ssize_t frame_len,
                                     size_t nd_hdr_len,
                                     uint8_t opt_type,
                                     const MacAddress& target_mac) {
  nd_opt_hdr* opt;
  nd_opt_hdr* end = reinterpret_cast<nd_opt_hdr*>(&frame[frame_len]);
  for (opt = reinterpret_cast<nd_opt_hdr*>(frame + ETHER_HDR_LEN +
                                           sizeof(ip6_hdr) + nd_hdr_len);
       opt < end && opt->nd_opt_len > 0;
       opt = reinterpret_cast<nd_opt_hdr*>(reinterpret_cast<uint64_t*>(opt) +
                                           opt->nd_opt_len)) {
    if (opt->nd_opt_type == opt_type) {
      uint8_t* mac_in_opt =
          reinterpret_cast<uint8_t*>(opt) + sizeof(nd_opt_hdr);
      memcpy(mac_in_opt, target_mac.data(), ETHER_ADDR_LEN);
    }
  }
}

// RFC 4389
// Read the input ICMPv6 frame and determine whether it should be proxied. If
// so, fill out_frame buffer with proxied frame and return the length of proxied
// frame (usually same with input frame length). Return a negative value if
// proxy is not needed or error occured.
// in_frame: buffer containing input ethernet frame; needs special alignment
//           so that IP header is 4-bytes aligned;
// frame_len: the length of input frame;
// local_mac_addr: MAC address of interface that will be used to send frame;
// out_frame: buffer for output frame; should have at least space of frame_len;
//            needs special alignment so that IP header is 4-bytes aligned.
ssize_t NDProxy::TranslateNDFrame(const uint8_t* in_frame,
                                  ssize_t frame_len,
                                  const MacAddress& local_mac_addr,
                                  uint8_t* out_frame) {
  if ((reinterpret_cast<uintptr_t>(in_frame + ETHER_HDR_LEN) & 0x3) != 0 ||
      (reinterpret_cast<uintptr_t>(out_frame + ETHER_HDR_LEN) & 0x3) != 0) {
    return kTranslateErrorBufferMisaligned;
  }
  if (frame_len < ETHER_HDR_LEN + sizeof(ip6_hdr) + sizeof(icmp6_hdr)) {
    return kTranslateErrorInsufficientLength;
  }
  if (reinterpret_cast<const ethhdr*>(in_frame)->h_proto != htons(ETH_P_IPV6) ||
      reinterpret_cast<const ip6_hdr*>(in_frame + ETHER_HDR_LEN)->ip6_nxt !=
          IPPROTO_ICMPV6) {
    return kTranslateErrorNotICMPv6Frame;
  }

  memcpy(out_frame, in_frame, frame_len);
  ethhdr* eth = reinterpret_cast<ethhdr*>(out_frame);
  ip6_hdr* ip6 = reinterpret_cast<ip6_hdr*>(out_frame + ETHER_HDR_LEN);
  icmp6_hdr* icmp6 =
      reinterpret_cast<icmp6_hdr*>(out_frame + ETHER_HDR_LEN + sizeof(ip6_hdr));

  // If destination MAC is unicast (Individual/Group bit in MAC address == 0),
  // it needs to be modified so guest OS L3 stack can see it.
  // For proxy cascading case, we also need to recheck if destination MAC is
  // ff:ff:ff:ff:ff:ff (which must have been filled by an upstream proxy).
  if (!(eth->h_dest[0] & 0x1) ||
      memcmp(eth->h_dest, kBroadcastMacAddress, ETHER_ADDR_LEN) == 0) {
    MacAddress neighbor_mac;
    if (GetNeighborMac(ip6->ip6_dst, &neighbor_mac)) {
      memcpy(eth->h_dest, neighbor_mac.data(), ETHER_ADDR_LEN);
    } else {
      // If we can't resolve the destination IP into MAC from kernel neighbor
      // table, fill destination MAC with broadcast MAC instead.
      memcpy(eth->h_dest, kBroadcastMacAddress, ETHER_ADDR_LEN);
    }
  }

  switch (icmp6->icmp6_type) {
    case ND_ROUTER_SOLICIT:
      ReplaceMacInIcmpOption(out_frame, frame_len, sizeof(nd_router_solicit),
                             ND_OPT_SOURCE_LINKADDR, local_mac_addr);
      break;
    case ND_ROUTER_ADVERT: {
      // RFC 4389 Section 4.1.3.3 - Set Proxy bit
      nd_router_advert* ra = reinterpret_cast<nd_router_advert*>(icmp6);
      if (ra->nd_ra_flags_reserved & 0x04) {
        // According to RFC 4389, an RA packet with 'Proxy' bit set already
        // should not be proxied again, in order to avoid loop. However, we'll
        // need this form of proxy cascading in Crostini (Host->VM->Container)
        // so we are ignoring the check here. Note that we know we are doing RA
        // proxy in only one direction so there should be no loop.
      }
      ra->nd_ra_flags_reserved |= 0x04;

      ReplaceMacInIcmpOption(out_frame, frame_len, sizeof(nd_router_advert),
                             ND_OPT_SOURCE_LINKADDR, local_mac_addr);
      break;
    }
    case ND_NEIGHBOR_SOLICIT:
      ReplaceMacInIcmpOption(out_frame, frame_len, sizeof(nd_neighbor_solicit),
                             ND_OPT_SOURCE_LINKADDR, local_mac_addr);
      break;
    case ND_NEIGHBOR_ADVERT:
      ReplaceMacInIcmpOption(out_frame, frame_len, sizeof(nd_neighbor_advert),
                             ND_OPT_TARGET_LINKADDR, local_mac_addr);
      break;
    default:
      return kTranslateErrorNotNDFrame;
  }

  // We need to clear the old checksum first so checksum calculation does not
  // wrongly take old checksum into account.
  icmp6->icmp6_cksum = 0;
  icmp6->icmp6_cksum = Icmpv6Checksum(ip6, icmp6);

  memcpy(eth->h_source, local_mac_addr.data(), ETHER_ADDR_LEN);
  return frame_len;
}

void NDProxy::ReplaceSourceIP(uint8_t* frame, const in6_addr& src_ip) {
  ip6_hdr* ip6 = reinterpret_cast<ip6_hdr*>(frame + ETHER_HDR_LEN);
  icmp6_hdr* icmp6 =
      reinterpret_cast<icmp6_hdr*>(frame + ETHER_HDR_LEN + sizeof(ip6_hdr));

  memcpy(&ip6->ip6_src, &src_ip, sizeof(in6_addr));

  // Recalculate checksum.
  icmp6->icmp6_cksum = 0;
  icmp6->icmp6_cksum = Icmpv6Checksum(ip6, icmp6);
}

void NDProxy::ReadAndProcessOneFrame(int fd) {
  sockaddr_ll dst_addr;
  struct iovec iov = {
      .iov_base = in_frame_buffer_,
      .iov_len = IP_MAXPACKET,
  };
  msghdr hdr = {
      .msg_name = &dst_addr,
      .msg_namelen = sizeof(dst_addr),
      .msg_iov = &iov,
      .msg_iovlen = 1,
      .msg_control = nullptr,
      .msg_controllen = 0,
      .msg_flags = 0,
  };

  ssize_t len;
  if ((len = recvmsg(fd, &hdr, 0)) < 0) {
    // Ignore ENETDOWN: this can happen if the interface is not yet configured
    if (errno != ENETDOWN) {
      PLOG(WARNING) << "recvmsg() failed";
    }
    return;
  }
  ip6_hdr* ip6 = reinterpret_cast<ip6_hdr*>(in_frame_buffer_ + ETH_HLEN);
  icmp6_hdr* icmp6 = reinterpret_cast<icmp6_hdr*>(
      in_frame_buffer_ + ETHER_HDR_LEN + sizeof(ip6_hdr));

  if (ip6->ip6_nxt != IPPROTO_ICMPV6 || icmp6->icmp6_type < ND_ROUTER_SOLICIT ||
      icmp6->icmp6_type > ND_NEIGHBOR_ADVERT)
    return;

  // Notify DeviceManager on receiving NA from guest, so a /128 route to the
  // guest can be added on the host.
  if (icmp6->icmp6_type == ND_NEIGHBOR_ADVERT &&
      IsGuestInterface(dst_addr.sll_ifindex) &&
      !guest_discovery_handler_.is_null()) {
    nd_neighbor_advert* na = reinterpret_cast<nd_neighbor_advert*>(icmp6);
    if (((na->nd_na_target.s6_addr[0] & 0xe0) == 0x20)        // Global Unicast
        || ((na->nd_na_target.s6_addr[0] & 0xfe) == 0xfc)) {  // Unique Local
      char ifname[IFNAMSIZ];
      if_indextoname(dst_addr.sll_ifindex, ifname);
      char ipv6_addr_str[INET6_ADDRSTRLEN];
      inet_ntop(AF_INET6, &(na->nd_na_target.s6_addr), ipv6_addr_str,
                INET6_ADDRSTRLEN);
      guest_discovery_handler_.Run(std::string(ifname),
                                   std::string(ipv6_addr_str));
    }
  }

  // On receiving RA from router, generate an address for each guest-facing
  // interface, and sent it to DeviceManager so it can be assigned. This address
  // will be used when directly communicating with guest OS through IPv6.
  if (icmp6->icmp6_type == ND_ROUTER_ADVERT &&
      IsRouterInterface(dst_addr.sll_ifindex) &&
      !router_discovery_handler_.is_null()) {
    const nd_opt_prefix_info* prefix_info =
        GetPrefixInfoOption(in_frame_buffer_, len);
    if (prefix_info != nullptr && prefix_info->nd_opt_pi_prefix_len <= 64) {
      // Generate an EUI-64 address from virtual interface MAC. A prefix
      // larger that /64 is required.
      for (int target_if : if_map_ra_[dst_addr.sll_ifindex]) {
        MacAddress local_mac;
        if (!GetLocalMac(target_if, &local_mac))
          continue;
        in6_addr eui64_ip;
        GenerateEUI64Address(&eui64_ip, prefix_info->nd_opt_pi_prefix,
                             local_mac);
        char eui64_addr_str[INET6_ADDRSTRLEN];
        inet_ntop(AF_INET6, &eui64_ip, eui64_addr_str, INET6_ADDRSTRLEN);
        char target_ifname[IFNAMSIZ];
        if_indextoname(target_if, target_ifname);
        router_discovery_handler_.Run(std::string(target_ifname),
                                      std::string(eui64_addr_str));
      }
    }
  }

  // b/187918638: with Fibocom cellular modem we are observing irregular RAs
  // coming from a src IP that either cannot map to a hardware address in
  // neighbor table, or is mapped to the local MAC address on the cellular
  // interface. Directly proxying these RAs will cause guest OS to set up a
  // default route to a next hop that's not reachable.
  // A workaround is taken to overwrite that router IP with the host link local
  // IP, so that the guest OS set up the default route with the host as next hop
  // instead.
  // This piece of code detect this irregular case and the actual translation
  // code happens later below.
  bool unusual_ra_src = false;
  if (icmp6->icmp6_type == ND_ROUTER_ADVERT &&
      IsRouterInterface(dst_addr.sll_ifindex)) {
    MacAddress router_mac;
    MacAddress inbound_local_mac;
    if (!GetNeighborMac(ip6->ip6_src, &router_mac)) {
      // The router ip is not in neighbor table
      unusual_ra_src = true;
    } else {
      // Detect if the router ip get resolved to a local MAC
      unusual_ra_src = (GetLocalMac(dst_addr.sll_ifindex, &inbound_local_mac) &&
                        router_mac == inbound_local_mac);
    }
    if (unusual_ra_src)
      irregular_router_ifs.insert(dst_addr.sll_ifindex);
  }

  // b/187918638(cont.): since these cell upstream never send proper NS and NA,
  // there is no chance that we get the guest IP as normally from NA. Instead,
  // we have to monitor DAD NS frames and use it as judgement. Notice that since
  // upstream never reply NA, this DAD never fails.
  if (icmp6->icmp6_type == ND_NEIGHBOR_SOLICIT &&
      IsGuestToIrregularRouter(dst_addr.sll_ifindex) &&
      !guest_discovery_handler_.is_null()) {
    uint8_t zerobuf[sizeof(in6_addr)] = {0};
    nd_neighbor_solicit* ns = reinterpret_cast<nd_neighbor_solicit*>(icmp6);
    if (memcmp(&ip6->ip6_src, zerobuf, sizeof(in6_addr)) ==
            0  // Empty source IP indicates DAD
        &&
        (((ns->nd_ns_target.s6_addr[0] & 0xe0) == 0x20)  // Global Unicast
         || ((ns->nd_ns_target.s6_addr[0] & 0xfe) == 0xfc))) {  // Unique Local
      char ifname[IFNAMSIZ];
      if_indextoname(dst_addr.sll_ifindex, ifname);
      char ipv6_addr_str[INET6_ADDRSTRLEN];
      inet_ntop(AF_INET6, &(ns->nd_ns_target.s6_addr), ipv6_addr_str,
                INET6_ADDRSTRLEN);
      guest_discovery_handler_.Run(std::string(ifname),
                                   std::string(ipv6_addr_str));
    }
  }

  // Translate the NDP frame and send it through proxy interface
  auto map_entry = MapForType(icmp6->icmp6_type)->find(dst_addr.sll_ifindex);
  if (map_entry == MapForType(icmp6->icmp6_type)->end())
    return;
  const auto& target_ifs = map_entry->second;
  for (int target_if : target_ifs) {
    MacAddress local_mac;
    if (!GetLocalMac(target_if, &local_mac))
      continue;
    int result =
        TranslateNDFrame(in_frame_buffer_, len, local_mac, out_frame_buffer_);
    if (result < 0) {
      switch (result) {
        case kTranslateErrorNotICMPv6Frame:
          LOG(DFATAL) << "Attempt to TranslateNDFrame on a non-ICMPv6 frame";
          return;
        case kTranslateErrorNotNDFrame:
          LOG(DFATAL) << "Attempt to TranslateNDFrame on a non-NDP frame, "
                         "icmpv6 type = "
                      << static_cast<int>(reinterpret_cast<icmp6_hdr*>(
                                              in_frame_buffer_ + ETHER_HDR_LEN +
                                              sizeof(ip6_hdr))
                                              ->icmp6_type);
          return;
        case kTranslateErrorInsufficientLength:
          LOG(DFATAL) << "TranslateNDFrame failed: frame_len = " << len
                      << " is too small";
          return;
        default:
          LOG(DFATAL) << "Unknown error in TranslateNDFrame";
          return;
      }
    }

    // b/187918638: Overwrite source IP address with host address to workaround
    // irregular router address on Fibocom cell modem, as described above.
    if (unusual_ra_src) {
      in6_addr new_src;
      if (!GetLinkLocalAddress(target_if, &new_src)) {
        LOG(WARNING) << "Cannot find a local address for L3 relay, skipping "
                        "proxy RA to interface "
                     << target_if;
        return;
      }
      ReplaceSourceIP(out_frame_buffer_, new_src);
    }

    struct iovec iov_out = {
        .iov_base = out_frame_buffer_,
        .iov_len = static_cast<size_t>(len),
    };
    sockaddr_ll addr = {
        .sll_family = AF_PACKET,
        .sll_protocol = htons(ETH_P_IPV6),
        .sll_ifindex = target_if,
        .sll_halen = ETHER_ADDR_LEN,
    };
    memcpy(addr.sll_addr, reinterpret_cast<ethhdr*>(out_frame_buffer_)->h_dest,
           ETHER_ADDR_LEN);
    msghdr hdr = {
        .msg_name = &addr,
        .msg_namelen = sizeof(addr),
        .msg_iov = &iov_out,
        .msg_iovlen = 1,
        .msg_control = nullptr,
        .msg_controllen = 0,
    };
    if (sendmsg(fd, &hdr, 0) < 0) {
      // Ignore ENETDOWN: this can happen if the interface is not yet configured
      if (if_map_ra_.find(target_if) != if_map_ra_.end() && errno != ENETDOWN) {
        PLOG(WARNING) << "sendmsg() failed on interface " << target_if;
      }
    }
  }
}

const nd_opt_prefix_info* NDProxy::GetPrefixInfoOption(const uint8_t* in_frame,
                                                       ssize_t frame_len) {
  const uint8_t* ptr =
      in_frame + ETH_HLEN + sizeof(ip6_hdr) + sizeof(nd_router_advert);
  while (ptr + offsetof(nd_opt_hdr, nd_opt_len) < in_frame + frame_len) {
    const nd_opt_hdr* opt = reinterpret_cast<const nd_opt_hdr*>(ptr);
    if (opt->nd_opt_len == 0)
      return nullptr;
    ptr += opt->nd_opt_len << 3;  // nd_opt_len is in 8 bytes
    if (ptr > in_frame + frame_len)
      return nullptr;
    if (opt->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
        opt->nd_opt_len << 3 == sizeof(nd_opt_prefix_info)) {
      return reinterpret_cast<const nd_opt_prefix_info*>(opt);
    }
  }
  return nullptr;
}

bool NDProxy::GetLinkLocalAddress(int ifindex, in6_addr* link_local) {
  DCHECK(link_local != nullptr);
  std::ifstream proc_file("/proc/net/if_inet6");
  std::string line;
  while (std::getline(proc_file, line)) {
    // Line format in /proc/net/if_inet6:
    //   address ifindex prefix_len scope flags ifname
    auto tokens = base::SplitString(line, " \t", base::TRIM_WHITESPACE,
                                    base::SPLIT_WANT_NONEMPTY);
    if (tokens[3] != "20") {
      // We are only looking for link local address (scope value == "20")
      continue;
    }
    int line_if_id;
    if (!base::HexStringToInt(tokens[1], &line_if_id) ||
        line_if_id != ifindex) {
      continue;
    }
    std::vector<uint8_t> line_address;
    if (!base::HexStringToBytes(tokens[0], &line_address) ||
        line_address.size() != sizeof(in6_addr)) {
      continue;
    }
    memcpy(link_local, line_address.data(), sizeof(in6_addr));
    return true;
  }
  return false;
}

bool NDProxy::GetLocalMac(int if_id, MacAddress* mac_addr) {
  ifreq ifr = {
      .ifr_ifindex = if_id,
  };
  if (ioctl(dummy_fd_.get(), SIOCGIFNAME, &ifr) < 0) {
    PLOG(ERROR) << "ioctl() failed to get interface name on interface "
                << if_id;
    return false;
  }
  if (ioctl(dummy_fd_.get(), SIOCGIFHWADDR, &ifr) < 0) {
    PLOG(ERROR) << "ioctl() failed to get MAC address on interface " << if_id;
    return false;
  }
  memcpy(mac_addr->data(), ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
  return true;
}

bool NDProxy::GetNeighborMac(const in6_addr& ipv6_addr, MacAddress* mac_addr) {
  sockaddr_nl kernel = {
      .nl_family = AF_NETLINK,
      .nl_groups = 0,
  };
  struct nl_req {
    nlmsghdr hdr;
    rtgenmsg gen;
  } req = {
      .hdr =
          {
              .nlmsg_len = NLMSG_LENGTH(sizeof(rtgenmsg)),
              .nlmsg_type = RTM_GETNEIGH,
              .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
              .nlmsg_seq = 1,
          },
      .gen =
          {
              .rtgen_family = AF_INET6,
          },
  };
  iovec io_req = {
      .iov_base = &req,
      .iov_len = req.hdr.nlmsg_len,
  };
  msghdr rtnl_req = {
      .msg_name = &kernel,
      .msg_namelen = sizeof(kernel),
      .msg_iov = &io_req,
      .msg_iovlen = 1,
  };
  if (sendmsg(rtnl_fd_.get(), &rtnl_req, 0) < 0) {
    PLOG(ERROR) << "sendmsg() failed on rtnetlink socket";
    return false;
  }

  static constexpr size_t kRtnlReplyBufferSize = 32768;
  char reply_buffer[kRtnlReplyBufferSize];
  iovec io_reply = {
      .iov_base = reply_buffer,
      .iov_len = kRtnlReplyBufferSize,
  };
  msghdr rtnl_reply = {
      .msg_name = &kernel,
      .msg_namelen = sizeof(kernel),
      .msg_iov = &io_reply,
      .msg_iovlen = 1,
  };

  bool any_entry_matched = false;
  bool done = false;
  while (!done) {
    ssize_t len;
    if ((len = recvmsg(rtnl_fd_.get(), &rtnl_reply, 0)) < 0) {
      PLOG(ERROR) << "recvmsg() failed on rtnetlink socket";
      return false;
    }
    for (nlmsghdr* msg_ptr = reinterpret_cast<nlmsghdr*>(reply_buffer);
         NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) {
      switch (msg_ptr->nlmsg_type) {
        case NLMSG_DONE: {
          done = true;
          break;
        }
        case RTM_NEWNEIGH: {
          // Bitmap - 0x1: Found IP match; 0x2: found MAC address;
          uint8_t current_entry_status = 0x0;
          uint8_t current_mac[ETHER_ADDR_LEN];
          ndmsg* nd_msg = reinterpret_cast<ndmsg*>(NLMSG_DATA(msg_ptr));
          rtattr* rt_attr = reinterpret_cast<rtattr*>(RTM_RTA(nd_msg));
          size_t rt_attr_len = RTM_PAYLOAD(msg_ptr);
          for (; RTA_OK(rt_attr, rt_attr_len);
               rt_attr = RTA_NEXT(rt_attr, rt_attr_len)) {
            if (rt_attr->rta_type == NDA_DST &&
                memcmp(&ipv6_addr, RTA_DATA(rt_attr), sizeof(in6_addr)) == 0) {
              current_entry_status |= 0x1;
            } else if (rt_attr->rta_type == NDA_LLADDR) {
              current_entry_status |= 0x2;
              memcpy(current_mac, RTA_DATA(rt_attr), ETHER_ADDR_LEN);
            }
          }
          if (current_entry_status == 0x3) {
            memcpy(mac_addr->data(), current_mac, ETHER_ADDR_LEN);
            any_entry_matched = true;
          }
          break;
        }
        default: {
          LOG(WARNING) << "received unexpected rtnetlink message type "
                       << msg_ptr->nlmsg_type << ", length "
                       << msg_ptr->nlmsg_len;
          break;
        }
      }
    }
  }
  return any_entry_matched;
}

void NDProxy::RegisterOnGuestIpDiscoveryHandler(
    base::RepeatingCallback<void(const std::string&, const std::string&)>
        handler) {
  guest_discovery_handler_ = std::move(handler);
}

void NDProxy::RegisterOnRouterDiscoveryHandler(
    base::RepeatingCallback<void(const std::string&, const std::string&)>
        handler) {
  router_discovery_handler_ = std::move(handler);
}

NDProxy::interface_mapping* NDProxy::MapForType(uint8_t type) {
  switch (type) {
    case ND_ROUTER_SOLICIT:
      return &if_map_rs_;
    case ND_ROUTER_ADVERT:
      return &if_map_ra_;
    case ND_NEIGHBOR_SOLICIT:
      return &if_map_ns_na_;
    case ND_NEIGHBOR_ADVERT:
      return &if_map_ns_na_;
    default:
      LOG(DFATAL) << "Attempt to get interface map on illegal icmpv6 type "
                  << static_cast<int>(type);
      return nullptr;
  }
}

bool NDProxy::AddInterfacePair(const std::string& ifname_physical,
                               const std::string& ifname_guest) {
  LOG(INFO) << "Adding interface pair between physical: " << ifname_physical
            << ", guest: " << ifname_guest;
  int ifid_physical = if_nametoindex(ifname_physical.c_str());
  if (ifid_physical == 0) {
    PLOG(ERROR) << "Get interface index failed on " << ifname_physical;
    return false;
  }
  int ifid_guest = if_nametoindex(ifname_guest.c_str());
  if (ifid_guest == 0) {
    PLOG(ERROR) << "Get interface index failed on " << ifname_guest;
    return false;
  }
  if (ifid_physical == ifid_guest) {
    LOG(ERROR) << "Rejected attempt to forward between same interface "
               << ifname_physical << " and " << ifname_guest;
    return false;
  }
  if_map_rs_[ifid_guest].insert(ifid_physical);
  if_map_ra_[ifid_physical].insert(ifid_guest);
  if_map_ns_na_[ifid_physical].insert(ifid_guest);
  if_map_ns_na_[ifid_guest].insert(ifid_physical);
  for (int ifid_other_guest : if_map_ra_[ifid_physical]) {
    if (ifid_other_guest != ifid_guest) {
      if_map_ns_na_[ifid_other_guest].insert(ifid_guest);
      if_map_ns_na_[ifid_guest].insert(ifid_other_guest);
    }
  }
  return true;
}

bool NDProxy::RemoveInterfacePair(const std::string& ifname_physical,
                                  const std::string& ifname_guest) {
  LOG(INFO) << "Removing interface pair between physical: " << ifname_physical
            << ", guest: " << ifname_guest;
  int ifid_physical = if_nametoindex(ifname_physical.c_str());
  if (ifid_physical == 0) {
    PLOG(ERROR) << "Get interface index failed on " << ifname_physical;
    return false;
  }
  int ifid_guest = if_nametoindex(ifname_guest.c_str());
  if (ifid_guest == 0) {
    PLOG(ERROR) << "Get interface index failed on " << ifname_guest;
    return false;
  }
  if (ifid_physical == ifid_guest) {
    LOG(ERROR) << "Rejected attempt to forward between same interface "
               << ifname_physical << " and " << ifname_guest;
    return false;
  }
  if_map_rs_.erase(ifid_guest);
  if_map_ra_[ifid_physical].erase(ifid_guest);
  if_map_ns_na_.erase(ifid_guest);
  if_map_ns_na_[ifid_physical].erase(ifid_guest);
  for (int ifid_other_guest : if_map_ra_[ifid_physical]) {
    if_map_ns_na_[ifid_other_guest].erase(ifid_guest);
  }
  return true;
}

bool NDProxy::RemoveInterface(const std::string& ifname) {
  LOG(INFO) << "Removing physical interface " << ifname;
  int ifindex = if_nametoindex(ifname.c_str());
  if (ifindex == 0) {
    PLOG(ERROR) << "Get interface index failed on " << ifname;
    return false;
  }
  for (int ifid_guest : if_map_ra_[ifindex]) {
    if_map_rs_.erase(ifid_guest);
    if_map_ns_na_.erase(ifid_guest);
  }
  if_map_ra_.erase(ifindex);
  if_map_ns_na_.erase(ifindex);
  return true;
}

bool NDProxy::IsGuestInterface(int ifindex) {
  return if_map_rs_.find(ifindex) != if_map_rs_.end();
}

bool NDProxy::IsRouterInterface(int ifindex) {
  return if_map_ra_.find(ifindex) != if_map_ra_.end();
}

bool NDProxy::IsGuestToIrregularRouter(int ifindex) {
  if (!IsGuestInterface(ifindex))
    return false;
  for (int target_if : if_map_rs_[ifindex]) {
    if (irregular_router_ifs.count(target_if) > 0)
      return true;
  }
  return false;
}

std::vector<std::string> NDProxy::GetGuestInterfaces(
    const std::string& ifname_physical) {
  std::vector<std::string> result;
  int ifid_physical = if_nametoindex(ifname_physical.c_str());
  if (ifid_physical == 0)
    return result;
  for (int ifid_guest : if_map_ra_[ifid_physical]) {
    char ifname[IFNAMSIZ];
    if_indextoname(ifid_guest, ifname);
    result.push_back(ifname);
  }
  return result;
}

NDProxyDaemon::NDProxyDaemon(base::ScopedFD control_fd)
    : msg_dispatcher_(
          std::make_unique<MessageDispatcher>(std::move(control_fd))) {}

NDProxyDaemon::~NDProxyDaemon() {}

int NDProxyDaemon::OnInit() {
  // Prevent the main process from sending us any signals.
  if (setsid() < 0) {
    PLOG(ERROR) << "Failed to created a new session with setsid: exiting";
    return EX_OSERR;
  }

  EnterChildProcessJail();

  // Register control fd callbacks
  if (msg_dispatcher_) {
    msg_dispatcher_->RegisterFailureHandler(base::BindRepeating(
        &NDProxyDaemon::OnParentProcessExit, weak_factory_.GetWeakPtr()));
    msg_dispatcher_->RegisterDeviceMessageHandler(base::BindRepeating(
        &NDProxyDaemon::OnDeviceMessage, weak_factory_.GetWeakPtr()));
  }

  // Initialize NDProxy and register guest IP discovery callback
  if (!proxy_.Init()) {
    PLOG(ERROR) << "Failed to initialize NDProxy internal state";
    return EX_OSERR;
  }
  proxy_.RegisterOnGuestIpDiscoveryHandler(base::BindRepeating(
      &NDProxyDaemon::OnGuestIpDiscovery, weak_factory_.GetWeakPtr()));
  proxy_.RegisterOnRouterDiscoveryHandler(base::BindRepeating(
      &NDProxyDaemon::OnRouterDiscovery, weak_factory_.GetWeakPtr()));

  // Initialize data fd
  fd_ = NDProxy::PreparePacketSocket();
  if (!fd_.is_valid()) {
    return EX_OSERR;
  }

  // Start watching on data fd
  watcher_ = base::FileDescriptorWatcher::WatchReadable(
      fd_.get(), base::BindRepeating(&NDProxyDaemon::OnDataSocketReadReady,
                                     weak_factory_.GetWeakPtr()));
  LOG(INFO) << "Started watching on packet fd...";

  return Daemon::OnInit();
}

void NDProxyDaemon::OnDataSocketReadReady() {
  proxy_.ReadAndProcessOneFrame(fd_.get());
}

void NDProxyDaemon::OnParentProcessExit() {
  LOG(ERROR) << "Quitting because the parent process died";
  Quit();
}

void NDProxyDaemon::OnDeviceMessage(const DeviceMessage& msg) {
  const std::string& dev_ifname = msg.dev_ifname();
  LOG_IF(DFATAL, dev_ifname.empty())
      << "Received DeviceMessage w/ empty dev_ifname";
  if (msg.has_teardown()) {
    if (msg.has_br_ifname()) {
      proxy_.RemoveInterfacePair(dev_ifname, msg.br_ifname());
      if (guest_if_addrs_.find(msg.br_ifname()) != guest_if_addrs_.end()) {
        SendMessage(NDProxyMessage::DEL_ADDR, msg.br_ifname(),
                    guest_if_addrs_[msg.br_ifname()]);
        guest_if_addrs_.erase(msg.br_ifname());
      }

    } else {
      auto guest_ifs = proxy_.GetGuestInterfaces(dev_ifname);
      proxy_.RemoveInterface(dev_ifname);
      for (const auto& guest_if : guest_ifs) {
        if (guest_if_addrs_.find(guest_if) != guest_if_addrs_.end()) {
          SendMessage(NDProxyMessage::DEL_ADDR, guest_if,
                      guest_if_addrs_[guest_if]);
          guest_if_addrs_.erase(guest_if);
        }
      }
    }
  } else if (msg.has_br_ifname()) {
    proxy_.AddInterfacePair(dev_ifname, msg.br_ifname());
  }
}

void NDProxyDaemon::OnGuestIpDiscovery(const std::string& ifname,
                                       const std::string& ip6addr) {
  SendMessage(NDProxyMessage::ADD_ROUTE, ifname, ip6addr);
}

void NDProxyDaemon::OnRouterDiscovery(const std::string& ifname,
                                      const std::string& ip6addr) {
  std::string current_addr = guest_if_addrs_[ifname];
  if (current_addr == ip6addr)
    return;
  if (!current_addr.empty()) {
    SendMessage(NDProxyMessage::DEL_ADDR, ifname, current_addr);
  }
  SendMessage(NDProxyMessage::ADD_ADDR, ifname, ip6addr);
  guest_if_addrs_[ifname] = ip6addr;
}

void NDProxyDaemon::SendMessage(NDProxyMessage::NDProxyEventType type,
                                const std::string& ifname,
                                const std::string& ip6addr) {
  if (!msg_dispatcher_)
    return;
  NDProxyMessage msg;
  msg.set_type(type);
  msg.set_ifname(ifname);
  msg.set_ip6addr(ip6addr);
  IpHelperMessage ipm;
  *ipm.mutable_ndproxy_message() = msg;
  msg_dispatcher_->SendMessage(ipm);
}

}  // namespace patchpanel
