]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/winnet.c
Make some static text in GTK dialogs selectable.
[PuTTY.git] / windows / winnet.c
index f4507240ff5497248117a929b90936c6d65596f7..fa2de80967565e91cd7161512fd2646f7d563bfc 100644 (file)
@@ -50,7 +50,7 @@ struct SockAddrStep_tag {
 struct Socket_tag {
     const struct socket_function_table *fn;
     /* the above variable absolutely *must* be the first in this structure */
-    char *error;
+    const char *error;
     SOCKET s;
     Plug plug;
     bufchain output_data;
@@ -138,7 +138,7 @@ static int cmpfortree(void *av, void *bv)
 static int cmpforsearch(void *av, void *bv)
 {
     Actual_Socket b = (Actual_Socket) bv;
-    unsigned long as = (unsigned long) av, bs = (unsigned long) b->s;
+    uintptr_t as = (uintptr_t) av, bs = (uintptr_t) b->s;
     if (as < bs)
        return -1;
     if (as > bs)
@@ -160,6 +160,8 @@ DECL_WINDOWS_FUNCTION(static, struct servent FAR *, getservbyname,
                      (const char FAR *, const char FAR *));
 DECL_WINDOWS_FUNCTION(static, unsigned long, inet_addr, (const char FAR *));
 DECL_WINDOWS_FUNCTION(static, char FAR *, inet_ntoa, (struct in_addr));
+DECL_WINDOWS_FUNCTION(static, const char FAR *, inet_ntop,
+                      (int, void FAR *, char *, size_t));
 DECL_WINDOWS_FUNCTION(static, int, connect,
                      (SOCKET, const struct sockaddr FAR *, int));
 DECL_WINDOWS_FUNCTION(static, int, bind,
@@ -174,6 +176,8 @@ DECL_WINDOWS_FUNCTION(static, int, ioctlsocket,
                      (SOCKET, long, u_long FAR *));
 DECL_WINDOWS_FUNCTION(static, SOCKET, accept,
                      (SOCKET, struct sockaddr FAR *, int FAR *));
+DECL_WINDOWS_FUNCTION(static, int, getpeername,
+                     (SOCKET, struct sockaddr FAR *, int FAR *));
 DECL_WINDOWS_FUNCTION(static, int, recv, (SOCKET, char FAR *, int, int));
 DECL_WINDOWS_FUNCTION(static, int, WSAIoctl,
                      (SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD,
@@ -288,6 +292,7 @@ void sk_init(void)
     GET_WINDOWS_FUNCTION(winsock_module, getservbyname);
     GET_WINDOWS_FUNCTION(winsock_module, inet_addr);
     GET_WINDOWS_FUNCTION(winsock_module, inet_ntoa);
+    GET_WINDOWS_FUNCTION(winsock_module, inet_ntop);
     GET_WINDOWS_FUNCTION(winsock_module, connect);
     GET_WINDOWS_FUNCTION(winsock_module, bind);
     GET_WINDOWS_FUNCTION(winsock_module, setsockopt);
@@ -297,6 +302,7 @@ void sk_init(void)
     GET_WINDOWS_FUNCTION(winsock_module, shutdown);
     GET_WINDOWS_FUNCTION(winsock_module, ioctlsocket);
     GET_WINDOWS_FUNCTION(winsock_module, accept);
+    GET_WINDOWS_FUNCTION(winsock_module, getpeername);
     GET_WINDOWS_FUNCTION(winsock_module, recv);
     GET_WINDOWS_FUNCTION(winsock_module, WSAIoctl);
 
@@ -356,7 +362,7 @@ static int errstring_compare(void *av, void *bv)
 
 static tree234 *errstrings = NULL;
 
-char *winsock_error_string(int error)
+const char *winsock_error_string(int error)
 {
     const char prefix[] = "Network error: ";
     struct errstring *es;
@@ -472,8 +478,8 @@ char *winsock_error_string(int error)
                            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                            es->text + bufused, bufsize - bufused, NULL)) {
             sprintf(es->text + bufused,
-                    "Windows error code %d (and FormatMessage returned %d)", 
-                    error, GetLastError());
+                    "Windows error code %d (and FormatMessage returned %u)",
+                    error, (unsigned int)GetLastError());
         } else {
             int len = strlen(es->text);
             if (len > 0 && es->text[len-1] == '\n')
@@ -527,7 +533,13 @@ SockAddr sk_namelookup(const char *host, char **canonicalname,
            memset(&hints, 0, sizeof(hints));
            hints.ai_family = hint_family;
            hints.ai_flags = AI_CANONNAME;
-           if ((err = p_getaddrinfo(host, NULL, &hints, &ret->ais)) == 0)
+            {
+                /* strip [] on IPv6 address literals */
+                char *trimmed_host = host_strduptrim(host);
+                err = p_getaddrinfo(trimmed_host, NULL, &hints, &ret->ais);
+                sfree(trimmed_host);
+            }
+           if (err == 0)
                ret->resolved = TRUE;
        } else
 #endif
@@ -855,6 +867,7 @@ static int sk_tcp_write_oob(Socket s, const char *data, int len);
 static void sk_tcp_write_eof(Socket s);
 static void sk_tcp_set_frozen(Socket s, int is_frozen);
 static const char *sk_tcp_socket_error(Socket s);
+static char *sk_tcp_peer_info(Socket s);
 
 extern char *do_select(SOCKET skt, int startup);
 
@@ -868,7 +881,8 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
        sk_tcp_write_eof,
        sk_tcp_flush,
        sk_tcp_set_frozen,
-       sk_tcp_socket_error
+       sk_tcp_socket_error,
+       sk_tcp_peer_info,
     };
 
     DWORD err;
@@ -1116,7 +1130,8 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
        sk_tcp_write_eof,
        sk_tcp_flush,
        sk_tcp_set_frozen,
-       sk_tcp_socket_error
+       sk_tcp_socket_error,
+       sk_tcp_peer_info,
     };
 
     Actual_Socket ret;
@@ -1156,8 +1171,8 @@ 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,
-                     int orig_address_family)
+Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
+                      int local_host_only, int orig_address_family)
 {
     static const struct socket_function_table fn_table = {
        sk_tcp_plug,
@@ -1167,7 +1182,8 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only,
        sk_tcp_write_eof,
        sk_tcp_flush,
        sk_tcp_set_frozen,
-       sk_tcp_socket_error
+       sk_tcp_socket_error,
+       sk_tcp_peer_info,
     };
 
     SOCKET s;
@@ -1241,15 +1257,29 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only,
        if (address_family == AF_INET6) {
            memset(&a6, 0, sizeof(a6));
            a6.sin6_family = AF_INET6;
-           /* FIXME: srcaddr is ignored for IPv6, because I (SGT) don't
-            * know how to do it. :-)
-            * (jeroen:) saddr is specified as an address.. eg 2001:db8::1
-            * Thus we need either a parser that understands [2001:db8::1]:80
-            * style addresses and/or enhance this to understand hostnames too. */
            if (local_host_only)
                a6.sin6_addr = in6addr_loopback;
            else
                a6.sin6_addr = in6addr_any;
+            if (srcaddr != NULL && p_getaddrinfo) {
+                struct addrinfo hints;
+                struct addrinfo *ai;
+                int err;
+
+                memset(&hints, 0, sizeof(hints));
+                hints.ai_family = AF_INET6;
+                hints.ai_flags = 0;
+                {
+                    /* strip [] on IPv6 address literals */
+                    char *trimmed_addr = host_strduptrim(srcaddr);
+                    err = p_getaddrinfo(trimmed_addr, NULL, &hints, &ai);
+                    sfree(trimmed_addr);
+                }
+                if (err == 0 && ai->ai_family == AF_INET6) {
+                    a6.sin6_addr =
+                        ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
+                }
+            }
            a6.sin6_port = p_htons(port);
        } else
 #endif
@@ -1628,7 +1658,7 @@ int select_result(WPARAM wParam, LPARAM lParam)
        ret = p_recv(s->s, buf, sizeof(buf), MSG_OOB);
        noise_ultralight(ret);
        if (ret <= 0) {
-           char *str = (ret == 0 ? "Internal networking trouble" :
+           const char *str = (ret == 0 ? "Internal networking trouble" :
                         winsock_error_string(p_WSAGetLastError()));
            /* We're inside the Windows frontend here, so we know
             * that the frontend handle is unnecessary. */
@@ -1724,6 +1754,38 @@ static const char *sk_tcp_socket_error(Socket sock)
     return s->error;
 }
 
+static char *sk_tcp_peer_info(Socket sock)
+{
+    Actual_Socket s = (Actual_Socket) sock;
+#ifdef NO_IPV6
+    struct sockaddr_in addr;
+#else
+    struct sockaddr_storage addr;
+#endif
+    int addrlen = sizeof(addr);
+    char buf[INET6_ADDRSTRLEN];
+
+    if (p_getpeername(s->s, (struct sockaddr *)&addr, &addrlen) < 0)
+        return NULL;
+
+    if (((struct sockaddr *)&addr)->sa_family == AF_INET) {
+        return dupprintf
+            ("%s:%d",
+             p_inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr),
+             (int)p_ntohs(((struct sockaddr_in *)&addr)->sin_port));
+#ifndef NO_IPV6
+    } else if (((struct sockaddr *)&addr)->sa_family == AF_INET6) {
+        return dupprintf
+            ("[%s]:%d",
+             p_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
+                         buf, sizeof(buf)),
+             (int)p_ntohs(((struct sockaddr_in6 *)&addr)->sin6_port));
+#endif
+    } else {
+        return NULL;
+    }
+}
+
 static void sk_tcp_set_frozen(Socket sock, int is_frozen)
 {
     Actual_Socket s = (Actual_Socket) sock;