--- src/ftpd.c.00 Wed Jan 29 12:00:12 2003 +++ src/ftpd.c Wed Jan 29 12:20:53 2003 @@ -4753,6 +4753,7 @@ FILE *file; int retry = 0; int on = 1; + int cval, serrno; #ifdef IPTOS_LOWDELAY int tos; #endif @@ -4873,32 +4874,41 @@ return (NULL); } usedefault = 1; - file = getdatasock(mode); - if (file == NULL) { - reply(425, "Can't create data socket (%s,%d): %s.", - inet_ntoa(data_source.sin_addr), - ntohs(data_source.sin_port), strerror(errno)); - return (NULL); - } - data = fileno(file); - (void) signal(SIGALRM, alarm_signal); - alarm(timeout_connect); - while (connect(data, (struct sockaddr *) &data_dest, - sizeof(data_dest)) < 0) { + do { + file = getdatasock(mode); + if (file == NULL) { + reply(425, "Can't create data socket (%s,%d): %s.", + inet_ntoa(data_source.sin_addr), + ntohs(data_source.sin_port), strerror(errno)); + return (NULL); + } + data = fileno(file); + (void) signal(SIGALRM, alarm_signal); + alarm(timeout_connect); + cval = connect(data, (struct sockaddr *) &data_dest, sizeof(data_dest)); + serrno = errno; alarm(0); - if ((errno == EADDRINUSE || errno == EINTR) && retry < swaitmax) { - sleep((unsigned) swaitint); - retry += swaitint; - (void) signal(SIGALRM, alarm_signal); - alarm(timeout_connect); - continue; + if (cval == -1) { + /* + * When connect fails, the state of the socket is unspecified so + * it should be closed and a new socket created for each connection + * attempt. This also prevents denial of service problems when + * running on operating systems that only allow one non-connected + * socket bound to the same local address. + */ + (void) fclose(file); + data = -1; + errno = serrno; + if ((errno == EADDRINUSE || errno == EINTR) && retry < swaitmax) { + sleep((unsigned) swaitint); + retry += swaitint; + } + else { + perror_reply(425, "Can't build data connection"); + return (NULL); + } } - perror_reply(425, "Can't build data connection"); - (void) fclose(file); - data = -1; - return (NULL); - } - alarm(0); + } while (cval == -1); if (keepalive) (void) setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)); if (TCPwindowsize)