Date: Fri, 14 Nov 1997 22:32:50 -0800 (PST) From: Matthew Dillon <dillon@backplane.com> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: kern/5048: if shutdown(fd,1) called twice on socket, pending input data is lost Message-ID: <199711150632.WAA23109@apollo.backplane.com> Resent-Message-ID: <199711150640.WAA03760@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 5048 >Category: kern >Synopsis: Calling shutdown(fd,1) multiple times will blow up input data >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Nov 14 22:40:00 PST 1997 >Last-Modified: >Originator: Matthew Dillon >Organization: Best Internet Communications >Release: FreeBSD 2.2-STABLE i386 >Environment: FreeBSD 2.2.5 >Description: If you call shutdown(socket, 1) twice, pending input data on the socket may be lost. >How-To-Repeat: Open a TCP connection to some destination that sends you data (e.g. chargen), then call shutdown on the socket multiple times, the chargen will eventually stall. /* * TESTSHUTDOWN localhost chargen */ #include <sys/types.h> #include <sys/socket.h> #include <sys/file.h> #include <sys/time.h> #include <netinet/in.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <setjmp.h> #include <ctype.h> #include <netdb.h> void goforit(int fd); int main(int ac, char **av) { int fd; int i; struct sockaddr_in sin; struct hostent *host; struct servent *serv; char *hostName = NULL; char *servName = NULL; for (i = 1; i < ac; ++i) { char *ptr = av[i]; if (*ptr != '-') { if (hostName == NULL) hostName = ptr; else servName = ptr; continue; } ptr += 2; switch(ptr[-1]) { case 'b': default: printf("bad option: %s\n", ptr - 2); exit(0); } } if (hostName == NULL) { puts("no hostname / ip address specified"); exit(0); } if (servName == NULL) { puts("no portname / port number specified"); exit(0); } bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) > 0) { if ((host = gethostbyname(hostName)) != NULL) { sin.sin_family = host->h_addrtype; bcopy(host->h_addr, &sin.sin_addr, host->h_length); } else { sin.sin_addr.s_addr = inet_addr(hostName); } if ((serv = getservbyname(servName, "tcp")) != NULL) { sin.sin_port = serv->s_port; } else { sin.sin_port = htons(strtol(servName, NULL, 0)); } if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == 0) { puts("connected"); goforit(fd); close(fd); } else { perror("connect"); } } return(0); } void goforit(int fd) { int pid; int n; char buf[256]; if ((pid = fork()) == 0) { int ttl = 0; while ((n = read(fd, buf, sizeof(buf))) > 0) { write(1, buf, n); ttl += n; if (ttl > 1024) { printf("\n****** (CALLING SHUTDOWN) *******\n"); shutdown(fd, 1); shutdown(fd, 1); ttl = 0; } } exit(0); } while ((n = read(0, buf, sizeof(buf))) > 0) { int i = 0; int r; while (i < n && (r = write(fd, buf + i, n - i)) > 0) { i += r; } } shutdown(fd, 1); while (wait(NULL) != pid) ; } >Fix: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711150632.WAA23109>