1 /*
   2  * Copyright (c) 1997, 2019, 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 <errno.h>
  26 
  27 #include "jvm.h"
  28 #include "net_util.h"
  29 
  30 #include "java_net_SocketOptions.h"
  31 #include "java_net_PlainSocketImpl.h"
  32 
  33 /************************************************************************
  34  * PlainSocketImpl
  35  */
  36 
  37 static jfieldID IO_fd_fdID;
  38 
  39 jfieldID psi_fdID;
  40 jfieldID psi_addressID;
  41 jfieldID psi_ipaddressID;
  42 jfieldID psi_portID;
  43 jfieldID psi_localportID;
  44 jfieldID psi_timeoutID;
  45 jfieldID psi_trafficClassID;
  46 jfieldID psi_fdLockID;
  47 jfieldID psi_closePendingID;
  48 
  49 /*
  50  * file descriptor used for dup2
  51  */
  52 static int marker_fd = -1;
  53 
  54 
  55 #define SET_NONBLOCKING(fd) {           \
  56         int flags = fcntl(fd, F_GETFL); \
  57         flags |= O_NONBLOCK;            \
  58         fcntl(fd, F_SETFL, flags);      \
  59 }
  60 
  61 #define SET_BLOCKING(fd) {              \
  62         int flags = fcntl(fd, F_GETFL); \
  63         flags &= ~O_NONBLOCK;           \
  64         fcntl(fd, F_SETFL, flags);      \
  65 }
  66 
  67 /*
  68  * Create the marker file descriptor by establishing a loopback connection
  69  * which we shutdown but do not close the fd. The result is an fd that
  70  * can be used for read/write.
  71  */
  72 static int getMarkerFD()
  73 {
  74     int sv[2];
  75 
  76 #ifdef AF_UNIX
  77     if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
  78         return -1;
  79     }
  80 #else
  81     return -1;
  82 #endif
  83 
  84     /*
  85      * Finally shutdown sv[0] (any reads to this fd will get
  86      * EOF; any writes will get an error).
  87      */
  88     shutdown(sv[0], 2);
  89     close(sv[1]);
  90 
  91     return sv[0];
  92 }
  93 
  94 /*
  95  * Return the file descriptor given a PlainSocketImpl
  96  */
  97 static int getFD(JNIEnv *env, jobject this) {
  98     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
  99     CHECK_NULL_RETURN(fdObj, -1);
 100     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 101 }
 102 
 103 /*
 104  * The initroto function is called whenever PlainSocketImpl is
 105  * loaded, to cache field IDs for efficiency. This is called every time
 106  * the Java class is loaded.
 107  *
 108  * Class:     java_net_PlainSocketImpl
 109  * Method:    initProto
 110  * Signature: ()V
 111  */
 112 JNIEXPORT void JNICALL
 113 Java_java_net_PlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
 114     psi_fdID = (*env)->GetFieldID(env, cls , "fd",
 115                                   "Ljava/io/FileDescriptor;");
 116     CHECK_NULL(psi_fdID);
 117     psi_addressID = (*env)->GetFieldID(env, cls, "address",
 118                                           "Ljava/net/InetAddress;");
 119     CHECK_NULL(psi_addressID);
 120     psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
 121     CHECK_NULL(psi_portID);
 122     psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
 123     CHECK_NULL(psi_localportID);
 124     psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
 125     CHECK_NULL(psi_timeoutID);
 126     psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
 127     CHECK_NULL(psi_trafficClassID);
 128     psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
 129                                       "Ljava/lang/Object;");
 130     CHECK_NULL(psi_fdLockID);
 131     psi_closePendingID = (*env)->GetFieldID(env, cls, "closePending", "Z");
 132     CHECK_NULL(psi_closePendingID);
 133     IO_fd_fdID = NET_GetFileDescriptorID(env);
 134     CHECK_NULL(IO_fd_fdID);
 135 
 136     initInetAddressIDs(env);
 137     JNU_CHECK_EXCEPTION(env);
 138 
 139     /* Create the marker fd used for dup2 */
 140     marker_fd = getMarkerFD();
 141 }
 142 
 143 /* a global reference to the java.net.SocketException class. In
 144  * socketCreate, we ensure that this is initialized. This is to
 145  * prevent the problem where socketCreate runs out of file
 146  * descriptors, and is then unable to load the exception class.
 147  */
 148 static jclass socketExceptionCls;
 149 
 150 /*
 151  * Class:     java_net_PlainSocketImpl
 152  * Method:    socketCreate
 153  * Signature: (ZZ)V */
 154 JNIEXPORT void JNICALL
 155 Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
 156                                            jboolean stream, jboolean isServer) {
 157     jobject fdObj, ssObj;
 158     int fd;
 159     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
 160     int domain = ipv6_available() ? AF_INET6 : AF_INET;
 161 
 162     if (socketExceptionCls == NULL) {
 163         jclass c = (*env)->FindClass(env, "java/net/SocketException");
 164         CHECK_NULL(c);
 165         socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
 166         CHECK_NULL(socketExceptionCls);
 167     }
 168     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 169 
 170     if (fdObj == NULL) {
 171         (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
 172         return;
 173     }
 174 
 175     if ((fd = socket(domain, type, 0)) == -1) {
 176         /* note: if you run out of fds, you may not be able to load
 177          * the exception class, and get a NoClassDefFoundError
 178          * instead.
 179          */
 180         NET_ThrowNew(env, errno, "can't create socket");
 181         return;
 182     }
 183 
 184     /*
 185      * If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
 186      */
 187     if (domain == AF_INET6 && ipv4_available()) {
 188         int arg = 0;
 189         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
 190                        sizeof(int)) < 0) {
 191             NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
 192             close(fd);
 193             return;
 194         }
 195     }
 196 
 197     /*
 198      * If this is a server socket then enable SO_REUSEADDR
 199      * automatically and set to non blocking.
 200      */
 201     if (isServer) {
 202         int arg = 1;
 203         SET_NONBLOCKING(fd);
 204         if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
 205                        sizeof(arg)) < 0) {
 206             NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
 207             close(fd);
 208             return;
 209         }
 210     }
 211 
 212     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 213 }
 214 
 215 /*
 216  * inetAddress is the address object passed to the socket connect
 217  * call.
 218  *
 219  * Class:     java_net_PlainSocketImpl
 220  * Method:    socketConnect
 221  * Signature: (Ljava/net/InetAddress;I)V
 222  */
 223 JNIEXPORT void JNICALL
 224 Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
 225                                             jobject iaObj, jint port,
 226                                             jint timeout)
 227 {
 228     jint localport = (*env)->GetIntField(env, this, psi_localportID);
 229     int len = 0;
 230     /* fdObj is the FileDescriptor field on this */
 231     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 232 
 233     jclass clazz = (*env)->GetObjectClass(env, this);
 234 
 235     jobject fdLock;
 236 
 237     jint trafficClass = (*env)->GetIntField(env, this, psi_trafficClassID);
 238 
 239     /* fd is an int field on iaObj */
 240     jint fd;
 241 
 242     SOCKETADDRESS sa;
 243     /* The result of the connection */
 244     int connect_rv = -1;
 245 
 246     if (IS_NULL(fdObj)) {
 247         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
 248         return;
 249     } else {
 250         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 251     }
 252     if (IS_NULL(iaObj)) {
 253         JNU_ThrowNullPointerException(env, "inet address argument null.");
 254         return;
 255     }
 256 
 257     /* connect */
 258     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
 259                                   JNI_TRUE) != 0) {
 260         return;
 261     }
 262 
 263     if (trafficClass != 0 && ipv6_available()) {
 264         NET_SetTrafficClass(&sa, trafficClass);
 265     }
 266 
 267     if (timeout <= 0) {
 268         connect_rv = NET_Connect(fd, &sa.sa, len);
 269 #ifdef __solaris__
 270         if (connect_rv == -1 && errno == EINPROGRESS ) {
 271 
 272             /* This can happen if a blocking connect is interrupted by a signal.
 273              * See 6343810.
 274              */
 275             while (1) {
 276                 struct pollfd pfd;
 277                 pfd.fd = fd;
 278                 pfd.events = POLLOUT;
 279 
 280                 connect_rv = NET_Poll(&pfd, 1, -1);
 281 
 282                 if (connect_rv == -1) {
 283                     if (errno == EINTR) {
 284                         continue;
 285                     } else {
 286                         break;
 287                     }
 288                 }
 289                 if (connect_rv > 0) {
 290                     socklen_t optlen;
 291                     /* has connection been established */
 292                     optlen = sizeof(connect_rv);
 293                     if (getsockopt(fd, SOL_SOCKET, SO_ERROR,
 294                                    (void*)&connect_rv, &optlen) <0) {
 295                         connect_rv = errno;
 296                     }
 297 
 298                     if (connect_rv != 0) {
 299                         /* restore errno */
 300                         errno = connect_rv;
 301                         connect_rv = -1;
 302                     }
 303                     break;
 304                 }
 305             }
 306         }
 307 #endif
 308     } else {
 309         /*
 310          * A timeout was specified. We put the socket into non-blocking
 311          * mode, connect, and then wait for the connection to be
 312          * established, fail, or timeout.
 313          */
 314         SET_NONBLOCKING(fd);
 315 
 316         /* no need to use NET_Connect as non-blocking */
 317         connect_rv = connect(fd, &sa.sa, len);
 318 
 319         /* connection not established immediately */
 320         if (connect_rv != 0) {
 321             socklen_t optlen;
 322             jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
 323             jlong prevNanoTime = JVM_NanoTime(env, 0);
 324 
 325             if (errno != EINPROGRESS) {
 326                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
 327                              "connect failed");
 328                 SET_BLOCKING(fd);
 329                 return;
 330             }
 331 
 332             /*
 333              * Wait for the connection to be established or a
 334              * timeout occurs. poll needs to handle EINTR in
 335              * case lwp sig handler redirects any process signals to
 336              * this thread.
 337              */
 338             while (1) {
 339                 jlong newNanoTime;
 340                 struct pollfd pfd;
 341                 pfd.fd = fd;
 342                 pfd.events = POLLOUT;
 343 
 344                 errno = 0;
 345                 connect_rv = NET_Poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
 346 
 347                 if (connect_rv >= 0) {
 348                     break;
 349                 }
 350                 if (errno != EINTR) {
 351                     break;
 352                 }
 353 
 354                 /*
 355                  * The poll was interrupted so adjust timeout and
 356                  * restart
 357                  */
 358                 newNanoTime = JVM_NanoTime(env, 0);
 359                 nanoTimeout -= (newNanoTime - prevNanoTime);
 360                 if (nanoTimeout < NET_NSEC_PER_MSEC) {
 361                     connect_rv = 0;
 362                     break;
 363                 }
 364                 prevNanoTime = newNanoTime;
 365 
 366             } /* while */
 367 
 368             if (connect_rv == 0) {
 369                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
 370                             "connect timed out");
 371 
 372                 /*
 373                  * Timeout out but connection may still be established.
 374                  * At the high level it should be closed immediately but
 375                  * just in case we make the socket blocking again and
 376                  * shutdown input & output.
 377                  */
 378                 SET_BLOCKING(fd);
 379                 shutdown(fd, 2);
 380                 return;
 381             }
 382 
 383             /* has connection been established */
 384             optlen = sizeof(connect_rv);
 385             if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
 386                            &optlen) <0) {
 387                 connect_rv = errno;
 388             }
 389         }
 390 
 391         /* make socket blocking again */
 392         SET_BLOCKING(fd);
 393 
 394         /* restore errno */
 395         if (connect_rv != 0) {
 396             errno = connect_rv;
 397             connect_rv = -1;
 398         }
 399     }
 400 
 401     /* report the appropriate exception */
 402     if (connect_rv < 0) {
 403 
 404 #ifdef __linux__
 405         /*
 406          * Linux/GNU distribution setup /etc/hosts so that
 407          * InetAddress.getLocalHost gets back the loopback address
 408          * rather than the host address. Thus a socket can be
 409          * bound to the loopback address and the connect will
 410          * fail with EADDRNOTAVAIL. In addition the Linux kernel
 411          * returns the wrong error in this case - it returns EINVAL
 412          * instead of EADDRNOTAVAIL. We handle this here so that
 413          * a more descriptive exception text is used.
 414          */
 415         if (connect_rv == -1 && errno == EINVAL) {
 416             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 417                 "Invalid argument or cannot assign requested address");
 418             return;
 419         }
 420 #endif
 421 #if defined(EPROTO)
 422         if (errno == EPROTO) {
 423             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
 424                            "Protocol error");
 425             return;
 426         }
 427 #endif
 428         if (errno == ECONNREFUSED) {
 429             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
 430                            "Connection refused");
 431         } else if (errno == ETIMEDOUT) {
 432             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
 433                            "Connection timed out");
 434         } else if (errno == EHOSTUNREACH) {
 435             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
 436                            "Host unreachable");
 437         } else if (errno == EADDRNOTAVAIL) {
 438             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
 439                              "Address not available");
 440         } else if ((errno == EISCONN) || (errno == EBADF)) {
 441             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 442                             "Socket closed");
 443         } else {
 444             JNU_ThrowByNameWithMessageAndLastError
 445                 (env, JNU_JAVANETPKG "SocketException", "connect failed");
 446         }
 447         return;
 448     }
 449 
 450     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 451 
 452     /* set the remote peer address and port */
 453     (*env)->SetObjectField(env, this, psi_addressID, iaObj);
 454     (*env)->SetIntField(env, this, psi_portID, port);
 455 
 456     /*
 457      * we need to initialize the local port field if bind was called
 458      * previously to the connect (by the client) then localport field
 459      * will already be initialized
 460      */
 461     if (localport == 0) {
 462         /* Now that we're a connected socket, let's extract the port number
 463          * that the system chose for us and store it in the Socket object.
 464          */
 465         socklen_t slen = sizeof(SOCKETADDRESS);
 466         if (getsockname(fd, &sa.sa, &slen) == -1) {
 467             JNU_ThrowByNameWithMessageAndLastError
 468                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
 469         } else {
 470             localport = NET_GetPortFromSockaddr(&sa);
 471             (*env)->SetIntField(env, this, psi_localportID, localport);
 472         }
 473     }
 474 }
 475 
 476 /*
 477  * Class:     java_net_PlainSocketImpl
 478  * Method:    socketBind
 479  * Signature: (Ljava/net/InetAddress;I)V
 480  */
 481 JNIEXPORT void JNICALL
 482 Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
 483                                          jobject iaObj, jint localport) {
 484 
 485     /* fdObj is the FileDescriptor field on this */
 486     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 487     /* fd is an int field on fdObj */
 488     int fd;
 489     int len = 0;
 490     SOCKETADDRESS sa;
 491 
 492     if (IS_NULL(fdObj)) {
 493         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 494                         "Socket closed");
 495         return;
 496     } else {
 497         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 498     }
 499     if (IS_NULL(iaObj)) {
 500         JNU_ThrowNullPointerException(env, "iaObj is null.");
 501         return;
 502     }
 503 
 504     /* bind */
 505     if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa,
 506                                   &len, JNI_TRUE) != 0) {
 507         return;
 508     }
 509 
 510     if (NET_Bind(fd, &sa, len) < 0) {
 511         if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
 512             errno == EPERM || errno == EACCES) {
 513             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
 514                            "Bind failed");
 515         } else {
 516             JNU_ThrowByNameWithMessageAndLastError
 517                 (env, JNU_JAVANETPKG "SocketException", "Bind failed");
 518         }
 519         return;
 520     }
 521 
 522     /* set the address */
 523     (*env)->SetObjectField(env, this, psi_addressID, iaObj);
 524 
 525     /* initialize the local port */
 526     if (localport == 0) {
 527         socklen_t slen = sizeof(SOCKETADDRESS);
 528         /* Now that we're a connected socket, let's extract the port number
 529          * that the system chose for us and store it in the Socket object.
 530          */
 531         if (getsockname(fd, &sa.sa, &slen) == -1) {
 532             JNU_ThrowByNameWithMessageAndLastError
 533                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
 534             return;
 535         }
 536         localport = NET_GetPortFromSockaddr(&sa);
 537         (*env)->SetIntField(env, this, psi_localportID, localport);
 538     } else {
 539         (*env)->SetIntField(env, this, psi_localportID, localport);
 540     }
 541 }
 542 
 543 /*
 544  * Class:     java_net_PlainSocketImpl
 545  * Method:    socketListen
 546  * Signature: (I)V
 547  */
 548 JNIEXPORT void JNICALL
 549 Java_java_net_PlainSocketImpl_socketListen(JNIEnv *env, jobject this,
 550                                            jint count)
 551 {
 552     /* this FileDescriptor fd field */
 553     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 554     /* fdObj's int fd field */
 555     int fd;
 556 
 557     if (IS_NULL(fdObj)) {
 558         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 559                         "Socket closed");
 560         return;
 561     } else {
 562         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 563     }
 564 
 565     /*
 566      * Workaround for bugid 4101691 in Solaris 2.6. See 4106600.
 567      * If listen backlog is Integer.MAX_VALUE then subtract 1.
 568      */
 569     if (count == 0x7fffffff)
 570         count -= 1;
 571 
 572     if (listen(fd, count) == -1) {
 573         JNU_ThrowByNameWithMessageAndLastError
 574             (env, JNU_JAVANETPKG "SocketException", "Listen failed");
 575     }
 576 }
 577 
 578 /*
 579  * Class:     java_net_PlainSocketImpl
 580  * Method:    socketAccept
 581  * Signature: (Ljava/net/SocketImpl;)V
 582  */
 583 JNIEXPORT void JNICALL
 584 Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
 585                                            jobject socket)
 586 {
 587     /* fields on this */
 588     int port;
 589     jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
 590     jlong prevNanoTime = 0;
 591     jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
 592     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 593 
 594     /* the FileDescriptor field on socket */
 595     jobject socketFdObj;
 596     /* the InetAddress field on socket */
 597     jobject socketAddressObj;
 598 
 599     /* the ServerSocket fd int field on fdObj */
 600     jint fd;
 601 
 602     /* accepted fd */
 603     jint newfd;
 604 
 605     SOCKETADDRESS sa;
 606     socklen_t slen = sizeof(SOCKETADDRESS);
 607 
 608     if (IS_NULL(fdObj)) {
 609         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 610                         "Socket closed");
 611         return;
 612     } else {
 613         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 614     }
 615     if (IS_NULL(socket)) {
 616         JNU_ThrowNullPointerException(env, "socket is null");
 617         return;
 618     }
 619 
 620     /*
 621      * accept connection but ignore ECONNABORTED indicating that
 622      * connection was eagerly accepted by the OS but was reset
 623      * before accept() was called.
 624      *
 625      * If accept timeout in place and timeout is adjusted with
 626      * each ECONNABORTED or EWOULDBLOCK or EAGAIN to ensure that
 627      * semantics of timeout are preserved.
 628      */
 629     for (;;) {
 630         int ret;
 631         jlong currNanoTime;
 632 
 633         /* first usage pick up current time */
 634         if (prevNanoTime == 0 && nanoTimeout > 0) {
 635             prevNanoTime = JVM_NanoTime(env, 0);
 636         }
 637 
 638         /* passing a timeout of 0 to poll will return immediately,
 639            but in the case of ServerSocket 0 means infinite. */
 640         if (timeout <= 0) {
 641             ret = NET_Timeout(env, fd, -1, 0);
 642         } else {
 643             ret = NET_Timeout(env, fd, nanoTimeout / NET_NSEC_PER_MSEC, prevNanoTime);
 644         }
 645         if (ret == 0) {
 646             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
 647                             "Accept timed out");
 648             return;
 649         } else if (ret == -1) {
 650             if (errno == EBADF) {
 651                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
 652             } else if (errno == ENOMEM) {
 653                JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
 654             } else {
 655                JNU_ThrowByNameWithMessageAndLastError
 656                    (env, JNU_JAVANETPKG "SocketException", "Accept failed");
 657             }
 658             return;
 659         }
 660 
 661         newfd = NET_Accept(fd, &sa.sa, &slen);
 662 
 663         /* connection accepted */
 664         if (newfd >= 0) {
 665             SET_BLOCKING(newfd);
 666             break;
 667         }
 668 
 669         /* non (ECONNABORTED or EWOULDBLOCK or EAGAIN) error */
 670         if (!(errno == ECONNABORTED || errno == EWOULDBLOCK || errno == EAGAIN)) {
 671             break;
 672         }
 673 
 674         /* ECONNABORTED or EWOULDBLOCK or EAGAIN error so adjust timeout if there is one. */
 675         if (nanoTimeout >= NET_NSEC_PER_MSEC) {
 676             currNanoTime = JVM_NanoTime(env, 0);
 677             nanoTimeout -= (currNanoTime - prevNanoTime);
 678             if (nanoTimeout < NET_NSEC_PER_MSEC) {
 679                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
 680                         "Accept timed out");
 681                 return;
 682             }
 683             prevNanoTime = currNanoTime;
 684         }
 685     }
 686 
 687     if (newfd < 0) {
 688         if (newfd == -2) {
 689             JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
 690                             "operation interrupted");
 691         } else {
 692             if (errno == EINVAL) {
 693                 errno = EBADF;
 694             }
 695             if (errno == EBADF) {
 696                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
 697             } else {
 698                 JNU_ThrowByNameWithMessageAndLastError
 699                     (env, JNU_JAVANETPKG "SocketException", "Accept failed");
 700             }
 701         }
 702         return;
 703     }
 704 
 705     /*
 706      * fill up the remote peer port and address in the new socket structure.
 707      */
 708     socketAddressObj = NET_SockaddrToInetAddress(env, &sa, &port);
 709     if (socketAddressObj == NULL) {
 710         /* should be pending exception */
 711         close(newfd);
 712         return;
 713     }
 714 
 715     /*
 716      * Populate SocketImpl.fd.fd
 717      */
 718     socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
 719     (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, newfd);
 720 
 721     (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
 722     (*env)->SetIntField(env, socket, psi_portID, port);
 723     /* also fill up the local port information */
 724      port = (*env)->GetIntField(env, this, psi_localportID);
 725     (*env)->SetIntField(env, socket, psi_localportID, port);
 726 }
 727 
 728 
 729 /*
 730  * Class:     java_net_PlainSocketImpl
 731  * Method:    socketAvailable
 732  * Signature: ()I
 733  */
 734 JNIEXPORT jint JNICALL
 735 Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
 736     int count = 0;
 737     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 738     jint fd;
 739 
 740     if (IS_NULL(fdObj)) {
 741         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 742                         "Socket closed");
 743         return -1;
 744     } else {
 745         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 746     }
 747     if (NET_SocketAvailable(fd, &count) != 0) {
 748         if (errno == ECONNRESET) {
 749             JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
 750         } else {
 751             JNU_ThrowByNameWithMessageAndLastError
 752                 (env, JNU_JAVANETPKG "SocketException", "ioctl FIONREAD failed");
 753         }
 754     }
 755     return (jint) count;
 756 }
 757 
 758 /*
 759  * Class:     java_net_PlainSocketImpl
 760  * Method:    socketClose0
 761  * Signature: (Z)V
 762  */
 763 JNIEXPORT void JNICALL
 764 Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
 765                                           jboolean useDeferredClose) {
 766 
 767     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 768     jint fd;
 769 
 770     if (IS_NULL(fdObj)) {
 771         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 772                         "socket already closed");
 773         return;
 774     } else {
 775         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 776     }
 777     if (fd != -1) {
 778         if (useDeferredClose && marker_fd >= 0) {
 779             NET_Dup2(marker_fd, fd);
 780         } else {
 781             (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
 782             NET_SocketClose(fd);
 783         }
 784     }
 785 }
 786 
 787 /*
 788  * Class:     java_net_PlainSocketImpl
 789  * Method:    socketShutdown
 790  * Signature: (I)V
 791  */
 792 JNIEXPORT void JNICALL
 793 Java_java_net_PlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
 794                                              jint howto)
 795 {
 796 
 797     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 798     jint fd;
 799 
 800     /*
 801      * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
 802      * -1 already?
 803      */
 804     if (IS_NULL(fdObj)) {
 805         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 806                         "socket already closed");
 807         return;
 808     } else {
 809         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 810     }
 811     shutdown(fd, howto);
 812 }
 813 
 814 
 815 /*
 816  * Class:     java_net_PlainSocketImpl
 817  * Method:    socketSetOption0
 818  * Signature: (IZLjava/lang/Object;)V
 819  */
 820 JNIEXPORT void JNICALL
 821 Java_java_net_PlainSocketImpl_socketSetOption0
 822   (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
 823 {
 824     int fd;
 825     int level, optname, optlen;
 826     union {
 827         int i;
 828         struct linger ling;
 829     } optval;
 830 
 831     /*
 832      * Check that socket hasn't been closed
 833      */
 834     fd = getFD(env, this);
 835     if (fd < 0) {
 836         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 837                         "Socket closed");
 838         return;
 839     }
 840 
 841     /*
 842      * SO_TIMEOUT is a NOOP on Solaris/Linux
 843      */
 844     if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
 845         return;
 846     }
 847 
 848     /*
 849      * Map the Java level socket option to the platform specific
 850      * level and option name.
 851      */
 852     if (NET_MapSocketOption(cmd, &level, &optname)) {
 853         JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
 854         return;
 855     }
 856 
 857     switch (cmd) {
 858         case java_net_SocketOptions_SO_SNDBUF :
 859         case java_net_SocketOptions_SO_RCVBUF :
 860         case java_net_SocketOptions_SO_LINGER :
 861         case java_net_SocketOptions_IP_TOS :
 862             {
 863                 jclass cls;
 864                 jfieldID fid;
 865 
 866                 cls = (*env)->FindClass(env, "java/lang/Integer");
 867                 CHECK_NULL(cls);
 868                 fid = (*env)->GetFieldID(env, cls, "value", "I");
 869                 CHECK_NULL(fid);
 870 
 871                 if (cmd == java_net_SocketOptions_SO_LINGER) {
 872                     if (on) {
 873                         optval.ling.l_onoff = 1;
 874                         optval.ling.l_linger = (*env)->GetIntField(env, value, fid);
 875                     } else {
 876                         optval.ling.l_onoff = 0;
 877                         optval.ling.l_linger = 0;
 878                     }
 879                     optlen = sizeof(optval.ling);
 880                 } else {
 881                     optval.i = (*env)->GetIntField(env, value, fid);
 882                     optlen = sizeof(optval.i);
 883                 }
 884 
 885                 break;
 886             }
 887 
 888         /* Boolean -> int */
 889         default :
 890             optval.i = (on ? 1 : 0);
 891             optlen = sizeof(optval.i);
 892 
 893     }
 894 
 895     if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
 896 #if defined(__solaris__) || defined(_AIX)
 897         if (errno == EINVAL) {
 898             // On Solaris setsockopt will set errno to EINVAL if the socket
 899             // is closed. The default error message is then confusing
 900             char fullMsg[128];
 901             jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
 902             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
 903             return;
 904         }
 905 #endif /* __solaris__ */
 906         JNU_ThrowByNameWithMessageAndLastError
 907             (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
 908     }
 909 }
 910 
 911 /*
 912  * Class:     java_net_PlainSocketImpl
 913  * Method:    socketGetOption
 914  * Signature: (ILjava/lang/Object;)I
 915  */
 916 JNIEXPORT jint JNICALL
 917 Java_java_net_PlainSocketImpl_socketGetOption
 918   (JNIEnv *env, jobject this, jint cmd, jobject iaContainerObj)
 919 {
 920     int fd;
 921     int level, optname, optlen;
 922     union {
 923         int i;
 924         struct linger ling;
 925     } optval;
 926 
 927     /*
 928      * Check that socket hasn't been closed
 929      */
 930     fd = getFD(env, this);
 931     if (fd < 0) {
 932         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 933                         "Socket closed");
 934         return -1;
 935     }
 936 
 937     /*
 938      * SO_BINDADDR isn't a socket option
 939      */
 940     if (cmd == java_net_SocketOptions_SO_BINDADDR) {
 941         SOCKETADDRESS sa;
 942         socklen_t len = sizeof(SOCKETADDRESS);
 943         int port;
 944         jobject iaObj;
 945         jclass iaCntrClass;
 946         jfieldID iaFieldID;
 947 
 948         if (getsockname(fd, &sa.sa, &len) < 0) {
 949             JNU_ThrowByNameWithMessageAndLastError
 950                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
 951             return -1;
 952         }
 953         iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
 954         CHECK_NULL_RETURN(iaObj, -1);
 955 
 956         iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
 957         iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
 958         CHECK_NULL_RETURN(iaFieldID, -1);
 959         (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
 960         return 0; /* notice change from before */
 961     }
 962 
 963     /*
 964      * Map the Java level socket option to the platform specific
 965      * level and option name.
 966      */
 967     if (NET_MapSocketOption(cmd, &level, &optname)) {
 968         JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
 969         return -1;
 970     }
 971 
 972     /*
 973      * Args are int except for SO_LINGER
 974      */
 975     if (cmd == java_net_SocketOptions_SO_LINGER) {
 976         optlen = sizeof(optval.ling);
 977     } else {
 978         optlen = sizeof(optval.i);
 979     }
 980 
 981     if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
 982         JNU_ThrowByNameWithMessageAndLastError
 983             (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
 984         return -1;
 985     }
 986 
 987     switch (cmd) {
 988         case java_net_SocketOptions_SO_LINGER:
 989             return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
 990 
 991         case java_net_SocketOptions_SO_SNDBUF:
 992         case java_net_SocketOptions_SO_RCVBUF:
 993         case java_net_SocketOptions_IP_TOS:
 994             return optval.i;
 995 
 996         default :
 997             return (optval.i == 0) ? -1 : 1;
 998     }
 999 }
1000 
1001 
1002 /*
1003  * Class:     java_net_PlainSocketImpl
1004  * Method:    socketSendUrgentData
1005  * Signature: (B)V
1006  */
1007 JNIEXPORT void JNICALL
1008 Java_java_net_PlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this,
1009                                              jint data) {
1010     /* The fd field */
1011     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
1012     int n, fd;
1013     unsigned char d = data & 0xFF;
1014 
1015     if (IS_NULL(fdObj)) {
1016         JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1017         return;
1018     } else {
1019         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
1020         /* Bug 4086704 - If the Socket associated with this file descriptor
1021          * was closed (sysCloseFD), the file descriptor is set to -1.
1022          */
1023         if (fd == -1) {
1024             JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1025             return;
1026         }
1027 
1028     }
1029     n = NET_Send(fd, (char *)&d, 1, MSG_OOB);
1030     if (n == -1) {
1031         JNU_ThrowIOExceptionWithLastError(env, "Write failed");
1032     }
1033 }