/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2011-2022, Regents of the University of California.
 *
 * This file is part of ndn-tools (Named Data Networking Essential Tools).
 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
 *
 * ndn-tools is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * ndn-tools, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "ndndump.hpp"

#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>

#include <pcap/sll.h>

#include <iomanip>
#include <sstream>

#include <ndn-cxx/lp/nack.hpp>
#include <ndn-cxx/lp/packet.hpp>
#include <ndn-cxx/net/ethernet.hpp>
#include <ndn-cxx/util/scope.hpp>
#include <ndn-cxx/util/string-helper.hpp>

#include <boost/endian/conversion.hpp>

namespace ndn {
namespace dump {

namespace endian = boost::endian;

class OutputFormatter : noncopyable
{
public:
  OutputFormatter(std::ostream& os, std::string d)
    : m_os(os)
    , m_delim(std::move(d))
  {
  }

  OutputFormatter&
  addDelimiter()
  {
    if (!m_isEmpty) {
      m_wantDelim = true;
    }
    return *this;
  }

private:
  std::ostream& m_os;
  std::string m_delim;
  bool m_isEmpty = true;
  bool m_wantDelim = false;

  template<typename T>
  friend OutputFormatter& operator<<(OutputFormatter&, const T&);
};

template<typename T>
OutputFormatter&
operator<<(OutputFormatter& out, const T& val)
{
  if (out.m_wantDelim) {
    out.m_os << out.m_delim;
    out.m_wantDelim = false;
  }
  out.m_os << val;
  out.m_isEmpty = false;
  return out;
}

NdnDump::~NdnDump()
{
  if (m_pcap)
    pcap_close(m_pcap);
}

void
NdnDump::run()
{
  char errbuf[PCAP_ERRBUF_SIZE] = {};

  if (inputFile.empty() && interface.empty()) {
    pcap_if_t* allDevs = nullptr;
    int res = pcap_findalldevs(&allDevs, errbuf);
    auto freealldevs = ndn::make_scope_exit([=] { pcap_freealldevs(allDevs); });

    if (res != 0) {
      NDN_THROW(Error(errbuf));
    }
    if (allDevs == nullptr) {
      NDN_THROW(Error("No network interface found"));
    }

    interface = allDevs->name;
  }

  std::string action;
  if (!interface.empty()) {
    m_pcap = pcap_open_live(interface.data(), 65535, wantPromisc, 1000, errbuf);
    if (m_pcap == nullptr) {
      NDN_THROW(Error("Cannot open interface " + interface + ": " + errbuf));
    }
    action = "listening on " + interface;
  }
  else {
    m_pcap = pcap_open_offline(inputFile.data(), errbuf);
    if (m_pcap == nullptr) {
      NDN_THROW(Error("Cannot open file '" + inputFile + "' for reading: " + errbuf));
    }
    action = "reading from file " + inputFile;
  }

  m_dataLinkType = pcap_datalink(m_pcap);
  const char* dltName = pcap_datalink_val_to_name(m_dataLinkType);
  const char* dltDesc = pcap_datalink_val_to_description(m_dataLinkType);
  std::string formattedDlt = dltName ? dltName : to_string(m_dataLinkType);
  if (dltDesc) {
    formattedDlt += " ("s + dltDesc + ")";
  }

  std::cerr << "ndndump: " << action << ", link-type " << formattedDlt << std::endl;

  switch (m_dataLinkType) {
  case DLT_EN10MB:
  case DLT_LINUX_SLL:
  case DLT_PPP:
    // we know how to handle these
    break;
  default:
    NDN_THROW(Error("Unsupported link-layer header type " + formattedDlt));
  }

  if (!pcapFilter.empty()) {
    if (wantVerbose) {
      std::cerr << "ndndump: using pcap filter: " << pcapFilter << std::endl;
    }

    bpf_program program;
    int res = pcap_compile(m_pcap, &program, pcapFilter.data(), 1, PCAP_NETMASK_UNKNOWN);
    if (res < 0) {
      NDN_THROW(Error("Cannot compile pcap filter '" + pcapFilter + "': " + pcap_geterr(m_pcap)));
    }
    auto freecode = ndn::make_scope_exit([&] { pcap_freecode(&program); });

    res = pcap_setfilter(m_pcap, &program);
    if (res < 0) {
      NDN_THROW(Error("Cannot set pcap filter: "s + pcap_geterr(m_pcap)));
    }
  }

  auto callback = [] (uint8_t* user, const pcap_pkthdr* pkthdr, const uint8_t* payload) {
    reinterpret_cast<const NdnDump*>(user)->printPacket(pkthdr, payload);
  };

  if (pcap_loop(m_pcap, -1, callback, reinterpret_cast<uint8_t*>(this)) < 0) {
    NDN_THROW(Error("pcap_loop: "s + pcap_geterr(m_pcap)));
  }
}

void
NdnDump::printPacket(const pcap_pkthdr* pkthdr, const uint8_t* payload) const
{
  // sanity checks
  if (pkthdr->caplen == 0) {
    std::cout << "[Invalid header: caplen=0]" << std::endl;
    return;
  }
  if (pkthdr->len == 0) {
    std::cout << "[Invalid header: len=0]" << std::endl;
    return;
  }
  else if (pkthdr->len < pkthdr->caplen) {
    std::cout << "[Invalid header: len(" << pkthdr->len
              << ") < caplen(" << pkthdr->caplen << ")]" << std::endl;
    return;
  }

  std::ostringstream os;
  OutputFormatter out(os, ", ");

  bool shouldPrint = false;
  switch (m_dataLinkType) {
  case DLT_EN10MB:
    shouldPrint = printEther(out, payload, pkthdr->len);
    break;
  case DLT_LINUX_SLL:
    shouldPrint = printLinuxSll(out, payload, pkthdr->len);
    break;
  case DLT_PPP:
    shouldPrint = printPpp(out, payload, pkthdr->len);
    break;
  default:
    BOOST_ASSERT(false);
    return;
  }

  if (shouldPrint) {
    if (wantTimestamp) {
      printTimestamp(std::cout, pkthdr->ts);
    }
    std::cout << os.str() << std::endl;
  }
}

void
NdnDump::printTimestamp(std::ostream& os, const timeval& tv) const
{
  /// \todo Add more timestamp formats (time since previous packet, time since first packet, ...)
  os << tv.tv_sec
     << "."
     << std::setfill('0') << std::setw(6) << tv.tv_usec
     << " ";
}

bool
NdnDump::dispatchByEtherType(OutputFormatter& out, const uint8_t* pkt, size_t len, uint16_t etherType) const
{
  out.addDelimiter();

  switch (etherType) {
  case ETHERTYPE_IP:
    return printIp4(out, pkt, len);
  case ETHERTYPE_IPV6:
    return printIp6(out, pkt, len);
  case ethernet::ETHERTYPE_NDN:
  case 0x7777: // NDN ethertype used in ndnSIM
    out << "Ethernet";
    return printNdn(out, pkt, len);
  default:
    out << "[Unsupported ethertype " << AsHex{etherType} << "]";
    return true;
  }
}

bool
NdnDump::dispatchByIpProto(OutputFormatter& out, const uint8_t* pkt, size_t len, uint8_t ipProto) const
{
  out.addDelimiter();

  switch (ipProto) {
  case IPPROTO_NONE:
    out << "[No next header]";
    return true;
  case IPPROTO_TCP:
    return printTcp(out, pkt, len);
  case IPPROTO_UDP:
    return printUdp(out, pkt, len);
  default:
    out << "[Unsupported IP proto " << static_cast<int>(ipProto) << "]";
    return true;
  }
}

bool
NdnDump::printEther(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  // IEEE 802.3 Ethernet

  if (len < ethernet::HDR_LEN) {
    out << "Truncated Ethernet frame, length " << len;
    return true;
  }

  auto ether = reinterpret_cast<const ether_header*>(pkt);
  pkt += ethernet::HDR_LEN;
  len -= ethernet::HDR_LEN;

  return dispatchByEtherType(out, pkt, len, endian::big_to_native(ether->ether_type));
}

bool
NdnDump::printLinuxSll(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  // Linux "cooked" capture encapsulation
  // https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html

  if (len < SLL_HDR_LEN) {
    out << "Truncated LINUX_SLL frame, length " << len;
    return true;
  }

  auto sll = reinterpret_cast<const sll_header*>(pkt);
  pkt += SLL_HDR_LEN;
  len -= SLL_HDR_LEN;

  return dispatchByEtherType(out, pkt, len, endian::big_to_native(sll->sll_protocol));
}

bool
NdnDump::printPpp(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  // PPP, as per RFC 1661 and RFC 1662; if the first 2 bytes are 0xff and 0x03,
  // it's PPP in HDLC-like framing, with the PPP header following those two bytes,
  // otherwise it's PPP without framing, and the packet begins with the PPP header.
  // The data in the frame is not octet-stuffed or bit-stuffed.

  if (len < 2) {
    out << "Truncated PPP frame, length " << len;
    return true;
  }

  if (pkt[0] == 0xff && pkt[1] == 0x03) {
    // PPP in HDLC-like framing, skip the Address and Control fields
    if (len < 4) {
      out << "Truncated PPP frame, length " << len;
      return true;
    }
    pkt += 2;
    len -= 2;
  }

  unsigned int proto = pkt[0];
  if (proto & 0x1) {
    // Protocol field is compressed in 1 byte
    pkt += 1;
    len -= 1;
  }
  else {
    // Protocol field is 2 bytes, in network byte order
    proto = (proto << 8) | pkt[1];
    pkt += 2;
    len -= 2;
  }

  switch (proto) {
  case 0x0077: // NDN in PPP frame, used by ndnSIM pcap traces
    // For some reason, ndnSIM produces PPP frames with 2 extra bytes
    // between the protocol field and the beginning of the NDN packet
    if (len < 2) {
      out << "Truncated NDN/PPP frame";
      return true;
    }
    pkt += 2;
    len -= 2;
    out << "PPP";
    return printNdn(out, pkt, len);
  default:
    out << "[Unsupported PPP proto " << AsHex{proto} << "]";
    return true;
  }
}

static void
printIpAddress(OutputFormatter& out, int af, const void* addr)
{
  char addrStr[1 + std::max(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)] = {};
  if (inet_ntop(af, addr, addrStr, sizeof(addrStr))) {
    out << addrStr;
  }
  else {
    out << "???";
  }
}

bool
NdnDump::printIp4(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  out.addDelimiter() << "IP ";

  if (len < sizeof(ip)) {
    out << "truncated header, length " << len;
    return true;
  }

  auto ih = reinterpret_cast<const ip*>(pkt);
  if (ih->ip_v != 4) {
    // huh? link layer said this was an IPv4 packet but IP header says otherwise
    out << "bad version " << ih->ip_v;
    return true;
  }

  size_t ipHdrLen = ih->ip_hl * 4;
  if (ipHdrLen < sizeof(ip)) {
    out << "bad header length " << ipHdrLen;
    return true;
  }

  size_t ipLen = endian::big_to_native(ih->ip_len);
  if (ipLen < ipHdrLen) {
    out << "bad length " << ipLen;
    return true;
  }
  if (ipLen > len) {
    out << "truncated packet, " << ipLen - len << " bytes missing";
    return true;
  }
  // if we reached this point, the following is true:
  //     sizeof(ip) <= ipHdrLen <= ipLen <= len

  printIpAddress(out, AF_INET, &ih->ip_src);
  out << " > ";
  printIpAddress(out, AF_INET, &ih->ip_dst);

  pkt += ipHdrLen;
  len -= ipHdrLen;

  return dispatchByIpProto(out, pkt, len, ih->ip_p);
}

bool
NdnDump::printIp6(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  out.addDelimiter() << "IP6 ";

  if (len < sizeof(ip6_hdr)) {
    out << "truncated header, length " << len;
    return true;
  }

  auto ip6 = reinterpret_cast<const ip6_hdr*>(pkt);
  unsigned int ipVer = (ip6->ip6_vfc & 0xf0) >> 4;
  if (ipVer != 6) {
    // huh? link layer said this was an IPv6 packet but IP header says otherwise
    out << "bad version " << ipVer;
    return true;
  }

  pkt += sizeof(ip6_hdr);
  len -= sizeof(ip6_hdr);

  size_t payloadLen = endian::big_to_native(ip6->ip6_plen);
  if (len < payloadLen) {
    out << "truncated payload, " << payloadLen - len << " bytes missing";
    return true;
  }

  printIpAddress(out, AF_INET6, &ip6->ip6_src);
  out << " > ";
  printIpAddress(out, AF_INET6, &ip6->ip6_dst);

  // we assume no extension headers are present
  return dispatchByIpProto(out, pkt, len, ip6->ip6_nxt);
}

bool
NdnDump::printTcp(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  out.addDelimiter() << "TCP";

  if (len < sizeof(tcphdr)) {
    out << " truncated header, length " << len;
    return true;
  }

  auto th = reinterpret_cast<const tcphdr*>(pkt);
  size_t tcpHdrLen = th->TH_OFF * 4;
  if (tcpHdrLen < sizeof(tcphdr)) {
    out << " bad header length " << tcpHdrLen;
    return true;
  }
  if (tcpHdrLen > len) {
    out << " truncated header, " << tcpHdrLen - len << " bytes missing";
    return true;
  }

  pkt += tcpHdrLen;
  len -= tcpHdrLen;

  out.addDelimiter() << "length " << len;

  return printNdn(out, pkt, len);
}

bool
NdnDump::printUdp(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  out.addDelimiter() << "UDP";

  if (len < sizeof(udphdr)) {
    out << " truncated header, length " << len;
    return true;
  }

  auto uh = reinterpret_cast<const udphdr*>(pkt);
  size_t udpLen = endian::big_to_native(uh->UH_LEN);
  if (udpLen < sizeof(udphdr)) {
    out << " bad length " << udpLen;
    return true;
  }
  if (udpLen > len) {
    out << " truncated packet, " << udpLen - len << " bytes missing";
    return true;
  }
  else {
    len = udpLen;
  }

  pkt += sizeof(udphdr);
  len -= sizeof(udphdr);

  out.addDelimiter() << "length " << len;

  return printNdn(out, pkt, len);
}

bool
NdnDump::printNdn(OutputFormatter& out, const uint8_t* pkt, size_t len) const
{
  if (len == 0) {
    return false;
  }
  out.addDelimiter();

  bool isOk = false;
  Block block;
  std::tie(isOk, block) = Block::fromBuffer(pkt, len);
  if (!isOk) {
    // if packet is incomplete, we will not be able to process it
    out << "NDN truncated packet, length " << len;
    return true;
  }

  lp::Packet lpPacket;
  Block netPacket;

  if (block.type() == lp::tlv::LpPacket) {
    out << "NDNLPv2";
    try {
      lpPacket.wireDecode(block);
    }
    catch (const tlv::Error& e) {
      out << " invalid packet: " << e.what();
      return true;
    }

    Buffer::const_iterator begin, end;
    if (lpPacket.has<lp::FragmentField>()) {
      std::tie(begin, end) = lpPacket.get<lp::FragmentField>();
    }
    else {
      out << " idle";
      return true;
    }

    bool isOk = false;
    std::tie(isOk, netPacket) = Block::fromBuffer(&*begin, std::distance(begin, end));
    if (!isOk) {
      // if network packet is fragmented, we will not be able to process it
      out << " fragment";
      return true;
    }
  }
  else {
    netPacket = std::move(block);
  }
  out.addDelimiter();

  try {
    switch (netPacket.type()) {
      case tlv::Interest: {
        Interest interest(netPacket);
        if (!matchesFilter(interest.getName())) {
          return false;
        }

        if (lpPacket.has<lp::NackField>()) {
          lp::Nack nack(interest);
          nack.setHeader(lpPacket.get<lp::NackField>());
          out << "NACK (" << nack.getReason() << "): " << interest;
        }
        else {
          out << "INTEREST: " << interest;
        }
        break;
      }
      case tlv::Data: {
        Data data(netPacket);
        if (!matchesFilter(data.getName())) {
          return false;
        }

        out << "DATA: " << data.getName();
        break;
      }
      default: {
        out << "[Unsupported NDN packet type " << netPacket.type() << "]";
        break;
      }
    }
  }
  catch (const tlv::Error& e) {
    out << "invalid network packet: " << e.what();
  }

  return true;
}

bool
NdnDump::matchesFilter(const Name& name) const
{
  if (!nameFilter)
    return true;

  /// \todo Switch to NDN regular expressions
  return std::regex_match(name.toUri(), *nameFilter);
}

} // namespace dump
} // namespace ndn
