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-ip6.c b/print-ip6.c
index 29e5988..3e8db27 100644
--- a/print-ip6.c
+++ b/print-ip6.c
@@ -21,7 +21,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.47.2.5 2007/09/21 07:07:52 hannes Exp $";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.52 2007-09-21 07:05:33 hannes Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -36,6 +36,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "netdissect.h"
 #include "interface.h"
 #include "addrtoname.h"
 #include "extract.h"
@@ -44,10 +45,41 @@
 #include "ipproto.h"
 
 /*
+ * Compute a V6-style checksum by building a pseudoheader.
+ */
+int
+nextproto6_cksum(const struct ip6_hdr *ip6, const u_int8_t *data,
+		 u_int len, u_int next_proto)
+{
+        struct {
+                struct in6_addr ph_src;
+                struct in6_addr ph_dst;
+                u_int32_t       ph_len;
+                u_int8_t        ph_zero[3];
+                u_int8_t        ph_nxt;
+        } ph;
+        struct cksum_vec vec[2];
+
+        /* pseudo-header */
+        memset(&ph, 0, sizeof(ph));
+        UNALIGNED_MEMCPY(&ph.ph_src, &ip6->ip6_src, sizeof (struct in6_addr));
+        UNALIGNED_MEMCPY(&ph.ph_dst, &ip6->ip6_dst, sizeof (struct in6_addr));
+        ph.ph_len = htonl(len);
+        ph.ph_nxt = next_proto;
+
+        vec[0].ptr = (const u_int8_t *)(void *)&ph;
+        vec[0].len = sizeof(ph);
+        vec[1].ptr = data;
+        vec[1].len = len;
+
+        return in_cksum(vec, 2);
+}
+
+/*
  * print an IP6 datagram.
  */
 void
-ip6_print(register const u_char *bp, register u_int length)
+ip6_print(netdissect_options *ndo, const u_char *bp, u_int length)
 {
 	register const struct ip6_hdr *ip6;
 	register int advance;
@@ -63,62 +95,62 @@
 
 	TCHECK(*ip6);
 	if (length < sizeof (struct ip6_hdr)) {
-		(void)printf("truncated-ip6 %u", length);
+		(void)ND_PRINT((ndo, "truncated-ip6 %u", length));
 		return;
 	}
 
-        if (!eflag)
-            printf("IP6 ");
+        if (!ndo->ndo_eflag)
+            ND_PRINT((ndo, "IP6 "));
 
 	payload_len = EXTRACT_16BITS(&ip6->ip6_plen);
 	len = payload_len + sizeof(struct ip6_hdr);
 	if (length < len)
-		(void)printf("truncated-ip6 - %u bytes missing!",
-			len - length);
+		(void)ND_PRINT((ndo, "truncated-ip6 - %u bytes missing!",
+			len - length));
 
-        if (vflag) {
+        if (ndo->ndo_vflag) {
             flow = EXTRACT_32BITS(&ip6->ip6_flow);
-            printf("(");
+            ND_PRINT((ndo, "("));
 #if 0
             /* rfc1883 */
             if (flow & 0x0f000000)
-		(void)printf("pri 0x%02x, ", (flow & 0x0f000000) >> 24);
+		(void)ND_PRINT((ndo, "pri 0x%02x, ", (flow & 0x0f000000) >> 24));
             if (flow & 0x00ffffff)
-		(void)printf("flowlabel 0x%06x, ", flow & 0x00ffffff);
+		(void)ND_PRINT((ndo, "flowlabel 0x%06x, ", flow & 0x00ffffff));
 #else
             /* RFC 2460 */
             if (flow & 0x0ff00000)
-		(void)printf("class 0x%02x, ", (flow & 0x0ff00000) >> 20);
+		(void)ND_PRINT((ndo, "class 0x%02x, ", (flow & 0x0ff00000) >> 20));
             if (flow & 0x000fffff)
-		(void)printf("flowlabel 0x%05x, ", flow & 0x000fffff);
+		(void)ND_PRINT((ndo, "flowlabel 0x%05x, ", flow & 0x000fffff));
 #endif
 
-            (void)printf("hlim %u, next-header %s (%u) payload length: %u) ",
+            (void)ND_PRINT((ndo, "hlim %u, next-header %s (%u) payload length: %u) ",
                          ip6->ip6_hlim,
                          tok2str(ipproto_values,"unknown",ip6->ip6_nxt),
                          ip6->ip6_nxt,
-                         payload_len);
+                         payload_len));
         }
 
 	/*
 	 * Cut off the snapshot length to the end of the IP payload.
 	 */
 	ipend = bp + len;
-	if (ipend < snapend)
-		snapend = ipend;
+	if (ipend < ndo->ndo_snapend)
+		ndo->ndo_snapend = ipend;
 
 	cp = (const u_char *)ip6;
 	advance = sizeof(struct ip6_hdr);
 	nh = ip6->ip6_nxt;
-	while (cp < snapend && advance > 0) {
+	while (cp < ndo->ndo_snapend && advance > 0) {
 		cp += advance;
 		len -= advance;
 
 		if (cp == (const u_char *)(ip6 + 1) &&
 		    nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
 		    nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) {
-			(void)printf("%s > %s: ", ip6addr_string(&ip6->ip6_src),
-				     ip6addr_string(&ip6->ip6_dst));
+			(void)ND_PRINT((ndo, "%s > %s: ", ip6addr_string(&ip6->ip6_src),
+				     ip6addr_string(&ip6->ip6_dst)));
 		}
 
 		switch (nh) {
@@ -132,7 +164,7 @@
 			break;
 		case IPPROTO_FRAGMENT:
 			advance = frag6_print(cp, (const u_char *)ip6);
-			if (snapend <= cp + advance)
+			if (ndo->ndo_snapend <= cp + advance)
 				return;
 			nh = *cp;
 			fragmented = 1;
@@ -170,7 +202,7 @@
 			udp_print(cp, len, (const u_char *)ip6, fragmented);
 			return;
 		case IPPROTO_ICMPV6:
-			icmp6_print(cp, len, (const u_char *)ip6, fragmented);
+			icmp6_print(ndo, cp, len, (const u_char *)ip6, fragmented);
 			return;
 		case IPPROTO_AH:
 			advance = ah_print(cp);
@@ -179,7 +211,7 @@
 		case IPPROTO_ESP:
 		    {
 			int enh, padlen;
-			advance = esp_print(gndo, cp, len, (const u_char *)ip6, &enh, &padlen);
+			advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen);
 			nh = enh & 0xff;
 			len -= padlen;
 			break;
@@ -193,7 +225,8 @@
 		    }
 
 		case IPPROTO_PIM:
-			pim_print(cp, len);
+			pim_print(cp, len, nextproto6_cksum(ip6, cp, len,
+							    IPPROTO_PIM));
 			return;
 
 		case IPPROTO_OSPF:
@@ -201,11 +234,11 @@
 			return;
 
 		case IPPROTO_IPV6:
-			ip6_print(cp, len);
+			ip6_print(ndo, cp, len);
 			return;
 
 		case IPPROTO_IPV4:
-		        ip_print(gndo, cp, len);
+		        ip_print(ndo, cp, len);
 			return;
 
                 case IPPROTO_PGM:
@@ -221,18 +254,18 @@
 			return;
 
 		case IPPROTO_NONE:
-			(void)printf("no next header");
+			(void)ND_PRINT((ndo, "no next header"));
 			return;
 
 		default:
-			(void)printf("ip-proto-%d %d", nh, len);
+			(void)ND_PRINT((ndo, "ip-proto-%d %d", nh, len));
 			return;
 		}
 	}
 
 	return;
 trunc:
-	(void)printf("[|ip6]");
+	(void)ND_PRINT((ndo, "[|ip6]"));
 }
 
 #endif /* INET6 */