]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Add workaround for Win32 to fix MS bug with UDP sockets.
authorDanny Mayer <mayer@ntp.org>
Wed, 11 Jun 2003 22:44:49 +0000 (18:44 -0400)
committerDanny Mayer <mayer@ntp.org>
Wed, 11 Jun 2003 22:44:49 +0000 (18:44 -0400)
See KB Q263823.

bk: 3ee7b0e13mfNsyMopxSCRFsTGgxQPg

ntpd/ntp_io.c
ports/winnt/include/isc/win32os.h [new file with mode: 0644]
ports/winnt/libisc/win32os.c [new file with mode: 0644]
ports/winnt/libntp/libntp.dsp

index 74f086a7d904493708135a713fd2cf7331591960..55cc571b9901417690f39fcae6ce57341d6f79fd 100644 (file)
@@ -56,6 +56,18 @@ extern int listen_to_virtual_ips;
 
 #if defined(SYS_WINNT)
 #include <transmitbuff.h>
+#include <isc/win32os.h>
+/*
+ * Define this macro to control the behavior of connection
+ * resets on UDP sockets.  See Microsoft KnowledgeBase Article Q263823
+ * for details.
+ * NOTE: This requires that Windows 2000 systems install Service Pack 2
+ * or later.
+ */
+#ifndef SIO_UDP_CONNRESET 
+#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) 
+#endif
+
 #endif
 
 /*
@@ -138,6 +150,36 @@ int        create_wildcards        P((u_short));
 isc_boolean_t address_okay     P((isc_interface_t *));
 void   convert_isc_if          P((isc_interface_t *, struct interface *, u_short));
 
+#ifdef SYS_WINNT
+/*
+ * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
+ * to not work correctly, returning a WSACONNRESET error when a WSASendTo
+ * fails with an "ICMP port unreachable" response and preventing the
+ * socket from using the WSARecvFrom in subsequent operations.
+ * The function below fixes this, but requires that Windows 2000
+ * Service Pack 2 or later be installed on the system.  NT 4.0
+ * systems are not affected by this and work correctly.
+ * See Microsoft Knowledge Base Article Q263823 for details of this.
+ */
+isc_result_t
+connection_reset_fix(SOCKET fd) {
+       DWORD dwBytesReturned = 0;
+       BOOL  bNewBehavior = FALSE;
+       DWORD status;
+
+       if(isc_win32os_majorversion() < 5)
+               return (ISC_R_SUCCESS); /*  NT 4.0 has no problem */
+
+       /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */
+       status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
+                         sizeof(bNewBehavior), NULL, 0,
+                         &dwBytesReturned, NULL, NULL);
+       if (status != SOCKET_ERROR)
+               return (ISC_R_SUCCESS);
+       else
+               return (ISC_R_UNEXPECTED);
+}
+#endif
 /*
  * init_io - initialize I/O data structures and call socket creation routine
  */
@@ -970,6 +1012,11 @@ open_socket(
                exit(1);
                /*NOTREACHED*/
        }
+       if (connection_reset_fix(fd) != ISC_R_SUCCESS) {
+               netsyslog(LOG_ERR, "connection_reset_fix(fd) failed on address %s: %m",
+                       stoa(addr));
+       }
+
 #endif /* SYS_WINNT */
 
        /* set SO_REUSEADDR since we will be binding the same port
diff --git a/ports/winnt/include/isc/win32os.h b/ports/winnt/include/isc/win32os.h
new file mode 100644 (file)
index 0000000..6379456
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: win32os.h,v 1.2 2002/08/03 01:36:24 mayer Exp $ */
+
+#ifndef ISC_WIN32OS_H
+#define ISC_WIN32OS_H 1
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Return the number of CPUs available on the system, or 1 if this cannot
+ * be determined.
+ */
+
+unsigned int
+isc_win32os_majorversion(void);
+/*
+ * Major Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_minorversion(void);
+/*
+ * Minor Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackmajor(void);
+/*
+ * Major Version of the Service Pack for O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackminor(void);
+/*
+ * Minor Version of the Service Pack for O/S.
+ */
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+                    unsigned int updatemajor, unsigned int updateminor);
+
+/*
+ * Checks the current version of the operating system with the
+ * supplied version information.
+ * Returns:
+ * -1  if less than the version information supplied
+ *  0   if equal to all of the version information supplied
+ * +1   if greater than the version information supplied
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_OS_H */
diff --git a/ports/winnt/libisc/win32os.c b/ports/winnt/libisc/win32os.c
new file mode 100644 (file)
index 0000000..05ca09e
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: win32os.c,v 1.2 2002/08/03 01:36:24 mayer Exp $ */
+
+#include <windows.h>
+
+#include <isc/win32os.h>
+
+static BOOL bInit = FALSE;
+static OSVERSIONINFOEX osVer;
+
+static void
+initialize_action(void) {
+       BOOL bSuccess;
+
+       if (bInit)
+               return; 
+       /*
+        * NOTE: VC++ 6.0 gets this function declaration wrong
+        * so we compensate by casting the argument
+        */
+       osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+       bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+
+       /*
+        * Versions of NT before NT4.0 SP6 did not return the
+        * extra info that the EX structure provides and returns
+        * a failure so we need to retry with the old structure.
+        */
+       if(!bSuccess) {
+               osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+               bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+       }
+       bInit = TRUE;
+}
+
+unsigned int
+isc_win32os_majorversion(void) {
+       initialize_action();
+       return ((unsigned int)osVer.dwMajorVersion);
+}
+
+unsigned int
+isc_win32os_minorversion(void) {
+       initialize_action();
+       return ((unsigned int)osVer.dwMinorVersion);
+}
+
+unsigned int
+isc_win32os_servicepackmajor(void) {
+       initialize_action();
+       return ((unsigned int)osVer.wServicePackMajor);
+}
+
+unsigned int
+isc_win32os_servicepackminor(void) {
+       initialize_action();
+       return ((unsigned int)osVer.wServicePackMinor);
+}
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+                    unsigned int spmajor, unsigned int spminor) {
+
+       initialize_action();
+
+       if (major < isc_win32os_majorversion())
+               return (1);
+       if (major > isc_win32os_majorversion())
+               return (-1);
+       if (minor < isc_win32os_minorversion())
+               return (1);
+       if (minor > isc_win32os_minorversion())
+               return (-1);
+       if (spmajor < isc_win32os_servicepackmajor())
+               return (1);
+       if (spmajor > isc_win32os_servicepackmajor())
+               return (-1);
+       if (spminor < isc_win32os_servicepackminor())
+               return (1);
+       if (spminor > isc_win32os_servicepackminor())
+               return (-1);
+
+       /* Exact */
+       return (0);
+}
\ No newline at end of file
index 8cd426de10e25ebc50123aa3086270a9d7ccad21..5fae5a6b260bc47b6e4b041610aefaa23c1366f8 100644 (file)
@@ -401,6 +401,10 @@ SOURCE=..\..\..\libntp\utvtoa.c
 # End Source File
 # Begin Source File
 
+SOURCE=..\libisc\win32os.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\..\libntp\ymd2yd.c
 # End Source File
 # End Group
@@ -579,6 +583,10 @@ SOURCE=..\include\transmitbuff.h
 
 SOURCE=..\include\win32_io.h
 # End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\win32os.h
+# End Source File
 # End Group
 # Begin Group "Generated Files"