Subject: kern/29282: TCP connections should fail on soft error (ICMP)
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <bp009@terran.org>
List: netbsd-bugs
Date: 02/08/2005 04:37:00
>Number:         29282
>Category:       kern
>Synopsis:       TCP connections should fail on soft error (ICMP)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Feb 08 04:37:00 +0000 2005
>Originator:     Bryan J. Phillippe
>Release:        NetBSD 1.6.2_STABLE
>Organization:
-bp
--
>Environment:
System: NetBSD jupiter 1.6.2_STABLE NetBSD 1.6.2_STABLE (jupiter 20030804) #7: Sat May 15 08:34:21 PDT 2004 bryan@jupiter:/usr/home/bryan/etc/src/NetBSD/1.6/src/sys/arch/alpha/compile/jupiter alpha
Architecture: alpha
Machine: alpha
>Description:
	TCP connection initiation is not aborted by ICMP error, such as
	network unreachable, until after several retransmits.  This means
	lengthy timeouts before the application can retry or take other
	action.  This is especially bad for dual-mode stacks where the
	AAAA record of a hostname is unreachable but the A record is
	reachable.  For example, if you have a private IPv6 network and
	try to connect to any public IPv6-enabled site (e.x.
	www.netbsd.org) with a browser.  It  takes   forever.
	See also the thread on tech-net titled "Usability enhancement for
	IPv6".
>How-To-Repeat:
	Enable IPv6 autohost on a client that is on a private IPv6 network
	with Internet access only via IPv4.  Connect to www.netbsd.org
	or try to use pkgsrc.
>Fix:
	The following patch fixes the problem, though similar changes
	should probably be made for TCPv4 as well.
Index: netinet/tcp_subr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.160.2.5
diff -u -r1.160.2.5 tcp_subr.c
--- netinet/tcp_subr.c	19 Sep 2004 15:38:01 -0000	1.160.2.5
+++ netinet/tcp_subr.c	5 Feb 2005 19:00:24 -0000
@@ -1342,17 +1342,18 @@

 	/*
 	 * Ignore some errors if we are hooked up.
-	 * If connection hasn't completed, has retransmitted several times,
-	 * and receives a second error, give up now.  This is better
-	 * than waiting a long time to establish a connection that
-	 * can never complete.
+	 * If connection hasn't completed, and either gets a "host/net
+	 * unreachable" or has retransmitted several times and receives a
+	 * second error, give up now.  This is better than waiting a long
+	 * time to establish a connection that can never complete.
 	 */
 	if (tp->t_state == TCPS_ESTABLISHED &&
 	     (error == EHOSTUNREACH || error == ENETUNREACH ||
 	      error == EHOSTDOWN)) {
 		return;
 	} else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&
-	    tp->t_rxtshift > 3 && tp->t_softerror)
+	    ((error == EHOSTUNREACH || error == ENETUNREACH) ||
+	     (tp->t_rxtshift > 3 && tp->t_softerror)))
 		so->so_error = error;
 	else
 		tp->t_softerror = error;