OSDN Git Service

* fhandler_socket.cc (fhandler_socket::bind): Don't run explicit
authorcorinna <corinna>
Tue, 8 Jul 2008 20:12:46 +0000 (20:12 +0000)
committercorinna <corinna>
Tue, 8 Jul 2008 20:12:46 +0000 (20:12 +0000)
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.

winsup/cygwin/ChangeLog
winsup/cygwin/fhandler_socket.cc
winsup/cygwin/net.cc
winsup/cygwin/wincap.cc
winsup/cygwin/wincap.h

index 368ffb4..9df84c2 100644 (file)
@@ -1,5 +1,16 @@
 2008-07-08  Corinna Vinschen  <corinna@vinschen.de>
 
+       * 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.
+
+2008-07-08  Corinna Vinschen  <corinna@vinschen.de>
+
        * net.cc (ipv6_inited): Make NO_COPY.
 
 2008-07-02  Corinna Vinschen  <corinna@vinschen.de>
index c0df1fb..2a39d38 100644 (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))
                {
index ded37aa..8be3219 100644 (file)
@@ -649,8 +649,16 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
       if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
        optname = convert_ws1_ip_optname (optname);
 
-      res = setsockopt (fh->get_socket (), level, optname,
-                       (const char *) optval, optlen);
+      /* On systems supporting "enhanced socket security (2K3 and later),
+        the default behaviour of socket binding is equivalent to the POSIX
+        behaviour with SO_REUSEADDR.  Setting SO_REUSEADDR would only result
+        in wrong behaviour.  See also fhandler_socket::bind(). */
+      if (level == SOL_SOCKET && optname == SO_REUSEADDR
+         && wincap.has_enhanced_socket_security ())
+       res = 0;
+      else
+       res = setsockopt (fh->get_socket (), level, optname,
+                         (const char *) optval, optlen);
 
       if (optlen == 4)
        syscall_printf ("setsockopt optval=%x", *(long *) optval);
index cf44dcc..f2a3ef1 100644 (file)
@@ -33,6 +33,7 @@ static NO_COPY wincaps wincap_unknown = {
   has_disabled_user_tos_setting:false,
   has_fileid_dirinfo:false,
   has_exclusiveaddruse:false,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:true,
@@ -64,6 +65,7 @@ static NO_COPY wincaps wincap_nt4 = {
   has_disabled_user_tos_setting:false,
   has_fileid_dirinfo:false,
   has_exclusiveaddruse:false,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:true,
@@ -95,6 +97,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
   has_disabled_user_tos_setting:false,
   has_fileid_dirinfo:false,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:true,
@@ -126,6 +129,7 @@ static NO_COPY wincaps wincap_2000 = {
   has_disabled_user_tos_setting:true,
   has_fileid_dirinfo:true,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:true,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:true,
@@ -157,6 +161,7 @@ static NO_COPY wincaps wincap_2000sp4 = {
   has_disabled_user_tos_setting:true,
   has_fileid_dirinfo:true,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:true,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:true,
@@ -188,6 +193,7 @@ static NO_COPY wincaps wincap_xp = {
   has_disabled_user_tos_setting:true,
   has_fileid_dirinfo:true,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:false,
@@ -219,6 +225,7 @@ static NO_COPY wincaps wincap_xpsp1 = {
   has_disabled_user_tos_setting:true,
   has_fileid_dirinfo:true,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:false,
@@ -250,6 +257,7 @@ static NO_COPY wincaps wincap_xpsp2 = {
   has_disabled_user_tos_setting:true,
   has_fileid_dirinfo:true,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:false,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:false,
@@ -281,6 +289,7 @@ static NO_COPY wincaps wincap_2003 = {
   has_disabled_user_tos_setting:true,
   has_fileid_dirinfo:true,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:true,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:false,
   needs_logon_sid_in_sid_list:false,
@@ -312,6 +321,7 @@ static NO_COPY wincaps wincap_vista = {
   has_disabled_user_tos_setting:true,
   has_fileid_dirinfo:true,
   has_exclusiveaddruse:true,
+  has_enhanced_socket_security:true,
   has_buggy_restart_scan:false,
   has_mandatory_integrity_control:true,
   needs_logon_sid_in_sid_list:false,
index 2035ecc..7028402 100644 (file)
@@ -31,6 +31,7 @@ struct wincaps
   unsigned has_disabled_user_tos_setting               : 1;
   unsigned has_fileid_dirinfo                          : 1;
   unsigned has_exclusiveaddruse                                : 1;
+  unsigned has_enhanced_socket_security                        : 1;
   unsigned has_buggy_restart_scan                      : 1;
   unsigned has_mandatory_integrity_control             : 1;
   unsigned needs_logon_sid_in_sid_list                 : 1;
@@ -78,6 +79,7 @@ public:
   bool IMPLEMENT (has_disabled_user_tos_setting)
   bool IMPLEMENT (has_fileid_dirinfo)
   bool IMPLEMENT (has_exclusiveaddruse)
+  bool IMPLEMENT (has_enhanced_socket_security)
   bool IMPLEMENT (has_buggy_restart_scan)
   bool IMPLEMENT (has_mandatory_integrity_control)
   bool IMPLEMENT (needs_logon_sid_in_sid_list)