* 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:
@@ -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))
|
||||
{
|
||||
|
Reference in New Issue
Block a user