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-nflog.c b/print-nflog.c
new file mode 100644
index 0000000..94dee18
--- /dev/null
+++ b/print-nflog.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2013, Petar Alilovic,
+ * Faculty of Electrical Engineering and Computing, University of Zagreb
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ *	 this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <pcap.h>
+
+#include "netdissect.h"
+#include "interface.h"
+
+#if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H)
+#include <pcap/nflog.h>
+
+static const struct tok nflog_values[] = {
+	{ AF_INET,		"IPv4" },
+	{ AF_INET6,		"IPv6" },
+	{ 0,				NULL }
+};
+
+static inline void
+nflog_hdr_print(struct netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length)
+{
+	ND_PRINT((ndo, "version %d, resource ID %d", hdr->nflog_version, ntohs(hdr->nflog_rid)));
+
+	if (!ndo->ndo_qflag) {
+		ND_PRINT((ndo,", family %s (%d)",
+						  tok2str(nflog_values, "Unknown",
+								  hdr->nflog_family),
+						  hdr->nflog_family));
+		} else {
+		ND_PRINT((ndo,", %s",
+						  tok2str(nflog_values,
+								  "Unknown NFLOG (0x%02x)",
+								  hdr->nflog_family)));
+		}
+
+	ND_PRINT((ndo, ", length %u: ", length));
+}
+
+u_int
+nflog_if_print(struct netdissect_options *ndo,
+			   const struct pcap_pkthdr *h, const u_char *p)
+{
+	const nflog_hdr_t *hdr = (const nflog_hdr_t *)p;
+	const nflog_tlv_t *tlv;
+	u_int16_t size;
+	u_int16_t h_size = sizeof(nflog_hdr_t);
+	u_int caplen = h->caplen;
+	u_int length = h->len;
+
+	if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) {
+		ND_PRINT((ndo, "[|nflog]"));
+		return h_size;
+	}
+
+	if (!(hdr->nflog_version) == 0) {
+		ND_PRINT((ndo, "version %u (unknown)", hdr->nflog_version));
+		return h_size;
+	}
+
+	if (ndo->ndo_eflag)
+		nflog_hdr_print(ndo, hdr, length);
+
+	p += sizeof(nflog_hdr_t);
+	length -= sizeof(nflog_hdr_t);
+	caplen -= sizeof(nflog_hdr_t);
+
+	while (length > 0) {
+		/* We have some data.  Do we have enough for the TLV header? */
+		if (caplen < sizeof(nflog_tlv_t) || length < sizeof(nflog_tlv_t)) {
+			/* No. */
+			ND_PRINT((ndo, "[|nflog]"));
+			return h_size;
+		}
+
+		tlv = (const nflog_tlv_t *) p;
+		size = tlv->tlv_length;
+		if (size % 4 != 0)
+			size += 4 - size % 4;
+
+		/* Is the TLV's length less than the minimum? */
+		if (size < sizeof(nflog_tlv_t)) {
+			/* Yes. Give up now. */
+			ND_PRINT((ndo, "[|nflog]"));
+			return h_size;
+		}
+
+		/* Do we have enough data for the full TLV? */
+		if (caplen < size || length < size) {
+			/* No. */
+			ND_PRINT((ndo, "[|nflog]"));
+			return h_size;
+		}
+
+		if (tlv->tlv_type == NFULA_PAYLOAD) {
+			/*
+			 * This TLV's data is the packet payload.
+			 * Skip past the TLV header, and break out
+			 * of the loop so we print the packet data.
+			 */
+			p += sizeof(nflog_tlv_t);
+			h_size += sizeof(nflog_tlv_t);
+			length -= sizeof(nflog_tlv_t);
+			caplen -= sizeof(nflog_tlv_t);
+			break;
+		}
+
+		p += size;
+		h_size += size;
+		length -= size;
+		caplen -= size;
+	}
+
+	switch (hdr->nflog_family) {
+
+	case AF_INET:
+		ip_print(ndo, p, length);
+		break;
+
+#ifdef INET6
+	case AF_INET6:
+		ip6_print(ndo, p, length);
+		break;
+#endif /*INET6*/
+
+	default:
+		if (!ndo->ndo_eflag)
+			nflog_hdr_print(ndo, hdr,
+				length + sizeof(nflog_hdr_t));
+
+		if (!ndo->ndo_suppress_default_print)
+			ndo->ndo_default_print(ndo, p, caplen);
+		break;
+	}
+
+	return h_size;
+}
+
+#endif /* defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) */