Loading CHANGES +3 −0 Original line number Original line Diff line number Diff line Loading @@ -8,6 +8,9 @@ Daniel (5 February 2001) Daniel (5 February 2001) - Jun-ichiro itojun Hagino brought a big patch that brings IPv6-awareness to a bunch of different areas within libcurl. - Robert Weaver told me about the problems the MS VC++ 6.0 compiler has with - Robert Weaver told me about the problems the MS VC++ 6.0 compiler has with the 'static' keyword on a number of libcurl functions. I might need to add a the 'static' keyword on a number of libcurl functions. I might need to add a patch that redefines static when libcurl is compiled with that compiler. patch that redefines static when libcurl is compiled with that compiler. Loading configure.in +7 −8 Original line number Original line Diff line number Diff line Loading @@ -53,15 +53,9 @@ dnl AC_DEFUN(CURL_CHECK_WORKING_GETADDRINFO,[ AC_DEFUN(CURL_CHECK_WORKING_GETADDRINFO,[ AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[ AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[ AC_TRY_RUN( [ AC_TRY_RUN( [ #ifdef HAVE_NETDB_H #include <netdb.h> #include <netdb.h> #endif #include <sys/types.h> #ifdef HAVE_STRING_H #include <string.h> #endif #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #include <sys/socket.h> #endif void main(void) { void main(void) { struct addrinfo hints, *ai; struct addrinfo hints, *ai; Loading Loading @@ -434,6 +428,10 @@ AC_MSG_CHECKING([if Kerberos4 support is requested]) if test "$want_krb4" = yes if test "$want_krb4" = yes then then if test "$ipv6" = "yes"; then echo krb4 is not compatible with IPv6 exit 1 fi AC_MSG_RESULT(yes) AC_MSG_RESULT(yes) dnl Check for & handle argument to --with-krb4 dnl Check for & handle argument to --with-krb4 Loading Loading @@ -691,7 +689,8 @@ AC_CHECK_FUNCS( socket \ setvbuf \ setvbuf \ sigaction \ sigaction \ signal \ signal \ getpass_r getpass_r \ strlcat ) ) dnl removed 'getpass' check on October 26, 2000 dnl removed 'getpass' check on October 26, 2000 Loading docs/curl.1 +1 −0 Original line number Original line Diff line number Diff line Loading @@ -788,6 +788,7 @@ If you do find bugs, mail them to curl-bug@haxx.se. - Loic Dachary <loic@senga.org> - Loic Dachary <loic@senga.org> - Robert Weaver <robert.weaver@sabre.com> - Robert Weaver <robert.weaver@sabre.com> - Ingo Ralf Blum <ingoralfblum@ingoralfblum.com> - Ingo Ralf Blum <ingoralfblum@ingoralfblum.com> - Jun-ichiro itojun Hagino <itojun@iijlab.net> .SH WWW .SH WWW http://curl.haxx.se http://curl.haxx.se Loading lib/ftp.c +256 −7 Original line number Original line Diff line number Diff line Loading @@ -564,6 +564,9 @@ CURLcode _ftp(struct connectdata *conn) #if defined (HAVE_INET_NTOA_R) #if defined (HAVE_INET_NTOA_R) char ntoa_buf[64]; char ntoa_buf[64]; #endif #endif #ifdef ENABLE_IPV6 struct addrinfo *ai; #endif struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */ /* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */ Loading Loading @@ -702,6 +705,174 @@ CURLcode _ftp(struct connectdata *conn) /* We have chosen to use the PORT command */ /* We have chosen to use the PORT command */ if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) { #ifdef ENABLE_IPV6 struct addrinfo hints, *res, *ai; struct sockaddr_storage ss; int sslen; char hbuf[NI_MAXHOST]; char *localaddr; #ifdef NI_WITHSCOPEID const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID; #else const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; #endif unsigned char *ap; unsigned char *pp; int alen, plen; char portmsgbuf[4096], tmp[4096]; char *p; char *mode[] = { "EPRT", "LPRT", "PORT", NULL }; char **modep; /* * 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); if (getsockname(data->firstsocket, (struct sockaddr *)&ss, &sslen) < 0) return CURLE_FTP_PORT_FAILED; if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0, niflags)) return CURLE_FTP_PORT_FAILED; memset(&hints, 0, sizeof(hints)); hints.ai_family = ss.ss_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if (getaddrinfo(hbuf, "0", &hints, &res)) return CURLE_FTP_PORT_FAILED; portsock = -1; for (ai = res; ai; ai = ai->ai_next) { portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (portsock < 0) continue; if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) { close(portsock); portsock = -1; continue; } if (listen(portsock, 1) < 0) { close(portsock); portsock = -1; continue; } break; } if (portsock < 0) { failf(data, strerror(errno)); freeaddrinfo(res); return CURLE_FTP_PORT_FAILED; } sslen = sizeof(ss); if (getsockname(portsock, (struct sockaddr *)&ss, &sslen) < 0) { failf(data, strerror(errno)); freeaddrinfo(res); return CURLE_FTP_PORT_FAILED; } for (modep = mode; modep && *modep; modep++) { int lprtaf, eprtaf; switch (ss.ss_family) { case AF_INET: ap = (char *)&((struct sockaddr_in *)&ss)->sin_addr; alen = sizeof(((struct sockaddr_in *)&ss)->sin_addr); pp = (char *)&((struct sockaddr_in *)&ss)->sin_port; plen = sizeof(((struct sockaddr_in *)&ss)->sin_port); lprtaf = 4; eprtaf = 1; break; case AF_INET6: ap = (char *)&((struct sockaddr_in6 *)&ss)->sin6_addr; alen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_addr); pp = (char *)&((struct sockaddr_in6 *)&ss)->sin6_port; plen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_port); lprtaf = 6; eprtaf = 2; break; default: ap = pp = NULL; lprtaf = eprtaf = -1; break; } if (strcmp(*modep, "EPRT") == 0) { if (eprtaf < 0) continue; if (getnameinfo((struct sockaddr *)&ss, sslen, portmsgbuf, sizeof(portmsgbuf), tmp, sizeof(tmp), niflags)) continue; /* do not transmit IPv6 scope identifier to the wire */ if (ss.ss_family == AF_INET6) { char *q = strchr(portmsgbuf, '%'); if (q) *q = '\0'; } ftpsendf(data->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf, portmsgbuf, tmp); } else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) { int i; if (strcmp(*modep, "LPRT") == 0 && lprtaf < 0) continue; if (strcmp(*modep, "PORT") == 0 && ss.ss_family != AF_INET) continue; portmsgbuf[0] = '\0'; if (strcmp(*modep, "LPRT") == 0) { snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { goto again; } } for (i = 0; i < alen; i++) { if (portmsgbuf[0]) snprintf(tmp, sizeof(tmp), ",%u", ap[i]); else snprintf(tmp, sizeof(tmp), "%u", ap[i]); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { goto again; } } if (strcmp(*modep, "LPRT") == 0) { snprintf(tmp, sizeof(tmp), ",%d", plen); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) goto again; } for (i = 0; i < plen; i++) { snprintf(tmp, sizeof(tmp), ",%u", pp[i]); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { goto again; } } ftpsendf(data->firstsocket, conn, "%s %s", *modep, portmsgbuf); } nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); if (nread < 0) return CURLE_OPERATION_TIMEOUTED; if (ftpcode != 200) { failf(data, "Server does not grok %s", *modep); continue; } else break; again:; } if (!*modep) { close(portsock); freeaddrinfo(res); return CURLE_FTP_PORT_FAILED; } #else struct sockaddr_in sa; struct sockaddr_in sa; struct hostent *h=NULL; struct hostent *h=NULL; char *hostdataptr=NULL; char *hostdataptr=NULL; Loading Loading @@ -809,26 +980,43 @@ CURLcode _ftp(struct connectdata *conn) failf(data, "Server does not grok PORT, try without it!"); failf(data, "Server does not grok PORT, try without it!"); return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED; } } #endif /* ENABLE_IPV6 */ } } else { /* we use the PASV command */ else { /* we use the PASV command */ #if 0 char *mode[] = { "EPSV", "LPSV", "PASV", NULL }; int results[] = { 229, 228, 227, 0 }; #else char *mode[] = { "PASV", NULL }; int results[] = { 227, 0 }; #endif int modeoff; ftpsendf(data->firstsocket, conn, "PASV"); for (modeoff = 0; mode[modeoff]; modeoff++) { ftpsendf(data->firstsocket, conn, mode[modeoff]); nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); if(nread < 0) if(nread < 0) return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED; if(ftpcode != 227) { if (ftpcode == results[modeoff]) break; } if (!mode[modeoff]) { 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 { else if (strcmp(mode[modeoff], "PASV") == 0) { int ip[4]; int ip[4]; int port[2]; int port[2]; unsigned short newport; /* remote port, not necessary the local one */ unsigned short newport; /* remote port, not necessary the local one */ unsigned short connectport; /* the local port connect() should use! */ unsigned short connectport; /* the local port connect() should use! */ char newhost[32]; char newhost[32]; #ifdef ENABLE_IPV6 struct addrinfo *res; #else struct hostent *he; struct hostent *he; #endif char *str=buf,*ip_addr; char *str=buf,*ip_addr; char *hostdataptr=NULL; char *hostdataptr=NULL; Loading Loading @@ -863,20 +1051,78 @@ CURLcode _ftp(struct connectdata *conn) * proxy again here. We already have the name info for it since the * proxy again here. We already have the name info for it since the * previous lookup. * previous lookup. */ */ #ifdef ENABLE_IPV6 res = conn->res; #else he = conn->hp; he = conn->hp; #endif connectport = connectport = (unsigned short)data->port; /* we connect to the proxy's port */ (unsigned short)data->port; /* we connect to the proxy's port */ } } else { else { /* normal, direct, ftp connection */ /* normal, direct, ftp connection */ #ifdef ENABLE_IPV6 res = Curl_getaddrinfo(data, newhost, newport); if(!res) #else he = Curl_gethost(data, newhost, &hostdataptr); he = Curl_gethost(data, newhost, &hostdataptr); if(!he) { if(!he) #endif { failf(data, "Can't resolve new host %s", newhost); failf(data, "Can't resolve new host %s", newhost); return CURLE_FTP_CANT_GET_HOST; return CURLE_FTP_CANT_GET_HOST; } } connectport = newport; /* we connect to the remote port */ connectport = newport; /* we connect to the remote port */ } } #ifdef ENABLE_IPV6 data->secondarysocket = -1; for (ai = res; ai; ai = ai->ai_next) { /* XXX for now, we can do IPv4 only */ if (ai->ai_family != AF_INET) continue; data->secondarysocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (data->secondarysocket < 0) continue; if(data->bits.verbose) { char hbuf[NI_MAXHOST]; char nbuf[NI_MAXHOST]; char sbuf[NI_MAXSERV]; #ifdef NI_WITHSCOPEID const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID; #else const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; #endif if (getnameinfo(res->ai_addr, res->ai_addrlen, nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) { snprintf(nbuf, sizeof(nbuf), "?"); snprintf(sbuf, sizeof(sbuf), "?"); } if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, 0)) { infof(data, "Connecting to %s port %s\n", nbuf, sbuf); } else { infof(data, "Connecting to %s (%s) port %s\n", hbuf, nbuf, sbuf); } } if (connect(data->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) { close(data->secondarysocket); data->secondarysocket = -1; continue; } break; } if (data->secondarysocket < 0) { failf(data, strerror(errno)); return CURLE_FTP_CANT_RECONNECT; } #else data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0); data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0); memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memset((char *) &serv_addr, '\0', sizeof(serv_addr)); Loading Loading @@ -971,6 +1217,7 @@ CURLcode _ftp(struct connectdata *conn) } } return CURLE_FTP_CANT_RECONNECT; return CURLE_FTP_CANT_RECONNECT; } } #endif /*ENABLE_IPV6*/ if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) { /* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */ Loading @@ -979,6 +1226,8 @@ CURLcode _ftp(struct connectdata *conn) if(CURLE_OK != result) if(CURLE_OK != result) return result; return result; } } } else { return CURLE_FTP_CANT_RECONNECT; } } } } /* we have the (new) data connection ready */ /* we have the (new) data connection ready */ Loading lib/hostip.c +23 −0 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,29 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len) return (addr); return (addr); } } #ifdef ENABLE_IPV6 struct addrinfo *Curl_getaddrinfo(struct UrlData *data, char *hostname, int port) { struct addrinfo hints, *res; int error; char sbuf[NI_MAXSERV]; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; snprintf(sbuf, sizeof(sbuf), "%d", port); error = getaddrinfo(hostname, sbuf, &hints, &res); if (error) { infof(data, "getaddrinfo(3) failed for %s\n", hostname); return NULL; } return res; } #endif /* The original code to this function was once stolen from the Dancer source /* The original code to this function was once stolen from the Dancer source code, written by Bjorn Reese, it has since been patched and modified code, written by Bjorn Reese, it has since been patched and modified considerably. */ considerably. */ Loading Loading
CHANGES +3 −0 Original line number Original line Diff line number Diff line Loading @@ -8,6 +8,9 @@ Daniel (5 February 2001) Daniel (5 February 2001) - Jun-ichiro itojun Hagino brought a big patch that brings IPv6-awareness to a bunch of different areas within libcurl. - Robert Weaver told me about the problems the MS VC++ 6.0 compiler has with - Robert Weaver told me about the problems the MS VC++ 6.0 compiler has with the 'static' keyword on a number of libcurl functions. I might need to add a the 'static' keyword on a number of libcurl functions. I might need to add a patch that redefines static when libcurl is compiled with that compiler. patch that redefines static when libcurl is compiled with that compiler. Loading
configure.in +7 −8 Original line number Original line Diff line number Diff line Loading @@ -53,15 +53,9 @@ dnl AC_DEFUN(CURL_CHECK_WORKING_GETADDRINFO,[ AC_DEFUN(CURL_CHECK_WORKING_GETADDRINFO,[ AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[ AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[ AC_TRY_RUN( [ AC_TRY_RUN( [ #ifdef HAVE_NETDB_H #include <netdb.h> #include <netdb.h> #endif #include <sys/types.h> #ifdef HAVE_STRING_H #include <string.h> #endif #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #include <sys/socket.h> #endif void main(void) { void main(void) { struct addrinfo hints, *ai; struct addrinfo hints, *ai; Loading Loading @@ -434,6 +428,10 @@ AC_MSG_CHECKING([if Kerberos4 support is requested]) if test "$want_krb4" = yes if test "$want_krb4" = yes then then if test "$ipv6" = "yes"; then echo krb4 is not compatible with IPv6 exit 1 fi AC_MSG_RESULT(yes) AC_MSG_RESULT(yes) dnl Check for & handle argument to --with-krb4 dnl Check for & handle argument to --with-krb4 Loading Loading @@ -691,7 +689,8 @@ AC_CHECK_FUNCS( socket \ setvbuf \ setvbuf \ sigaction \ sigaction \ signal \ signal \ getpass_r getpass_r \ strlcat ) ) dnl removed 'getpass' check on October 26, 2000 dnl removed 'getpass' check on October 26, 2000 Loading
docs/curl.1 +1 −0 Original line number Original line Diff line number Diff line Loading @@ -788,6 +788,7 @@ If you do find bugs, mail them to curl-bug@haxx.se. - Loic Dachary <loic@senga.org> - Loic Dachary <loic@senga.org> - Robert Weaver <robert.weaver@sabre.com> - Robert Weaver <robert.weaver@sabre.com> - Ingo Ralf Blum <ingoralfblum@ingoralfblum.com> - Ingo Ralf Blum <ingoralfblum@ingoralfblum.com> - Jun-ichiro itojun Hagino <itojun@iijlab.net> .SH WWW .SH WWW http://curl.haxx.se http://curl.haxx.se Loading
lib/ftp.c +256 −7 Original line number Original line Diff line number Diff line Loading @@ -564,6 +564,9 @@ CURLcode _ftp(struct connectdata *conn) #if defined (HAVE_INET_NTOA_R) #if defined (HAVE_INET_NTOA_R) char ntoa_buf[64]; char ntoa_buf[64]; #endif #endif #ifdef ENABLE_IPV6 struct addrinfo *ai; #endif struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */ /* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */ Loading Loading @@ -702,6 +705,174 @@ CURLcode _ftp(struct connectdata *conn) /* We have chosen to use the PORT command */ /* We have chosen to use the PORT command */ if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) { #ifdef ENABLE_IPV6 struct addrinfo hints, *res, *ai; struct sockaddr_storage ss; int sslen; char hbuf[NI_MAXHOST]; char *localaddr; #ifdef NI_WITHSCOPEID const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID; #else const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; #endif unsigned char *ap; unsigned char *pp; int alen, plen; char portmsgbuf[4096], tmp[4096]; char *p; char *mode[] = { "EPRT", "LPRT", "PORT", NULL }; char **modep; /* * 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); if (getsockname(data->firstsocket, (struct sockaddr *)&ss, &sslen) < 0) return CURLE_FTP_PORT_FAILED; if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0, niflags)) return CURLE_FTP_PORT_FAILED; memset(&hints, 0, sizeof(hints)); hints.ai_family = ss.ss_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if (getaddrinfo(hbuf, "0", &hints, &res)) return CURLE_FTP_PORT_FAILED; portsock = -1; for (ai = res; ai; ai = ai->ai_next) { portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (portsock < 0) continue; if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) { close(portsock); portsock = -1; continue; } if (listen(portsock, 1) < 0) { close(portsock); portsock = -1; continue; } break; } if (portsock < 0) { failf(data, strerror(errno)); freeaddrinfo(res); return CURLE_FTP_PORT_FAILED; } sslen = sizeof(ss); if (getsockname(portsock, (struct sockaddr *)&ss, &sslen) < 0) { failf(data, strerror(errno)); freeaddrinfo(res); return CURLE_FTP_PORT_FAILED; } for (modep = mode; modep && *modep; modep++) { int lprtaf, eprtaf; switch (ss.ss_family) { case AF_INET: ap = (char *)&((struct sockaddr_in *)&ss)->sin_addr; alen = sizeof(((struct sockaddr_in *)&ss)->sin_addr); pp = (char *)&((struct sockaddr_in *)&ss)->sin_port; plen = sizeof(((struct sockaddr_in *)&ss)->sin_port); lprtaf = 4; eprtaf = 1; break; case AF_INET6: ap = (char *)&((struct sockaddr_in6 *)&ss)->sin6_addr; alen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_addr); pp = (char *)&((struct sockaddr_in6 *)&ss)->sin6_port; plen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_port); lprtaf = 6; eprtaf = 2; break; default: ap = pp = NULL; lprtaf = eprtaf = -1; break; } if (strcmp(*modep, "EPRT") == 0) { if (eprtaf < 0) continue; if (getnameinfo((struct sockaddr *)&ss, sslen, portmsgbuf, sizeof(portmsgbuf), tmp, sizeof(tmp), niflags)) continue; /* do not transmit IPv6 scope identifier to the wire */ if (ss.ss_family == AF_INET6) { char *q = strchr(portmsgbuf, '%'); if (q) *q = '\0'; } ftpsendf(data->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf, portmsgbuf, tmp); } else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) { int i; if (strcmp(*modep, "LPRT") == 0 && lprtaf < 0) continue; if (strcmp(*modep, "PORT") == 0 && ss.ss_family != AF_INET) continue; portmsgbuf[0] = '\0'; if (strcmp(*modep, "LPRT") == 0) { snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { goto again; } } for (i = 0; i < alen; i++) { if (portmsgbuf[0]) snprintf(tmp, sizeof(tmp), ",%u", ap[i]); else snprintf(tmp, sizeof(tmp), "%u", ap[i]); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { goto again; } } if (strcmp(*modep, "LPRT") == 0) { snprintf(tmp, sizeof(tmp), ",%d", plen); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) goto again; } for (i = 0; i < plen; i++) { snprintf(tmp, sizeof(tmp), ",%u", pp[i]); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { goto again; } } ftpsendf(data->firstsocket, conn, "%s %s", *modep, portmsgbuf); } nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); if (nread < 0) return CURLE_OPERATION_TIMEOUTED; if (ftpcode != 200) { failf(data, "Server does not grok %s", *modep); continue; } else break; again:; } if (!*modep) { close(portsock); freeaddrinfo(res); return CURLE_FTP_PORT_FAILED; } #else struct sockaddr_in sa; struct sockaddr_in sa; struct hostent *h=NULL; struct hostent *h=NULL; char *hostdataptr=NULL; char *hostdataptr=NULL; Loading Loading @@ -809,26 +980,43 @@ CURLcode _ftp(struct connectdata *conn) failf(data, "Server does not grok PORT, try without it!"); failf(data, "Server does not grok PORT, try without it!"); return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED; } } #endif /* ENABLE_IPV6 */ } } else { /* we use the PASV command */ else { /* we use the PASV command */ #if 0 char *mode[] = { "EPSV", "LPSV", "PASV", NULL }; int results[] = { 229, 228, 227, 0 }; #else char *mode[] = { "PASV", NULL }; int results[] = { 227, 0 }; #endif int modeoff; ftpsendf(data->firstsocket, conn, "PASV"); for (modeoff = 0; mode[modeoff]; modeoff++) { ftpsendf(data->firstsocket, conn, mode[modeoff]); nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); if(nread < 0) if(nread < 0) return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED; if(ftpcode != 227) { if (ftpcode == results[modeoff]) break; } if (!mode[modeoff]) { 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 { else if (strcmp(mode[modeoff], "PASV") == 0) { int ip[4]; int ip[4]; int port[2]; int port[2]; unsigned short newport; /* remote port, not necessary the local one */ unsigned short newport; /* remote port, not necessary the local one */ unsigned short connectport; /* the local port connect() should use! */ unsigned short connectport; /* the local port connect() should use! */ char newhost[32]; char newhost[32]; #ifdef ENABLE_IPV6 struct addrinfo *res; #else struct hostent *he; struct hostent *he; #endif char *str=buf,*ip_addr; char *str=buf,*ip_addr; char *hostdataptr=NULL; char *hostdataptr=NULL; Loading Loading @@ -863,20 +1051,78 @@ CURLcode _ftp(struct connectdata *conn) * proxy again here. We already have the name info for it since the * proxy again here. We already have the name info for it since the * previous lookup. * previous lookup. */ */ #ifdef ENABLE_IPV6 res = conn->res; #else he = conn->hp; he = conn->hp; #endif connectport = connectport = (unsigned short)data->port; /* we connect to the proxy's port */ (unsigned short)data->port; /* we connect to the proxy's port */ } } else { else { /* normal, direct, ftp connection */ /* normal, direct, ftp connection */ #ifdef ENABLE_IPV6 res = Curl_getaddrinfo(data, newhost, newport); if(!res) #else he = Curl_gethost(data, newhost, &hostdataptr); he = Curl_gethost(data, newhost, &hostdataptr); if(!he) { if(!he) #endif { failf(data, "Can't resolve new host %s", newhost); failf(data, "Can't resolve new host %s", newhost); return CURLE_FTP_CANT_GET_HOST; return CURLE_FTP_CANT_GET_HOST; } } connectport = newport; /* we connect to the remote port */ connectport = newport; /* we connect to the remote port */ } } #ifdef ENABLE_IPV6 data->secondarysocket = -1; for (ai = res; ai; ai = ai->ai_next) { /* XXX for now, we can do IPv4 only */ if (ai->ai_family != AF_INET) continue; data->secondarysocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (data->secondarysocket < 0) continue; if(data->bits.verbose) { char hbuf[NI_MAXHOST]; char nbuf[NI_MAXHOST]; char sbuf[NI_MAXSERV]; #ifdef NI_WITHSCOPEID const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID; #else const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; #endif if (getnameinfo(res->ai_addr, res->ai_addrlen, nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), niflags)) { snprintf(nbuf, sizeof(nbuf), "?"); snprintf(sbuf, sizeof(sbuf), "?"); } if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, 0)) { infof(data, "Connecting to %s port %s\n", nbuf, sbuf); } else { infof(data, "Connecting to %s (%s) port %s\n", hbuf, nbuf, sbuf); } } if (connect(data->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) { close(data->secondarysocket); data->secondarysocket = -1; continue; } break; } if (data->secondarysocket < 0) { failf(data, strerror(errno)); return CURLE_FTP_CANT_RECONNECT; } #else data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0); data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0); memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memset((char *) &serv_addr, '\0', sizeof(serv_addr)); Loading Loading @@ -971,6 +1217,7 @@ CURLcode _ftp(struct connectdata *conn) } } return CURLE_FTP_CANT_RECONNECT; return CURLE_FTP_CANT_RECONNECT; } } #endif /*ENABLE_IPV6*/ if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) { /* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */ Loading @@ -979,6 +1226,8 @@ CURLcode _ftp(struct connectdata *conn) if(CURLE_OK != result) if(CURLE_OK != result) return result; return result; } } } else { return CURLE_FTP_CANT_RECONNECT; } } } } /* we have the (new) data connection ready */ /* we have the (new) data connection ready */ Loading
lib/hostip.c +23 −0 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,29 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len) return (addr); return (addr); } } #ifdef ENABLE_IPV6 struct addrinfo *Curl_getaddrinfo(struct UrlData *data, char *hostname, int port) { struct addrinfo hints, *res; int error; char sbuf[NI_MAXSERV]; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; snprintf(sbuf, sizeof(sbuf), "%d", port); error = getaddrinfo(hostname, sbuf, &hints, &res); if (error) { infof(data, "getaddrinfo(3) failed for %s\n", hostname); return NULL; } return res; } #endif /* The original code to this function was once stolen from the Dancer source /* The original code to this function was once stolen from the Dancer source code, written by Bjorn Reese, it has since been patched and modified code, written by Bjorn Reese, it has since been patched and modified considerably. */ considerably. */ Loading