dump: add IPv6 support

Change-Id: Id9d10cf1080d2d7f98e9a48216c6564c6bbf8607
Refs: #3861
diff --git a/tools/dump/ndndump.cpp b/tools/dump/ndndump.cpp
index 6722a78..2be64f9 100644
--- a/tools/dump/ndndump.cpp
+++ b/tools/dump/ndndump.cpp
@@ -22,6 +22,7 @@
 #include <arpa/inet.h>
 #include <net/ethernet.h>
 #include <netinet/ip.h>
+#include <netinet/ip6.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 
@@ -230,6 +231,8 @@
   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";
@@ -246,6 +249,9 @@
   out.addDelimiter();
 
   switch (ipProto) {
+  case IPPROTO_NONE:
+    out << "[No next header]";
+    return true;
   case IPPROTO_TCP:
     return printTcp(out, pkt, len);
   case IPPROTO_UDP:
@@ -403,6 +409,41 @@
 }
 
 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";