summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-07-14 15:56:11 +0000
committerCorinna Vinschen <corinna@vinschen.de>2008-07-14 15:56:11 +0000
commit88d1b6df9404ee846a455fffb7bef7623010b1aa (patch)
treecc123cd6cbc84f75e79b7759b90934a7be300de0
parentc0bb6b5bd611885d9576a01c6cc57a2c8d205640 (diff)
downloadcygnal-88d1b6df9404ee846a455fffb7bef7623010b1aa.tar.gz
cygnal-88d1b6df9404ee846a455fffb7bef7623010b1aa.tar.bz2
cygnal-88d1b6df9404ee846a455fffb7bef7623010b1aa.zip
* 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.
-rw-r--r--winsup/cygwin/ChangeLog10
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/fhandler_socket.cc75
-rw-r--r--winsup/cygwin/net.cc2
4 files changed, 68 insertions, 20 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 31a865758..7bbf33add 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,13 @@
+2008-07-14 Corinna Vinschen <corinna@vinschen.de>
+
+ * 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 <ebb9@byu.net>
Fix usage of recently fixed Interlocked* functions.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 80228e24e..ac1bf7104 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 2a39d387e..6756bf513 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 8be32197c..09194ce8b 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);
}
}