aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2011-11-06 16:53:07 +0100
committerDaniel Stenberg <daniel@haxx.se>2011-11-06 23:02:27 +0100
commite3166df1bb3e027e20455c7b99b42779e607ccfb (patch)
treee9f5ae191e6888f8c038aa6bf79945a7a1c47713
parent06a83e805070b01e8c8ebffb1f6b56e113b1810a (diff)
ftp PORT: don't hang if bind() fails
When the user requests PORT with a specific port or port range, the code could lock up in an endless loop. There's now an extra conditional that makes sure to special treat the error and try the local address only once so a second failure will abort the loop correctly. Bug: http://curl.haxx.se/bug/view.cgi?id=3433968 Reported by: Gokhan Sengun
-rw-r--r--lib/ftp.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index c1dc6689a..e5b1682fc 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -753,6 +753,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
unsigned short port_min = 0;
unsigned short port_max = 0;
unsigned short port;
+ bool possibly_non_local = TRUE;
char *addr = NULL;
@@ -869,6 +870,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
break;
}
host = hbuf; /* use this host name */
+ possibly_non_local = FALSE; /* we know it is local now */
}
/* resolv ip/host to ip */
@@ -932,12 +934,12 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(bind(portsock, sa, sslen) ) {
/* It failed. */
error = SOCKERRNO;
- if(error == EADDRNOTAVAIL) {
-
+ if(possibly_non_local && (error == EADDRNOTAVAIL)) {
/* The requested bind address is not local. Use the address used for
* the control connection instead and restart the port loop
*/
- failf(data, "bind(port=%hu) failed: %s", port,
+
+ infof(data, "bind(port=%hu) on non-local address failed: %s", port,
Curl_strerror(conn, error) );
sslen = sizeof(ss);
@@ -948,6 +950,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
return CURLE_FTP_PORT_FAILED;
}
port = port_min;
+ possibly_non_local = FALSE; /* don't try this again */
continue;
}
else if(error != EADDRINUSE && error != EACCES) {