1 /*
2  * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 #include <windows.h>
26 #include <winsock2.h>
27 #include <ws2tcpip.h>
28 
29 #include "sysSocket.h"
30 #include "socketTransport.h"
31 
32 typedef jboolean bool_t;
33 
34 /*
35  * Table of Windows Sockets errors, the specific exception we
36  * throw for the error, and the error text.
37  *
38  * Note that this table excludes OS dependent errors.
39  */
40 static struct {
41     int errCode;
42     const char *errString;
43 } const winsock_errors[] = {
44     { WSAEPROVIDERFAILEDINIT,   "Provider initialization failed (check %SystemRoot%)" },
45     { WSAEACCES,                "Permission denied" },
46     { WSAEADDRINUSE,            "Address already in use" },
47     { WSAEADDRNOTAVAIL,         "Cannot assign requested address" },
48     { WSAEAFNOSUPPORT,          "Address family not supported by protocol family" },
49     { WSAEALREADY,              "Operation already in progress" },
50     { WSAECONNABORTED,          "Software caused connection abort" },
51     { WSAECONNREFUSED,          "Connection refused" },
52     { WSAECONNRESET,            "Connection reset by peer" },
53     { WSAEDESTADDRREQ,          "Destination address required" },
54     { WSAEFAULT,                "Bad address" },
55     { WSAEHOSTDOWN,             "Host is down" },
56     { WSAEHOSTUNREACH,          "No route to host" },
57     { WSAEINPROGRESS,           "Operation now in progress" },
58     { WSAEINTR,                 "Interrupted function call" },
59     { WSAEINVAL,                "Invalid argument" },
60     { WSAEISCONN,               "Socket is already connected" },
61     { WSAEMFILE,                "Too many open files" },
62     { WSAEMSGSIZE,              "The message is larger than the maximum supported by the underlying transport" },
63     { WSAENETDOWN,              "Network is down" },
64     { WSAENETRESET,             "Network dropped connection on reset" },
65     { WSAENETUNREACH,           "Network is unreachable" },
66     { WSAENOBUFS,               "No buffer space available (maximum connections reached?)" },
67     { WSAENOPROTOOPT,           "Bad protocol option" },
68     { WSAENOTCONN,              "Socket is not connected" },
69     { WSAENOTSOCK,              "Socket operation on nonsocket" },
70     { WSAEOPNOTSUPP,            "Operation not supported" },
71     { WSAEPFNOSUPPORT,          "Protocol family not supported" },
72     { WSAEPROCLIM,              "Too many processes" },
73     { WSAEPROTONOSUPPORT,       "Protocol not supported" },
74     { WSAEPROTOTYPE,            "Protocol wrong type for socket" },
75     { WSAESHUTDOWN,             "Cannot send after socket shutdown" },
76     { WSAESOCKTNOSUPPORT,       "Socket type not supported" },
77     { WSAETIMEDOUT,             "Connection timed out" },
78     { WSATYPE_NOT_FOUND,        "Class type not found" },
79     { WSAEWOULDBLOCK,           "Resource temporarily unavailable" },
80     { WSAHOST_NOT_FOUND,        "Host not found" },
81     { WSA_NOT_ENOUGH_MEMORY,    "Insufficient memory available" },
82     { WSANOTINITIALISED,        "Successful WSAStartup not yet performed" },
83     { WSANO_DATA,               "Valid name, no data record of requested type" },
84     { WSANO_RECOVERY,           "This is a nonrecoverable error" },
85     { WSASYSNOTREADY,           "Network subsystem is unavailable" },
86     { WSATRY_AGAIN,             "Nonauthoritative host not found" },
87     { WSAVERNOTSUPPORTED,       "Winsock.dll version out of range" },
88     { WSAEDISCON,               "Graceful shutdown in progress" },
89     { WSA_OPERATION_ABORTED,    "Overlapped operation aborted" },
90 };
91 
92 
93 /*
94  * Initialize Windows Sockets API support
95  */
96 BOOL WINAPI
DllMain(HINSTANCE hinst,DWORD reason,LPVOID reserved)97 DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
98 {
99     WSADATA wsadata;
100 
101     switch (reason) {
102         case DLL_PROCESS_ATTACH:
103             if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) {
104                 return FALSE;
105             }
106             break;
107 
108         case DLL_PROCESS_DETACH:
109             WSACleanup();
110             break;
111 
112         default:
113             break;
114     }
115     return TRUE;
116 }
117 
118 /*
119  * If we get a nonnull function pointer it might still be the case
120  * that some other thread is in the process of initializing the socket
121  * function pointer table, but our pointer should still be good.
122  */
123 int
dbgsysListen(int fd,int backlog)124 dbgsysListen(int fd, int backlog) {
125     return listen(fd, backlog);
126 }
127 
128 int
dbgsysConnect(int fd,struct sockaddr * name,socklen_t namelen)129 dbgsysConnect(int fd, struct sockaddr *name, socklen_t namelen) {
130     int rv = connect(fd, name, namelen);
131     if (rv == SOCKET_ERROR) {
132         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK) {
133             return DBG_EINPROGRESS;
134         }
135     }
136     return rv;
137 }
138 
dbgsysFinishConnect(int fd,int timeout)139 int dbgsysFinishConnect(int fd, int timeout) {
140     int rv;
141     struct timeval t;
142     fd_set wr, ex;
143 
144     t.tv_sec = timeout / 1000;
145     t.tv_usec = (timeout % 1000) * 1000;
146 
147     FD_ZERO(&wr);
148     FD_ZERO(&ex);
149     FD_SET((unsigned int)fd, &wr);
150     FD_SET((unsigned int)fd, &ex);
151 
152     rv = select(fd+1, 0, &wr, &ex, &t);
153     if (rv == 0) {
154         return SYS_ERR;     /* timeout */
155     }
156 
157     /*
158      * Check if there was an error - this is preferable to check if
159      * the socket is writable because some versions of Windows don't
160      * report a connected socket as being writable.
161      */
162     if (!FD_ISSET(fd, &ex)) {
163         return SYS_OK;
164     }
165 
166     /*
167      * Unable to establish connection - to get the reason we must
168      * call getsockopt.
169      */
170     return SYS_ERR;
171 }
172 
173 
174 int
dbgsysAccept(int fd,struct sockaddr * name,socklen_t * namelen)175 dbgsysAccept(int fd, struct sockaddr *name, socklen_t *namelen) {
176     return (int)accept(fd, name, namelen);
177 }
178 
179 int
dbgsysRecvFrom(int fd,char * buf,size_t nBytes,int flags,struct sockaddr * from,socklen_t * fromlen)180 dbgsysRecvFrom(int fd, char *buf, size_t nBytes,
181                   int flags, struct sockaddr *from, socklen_t *fromlen) {
182     return recvfrom(fd, buf, (int)nBytes, flags, from, fromlen);
183 }
184 
185 int
dbgsysSendTo(int fd,char * buf,size_t len,int flags,struct sockaddr * to,socklen_t tolen)186 dbgsysSendTo(int fd, char *buf, size_t len,
187                 int flags, struct sockaddr *to, socklen_t tolen) {
188     return sendto(fd, buf, (int)len, flags, to, tolen);
189 }
190 
191 int
dbgsysRecv(int fd,char * buf,size_t nBytes,int flags)192 dbgsysRecv(int fd, char *buf, size_t nBytes, int flags) {
193     return recv(fd, buf, (int) nBytes, flags);
194 }
195 
196 int
dbgsysSend(int fd,char * buf,size_t nBytes,int flags)197 dbgsysSend(int fd, char *buf, size_t nBytes, int flags) {
198     return send(fd, buf, (int)nBytes, flags);
199 }
200 
201 int
dbgsysGetAddrInfo(const char * hostname,const char * service,const struct addrinfo * hints,struct addrinfo ** result)202 dbgsysGetAddrInfo(const char *hostname, const char *service,
203                   const struct addrinfo *hints,
204                   struct addrinfo **result) {
205     return getaddrinfo(hostname, service, hints, result);
206 }
207 
208 void
dbgsysFreeAddrInfo(struct addrinfo * info)209 dbgsysFreeAddrInfo(struct addrinfo *info) {
210     freeaddrinfo(info);
211 }
212 
213 unsigned short
dbgsysHostToNetworkShort(unsigned short hostshort)214 dbgsysHostToNetworkShort(unsigned short hostshort) {
215     return htons(hostshort);
216 }
217 
218 int
dbgsysSocket(int domain,int type,int protocol)219 dbgsysSocket(int domain, int type, int protocol) {
220   int fd = (int)socket(domain, type, protocol);
221   if (fd != SOCKET_ERROR) {
222     SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
223   }
224   return fd;
225 }
226 
227 int
dbgsysSocketClose(int fd)228 dbgsysSocketClose(int fd) {
229     struct linger l;
230     int len = sizeof(l);
231 
232     if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) {
233         if (l.l_onoff == 0) {
234             shutdown(fd, SD_SEND);
235         }
236     }
237     return closesocket(fd);
238 }
239 
240 /* Additions to original follow */
241 
242 int
dbgsysBind(int fd,struct sockaddr * name,socklen_t namelen)243 dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) {
244     return bind(fd, name, namelen);
245 }
246 
247 
248 uint32_t
dbgsysHostToNetworkLong(uint32_t hostlong)249 dbgsysHostToNetworkLong(uint32_t hostlong) {
250     return (uint32_t)htonl((u_long)hostlong);
251 }
252 
253 unsigned short
dbgsysNetworkToHostShort(unsigned short netshort)254 dbgsysNetworkToHostShort(unsigned short netshort) {
255     return ntohs(netshort);
256 }
257 
258 int
dbgsysGetSocketName(int fd,struct sockaddr * name,socklen_t * namelen)259 dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) {
260     return getsockname(fd, name, namelen);
261 }
262 
263 uint32_t
dbgsysNetworkToHostLong(uint32_t netlong)264 dbgsysNetworkToHostLong(uint32_t netlong) {
265     return (uint32_t)ntohl((u_long)netlong);
266 }
267 
268 /*
269  * Below Adapted from PlainSocketImpl.c, win32 version 1.18. Changed exception
270  * throws to returns of SYS_ERR; we should improve the error codes
271  * eventually. Changed java objects to values the debugger back end can
272  * more easily deal with.
273  */
274 
275 int
dbgsysSetSocketOption(int fd,jint cmd,jboolean on,jvalue value)276 dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
277 {
278     if (cmd == TCP_NODELAY) {
279         struct protoent *proto = getprotobyname("TCP");
280         int tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
281         long onl = (long)on;
282 
283         if (setsockopt(fd, tcp_level, TCP_NODELAY,
284                        (char *)&onl, sizeof(long)) < 0) {
285                 return SYS_ERR;
286         }
287     } else if (cmd == SO_LINGER) {
288         struct linger arg;
289         arg.l_onoff = on;
290 
291         if(on) {
292             arg.l_linger = (unsigned short)value.i;
293             if(setsockopt(fd, SOL_SOCKET, SO_LINGER,
294                           (char*)&arg, sizeof(arg)) < 0) {
295                 return SYS_ERR;
296             }
297         } else {
298             if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
299                            (char*)&arg, sizeof(arg)) < 0) {
300                 return SYS_ERR;
301             }
302         }
303     } else if (cmd == SO_SNDBUF) {
304         jint buflen = value.i;
305         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
306                        (char *)&buflen, sizeof(buflen)) < 0) {
307             return SYS_ERR;
308         }
309     } else if (cmd == SO_REUSEADDR) {
310         /*
311          * On Windows the SO_REUSEADDR socket option doesn't implement
312          * BSD semantics. Specifically, the socket option allows multiple
313          * processes to bind to the same address/port rather than allowing
314          * a process to bind with a previous connection in the TIME_WAIT
315          * state. Hence on Windows we never enable this option for TCP
316          * option.
317          */
318         int sotype, arglen=sizeof(sotype);
319         if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) == SOCKET_ERROR) {
320             return SYS_ERR;
321         }
322         if (sotype != SOCK_STREAM) {
323             int oni = (int)on;
324             if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
325                        (char *)&oni, sizeof(oni)) == SOCKET_ERROR) {
326                 return SYS_ERR;
327             }
328         }
329     } else {
330         return SYS_ERR;
331     }
332     return SYS_OK;
333 }
334 
dbgsysConfigureBlocking(int fd,jboolean blocking)335 int dbgsysConfigureBlocking(int fd, jboolean blocking) {
336     u_long argp;
337     int result = 0;
338 
339     if (blocking == JNI_FALSE) {
340         argp = 1;
341     } else {
342         argp = 0;
343     }
344     result = ioctlsocket(fd, FIONBIO, &argp);
345     if (result == SOCKET_ERROR) {
346         return SYS_ERR;
347     } else {
348         return SYS_OK;
349     }
350 }
351 
352 int
dbgsysPoll(int fd,jboolean rd,jboolean wr,long timeout)353 dbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) {
354     int rv;
355     struct timeval t;
356     fd_set rd_tbl, wr_tbl;
357 
358     t.tv_sec = timeout / 1000;
359     t.tv_usec = (timeout % 1000) * 1000;
360 
361     FD_ZERO(&rd_tbl);
362     if (rd) {
363         FD_SET((unsigned int)fd, &rd_tbl);
364     }
365 
366     FD_ZERO(&wr_tbl);
367     if (wr) {
368         FD_SET((unsigned int)fd, &wr_tbl);
369     }
370 
371     rv = select(fd+1, &rd_tbl, &wr_tbl, 0, &t);
372     if (rv >= 0) {
373         rv = 0;
374         if (FD_ISSET(fd, &rd_tbl)) {
375             rv |= DBG_POLLIN;
376         }
377         if (FD_ISSET(fd, &wr_tbl)) {
378             rv |= DBG_POLLOUT;
379         }
380     }
381     return rv;
382 }
383 
384 int
dbgsysGetLastIOError(char * buf,jint size)385 dbgsysGetLastIOError(char *buf, jint size) {
386     int table_size = sizeof(winsock_errors) /
387                      sizeof(winsock_errors[0]);
388     int i;
389     int error = WSAGetLastError();
390 
391     /*
392      * Check table for known winsock errors
393      */
394     i=0;
395     while (i < table_size) {
396         if (error == winsock_errors[i].errCode) {
397             break;
398         }
399         i++;
400     }
401 
402     if (i < table_size) {
403         strcpy(buf, winsock_errors[i].errString);
404     } else {
405         sprintf(buf, "winsock error %d", error);
406     }
407     return 0;
408 }
409 
410 
411 int
dbgsysTlsAlloc()412 dbgsysTlsAlloc() {
413     return TlsAlloc();
414 }
415 
416 void
dbgsysTlsFree(int index)417 dbgsysTlsFree(int index) {
418     TlsFree(index);
419 }
420 
421 void
dbgsysTlsPut(int index,void * value)422 dbgsysTlsPut(int index, void *value) {
423     TlsSetValue(index, value);
424 }
425 
426 void *
dbgsysTlsGet(int index)427 dbgsysTlsGet(int index) {
428     return TlsGetValue(index);
429 }
430 
431 #define FT2INT64(ft) \
432         ((INT64)(ft).dwHighDateTime << 32 | (INT64)(ft).dwLowDateTime)
433 
434 long
dbgsysCurrentTimeMillis()435 dbgsysCurrentTimeMillis() {
436     static long fileTime_1_1_70 = 0;    /* midnight 1/1/70 */
437     SYSTEMTIME st0;
438     FILETIME   ft0;
439 
440     /* initialize on first usage */
441     if (fileTime_1_1_70 == 0) {
442         memset(&st0, 0, sizeof(st0));
443         st0.wYear  = 1970;
444         st0.wMonth = 1;
445         st0.wDay   = 1;
446         SystemTimeToFileTime(&st0, &ft0);
447         fileTime_1_1_70 = FT2INT64(ft0);
448     }
449 
450     GetSystemTime(&st0);
451     SystemTimeToFileTime(&st0, &ft0);
452 
453     return (FT2INT64(ft0) - fileTime_1_1_70) / 10000;
454 }
455