1 --- a/src/data.c |
1 --- a/src/data.c |
2 +++ b/src/data.c |
2 +++ b/src/data.c |
3 @@ -333,6 +333,7 @@ static int data_pasv_open(char *reason, off_t size) { |
3 @@ -337,6 +337,7 @@ static int data_pasv_open(char *reason, off_t size) { |
4 static int data_active_open(char *reason, off_t size) { |
4 static int data_active_open(char *reason, off_t size) { |
5 conn_t *c; |
5 conn_t *c; |
6 int rev; |
6 int bind_port, rev; |
7 + int retries = 0; |
7 + int retries = 0; |
8 pr_netaddr_t *bind_addr; |
8 pr_netaddr_t *bind_addr; |
|
9 unsigned char *root_revoke = NULL; |
9 |
10 |
10 if (!reason && session.xfer.filename) |
11 @@ -368,7 +369,9 @@ static int data_active_open(char *reason, off_t size) { |
11 @@ -348,45 +349,55 @@ static int data_active_open(char *reason, off_t size) { |
12 bind_port = INPORT_ANY; |
12 bind_addr = pr_netaddr_v6tov4(session.xfer.p, session.c->local_addr); |
|
13 } |
13 } |
14 |
14 |
15 - session.d = pr_inet_create_conn(session.pool, -1, bind_addr, |
15 - session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE); |
16 - session.c->local_port-1, TRUE); |
|
17 + for (;;) { |
16 + for (;;) { |
18 + session.d = pr_inet_create_conn(session.pool, -1, bind_addr, |
17 + session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, |
19 + session.c->local_port-1, TRUE); |
18 + TRUE); |
20 |
19 |
21 - /* Set the "stalled" timer, if any, to prevent the connection |
20 /* Default remote address to which to connect for an active transfer, |
22 - * open from taking too long |
21 * if the client has not specified a different address via PORT/EPRT, |
23 - */ |
22 @@ -416,6 +419,15 @@ static int data_active_open(char *reason, off_t size) { |
24 - if (timeout_stalled) { |
23 |
25 - pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb, |
24 if (pr_inet_connect(session.d->pool, session.d, &session.data_addr, |
26 - "TimeoutStalled"); |
25 session.data_port) == -1) { |
27 - } |
26 + |
28 + /* Set the "stalled" timer, if any, to prevent the connection |
27 + if (session.d->xerrno == EADDRINUSE && retries < 16) { |
29 + * open from taking too long |
28 + destroy_pool(session.d->pool); |
30 + */ |
29 + pr_signals_handle(); |
31 + if (timeout_stalled) { |
30 + /* Wait up to MSL to avoid TIME_WAIT. */ |
32 + pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb, |
31 + sleep(retries++); |
33 + "TimeoutStalled"); |
32 + continue; |
34 + } |
33 + } |
35 |
34 + |
36 - rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS); |
35 pr_log_debug(DEBUG6, |
37 + rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS); |
36 "Error connecting to %s#%u for active data transfer: %s", |
38 |
37 pr_netaddr_get_ipstr(&session.data_addr), session.data_port, |
39 - /* Protocol and socket options should be set before handshaking. */ |
38 @@ -427,6 +439,9 @@ static int data_active_open(char *reason, off_t size) { |
40 + /* Protocol and socket options should be set before handshaking. */ |
39 destroy_pool(session.d->pool); |
41 |
40 session.d = NULL; |
42 - if (session.xfer.direction == PR_NETIO_IO_RD) { |
41 return -1; |
43 - pr_inet_set_socket_opts(session.d->pool, session.d, |
42 + } else |
44 - (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0); |
43 + break; |
45 + if (session.xfer.direction == PR_NETIO_IO_RD) { |
44 + |
46 + pr_inet_set_socket_opts(session.d->pool, session.d, |
|
47 + (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0); |
|
48 |
|
49 - } else { |
|
50 - pr_inet_set_socket_opts(session.d->pool, session.d, |
|
51 - 0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0)); |
|
52 - } |
|
53 + } else { |
|
54 + pr_inet_set_socket_opts(session.d->pool, session.d, |
|
55 + 0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0)); |
|
56 + } |
|
57 |
|
58 - /* Make sure that the necessary socket options are set on the socket prior |
|
59 - * to the call to connect(2). |
|
60 - */ |
|
61 - pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0, |
|
62 - IPTOS_THROUGHPUT, 1); |
|
63 - pr_inet_generate_socket_event("core.data-connect", main_server, |
|
64 - session.d->local_addr, session.d->listen_fd); |
|
65 + /* Make sure that the necessary socket options are set on the socket prior |
|
66 + * to the call to connect(2). |
|
67 + */ |
|
68 + pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0, |
|
69 + IPTOS_THROUGHPUT, 1); |
|
70 + pr_inet_generate_socket_event("core.data-connect", main_server, |
|
71 + session.d->local_addr, session.d->listen_fd); |
|
72 |
|
73 - if (pr_inet_connect(session.d->pool, session.d, &session.data_addr, |
|
74 + if (pr_inet_connect(session.d->pool, session.d, &session.data_addr, |
|
75 session.data_port) == -1) { |
|
76 - pr_response_add_err(R_425, _("Unable to build data connection: %s"), |
|
77 - strerror(session.d->xerrno)); |
|
78 - destroy_pool(session.d->pool); |
|
79 - session.d = NULL; |
|
80 - return -1; |
|
81 + if (session.d->xerrno == EADDRINUSE && retries < 16) { |
|
82 + destroy_pool(session.d->pool); |
|
83 + pr_signals_handle(); |
|
84 + /* Wait up to MSL to avoid TIME_WAIT. */ |
|
85 + sleep(retries++); |
|
86 + continue; |
|
87 + } |
|
88 + pr_response_add_err(R_425, _("Unable to build data connection: %s"), |
|
89 + strerror(session.d->xerrno)); |
|
90 + destroy_pool(session.d->pool); |
|
91 + session.d = NULL; |
|
92 + return -1; |
|
93 + } else |
|
94 + break; |
|
95 } |
45 } |
96 |
46 |
97 c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA, |
47 c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA, |
98 |
48 |