1 /*
2 * Copyright (c) 1998, 2020, 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 <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30
31 #include "jni.h"
32 #include "jdwpTransport.h"
33 #include "sysSocket.h"
34
35 #ifdef _WIN32
36 #include <winsock2.h>
37 #include <ws2tcpip.h>
38 #include <iphlpapi.h>
39 #else
40 #include <arpa/inet.h>
41 #include <sys/socket.h>
42 #include <net/if.h>
43 #endif
44
45 /*
46 * The Socket Transport Library.
47 *
48 * This module is an implementation of the Java Debug Wire Protocol Transport
49 * Service Provider Interface - see src/share/javavm/export/jdwpTransport.h.
50 */
51
52 static int serverSocketFD = -1;
53 static int socketFD = -1;
54 static jdwpTransportCallback *callback;
55 static JavaVM *jvm;
56 static int tlsIndex;
57 static jboolean initialized;
58 static struct jdwpTransportNativeInterface_ interface;
59 static jdwpTransportEnv single_env = (jdwpTransportEnv)&interface;
60
61 #define RETURN_ERROR(err, msg) \
62 if (1==1) { \
63 setLastError(err, msg); \
64 return err; \
65 }
66
67 #define RETURN_IO_ERROR(msg) RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, msg);
68
69 #define RETURN_RECV_ERROR(n) \
70 if (n == 0) { \
71 RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, "premature EOF"); \
72 } else { \
73 RETURN_IO_ERROR("recv error"); \
74 }
75
76 #define MAX_DATA_SIZE 1000
77
78 static jint recv_fully(int, char *, int);
79 static jint send_fully(int, char *, int);
80
81 /* version >= JDWPTRANSPORT_VERSION_1_1 */
82 typedef struct {
83 /* subnet and mask are stored as IPv6 addresses, IPv4 is stored as mapped IPv6 */
84 struct in6_addr subnet;
85 struct in6_addr netmask;
86 } AllowedPeerInfo;
87
88 #define STR(x) #x
89 #define MAX_PEER_ENTRIES 32
90 #define MAX_PEERS_STR STR(MAX_PEER_ENTRIES)
91 static AllowedPeerInfo _peers[MAX_PEER_ENTRIES];
92 static int _peers_cnt = 0;
93
94
95 static int allowOnlyIPv4 = 0; // reflects "java.net.preferIPv4Stack" sys. property
96 static int preferredAddressFamily = AF_INET; // "java.net.preferIPv6Addresses"
97
98 /*
99 * Record the last error for this thread.
100 */
101 static void
setLastError(jdwpTransportError err,char * newmsg)102 setLastError(jdwpTransportError err, char *newmsg) {
103 char buf[255];
104 char *msg;
105
106 /* get any I/O first in case any system calls override errno */
107 if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
108 dbgsysGetLastIOError(buf, sizeof(buf));
109 }
110
111 msg = (char *)dbgsysTlsGet(tlsIndex);
112 if (msg != NULL) {
113 (*callback->free)(msg);
114 }
115
116 if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
117 char *join_str = ": ";
118 int msg_len = (int)strlen(newmsg) + (int)strlen(join_str) +
119 (int)strlen(buf) + 3;
120 msg = (*callback->alloc)(msg_len);
121 if (msg != NULL) {
122 strcpy(msg, newmsg);
123 strcat(msg, join_str);
124 strcat(msg, buf);
125 }
126 } else {
127 msg = (*callback->alloc)((int)strlen(newmsg)+1);
128 if (msg != NULL) {
129 strcpy(msg, newmsg);
130 }
131 }
132
133 dbgsysTlsPut(tlsIndex, msg);
134 }
135
136 /*
137 * Return the last error for this thread (may be NULL)
138 */
139 static char*
getLastError()140 getLastError() {
141 return (char *)dbgsysTlsGet(tlsIndex);
142 }
143
144 /* Set options common to client and server sides */
145 static jdwpTransportError
setOptionsCommon(int domain,int fd)146 setOptionsCommon(int domain, int fd)
147 {
148 jvalue dontcare;
149 int err;
150
151 if (domain == AF_INET6) {
152 int off = 0;
153 // make the socket a dual mode socket
154 // this may fail if IPv4 is not supported - it's ok
155 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off));
156 }
157
158 dontcare.i = 0; /* keep compiler happy */
159 err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);
160 if (err < 0) {
161 RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
162 }
163
164 return JDWPTRANSPORT_ERROR_NONE;
165 }
166
167 /* Set the SO_REUSEADDR option */
168 static jdwpTransportError
setReuseAddrOption(int fd)169 setReuseAddrOption(int fd)
170 {
171 jvalue dontcare;
172 int err;
173
174 dontcare.i = 0; /* keep compiler happy */
175
176 err = dbgsysSetSocketOption(fd, SO_REUSEADDR, JNI_TRUE, dontcare);
177 if (err < 0) {
178 RETURN_IO_ERROR("setsockopt SO_REUSEADDR failed");
179 }
180
181 return JDWPTRANSPORT_ERROR_NONE;
182 }
183
184 static jdwpTransportError
handshake(int fd,jlong timeout)185 handshake(int fd, jlong timeout) {
186 const char *hello = "JDWP-Handshake";
187 char b[16];
188 int rv, helloLen, received;
189
190 if (timeout > 0) {
191 dbgsysConfigureBlocking(fd, JNI_FALSE);
192 }
193 helloLen = (int)strlen(hello);
194 received = 0;
195 while (received < helloLen) {
196 int n;
197 char *buf;
198 if (timeout > 0) {
199 rv = dbgsysPoll(fd, JNI_TRUE, JNI_FALSE, (long)timeout);
200 if (rv <= 0) {
201 setLastError(0, "timeout during handshake");
202 return JDWPTRANSPORT_ERROR_IO_ERROR;
203 }
204 }
205 buf = b;
206 buf += received;
207 n = recv_fully(fd, buf, helloLen-received);
208 if (n == 0) {
209 setLastError(0, "handshake failed - connection prematurally closed");
210 return JDWPTRANSPORT_ERROR_IO_ERROR;
211 }
212 if (n < 0) {
213 RETURN_IO_ERROR("recv failed during handshake");
214 }
215 received += n;
216 }
217 if (timeout > 0) {
218 dbgsysConfigureBlocking(fd, JNI_TRUE);
219 }
220 if (strncmp(b, hello, received) != 0) {
221 char msg[80+2*16];
222 b[received] = '\0';
223 /*
224 * We should really use snprintf here but it's not available on Windows.
225 * We can't use jio_snprintf without linking the transport against the VM.
226 */
227 sprintf(msg, "handshake failed - received >%s< - expected >%s<", b, hello);
228 setLastError(0, msg);
229 return JDWPTRANSPORT_ERROR_IO_ERROR;
230 }
231
232 if (send_fully(fd, (char*)hello, helloLen) != helloLen) {
233 RETURN_IO_ERROR("send failed during handshake");
234 }
235 return JDWPTRANSPORT_ERROR_NONE;
236 }
237
238 static int
getPortNumber(const char * s_port)239 getPortNumber(const char *s_port) {
240 u_long n;
241 char *eptr;
242
243 if (*s_port == 0) {
244 // bad address - colon with no port number in parameters
245 return -1;
246 }
247
248 n = strtoul(s_port, &eptr, 10);
249 if (eptr != s_port + strlen(s_port)) {
250 // incomplete conversion - port number contains non-digit
251 return -1;
252 }
253
254 if (n > (u_short) -1) {
255 // check that value supplied by user is less than
256 // maximum possible u_short value (65535) and
257 // will not be truncated later.
258 return -1;
259 }
260
261 return n;
262 }
263
getPort(struct sockaddr * sa)264 static unsigned short getPort(struct sockaddr *sa)
265 {
266 return dbgsysNetworkToHostShort(sa->sa_family == AF_INET
267 ? (((struct sockaddr_in*)sa)->sin_port)
268 : (((struct sockaddr_in6*)sa)->sin6_port));
269 }
270
271 /*
272 * Parses scope id.
273 * Scope id is ulong on Windows, uint32 on unix, so returns long which can be cast to uint32.
274 * On error sets last error and returns -1.
275 */
parseScopeId(const char * str)276 static long parseScopeId(const char *str) {
277 // try to handle scope as interface name
278 unsigned long scopeId = if_nametoindex(str);
279 if (scopeId == 0) {
280 // try to parse integer value
281 char *end;
282 scopeId = strtoul(str, &end, 10);
283 if (*end != '\0') {
284 setLastError(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "failed to parse scope");
285 return -1;
286 }
287 }
288 // ensure parsed value is in uint32 range
289 if (scopeId > 0xFFFFFFFF) {
290 setLastError(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "scope is out of range");
291 return -1;
292 }
293 return (long)scopeId;
294 }
295
296 /*
297 * Wrapper for dbgsysGetAddrInfo (getaddrinfo).
298 * Handles enclosing square brackets and scopes.
299 */
300 static jdwpTransportError
getAddrInfo(const char * hostname,size_t hostnameLen,const char * service,const struct addrinfo * hints,struct addrinfo ** result)301 getAddrInfo(const char *hostname, size_t hostnameLen,
302 const char *service,
303 const struct addrinfo *hints,
304 struct addrinfo **result)
305 {
306 int err = 0;
307 char *buffer = NULL;
308 long scopeId = 0;
309
310 if (hostname != NULL) {
311 char *scope = NULL;
312 // skip surrounding
313 if (hostnameLen > 2 && hostname[0] == '[' && hostname[hostnameLen - 1] == ']') {
314 hostname++;
315 hostnameLen -= 2;
316 }
317 buffer = (*callback->alloc)((int)hostnameLen + 1);
318 if (buffer == NULL) {
319 RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
320 }
321 memcpy(buffer, hostname, hostnameLen);
322 buffer[hostnameLen] = '\0';
323
324 scope = strchr(buffer, '%');
325 if (scope != NULL) {
326 // drop scope from the address
327 *scope = '\0';
328 // and parse the value
329 scopeId = parseScopeId(scope + 1);
330 if (scopeId < 0) {
331 (*callback->free)(buffer);
332 return JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT;
333 }
334 }
335 }
336
337 err = dbgsysGetAddrInfo(buffer, service, hints, result);
338
339 if (buffer != NULL) {
340 (*callback->free)(buffer);
341 }
342 if (err != 0) {
343 setLastError(err, "getaddrinfo: failed to parse address");
344 return JDWPTRANSPORT_ERROR_IO_ERROR;
345 }
346
347 if (scopeId > 0) {
348 if ((*result)->ai_family != AF_INET6) {
349 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "IPv4 address cannot contain scope");
350 }
351
352 ((struct sockaddr_in6 *)((*result)->ai_addr))->sin6_scope_id = (uint32_t)scopeId;
353 }
354
355 return JDWPTRANSPORT_ERROR_NONE;
356 }
357
358 /*
359 * Result must be released with dbgsysFreeAddrInfo.
360 */
361 static jdwpTransportError
parseAddress(const char * address,struct addrinfo ** result)362 parseAddress(const char *address, struct addrinfo **result) {
363 const char *colon;
364 size_t hostnameLen;
365 const char *port;
366 struct addrinfo hints;
367
368 *result = NULL;
369
370 /* check for host:port or port */
371 colon = strrchr(address, ':');
372 port = (colon == NULL ? address : colon + 1);
373
374 /* ensure the port is valid (getaddrinfo allows port to be empty) */
375 if (getPortNumber(port) < 0) {
376 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "invalid port number specified");
377 }
378
379 memset (&hints, 0, sizeof(hints));
380 hints.ai_family = allowOnlyIPv4 ? AF_INET : AF_UNSPEC;
381 hints.ai_socktype = SOCK_STREAM;
382 hints.ai_protocol = IPPROTO_TCP;
383 hints.ai_flags = AI_NUMERICSERV; // port must be a number
384
385 hostnameLen = (colon == NULL ? 0 : colon - address);
386 if (hostnameLen == 0) {
387 /* no hostname - use localhost address (pass NULL to getaddrinfo) */
388 address = NULL;
389 } else if (*address == '*' && hostnameLen == 1) {
390 /* *:port - listen on all interfaces
391 * use IPv6 socket (to accept IPv6 and mapped IPv4),
392 * pass hostname == NULL to getaddrinfo.
393 */
394 hints.ai_family = allowOnlyIPv4 ? AF_INET : AF_INET6;
395 #ifdef __OpenBSD__
396 hints.ai_flags |= AI_PASSIVE;
397 #else
398 hints.ai_flags |= AI_PASSIVE | (allowOnlyIPv4 ? 0 : AI_V4MAPPED | AI_ALL);
399 #endif
400 address = NULL;
401 }
402
403 return getAddrInfo(address, hostnameLen, port, &hints, result);
404 }
405
406 /*
407 * Input is sockaddr just because all clients have it.
408 */
convertIPv4ToIPv6(const struct sockaddr * addr4,struct in6_addr * addr6)409 static void convertIPv4ToIPv6(const struct sockaddr *addr4, struct in6_addr *addr6) {
410 // Implement in a platform-independent way.
411 // Spec requires in_addr has s_addr member, in6_addr has s6_addr[16] member.
412 struct in_addr *a4 = &(((struct sockaddr_in*)addr4)->sin_addr);
413 memset(addr6, 0, sizeof(*addr6)); // for safety
414
415 // Mapped address contains 80 zero bits, then 16 "1" bits, then IPv4 address (4 bytes).
416 addr6->s6_addr[10] = addr6->s6_addr[11] = 0xFF;
417 memcpy(&(addr6->s6_addr[12]), &(a4->s_addr), 4);
418 }
419
420 /*
421 * Parses address (IPv4 or IPv6), fills in result by parsed address.
422 * For IPv4 mapped IPv6 is returned in result, isIPv4 is set.
423 */
424 static jdwpTransportError
parseAllowedAddr(const char * buffer,struct in6_addr * result,int * isIPv4)425 parseAllowedAddr(const char *buffer, struct in6_addr *result, int *isIPv4) {
426 struct addrinfo hints;
427 struct addrinfo *addrInfo = NULL;
428 jdwpTransportError err;
429
430 /*
431 * To parse both IPv4 and IPv6 need to specify AF_UNSPEC family
432 * (with AF_INET6 IPv4 addresses are not parsed even with AI_V4MAPPED and AI_ALL flags).
433 */
434 memset (&hints, 0, sizeof(hints));
435 hints.ai_family = AF_UNSPEC; // IPv6 or mapped IPv4
436 hints.ai_socktype = SOCK_STREAM;
437 hints.ai_protocol = IPPROTO_TCP;
438 hints.ai_flags = AI_NUMERICHOST; // only numeric addresses, no resolution
439
440 err = getAddrInfo(buffer, strlen(buffer), NULL, &hints, &addrInfo);
441
442 if (err != JDWPTRANSPORT_ERROR_NONE) {
443 return err;
444 }
445
446 if (addrInfo->ai_family == AF_INET6) {
447 memcpy(result, &(((struct sockaddr_in6 *)(addrInfo->ai_addr))->sin6_addr), sizeof(*result));
448 *isIPv4 = 0;
449 } else { // IPv4 address - convert to mapped IPv6
450 struct in6_addr addr6;
451 convertIPv4ToIPv6(addrInfo->ai_addr, &addr6);
452 memcpy(result, &addr6, sizeof(*result));
453 *isIPv4 = 1;
454 }
455
456 dbgsysFreeAddrInfo(addrInfo);
457
458 return JDWPTRANSPORT_ERROR_NONE;
459 }
460
461 /*
462 * Parses prefix length from buffer (integer value), fills in result with corresponding net mask.
463 * For IPv4 (isIPv4 is set), maximum prefix length is 32 bit, for IPv6 - 128 bit.
464 */
465 static jdwpTransportError
parseAllowedMask(const char * buffer,int isIPv4,struct in6_addr * result)466 parseAllowedMask(const char *buffer, int isIPv4, struct in6_addr *result) {
467 int prefixLen = 0;
468 int maxValue = isIPv4 ? 32 : 128;
469 int i;
470
471 do {
472 if (*buffer < '0' || *buffer > '9') {
473 return JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT;
474 }
475 prefixLen = prefixLen * 10 + (*buffer - '0');
476 if (prefixLen > maxValue) { // avoid overflow
477 return JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT;
478 }
479 buffer++;
480 } while (*buffer != '\0');
481
482 if (isIPv4) {
483 // IPv4 are stored as mapped IPv6, prefixLen needs to be converted too
484 prefixLen += 96;
485 }
486
487 if (prefixLen == 0) {
488 return JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT;
489 }
490
491 // generate mask for prefix length
492 memset(result, 0, sizeof(*result));
493
494 // prefixLen <= 128, so we won't go over result's size
495 for (i = 0; prefixLen > 0; i++, prefixLen -= 8) {
496 if (prefixLen >= 8) {
497 // set the whole byte
498 result->s6_addr[i] = 0xFF;
499 } else {
500 // set only "prefixLen" bits
501 result->s6_addr[i] = (char)(0xFF << (8 - prefixLen));
502 }
503 }
504
505 return JDWPTRANSPORT_ERROR_NONE;
506 }
507
508 /*
509 * Internal implementation of parseAllowedPeers (requires writable buffer).
510 */
511 static jdwpTransportError
parseAllowedPeersInternal(char * buffer)512 parseAllowedPeersInternal(char *buffer) {
513 char *next;
514 int isIPv4 = 0;
515
516 do {
517 char *mask = NULL;
518 char *endOfAddr = strpbrk(buffer, "/+");
519 if (endOfAddr == NULL) {
520 // this is the last address and there is no prefix length
521 next = NULL;
522 } else {
523 next = endOfAddr + 1;
524 if (*endOfAddr == '/') {
525 // mask (prefix length) presents
526 char *endOfMask = strchr(next, '+');
527 mask = next;
528 if (endOfMask == NULL) {
529 // no more addresses
530 next = NULL;
531 } else {
532 next = endOfMask + 1;
533 *endOfMask = '\0';
534 }
535 }
536 *endOfAddr = '\0';
537 }
538
539 // parse subnet address (IPv4 is stored as mapped IPv6)
540 if (parseAllowedAddr(buffer, &(_peers[_peers_cnt].subnet), &isIPv4) != JDWPTRANSPORT_ERROR_NONE) {
541 _peers_cnt = 0;
542 fprintf(stderr, "Error in allow option: '%s'\n", buffer);
543 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
544 "invalid IP address in allow option");
545 }
546 if (mask != NULL) {
547 size_t i;
548 if (parseAllowedMask(mask, isIPv4, &(_peers[_peers_cnt].netmask)) != JDWPTRANSPORT_ERROR_NONE) {
549 _peers_cnt = 0;
550 fprintf(stderr, "Error in allow option: '%s'\n", mask);
551 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
552 "invalid netmask in allow option");
553 }
554 // for safety update subnet to satisfy the mask
555 for (i = 0; i < sizeof(_peers[_peers_cnt].subnet); i++) {
556 _peers[_peers_cnt].subnet.s6_addr[i] &= _peers[_peers_cnt].netmask.s6_addr[i];
557 }
558 } else {
559 memset(&(_peers[_peers_cnt].netmask), 0xFF, sizeof(_peers[_peers_cnt].netmask));
560 }
561 _peers_cnt++;
562 buffer = next;
563 } while (next != NULL);
564
565 return JDWPTRANSPORT_ERROR_NONE;
566 }
567
568 /*
569 * Parses 'allow' argument (fills in list of allowed peers (global _peers variable)).
570 * 'Allow' value consists of tokens separated by '+',
571 * each token contains IP address (IPv4 or IPv6) and optional prefixLength:
572 * '<addr>[/<prefixLength>]'.
573 * Example: '192.168.1.10+192.168.0.0/24'
574 * - connections are allowed from 192.168.1.10 and subnet 192.168.0.XX.
575 */
576 static jdwpTransportError
parseAllowedPeers(const char * allowed_peers,size_t len)577 parseAllowedPeers(const char *allowed_peers, size_t len) {
578 // Build a list of allowed peers from char string
579 // of format 192.168.0.10+192.168.0.0/24
580
581 // writable copy of the value
582 char *buffer = (*callback->alloc)((int)len + 1);
583 if (buffer == NULL) {
584 RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
585 }
586 memcpy(buffer, allowed_peers, len);
587 buffer[len] = '\0';
588
589 jdwpTransportError err = parseAllowedPeersInternal(buffer);
590
591 (*callback->free)(buffer);
592
593 return err;
594 }
595
596 static int
isAddressInSubnet(const struct in6_addr * address,const struct in6_addr * subnet,const struct in6_addr * mask)597 isAddressInSubnet(const struct in6_addr *address, const struct in6_addr *subnet, const struct in6_addr *mask) {
598 size_t i;
599 for (i = 0; i < sizeof(struct in6_addr); i++) {
600 if ((address->s6_addr[i] & mask->s6_addr[i]) != subnet->s6_addr[i]) {
601 return 0;
602 }
603 }
604 return 1;
605 }
606
607 static int
isPeerAllowed(struct sockaddr_storage * peer)608 isPeerAllowed(struct sockaddr_storage *peer) {
609 struct in6_addr tmp;
610 struct in6_addr *addr6;
611 int i;
612 // _peers contains IPv6 subnet and mask (IPv4 is converted to mapped IPv6)
613 if (peer->ss_family == AF_INET) {
614 convertIPv4ToIPv6((struct sockaddr *)peer, &tmp);
615 addr6 = &tmp;
616 } else {
617 addr6 = &(((struct sockaddr_in6 *)peer)->sin6_addr);
618 }
619
620 for (i = 0; i < _peers_cnt; ++i) {
621 if (isAddressInSubnet(addr6, &(_peers[i].subnet), &(_peers[i].netmask))) {
622 return 1;
623 }
624 }
625
626 return 0;
627 }
628
629 static jdwpTransportError JNICALL
socketTransport_getCapabilities(jdwpTransportEnv * env,JDWPTransportCapabilities * capabilitiesPtr)630 socketTransport_getCapabilities(jdwpTransportEnv* env,
631 JDWPTransportCapabilities* capabilitiesPtr)
632 {
633 JDWPTransportCapabilities result;
634
635 memset(&result, 0, sizeof(result));
636 result.can_timeout_attach = JNI_TRUE;
637 result.can_timeout_accept = JNI_TRUE;
638 result.can_timeout_handshake = JNI_TRUE;
639
640 *capabilitiesPtr = result;
641
642 return JDWPTRANSPORT_ERROR_NONE;
643 }
644
645 /*
646 * Starts listening on the specified addrinfo,
647 * returns listening socket and actual listening port.
648 * If the function fails and returned socket != -1, the socket should be closed.
649 */
startListening(struct addrinfo * ai,int * socket,char ** actualAddress)650 static jdwpTransportError startListening(struct addrinfo *ai, int *socket, char** actualAddress)
651 {
652 int err;
653
654 *socket = dbgsysSocket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
655 if (*socket < 0) {
656 RETURN_IO_ERROR("socket creation failed");
657 }
658
659 err = setOptionsCommon(ai->ai_family, *socket);
660 if (err) {
661 return err;
662 }
663
664 if (getPort(ai->ai_addr) != 0) {
665 /*
666 * Only need SO_REUSEADDR if we're using a fixed port. If we
667 * start seeing EADDRINUSE due to collisions in free ports
668 * then we should retry the dbgsysBind() a few times.
669 */
670 err = setReuseAddrOption(*socket);
671 if (err) {
672 return err;
673 }
674 }
675
676 err = dbgsysBind(*socket, ai->ai_addr, (socklen_t)ai->ai_addrlen);
677 if (err < 0) {
678 RETURN_IO_ERROR("bind failed");
679 }
680
681 err = dbgsysListen(*socket, 1); // only 1 debugger can attach
682 if (err < 0) {
683 RETURN_IO_ERROR("listen failed");
684 }
685
686 {
687 char buf[20];
688 struct sockaddr_storage addr;
689 socklen_t len = sizeof(addr);
690 jint portNum;
691 err = dbgsysGetSocketName(*socket, (struct sockaddr *)&addr, &len);
692 if (err != 0) {
693 RETURN_IO_ERROR("getsockname failed");
694 }
695
696 portNum = getPort((struct sockaddr *)&addr);
697 sprintf(buf, "%d", portNum);
698 *actualAddress = (*callback->alloc)((int)strlen(buf) + 1);
699 if (*actualAddress == NULL) {
700 RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
701 } else {
702 strcpy(*actualAddress, buf);
703 }
704 }
705
706 return JDWPTRANSPORT_ERROR_NONE;
707 }
708
isEqualIPv6Addr(const struct addrinfo * ai,const struct in6_addr in6Addr)709 static int isEqualIPv6Addr(const struct addrinfo *ai, const struct in6_addr in6Addr)
710 {
711 if (ai->ai_addr->sa_family == AF_INET6) {
712 const struct sockaddr_in6 sa = *((struct sockaddr_in6*) ai->ai_addr);
713 return (memcmp(&sa.sin6_addr, &in6Addr, sizeof(in6Addr)) == 0);
714 }
715 return 0;
716 }
717
718 static jdwpTransportError JNICALL
socketTransport_startListening(jdwpTransportEnv * env,const char * address,char ** actualAddress)719 socketTransport_startListening(jdwpTransportEnv* env, const char* address,
720 char** actualAddress)
721 {
722 int err;
723 struct addrinfo *addrInfo = NULL;
724 struct addrinfo *listenAddr = NULL;
725 struct addrinfo *ai = NULL;
726 struct in6_addr mappedAny = IN6ADDR_ANY_INIT;
727
728 /* no address provided */
729 if ((address == NULL) || (address[0] == '\0')) {
730 address = "0";
731 }
732
733 err = parseAddress(address, &addrInfo);
734 if (err != JDWPTRANSPORT_ERROR_NONE) {
735 return err;
736 }
737
738 // Try to find bind address of preferred address family first.
739 for (ai = addrInfo; ai != NULL; ai = ai->ai_next) {
740 if (ai->ai_family == preferredAddressFamily) {
741 listenAddr = ai;
742 break;
743 }
744 }
745
746 if (listenAddr == NULL) {
747 // No address of preferred addres family found, grab the fist one.
748 listenAddr = &(addrInfo[0]);
749 }
750
751 if (listenAddr == NULL) {
752 dbgsysFreeAddrInfo(addrInfo);
753 RETURN_ERROR(JDWPTRANSPORT_ERROR_INTERNAL, "listen failed: wrong address");
754 }
755
756 // Binding to IN6ADDR_ANY allows to serve both IPv4 and IPv6 connections,
757 // but binding to mapped INADDR_ANY (::ffff:0.0.0.0) allows to serve IPv4
758 // connections only. Make sure that IN6ADDR_ANY is preferred over
759 // mapped INADDR_ANY if preferredAddressFamily is AF_INET6 or not set.
760
761 if (preferredAddressFamily != AF_INET) {
762 inet_pton(AF_INET6, "::ffff:0.0.0.0", &mappedAny);
763
764 if (isEqualIPv6Addr(listenAddr, mappedAny)) {
765 for (ai = addrInfo; ai != NULL; ai = ai->ai_next) {
766 if (isEqualIPv6Addr(listenAddr, in6addr_any)) {
767 listenAddr = ai;
768 break;
769 }
770 }
771 }
772 }
773
774 err = startListening(listenAddr, &serverSocketFD, actualAddress);
775
776 dbgsysFreeAddrInfo(addrInfo);
777
778 if (err != JDWPTRANSPORT_ERROR_NONE) {
779 if (serverSocketFD >= 0) {
780 dbgsysSocketClose(serverSocketFD);
781 serverSocketFD = -1;
782 }
783 return err;
784 }
785
786 return JDWPTRANSPORT_ERROR_NONE;
787 }
788
789 static jdwpTransportError JNICALL
socketTransport_accept(jdwpTransportEnv * env,jlong acceptTimeout,jlong handshakeTimeout)790 socketTransport_accept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout)
791 {
792 int err = JDWPTRANSPORT_ERROR_NONE;
793 struct sockaddr_storage clientAddr;
794 socklen_t clientAddrLen;
795 jlong startTime = 0;
796
797 /*
798 * Use a default handshake timeout if not specified - this avoids an indefinite
799 * hang in cases where something other than a debugger connects to our port.
800 */
801 if (handshakeTimeout == 0) {
802 handshakeTimeout = 2000;
803 }
804
805 do {
806 /*
807 * If there is an accept timeout then we put the socket in non-blocking
808 * mode and poll for a connection.
809 */
810 if (acceptTimeout > 0) {
811 int rv;
812 dbgsysConfigureBlocking(serverSocketFD, JNI_FALSE);
813 startTime = dbgsysCurrentTimeMillis();
814 rv = dbgsysPoll(serverSocketFD, JNI_TRUE, JNI_FALSE, (long)acceptTimeout);
815 if (rv <= 0) {
816 /* set the last error here as could be overridden by configureBlocking */
817 if (rv == 0) {
818 setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "poll failed");
819 }
820 /* restore blocking state */
821 dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
822 if (rv == 0) {
823 RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "timed out waiting for connection");
824 } else {
825 return JDWPTRANSPORT_ERROR_IO_ERROR;
826 }
827 }
828 }
829
830 /*
831 * Accept the connection
832 */
833 clientAddrLen = sizeof(clientAddr);
834 socketFD = dbgsysAccept(serverSocketFD,
835 (struct sockaddr *)&clientAddr,
836 &clientAddrLen);
837 /* set the last error here as could be overridden by configureBlocking */
838 if (socketFD < 0) {
839 setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "accept failed");
840 }
841 /*
842 * Restore the blocking state - note that the accepted socket may be in
843 * blocking or non-blocking mode (platform dependent). However as there
844 * is a handshake timeout set then it will go into non-blocking mode
845 * anyway for the handshake.
846 */
847 if (acceptTimeout > 0) {
848 dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
849 }
850 if (socketFD < 0) {
851 return JDWPTRANSPORT_ERROR_IO_ERROR;
852 }
853
854 /*
855 * version >= JDWPTRANSPORT_VERSION_1_1:
856 * Verify that peer is allowed to connect.
857 */
858 if (_peers_cnt > 0) {
859 if (!isPeerAllowed(&clientAddr)) {
860 char ebuf[64] = { 0 };
861 char addrStr[INET_ADDRSTRLEN] = { 0 };
862 int err2 = getnameinfo((struct sockaddr *)&clientAddr, clientAddrLen,
863 addrStr, sizeof(addrStr), NULL, 0,
864 NI_NUMERICHOST);
865 sprintf(ebuf, "ERROR: Peer not allowed to connect: %s\n",
866 (err2 != 0) ? "<bad address>" : addrStr);
867 dbgsysSocketClose(socketFD);
868 socketFD = -1;
869 err = JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT;
870 setLastError(err, ebuf);
871 }
872 }
873
874 if (socketFD > 0) {
875 /* handshake with the debugger */
876 err = handshake(socketFD, handshakeTimeout);
877 }
878
879 /*
880 * If the handshake fails then close the connection. If there if an accept
881 * timeout then we must adjust the timeout for the next poll.
882 */
883 if (err != JDWPTRANSPORT_ERROR_NONE) {
884 fprintf(stderr, "Debugger failed to attach: %s\n", getLastError());
885 dbgsysSocketClose(socketFD);
886 socketFD = -1;
887 if (acceptTimeout > 0) {
888 long endTime = dbgsysCurrentTimeMillis();
889 acceptTimeout -= (endTime - startTime);
890 if (acceptTimeout <= 0) {
891 setLastError(JDWPTRANSPORT_ERROR_IO_ERROR,
892 "timeout waiting for debugger to connect");
893 return JDWPTRANSPORT_ERROR_IO_ERROR;
894 }
895 }
896 }
897 } while (socketFD < 0);
898
899 return JDWPTRANSPORT_ERROR_NONE;
900 }
901
902 static jdwpTransportError JNICALL
socketTransport_stopListening(jdwpTransportEnv * env)903 socketTransport_stopListening(jdwpTransportEnv *env)
904 {
905 if (serverSocketFD < 0) {
906 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "connection not open");
907 }
908 if (dbgsysSocketClose(serverSocketFD) < 0) {
909 RETURN_IO_ERROR("close failed");
910 }
911 serverSocketFD = -1;
912 return JDWPTRANSPORT_ERROR_NONE;
913 }
914
915 /*
916 * Tries to connect to the specified addrinfo, returns connected socket.
917 * If the function fails and returned socket != -1, the socket should be closed.
918 */
connectToAddr(struct addrinfo * ai,jlong timeout,int * socket)919 static jdwpTransportError connectToAddr(struct addrinfo *ai, jlong timeout, int *socket) {
920 int err;
921
922 *socket = dbgsysSocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
923 if (*socket < 0) {
924 RETURN_IO_ERROR("unable to create socket");
925 }
926
927 err = setOptionsCommon(ai->ai_family, socketFD);
928 if (err) {
929 return err;
930 }
931
932 /*
933 * We don't call setReuseAddrOption() for the non-server socket
934 * case. If we start seeing EADDRINUSE due to collisions in free
935 * ports then we should retry the dbgsysConnect() a few times.
936 */
937
938 /*
939 * To do a timed connect we make the socket non-blocking
940 * and poll with a timeout;
941 */
942 if (timeout > 0) {
943 dbgsysConfigureBlocking(socketFD, JNI_FALSE);
944 }
945
946 err = dbgsysConnect(socketFD, ai->ai_addr, (socklen_t)ai->ai_addrlen);
947
948 if (err == DBG_EINPROGRESS && timeout > 0) {
949 err = dbgsysFinishConnect(socketFD, (long)timeout);
950
951 if (err == DBG_ETIMEOUT) {
952 dbgsysConfigureBlocking(socketFD, JNI_TRUE);
953 RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "connect timed out");
954 }
955 }
956
957 if (err) {
958 RETURN_IO_ERROR("connect failed");
959 }
960
961 return err;
962 }
963
964
965 static jdwpTransportError JNICALL
socketTransport_attach(jdwpTransportEnv * env,const char * addressString,jlong attachTimeout,jlong handshakeTimeout)966 socketTransport_attach(jdwpTransportEnv* env, const char* addressString, jlong attachTimeout,
967 jlong handshakeTimeout)
968 {
969 int err;
970 int pass;
971 struct addrinfo *addrInfo = NULL;
972 struct addrinfo *ai;
973
974 if (addressString == NULL || addressString[0] == '\0') {
975 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "address is missing");
976 }
977
978 err = parseAddress(addressString, &addrInfo);
979 if (err) {
980 return err;
981 }
982
983 /* 1st pass - preferredAddressFamily (by default IPv4), 2nd pass - the rest */
984 for (pass = 0; pass < 2 && socketFD < 0; pass++) {
985 for (ai = addrInfo; ai != NULL; ai = ai->ai_next) {
986 if ((pass == 0 && ai->ai_family == preferredAddressFamily) ||
987 (pass == 1 && ai->ai_family != preferredAddressFamily))
988 {
989 err = connectToAddr(ai, attachTimeout, &socketFD);
990 if (err == JDWPTRANSPORT_ERROR_NONE) {
991 break;
992 }
993 if (socketFD >= 0) {
994 dbgsysSocketClose(socketFD);
995 socketFD = -1;
996 }
997 }
998 }
999 }
1000
1001 freeaddrinfo(addrInfo);
1002
1003 /* err from the last connectToAddr() call */
1004 if (err != 0) {
1005 return err;
1006 }
1007
1008 if (attachTimeout > 0) {
1009 dbgsysConfigureBlocking(socketFD, JNI_TRUE);
1010 }
1011
1012 err = handshake(socketFD, handshakeTimeout);
1013 if (err) {
1014 dbgsysSocketClose(socketFD);
1015 socketFD = -1;
1016 return err;
1017 }
1018
1019 return JDWPTRANSPORT_ERROR_NONE;
1020 }
1021
1022 static jboolean JNICALL
socketTransport_isOpen(jdwpTransportEnv * env)1023 socketTransport_isOpen(jdwpTransportEnv* env)
1024 {
1025 if (socketFD >= 0) {
1026 return JNI_TRUE;
1027 } else {
1028 return JNI_FALSE;
1029 }
1030 }
1031
1032 static jdwpTransportError JNICALL
socketTransport_close(jdwpTransportEnv * env)1033 socketTransport_close(jdwpTransportEnv* env)
1034 {
1035 int fd = socketFD;
1036 socketFD = -1;
1037 if (fd < 0) {
1038 return JDWPTRANSPORT_ERROR_NONE;
1039 }
1040 #ifdef _AIX
1041 /*
1042 AIX needs a workaround for I/O cancellation, see:
1043 http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
1044 ...
1045 The close subroutine is blocked until all subroutines which use the file
1046 descriptor return to usr space. For example, when a thread is calling close
1047 and another thread is calling select with the same file descriptor, the
1048 close subroutine does not return until the select call returns.
1049 ...
1050 */
1051 shutdown(fd, 2);
1052 #endif
1053 if (dbgsysSocketClose(fd) < 0) {
1054 /*
1055 * close failed - it's pointless to restore socketFD here because
1056 * any subsequent close will likely fail as well.
1057 */
1058 RETURN_IO_ERROR("close failed");
1059 }
1060 return JDWPTRANSPORT_ERROR_NONE;
1061 }
1062
1063 static jdwpTransportError JNICALL
socketTransport_writePacket(jdwpTransportEnv * env,const jdwpPacket * packet)1064 socketTransport_writePacket(jdwpTransportEnv* env, const jdwpPacket *packet)
1065 {
1066 jint len, data_len, id;
1067 /*
1068 * room for header and up to MAX_DATA_SIZE data bytes
1069 */
1070 char header[JDWP_HEADER_SIZE + MAX_DATA_SIZE];
1071 jbyte *data;
1072
1073 /* packet can't be null */
1074 if (packet == NULL) {
1075 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is NULL");
1076 }
1077
1078 len = packet->type.cmd.len; /* includes header */
1079 data_len = len - JDWP_HEADER_SIZE;
1080
1081 /* bad packet */
1082 if (data_len < 0) {
1083 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "invalid length");
1084 }
1085
1086 /* prepare the header for transmission */
1087 len = (jint)dbgsysHostToNetworkLong(len);
1088 id = (jint)dbgsysHostToNetworkLong(packet->type.cmd.id);
1089
1090 memcpy(header + 0, &len, 4);
1091 memcpy(header + 4, &id, 4);
1092 header[8] = packet->type.cmd.flags;
1093 if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1094 jshort errorCode =
1095 dbgsysHostToNetworkShort(packet->type.reply.errorCode);
1096 memcpy(header + 9, &errorCode, 2);
1097 } else {
1098 header[9] = packet->type.cmd.cmdSet;
1099 header[10] = packet->type.cmd.cmd;
1100 }
1101
1102 data = packet->type.cmd.data;
1103 /* Do one send for short packets, two for longer ones */
1104 if (data_len <= MAX_DATA_SIZE) {
1105 memcpy(header + JDWP_HEADER_SIZE, data, data_len);
1106 if (send_fully(socketFD, (char *)&header, JDWP_HEADER_SIZE + data_len) !=
1107 JDWP_HEADER_SIZE + data_len) {
1108 RETURN_IO_ERROR("send failed");
1109 }
1110 } else {
1111 memcpy(header + JDWP_HEADER_SIZE, data, MAX_DATA_SIZE);
1112 if (send_fully(socketFD, (char *)&header, JDWP_HEADER_SIZE + MAX_DATA_SIZE) !=
1113 JDWP_HEADER_SIZE + MAX_DATA_SIZE) {
1114 RETURN_IO_ERROR("send failed");
1115 }
1116 /* Send the remaining data bytes right out of the data area. */
1117 if (send_fully(socketFD, (char *)data + MAX_DATA_SIZE,
1118 data_len - MAX_DATA_SIZE) != data_len - MAX_DATA_SIZE) {
1119 RETURN_IO_ERROR("send failed");
1120 }
1121 }
1122
1123 return JDWPTRANSPORT_ERROR_NONE;
1124 }
1125
1126 static jint
recv_fully(int f,char * buf,int len)1127 recv_fully(int f, char *buf, int len)
1128 {
1129 int nbytes = 0;
1130 while (nbytes < len) {
1131 int res = dbgsysRecv(f, buf + nbytes, len - nbytes, 0);
1132 if (res < 0) {
1133 return res;
1134 } else if (res == 0) {
1135 break; /* eof, return nbytes which is less than len */
1136 }
1137 nbytes += res;
1138 }
1139 return nbytes;
1140 }
1141
1142 jint
send_fully(int f,char * buf,int len)1143 send_fully(int f, char *buf, int len)
1144 {
1145 int nbytes = 0;
1146 while (nbytes < len) {
1147 int res = dbgsysSend(f, buf + nbytes, len - nbytes, 0);
1148 if (res < 0) {
1149 return res;
1150 } else if (res == 0) {
1151 break; /* eof, return nbytes which is less than len */
1152 }
1153 nbytes += res;
1154 }
1155 return nbytes;
1156 }
1157
1158 static jdwpTransportError JNICALL
socketTransport_readPacket(jdwpTransportEnv * env,jdwpPacket * packet)1159 socketTransport_readPacket(jdwpTransportEnv* env, jdwpPacket* packet) {
1160 jint length, data_len;
1161 jint n;
1162
1163 /* packet can't be null */
1164 if (packet == NULL) {
1165 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is null");
1166 }
1167
1168 /* read the length field */
1169 n = recv_fully(socketFD, (char *)&length, sizeof(jint));
1170
1171 /* check for EOF */
1172 if (n == 0) {
1173 packet->type.cmd.len = 0;
1174 return JDWPTRANSPORT_ERROR_NONE;
1175 }
1176 if (n != sizeof(jint)) {
1177 RETURN_RECV_ERROR(n);
1178 }
1179
1180 length = (jint)dbgsysNetworkToHostLong(length);
1181 packet->type.cmd.len = length;
1182
1183
1184 n = recv_fully(socketFD,(char *)&(packet->type.cmd.id), sizeof(jint));
1185 if (n < (int)sizeof(jint)) {
1186 RETURN_RECV_ERROR(n);
1187 }
1188
1189 packet->type.cmd.id = (jint)dbgsysNetworkToHostLong(packet->type.cmd.id);
1190
1191 n = recv_fully(socketFD,(char *)&(packet->type.cmd.flags), sizeof(jbyte));
1192 if (n < (int)sizeof(jbyte)) {
1193 RETURN_RECV_ERROR(n);
1194 }
1195
1196 if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1197 n = recv_fully(socketFD,(char *)&(packet->type.reply.errorCode), sizeof(jbyte));
1198 if (n < (int)sizeof(jshort)) {
1199 RETURN_RECV_ERROR(n);
1200 }
1201
1202 /* FIXME - should the error be converted to host order?? */
1203
1204
1205 } else {
1206 n = recv_fully(socketFD,(char *)&(packet->type.cmd.cmdSet), sizeof(jbyte));
1207 if (n < (int)sizeof(jbyte)) {
1208 RETURN_RECV_ERROR(n);
1209 }
1210
1211 n = recv_fully(socketFD,(char *)&(packet->type.cmd.cmd), sizeof(jbyte));
1212 if (n < (int)sizeof(jbyte)) {
1213 RETURN_RECV_ERROR(n);
1214 }
1215 }
1216
1217 data_len = length - ((sizeof(jint) * 2) + (sizeof(jbyte) * 3));
1218
1219 if (data_len < 0) {
1220 setLastError(0, "Badly formed packet received - invalid length");
1221 return JDWPTRANSPORT_ERROR_IO_ERROR;
1222 } else if (data_len == 0) {
1223 packet->type.cmd.data = NULL;
1224 } else {
1225 packet->type.cmd.data= (*callback->alloc)(data_len);
1226
1227 if (packet->type.cmd.data == NULL) {
1228 RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
1229 }
1230
1231 n = recv_fully(socketFD,(char *)packet->type.cmd.data, data_len);
1232 if (n < data_len) {
1233 (*callback->free)(packet->type.cmd.data);
1234 RETURN_RECV_ERROR(n);
1235 }
1236 }
1237
1238 return JDWPTRANSPORT_ERROR_NONE;
1239 }
1240
1241 static jdwpTransportError JNICALL
socketTransport_getLastError(jdwpTransportEnv * env,char ** msgP)1242 socketTransport_getLastError(jdwpTransportEnv* env, char** msgP) {
1243 char *msg = (char *)dbgsysTlsGet(tlsIndex);
1244 if (msg == NULL) {
1245 return JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE;
1246 }
1247 *msgP = (*callback->alloc)((int)strlen(msg)+1);
1248 if (*msgP == NULL) {
1249 return JDWPTRANSPORT_ERROR_OUT_OF_MEMORY;
1250 }
1251 strcpy(*msgP, msg);
1252 return JDWPTRANSPORT_ERROR_NONE;
1253 }
1254
1255 static jdwpTransportError JNICALL
socketTransport_setConfiguration(jdwpTransportEnv * env,jdwpTransportConfiguration * cfg)1256 socketTransport_setConfiguration(jdwpTransportEnv* env, jdwpTransportConfiguration* cfg) {
1257 const char* allowed_peers = NULL;
1258
1259 if (cfg == NULL) {
1260 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
1261 "NULL pointer to transport configuration is invalid");
1262 }
1263 allowed_peers = cfg->allowed_peers;
1264 _peers_cnt = 0;
1265 if (allowed_peers != NULL) {
1266 size_t len = strlen(allowed_peers);
1267 if (len == 0) { /* Impossible: parseOptions() would reject it */
1268 fprintf(stderr, "Error in allow option: '%s'\n", allowed_peers);
1269 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
1270 "allow option should not be empty");
1271 } else if (*allowed_peers == '*') {
1272 if (len != 1) {
1273 fprintf(stderr, "Error in allow option: '%s'\n", allowed_peers);
1274 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
1275 "allow option '*' cannot be expanded");
1276 }
1277 } else {
1278 int err = parseAllowedPeers(allowed_peers, len);
1279 if (err != JDWPTRANSPORT_ERROR_NONE) {
1280 return err;
1281 }
1282 }
1283 }
1284 return JDWPTRANSPORT_ERROR_NONE;
1285 }
1286
1287 /*
1288 * Reads boolean system value, sets *result to
1289 * - trueValue if the property is "true";
1290 * - falseValue if the property is "false".
1291 * Doesn't change *result if the property is not set or failed to read.
1292 */
readBooleanSysProp(int * result,int trueValue,int falseValue,JNIEnv * jniEnv,jclass sysClass,jmethodID getPropMethod,const char * propName)1293 static int readBooleanSysProp(int *result, int trueValue, int falseValue,
1294 JNIEnv* jniEnv, jclass sysClass, jmethodID getPropMethod, const char *propName)
1295 {
1296 jstring value;
1297 jstring name = (*jniEnv)->NewStringUTF(jniEnv, propName);
1298
1299 if (name == NULL) {
1300 return JNI_ERR;
1301 }
1302 value = (jstring)(*jniEnv)->CallStaticObjectMethod(jniEnv, sysClass, getPropMethod, name);
1303 if ((*jniEnv)->ExceptionCheck(jniEnv)) {
1304 return JNI_ERR;
1305 }
1306 if (value != NULL) {
1307 const char *theValue = (*jniEnv)->GetStringUTFChars(jniEnv, value, NULL);
1308 if (theValue == NULL) {
1309 return JNI_ERR;
1310 }
1311 if (strcmp(theValue, "true") == 0) {
1312 *result = trueValue;
1313 } else if (strcmp(theValue, "false") == 0) {
1314 *result = falseValue;
1315 }
1316 (*jniEnv)->ReleaseStringUTFChars(jniEnv, value, theValue);
1317 }
1318 return JNI_OK;
1319 }
1320
1321 JNIEXPORT jint JNICALL
jdwpTransport_OnLoad(JavaVM * vm,jdwpTransportCallback * cbTablePtr,jint version,jdwpTransportEnv ** env)1322 jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr,
1323 jint version, jdwpTransportEnv** env)
1324 {
1325 JNIEnv* jniEnv = NULL;
1326
1327 if (version < JDWPTRANSPORT_VERSION_1_0 ||
1328 version > JDWPTRANSPORT_VERSION_1_1) {
1329 return JNI_EVERSION;
1330 }
1331 if (initialized) {
1332 /*
1333 * This library doesn't support multiple environments (yet)
1334 */
1335 return JNI_EEXIST;
1336 }
1337 initialized = JNI_TRUE;
1338 jvm = vm;
1339 callback = cbTablePtr;
1340
1341 /* initialize interface table */
1342 interface.GetCapabilities = &socketTransport_getCapabilities;
1343 interface.Attach = &socketTransport_attach;
1344 interface.StartListening = &socketTransport_startListening;
1345 interface.StopListening = &socketTransport_stopListening;
1346 interface.Accept = &socketTransport_accept;
1347 interface.IsOpen = &socketTransport_isOpen;
1348 interface.Close = &socketTransport_close;
1349 interface.ReadPacket = &socketTransport_readPacket;
1350 interface.WritePacket = &socketTransport_writePacket;
1351 interface.GetLastError = &socketTransport_getLastError;
1352 if (version >= JDWPTRANSPORT_VERSION_1_1) {
1353 interface.SetTransportConfiguration = &socketTransport_setConfiguration;
1354 }
1355 *env = &single_env;
1356
1357 /* initialized TLS */
1358 tlsIndex = dbgsysTlsAlloc();
1359
1360 // retrieve network-related system properties
1361 do {
1362 jclass sysClass;
1363 jmethodID getPropMethod;
1364 if ((*vm)->GetEnv(vm, (void **)&jniEnv, JNI_VERSION_9) != JNI_OK) {
1365 break;
1366 }
1367 sysClass = (*jniEnv)->FindClass(jniEnv, "java/lang/System");
1368 if (sysClass == NULL) {
1369 break;
1370 }
1371 getPropMethod = (*jniEnv)->GetStaticMethodID(jniEnv, sysClass,
1372 "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
1373 if (getPropMethod == NULL) {
1374 break;
1375 }
1376 readBooleanSysProp(&allowOnlyIPv4, 1, 0,
1377 jniEnv, sysClass, getPropMethod, "java.net.preferIPv4Stack");
1378 readBooleanSysProp(&preferredAddressFamily, AF_INET6, AF_INET,
1379 jniEnv, sysClass, getPropMethod, "java.net.preferIPv6Addresses");
1380 } while (0);
1381
1382 if (jniEnv != NULL && (*jniEnv)->ExceptionCheck(jniEnv)) {
1383 (*jniEnv)->ExceptionClear(jniEnv);
1384 }
1385
1386
1387 return JNI_OK;
1388 }
1389