From f332f141021e027d603d2adf62cebaedd469575f Mon Sep 17 00:00:00 2001 From: Marc Hoersken Date: Mon, 10 Sep 2012 12:44:37 +0200 Subject: socks.c: Added support for IPv6 connections through SOCKSv5 proxy --- docs/KNOWN_BUGS | 1 - lib/socks.c | 65 ++++++++++++++++++++++++++++++--------------------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS index 4601d48da..d36382740 100644 --- a/docs/KNOWN_BUGS +++ b/docs/KNOWN_BUGS @@ -163,7 +163,6 @@ may have been fixed since this was written! to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867 23. SOCKS-related problems: - A) libcurl doesn't support SOCKS for IPv6. B) libcurl doesn't support FTPS over a SOCKS proxy. E) libcurl doesn't support active FTP over a SOCKS proxy diff --git a/lib/socks.c b/lib/socks.c index 43e6d95f6..e55964a4c 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -371,6 +371,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name, bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE; const size_t hostname_len = strlen(hostname); ssize_t packetsize = 0; + int len; /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ if(!socks5_resolve_local && hostname_len > 255) { @@ -474,7 +475,6 @@ CURLcode Curl_SOCKS5(const char *proxy_name, else if(socksreq[1] == 2) { /* Needs user name and password */ size_t userlen, pwlen; - int len; if(proxy_name && proxy_password) { userlen = strlen(proxy_name); pwlen = strlen(proxy_password); @@ -554,31 +554,22 @@ CURLcode Curl_SOCKS5(const char *proxy_name, } /* Authentication is complete, now specify destination to the proxy */ - socksreq[0] = 5; /* version (SOCKS5) */ - socksreq[1] = 1; /* connect */ - socksreq[2] = 0; /* must be zero */ + len = 0; + socksreq[len++] = 5; /* version (SOCKS5) */ + socksreq[len++] = 1; /* connect */ + socksreq[len++] = 0; /* must be zero */ if(!socks5_resolve_local) { - packetsize = (ssize_t)(5 + hostname_len + 2); - - socksreq[3] = 3; /* ATYP: domain name = 3 */ - socksreq[4] = (char) hostname_len; /* address length */ - memcpy(&socksreq[5], hostname, hostname_len); /* address bytes w/o NULL */ - - /* PORT MSB */ - socksreq[hostname_len+5] = (unsigned char)((remote_port >> 8) & 0xff); - /* PORT LSB */ - socksreq[hostname_len+6] = (unsigned char)(remote_port & 0xff); + socksreq[len++] = 3; /* ATYP: domain name = 3 */ + socksreq[len++] = (char) hostname_len; /* address length */ + memcpy(&socksreq[len], hostname, hostname_len); /* address bytes w/o NULL */ + len += hostname_len; } else { struct Curl_dns_entry *dns; - Curl_addrinfo *hp=NULL; + Curl_addrinfo *hp = NULL; int rc = Curl_resolv(conn, hostname, remote_port, &dns); - packetsize = 10; - - socksreq[3] = 1; /* IPv4 = 1 */ - if(rc == CURLRESOLV_ERROR) return CURLE_COULDNT_RESOLVE_HOST; @@ -596,16 +587,26 @@ CURLcode Curl_SOCKS5(const char *proxy_name, if(dns) hp=dns->addr; if(hp) { - char buf[64]; - unsigned short ip[4]; - Curl_printable_address(hp, buf, sizeof(buf)); + struct sockaddr_in *saddr_in; + struct sockaddr_in6 *saddr_in6; + int i; + + if(hp->ai_family == AF_INET) { + socksreq[len++] = 1; /* IPv4 = 1 */ + + saddr_in = (struct sockaddr_in*)hp->ai_addr; + for(i = 0; i < 4; i++) { + socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i]; + infof(data, "%d\n", socksreq[len-1]); + } + } + else if(hp->ai_family == AF_INET6) { + socksreq[len++] = 4; /* IPv6 = 4 */ - if(4 == sscanf( buf, "%hu.%hu.%hu.%hu", - &ip[0], &ip[1], &ip[2], &ip[3])) { - socksreq[4] = (unsigned char)ip[0]; - socksreq[5] = (unsigned char)ip[1]; - socksreq[6] = (unsigned char)ip[2]; - socksreq[7] = (unsigned char)ip[3]; + saddr_in6 = (struct sockaddr_in6*)hp->ai_addr; + for(i = 0; i < 16; i++) { + socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i]; + } } else hp = NULL; /* fail! */ @@ -617,11 +618,13 @@ CURLcode Curl_SOCKS5(const char *proxy_name, hostname); return CURLE_COULDNT_RESOLVE_HOST; } - - socksreq[8] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ - socksreq[9] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ } + socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */ + socksreq[len++] = (unsigned char)(remote_port & 0xff); /* PORT LSB */ + + packetsize = len; + #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) if(conn->socks5_gssapi_enctype) { failf(data, "SOCKS5 gssapi protection not yet implemented."); -- cgit v1.2.3