Subject: bin/13651: traceroute -g makes udp packets with invalid cksum
To: None <gnats-bugs@gnats.netbsd.org>
From: None <yamt@netbsd.org>
List: netbsd-bugs
Date: 08/08/2001 14:42:12
>Number: 13651
>Category: bin
>Synopsis: traceroute -g makes udp packets with invalid cksum
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Aug 07 22:40:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: YAMAMOTO Takashi
>Release: current 2001/08/07
>Organization:
>Environment:
System: NetBSD capybara 1.5X NetBSD 1.5X (stg) #307: Tue Aug 7 16:07:45 JST 2001 takashi@capybara:/usr/src/sys/arch/i386/compile/stg i386
Architecture: i386
Machine: i386
>Description:
traceroute mistakenly includes ip-options to calculate cksum.
>How-To-Repeat:
traceroute -g somewhere somewhere
>Fix:
Index: traceroute.c
===================================================================
RCS file: /cvs/cvsroot/basesrc/usr.sbin/traceroute/traceroute.c,v
retrieving revision 1.42
diff -u -r1.42 traceroute.c
--- traceroute.c 2001/01/12 18:53:21 1.42
+++ traceroute.c 2001/08/08 05:29:48
@@ -353,6 +353,7 @@
void getaddr(u_int32_t *, char *);
struct hostinfo *gethostinfo(char *);
u_short in_cksum(u_short *, int);
+u_short in_cksum2(u_short, u_short *, int);
char *inetname(struct in_addr);
int main(int, char **);
int packet_ok(u_char *, int, struct sockaddr_in *, int);
@@ -1113,6 +1114,7 @@
if (outicmp->icmp_cksum == 0)
outicmp->icmp_cksum = 0xffff;
} else {
+ u_short sum;
/* Checksum (must save and restore ip header) */
tip = *outip;
ui = (struct udpiphdr *)outip;
@@ -1125,7 +1127,9 @@
#endif
ui->ui_len = outudp->uh_ulen;
outudp->uh_sum = 0;
- outudp->uh_sum = in_cksum((u_short *)ui, packlen);
+ sum = in_cksum2(0, (u_short *)ui, sizeof(*outip));
+ sum = in_cksum2(sum, (u_short *)outudp, ntohs(outudp->uh_ulen));
+ outudp->uh_sum = ~sum;
if (outudp->uh_sum == 0)
outudp->uh_sum = 0xffff;
*outip = tip;
@@ -1349,16 +1353,23 @@
Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
}
+u_short
+in_cksum(u_short *addr, int len)
+{
+
+ return ~in_cksum2(0, addr, len);
+}
+
/*
* Checksum routine for Internet Protocol family headers (C Version)
*/
u_short
-in_cksum(register u_short *addr, register int len)
+in_cksum2(u_short seed, register u_short *addr, register int len)
{
register int nleft = len;
register u_short *w = addr;
register u_short answer;
- register int sum = 0;
+ register int sum = seed;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum),
@@ -1380,7 +1391,7 @@
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
- answer = ~sum; /* truncate to 16 bits */
+ answer = sum; /* truncate to 16 bits */
return (answer);
}
>Release-Note:
>Audit-Trail:
>Unformatted: