diff options
author | Simon Tatham <anakin@pobox.com> | 2004-12-30 19:45:11 +0300 |
---|---|---|
committer | Simon Tatham <anakin@pobox.com> | 2004-12-30 19:45:11 +0300 |
commit | 6daf6faede46bd8aa3a39cbe59d34c987b2ea114 (patch) | |
tree | 2cc3ffe7c6bebeebc922c07e7f7317a8c346ca78 /unix | |
parent | 7573f3733f3ba896018dc7b1cdd2b3a51b450096 (diff) |
Integrate unfix.org's IPv6 patches up to level 10, with rather a lot
of polishing to bring them to what I think should in principle be
release quality. Unlike the unfix.org patches themselves, this
checkin enables IPv6 by default; if you want to leave it out, you
have to build with COMPAT=-DNO_IPV6.
I have tested that this compiles on Visual C 7 (so the nightlies
_should_ acquire IPv6 support without missing a beat), but since I
don't have IPv6 set up myself I haven't actually tested that it
_works_. It still seems to make correct IPv4 connections, but that's
all I've been able to verify for myself. Further testing is needed.
[originally from svn r5047]
[this svn revision also touched putty-wishlist]
Diffstat (limited to 'unix')
-rw-r--r-- | unix/uxnet.c | 63 | ||||
-rw-r--r-- | unix/uxplink.c | 1 |
2 files changed, 42 insertions, 22 deletions
diff --git a/unix/uxnet.c b/unix/uxnet.c index 08fb4e17..f1ef98b0 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -69,7 +69,7 @@ struct SockAddr_tag { * in this SockAddr structure. */ int family; -#ifdef IPV6 +#ifndef NO_IPV6 struct addrinfo *ai; /* Address IPv6 style. */ #else unsigned long address; /* Address IPv4 style. */ @@ -125,10 +125,10 @@ const char *error_string(int error) return strerror(error); } -SockAddr sk_namelookup(const char *host, char **canonicalname) +SockAddr sk_namelookup(const char *host, char **canonicalname, int address_family) { SockAddr ret = snew(struct SockAddr_tag); -#ifdef IPV6 +#ifndef NO_IPV6 struct addrinfo hints; int err; #else @@ -143,9 +143,9 @@ SockAddr sk_namelookup(const char *host, char **canonicalname) *realhost = '\0'; ret->error = NULL; -#ifdef IPV6 +#ifndef NO_IPV6 hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_UNSPEC; + hints.ai_family = address_family; hints.ai_socktype = 0; hints.ai_protocol = 0; hints.ai_addrlen = 0; @@ -219,7 +219,7 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen) strncpy(buf, addr->hostname, buflen); buf[buflen-1] = '\0'; } else { -#ifdef IPV6 +#ifndef NO_IPV6 if (getnameinfo(addr->ai->ai_addr, addr->ai->ai_addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST) != 0) { buf[0] = '\0'; @@ -246,7 +246,7 @@ int sk_address_is_local(SockAddr addr) if (addr->family == AF_UNSPEC) return 0; /* we don't know; assume not */ else { -#ifdef IPV6 +#ifndef NO_IPV6 if (addr->family == AF_INET) return ipv4_is_loopback( ((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr); @@ -267,7 +267,7 @@ int sk_address_is_local(SockAddr addr) int sk_addrtype(SockAddr addr) { return (addr->family == AF_INET ? ADDRTYPE_IPV4 : -#ifdef IPV6 +#ifndef NO_IPV6 addr->family == AF_INET6 ? ADDRTYPE_IPV6 : #endif ADDRTYPE_NAME); @@ -276,7 +276,7 @@ int sk_addrtype(SockAddr addr) void sk_addrcopy(SockAddr addr, char *buf) { -#ifdef IPV6 +#ifndef NO_IPV6 if (addr->family == AF_INET) memcpy(buf, &((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr, sizeof(struct in_addr)); @@ -297,7 +297,7 @@ void sk_addrcopy(SockAddr addr, char *buf) void sk_addr_free(SockAddr addr) { -#ifdef IPV6 +#ifndef NO_IPV6 if (addr->ai != NULL) freeaddrinfo(addr->ai); #endif @@ -381,7 +381,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug) { int s; -#ifdef IPV6 +#ifndef NO_IPV6 struct sockaddr_in6 a6; #endif struct sockaddr_in a; @@ -448,7 +448,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, /* BSD IP stacks need sockaddr_in zeroed before filling in */ memset(&a,'\0',sizeof(struct sockaddr_in)); -#ifdef IPV6 +#ifndef NO_IPV6 memset(&a6,'\0',sizeof(struct sockaddr_in6)); #endif @@ -459,7 +459,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, while (1) { int retcode; -#ifdef IPV6 +#ifndef NO_IPV6 if (addr->family == AF_INET6) { /* XXX use getaddrinfo to get a local address? */ a6.sin6_family = AF_INET6; @@ -501,7 +501,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, * Connect to remote address. */ switch(addr->family) { -#ifdef IPV6 +#ifndef NO_IPV6 case AF_INET: /* XXX would be better to have got getaddrinfo() to fill in the port. */ ((struct sockaddr_in *)addr->ai->ai_addr)->sin_port = @@ -564,13 +564,10 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, return (Socket) ret; } -Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) +Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int address_family) { int s; -#ifdef IPV6 -#if 0 - struct sockaddr_in6 a6; -#endif +#ifndef NO_IPV6 struct addrinfo hints, *ai; char portstr[6]; #endif @@ -598,9 +595,31 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) ret->listener = 1; /* + * Translate address_family from platform-independent constants + * into local reality. + */ + address_family = (address_family == ADDRTYPE_IPV4 ? AF_INET : + address_family == ADDRTYPE_IPV6 ? AF_INET6 : AF_UNSPEC); + +#ifndef NO_IPV6 + /* Let's default to IPv6. + * If the stack doesn't support IPv6, we will fall back to IPv4. */ + if (address_family == AF_UNSPEC) address_family = AF_INET6; +#else + /* No other choice, default to IPv4 */ + if (address_family == AF_UNSPEC) address_family = AF_INET; +#endif + + /* * Open socket. */ - s = socket(AF_INET, SOCK_STREAM, 0); + s = socket(address_family, SOCK_STREAM, 0); + + /* If the host doesn't support IPv6 try fallback to IPv4. */ + if (s < 0 && address_family == AF_INET6) { + address_family = AF_INET; + s = socket(address_family, SOCK_STREAM, 0); + } ret->s = s; if (s < 0) { @@ -614,12 +633,12 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) /* BSD IP stacks need sockaddr_in zeroed before filling in */ memset(&a,'\0',sizeof(struct sockaddr_in)); -#ifdef IPV6 +#ifndef NO_IPV6 #if 0 memset(&a6,'\0',sizeof(struct sockaddr_in6)); #endif hints.ai_flags = AI_NUMERICHOST; - hints.ai_family = AF_UNSPEC; + hints.ai_family = address_family; hints.ai_socktype = 0; hints.ai_protocol = 0; hints.ai_addrlen = 0; diff --git a/unix/uxplink.c b/unix/uxplink.c index 6f17b5a2..fdc0f666 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -227,6 +227,7 @@ static void usage(void) printf(" -A -a enable / disable agent forwarding\n"); printf(" -t -T enable / disable pty allocation\n"); printf(" -1 -2 force use of particular protocol version\n"); + printf(" -4 -6 force use of IPv4 or IPv6\n"); printf(" -C enable compression\n"); printf(" -i key private key file for authentication\n"); printf(" -s remote command is an SSH subsystem (SSH-2 only)\n"); |