--- 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)