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. Fix: b:/usr/src/sys/netinet $ diff -u ip_input.c.orig ip_input.c 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); } }--xhbVGMPOMUOgAjfUvNekJ1eCoXTRrrX5n9EaPLwAq2SxdYNr Content-Type: text/plain; name="file.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="file.diff" --- 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.) 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.
Responsible Changed From-To: freebsd-bugs->silby Barney reminded me to take this
State Changed From-To: open->closed Committed to both -current and -stable.