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);

Reply via email to