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