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;