summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfenner <fenner>2002-07-28 04:14:21 +0000
committerfenner <fenner>2002-07-28 04:14:21 +0000
commita71d112b5c898951be91480f193dce7101727d2d (patch)
treece7227eee6c510def89caad6a6c9239011f5c544
parentdc97370ce2efb3b5841eb6db755ef955a6eba937 (diff)
downloadtcpdump-a71d112b5c898951be91480f193dce7101727d2d.tar.gz
Calculate UDP/TCP pseudo-checksum properly in the presence of
source-route options.
-rw-r--r--ip.h5
-rw-r--r--print-ip.c48
-rw-r--r--print-tcp.c7
-rw-r--r--print-udp.c7
4 files changed, 61 insertions, 6 deletions
diff --git a/ip.h b/ip.h
index 5b7e449c..dd8bad60 100644
--- a/ip.h
+++ b/ip.h
@@ -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 *);
diff --git a/print-ip.c b/print-ip.c
index d8eda70a..0ab20d3b 100644
--- a/print-ip.c
+++ b/print-ip.c
@@ -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,