X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/7674964da3b8972a1ec6467470bbb6e3484c19b8..062af27bcc7ffd6d9d82d4022d625e53dc962351:/unix/uxnet.c diff --git a/unix/uxnet.c b/unix/uxnet.c index b7c20cff..71c45151 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -26,8 +26,6 @@ # define X11_UNIX_PATH "/tmp/.X11-unix/X" #endif -#define ipv4_is_loopback(addr) (inet_netof(addr) == IN_LOOPBACKNET) - struct Socket_tag { struct socket_function_table *fn; /* the above variable absolutely *must* be the first in this structure */ @@ -277,6 +275,32 @@ int sk_hostname_is_local(char *name) return !strcmp(name, "localhost"); } +#define ipv4_is_loopback(addr) \ + (((addr).s_addr & htonl(0xff000000)) == htonl(0x7f000000)) + +static int sockaddr_is_loopback(struct sockaddr *sa) +{ + struct sockaddr_in *sin; +#ifndef NO_IPV6 + struct sockaddr_in6 *sin6; +#endif + + switch (sa->sa_family) { + case AF_INET: + sin = (struct sockaddr_in *)sa; + return ipv4_is_loopback(sin->sin_addr); +#ifndef NO_IPV6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *)sa; + return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr); +#endif + case AF_LOCAL: + return TRUE; + default: + return FALSE; + } +} + int sk_address_is_local(SockAddr addr) { @@ -284,14 +308,7 @@ int sk_address_is_local(SockAddr addr) return 0; /* we don't know; assume not */ else { #ifndef NO_IPV6 - if (addr->family == AF_INET) - return ipv4_is_loopback( - ((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr); - else if (addr->family == AF_INET6) - return IN6_IS_ADDR_LOOPBACK( - &((struct sockaddr_in6 *)addr->ai->ai_addr)->sin6_addr); - else - return 0; + return sockaddr_is_loopback(addr->ai->ai_addr); #else struct in_addr a; assert(addr->family == AF_INET); @@ -705,16 +722,19 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, i #ifndef NO_IPV6 hints.ai_flags = AI_NUMERICHOST; hints.ai_family = address_family; - hints.ai_socktype = 0; + hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; + assert(port >= 0 && port <= 99999); sprintf(portstr, "%d", port); retcode = getaddrinfo(srcaddr, portstr, &hints, &ai); - addr = ai->ai_addr; - addrlen = ai->ai_addrlen; + if (retcode == 0) { + addr = ai->ai_addr; + addrlen = ai->ai_addrlen; + } #else memset(&a,'\0',sizeof(struct sockaddr_in)); a.sin_family = AF_INET; @@ -1007,17 +1027,22 @@ static int net_select_result(int fd, int event) * On a listening socket, the readability event means a * connection is ready to be accepted. */ - struct sockaddr_in isa; - int addrlen = sizeof(struct sockaddr_in); +#ifdef NO_IPV6 + struct sockaddr_in ss; +#else + struct sockaddr_storage ss; +#endif + socklen_t addrlen = sizeof(ss); int t; /* socket of connection */ - memset(&isa, 0, sizeof(struct sockaddr_in)); - t = accept(s->s,(struct sockaddr *)&isa,(socklen_t *) &addrlen); + memset(&ss, 0, addrlen); + t = accept(s->s, (struct sockaddr *)&ss, &addrlen); if (t < 0) { break; } - if (s->localhost_only && !ipv4_is_loopback(isa.sin_addr)) { + if (s->localhost_only && + !sockaddr_is_loopback((struct sockaddr *)&ss)) { close(t); /* someone let nonlocal through?! */ } else if (plug_accepting(s->plug, t)) { close(t); /* denied or error */