kern/50839: icmp time-exceeded causes tcp connect to return success
bogusly
Barney Wolff
barney at pit.databus.com
Fri Apr 11 15:40:07 PDT 2003
>Number: 50839
>Category: kern
>Synopsis: icmp time-exceeded causes tcp connect to return success bogusly
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Apr 11 15:40:05 PDT 2003
>Closed-Date:
>Last-Modified:
>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 at 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 at 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 at 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:
>Unformatted:
More information about the freebsd-bugs
mailing list