aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES14
-rw-r--r--lib/ftp.c187
-rw-r--r--lib/url.c5
-rw-r--r--lib/urldata.h6
-rw-r--r--tests/data/test2125
5 files changed, 101 insertions, 116 deletions
diff --git a/CHANGES b/CHANGES
index d2e35cd64..16de2cb7c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,9 +6,19 @@
Changelog
+Daniel (20 January 2006)
+- Duane Cathey was one of our friends who reported that curl -P [IP]
+ (CURLOPT_FTPPORT) didn't work for ipv6-enabed curls if the IP wasn't a
+ "native" IP while it works fine for ipv6-disabled builds!
+
+ In the process of fixing this, I removed the support for LPRT since I can't
+ think of many reasons to keep doing it and asking on the mailing list didn't
+ reveal anyone else that could either. The code that sends EPRT and PORT is
+ now also a lot simpler than before (IMHO).
+
Daniel (19 January 2006)
-- Jon Turner pointed out that doing -P [hostname] with curl (built ipv4-only)
- didn't work.
+- Jon Turner pointed out that doing -P [hostname] (CURLOPT_FTPPORT) with curl
+ (built ipv4-only) didn't work.
Daniel (18 January 2006)
- As reported in bug #1408742 (http://curl.haxx.se/bug/view.cgi?id=1408742),
diff --git a/lib/ftp.c b/lib/ftp.c
index 2361c89ec..3cdcc32ef 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -763,7 +763,11 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
return result;
}
-typedef enum { EPRT, LPRT, PORT, DONE } ftpport;
+typedef enum {
+ EPRT,
+ PORT,
+ DONE
+} ftpport;
static CURLcode ftp_state_use_port(struct connectdata *conn,
ftpport fcmd) /* start with this */
@@ -773,6 +777,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
struct FTP *ftp = conn->proto.ftp;
struct SessionHandle *data=conn->data;
curl_socket_t portsock= CURL_SOCKET_BAD;
+ char myhost[256] = "";
#ifdef ENABLE_IPV6
/******************************************************************
@@ -783,14 +788,15 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
socklen_t sslen;
char hbuf[NI_MAXHOST];
struct sockaddr *sa=(struct sockaddr *)&ss;
- unsigned char *ap;
- unsigned char *pp;
- char portmsgbuf[1024], tmp[1024];
- const char *mode[] = { "EPRT", "LPRT", "PORT", NULL };
+ char tmp[1024];
+ const char *mode[] = { "EPRT", "PORT", NULL };
int rc;
int error;
char *host=NULL;
struct Curl_dns_entry *h=NULL;
+ unsigned short port;
+
+ /* Step 1, figure out what address that is requested */
if(data->set.ftpport && (strlen(data->set.ftpport) > 1)) {
/* attempt to get the address of the given interface name */
@@ -833,6 +839,9 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
else
res = NULL; /* failure! */
+
+ /* step 2, create a socket for the requested address */
+
portsock = CURL_SOCKET_BAD;
error = 0;
for (ai = res; ai; ai = ai->ai_next) {
@@ -847,35 +856,65 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
error = Curl_ourerrno();
continue;
}
+ break;
+ }
+ if(!ai) {
+ failf(data, "socket failure: %s", Curl_strerror(conn, error));
+ return CURLE_FTP_PORT_FAILED;
+ }
- if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) {
- error = Curl_ourerrno();
+ /* step 3, bind to a suitable local address */
+
+ /* Try binding the given address. */
+ if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) {
+
+ /* It failed. Bind the address used for the control connection instead */
+ sslen = sizeof(ss);
+
+ if (getsockname(conn->sock[FIRSTSOCKET],
+ (struct sockaddr *)sa, &sslen) < 0) {
+ failf(data, "getsockname() failed");
sclose(portsock);
- portsock = CURL_SOCKET_BAD;
- continue;
+ return CURLE_FTP_PORT_FAILED;
}
- if (listen(portsock, 1) < 0) {
- error = Curl_ourerrno();
+ /* set port number to zero to make bind() pick "any" */
+ if(((struct sockaddr *)sa)->sa_family == AF_INET)
+ ((struct sockaddr_in *)sa)->sin_port=0;
+ else
+ ((struct sockaddr_in6 *)sa)->sin6_port =0;
+
+ if(bind(portsock, (struct sockaddr *)sa, sslen) < 0) {
+ failf(data, "bind failed: %s", Curl_strerror(conn, Curl_ourerrno()));
sclose(portsock);
- portsock = CURL_SOCKET_BAD;
- continue;
+ return CURLE_FTP_PORT_FAILED;
}
-
- break;
}
- if (portsock == CURL_SOCKET_BAD) {
- failf(data, "socket failure: %s", Curl_strerror(conn,error));
+ /* get the name again after the bind() so that we can extract the
+ port number it uses now */
+ sslen = sizeof(ss);
+ if(getsockname(portsock, (struct sockaddr *)sa, &sslen)<0) {
+ failf(data, "getsockname() failed: %s",
+ Curl_strerror(conn, Curl_ourerrno()) );
return CURLE_FTP_PORT_FAILED;
}
- sslen = sizeof(ss);
- if (getsockname(portsock, sa, &sslen) < 0) {
- failf(data, "getsockname(): %s", Curl_strerror(conn,Curl_ourerrno()));
+ /* step 4, listen on the socket */
+
+ if (listen(portsock, 1) < 0) {
+ error = Curl_ourerrno();
+ sclose(portsock);
+ failf(data, "socket failure: %s", Curl_strerror(conn, error));
return CURLE_FTP_PORT_FAILED;
}
+ /* step 5, send the proper FTP command */
+
+ /* get a plain printable version of the numerical address to work with
+ below */
+ Curl_printable_address(ai, myhost, sizeof(myhost));
+
#ifdef PF_INET6
if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
/* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
@@ -884,107 +923,58 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
#endif
for (; fcmd != DONE; fcmd++) {
- int lprtaf, eprtaf;
- int alen=0, plen=0;
if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
/* if disabled, goto next */
continue;
- if(!conn->bits.ftp_use_lprt && (LPRT == fcmd))
- /* if disabled, goto next */
- continue;
-
switch (sa->sa_family) {
case AF_INET:
- ap = (unsigned char *)&((struct sockaddr_in *)&ss)->sin_addr;
- alen = sizeof(((struct sockaddr_in *)&ss)->sin_addr);
- pp = (unsigned char *)&((struct sockaddr_in *)&ss)->sin_port;
- plen = sizeof(((struct sockaddr_in *)&ss)->sin_port);
- lprtaf = 4;
- eprtaf = 1;
+ port = ntohs(((struct sockaddr_in *)sa)->sin_port);
break;
case AF_INET6:
- ap = (unsigned char *)&((struct sockaddr_in6 *)&ss)->sin6_addr;
- alen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_addr);
- pp = (unsigned char *)&((struct sockaddr_in6 *)&ss)->sin6_port;
- plen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_port);
- lprtaf = 6;
- eprtaf = 2;
+ port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
break;
default:
- ap = pp = NULL;
- lprtaf = eprtaf = -1;
break;
}
if (EPRT == fcmd) {
- if (eprtaf < 0)
- continue;
- if (getnameinfo((struct sockaddr *)&ss, sslen,
- portmsgbuf, sizeof(portmsgbuf), tmp, sizeof(tmp),
- NIFLAGS))
- continue;
-
- /* do not transmit IPv6 scope identifier to the wire */
- if (sa->sa_family == AF_INET6) {
- char *q = strchr(portmsgbuf, '%');
- if (q)
- *q = '\0';
- }
+ /*
+ * Two fine examples from RFC2428;
+ *
+ * EPRT |1|132.235.1.2|6275|
+ *
+ * EPRT |2|1080::8:800:200C:417A|5282|
+ */
- result = Curl_nbftpsendf(conn, "%s |%d|%s|%s|", mode[fcmd], eprtaf,
- portmsgbuf, tmp);
+ result = Curl_nbftpsendf(conn, "%s |%d|%s|%d|", mode[fcmd],
+ ai->ai_family == AF_INET?1:2,
+ myhost, port);
if(result)
return result;
break;
}
- else if ((LPRT == fcmd) || (PORT == fcmd)) {
- int i;
+ else if (PORT == fcmd) {
+ char *source = myhost;
+ char *dest = tmp;
- if ((LPRT == fcmd) && lprtaf < 0)
- continue;
- if ((PORT == fcmd) && sa->sa_family != AF_INET)
+ if ((PORT == fcmd) && ai->ai_family != AF_INET)
continue;
- portmsgbuf[0] = '\0';
- if (LPRT == fcmd) {
- snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen);
- if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >=
- sizeof(portmsgbuf)) {
- continue;
- }
- }
-
- for (i = 0; i < alen; i++) {
- if (portmsgbuf[0])
- snprintf(tmp, sizeof(tmp), ",%u", ap[i]);
+ /* translate x.x.x.x to x,x,x,x */
+ while(source && *source) {
+ if(*source == '.')
+ *dest=',';
else
- snprintf(tmp, sizeof(tmp), "%u", ap[i]);
-
- if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >=
- sizeof(portmsgbuf)) {
- continue;
- }
- }
-
- if (LPRT == fcmd) {
- snprintf(tmp, sizeof(tmp), ",%d", plen);
-
- if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf))
- continue;
+ *dest = *source;
+ dest++;
+ source++;
}
+ *dest = 0;
+ snprintf(dest, 20, ",%d,%d", port>>8, port&0xff);
- for (i = 0; i < plen; i++) {
- snprintf(tmp, sizeof(tmp), ",%u", pp[i]);
-
- if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >=
- sizeof(portmsgbuf)) {
- continue;
- }
- }
-
- result = Curl_nbftpsendf(conn, "%s %s", mode[fcmd], portmsgbuf);
+ result = Curl_nbftpsendf(conn, "%s %s", mode[fcmd], tmp);
if(result)
return result;
break;
@@ -1007,7 +997,6 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
*/
struct sockaddr_in sa;
unsigned short porttouse;
- char myhost[256] = "";
bool sa_filled_in = FALSE;
Curl_addrinfo *addr = NULL;
unsigned short ip[4];
@@ -1735,10 +1724,6 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn,
infof(data, "disabling EPRT usage\n");
conn->bits.ftp_use_eprt = FALSE;
}
- else if (LPRT == fcmd) {
- infof(data, "disabling LPRT usage\n");
- conn->bits.ftp_use_lprt = FALSE;
- }
fcmd++;
if(fcmd == DONE) {
diff --git a/lib/url.c b/lib/url.c
index b8927fbcd..a4bd0f509 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -326,7 +326,6 @@ CURLcode Curl_open(struct SessionHandle **curl)
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
data->set.ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
- data->set.ftp_use_lprt = TRUE; /* FTP defaults to EPRT operations */
data->set.ftp_filemethod = FTPFILE_MULTICWD;
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
@@ -964,7 +963,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
case CURLOPT_FTP_USE_EPRT:
data->set.ftp_use_eprt = va_arg(param, long)?TRUE:FALSE;
- data->set.ftp_use_lprt = data->set.ftp_use_eprt;
break;
case CURLOPT_FTP_USE_EPSV:
@@ -2365,7 +2363,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
- conn->bits.ftp_use_lprt = data->set.ftp_use_lprt;
/* This initing continues below, see the comment "Continue connectdata
* initialization here" */
diff --git a/lib/urldata.h b/lib/urldata.h
index 94889234a..c3a76b45c 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -427,9 +427,6 @@ struct ConnectBits {
bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
EPRT doesn't work we disable it for the forthcoming
requests */
- bool ftp_use_lprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
- LPRT doesn't work we disable it for the forthcoming
- requests */
bool netrc; /* name+password provided by netrc */
bool trailerHdrPresent; /* Set when Trailer: header found in HTTP response.
@@ -1075,7 +1072,6 @@ struct UserDefined {
bool expect100header; /* TRUE if we added Expect: 100-continue */
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
bool ftp_use_eprt; /* if EPRT is to be attempted or not */
- bool ftp_use_lprt; /* if LPRT is to be attempted or not */
curl_ftpssl ftp_ssl; /* if AUTH TLS is to be attempted etc */
curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
bool no_signal; /* do not use any signal/alarm handler */
diff --git a/tests/data/test212 b/tests/data/test212
index 8633ae5d4..3fac26bde 100644
--- a/tests/data/test212
+++ b/tests/data/test212
@@ -15,14 +15,13 @@ ipv6
ftp
</server>
<name>
-Get two FTP files with no remote EPRT or LPRT support
+Get two FTP files with no remote EPRT support
</name>
<command>
ftp://%HOSTIP:%FTPPORT/a/path/212 ftp://%HOSTIP:%FTPPORT/a/path/212 -P -
</command>
<file name="log/ftpserver.cmd">
REPLY EPRT 500 no such command
-REPLY LPRT 500 no such command
</file>
<stdout>
data blobb
@@ -34,7 +33,6 @@ data blobb
<verify>
<strippart>
s/^(EPRT \|1\|127.0.0.1).*/$1/
-s/^(LPRT 4,4,127,0,0,1,).*/$1/
s/^(PORT 127,0,0,1,).*/$1/
</strippart>
<protocol>
@@ -44,7 +42,6 @@ PWD
CWD a
CWD path
EPRT |1|127.0.0.1
-LPRT 4,4,127,0,0,1,
PORT 127,0,0,1,
TYPE I
SIZE 212