Ethereal-dev: Re: [ethereal-dev] ICMP Checksum

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

From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Fri, 9 Jun 2000 22:50:01 -0700
On Fri, Jun 09, 2000 at 06:50:35PM -0400, Joshua Krage wrote:
> Well here is a vote that ICMP checksums receive some attention. :)

Well, here is a patch that should do the job, although it suffers from
one of the same problems as my TCP/UDP payload checksum patch, i.e. it
doesn't blow off the checksum checking for fragmented datagrams.
Index: packet-ip.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet-ip.c,v
retrieving revision 1.92
diff -c -r1.92 packet-ip.c
*** packet-ip.c	2000/06/05 03:21:01	1.92
--- packet-ip.c	2000/06/10 05:47:56
***************
*** 775,791 ****
    "Not set"
  };
  
! static char *ip_checksum_state(e_ip *iph)
  {
      unsigned long Sum;
!     unsigned char *Ptr, *PtrEnd;
      unsigned short word;
  
      Sum    = 0;
!     PtrEnd = (lo_nibble(iph->ip_v_hl) * 4 + (char *)iph);
!     for (Ptr = (unsigned char *) iph; Ptr < PtrEnd; Ptr += 2) {
  	memcpy(&word, Ptr, sizeof word);
          Sum += word;
      }
  
      Sum = (Sum & 0xFFFF) + (Sum >> 16);
--- 775,792 ----
    "Not set"
  };
  
! static char *ip_checksum_state(const u_char *Ptr, int len)
  {
      unsigned long Sum;
!     const u_char *PtrEnd;
      unsigned short word;
  
      Sum    = 0;
!     PtrEnd = Ptr + len;
!     while (Ptr < PtrEnd) {
  	memcpy(&word, Ptr, sizeof word);
          Sum += word;
+         Ptr += 2;
      }
  
      Sum = (Sum & 0xFFFF) + (Sum >> 16);
***************
*** 903,909 ****
      proto_tree_add_uint_format(ip_tree, hf_ip_proto, NullTVB, offset +  9, 1, iph.ip_p,
  	"Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
      proto_tree_add_uint_format(ip_tree, hf_ip_checksum, NullTVB, offset + 10, 2, iph.ip_sum,
!         "Header checksum: 0x%04x (%s)", iph.ip_sum, ip_checksum_state((e_ip*) &pd[offset]));
      proto_tree_add_ipv4(ip_tree, hf_ip_src, NullTVB, offset + 12, 4, iph.ip_src);
      proto_tree_add_ipv4(ip_tree, hf_ip_dst, NullTVB, offset + 16, 4, iph.ip_dst);
      proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 12, 4, iph.ip_src);
--- 904,911 ----
      proto_tree_add_uint_format(ip_tree, hf_ip_proto, NullTVB, offset +  9, 1, iph.ip_p,
  	"Protocol: %s (0x%02x)", ipprotostr(iph.ip_p), iph.ip_p);
      proto_tree_add_uint_format(ip_tree, hf_ip_checksum, NullTVB, offset + 10, 2, iph.ip_sum,
! 	"Header checksum: 0x%04x (%s)", iph.ip_sum,
! 	ip_checksum_state(&pd[offset], hlen));
      proto_tree_add_ipv4(ip_tree, hf_ip_src, NullTVB, offset + 12, 4, iph.ip_src);
      proto_tree_add_ipv4(ip_tree, hf_ip_dst, NullTVB, offset + 16, 4, iph.ip_dst);
      proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, NullTVB, offset + 12, 4, iph.ip_src);
***************
*** 1083,1089 ****
      col_add_str(fd, COL_INFO, type_str);
  
    if (tree) {
!     ti = proto_tree_add_item(tree, proto_icmp, NullTVB, offset, 4, FALSE);
      icmp_tree = proto_item_add_subtree(ti, ett_icmp);
      proto_tree_add_uint_format(icmp_tree, hf_icmp_type, NullTVB, offset,      1, 
  			       ih.icmp_type,
--- 1085,1091 ----
      col_add_str(fd, COL_INFO, type_str);
  
    if (tree) {
!     ti = proto_tree_add_item(tree, proto_icmp, NullTVB, offset, END_OF_FRAME, FALSE);
      icmp_tree = proto_item_add_subtree(ti, ett_icmp);
      proto_tree_add_uint_format(icmp_tree, hf_icmp_type, NullTVB, offset,      1, 
  			       ih.icmp_type,
***************
*** 1093,1100 ****
  			       ih.icmp_code,
  			       "Code: %u %s",
  			       ih.icmp_code, code_str);
!     proto_tree_add_uint(icmp_tree, hf_icmp_checksum, NullTVB, offset +  2, 2, 
  			cksum);
  
      /* Decode the second 4 bytes of the packet. */
      switch (ih.icmp_type) {
--- 1095,1113 ----
  			       ih.icmp_code,
  			       "Code: %u %s",
  			       ih.icmp_code, code_str);
!     if (pi.captured_len >= pi.len) {
!       /* The packet isn't truncated, so we can checksum it.
!          XXX - we have to check whether this is part of a fragmented
! 	 IP datagram, too.... */
! 
!       proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, NullTVB, offset +  2, 2, 
! 			cksum,
! 			"Checksum: 0x%04x (%s)", cksum,
! 			ip_checksum_state(&pd[offset], END_OF_FRAME));
!     } else {
!       proto_tree_add_uint(icmp_tree, hf_icmp_checksum, NullTVB, offset +  2, 2, 
  			cksum);
+     }
  
      /* Decode the second 4 bytes of the packet. */
      switch (ih.icmp_type) {