From 064bc3ecbc13c877139bc4003d95bc2e3cea2ebe Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 28 Jan 2005 08:26:36 +0000 Subject: [PATCH] Stephen More pointed out that CURLOPT_FTPPORT and the -P option didn't work when built ipv6-enabled. I've now made a fix for it. Writing test cases for custom port strings turned too tricky so unfortunately there's none. --- CHANGES | 5 ++++ RELEASE-NOTES | 3 +- lib/ftp.c | 79 ++++++++++++++++++++++++++++----------------------- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/CHANGES b/CHANGES index 77b770f71..5aa5a84eb 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,11 @@ Changelog +Daniel (28 January 2005) +- Stephen More pointed out that CURLOPT_FTPPORT and the -P option didn't work + when built ipv6-enabled. I've now made a fix for it. Writing test cases for + custom port hosts turned too tricky so unfortunately there's none. + Daniel (25 January 2005) - Ian Ford asked about support for the FTP command ACCT, and I discovered it is present in RFC959... so now (lib)curl supports it as well. --ftp-account diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 5e57b2231..74609e5f8 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -22,6 +22,7 @@ This release includes the following changes: This release includes the following bugfixes: + o CURLOPT_FTPPORT and -P work when built ipv6-enabled o FTP third party transfers was much improved o proxy environment variables are now ignored when built HTTP-disabled o CURLOPT_PROXY can now disable HTTP proxy even when built HTTP-disabled @@ -50,6 +51,6 @@ advice from friends like these: Werner Koch, Gisle Vanem, Alex Neblett, Kai Sommerfeld, Marty Kuhrt, Hzhijun, Pavel Orehov, Bruce Mitchener, Cyrill Osterwalder, Dan Torop, Martijn Koster, Alex aka WindEagle, Cody Jones, Samuel Díaz García, - Stephan Bergmann, Philippe Hameau, Ian Ford + Stephan Bergmann, Philippe Hameau, Ian Ford, Stephen More Thanks! (and sorry if I forgot to mention someone) diff --git a/lib/ftp.c b/lib/ftp.c index caca95e95..e5ad8bde1 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1130,49 +1130,58 @@ CURLcode ftp_use_port(struct connectdata *conn) struct addrinfo hints, *res, *ai; struct sockaddr_storage ss; socklen_t sslen; - char hbuf[NI_MAXHOST]; - + char hbuf[NI_MAXHOST]=""; struct sockaddr *sa=(struct sockaddr *)&ss; unsigned char *ap; unsigned char *pp; char portmsgbuf[1024], tmp[1024]; - enum ftpcommand { EPRT, LPRT, PORT, DONE } fcmd; const char *mode[] = { "EPRT", "LPRT", "PORT", NULL }; int rc; int error; + char *host=NULL; + struct Curl_dns_entry *h=NULL; - /* - * we should use Curl_if2ip? given pickiness of recent ftpd, - * I believe we should use the same address as the control connection. - */ - sslen = sizeof(ss); - rc = getsockname(conn->sock[FIRSTSOCKET], (struct sockaddr *)&ss, &sslen); - if(rc < 0) { - failf(data, "getsockname() returned %d\n", rc); - return CURLE_FTP_PORT_FAILED; + if(data->set.ftpport && (strlen(data->set.ftpport) > 1)) { + /* attempt to get the address of the given interface name */ + if(!Curl_if2ip(data->set.ftpport, hbuf, sizeof(hbuf))) + /* not an interface, use the given string as host name instead */ + host = data->set.ftpport; + else + host = hbuf; /* use the hbuf for host name */ + } /* data->set.ftpport */ + + if(!host) { + /* not an interface and not a host name, get default by extracting + the IP from the control connection */ + + sslen = sizeof(ss); + rc = getsockname(conn->sock[FIRSTSOCKET], (struct sockaddr *)&ss, &sslen); + if(rc < 0) { + failf(data, "getsockname() returned %d\n", rc); + return CURLE_FTP_PORT_FAILED; + } + + rc = getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, + 0, NIFLAGS); + if(rc) { + failf(data, "getnameinfo() returned %d\n", rc); + return CURLE_FTP_PORT_FAILED; + } + host = hbuf; /* use this host name */ } - rc = getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0, - NIFLAGS); - if(rc) { - failf(data, "getnameinfo() returned %d\n", rc); - return CURLE_FTP_PORT_FAILED; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = sa->sa_family; - /*hints.ai_family = ss.ss_family; - this way can be used if sockaddr_storage is properly defined, as glibc - 2.1.X doesn't do*/ - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - rc = getaddrinfo(hbuf, NULL, &hints, &res); - if(rc) { - failf(data, "getaddrinfo() returned %d\n", rc); - return CURLE_FTP_PORT_FAILED; - } + rc = Curl_resolv(conn, host, 0, &h); + if(rc == CURLRESOLV_PENDING) + rc = Curl_wait_for_resolv(conn, &h); + if(h) { + res = h->addr; + /* when we return from this function, we can forget about this entry + to we can unlock it now already */ + Curl_resolv_unlock(data, h); + } /* (h) */ + else + res = NULL; /* failure! */ portsock = CURL_SOCKET_BAD; error = 0; @@ -1188,7 +1197,6 @@ CURLcode ftp_use_port(struct connectdata *conn) error = Curl_ourerrno(); continue; } - if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) { error = Curl_ourerrno(); sclose(portsock); @@ -1205,7 +1213,7 @@ CURLcode ftp_use_port(struct connectdata *conn) break; } - freeaddrinfo(res); + if (portsock == CURL_SOCKET_BAD) { failf(data, "%s", Curl_strerror(conn,error)); return CURLE_FTP_PORT_FAILED; @@ -1226,7 +1234,6 @@ CURLcode ftp_use_port(struct connectdata *conn) } #endif - for (fcmd = EPRT; fcmd != DONE; fcmd++) { int lprtaf, eprtaf; int alen=0, plen=0;