Subject: [823] Re: AIX and Linux probs, was: ftp only guest accounts

From: [email-masked] (David C Lawrence)
Date: Fri, 02 Dec 1994 10:33:23 -0500

Back in May I said:

> Harald Milz writes:
> > My Linux box at home is publicly accessible via
> > anonymous UUCP and SLIP. People can log in and FTP some
> > data. From time to time, someone from Russia logs in.
> > As you know, phone lines aren't too good over there so
> > that sometimes the modem connection breaks. However,
> > running IP services remain in the "ESTABLISHED" state
> > (visible via the netstat command). The respective
> > processes are still running, and only after manually
> > killing them, the ESTABLISHED status is replaced by
> > WAIT CLOSE, and off it goes. This leads me to the
> > suspicion that there's no appropriate timeout feature
> > in wu-ftpd. BTW in all cases observed, there was still
> > a certain amount of data in the queue waiting to be
> > transmitted (in the 10 - 20 kB range).
> 
> I see hung sessions a lot on ftp.uu.net too.   There are generally a
> few a day and they are a problem because they keep huge log files open
> after they are rolled and unlinked.  I have not had the time to look
> closely at why they do not time out and exit, but I really wish they
> would.

A week ago I took another look at this and found one of the problems.
The accept() call in ftpd.c:dataconn() was blocking.  My theory about
this is that the server was in passive mode and then asked to use the
data channel, but then the client never connected.  I have patched
this by putting a select() with a five minute timeout before the
accept().

In checking this out, I also noticed that ftpd.c:passive() leaks file
descriptors by not checking if it already has a passive socket open.
It will now close this socket.

This has not completely fixed the problem.  I checked our server to see
how many old ftpds it has on it, and there are far fewer, but still
about a half score in the past week (most attributable to one
site).  It appears they are all hung in a read(), all but one during
STOR.  I have not yet examined the code to see why it might be
happening or how to avoid it.

Unofficial patch to wu-ftpd-2.4:

--- ftpd.c.dist Wed Oct 12 19:55:46 1994
+++ ftpd.c      Fri Nov 25 16:07:39 1994
@@ -48,6 +48,7 @@
 #include <sys/socket.h>
 #include <sys/file.h>
 #include <sys/wait.h>
+#include <sys/time.h>
 
 #ifdef AIX
 #include <sys/id.h>
@@ -1706,7 +1707,24 @@
         struct sockaddr_in from;
         int s,
           fromlen = sizeof(from);
+       fd_set rmask, xmask;
+       struct timeval timeo;
 
+       timeo.tv_sec = 300;     /* five minute timeout */
+       timeo.tv_usec = 0;
+       FD_ZERO(&rmask);
+       FD_ZERO(&xmask);
+       FD_SET(pdata, &rmask);
+       FD_SET(pdata, &xmask);
+       /* make sure a connexion comes, or timeout */
+       s = select(pdata + 1, &rmask, (fd_set *)NULL, &xmask, &timeo);
+        /* error in select, timeout or exception on descriptor */
+       if (s <= 0 || FD_ISSET(pdata, &xmask)) {
+            reply(425, "Failed select for data connection.");
+            (void) close(pdata);
+            pdata = -1;
+            return (NULL);
+       }
         s = accept(pdata, (struct sockaddr *) &from, &fromlen);
         if (s < 0) {
             reply(425, "Can't open data connection.");
@@ -2464,6 +2482,9 @@
     int len;
     register char *p,
      *a;
+
+    if (pdata >= 0)
+      (void)close(pdata);
 
     pdata = socket(AF_INET, SOCK_STREAM, 0);
     if (pdata < 0) {