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