mirror of
https://github.com/moparisthebest/curl
synced 2024-11-11 12:05:06 -05:00
initial code added to support EPSV (IPv6-style PASV)
This commit is contained in:
parent
4382a80b9a
commit
6003f24f78
148
lib/ftp.c
148
lib/ftp.c
@ -1258,6 +1258,23 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
||||
char *buf = data->state.buffer; /* this is our buffer */
|
||||
int ftpcode; /* receive FTP response codes in this */
|
||||
CURLcode result;
|
||||
Curl_addrinfo *addr=NULL;
|
||||
Curl_ipconnect *conninfo;
|
||||
|
||||
/*
|
||||
Here's the excecutive summary on what to do:
|
||||
|
||||
PASV is RFC959, expect:
|
||||
227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
|
||||
|
||||
LPSV is RFC1639, expect:
|
||||
228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
|
||||
(Is this actually supported *anywhere*?)
|
||||
|
||||
EPSV is RFC2428, expect:
|
||||
229 Entering Extended Passive Mode (|||port|)
|
||||
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/* no support for IPv6 passive mode yet */
|
||||
@ -1268,6 +1285,13 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
||||
int results[] = { 227, 0 };
|
||||
#endif
|
||||
int modeoff;
|
||||
unsigned short connectport; /* the local port connect() should use! */
|
||||
unsigned short newport; /* remote port, not necessary the local one */
|
||||
char *hostdataptr=NULL;
|
||||
|
||||
/* newhost must be able to hold a full IP-style address in ASCII, which
|
||||
in the IPv6 case means 5*8-1 = 39 letters */
|
||||
char newhost[48];
|
||||
|
||||
for (modeoff = 0; mode[modeoff]; modeoff++) {
|
||||
FTPSENDF(conn, mode[modeoff], "");
|
||||
@ -1283,16 +1307,9 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
||||
failf(data, "Odd return code after PASV");
|
||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||
}
|
||||
else if (strcmp(mode[modeoff], "PASV") == 0) {
|
||||
else if (227 == results[modeoff]) {
|
||||
int ip[4];
|
||||
int port[2];
|
||||
unsigned short newport; /* remote port, not necessary the local one */
|
||||
unsigned short connectport; /* the local port connect() should use! */
|
||||
char newhost[32];
|
||||
|
||||
Curl_addrinfo *addr;
|
||||
char *hostdataptr=NULL;
|
||||
Curl_ipconnect *conninfo;
|
||||
char *str=buf;
|
||||
|
||||
/*
|
||||
@ -1321,54 +1338,87 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
|
||||
|
||||
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
newport = (port[0]<<8) + port[1];
|
||||
if(data->change.proxy) {
|
||||
/*
|
||||
* This is a tunnel through a http proxy and we need to connect to the
|
||||
* proxy again here. We already have the name info for it since the
|
||||
* previous lookup.
|
||||
*/
|
||||
addr = conn->hostaddr;
|
||||
connectport =
|
||||
(unsigned short)conn->port; /* we connect to the proxy's port */
|
||||
}
|
||||
else {
|
||||
/* normal, direct, ftp connection */
|
||||
addr = Curl_getaddrinfo(data, newhost, newport, &hostdataptr);
|
||||
if(!addr) {
|
||||
failf(data, "Can't resolve new host %s", newhost);
|
||||
return CURLE_FTP_CANT_GET_HOST;
|
||||
|
||||
/* we should compare to see if this is the same IP like the one
|
||||
we're already connected to, as then we can skip the name function
|
||||
call below, in similar style that we do for the EPSV reply */
|
||||
}
|
||||
#if 1
|
||||
else if (strcmp(mode[modeoff], "EPSV") == 0) {
|
||||
char *ptr = strchr(buf, '(');
|
||||
if(ptr) {
|
||||
unsigned int num;
|
||||
char separator[4];
|
||||
ptr++;
|
||||
if(5 == sscanf(ptr, "%c%c%c%u%c",
|
||||
&separator[0],
|
||||
&separator[1],
|
||||
&separator[2],
|
||||
&num,
|
||||
&separator[3])) {
|
||||
/* the four separators should be identical */
|
||||
newport = num;
|
||||
|
||||
/* we should use the same host we already are connected to */
|
||||
addr = conn->hostaddr;
|
||||
}
|
||||
connectport = newport; /* we connect to the remote port */
|
||||
else
|
||||
ptr=NULL;
|
||||
}
|
||||
|
||||
result = Curl_connecthost(conn,
|
||||
addr,
|
||||
connectport,
|
||||
&conn->secondarysocket,
|
||||
&conninfo);
|
||||
|
||||
if((CURLE_OK == result) &&
|
||||
data->set.verbose)
|
||||
/* this just dumps information about this second connection */
|
||||
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
|
||||
|
||||
if(hostdataptr)
|
||||
Curl_freeaddrinfo(hostdataptr);
|
||||
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
|
||||
if (data->set.tunnel_thru_httpproxy) {
|
||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||
result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
|
||||
newhost, newport);
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
if(!ptr) {
|
||||
failf(data, "Weirdly formatted EPSV reply");
|
||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return CURLE_FTP_CANT_RECONNECT;
|
||||
|
||||
if(data->change.proxy) {
|
||||
/*
|
||||
* This is a tunnel through a http proxy and we need to connect to the
|
||||
* proxy again here. We already have the name info for it since the
|
||||
* previous lookup.
|
||||
*/
|
||||
addr = conn->hostaddr;
|
||||
connectport =
|
||||
(unsigned short)conn->port; /* we connect to the proxy's port */
|
||||
}
|
||||
else if(!addr) {
|
||||
/* normal, direct, ftp connection */
|
||||
addr = Curl_getaddrinfo(data, newhost, newport, &hostdataptr);
|
||||
if(!addr) {
|
||||
failf(data, "Can't resolve new host %s", newhost);
|
||||
return CURLE_FTP_CANT_GET_HOST;
|
||||
}
|
||||
connectport = newport; /* we connect to the remote port */
|
||||
}
|
||||
|
||||
result = Curl_connecthost(conn,
|
||||
addr,
|
||||
connectport,
|
||||
&conn->secondarysocket,
|
||||
&conninfo);
|
||||
|
||||
if((CURLE_OK == result) &&
|
||||
data->set.verbose)
|
||||
/* this just dumps information about this second connection */
|
||||
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
|
||||
|
||||
if(hostdataptr)
|
||||
Curl_freeaddrinfo(hostdataptr);
|
||||
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
|
||||
if (data->set.tunnel_thru_httpproxy) {
|
||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||
result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
|
||||
newhost, newport);
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user