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,