diff options
author | fenner <fenner> | 2002-07-28 04:14:21 +0000 |
---|---|---|
committer | fenner <fenner> | 2002-07-28 04:14:21 +0000 |
commit | a71d112b5c898951be91480f193dce7101727d2d (patch) | |
tree | ce7227eee6c510def89caad6a6c9239011f5c544 | |
parent | dc97370ce2efb3b5841eb6db755ef955a6eba937 (diff) | |
download | tcpdump-a71d112b5c898951be91480f193dce7101727d2d.tar.gz |
Calculate UDP/TCP pseudo-checksum properly in the presence of
source-route options.
-rw-r--r-- | ip.h | 5 | ||||
-rw-r--r-- | print-ip.c | 48 | ||||
-rw-r--r-- | print-tcp.c | 7 | ||||
-rw-r--r-- | print-udp.c | 7 |
4 files changed, 61 insertions, 6 deletions
@@ -1,4 +1,4 @@ -/* @(#) $Header: /tcpdump/master/tcpdump/ip.h,v 1.7 2000-10-03 09:17:40 guy Exp $ (LBL) */ +/* @(#) $Header: /tcpdump/master/tcpdump/ip.h,v 1.8 2002-07-28 04:14:21 fenner Exp $ (LBL) */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. @@ -157,3 +157,6 @@ struct ip_timestamp { #define IPTTLDEC 1 /* subtracted when forwarding */ #define IP_MSS 576 /* default maximum segment size */ + +/* in print-ip.c */ +extern u_int32_t ip_finddst(const struct ip *); @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.109 2002-07-21 20:48:26 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.110 2002-07-28 04:14:21 fenner Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -76,6 +76,52 @@ ip_printroute(const char *type, register const u_char *cp, u_int length) printf("%s}", ptr == len? "#" : ""); } +/* + * If source-routing is present, return the final destination. + * Otherwise, return IP destination. + * + * This is used for UDP and TCP pseudo-header in the checksum + * calculation. + */ +u_int32_t +ip_finddst(const struct ip *ip) +{ + int length; + int len; + const u_char *cp; + uint32_t retval; + + cp = (const u_char *)(ip + 1); + length = (IP_HL(ip) << 2) - sizeof(struct ip); + + for (; length > 0; cp += len, length -= len) { + int tt = *cp; + + if (tt == IPOPT_NOP || tt == IPOPT_EOL) + len = 1; + else { + if (&cp[1] >= snapend) { + return 0; + } + len = cp[1]; + } + if (len <= 0) { + return 0; + } + if (&cp[1] >= snapend || cp + len > snapend) { + return 0; + } + switch (tt) { + + case IPOPT_SSRR: + case IPOPT_LSRR: + memcpy(&retval, cp + len - 4, 4); + return retval; + } + } + return ip->ip_dst.s_addr; +} + static void ip_printts(register const u_char *cp, u_int length) { diff --git a/print-tcp.c b/print-tcp.c index 1f57dfcf..0d924dea 100644 --- a/print-tcp.c +++ b/print-tcp.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.96 2002-07-21 20:56:24 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.97 2002-07-28 04:14:22 fenner Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -122,7 +122,10 @@ static int tcp_cksum(register const struct ip *ip, phu.ph.mbz = 0; phu.ph.proto = IPPROTO_TCP; memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); - memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); + if (IP_HL(ip) == 5) + memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); + else + phu.ph.dst = ip_finddst(ip); sp = &phu.pa[0]; return in_cksum((u_short *)tp, len, diff --git a/print-udp.c b/print-udp.c index c27989f6..f8b6a070 100644 --- a/print-udp.c +++ b/print-udp.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.104 2002-06-11 17:08:58 itojun Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.105 2002-07-28 04:14:22 fenner Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -305,7 +305,10 @@ static int udp_cksum(register const struct ip *ip, phu.ph.mbz = 0; phu.ph.proto = IPPROTO_UDP; memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); - memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); + if (IP_HL(ip) == 5) + memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); + else + phu.ph.dst = ip_finddst(ip); sp = &phu.pa[0]; return in_cksum((u_short *)up, len, |