* fhandler_socket.cc (fhandler_socket::bind): Don't run explicit

local socket test in SO_REUSEADDR case on systems supporting
	enhanced socket security.  Explain why.  Only call address_in_use
	for AF_INET sockets.
	* net.cc (cygwin_setsockopt): Don't call setsockopt to set SO_REUSEADDR
	on systems supporting enhanced socket security.  Add comment.
	* wincap.h (wincaps::has_enhanced_socket_security): New element.
	* wincap.cc: Implement above element throughout.
This commit is contained in:
Corinna Vinschen
2008-07-08 20:12:46 +00:00
parent b8fbf5d4c4
commit 23672785ee
5 changed files with 50 additions and 7 deletions

View File

@@ -911,17 +911,29 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
(const char *) &on, sizeof on);
debug_printf ("%d = setsockopt (SO_EXCLUSIVEADDRUSE), %E", ret);
}
else
else if (!wincap.has_enhanced_socket_security ())
{
debug_printf ("SO_REUSEADDR set");
/* There's a bug in SO_REUSEADDR handling in WinSock.
Per standards, we must not be able to reuse a complete
duplicate of a local TCP address (same IP, same port),
even if SO_REUSEADDR has been set. That's unfortunately
possible in WinSock. So we're testing here if the local
address is already in use and don't bind, if so. This
only works for OSes with IP Helper support. */
if (get_socket_type () == SOCK_STREAM
possible in WinSock.
So we're testing here if the local address is already in
use and don't bind, if so. This only works for OSes with
IP Helper support and is, of course, still prone to races.
However, we don't have to do this on systems supporting
"enhanced socket security" (2K3 and later). On these
systems the default binding behaviour is exactly as you'd
expect for SO_REUSEADDR, while setting SO_REUSEADDR re-enables
the wrong behaviour. So all we have to do on these newer
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
&& wincap.has_ip_helper_lib ()
&& address_in_use ((struct sockaddr_in *) name))
{