mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
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).
This commit is contained in:
parent
c31451cf13
commit
fcfd6d9504
14
CHANGES
14
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),
|
||||
|
197
lib/ftp.c
197
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;
|
||||
}
|
||||
|
||||
if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
error = Curl_ourerrno();
|
||||
sclose(portsock);
|
||||
portsock = CURL_SOCKET_BAD;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listen(portsock, 1) < 0) {
|
||||
error = Curl_ourerrno();
|
||||
sclose(portsock);
|
||||
portsock = CURL_SOCKET_BAD;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (portsock == CURL_SOCKET_BAD) {
|
||||
failf(data, "socket failure: %s", Curl_strerror(conn,error));
|
||||
if(!ai) {
|
||||
failf(data, "socket failure: %s", Curl_strerror(conn, error));
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the name again after the bind() so that we can extract the
|
||||
port number it uses now */
|
||||
sslen = sizeof(ss);
|
||||
if (getsockname(portsock, sa, &sslen) < 0) {
|
||||
failf(data, "getsockname(): %s", Curl_strerror(conn,Curl_ourerrno()));
|
||||
if(getsockname(portsock, (struct sockaddr *)sa, &sslen)<0) {
|
||||
failf(data, "getsockname() failed: %s",
|
||||
Curl_strerror(conn, Curl_ourerrno()) );
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/*
|
||||
* Two fine examples from RFC2428;
|
||||
*
|
||||
* EPRT |1|132.235.1.2|6275|
|
||||
*
|
||||
* EPRT |2|1080::8:800:200C:417A|5282|
|
||||
*/
|
||||
|
||||
/* do not transmit IPv6 scope identifier to the wire */
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
char *q = strchr(portmsgbuf, '%');
|
||||
if (q)
|
||||
*q = '\0';
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
*dest = *source;
|
||||
dest++;
|
||||
source++;
|
||||
}
|
||||
*dest = 0;
|
||||
snprintf(dest, 20, ",%d,%d", port>>8, port&0xff);
|
||||
|
||||
if (LPRT == fcmd) {
|
||||
snprintf(tmp, sizeof(tmp), ",%d", plen);
|
||||
|
||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf))
|
||||
continue;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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" */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user