From: Danny Mayer Date: Wed, 11 Jun 2003 22:44:49 +0000 (-0400) Subject: Add workaround for Win32 to fix MS bug with UDP sockets. X-Git-Tag: NTP_4_1_80_RC1~3^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=01c97a7b5f0ecc080de45d28eb7a2bd969fc7c97;p=thirdparty%2Fntp.git Add workaround for Win32 to fix MS bug with UDP sockets. See KB Q263823. bk: 3ee7b0e13mfNsyMopxSCRFsTGgxQPg --- diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index 74f086a7d..55cc571b9 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -56,6 +56,18 @@ extern int listen_to_virtual_ips; #if defined(SYS_WINNT) #include +#include +/* + * 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 index 000000000..63794565b --- /dev/null +++ b/ports/winnt/include/isc/win32os.h @@ -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_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 index 000000000..05ca09e35 --- /dev/null +++ b/ports/winnt/libisc/win32os.c @@ -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 + +#include + +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 diff --git a/ports/winnt/libntp/libntp.dsp b/ports/winnt/libntp/libntp.dsp index 8cd426de1..5fae5a6b2 100644 --- a/ports/winnt/libntp/libntp.dsp +++ b/ports/winnt/libntp/libntp.dsp @@ -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"