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