1 /*
   2  * Copyright (c) 1998, 2018, 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 "jdwpTransport.h"
  32 #include "sysSocket.h"
  33 
  34 #ifdef _WIN32
  35  #include <winsock2.h>
  36  #include <ws2tcpip.h>
  37 #else
  38  #include <arpa/inet.h>
  39  #include <sys/socket.h>
  40 #endif
  41 
  42 /*
  43  * The Socket Transport Library.
  44  *
  45  * This module is an implementation of the Java Debug Wire Protocol Transport
  46  * Service Provider Interface - see src/share/javavm/export/jdwpTransport.h.
  47  */
  48 
  49 static int serverSocketFD;
  50 static int socketFD = -1;
  51 static jdwpTransportCallback *callback;
  52 static JavaVM *jvm;
  53 static int tlsIndex;
  54 static jboolean initialized;
  55 static struct jdwpTransportNativeInterface_ interface;
  56 static jdwpTransportEnv single_env = (jdwpTransportEnv)&interface;
  57 
  58 #define RETURN_ERROR(err, msg) \
  59         if (1==1) { \
  60             setLastError(err, msg); \
  61             return err; \
  62         }
  63 
  64 #define RETURN_IO_ERROR(msg)    RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, msg);
  65 
  66 #define RETURN_RECV_ERROR(n) \
  67         if (n == 0) { \
  68             RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, "premature EOF"); \
  69         } else { \
  70             RETURN_IO_ERROR("recv error"); \
  71         }
  72 
  73 #define MAX_DATA_SIZE 1000
  74 
  75 static jint recv_fully(int, char *, int);
  76 static jint send_fully(int, char *, int);
  77 
  78 /* version >= JDWPTRANSPORT_VERSION_1_1 */
  79 typedef struct {
  80     uint32_t subnet;
  81     uint32_t netmask;
  82 } AllowedPeerInfo;
  83 
  84 #define STR(x) #x
  85 #define MAX_PEER_ENTRIES 32
  86 #define MAX_PEERS_STR STR(MAX_PEER_ENTRIES)
  87 static AllowedPeerInfo _peers[MAX_PEER_ENTRIES];
  88 static int _peers_cnt = 0;
  89 
  90 
  91 /*
  92  * Record the last error for this thread.
  93  */
  94 static void
  95 setLastError(jdwpTransportError err, char *newmsg) {
  96     char buf[255];
  97     char *msg;
  98 
  99     /* get any I/O first in case any system calls override errno */
 100     if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
 101         dbgsysGetLastIOError(buf, sizeof(buf));
 102     }
 103 
 104     msg = (char *)dbgsysTlsGet(tlsIndex);
 105     if (msg != NULL) {
 106         (*callback->free)(msg);
 107     }
 108 
 109     if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {
 110         char *join_str = ": ";
 111         int msg_len = (int)strlen(newmsg) + (int)strlen(join_str) +
 112                       (int)strlen(buf) + 3;
 113         msg = (*callback->alloc)(msg_len);
 114         if (msg != NULL) {
 115             strcpy(msg, newmsg);
 116             strcat(msg, join_str);
 117             strcat(msg, buf);
 118         }
 119     } else {
 120         msg = (*callback->alloc)((int)strlen(newmsg)+1);
 121         if (msg != NULL) {
 122             strcpy(msg, newmsg);
 123         }
 124     }
 125 
 126     dbgsysTlsPut(tlsIndex, msg);
 127 }
 128 
 129 /*
 130  * Return the last error for this thread (may be NULL)
 131  */
 132 static char*
 133 getLastError() {
 134     return (char *)dbgsysTlsGet(tlsIndex);
 135 }
 136 
 137 /* Set options common to client and server sides */
 138 static jdwpTransportError
 139 setOptionsCommon(int fd)
 140 {
 141     jvalue dontcare;
 142     int err;
 143 
 144     dontcare.i = 0;  /* keep compiler happy */
 145 
 146     err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);
 147     if (err < 0) {
 148         RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
 149     }
 150 
 151     return JDWPTRANSPORT_ERROR_NONE;
 152 }
 153 
 154 /* Set the SO_REUSEADDR option */
 155 static jdwpTransportError
 156 setReuseAddrOption(int fd)
 157 {
 158     jvalue dontcare;
 159     int err;
 160 
 161     dontcare.i = 0;  /* keep compiler happy */
 162 
 163     err = dbgsysSetSocketOption(fd, SO_REUSEADDR, JNI_TRUE, dontcare);
 164     if (err < 0) {
 165         RETURN_IO_ERROR("setsockopt SO_REUSEADDR failed");
 166     }
 167 
 168     return JDWPTRANSPORT_ERROR_NONE;
 169 }
 170 
 171 static jdwpTransportError
 172 handshake(int fd, jlong timeout) {
 173     const char *hello = "JDWP-Handshake";
 174     char b[16];
 175     int rv, helloLen, received;
 176 
 177     if (timeout > 0) {
 178         dbgsysConfigureBlocking(fd, JNI_FALSE);
 179     }
 180     helloLen = (int)strlen(hello);
 181     received = 0;
 182     while (received < helloLen) {
 183         int n;
 184         char *buf;
 185         if (timeout > 0) {
 186             rv = dbgsysPoll(fd, JNI_TRUE, JNI_FALSE, (long)timeout);
 187             if (rv <= 0) {
 188                 setLastError(0, "timeout during handshake");
 189                 return JDWPTRANSPORT_ERROR_IO_ERROR;
 190             }
 191         }
 192         buf = b;
 193         buf += received;
 194         n = recv_fully(fd, buf, helloLen-received);
 195         if (n == 0) {
 196             setLastError(0, "handshake failed - connection prematurally closed");
 197             return JDWPTRANSPORT_ERROR_IO_ERROR;
 198         }
 199         if (n < 0) {
 200             RETURN_IO_ERROR("recv failed during handshake");
 201         }
 202         received += n;
 203     }
 204     if (timeout > 0) {
 205         dbgsysConfigureBlocking(fd, JNI_TRUE);
 206     }
 207     if (strncmp(b, hello, received) != 0) {
 208         char msg[80+2*16];
 209         b[received] = '\0';
 210         /*
 211          * We should really use snprintf here but it's not available on Windows.
 212          * We can't use jio_snprintf without linking the transport against the VM.
 213          */
 214         sprintf(msg, "handshake failed - received >%s< - expected >%s<", b, hello);
 215         setLastError(0, msg);
 216         return JDWPTRANSPORT_ERROR_IO_ERROR;
 217     }
 218 
 219     if (send_fully(fd, (char*)hello, helloLen) != helloLen) {
 220         RETURN_IO_ERROR("send failed during handshake");
 221     }
 222     return JDWPTRANSPORT_ERROR_NONE;
 223 }
 224 
 225 static uint32_t
 226 getLocalHostAddress() {
 227     // Simple routine to guess localhost address.
 228     // it looks up "localhost" and returns 127.0.0.1 if lookup
 229     // fails.
 230     struct addrinfo hints, *res = NULL;
 231     int err;
 232 
 233     // Use portable way to initialize the structure
 234     memset((void *)&hints, 0, sizeof(hints));
 235     hints.ai_family = AF_INET;
 236 
 237     err = getaddrinfo("localhost", NULL, &hints, &res);
 238     if (err < 0 || res == NULL) {
 239         return dbgsysHostToNetworkLong(INADDR_LOOPBACK);
 240     }
 241 
 242     // getaddrinfo might return more than one address
 243     // but we are using first one only
 244     uint32_t addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
 245     freeaddrinfo(res);
 246     return addr;
 247 }
 248 
 249 static int
 250 getPortNumber(const char *s_port) {
 251     u_long n;
 252     char *eptr;
 253 
 254     if (*s_port == 0) {
 255         // bad address - colon with no port number in parameters
 256         return -1;
 257     }
 258 
 259     n = strtoul(s_port, &eptr, 10);
 260     if (eptr != s_port + strlen(s_port)) {
 261         // incomplete conversion - port number contains non-digit
 262         return -1;
 263     }
 264 
 265     if (n > (u_short) -1) {
 266         // check that value supplied by user is less than
 267         // maximum possible u_short value (65535) and
 268         // will not be truncated later.
 269         return -1;
 270     }
 271 
 272     return n;
 273 }
 274 
 275 static jdwpTransportError
 276 parseAddress(const char *address, struct sockaddr_in *sa) {
 277     char *colon;
 278     int port;
 279 
 280     memset((void *)sa, 0, sizeof(struct sockaddr_in));
 281     sa->sin_family = AF_INET;
 282 
 283     /* check for host:port or port */
 284     colon = strchr(address, ':');
 285     port = getPortNumber((colon == NULL) ? address : colon +1);
 286     if (port < 0) {
 287         RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "invalid port number specified");
 288     }
 289     sa->sin_port = dbgsysHostToNetworkShort((u_short)port);
 290 
 291     if (colon == NULL) {
 292         // bind to localhost only if no address specified
 293         sa->sin_addr.s_addr = getLocalHostAddress();
 294     } else if (strncmp(address, "localhost:", 10) == 0) {
 295         // optimize for common case
 296         sa->sin_addr.s_addr = getLocalHostAddress();
 297     } else if (*address == '*' && *(address+1) == ':') {
 298         // we are explicitly asked to bind server to all available IP addresses
 299         // has no meaning for client.
 300         sa->sin_addr.s_addr = dbgsysHostToNetworkLong(INADDR_ANY);
 301      } else {
 302         char *buf;
 303         char *hostname;
 304         uint32_t addr;
 305 
 306         buf = (*callback->alloc)((int)strlen(address) + 1);
 307         if (buf == NULL) {
 308             RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
 309         }
 310         strcpy(buf, address);
 311         buf[colon - address] = '\0';
 312         hostname = buf;
 313 
 314         /*
 315          * First see if the host is a literal IP address.
 316          * If not then try to resolve it.
 317          */
 318         addr = dbgsysInetAddr(hostname);
 319         if (addr == 0xffffffff) {
 320             struct addrinfo hints;
 321             struct addrinfo *results = NULL;
 322             memset (&hints, 0, sizeof(hints));
 323             hints.ai_family = AF_INET;
 324             hints.ai_socktype = SOCK_STREAM;
 325             hints.ai_protocol = IPPROTO_TCP;
 326           
 327             int ai = dbgsysGetAddrInfo(hostname, NULL, &hints, &results);
 328 
 329             if (ai != 0) {
 330                 /* don't use RETURN_IO_ERROR as unknown host is normal */
 331                 setLastError(0, "getaddrinfo: unknown host");
 332                 (*callback->free)(buf);
 333                 return JDWPTRANSPORT_ERROR_IO_ERROR;
 334             }
 335 
 336             /* lookup was successful */
 337             sa->sin_addr =  ((struct sockaddr_in *)results->ai_addr)->sin_addr;
 338             freeaddrinfo(results);
 339         } else {
 340             sa->sin_addr.s_addr = addr;
 341         }
 342 
 343         (*callback->free)(buf);
 344     }
 345 
 346     return JDWPTRANSPORT_ERROR_NONE;
 347 }
 348 
 349 static const char *
 350 ip_s2u(const char *instr, uint32_t *ip) {
 351     // Convert string representation of ip to integer
 352     // in network byte order (big-endian)
 353     char t[4] = { 0, 0, 0, 0 };
 354     const char *s = instr;
 355     int i = 0;
 356 
 357     while (1) {
 358         if (*s == '.') {
 359             ++i;
 360             ++s;
 361             continue;
 362         }
 363         if (*s == 0 || *s == '+' || *s == '/') {
 364             break;
 365         }
 366         if (*s < '0' || *s > '9') {
 367             return instr;
 368         }
 369         t[i] = (t[i] * 10) + (*s - '0');
 370         ++s;
 371     }
 372 
 373     *ip = *(uint32_t*)(t);
 374     return s;
 375 }
 376 
 377 static const char *
 378 mask_s2u(const char *instr, uint32_t *mask) {
 379     // Convert the number of bits to a netmask
 380     // in network byte order (big-endian)
 381     unsigned char m = 0;
 382     const char *s = instr;
 383 
 384     while (1) {
 385         if (*s == 0 || *s == '+') {
 386             break;
 387         }
 388         if (*s < '0' || *s > '9') {
 389             return instr;
 390         }
 391         m = (m * 10) + (*s - '0');
 392         ++s;
 393     }
 394 
 395     if (m == 0 || m > 32) {
 396        // Drop invalid input
 397        return instr;
 398     }
 399 
 400     *mask = htonl(-1 << (32 - m));
 401     return s;
 402 }
 403 
 404 static int
 405 ip_in_subnet(uint32_t subnet, uint32_t mask, uint32_t ipaddr) {
 406     return (ipaddr & mask) == subnet;
 407 }
 408 
 409 static jdwpTransportError
 410 parseAllowedPeers(const char *allowed_peers) {
 411     // Build a list of allowed peers from char string
 412     // of format 192.168.0.10+192.168.0.0/24
 413     const char *s = NULL;
 414     const char *p = allowed_peers;
 415     uint32_t   ip = 0;
 416     uint32_t mask = 0xFFFFFFFF;
 417 
 418     while (1) {
 419         s = ip_s2u(p, &ip);
 420         if (s == p) {
 421             _peers_cnt = 0;
 422             fprintf(stderr, "Error in allow option: '%s'\n", s);
 423             RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
 424                          "invalid IP address in allow option");
 425         }
 426 
 427         if (*s == '/') {
 428             // netmask specified
 429             s = mask_s2u(s + 1, &mask);
 430             if (*(s - 1) == '/') {
 431                 // Input is not consumed, something bad happened
 432                 _peers_cnt = 0;
 433                 fprintf(stderr, "Error in allow option: '%s'\n", s);
 434                 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
 435                              "invalid netmask in allow option");
 436             }
 437         } else {
 438             // reset netmask
 439             mask = 0xFFFFFFFF;
 440         }
 441 
 442         if (*s == '+' || *s == 0) {
 443             if (_peers_cnt >= MAX_PEER_ENTRIES) {
 444                 fprintf(stderr, "Error in allow option: '%s'\n", allowed_peers);
 445                 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
 446                              "exceeded max number of allowed peers: " MAX_PEERS_STR);
 447             }
 448             _peers[_peers_cnt].subnet = ip;
 449             _peers[_peers_cnt].netmask = mask;
 450             _peers_cnt++;
 451             if (*s == 0) {
 452                 // end of options
 453                 break;
 454             }
 455             // advance to next IP block
 456             p = s + 1;
 457         }
 458     }
 459     return JDWPTRANSPORT_ERROR_NONE;
 460 }
 461 
 462 static int
 463 isPeerAllowed(struct sockaddr_in *peer) {
 464     int i;
 465     for (i = 0; i < _peers_cnt; ++i) {
 466         int peer_ip = peer->sin_addr.s_addr;
 467         if (ip_in_subnet(_peers[i].subnet, _peers[i].netmask, peer_ip)) {
 468             return 1;
 469         }
 470     }
 471 
 472     return 0;
 473 }
 474 
 475 static jdwpTransportError JNICALL
 476 socketTransport_getCapabilities(jdwpTransportEnv* env,
 477         JDWPTransportCapabilities* capabilitiesPtr)
 478 {
 479     JDWPTransportCapabilities result;
 480 
 481     memset(&result, 0, sizeof(result));
 482     result.can_timeout_attach = JNI_TRUE;
 483     result.can_timeout_accept = JNI_TRUE;
 484     result.can_timeout_handshake = JNI_TRUE;
 485 
 486     *capabilitiesPtr = result;
 487 
 488     return JDWPTRANSPORT_ERROR_NONE;
 489 }
 490 
 491 
 492 static jdwpTransportError JNICALL
 493 socketTransport_startListening(jdwpTransportEnv* env, const char* address,
 494                                char** actualAddress)
 495 {
 496     struct sockaddr_in sa;
 497     int err;
 498 
 499     memset((void *)&sa,0,sizeof(struct sockaddr_in));
 500     sa.sin_family = AF_INET;
 501 
 502     /* no address provided */
 503     if ((address == NULL) || (address[0] == '\0')) {
 504         address = "0";
 505     }
 506 
 507     err = parseAddress(address, &sa);
 508     if (err != JDWPTRANSPORT_ERROR_NONE) {
 509         return err;
 510     }
 511 
 512     serverSocketFD = dbgsysSocket(AF_INET, SOCK_STREAM, 0);
 513     if (serverSocketFD < 0) {
 514         RETURN_IO_ERROR("socket creation failed");
 515     }
 516 
 517     err = setOptionsCommon(serverSocketFD);
 518     if (err) {
 519         return err;
 520     }
 521     if (sa.sin_port != 0) {
 522         /*
 523          * Only need SO_REUSEADDR if we're using a fixed port. If we
 524          * start seeing EADDRINUSE due to collisions in free ports
 525          * then we should retry the dbgsysBind() a few times.
 526          */
 527         err = setReuseAddrOption(serverSocketFD);
 528         if (err) {
 529             return err;
 530         }
 531     }
 532 
 533     err = dbgsysBind(serverSocketFD, (struct sockaddr *)&sa, sizeof(sa));
 534     if (err < 0) {
 535         RETURN_IO_ERROR("bind failed");
 536     }
 537 
 538     err = dbgsysListen(serverSocketFD, 1);
 539     if (err < 0) {
 540         RETURN_IO_ERROR("listen failed");
 541     }
 542 
 543     {
 544         char buf[20];
 545         socklen_t len = sizeof(sa);
 546         jint portNum;
 547         err = dbgsysGetSocketName(serverSocketFD,
 548                                (struct sockaddr *)&sa, &len);
 549         portNum = dbgsysNetworkToHostShort(sa.sin_port);
 550         sprintf(buf, "%d", portNum);
 551         *actualAddress = (*callback->alloc)((int)strlen(buf) + 1);
 552         if (*actualAddress == NULL) {
 553             RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
 554         } else {
 555             strcpy(*actualAddress, buf);
 556         }
 557     }
 558 
 559     return JDWPTRANSPORT_ERROR_NONE;
 560 }
 561 
 562 static jdwpTransportError JNICALL
 563 socketTransport_accept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout)
 564 {
 565     socklen_t socketLen;
 566     int err = JDWPTRANSPORT_ERROR_NONE;
 567     struct sockaddr_in socket;
 568     jlong startTime = (jlong)0;
 569 
 570     /*
 571      * Use a default handshake timeout if not specified - this avoids an indefinite
 572      * hang in cases where something other than a debugger connects to our port.
 573      */
 574     if (handshakeTimeout == 0) {
 575         handshakeTimeout = 2000;
 576     }
 577 
 578     do {
 579         /*
 580          * If there is an accept timeout then we put the socket in non-blocking
 581          * mode and poll for a connection.
 582          */
 583         if (acceptTimeout > 0) {
 584             int rv;
 585             dbgsysConfigureBlocking(serverSocketFD, JNI_FALSE);
 586             startTime = dbgsysCurrentTimeMillis();
 587             rv = dbgsysPoll(serverSocketFD, JNI_TRUE, JNI_FALSE, (long)acceptTimeout);
 588             if (rv <= 0) {
 589                 /* set the last error here as could be overridden by configureBlocking */
 590                 if (rv == 0) {
 591                     setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "poll failed");
 592                 }
 593                 /* restore blocking state */
 594                 dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
 595                 if (rv == 0) {
 596                     RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "timed out waiting for connection");
 597                 } else {
 598                     return JDWPTRANSPORT_ERROR_IO_ERROR;
 599                 }
 600             }
 601         }
 602 
 603         /*
 604          * Accept the connection
 605          */
 606         memset((void *)&socket,0,sizeof(struct sockaddr_in));
 607         socketLen = sizeof(socket);
 608         socketFD = dbgsysAccept(serverSocketFD,
 609                                 (struct sockaddr *)&socket,
 610                                 &socketLen);
 611         /* set the last error here as could be overridden by configureBlocking */
 612         if (socketFD < 0) {
 613             setLastError(JDWPTRANSPORT_ERROR_IO_ERROR, "accept failed");
 614         }
 615         /*
 616          * Restore the blocking state - note that the accepted socket may be in
 617          * blocking or non-blocking mode (platform dependent). However as there
 618          * is a handshake timeout set then it will go into non-blocking mode
 619          * anyway for the handshake.
 620          */
 621         if (acceptTimeout > 0) {
 622             dbgsysConfigureBlocking(serverSocketFD, JNI_TRUE);
 623         }
 624         if (socketFD < 0) {
 625             return JDWPTRANSPORT_ERROR_IO_ERROR;
 626         }
 627 
 628         /*
 629          * version >= JDWPTRANSPORT_VERSION_1_1:
 630          * Verify that peer is allowed to connect.
 631          */
 632         if (_peers_cnt > 0) {
 633             if (!isPeerAllowed(&socket)) {
 634                 char ebuf[64] = { 0 };
 635                 char buf[INET_ADDRSTRLEN] = { 0 };
 636                 const char* addr_str = inet_ntop(AF_INET, &(socket.sin_addr), buf, INET_ADDRSTRLEN);
 637                 sprintf(ebuf, "ERROR: Peer not allowed to connect: %s\n",
 638                         (addr_str == NULL) ? "<bad address>" : addr_str);
 639                 dbgsysSocketClose(socketFD);
 640                 socketFD = -1;
 641                 err = JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT;
 642                 setLastError(err, ebuf);
 643             }
 644         }
 645 
 646         if (socketFD > 0) {
 647           /* handshake with the debugger */
 648           err = handshake(socketFD, handshakeTimeout);
 649         }
 650 
 651         /*
 652          * If the handshake fails then close the connection. If there if an accept
 653          * timeout then we must adjust the timeout for the next poll.
 654          */
 655         if (err != JDWPTRANSPORT_ERROR_NONE) {
 656             fprintf(stderr, "Debugger failed to attach: %s\n", getLastError());
 657             dbgsysSocketClose(socketFD);
 658             socketFD = -1;
 659             if (acceptTimeout > 0) {
 660                 long endTime = dbgsysCurrentTimeMillis();
 661                 acceptTimeout -= (endTime - startTime);
 662                 if (acceptTimeout <= 0) {
 663                     setLastError(JDWPTRANSPORT_ERROR_IO_ERROR,
 664                         "timeout waiting for debugger to connect");
 665                     return JDWPTRANSPORT_ERROR_IO_ERROR;
 666                 }
 667             }
 668         }
 669     } while (socketFD < 0);
 670 
 671     return JDWPTRANSPORT_ERROR_NONE;
 672 }
 673 
 674 static jdwpTransportError JNICALL
 675 socketTransport_stopListening(jdwpTransportEnv *env)
 676 {
 677     if (serverSocketFD < 0) {
 678         RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "connection not open");
 679     }
 680     if (dbgsysSocketClose(serverSocketFD) < 0) {
 681         RETURN_IO_ERROR("close failed");
 682     }
 683     serverSocketFD = -1;
 684     return JDWPTRANSPORT_ERROR_NONE;
 685 }
 686 
 687 static jdwpTransportError JNICALL
 688 socketTransport_attach(jdwpTransportEnv* env, const char* addressString, jlong attachTimeout,
 689                        jlong handshakeTimeout)
 690 {
 691     struct sockaddr_in sa;
 692     int err;
 693 
 694     if (addressString == NULL || addressString[0] == '\0') {
 695         RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "address is missing");
 696     }
 697 
 698     err = parseAddress(addressString, &sa);
 699     if (err != JDWPTRANSPORT_ERROR_NONE) {
 700         return err;
 701     }
 702 
 703     socketFD = dbgsysSocket(AF_INET, SOCK_STREAM, 0);
 704     if (socketFD < 0) {
 705         RETURN_IO_ERROR("unable to create socket");
 706     }
 707 
 708     err = setOptionsCommon(socketFD);
 709     if (err) {
 710         return err;
 711     }
 712 
 713     /*
 714      * We don't call setReuseAddrOption() for the non-server socket
 715      * case. If we start seeing EADDRINUSE due to collisions in free
 716      * ports then we should retry the dbgsysConnect() a few times.
 717      */
 718 
 719     /*
 720      * To do a timed connect we make the socket non-blocking
 721      * and poll with a timeout;
 722      */
 723     if (attachTimeout > 0) {
 724         dbgsysConfigureBlocking(socketFD, JNI_FALSE);
 725     }
 726 
 727     err = dbgsysConnect(socketFD, (struct sockaddr *)&sa, sizeof(sa));
 728     if (err == DBG_EINPROGRESS && attachTimeout > 0) {
 729         err = dbgsysFinishConnect(socketFD, (long)attachTimeout);
 730 
 731         if (err == DBG_ETIMEOUT) {
 732             dbgsysConfigureBlocking(socketFD, JNI_TRUE);
 733             RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "connect timed out");
 734         }
 735     }
 736 
 737     if (err < 0) {
 738         RETURN_IO_ERROR("connect failed");
 739     }
 740 
 741     if (attachTimeout > 0) {
 742         dbgsysConfigureBlocking(socketFD, JNI_TRUE);
 743     }
 744 
 745     err = handshake(socketFD, handshakeTimeout);
 746     if (err) {
 747         dbgsysSocketClose(socketFD);
 748         socketFD = -1;
 749         return err;
 750     }
 751 
 752     return JDWPTRANSPORT_ERROR_NONE;
 753 }
 754 
 755 static jboolean JNICALL
 756 socketTransport_isOpen(jdwpTransportEnv* env)
 757 {
 758     if (socketFD >= 0) {
 759         return JNI_TRUE;
 760     } else {
 761         return JNI_FALSE;
 762     }
 763 }
 764 
 765 static jdwpTransportError JNICALL
 766 socketTransport_close(jdwpTransportEnv* env)
 767 {
 768     int fd = socketFD;
 769     socketFD = -1;
 770     if (fd < 0) {
 771         return JDWPTRANSPORT_ERROR_NONE;
 772     }
 773 #ifdef _AIX
 774     /*
 775       AIX needs a workaround for I/O cancellation, see:
 776       http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
 777       ...
 778       The close subroutine is blocked until all subroutines which use the file
 779       descriptor return to usr space. For example, when a thread is calling close
 780       and another thread is calling select with the same file descriptor, the
 781       close subroutine does not return until the select call returns.
 782       ...
 783     */
 784     shutdown(fd, 2);
 785 #endif
 786     if (dbgsysSocketClose(fd) < 0) {
 787         /*
 788          * close failed - it's pointless to restore socketFD here because
 789          * any subsequent close will likely fail as well.
 790          */
 791         RETURN_IO_ERROR("close failed");
 792     }
 793     return JDWPTRANSPORT_ERROR_NONE;
 794 }
 795 
 796 static jdwpTransportError JNICALL
 797 socketTransport_writePacket(jdwpTransportEnv* env, const jdwpPacket *packet)
 798 {
 799     jint len, data_len, id;
 800     /*
 801      * room for header and up to MAX_DATA_SIZE data bytes
 802      */
 803     char header[JDWP_HEADER_SIZE + MAX_DATA_SIZE];
 804     jbyte *data;
 805 
 806     /* packet can't be null */
 807     if (packet == NULL) {
 808         RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is NULL");
 809     }
 810 
 811     len = packet->type.cmd.len;         /* includes header */
 812     data_len = len - JDWP_HEADER_SIZE;
 813 
 814     /* bad packet */
 815     if (data_len < 0) {
 816         RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "invalid length");
 817     }
 818 
 819     /* prepare the header for transmission */
 820     len = (jint)dbgsysHostToNetworkLong(len);
 821     id = (jint)dbgsysHostToNetworkLong(packet->type.cmd.id);
 822 
 823     memcpy(header + 0, &len, 4);
 824     memcpy(header + 4, &id, 4);
 825     header[8] = packet->type.cmd.flags;
 826     if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
 827         jshort errorCode =
 828             dbgsysHostToNetworkShort(packet->type.reply.errorCode);
 829         memcpy(header + 9, &errorCode, 2);
 830     } else {
 831         header[9] = packet->type.cmd.cmdSet;
 832         header[10] = packet->type.cmd.cmd;
 833     }
 834 
 835     data = packet->type.cmd.data;
 836     /* Do one send for short packets, two for longer ones */
 837     if (data_len <= MAX_DATA_SIZE) {
 838         memcpy(header + JDWP_HEADER_SIZE, data, data_len);
 839         if (send_fully(socketFD, (char *)&header, JDWP_HEADER_SIZE + data_len) !=
 840             JDWP_HEADER_SIZE + data_len) {
 841             RETURN_IO_ERROR("send failed");
 842         }
 843     } else {
 844         memcpy(header + JDWP_HEADER_SIZE, data, MAX_DATA_SIZE);
 845         if (send_fully(socketFD, (char *)&header, JDWP_HEADER_SIZE + MAX_DATA_SIZE) !=
 846             JDWP_HEADER_SIZE + MAX_DATA_SIZE) {
 847             RETURN_IO_ERROR("send failed");
 848         }
 849         /* Send the remaining data bytes right out of the data area. */
 850         if (send_fully(socketFD, (char *)data + MAX_DATA_SIZE,
 851                        data_len - MAX_DATA_SIZE) != data_len - MAX_DATA_SIZE) {
 852             RETURN_IO_ERROR("send failed");
 853         }
 854     }
 855 
 856     return JDWPTRANSPORT_ERROR_NONE;
 857 }
 858 
 859 static jint
 860 recv_fully(int f, char *buf, int len)
 861 {
 862     int nbytes = 0;
 863     while (nbytes < len) {
 864         int res = dbgsysRecv(f, buf + nbytes, len - nbytes, 0);
 865         if (res < 0) {
 866             return res;
 867         } else if (res == 0) {
 868             break; /* eof, return nbytes which is less than len */
 869         }
 870         nbytes += res;
 871     }
 872     return nbytes;
 873 }
 874 
 875 jint
 876 send_fully(int f, char *buf, int len)
 877 {
 878     int nbytes = 0;
 879     while (nbytes < len) {
 880         int res = dbgsysSend(f, buf + nbytes, len - nbytes, 0);
 881         if (res < 0) {
 882             return res;
 883         } else if (res == 0) {
 884             break; /* eof, return nbytes which is less than len */
 885         }
 886         nbytes += res;
 887     }
 888     return nbytes;
 889 }
 890 
 891 static jdwpTransportError JNICALL
 892 socketTransport_readPacket(jdwpTransportEnv* env, jdwpPacket* packet) {
 893     jint length, data_len;
 894     jint n;
 895 
 896     /* packet can't be null */
 897     if (packet == NULL) {
 898         RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is null");
 899     }
 900 
 901     /* read the length field */
 902     n = recv_fully(socketFD, (char *)&length, sizeof(jint));
 903 
 904     /* check for EOF */
 905     if (n == 0) {
 906         packet->type.cmd.len = 0;
 907         return JDWPTRANSPORT_ERROR_NONE;
 908     }
 909     if (n != sizeof(jint)) {
 910         RETURN_RECV_ERROR(n);
 911     }
 912 
 913     length = (jint)dbgsysNetworkToHostLong(length);
 914     packet->type.cmd.len = length;
 915 
 916 
 917     n = recv_fully(socketFD,(char *)&(packet->type.cmd.id), sizeof(jint));
 918     if (n < (int)sizeof(jint)) {
 919         RETURN_RECV_ERROR(n);
 920     }
 921 
 922     packet->type.cmd.id = (jint)dbgsysNetworkToHostLong(packet->type.cmd.id);
 923 
 924     n = recv_fully(socketFD,(char *)&(packet->type.cmd.flags), sizeof(jbyte));
 925     if (n < (int)sizeof(jbyte)) {
 926         RETURN_RECV_ERROR(n);
 927     }
 928 
 929     if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
 930         n = recv_fully(socketFD,(char *)&(packet->type.reply.errorCode), sizeof(jbyte));
 931         if (n < (int)sizeof(jshort)) {
 932             RETURN_RECV_ERROR(n);
 933         }
 934 
 935         /* FIXME - should the error be converted to host order?? */
 936 
 937 
 938     } else {
 939         n = recv_fully(socketFD,(char *)&(packet->type.cmd.cmdSet), sizeof(jbyte));
 940         if (n < (int)sizeof(jbyte)) {
 941             RETURN_RECV_ERROR(n);
 942         }
 943 
 944         n = recv_fully(socketFD,(char *)&(packet->type.cmd.cmd), sizeof(jbyte));
 945         if (n < (int)sizeof(jbyte)) {
 946             RETURN_RECV_ERROR(n);
 947         }
 948     }
 949 
 950     data_len = length - ((sizeof(jint) * 2) + (sizeof(jbyte) * 3));
 951 
 952     if (data_len < 0) {
 953         setLastError(0, "Badly formed packet received - invalid length");
 954         return JDWPTRANSPORT_ERROR_IO_ERROR;
 955     } else if (data_len == 0) {
 956         packet->type.cmd.data = NULL;
 957     } else {
 958         packet->type.cmd.data= (*callback->alloc)(data_len);
 959 
 960         if (packet->type.cmd.data == NULL) {
 961             RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
 962         }
 963 
 964         n = recv_fully(socketFD,(char *)packet->type.cmd.data, data_len);
 965         if (n < data_len) {
 966             (*callback->free)(packet->type.cmd.data);
 967             RETURN_RECV_ERROR(n);
 968         }
 969     }
 970 
 971     return JDWPTRANSPORT_ERROR_NONE;
 972 }
 973 
 974 static jdwpTransportError JNICALL
 975 socketTransport_getLastError(jdwpTransportEnv* env, char** msgP) {
 976     char *msg = (char *)dbgsysTlsGet(tlsIndex);
 977     if (msg == NULL) {
 978         return JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE;
 979     }
 980     *msgP = (*callback->alloc)((int)strlen(msg)+1);
 981     if (*msgP == NULL) {
 982         return JDWPTRANSPORT_ERROR_OUT_OF_MEMORY;
 983     }
 984     strcpy(*msgP, msg);
 985     return JDWPTRANSPORT_ERROR_NONE;
 986 }
 987 
 988 static jdwpTransportError JNICALL
 989 socketTransport_setConfiguration(jdwpTransportEnv* env, jdwpTransportConfiguration* cfg) {
 990     const char* allowed_peers = NULL;
 991 
 992     if (cfg == NULL) {
 993         RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
 994                      "NULL pointer to transport configuration is invalid");
 995     }
 996     allowed_peers = cfg->allowed_peers;
 997     _peers_cnt = 0;
 998     if (allowed_peers != NULL) {
 999         size_t len = strlen(allowed_peers);
1000         if (len == 0) { /* Impossible: parseOptions() would reject it */
1001             fprintf(stderr, "Error in allow option: '%s'\n", allowed_peers);
1002             RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
1003                          "allow option should not be empty");
1004         } else if (*allowed_peers == '*') {
1005             if (len != 1) {
1006                 fprintf(stderr, "Error in allow option: '%s'\n", allowed_peers);
1007                 RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT,
1008                              "allow option '*' cannot be expanded");
1009             }
1010         } else {
1011             int err = parseAllowedPeers(allowed_peers);
1012             if (err != JDWPTRANSPORT_ERROR_NONE) {
1013                 return err;
1014             }
1015         }
1016     }
1017     return JDWPTRANSPORT_ERROR_NONE;
1018 }
1019 
1020 jint JNICALL
1021 jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr,
1022                      jint version, jdwpTransportEnv** env)
1023 {
1024     if (version < JDWPTRANSPORT_VERSION_1_0 ||
1025         version > JDWPTRANSPORT_VERSION_1_1) {
1026         return JNI_EVERSION;
1027     }
1028     if (initialized) {
1029         /*
1030          * This library doesn't support multiple environments (yet)
1031          */
1032         return JNI_EEXIST;
1033     }
1034     initialized = JNI_TRUE;
1035     jvm = vm;
1036     callback = cbTablePtr;
1037 
1038     /* initialize interface table */
1039     interface.GetCapabilities = &socketTransport_getCapabilities;
1040     interface.Attach = &socketTransport_attach;
1041     interface.StartListening = &socketTransport_startListening;
1042     interface.StopListening = &socketTransport_stopListening;
1043     interface.Accept = &socketTransport_accept;
1044     interface.IsOpen = &socketTransport_isOpen;
1045     interface.Close = &socketTransport_close;
1046     interface.ReadPacket = &socketTransport_readPacket;
1047     interface.WritePacket = &socketTransport_writePacket;
1048     interface.GetLastError = &socketTransport_getLastError;
1049     if (version >= JDWPTRANSPORT_VERSION_1_1) {
1050         interface.SetTransportConfiguration = &socketTransport_setConfiguration;
1051     }
1052     *env = &single_env;
1053 
1054     /* initialized TLS */
1055     tlsIndex = dbgsysTlsAlloc();
1056     return JNI_OK;
1057 }