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