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: