Subject: bin/2701: traceroute may never time out
To: None <gnats-bugs@NetBSD.ORG>
From: Havard Eidnes <>
List: netbsd-bugs
Date: 08/16/1996 14:10:34
>Number:         2701
>Category:       bin
>Synopsis:       traceroute may never time out
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Aug 16 08:35:02 1996
>Originator:     Havard Eidnes
>Release:        1.1
	i386, NetBSD 1.1
System: NetBSD 1.1 NetBSD 1.1 (VADER) #1: Mon Jan 15 20:46:37 MET 1996 i386

	Since a raw IP socket will receive all ICMP messages addressed
	to a host, traceroute may never time out and proceed if a probe
	packet or a response to a probe packet is lost and there is other
	ICMP traffic to the host running traceroute.

	Verbose print of packets returns bogus data because inet_ntoa()
	returns it's value in a static area, and it's used twice in a
	call to Printf().

	Start a continous ping to any other host.  Run traceroute over
	a path where some packet loss can be expected.  Observe traceroute
	hanging when there is a packet loss.

	Turn on -v and see that the source and dest are the same in the
	extra ICMP packets captured and displayed.
	The termination condition in traceroute for giving a timeout is too
	simplistic, work around this.

	The offending Printf() needs to be split in two.

*** traceroute.c	1996/08/13 14:11:27	1.1
--- traceroute.c	1996/08/16 11:57:03
*** 494,497 ****
--- 494,506 ----
  			while (cc = wait_for_reply(s, &from)) {
  				(void) gettimeofday(&t2, &tz);
+ 				/* Since we'll be receiving all ICMP
+ 				   messages to this host above, we may
+ 				   never end up with cc=0, so we need
+ 				   an additional termination check. */
+ 				if (t2.tv_sec - t1.tv_sec > waittime) {
+ 				        Printf(" *");
+ 					(void) fflush(stdout);
+ 					break;
+ 				}
  				if ((i = packet_ok(packet, cc, &from, seq))) {
  					if (from.sin_addr.s_addr != lastaddr) {
*** 697,702 ****
  		u_long *lp = (u_long *)&icp->icmp_ip;
! 		Printf("\n%d bytes from %s to %s", cc,
! 			inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
  		Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
--- 706,711 ----
  		u_long *lp = (u_long *)&icp->icmp_ip;
! 		Printf("\n%d bytes from %s ", cc, inet_ntoa(from->sin_addr)); 
! 		Printf("to %s", inet_ntoa(ip->ip_dst));
  		Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),