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