1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

initial code added to support EPSV (IPv6-style PASV)

This commit is contained in:
Daniel Stenberg 2001-11-27 00:48:45 +00:00
parent 4382a80b9a
commit 6003f24f78

148
lib/ftp.c
View File

@ -1258,6 +1258,23 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
char *buf = data->state.buffer; /* this is our buffer */ char *buf = data->state.buffer; /* this is our buffer */
int ftpcode; /* receive FTP response codes in this */ int ftpcode; /* receive FTP response codes in this */
CURLcode result; 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 #if 0
/* no support for IPv6 passive mode yet */ /* no support for IPv6 passive mode yet */
@ -1268,6 +1285,13 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
int results[] = { 227, 0 }; int results[] = { 227, 0 };
#endif #endif
int modeoff; 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++) { for (modeoff = 0; mode[modeoff]; modeoff++) {
FTPSENDF(conn, mode[modeoff], ""); FTPSENDF(conn, mode[modeoff], "");
@ -1283,16 +1307,9 @@ CURLcode ftp_use_pasv(struct connectdata *conn)
failf(data, "Odd return code after PASV"); failf(data, "Odd return code after PASV");
return CURLE_FTP_WEIRD_PASV_REPLY; return CURLE_FTP_WEIRD_PASV_REPLY;
} }
else if (strcmp(mode[modeoff], "PASV") == 0) { else if (227 == results[modeoff]) {
int ip[4]; int ip[4];
int port[2]; 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; 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]); sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
newport = (port[0]<<8) + port[1]; newport = (port[0]<<8) + port[1];
if(data->change.proxy) {
/* /* we should compare to see if this is the same IP like the one
* This is a tunnel through a http proxy and we need to connect to the we're already connected to, as then we can skip the name function
* proxy again here. We already have the name info for it since the call below, in similar style that we do for the EPSV reply */
* previous lookup. }
*/ #if 1
addr = conn->hostaddr; else if (strcmp(mode[modeoff], "EPSV") == 0) {
connectport = char *ptr = strchr(buf, '(');
(unsigned short)conn->port; /* we connect to the proxy's port */ if(ptr) {
} unsigned int num;
else { char separator[4];
/* normal, direct, ftp connection */ ptr++;
addr = Curl_getaddrinfo(data, newhost, newport, &hostdataptr); if(5 == sscanf(ptr, "%c%c%c%u%c",
if(!addr) { &separator[0],
failf(data, "Can't resolve new host %s", newhost); &separator[1],
return CURLE_FTP_CANT_GET_HOST; &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;
} }
if(!ptr) {
result = Curl_connecthost(conn, failf(data, "Weirdly formatted EPSV reply");
addr, return CURLE_FTP_WEIRD_PASV_REPLY;
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;
} }
} }
#endif
else else
return CURLE_FTP_CANT_RECONNECT; 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; return CURLE_OK;
} }