X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=windows%2Fwinnet.c;h=fdb83c806ca8f34df85388a8e5a45b0ec73ba204;hb=a063e522970946bf7d5dc052079d7773c0dee76d;hp=b6c9fa61a2ddaf3e004d869845fd90d6f2eadb0c;hpb=19fba3fe550785b2584264a59d3dccea81077451;p=PuTTY.git diff --git a/windows/winnet.c b/windows/winnet.c index b6c9fa61..fdb83c80 100644 --- a/windows/winnet.c +++ b/windows/winnet.c @@ -53,7 +53,6 @@ struct Socket_tag { char *error; SOCKET s; Plug plug; - void *private_ptr; bufchain output_data; int connected; int writable; @@ -82,6 +81,8 @@ struct SockAddr_tag { int refcount; char *error; int resolved; + int namedpipe; /* indicates that this SockAddr is phony, holding a Windows + * named pipe pathname instead of a network address */ #ifndef NO_IPV6 struct addrinfo *ais; /* Addresses IPv6 style. */ #endif @@ -159,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, @@ -173,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, @@ -287,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); @@ -296,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); @@ -505,6 +512,7 @@ SockAddr sk_namelookup(const char *host, char **canonicalname, #ifndef NO_IPV6 ret->ais = NULL; #endif + ret->namedpipe = FALSE; ret->addresses = NULL; ret->resolved = FALSE; ret->refcount = 1; @@ -525,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 @@ -611,6 +625,7 @@ SockAddr sk_nonamelookup(const char *host) #ifndef NO_IPV6 ret->ais = NULL; #endif + ret->namedpipe = FALSE; ret->addresses = NULL; ret->naddresses = 0; ret->refcount = 1; @@ -619,6 +634,23 @@ SockAddr sk_nonamelookup(const char *host) return ret; } +SockAddr sk_namedpipe_addr(const char *pipename) +{ + SockAddr ret = snew(struct SockAddr_tag); + ret->error = NULL; + ret->resolved = FALSE; +#ifndef NO_IPV6 + ret->ais = NULL; +#endif + ret->namedpipe = TRUE; + ret->addresses = NULL; + ret->naddresses = 0; + ret->refcount = 1; + strncpy(ret->hostname, pipename, lenof(ret->hostname)); + ret->hostname[lenof(ret->hostname)-1] = '\0'; + return ret; +} + int sk_nextaddr(SockAddr addr, SockAddrStep *step) { #ifndef NO_IPV6 @@ -672,6 +704,11 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen) } } +int sk_addr_needs_port(SockAddr addr) +{ + return addr->namedpipe ? FALSE : TRUE; +} + int sk_hostname_is_local(const char *name) { return !strcmp(name, "localhost") || @@ -828,10 +865,9 @@ static void sk_tcp_close(Socket s); static int sk_tcp_write(Socket s, const char *data, int len); 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_private_ptr(Socket s, void *ptr); -static void *sk_tcp_get_private_ptr(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); @@ -844,10 +880,9 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug) sk_tcp_write_oob, sk_tcp_write_eof, sk_tcp_flush, - sk_tcp_set_private_ptr, - sk_tcp_get_private_ptr, sk_tcp_set_frozen, - sk_tcp_socket_error + sk_tcp_socket_error, + sk_tcp_peer_info, }; DWORD err; @@ -1094,10 +1129,9 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, sk_tcp_write_oob, sk_tcp_write_eof, sk_tcp_flush, - sk_tcp_set_private_ptr, - sk_tcp_get_private_ptr, sk_tcp_set_frozen, - sk_tcp_socket_error + sk_tcp_socket_error, + sk_tcp_peer_info, }; Actual_Socket ret; @@ -1147,10 +1181,9 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, sk_tcp_write_oob, sk_tcp_write_eof, sk_tcp_flush, - sk_tcp_set_private_ptr, - sk_tcp_get_private_ptr, sk_tcp_set_frozen, - sk_tcp_socket_error + sk_tcp_socket_error, + sk_tcp_peer_info, }; SOCKET s; @@ -1224,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 @@ -1692,22 +1739,6 @@ int select_result(WPARAM wParam, LPARAM lParam) return 1; } -/* - * Each socket abstraction contains a `void *' private field in - * which the client can keep state. - */ -static void sk_tcp_set_private_ptr(Socket sock, void *ptr) -{ - Actual_Socket s = (Actual_Socket) sock; - s->private_ptr = ptr; -} - -static void *sk_tcp_get_private_ptr(Socket sock) -{ - Actual_Socket s = (Actual_Socket) sock; - return s->private_ptr; -} - /* * Special error values are returned from sk_namelookup and sk_new * if there's a problem. These functions extract an error message, @@ -1723,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;