Merge remote-tracking branch 'goog/tcpdump'

* goog/tcpdump: (3066 commits)
  Remove old version. Getting ready for new tcpdump 4.5
  Support -Q for setting the capture direction.
  Clean up the TLV processing loop.
  With -A and -AA, don't send CRs to the standard output.
  Use the new libpcap <pcap/nflog.h> for NFLOG definitions and declarations.
  Do our own isascii(), isprint(), isgraph(), and toascii().
  Fix a compiler warning.
  Don't use the __attribute__((packed)) on most platforms.
  The interval in an AODV HELLO extension is not aligned on a 4-byte boundary.
  As with memcpy, so with memcmp.
  More UNALIGNED_MEM{CPY,CMP} on IP addresses.
  Another case where UNALIGNED_MEMCPY() is probably necessary.
  No need for casting back and forth.
  Only do the unaligned_mem{cpy,cmp} hack if necessary.
  No need to declare unaligned_mem{cpy,cmp} in netdissect.h *and* interface.h.
  More possibly-unaligned memcpy()s and assignments - use unaligned_memcpy().
  Check for compiling for IPv6; don't check whether we can create an IPv6 socket.
  Use unaligned_memcmp() to compare with IPv{4,6} addresses in a packet.
  Use EXTRACT_nBITS even when just testing against zero.
  Fix some more unaligned accesses.
  ...

Change-Id: I9e98707d30c989b9e32dcd5af798bd0746ab4434
diff --git a/print-ipnet.c b/print-ipnet.c
new file mode 100644
index 0000000..e8ed94d
--- /dev/null
+++ b/print-ipnet.c
@@ -0,0 +1,109 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <pcap.h>
+
+#include "netdissect.h"
+#include "interface.h"
+#include "addrtoname.h"
+#include "ipnet.h"
+
+#ifdef DLT_IPNET
+
+static const struct tok ipnet_values[] = {
+	{ IPH_AF_INET,		"IPv4" },
+	{ IPH_AF_INET6,		"IPv6" },
+	{ 0,			NULL }
+};
+
+static inline void
+ipnet_hdr_print(struct netdissect_options *ndo, const u_char *bp, u_int length)
+{
+	const ipnet_hdr_t *hdr;
+	hdr = (const ipnet_hdr_t *)bp;
+
+	ND_PRINT((ndo, "%d > %d", hdr->iph_zsrc, hdr->iph_zdst));
+
+	if (!ndo->ndo_qflag) {
+		ND_PRINT((ndo,", family %s (%d)",
+                          tok2str(ipnet_values, "Unknown",
+                                  hdr->iph_family),
+                          hdr->iph_family));
+        } else {
+		ND_PRINT((ndo,", %s",
+                          tok2str(ipnet_values,
+                                  "Unknown Ethertype (0x%04x)",
+                                  hdr->iph_family)));
+        }
+
+	ND_PRINT((ndo, ", length %u: ", length));
+}
+
+static void
+ipnet_print(struct netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
+{
+	ipnet_hdr_t *hdr;
+
+	if (caplen < sizeof(ipnet_hdr_t)) {
+		ND_PRINT((ndo, "[|ipnet]"));
+		return;
+	}
+
+	if (ndo->ndo_eflag)
+		ipnet_hdr_print(ndo, p, length);
+
+	length -= sizeof(ipnet_hdr_t);
+	caplen -= sizeof(ipnet_hdr_t);
+	hdr = (ipnet_hdr_t *)p;
+	p += sizeof(ipnet_hdr_t);
+
+	switch (hdr->iph_family) {
+
+	case IPH_AF_INET:
+	        ip_print(ndo, p, length);
+		break;
+
+#ifdef INET6
+	case IPH_AF_INET6:
+		ip6_print(ndo, p, length);
+		break;
+#endif /*INET6*/
+
+	default:
+		if (!ndo->ndo_eflag)
+			ipnet_hdr_print(ndo, (u_char *)hdr,
+					length + sizeof(ipnet_hdr_t));
+
+		if (!ndo->ndo_suppress_default_print)
+			ndo->ndo_default_print(ndo, p, caplen);
+		break;
+	}
+}
+
+/*
+ * This is the top level routine of the printer.  'p' points
+ * to the ether header of the packet, 'h->ts' is the timestamp,
+ * 'h->len' is the length of the packet off the wire, and 'h->caplen'
+ * is the number of bytes actually captured.
+ */
+u_int
+ipnet_if_print(struct netdissect_options *ndo,
+               const struct pcap_pkthdr *h, const u_char *p)
+{
+	ipnet_print(ndo, p, h->len, h->caplen);
+
+	return (sizeof(ipnet_hdr_t));
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */
+
+#endif /* DLT_IPNET */