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