mirror of
https://github.com/moparisthebest/curl
synced 2025-03-11 07:39:50 -04:00
- Markus Koetter made CURLOPT_FTPPORT (and curl's -P/--ftpport) support a port
range if given colon-separated after the host name/address part. Like "192.168.0.1:2000-10000"
This commit is contained in:
parent
9cb68c6e32
commit
4f551259dd
10
CHANGES
10
CHANGES
@ -6,6 +6,16 @@
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Daniel Stenberg (29 Jun 2009)
|
||||||
|
- Markus Koetter made CURLOPT_FTPPORT (and curl's -P/--ftpport) support a port
|
||||||
|
range if given colon-separated after the host name/address part. Like
|
||||||
|
"192.168.0.1:2000-10000"
|
||||||
|
|
||||||
|
- Modified the separators used for CURLOPT_CERTINFO in multi-part outputs. I
|
||||||
|
don't know how they got wrong in the first place, but using this output
|
||||||
|
format makes it possible to quite easily separate the string into an array
|
||||||
|
of multiple items.
|
||||||
|
|
||||||
Daniel Fandrich (16 June 2009)
|
Daniel Fandrich (16 June 2009)
|
||||||
- Added a few more compiler warning options for gcc.
|
- Added a few more compiler warning options for gcc.
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ Curl and libcurl 7.19.6
|
|||||||
|
|
||||||
This release includes the following changes:
|
This release includes the following changes:
|
||||||
|
|
||||||
o
|
o CURLOPT_FTPPORT (and curl's -P/--ftpport) support port ranges
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
@ -41,6 +41,6 @@ advice from friends like these:
|
|||||||
Yang Tse, Daniel Fandrich, Kamil Dudka, Caolan McNamara, Frank McGeough,
|
Yang Tse, Daniel Fandrich, Kamil Dudka, Caolan McNamara, Frank McGeough,
|
||||||
Andre Guibert de Bruet, Mike Crowe, Claes Jakobsson, John E. Malmberg,
|
Andre Guibert de Bruet, Mike Crowe, Claes Jakobsson, John E. Malmberg,
|
||||||
Aaron Oneal, Igor Novoseltsev, Eric Wong, Bill Hoffman, Daniel Steinberg,
|
Aaron Oneal, Igor Novoseltsev, Eric Wong, Bill Hoffman, Daniel Steinberg,
|
||||||
Fabian Keil, Michal Marek, Reuven Wachtfogel
|
Fabian Keil, Michal Marek, Reuven Wachtfogel, Markus Koetter
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
@ -953,6 +953,12 @@ connection
|
|||||||
If this option is used several times, the last one will be used. Disable the
|
If this option is used several times, the last one will be used. Disable the
|
||||||
use of PORT with \fI--ftp-pasv\fP. Disable the attempt to use the EPRT command
|
use of PORT with \fI--ftp-pasv\fP. Disable the attempt to use the EPRT command
|
||||||
instead of PORT by using \fI--disable-eprt\fP. EPRT is really PORT++.
|
instead of PORT by using \fI--disable-eprt\fP. EPRT is really PORT++.
|
||||||
|
|
||||||
|
Starting in 7.19.5, you can append \&":[start]-[end]\&" to the right of the
|
||||||
|
address, to tell curl what TCP port range to use. That means you specify a
|
||||||
|
port range, from a lower to a higher number. A single number works as well,
|
||||||
|
but do not that it increases the risk of failure since the port may not be
|
||||||
|
available.
|
||||||
.IP "-q"
|
.IP "-q"
|
||||||
If used as the first parameter on the command line, the \fIcurlrc\fP config
|
If used as the first parameter on the command line, the \fIcurlrc\fP config
|
||||||
file will not be read and used. See the \fI-K/--config\fP for details on the
|
file will not be read and used. See the \fI-K/--config\fP for details on the
|
||||||
|
@ -1070,6 +1070,12 @@ be a plain IP address, a host name, a network interface name (under Unix) or
|
|||||||
just a '-' symbol to let the library use your system's default IP
|
just a '-' symbol to let the library use your system's default IP
|
||||||
address. Default FTP operations are passive, and thus won't use PORT.
|
address. Default FTP operations are passive, and thus won't use PORT.
|
||||||
|
|
||||||
|
Starting in 7.19.5, you can append \&":[start]-[end]\&" to the right of the
|
||||||
|
address, to tell libcurl what TCP port range to use. That means you specify a
|
||||||
|
port range, from a lower to a higher number. A single number works as well,
|
||||||
|
but do not that it increases the risk of failure since the port may not be
|
||||||
|
available.
|
||||||
|
|
||||||
You disable PORT again and go back to using the passive version by setting
|
You disable PORT again and go back to using the passive version by setting
|
||||||
this option to NULL.
|
this option to NULL.
|
||||||
.IP CURLOPT_QUOTE
|
.IP CURLOPT_QUOTE
|
||||||
|
346
lib/ftp.c
346
lib/ftp.c
@ -290,7 +290,8 @@ static void freedirs(struct ftp_conn *ftpc)
|
|||||||
*/
|
*/
|
||||||
static bool isBadFtpString(const char *string)
|
static bool isBadFtpString(const char *string)
|
||||||
{
|
{
|
||||||
return (bool)((NULL != strchr(string, '\r')) || (NULL != strchr(string, '\n')));
|
return (bool)((NULL != strchr(string, '\r')) ||
|
||||||
|
(NULL != strchr(string, '\n')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@ -882,36 +883,116 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
curl_socket_t portsock= CURL_SOCKET_BAD;
|
curl_socket_t portsock= CURL_SOCKET_BAD;
|
||||||
char myhost[256] = "";
|
char myhost[256] = "";
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
/******************************************************************
|
|
||||||
* IPv6-specific section
|
|
||||||
*/
|
|
||||||
struct Curl_sockaddr_storage ss;
|
struct Curl_sockaddr_storage ss;
|
||||||
Curl_addrinfo *res, *ai;
|
Curl_addrinfo *res, *ai;
|
||||||
curl_socklen_t sslen;
|
curl_socklen_t sslen;
|
||||||
char hbuf[NI_MAXHOST];
|
char hbuf[NI_MAXHOST];
|
||||||
struct sockaddr *sa=(struct sockaddr *)&ss;
|
struct sockaddr *sa=(struct sockaddr *)&ss;
|
||||||
struct sockaddr_in * const sa4 = (void *)sa;
|
struct sockaddr_in * const sa4 = (void *)sa;
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
struct sockaddr_in6 * const sa6 = (void *)sa;
|
struct sockaddr_in6 * const sa6 = (void *)sa;
|
||||||
|
#endif
|
||||||
char tmp[1024];
|
char tmp[1024];
|
||||||
static const char mode[][5] = { "EPRT", "PORT" };
|
static const char mode[][5] = { "EPRT", "PORT" };
|
||||||
int rc;
|
int rc;
|
||||||
int error;
|
int error;
|
||||||
char *host=NULL;
|
char *host=NULL;
|
||||||
|
char *string_ftpport = data->set.str[STRING_FTPPORT];
|
||||||
struct Curl_dns_entry *h=NULL;
|
struct Curl_dns_entry *h=NULL;
|
||||||
unsigned short port = 0;
|
unsigned short port_min = 0;
|
||||||
|
unsigned short port_max = 0;
|
||||||
|
unsigned short port;
|
||||||
|
|
||||||
/* Step 1, figure out what address that is requested */
|
char *addr = NULL;
|
||||||
|
|
||||||
|
/* Step 1, figure out what is requested,
|
||||||
|
* accepted format :
|
||||||
|
* (ipv4|ipv6|domain|interface)?(:port(-range)?)?
|
||||||
|
*/
|
||||||
|
|
||||||
if(data->set.str[STRING_FTPPORT] &&
|
if(data->set.str[STRING_FTPPORT] &&
|
||||||
(strlen(data->set.str[STRING_FTPPORT]) > 1)) {
|
(strlen(data->set.str[STRING_FTPPORT]) > 1)) {
|
||||||
/* attempt to get the address of the given interface name */
|
|
||||||
if(!Curl_if2ip(conn->ip_addr->ai_family, data->set.str[STRING_FTPPORT],
|
#ifdef ENABLE_IPV6
|
||||||
hbuf, sizeof(hbuf)))
|
size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
|
||||||
/* not an interface, use the given string as host name instead */
|
INET6_ADDRSTRLEN : strlen(string_ftpport);
|
||||||
host = data->set.str[STRING_FTPPORT];
|
#else
|
||||||
else
|
size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
|
||||||
host = hbuf; /* use the hbuf for host name */
|
INET_ADDRSTRLEN : strlen(string_ftpport);
|
||||||
|
#endif
|
||||||
|
char *ip_start = string_ftpport;
|
||||||
|
char *ip_end = NULL;
|
||||||
|
char *port_start = NULL;
|
||||||
|
char *port_sep = NULL;
|
||||||
|
|
||||||
|
addr = malloc(addrlen);
|
||||||
|
memset(addr, 0, addrlen);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
if(*string_ftpport == '[') {
|
||||||
|
/* [ipv6]:port(-range) */
|
||||||
|
ip_start = string_ftpport + 1;
|
||||||
|
if((ip_end = strchr(string_ftpport, ']')) != NULL )
|
||||||
|
strncpy(addr, ip_start, ip_end - ip_start);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if( *string_ftpport == ':') {
|
||||||
|
/* :port */
|
||||||
|
ip_end = string_ftpport;
|
||||||
|
} else
|
||||||
|
if( (ip_end = strchr(string_ftpport, ':')) != NULL) {
|
||||||
|
/* either ipv6 or (ipv4|domain|interface):port(-range) */
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
|
||||||
|
/* ipv6 */
|
||||||
|
port_min = port_max = 0;
|
||||||
|
strcpy(addr, string_ftpport);
|
||||||
|
ip_end = NULL; /* this got no port ! */
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* (ipv4|domain|interface):port(-range) */
|
||||||
|
strncpy(addr, string_ftpport, ip_end - ip_start );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* ipv4|interface */
|
||||||
|
strcpy(addr, string_ftpport);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse the port */
|
||||||
|
if( ip_end != NULL ) {
|
||||||
|
if((port_start = strchr(ip_end, ':')) != NULL) {
|
||||||
|
port_min = (unsigned short)strtol(port_start+1, NULL, 10);
|
||||||
|
if((port_sep = strchr(port_start, '-')) != NULL) {
|
||||||
|
port_max = (unsigned short)strtol(port_sep + 1, NULL, 10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
port_max = port_min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* correct errors like:
|
||||||
|
* :1234-1230
|
||||||
|
* :-4711 , in this case port_min is (unsigned)-1,
|
||||||
|
* therefore port_min > port_max for all cases
|
||||||
|
* but port_max = (unsigned)-1
|
||||||
|
*/
|
||||||
|
if(port_min > port_max )
|
||||||
|
port_min = port_max = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if(*addr != '\0') {
|
||||||
|
/* attempt to get the address of the given interface name */
|
||||||
|
if(!Curl_if2ip(conn->ip_addr->ai_family, addr,
|
||||||
|
hbuf, sizeof(hbuf)))
|
||||||
|
/* not an interface, use the given string as host name instead */
|
||||||
|
host = addr;
|
||||||
|
else
|
||||||
|
host = hbuf; /* use the hbuf for host name */
|
||||||
|
}else
|
||||||
|
/* there was only a port(-range) given, default the host */
|
||||||
|
host = NULL;
|
||||||
} /* data->set.ftpport */
|
} /* data->set.ftpport */
|
||||||
|
|
||||||
if(!host) {
|
if(!host) {
|
||||||
@ -922,20 +1003,24 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
if(getsockname(conn->sock[FIRSTSOCKET], (struct sockaddr *)&ss, &sslen)) {
|
if(getsockname(conn->sock[FIRSTSOCKET], (struct sockaddr *)&ss, &sslen)) {
|
||||||
failf(data, "getsockname() failed: %s",
|
failf(data, "getsockname() failed: %s",
|
||||||
Curl_strerror(conn, SOCKERRNO) );
|
Curl_strerror(conn, SOCKERRNO) );
|
||||||
|
if (addr)
|
||||||
|
free(addr);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sslen > (curl_socklen_t)sizeof(ss))
|
sslen = sizeof(ss);
|
||||||
sslen = sizeof(ss);
|
|
||||||
rc = getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL,
|
rc = getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL,
|
||||||
0, NIFLAGS);
|
0, NIFLAGS);
|
||||||
if(rc) {
|
if(rc) {
|
||||||
failf(data, "getnameinfo() returned %d", rc);
|
failf(data, "getnameinfo() returned %d", rc);
|
||||||
|
if (addr)
|
||||||
|
free(addr);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
host = hbuf; /* use this host name */
|
host = hbuf; /* use this host name */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* resolv ip/host to ip */
|
||||||
rc = Curl_resolv(conn, host, 0, &h);
|
rc = Curl_resolv(conn, host, 0, &h);
|
||||||
if(rc == CURLRESOLV_PENDING)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
rc = Curl_wait_for_resolv(conn, &h);
|
rc = Curl_wait_for_resolv(conn, &h);
|
||||||
@ -948,6 +1033,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
else
|
else
|
||||||
res = NULL; /* failure! */
|
res = NULL; /* failure! */
|
||||||
|
|
||||||
|
if (addr)
|
||||||
|
free(addr);
|
||||||
|
|
||||||
|
if (res == NULL) {
|
||||||
|
failf(data, "Curl_resolv failed, we can not recover!");
|
||||||
|
return CURLE_FTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
/* step 2, create a socket for the requested address */
|
/* step 2, create a socket for the requested address */
|
||||||
|
|
||||||
@ -974,32 +1066,56 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
|
|
||||||
/* step 3, bind to a suitable local address */
|
/* step 3, bind to a suitable local address */
|
||||||
|
|
||||||
/* Try binding the given address. */
|
memcpy(sa, ai->ai_addr, ai->ai_addrlen);
|
||||||
if(bind(portsock, ai->ai_addr, ai->ai_addrlen)) {
|
sslen = ai->ai_addrlen;
|
||||||
|
|
||||||
/* It failed. Bind the address used for the control connection instead */
|
for( port = port_min; port <= port_max; ) {
|
||||||
sslen = sizeof(ss);
|
if( sa->sa_family == AF_INET )
|
||||||
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
|
sa4->sin_port = htons(port);
|
||||||
failf(data, "getsockname() failed: %s",
|
#ifdef ENABLE_IPV6
|
||||||
Curl_strerror(conn, SOCKERRNO) );
|
|
||||||
sclose(portsock);
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set port number to zero to make bind() pick "any" */
|
|
||||||
if(sa->sa_family == AF_INET)
|
|
||||||
sa4->sin_port = 0;
|
|
||||||
else
|
else
|
||||||
sa6->sin6_port = 0;
|
sa6->sin6_port = htons(port);
|
||||||
|
#endif
|
||||||
|
/* Try binding the given address. */
|
||||||
|
if(bind(portsock, sa, sslen) ) {
|
||||||
|
/* It failed. */
|
||||||
|
if(errno == EADDRNOTAVAIL) {
|
||||||
|
|
||||||
if(sslen > (curl_socklen_t)sizeof(ss))
|
/* The requested bind address is not local
|
||||||
sslen = sizeof(ss);
|
* use the address used forthe control connection instead
|
||||||
|
* restart the port loop
|
||||||
|
*/
|
||||||
|
failf(data, "bind(port=%i) failed: %s", port,
|
||||||
|
Curl_strerror(conn, SOCKERRNO) );
|
||||||
|
|
||||||
if(bind(portsock, sa, sslen)) {
|
sslen = sizeof(ss);
|
||||||
failf(data, "bind failed: %s", Curl_strerror(conn, SOCKERRNO));
|
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
|
||||||
sclose(portsock);
|
failf(data, "getsockname() failed: %s",
|
||||||
return CURLE_FTP_PORT_FAILED;
|
Curl_strerror(conn, SOCKERRNO) );
|
||||||
}
|
sclose(portsock);
|
||||||
|
return CURLE_FTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
port = port_min;
|
||||||
|
continue;
|
||||||
|
}else
|
||||||
|
if(errno != EADDRINUSE && errno != EACCES) {
|
||||||
|
failf(data, "bind(port=%i) failed: %s", port,
|
||||||
|
Curl_strerror(conn, SOCKERRNO) );
|
||||||
|
sclose(portsock);
|
||||||
|
return CURLE_FTP_PORT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
|
port++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* maybe all ports were in use already*/
|
||||||
|
if (port > port_max) {
|
||||||
|
failf(data, "bind() failed, we ran out of ports!");
|
||||||
|
sclose(portsock);
|
||||||
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the name again after the bind() so that we can extract the
|
/* get the name again after the bind() so that we can extract the
|
||||||
@ -1039,6 +1155,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
/* if disabled, goto next */
|
/* if disabled, goto next */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if((PORT == fcmd) && sa->sa_family != AF_INET)
|
||||||
|
/* PORT is ipv4 only */
|
||||||
|
continue;
|
||||||
|
|
||||||
switch (sa->sa_family) {
|
switch (sa->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
port = ntohs(sa4->sin_port);
|
port = ntohs(sa4->sin_port);
|
||||||
@ -1060,7 +1180,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
result = Curl_nbftpsendf(conn, "%s |%d|%s|%d|", mode[fcmd],
|
result = Curl_nbftpsendf(conn, "%s |%d|%s|%d|", mode[fcmd],
|
||||||
ai->ai_family == AF_INET?1:2,
|
sa->sa_family == AF_INET?1:2,
|
||||||
myhost, port);
|
myhost, port);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
@ -1070,9 +1190,6 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
char *source = myhost;
|
char *source = myhost;
|
||||||
char *dest = tmp;
|
char *dest = tmp;
|
||||||
|
|
||||||
if((PORT == fcmd) && ai->ai_family != AF_INET)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* translate x.x.x.x to x,x,x,x */
|
/* translate x.x.x.x to x,x,x,x */
|
||||||
while(source && *source) {
|
while(source && *source) {
|
||||||
if(*source == '.')
|
if(*source == '.')
|
||||||
@ -1102,151 +1219,6 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
sclose(conn->sock[SECONDARYSOCKET]);
|
||||||
conn->sock[SECONDARYSOCKET] = portsock;
|
conn->sock[SECONDARYSOCKET] = portsock;
|
||||||
|
|
||||||
#else
|
|
||||||
/******************************************************************
|
|
||||||
* IPv4-specific section
|
|
||||||
*/
|
|
||||||
struct sockaddr_in sa;
|
|
||||||
unsigned short porttouse;
|
|
||||||
bool sa_filled_in = FALSE;
|
|
||||||
Curl_addrinfo *addr = NULL;
|
|
||||||
unsigned short ip[4];
|
|
||||||
bool freeaddr = TRUE;
|
|
||||||
curl_socklen_t sslen = sizeof(sa);
|
|
||||||
const char *ftpportstr = data->set.str[STRING_FTPPORT];
|
|
||||||
|
|
||||||
(void)fcmd; /* not used in the IPv4 code */
|
|
||||||
if(ftpportstr) {
|
|
||||||
struct in_addr in;
|
|
||||||
|
|
||||||
/* First check if the given string is an IP address */
|
|
||||||
if(Curl_inet_pton(AF_INET, ftpportstr, &in) > 0) {
|
|
||||||
/* this is an IPv4 address */
|
|
||||||
addr = Curl_ip2addr(AF_INET, &in, ftpportstr, 0);
|
|
||||||
}
|
|
||||||
/* otherwise check if the given string is an interface */
|
|
||||||
else if(Curl_if2ip(AF_INET, ftpportstr, myhost, sizeof(myhost))) {
|
|
||||||
/* The interface to IP conversion provided a dotted address */
|
|
||||||
if(Curl_inet_pton(AF_INET, myhost, &in) > 0)
|
|
||||||
addr = Curl_ip2addr(AF_INET, &in, myhost, 0);
|
|
||||||
}
|
|
||||||
else if(strlen(ftpportstr)> 1) {
|
|
||||||
/* might be a host name! */
|
|
||||||
struct Curl_dns_entry *h=NULL;
|
|
||||||
int rc = Curl_resolv(conn, ftpportstr, 0, &h);
|
|
||||||
if(rc == CURLRESOLV_PENDING)
|
|
||||||
/* BLOCKING */
|
|
||||||
rc = Curl_wait_for_resolv(conn, &h);
|
|
||||||
if(h) {
|
|
||||||
addr = h->addr;
|
|
||||||
/* when we return from this function, we can forget about this entry
|
|
||||||
so we can unlock it now already */
|
|
||||||
Curl_resolv_unlock(data, h);
|
|
||||||
|
|
||||||
freeaddr = FALSE; /* make sure we don't free 'addr' in this function
|
|
||||||
since it points to a DNS cache entry! */
|
|
||||||
} /* (h) */
|
|
||||||
else {
|
|
||||||
infof(data, "Failed to resolve host name %s\n", ftpportstr);
|
|
||||||
}
|
|
||||||
} /* strlen */
|
|
||||||
} /* ftpportstr */
|
|
||||||
|
|
||||||
if(!addr) {
|
|
||||||
/* pick a suitable default here */
|
|
||||||
|
|
||||||
if(getsockname(conn->sock[FIRSTSOCKET],
|
|
||||||
(struct sockaddr *)&sa, &sslen)) {
|
|
||||||
failf(data, "getsockname() failed: %s",
|
|
||||||
Curl_strerror(conn, SOCKERRNO) );
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
if(sslen > (curl_socklen_t)sizeof(sa))
|
|
||||||
sslen = sizeof(sa);
|
|
||||||
|
|
||||||
sa_filled_in = TRUE; /* the sa struct is filled in */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr || sa_filled_in) {
|
|
||||||
portsock = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if(CURL_SOCKET_BAD != portsock) {
|
|
||||||
|
|
||||||
/* we set the secondary socket variable to this for now, it
|
|
||||||
is only so that the cleanup function will close it in case
|
|
||||||
we fail before the true secondary stuff is made */
|
|
||||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
|
|
||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
|
||||||
conn->sock[SECONDARYSOCKET] = portsock;
|
|
||||||
|
|
||||||
if(!sa_filled_in) {
|
|
||||||
memcpy(&sa, addr->ai_addr, sslen);
|
|
||||||
sa.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
sa.sin_port = 0;
|
|
||||||
sslen = sizeof(sa);
|
|
||||||
|
|
||||||
if(bind(portsock, (struct sockaddr *)&sa, sslen) == 0) {
|
|
||||||
/* we succeeded to bind */
|
|
||||||
struct sockaddr_in add;
|
|
||||||
curl_socklen_t socksize = sizeof(add);
|
|
||||||
|
|
||||||
if(getsockname(portsock, (struct sockaddr *) &add,
|
|
||||||
&socksize)) {
|
|
||||||
failf(data, "getsockname() failed: %s",
|
|
||||||
Curl_strerror(conn, SOCKERRNO) );
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
porttouse = ntohs(add.sin_port);
|
|
||||||
|
|
||||||
if( listen(portsock, 1) < 0 ) {
|
|
||||||
failf(data, "listen(2) failed on socket");
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
failf(data, "bind(2) failed on socket");
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
failf(data, "socket(2) failed (%s)");
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
failf(data, "couldn't find IP address to use");
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sa_filled_in)
|
|
||||||
Curl_inet_ntop(AF_INET, &((struct sockaddr_in *)&sa)->sin_addr,
|
|
||||||
myhost, sizeof(myhost));
|
|
||||||
else
|
|
||||||
Curl_printable_address(addr, myhost, sizeof(myhost));
|
|
||||||
|
|
||||||
if(4 == sscanf(myhost, "%hu.%hu.%hu.%hu",
|
|
||||||
&ip[0], &ip[1], &ip[2], &ip[3])) {
|
|
||||||
|
|
||||||
infof(data, "Telling server to connect to %d.%d.%d.%d:%d\n",
|
|
||||||
ip[0], ip[1], ip[2], ip[3], porttouse);
|
|
||||||
|
|
||||||
result=Curl_nbftpsendf(conn, "PORT %d,%d,%d,%d,%d,%d",
|
|
||||||
ip[0], ip[1], ip[2], ip[3],
|
|
||||||
porttouse >> 8, porttouse & 255);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
|
||||||
|
|
||||||
if(freeaddr)
|
|
||||||
Curl_freeaddrinfo(addr);
|
|
||||||
|
|
||||||
ftpc->count1 = PORT;
|
|
||||||
|
|
||||||
#endif /* end of ipv4-specific code */
|
|
||||||
|
|
||||||
/* this tcpconnect assignment below is a hackish work-around to make the
|
/* this tcpconnect assignment below is a hackish work-around to make the
|
||||||
multi interface with active FTP work - as it will not wait for a
|
multi interface with active FTP work - as it will not wait for a
|
||||||
(passive) connect in Curl_is_connected().
|
(passive) connect in Curl_is_connected().
|
||||||
|
Loading…
x
Reference in New Issue
Block a user