Improve buffer handling in Windows sk_getaddr() -- we were passing
[u/mdw/putty] / windows / winnet.c
index 3848916..9d93baa 100644 (file)
@@ -167,6 +167,7 @@ DECL_WINSOCK_FUNCTION(static, u_long, ntohl, (u_long));
 DECL_WINSOCK_FUNCTION(static, u_long, htonl, (u_long));
 DECL_WINSOCK_FUNCTION(static, u_short, htons, (u_short));
 DECL_WINSOCK_FUNCTION(static, u_short, ntohs, (u_short));
+DECL_WINSOCK_FUNCTION(static, int, gethostname, (char *, int));
 DECL_WINSOCK_FUNCTION(static, struct hostent FAR *, gethostbyname,
                      (const char FAR *));
 DECL_WINSOCK_FUNCTION(static, struct servent FAR *, getservbyname,
@@ -203,7 +204,7 @@ DECL_WINSOCK_FUNCTION(static, int, getnameinfo,
 DECL_WINSOCK_FUNCTION(static, char *, gai_strerror, (int ecode));
 DECL_WINSOCK_FUNCTION(static, int, WSAAddressToStringA,
                      (LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFO,
-                      LPTSTR, LPDWORD));
+                      LPSTR, LPDWORD));
 #endif
 
 static HMODULE winsock_module = NULL;
@@ -295,6 +296,7 @@ void sk_init(void)
     GET_WINSOCK_FUNCTION(winsock_module, htonl);
     GET_WINSOCK_FUNCTION(winsock_module, htons);
     GET_WINSOCK_FUNCTION(winsock_module, ntohs);
+    GET_WINSOCK_FUNCTION(winsock_module, gethostname);
     GET_WINSOCK_FUNCTION(winsock_module, gethostbyname);
     GET_WINSOCK_FUNCTION(winsock_module, getservbyname);
     GET_WINSOCK_FUNCTION(winsock_module, inet_addr);
@@ -333,7 +335,8 @@ void sk_cleanup(void)
        sktree = NULL;
     }
 
-    p_WSACleanup();
+    if (p_WSACleanup)
+       p_WSACleanup();
     if (winsock_module)
        FreeLibrary(winsock_module);
 #ifndef NO_IPV6
@@ -426,10 +429,8 @@ SockAddr sk_namelookup(const char *host, char **canonicalname,
 {
     SockAddr ret = snew(struct SockAddr_tag);
     unsigned long a;
-    struct hostent *h = NULL;
     char realhost[8192];
     int hint_family;
-    int err;
 
     /* Default to IPv4. */
     hint_family = (address_family == ADDRTYPE_IPV4 ? AF_INET :
@@ -449,6 +450,8 @@ SockAddr sk_namelookup(const char *host, char **canonicalname,
     *realhost = '\0';
 
     if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) {
+       struct hostent *h = NULL;
+       int err;
 #ifndef NO_IPV6
        /*
         * Use getaddrinfo when it's available
@@ -581,11 +584,19 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen)
 
 #ifndef NO_IPV6
     if (step.ai) {
+       int err = 0;
        if (p_WSAAddressToStringA) {
-           p_WSAAddressToStringA(step.ai->ai_addr, step.ai->ai_addrlen,
-                                 NULL, buf, &buflen);
+           DWORD dwbuflen = buflen;
+           err = p_WSAAddressToStringA(step.ai->ai_addr, step.ai->ai_addrlen,
+                                       NULL, buf, &dwbuflen);
        } else
-           strncpy(buf, "IPv6", buflen);
+           err = -1;
+       if (err) {
+           strncpy(buf, addr->hostname, buflen);
+           if (!buf[0])
+               strncpy(buf, "<unknown>", buflen);
+           buf[buflen-1] = '\0';
+       }
     } else
 #endif
     if (SOCKADDR_FAMILY(addr, step) == AF_INET) {
@@ -602,7 +613,9 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen)
 
 int sk_hostname_is_local(char *name)
 {
-    return !strcmp(name, "localhost");
+    return !strcmp(name, "localhost") ||
+          !strcmp(name, "::1") ||
+          !strncmp(name, "127.", 4);
 }
 
 static INTERFACE_INFO local_interfaces[16];
@@ -1682,6 +1695,22 @@ int net_service_lookup(char *service)
        return 0;
 }
 
+char *get_hostname(void)
+{
+    int len = 128;
+    char *hostname = NULL;
+    do {
+       len *= 2;
+       hostname = sresize(hostname, len, char);
+       if (p_gethostname(hostname, len) < 0) {
+           sfree(hostname);
+           hostname = NULL;
+           break;
+       }
+    } while (strlen(hostname) >= len-1);
+    return hostname;
+}
+
 SockAddr platform_get_x11_unix_address(const char *display, int displaynum,
                                       char **canonicalname)
 {