1 /* This file implements i/o calls that are specific to Windows */
2
3 #include <config.h>
4 #include <stdio.h>
5 #include "ntp_fp.h"
6 #include "ntp_net.h"
7 #include "ntp_stdlib.h"
8 #include "ntp_syslog.h"
9 #include "win32_io.h"
10 #include <isc/win32os.h>
11
12 /*
13 * Define this macro to control the behavior of connection
14 * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823
15 * for details.
16 * Based on that article, it is surprising that a much newer winsock2.h
17 * does not define SIO_UDP_CONNRESET (the one that comes with VS 2008).
18 * NOTE: This requires that Windows 2000 systems install Service Pack 2
19 * or later.
20 */
21 #ifndef SIO_UDP_CONNRESET
22 #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
23 #endif
24
25 void
InitSockets(void)26 InitSockets(
27 void
28 )
29 {
30 WORD wVersionRequested;
31 WSADATA wsaData;
32 int err;
33
34 /* Need Winsock 2.0 or better */
35 wVersionRequested = MAKEWORD(2, 0);
36
37 err = WSAStartup(wVersionRequested, &wsaData);
38 if ( err != 0 ) {
39 SetLastError(err);
40 mfprintf(stderr, "No usable winsock: %m\n");
41 SetLastError(err);
42 msyslog(LOG_ERR, "No usable winsock: %m");
43 exit(1);
44 }
45 }
46
47 /*
48 * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
49 * to not work correctly, returning a WSACONNRESET error when a WSASendTo
50 * fails with an "ICMP port unreachable" response and preventing the
51 * socket from using the WSARecvFrom in subsequent operations.
52 * The function below fixes this, but requires that Windows 2000
53 * Service Pack 2 or later be installed on the system. NT 4.0
54 * systems are not affected by this and work correctly.
55 * See Microsoft Knowledge Base Article Q263823 for details of this.
56 */
57 void
connection_reset_fix(SOCKET fd,sockaddr_u * addr)58 connection_reset_fix(
59 SOCKET fd,
60 sockaddr_u * addr
61 )
62 {
63 DWORD dw;
64 BOOL bNewBehavior = FALSE;
65 DWORD status;
66
67 /*
68 * disable bad behavior using IOCTL: SIO_UDP_CONNRESET
69 * NT 4.0 has no problem
70 */
71 if (isc_win32os_majorversion() >= 5) {
72 status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
73 sizeof(bNewBehavior), NULL, 0,
74 &dw, NULL, NULL);
75 if (SOCKET_ERROR == status)
76 msyslog(LOG_ERR,
77 "connection_reset_fix() failed for address %s: %m",
78 stoa(addr));
79 }
80 }
81
82