]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/winnet.c
Key rollover: rewrite the PGP keys manual appendix.
[PuTTY.git] / windows / winnet.c
index 1a5a76f1d1c5dade5e4bab351661ecab8f94f36d..fdb83c806ca8f34df85388a8e5a45b0ec73ba204 100644 (file)
@@ -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);
 
@@ -861,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);
 
@@ -874,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;
@@ -1122,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;
@@ -1173,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;
@@ -1247,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
@@ -1730,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;