# # This is the patch, which seems to appear and disappear with # every upgrade of proftpd. It first disappeared with # integration of CR 23124279 [1] (ProFTPd: Update to 1.3.5b). # The upgrade removed the earlier fix for 15744390 [2]. # This omission got fixed by CR 23536514, which re-adds the patch. # # The history repeats with upgrade to 1.3.6 [4], which is going # to be fixed by current CR [5]. This time I've submitted also # a pull request [6], so we will know for sure whether the change # also got accepted by upstream or not. # # For 1.3.6 we also must increase number of connect(2) attempts # in case of connect(2) fails with EADDRINUSE # # [1] https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=23124279 # [2] https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=15744390 # [3] https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=23536514 # [4] https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=27889131 # [5] https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=30009346 # [6] https://github.com/proftpd/proftpd/pull/812 # [7] https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=30216085 # diff --git a/src/data.c b/src/data.c index 05b3a34d8..5b3f923a1 100644 --- a/src/data.c +++ b/src/data.c @@ -213,6 +213,7 @@ static int data_passive_open(const char *reason, off_t size) { static int data_active_open(const char *reason, off_t size) { conn_t *c; int bind_port, rev; + int retries = 0; const pr_netaddr_t *bind_addr = NULL; unsigned char *root_revoke = NULL; @@ -268,6 +269,7 @@ static int data_active_open(const char *reason, off_t size) { } } + for(;;) { /* begin of endless loop */ session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE); if (session.d == NULL) { int xerrno = errno; @@ -309,7 +311,7 @@ static int data_active_open(const char *reason, off_t size) { pr_inet_set_socket_opts(session.d->pool, session.d, (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0, main_server->tcp_keepalive); - + } else { pr_inet_set_socket_opts(session.d->pool, session.d, 0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0), @@ -328,6 +330,13 @@ static int data_active_open(const char *reason, off_t size) { session.data_port) < 0) { int xerrno = session.d->xerrno; + if (xerrno == EADDRINUSE && retries < 42) { + destroy_pool(session.d->pool); + pr_signals_handle(); + /* Wait up to MSL to avoid TIME_WAIT. */ + sleep(retries++); + continue; /* continue in endless loop */ + } pr_log_debug(DEBUG6, "Error connecting to %s#%u for active data transfer: %s", pr_netaddr_get_ipstr(&session.data_addr), session.data_port, @@ -340,7 +349,8 @@ static int data_active_open(const char *reason, off_t size) { errno = xerrno; return -1; - } + } else break; /* finish the endless loop */ + } /* end of endless loop */ c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA, session.d->listen_fd, -1, -1, TRUE);