Ethereal-dev: [Ethereal-dev] [Bug Report] IPv6 PIM checksum

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: SUZUKI Shinsuke <suz@xxxxxxxx>
Date: Tue, 30 Oct 2001 14:03:09 +0900
Hello all.

Here's a report and patch for ethereal's IPv6 PIM checksum calculation bug.
Could you please review this report and merge this patch into ethereal?

Thanks,
----
SUZUKI, Shinsuke @ KAME Project


-----
[Phenomena]
Ethereal says IPv6 PIM checksum is incorrect even for correct ones.


[Environment]
1) Operating System and version 
FreeBSD 4.4-RELEASE

2) Version of GTK+
1.2.10

3) Version of Ethereal
ethereal 0.8.19, with GTK+ 1.2.10, with GLib 1.2.10, with libpcap 0.5, with libz 1.1.3, without SNMP

4) The command I used to invoke Ethereal
just "ethereal"

5) The sequence of operations I performed that caused the bug to appear
just monitors IPv6 PIM packets generated from KAME's pim6sd.

e.g.) IPv6 PIM Hello Packet from fe80::1 to ff02::d, with holdtime=105.
	1c 00 00 00 60 00 00 00  00 0a 67 01 fe 80 00 00
	00 00 00 00 00 00 00 00  00 00 00 01 ff 02 00 00
	00 00 00 00 00 00 00 00  00 00 00 01 20 00 e1 9c
	00 01 00 02 00 69
     
      Ethereal says the PIM checksum in this packet(0xe19c) is incorrect and
      should be (0xdf93).


[Reason]
In packet_pim.c, ethereal calculates PIM checksum using just PIM message.
However in case of IPv6, IPv6 pseudo-header should also be used in its
calculation. (see draft-ietf-pim-sm-v2-new-03.txt Page.99)


[Patch]
Here's the patch for this issue.

--- packet-pim.c	Sat Jul 21 19:27:13 2001
+++ packet-pim.c.new	Tue Oct 30 13:43:34 2001
@@ -613,6 +613,7 @@
     guint length, pim_length;
     guint16 pim_cksum, computed_cksum;
     vec_t cksum_vec[1];
+    guint32 phdr[2];
     char *typestr;
     proto_tree *pim_tree = NULL;
     proto_item *ti; 
@@ -688,9 +689,33 @@
 	     * The packet isn't part of a fragmented datagram and isn't
 	     * truncated, so we can checksum it.
 	     */
-	    cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
-	    cksum_vec[0].len = pim_length;
-	    computed_cksum = in_cksum(&cksum_vec[0], 1);
+
+	    switch (pinfo->src.type) {
+	    case AT_IPv4:
+		cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
+		cksum_vec[0].len = pim_length;
+		computed_cksum = in_cksum(&cksum_vec[0], 1);
+		break;
+	    case AT_IPv6:
+		/* Set up the fields of the pseudo-header. */
+		cksum_vec[0].ptr = pinfo->src.data;
+		cksum_vec[0].len = pinfo->src.len;
+		cksum_vec[1].ptr = pinfo->dst.data;
+		cksum_vec[1].len = pinfo->dst.len;
+		cksum_vec[2].ptr = (const guint8 *)&phdr;
+		phdr[0] = htonl(pim_length);
+		phdr[1] = htonl(IP_PROTO_PIM);
+		cksum_vec[2].len = 8;
+		cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length);
+		cksum_vec[3].len = pim_length;
+		computed_cksum = in_cksum(&cksum_vec[0], 4);
+		break;
+	    default:
+	    	/* PIM is available for IPv4 and IPv6 right now */
+		g_assert_not_reached();
+		break;
+	    }
+
 	    if (computed_cksum == 0) {
 		proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
 			offset + 2, 2, pim_cksum,