components/proftpd/patches/proftpd-retry.patch
author Tomas Klacko <tomas.klacko@oracle.com>
Mon, 19 Aug 2013 21:48:06 +0200
branchs11u1-sru
changeset 2734 d23b6301c400
parent 554 0ed48135019d
child 1952 edbaa9c65514
permissions -rw-r--r--
16191277 problem in SERVICE/FTP-SERVER 16761173 proftpd in inetd mode, randomly fails to accept connections

--- a/src/data.c
+++ b/src/data.c
@@ -333,6 +333,7 @@ static int data_pasv_open(char *reason, off_t size) {
 static int data_active_open(char *reason, off_t size) {
   conn_t *c;
   int rev;
+  int retries = 0;
   pr_netaddr_t *bind_addr;
 
   if (!reason && session.xfer.filename)
@@ -348,45 +349,55 @@ static int data_active_open(char *reason, off_t size) {
     bind_addr = pr_netaddr_v6tov4(session.xfer.p, session.c->local_addr);
   }
 
-  session.d = pr_inet_create_conn(session.pool, -1, bind_addr,
-    session.c->local_port-1, TRUE);
+  for (;;) {
+    session.d = pr_inet_create_conn(session.pool, -1, bind_addr,
+      session.c->local_port-1, TRUE);
 
-  /* Set the "stalled" timer, if any, to prevent the connection
-   * open from taking too long
-   */
-  if (timeout_stalled) {
-    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
-      "TimeoutStalled");
-  }
+    /* Set the "stalled" timer, if any, to prevent the connection
+     * open from taking too long
+     */
+    if (timeout_stalled) {
+      pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
+        "TimeoutStalled");
+    }
 
-  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
+    rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
 
-  /* Protocol and socket options should be set before handshaking. */
+    /* Protocol and socket options should be set before handshaking. */
 
-  if (session.xfer.direction == PR_NETIO_IO_RD) {
-    pr_inet_set_socket_opts(session.d->pool, session.d,
-      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
+    if (session.xfer.direction == PR_NETIO_IO_RD) {
+      pr_inet_set_socket_opts(session.d->pool, session.d,
+        (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
     
-  } else {
-    pr_inet_set_socket_opts(session.d->pool, session.d,
-      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
-  }
+    } else {
+      pr_inet_set_socket_opts(session.d->pool, session.d,
+        0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
+    }
 
-  /* Make sure that the necessary socket options are set on the socket prior
-   * to the call to connect(2).
-   */
-  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
-    IPTOS_THROUGHPUT, 1);
-  pr_inet_generate_socket_event("core.data-connect", main_server,
-    session.d->local_addr, session.d->listen_fd);
+    /* Make sure that the necessary socket options are set on the socket prior
+     * to the call to connect(2).
+     */
+    pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
+      IPTOS_THROUGHPUT, 1);
+    pr_inet_generate_socket_event("core.data-connect", main_server,
+      session.d->local_addr, session.d->listen_fd);
 
-  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
+    if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
       session.data_port) == -1) {
-    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
-      strerror(session.d->xerrno));
-    destroy_pool(session.d->pool);
-    session.d = NULL;
-    return -1;
+      if (session.d->xerrno == EADDRINUSE && retries < 16) {
+        destroy_pool(session.d->pool);
+        pr_signals_handle();
+        /* Wait up to MSL to avoid TIME_WAIT. */
+        sleep(retries++);
+        continue;
+      }
+      pr_response_add_err(R_425, _("Unable to build data connection: %s"),
+        strerror(session.d->xerrno));
+      destroy_pool(session.d->pool);
+      session.d = NULL;
+      return -1;
+    } else
+      break;
   }
 
   c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,