From barney@pit.databus.com  Fri Apr 11 15:34:53 2003
Return-Path: <barney@pit.databus.com>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 9480137B401
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 11 Apr 2003 15:34:53 -0700 (PDT)
Received: from pit.databus.com (p70-227.acedsl.com [66.114.70.227])
	by mx1.FreeBSD.org (Postfix) with ESMTP id AD9D943FA3
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 11 Apr 2003 15:34:52 -0700 (PDT)
	(envelope-from barney@pit.databus.com)
Received: from pit.databus.com (localhost [127.0.0.1])
	by pit.databus.com (8.12.9/8.12.9) with ESMTP id h3BMYqdN050169
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 11 Apr 2003 18:34:52 -0400 (EDT)
	(envelope-from barney@pit.databus.com)
Received: (from barney@localhost)
	by pit.databus.com (8.12.9/8.12.9/Submit) id h3BMYqjv050168;
	Fri, 11 Apr 2003 18:34:52 -0400 (EDT)
Message-Id: <200304112234.h3BMYqjv050168@pit.databus.com>
Date: Fri, 11 Apr 2003 18:34:52 -0400 (EDT)
From: Barney Wolff <barney@pit.databus.com>
Reply-To: Barney Wolff <barney@pit.databus.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: icmp time-exceeded causes tcp connect to return success bogusly
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         50839
>Category:       kern
>Synopsis:       icmp time-exceeded causes tcp connect to return success bogusly
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    silby
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Apr 11 15:40:05 PDT 2003
>Closed-Date:    Tue Jun 24 19:45:00 PDT 2003
>Last-Modified:  Tue Jun 24 19:45:00 PDT 2003
>Originator:     Barney Wolff
>Release:        FreeBSD 4.8-STABLE i386
>Organization:
Databus Inc.
>Environment:
System: FreeBSD pit.databus.com 4.8-STABLE FreeBSD 4.8-STABLE #0: Wed Apr 9 15:22:45 EDT 2003 toor@pit.databus.com:/usr/obj/usr/src/sys/PIT i386
and
FreeBSD lab.databus.com 5.0-CURRENT FreeBSD 5.0-CURRENT #1: Fri Apr 11 18:00:56
EDT 2003     toor@lab.databus.com:/usr/obj/usr/src/sys/LAB  i386
>Description:
	TCP connect(2) returns 0 if a routing loop causes an ICMP unreach-time-
	exceeded to be returned.  Problem is that the cmd code is mapped to
	error 0 in in_input.
>How-To-Repeat:
	Set up routing loop (I just added a /32 bogus route on my internal net
	to do this).  Connect to looped destination.  Connect returns 0, but
	socket is of course not writable.  Test prog attached.  This fails on
	both stable and current.
>Fix:
b:/usr/src/sys/netinet $ diff -u ip_input.c.orig ip_input.c
--- ip_input.c.orig     Wed Apr  9 14:07:16 2003
+++ ip_input.c  Fri Apr 11 17:54:11 2003
@@ -1696,7 +1696,7 @@
        0,              EMSGSIZE,       EHOSTDOWN,      EHOSTUNREACH,
        EHOSTUNREACH,   EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
        EMSGSIZE,       EHOSTUNREACH,   0,              0,
-       0,              0,              0,              0,
+       0,              0,              EHOSTUNREACH,   0,
        ENOPROTOOPT,    ECONNREFUSED
 };
  
(This patch is to current.)


Here's the test prog:

/*	conntime.c	Barney Wolff	<barney@databus.com>	*/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/errno.h>
extern int errno;
#include <sys/time.h>

#ifdef __FreeBSD__
#define sigignore(x) signal(x,SIG_IGN)
#endif

main(int argc,char **argv) {
	int sockfd,lsockfd,i,recv=0,cookie=0,dofork=0;
	struct sockaddr_in skinaddr;
	struct timeval start,end;

	if (argc < 3) {
		fprintf(stderr,"%0 ipaddr port\n");
		exit(1);
	}

	sigignore(SIGPIPE);

	memset(&skinaddr,0,sizeof(skinaddr));
	skinaddr.sin_family = AF_INET;
	skinaddr.sin_addr.s_addr = inet_addr(argv[1]);
	skinaddr.sin_port = htons((short)atoi(argv[2]));

	if ((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0)
		{perror("socket"); exit(2);}

	i = 1;
	setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,&i,sizeof(i));

	gettimeofday(&start,NULL);
	i = connect(sockfd,(struct sockaddr *)&skinaddr,sizeof(skinaddr));
	gettimeofday(&end,NULL);

	if (i < 0) perror("connection failed");
	fprintf(stderr,"connect returned in %d usec\n",
		1000000*(end.tv_sec-start.tv_sec)+end.tv_usec-start.tv_usec);
	if (i == 0) {
		start = end;
		i = write(sockfd,"GET /\r\n\r\n",9);
		gettimeofday(&end,NULL);
		if (i < 0) perror("write failed");
		fprintf(stderr,"write returned in %d usec\n",
			1000000*(end.tv_sec-start.tv_sec)+end.tv_usec-start.tv_usec);
	}
}
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->silby 
Responsible-Changed-By: silby 
Responsible-Changed-When: Thu May 22 22:51:29 PDT 2003 
Responsible-Changed-Why:  
Barney reminded me to take this 

http://www.freebsd.org/cgi/query-pr.cgi?pr=50839 
State-Changed-From-To: open->closed 
State-Changed-By: silby 
State-Changed-When: Tue Jun 24 19:44:47 PDT 2003 
State-Changed-Why:  
Committed to both -current and -stable. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=50839 
>Unformatted:
