--- Quoting Camiel Dobbelaar on 2008/04/02 at 17:32 +0200: > Michael Hoffrath wrote: > > Same problem here Running OpenBSD 4.2 (GENERIC) #375 i386. > > > > It seems not only being a problem of Microsoft, I've found that problem also > > on VSFTPd (centos) and Filezilla (Windows 2003 Server). > > > > Both are sending "221 Goodbye" but ftp-proxy seems to swallow that from time > > to time. > > It sounds like a race condition, where the server FIN reaches the proxy > before the final data is sent out to the client. I'd have to dig into > it a bit more.
That's exactly what I saw when I broke out the sniffer to troubleshoot this. > Does it cause a real problem? (in other words: how urgent is the fix?) Unfortunately there seems to be a lot of shitty software out there that waits explicitly for the 221 response even though the TCP socket that that response is supposed to come in on has been closed. This is the patch that I've been running in production for some weeks. The firewall where I'm running this proxies outgoing ftp connections and also sits in front of an FTP server so I have two instances of ftp-proxy running. The patch fixes the 221 issue however I recently started getting reports of users being unable to ftp outbound. Seems the patch is causing ftp-proxy to crash at random (but only the instance that proxies the outgoing connections). I haven't had time to debug that yet. .joel Index: ftp-proxy.c =================================================================== RCS file: /cvs/src/usr.sbin/ftp-proxy/ftp-proxy.c,v retrieving revision 1.13 diff -p -u -r1.13 ftp-proxy.c --- ftp-proxy.c 30 Dec 2006 13:24:00 -0000 1.13 +++ ftp-proxy.c 8 Mar 2008 00:56:38 -0000 @@ -79,6 +79,8 @@ struct session { int cmd; u_int16_t port; u_int16_t proxy_port; + u_int8_t client_closed; + u_int8_t server_closed; LIST_ENTRY(session) entry; }; @@ -91,6 +93,8 @@ int client_parse_cmd(struct session *s); void client_read(struct bufferevent *, void *); int drop_privs(void); void end_session(struct session *); +void end_session_client(struct session *); +void end_session_server(struct session *); int exit_daemon(void); int getline(char *, size_t *); void handle_connection(const int, short, void *); @@ -134,7 +138,7 @@ client_error(struct bufferevent *bufev, else logmsg(LOG_ERR, "#%d abnormal client error: %d", s->id, what); - end_session(s); + end_session_client(s); } int @@ -270,15 +274,18 @@ end_session(struct session *s) logmsg(LOG_INFO, "#%d ending session", s->id); - if (s->client_fd != -1) - close(s->client_fd); - if (s->server_fd != -1) - close(s->server_fd); - - if (s->client_bufev) - bufferevent_free(s->client_bufev); - if (s->server_bufev) - bufferevent_free(s->server_bufev); + if (!s->client_closed) { + if (s->client_fd != -1) + close(s->client_fd); + if (s->client_bufev) + bufferevent_free(s->client_bufev); + } + if (!s->server_closed) { + if (s->server_fd != -1) + close(s->server_fd); + if (s->server_bufev) + bufferevent_free(s->server_bufev); + } /* Remove rulesets by commiting empty ones. */ err = 0; @@ -297,6 +304,42 @@ end_session(struct session *s) session_count--; } +void +end_session_client(struct session *s) +{ + logmsg(LOG_INFO, "#%d ending client session", s->id); + + if (s->client_fd != -1) + close(s->client_fd); + + if (s->client_bufev) + bufferevent_free(s->client_bufev); + + s->client_closed++; + + /* server connection is already closed, shut everything down */ + if (s->server_closed) + end_session(s); +} + +void +end_session_server(struct session *s) +{ + logmsg(LOG_INFO, "#%d ending server session", s->id); + + if (s->server_fd != -1) + close(s->server_fd); + + if (s->server_bufev) + bufferevent_free(s->server_bufev); + + s->server_closed++; + + /* client connection is already closed, shut everything down */ + if (s->client_closed) + end_session(s); +} + int exit_daemon(void) { @@ -882,7 +925,7 @@ server_error(struct bufferevent *bufev, else logmsg(LOG_ERR, "#%d abnormal server error: %d", s->id, what); - end_session(s); + end_session_server(s); } int