dump: add IPv6 support
Change-Id: Id9d10cf1080d2d7f98e9a48216c6564c6bbf8607
Refs: #3861
diff --git a/tests/dump/README.md b/tests/dump/README.md
deleted file mode 100644
index adf5f96..0000000
--- a/tests/dump/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-Testing Instructions
-====================
-
-This folder contains a tcpdump trace that can be used to manually check
-the correctness of ndndump.
-
-## Test Cases / Trace File Description
-
-### 1. NDNLPv2 NACK
-
-Trace file: `nack.pcap`
-
-Trace summary: Six IPv4 UDP packets, carrying NDN interests and NACK packets.
-Twelve IPv4 TCP packets, carrying NDN interests and NACK packets.
-
-Expected result of the capture:
-
-- 3 NDN interests are captured with UDP tunnel type.
-- 3 NACKs are captured with UDP tunnel type and the NACK reasons:
- - Congestion
- - Duplicate
- - None
-
-- 3 NDN interests are captured with TCP tunnel type.
-- 4 NACKs are captured with TCP tunnel type and the NACK reasons:
- - Congestion
- - Duplicate
- - None
- - None
-
-### 2. LINUX\_SLL link-type
-
-Trace file: `LINUXSLL-udp4.pcap` `LINUXSLL-udp6.pcap` `LINUXSLL-tcp4.pcap` `LINUXSLL-tcp6.pcap`
-
-These traces are captured inside an OpenVZ container which uses LINUX\_SLL (Linux cooked) link-type.
-
-Expected result:
-Some Interests and Data should be displayed from udp4 and tcp4 traces.
-Currently nothing is displayed from udp6 and tcp6 traces because ndndump lacks IPv6 support until [Feature 3861](https://redmine.named-data.net/issues/3861).
diff --git a/tests/dump/ndndump.t.cpp b/tests/dump/ndndump.t.cpp
index f4e3d67..771de00 100644
--- a/tests/dump/ndndump.t.cpp
+++ b/tests/dump/ndndump.t.cpp
@@ -313,6 +313,34 @@
BOOST_CHECK(output.is_equal("IP truncated packet, 980 bytes missing\n"));
}
+BOOST_AUTO_TEST_CASE(MalformedIpv6Header)
+{
+ dump.wantTimestamp = false;
+
+ uint8_t theAnswer = 42;
+
+ EncodingBuffer pkt1;
+ pkt1.prependByte(theAnswer);
+ this->receiveEthernet(pkt1, s_ethertypeIp6);
+ BOOST_CHECK(output.is_equal("IP6 truncated header, length 1\n"));
+
+ ip6_hdr ip6Hdr2{};
+ ip6Hdr2.ip6_vfc = 10 << 4;
+
+ EncodingBuffer pkt2;
+ this->receiveIp6(pkt2, &ip6Hdr2);
+ BOOST_CHECK(output.is_equal("IP6 bad version 10\n"));
+
+ ip6_hdr ip6Hdr3{};
+ ip6Hdr3.ip6_vfc = 6 << 4;
+ ip6Hdr3.ip6_plen = 1400;
+ endian::native_to_big_inplace(ip6Hdr3.ip6_plen);
+
+ EncodingBuffer pkt3;
+ this->receiveIp6(pkt3, &ip6Hdr3);
+ BOOST_CHECK(output.is_equal("IP6 truncated payload, 1400 bytes missing\n"));
+}
+
BOOST_AUTO_TEST_CASE(UnsupportedIpProto)
{
dump.wantTimestamp = false;
@@ -324,9 +352,17 @@
endian::native_to_big_inplace(ipHdr.ip_len);
ipHdr.ip_p = IPPROTO_SCTP;
- EncodingBuffer pkt;
- this->receiveIp4(pkt, &ipHdr);
+ EncodingBuffer pkt1;
+ this->receiveIp4(pkt1, &ipHdr);
BOOST_CHECK(output.is_equal("IP 0.0.0.0 > 0.0.0.0, [Unsupported IP proto 132]\n"));
+
+ ip6_hdr ip6Hdr{};
+ ip6Hdr.ip6_vfc = 6 << 4;
+ ip6Hdr.ip6_nxt = IPPROTO_NONE;
+
+ EncodingBuffer pkt2;
+ this->receiveIp6(pkt2, &ip6Hdr);
+ BOOST_CHECK(output.is_equal("IP6 :: > ::, [No next header]\n"));
}
BOOST_AUTO_TEST_CASE(MalformedTcpHeader)
@@ -435,6 +471,68 @@
BOOST_CHECK(output.is_equal(expected));
}
+BOOST_AUTO_TEST_CASE(LinuxSllTcp4)
+{
+ dump.wantTimestamp = false;
+ this->readFile("tests/dump/linux-sll-tcp4.pcap");
+
+ const std::string expected =
+ "IP 162.211.64.84 > 131.179.196.46, TCP, length 57, "
+ "INTEREST: /ndn/edu/ucla/ping/4436024701616433461?ndn.MustBeFresh=1&ndn.Nonce=1827520902\n"
+ "IP 162.211.64.84 > 131.179.196.46, TCP, length 41, "
+ "INTEREST: /ndn/edu/arizona/ping/8202?ndn.Nonce=1059849935\n"
+ "IP 131.179.196.46 > 162.211.64.84, TCP, length 403, "
+ "DATA: /ndn/edu/arizona/ping/8202\n"
+ "IP 131.179.196.46 > 162.211.64.84, TCP, length 57, "
+ "INTEREST: /ndn/edu/ucla/ping/4436024701616433462?ndn.MustBeFresh=1&ndn.Nonce=4082468009\n"
+ "IP 162.211.64.84 > 131.179.196.46, TCP, length 57, "
+ "INTEREST: /ndn/edu/ucla/ping/4436024701616433462?ndn.MustBeFresh=1&ndn.Nonce=4082468009\n";
+ BOOST_CHECK(output.is_equal(expected));
+}
+
+BOOST_AUTO_TEST_CASE(LinuxSllUdp4)
+{
+ dump.wantTimestamp = false;
+ this->readFile("tests/dump/linux-sll-udp4.pcap");
+
+ const std::string expected =
+ "IP 162.211.64.84 > 131.179.196.46, UDP, length 42, "
+ "INTEREST: /ndn/edu/arizona/ping/31044?ndn.Nonce=3171630323\n"
+ "IP 131.179.196.46 > 162.211.64.84, UDP, length 404, "
+ "DATA: /ndn/edu/arizona/ping/31044\n";
+ BOOST_CHECK(output.is_equal(expected));
+}
+
+BOOST_AUTO_TEST_CASE(LinuxSllTcp6)
+{
+ dump.wantTimestamp = false;
+ this->readFile("tests/dump/linux-sll-tcp6.pcap");
+
+ const std::string expected =
+ "IP6 2602:fff6:d:b317::39f8 > 2001:660:3302:282c:160::163, TCP, length 42, "
+ "INTEREST: /ndn/edu/arizona/ping/19573?ndn.Nonce=777756283\n"
+ "IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, TCP, length 404, "
+ "DATA: /ndn/edu/arizona/ping/19573\n"
+ "IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, TCP, length 56, "
+ "INTEREST: /ndn/fr/lip6/ping/7847878851635149046?ndn.MustBeFresh=1&ndn.Nonce=1836363210\n";
+ BOOST_CHECK(output.is_equal(expected));
+}
+
+BOOST_AUTO_TEST_CASE(LinuxSllUdp6)
+{
+ dump.wantTimestamp = false;
+ this->readFile("tests/dump/linux-sll-udp6.pcap");
+
+ const std::string expected =
+ "IP6 2602:fff6:d:b317::39f8 > 2001:660:3302:282c:160::163, UDP, length 39, "
+ "INTEREST: /ndn/edu/arizona/ping/18?ndn.Nonce=571618686\n"
+ "IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, UDP, length 401, "
+ "DATA: /ndn/edu/arizona/ping/18\n"
+ "IP6 2001:660:3302:282c:160::163 > 2602:fff6:d:b317::39f8, UDP, length 56, "
+ "INTEREST: /ndn/fr/lip6/ping/7847878851635149038?ndn.MustBeFresh=1&ndn.Nonce=192371114\n";
+ BOOST_CHECK(output.is_equal(expected));
+}
+
BOOST_AUTO_TEST_SUITE_END() // TestNdnDump
BOOST_AUTO_TEST_SUITE_END() // Dump
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";
diff --git a/tools/dump/ndndump.hpp b/tools/dump/ndndump.hpp
index 25a35d4..0198026 100644
--- a/tools/dump/ndndump.hpp
+++ b/tools/dump/ndndump.hpp
@@ -76,6 +76,9 @@
printIp4(OutputFormatter& out, const uint8_t* pkt, size_t len) const;
bool
+ printIp6(OutputFormatter& out, const uint8_t* pkt, size_t len) const;
+
+ bool
printTcp(OutputFormatter& out, const uint8_t* pkt, size_t len) const;
bool