From: itojun Date: Fri, 2 May 2003 08:13:54 +0000 (+0000) Subject: verify/warn icmpv6 checksum. from jinmei@kame X-Git-Tag: tcpdump-3.8-bp~160 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/ba8e54bc85811d3a03d59c18ae61d57297fab3e8 verify/warn icmpv6 checksum. from jinmei@kame --- diff --git a/interface.h b/interface.h index 07378f72..29b6f9b2 100644 --- a/interface.h +++ b/interface.h @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.208 2003-05-01 18:02:12 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.209 2003-05-02 08:13:54 itojun Exp $ (LBL) */ #ifndef tcpdump_interface_h @@ -312,7 +312,7 @@ extern int hbhopt_print(const u_char *); extern int dstopt_print(const u_char *); extern int frag6_print(const u_char *, const u_char *); extern int mobility_print(const u_char *, const u_char *); -extern void icmp6_print(const u_char *, const u_char *); +extern void icmp6_print(const u_char *, const u_char *, int); extern void ripng_print(const u_char *, unsigned int); extern int rt6_print(const u_char *, const u_char *); extern void ospf6_print(const u_char *, u_int); diff --git a/print-icmp6.c b/print-icmp6.c index ce7474f9..5b8b44f5 100644 --- a/print-icmp6.c +++ b/print-icmp6.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.69 2003-03-13 07:36:56 guy Exp $"; + "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.70 2003-05-02 08:13:55 itojun Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -100,8 +100,51 @@ print_lladdr(const u_int8_t *p, size_t l) } } +static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp, + int len) +{ + int i; + register const u_int16_t *sp; + u_int32_t sum; + union { + struct { + struct in6_addr ph_src; + struct in6_addr ph_dst; + u_int32_t ph_len; + u_int8_t ph_zero[3]; + u_int8_t ph_nxt; + } ph; + u_int16_t pa[20]; + } phu; + + /* pseudo-header */ + memset(&phu, 0, sizeof(phu)); + phu.ph.ph_src = ip6->ip6_src; + phu.ph.ph_dst = ip6->ip6_dst; + phu.ph.ph_len = htonl(len); + phu.ph.ph_nxt = IPPROTO_ICMPV6; + + sum = 0; + for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) + sum += phu.pa[i]; + + sp = (const u_int16_t *)icp; + + for (i = 0; i < (len & ~1); i += 2) + sum += *sp++; + + if (len & 1) + sum += htons((*(const u_int8_t *)sp) << 8); + + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum = ~sum & 0xffff; + + return (sum); +} + void -icmp6_print(const u_char *bp, const u_char *bp2) +icmp6_print(const u_char *bp, const u_char *bp2, int fragmented) { const struct icmp6_hdr *dp; const struct ip6_hdr *ip; @@ -125,7 +168,20 @@ icmp6_print(const u_char *bp, const u_char *bp2) else /* XXX: jumbo payload case... */ icmp6len = snapend - bp; - TCHECK(dp->icmp6_code); + TCHECK(dp->icmp6_cksum); + + if (vflag && !fragmented) { + int sum = dp->icmp6_cksum; + + if (TTEST2(bp[0], icmp6len)) { + sum = icmp6_cksum(ip, dp, icmp6len); + if (sum != 0) + (void)printf("[bad icmp6 cksum %x!] ", sum); + else + (void)printf("[icmp6 sum ok] "); + } + } + switch (dp->icmp6_type) { case ICMP6_DST_UNREACH: TCHECK(oip->ip6_dst); diff --git a/print-ip6.c b/print-ip6.c index 846071da..9f5777a3 100644 --- a/print-ip6.c +++ b/print-ip6.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.28 2002-12-11 07:14:02 guy Exp $"; + "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.29 2003-05-02 08:13:55 itojun Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -121,7 +121,7 @@ ip6_print(register const u_char *bp, register u_int length) (const u_char *)ip6, fragmented); goto end; case IPPROTO_ICMPV6: - icmp6_print(cp, (const u_char *)ip6); + icmp6_print(cp, (const u_char *)ip6, fragmented); goto end; case IPPROTO_AH: advance = ah_print(cp);