Subject: bin/4038: traceroute should know ICMP Unreach code 13
To: None <gnats-bugs@gnats.netbsd.org>
From: Havard Eidnes <he@vader.runit.sintef.no>
List: netbsd-bugs
Date: 08/26/1997 13:33:55
>Number:         4038
>Category:       bin
>Synopsis:       traceroute should know ICMP Unreach code 13
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Tue Aug 26 04:35:01 1997
>Last-Modified:
>Originator:     Havard Eidnes
>Organization:
	SINTEF RUNIT
>Release:        NetBSD-current as of 1997-08-26
>Environment:
System: NetBSD vader.runit.sintef.no 1.2G NetBSD 1.2G (VADER) #5: Wed Aug 20 19:47:38 MEST 1997 he@vader.runit.sintef.no:/usr/src/sys/arch/i386/compile/VADER i386


>Description:
	traceroute in NetBSD-current doesn't know how to handle
	"ICMP Unreachable, communication administratively prohibited",
	as defined in RFC 1716.  As a result, if you hit one of these,
	traceroute just gets the ICMPs from the filtering router and
	does not stop the traceroute at that point.

>How-To-Repeat:
	traceroute www.belnet.be

>Fix:
	The attached code was loosely adapted from the FreeBSD 2.2.2 version.
	Most routers rate-limit ICMP Unreach messages, the test to terminate
	below works for the default of 3 probes, but probably won't for 5
	probes.

	Remaining problem: The ICMP codes should be documented in the man page.

*** traceroute.c.old	Sun Apr 13 16:07:05 1997
--- traceroute.c	Tue Aug 26 13:26:47 1997
***************
*** 518,521 ****
--- 518,523 ----
  						Printf(" (ttl = %d)",
  						    ip->ip_ttl);
+ 					if (i == -1)
+ 						break;
  					switch(i - 1) {
  					case ICMP_UNREACH_PORT:
***************
*** 547,550 ****
--- 549,564 ----
  						Printf(" !S");
  						break;
+ /* rfc 1716 */
+ #ifndef ICMP_UNREACH_ADMIN_PROHIBIT
+ #define ICMP_UNREACH_ADMIN_PROHIBIT 13
+ #endif
+ 					case ICMP_UNREACH_ADMIN_PROHIBIT:
+ 						++unreachable;
+ 						Printf(" !A");
+ 						break;
+ 					default:
+ 						++unreachable;
+ 						printf(" !<%d>", i-1);
+ 						break;
  					}
  					break;
***************
*** 556,560 ****
  		}
  		putchar('\n');
! 		if (got_there || unreachable >= nprobes)
  			exit(0);
  	}
--- 570,575 ----
  		}
  		putchar('\n');
! 		if (got_there || 
! 			(unreachable > 0 && unreachable >= nprobes-1))
  			exit(0);
  	}
>Audit-Trail:
>Unformatted: