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>
index | next in thread | raw e-mail
>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:
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711150632.WAA23109>
