6411N/ASource: In-House
6411N/AReason: Solaris leave socket in TIME_WAIT status
6411N/AReasonable to upstream?: Not much for Linux.
6411N/A
6411N/ANote: This patch do not look "pretty" but its code
6411N/Ais re-used from the original patch which colided
6411N/Awith the proftpd-1.3.6 code. During proftpd update
6411N/Athe binaries were tested on huge # of small files
6411N/A(!passive) it looked good so the original patch was
6411N/Aremoved.
6411N/ANow it has returned as regression from supercluster
6411N/Atesting.
6411N/AFinal fix of this problem on Solaris will need further
6411N/Adiscussion with community then it will be probably fixed
6411N/Aby a proftpd update.
6411N/A
6411N/A--- a//src/data.c 2016-03-10 17:04:32.000000000 -0800
6411N/A+++ b/src/data.c 2016-06-23 05:41:37.547107933 -0700
6411N/A@@ -337,6 +337,7 @@
6411N/A static int data_active_open(char *reason, off_t size) {
6411N/A conn_t *c;
6411N/A int bind_port, rev;
6411N/A+ int retries = 0;
6411N/A pr_netaddr_t *bind_addr;
6411N/A unsigned char *root_revoke = NULL;
6411N/A
6411N/A@@ -384,6 +385,7 @@
6411N/A }
6411N/A }
6411N/A
6411N/A+ for(;;) { /* begin of endless loop */
6411N/A session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);
6411N/A if (session.d == NULL) {
6411N/A int xerrno = errno;
6411N/A@@ -425,7 +427,7 @@
6411N/A pr_inet_set_socket_opts(session.d->pool, session.d,
6411N/A (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
6411N/A main_server->tcp_keepalive);
6411N/A-
6411N/A+
6411N/A } else {
6411N/A pr_inet_set_socket_opts(session.d->pool, session.d,
6411N/A 0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
6411N/A@@ -442,6 +444,13 @@
6411N/A
6411N/A if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
6411N/A session.data_port) == -1) {
6411N/A+ if (session.d->xerrno == EADDRINUSE && retries < 16) {
6411N/A+ destroy_pool(session.d->pool);
6411N/A+ pr_signals_handle();
6411N/A+ /* Wait up to MSL to avoid TIME_WAIT. */
6411N/A+ sleep(retries++);
6411N/A+ continue; /* continue in endless loop */
6411N/A+ }
6411N/A pr_log_debug(DEBUG6,
6411N/A "Error connecting to %s#%u for active data transfer: %s",
6411N/A pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
6411N/A@@ -453,7 +462,8 @@
6411N/A destroy_pool(session.d->pool);
6411N/A session.d = NULL;
6411N/A return -1;
6411N/A- }
6411N/A+ } else break; /* finish the endless loop */
6411N/A+ } /* end of endless loop */
6411N/A
6411N/A c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
6411N/A session.d->listen_fd, -1, -1, TRUE);