From a784b8e5d1e8a886accf0a9206198333e6b356f4 Mon Sep 17 00:00:00 2001 From: corinna Date: Mon, 14 Jul 2008 15:56:10 +0000 Subject: [PATCH] * autoload.cc (GetExtendedTcpTable): Define. * fhandler_socket.cc (address_in_use): Take const struct sockaddr pointer as argument. Implement additional AF_INET6 table check. (fhandler_socket::bind): Drop AF_INET test before calling address_in_use. * net.cc (ipv4_getnameinfo): Return EAI_FAMILY instead of 1 if called with unsupported af_family. --- winsup/cygwin/ChangeLog | 10 ++++++ winsup/cygwin/autoload.cc | 1 + winsup/cygwin/fhandler_socket.cc | 75 ++++++++++++++++++++++++++++++---------- winsup/cygwin/net.cc | 2 +- 4 files changed, 68 insertions(+), 20 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 31a8657589..7bbf33addb 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2008-07-14 Corinna Vinschen + + * autoload.cc (GetExtendedTcpTable): Define. + * fhandler_socket.cc (address_in_use): Take const struct sockaddr + pointer as argument. Implement additional AF_INET6 table check. + (fhandler_socket::bind): Drop AF_INET test before calling + address_in_use. + * net.cc (ipv4_getnameinfo): Return EAI_FAMILY instead of 1 if + called with unsupported af_family. + 2008-07-12 Eric Blake Fix usage of recently fixed Interlocked* functions. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 80228e24eb..ac1bf7104e 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -397,6 +397,7 @@ LoadDLLfunc (WSAWaitForMultipleEvents, 20, ws2_32) // 50 = ERROR_NOT_SUPPORTED. Returned if OS doesn't supprot iphlpapi funcs LoadDLLfuncEx2 (GetAdaptersAddresses, 20, iphlpapi, 1, 50) +LoadDLLfuncEx2 (GetExtendedTcpTable, 24, iphlpapi, 1, 50) LoadDLLfuncEx2 (GetIfEntry, 4, iphlpapi, 1, 50) LoadDLLfuncEx2 (GetIpAddrTable, 12, iphlpapi, 1, 50) LoadDLLfuncEx2 (GetIpForwardTable, 12, iphlpapi, 1, 50) diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 2a39d387eb..6756bf513c 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -769,24 +769,62 @@ fhandler_socket::link (const char *newpath) } static inline bool -address_in_use (struct sockaddr_in *addr) +address_in_use (const struct sockaddr *addr) { - PMIB_TCPTABLE tab; - PMIB_TCPROW entry; - DWORD size = 0, i; - - if (GetTcpTable (NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER) + switch (addr->sa_family) { - tab = (PMIB_TCPTABLE) alloca (size); - if (!GetTcpTable (tab, &size, FALSE)) - { - for (i = tab->dwNumEntries, entry = tab->table; i > 0; --i, ++entry) - if (entry->dwLocalAddr == addr->sin_addr.s_addr - && entry->dwLocalPort == addr->sin_port - && entry->dwState >= MIB_TCP_STATE_LISTEN - && entry->dwState <= MIB_TCP_STATE_LAST_ACK) - return true; - } + case AF_INET: + { + PMIB_TCPTABLE tab; + PMIB_TCPROW entry; + DWORD size = 0, i; + struct sockaddr_in *in = (struct sockaddr_in *) addr; + + if (GetTcpTable (NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER) + { + tab = (PMIB_TCPTABLE) alloca (size += 16 * sizeof (PMIB_TCPROW)); + if (!GetTcpTable (tab, &size, FALSE)) + for (i = tab->dwNumEntries, entry = tab->table; i > 0; + --i, ++entry) + if (entry->dwLocalAddr == in->sin_addr.s_addr + && entry->dwLocalPort == in->sin_port + && entry->dwState >= MIB_TCP_STATE_LISTEN + && entry->dwState <= MIB_TCP_STATE_LAST_ACK) + return true; + } + } + break; + case AF_INET6: + { + /* This test works on XP SP2 and above which should cover almost + all IPv6 users... */ + PMIB_TCP6TABLE_OWNER_PID tab; + PMIB_TCP6ROW_OWNER_PID entry; + DWORD size = 0, i; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) addr; + + if (GetExtendedTcpTable (NULL, &size, FALSE, AF_INET6, + TCP_TABLE_OWNER_PID_ALL, 0) + == ERROR_INSUFFICIENT_BUFFER) + { + tab = (PMIB_TCP6TABLE_OWNER_PID) + alloca (size += 16 * sizeof (PMIB_TCP6ROW_OWNER_PID)); + if (!GetExtendedTcpTable (tab, &size, FALSE, AF_INET6, + TCP_TABLE_OWNER_PID_ALL, 0)) + for (i = tab->dwNumEntries, entry = tab->table; i > 0; + --i, ++entry) + if (IN6_ARE_ADDR_EQUAL (entry->ucLocalAddr, + in6->sin6_addr.s6_addr) + /* FIXME: Is testing for the scope required. too?!? */ + && entry->dwLocalPort == in6->sin6_port + && entry->dwState >= MIB_TCP_STATE_LISTEN + && entry->dwState <= MIB_TCP_STATE_LAST_ACK) + return true; + } + } + break; + default: + break; } return false; } @@ -932,10 +970,9 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen) systems is never to set SO_REUSEADDR but only to note that it has been set for the above SO_EXCLUSIVEADDRUSE setting. See setsockopt() in net.cc. */ - if (name->sa_family == AF_INET - && get_socket_type () == SOCK_STREAM + if (get_socket_type () == SOCK_STREAM && wincap.has_ip_helper_lib () - && address_in_use ((struct sockaddr_in *) name)) + && address_in_use (name)) { debug_printf ("Local address in use, don't bind"); set_errno (EADDRINUSE); diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 8be32197c0..09194ce8b6 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -3765,7 +3765,7 @@ ipv4_getnameinfo (const struct sockaddr *sa, socklen_t salen, #endif default: - return (1); + return (EAI_FAMILY); } } -- 2.11.0