Our tcpdump has the ability to detect bad TCP and UDP checksums with the
-v flag, but not ICMP and ICMPv6 checksums. Here are two diffs to let
tcpdump detect bad ICMP/ICMPv6 checksums, which should help when
debugging issues caused by such checksums. :)
The first diff (below) is simply a mechanical change to make
icmp_print() accept the length variable, which is the length of the
packet without the IP header. This value is needed by tcpdump's
in_cksum() (used by the second diff) to determine if an ICMP checksum is
correct.
Related functions like {tcp,udp,icmp6}_print() already accept this
length variable, so this change will make icmp_print() consistent with
them as well.
This diff introduces no functional change.
The second diff does the actual ICMP/ICMPv6 checksum verification; I'll
send it in a separate mail.
Index: interface.h
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/interface.h,v
retrieving revision 1.61
diff -u -p -U5 -r1.61 interface.h
--- interface.h 6 Apr 2010 16:01:57 -0000 1.61
+++ interface.h 1 Jan 2014 20:36:46 -0000
@@ -208,11 +208,11 @@ extern void ether_if_print(u_char *, con
const u_char *);
extern void fddi_if_print(u_char *, const struct pcap_pkthdr *, const u_char
*);
extern void ppp_ether_if_print(u_char *, const struct pcap_pkthdr *,
const u_char *);
extern void gre_print(const u_char *, u_int);
-extern void icmp_print(const u_char *, const u_char *);
+extern void icmp_print(const u_char *, u_int, const u_char *);
extern void ieee802_11_if_print(u_char *, const struct pcap_pkthdr *,
const u_char *);
extern void ieee802_11_radio_if_print(u_char *, const struct pcap_pkthdr *,
const u_char *);
extern void iapp_print(const u_char *, u_int);
Index: print-icmp.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-icmp.c,v
retrieving revision 1.20
diff -u -p -U5 -r1.20 print-icmp.c
--- print-icmp.c 27 Oct 2009 23:59:55 -0000 1.20
+++ print-icmp.c 2 Jan 2014 04:41:04 -0000
@@ -163,11 +163,11 @@ struct id_rdiscovery {
u_int32_t ird_addr;
u_int32_t ird_pref;
};
void
-icmp_print(const u_char *bp, const u_char *bp2)
+icmp_print(const u_char *bp, u_int length, const u_char *bp2)
{
const struct icmp *dp;
const struct ip *ip;
const char *str, *fmt;
const struct ip *oip;
Index: print-ip.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-ip.c,v
retrieving revision 1.36
diff -u -p -U5 -r1.36 print-ip.c
--- print-ip.c 12 Jan 2010 06:10:33 -0000 1.36
+++ print-ip.c 1 Jan 2014 20:37:01 -0000
@@ -425,11 +425,11 @@ ip_print(register const u_char *bp, regi
case IPPROTO_UDP:
udp_print(cp, len, (const u_char *)ip);
break;
case IPPROTO_ICMP:
- icmp_print(cp, (const u_char *)ip);
+ icmp_print(cp, len, (const u_char *)ip);
break;
#ifndef IPPROTO_IGRP
#define IPPROTO_IGRP 9
#endif
Index: print-ipsec.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-ipsec.c,v
retrieving revision 1.17
diff -u -p -U5 -r1.17 print-ipsec.c
--- print-ipsec.c 3 May 2012 10:17:23 -0000 1.17
+++ print-ipsec.c 1 Jan 2014 20:37:50 -0000
@@ -185,11 +185,11 @@ esp_decrypt (const u_char *bp, u_int len
break;
case IPPROTO_IPV4:
ip_print(data, len);
break;
case IPPROTO_ICMP:
- icmp_print(data, bp2);
+ icmp_print(data, len, bp2);
break;
case IPPROTO_ICMPV6:
icmp6_print(data, len, bp2);
break;
default:
@@ -296,11 +296,12 @@ ah_print (register const u_char *bp, reg
case IPPROTO_IPIP: /* Tunnel Mode, IP-in-IP */
ip_print(bp + pl_len, len - pl_len);
break;
case IPPROTO_ICMP: /* From here and down; Transport mode */
- icmp_print(bp + pl_len, (const u_char *) ip);
+ icmp_print(bp + pl_len, len - pl_len,
+ (const u_char *) ip);
break;
case IPPROTO_ICMPV6:
icmp6_print(bp + pl_len, len - pl_len,
(const u_char *) ip);