1 /*
   2  * Copyright (c) 1997, 2016, 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 
  26 #include <winsock2.h>
  27 #include <ws2tcpip.h>
  28 
  29 #include "net_util.h"
  30 #include "jni.h"
  31 
  32 // Taken from mstcpip.h in Windows SDK 8.0 or newer.
  33 #define SIO_LOOPBACK_FAST_PATH              _WSAIOW(IOC_VENDOR,16)
  34 
  35 #ifndef IPTOS_TOS_MASK
  36 #define IPTOS_TOS_MASK 0x1e
  37 #endif
  38 #ifndef IPTOS_PREC_MASK
  39 #define IPTOS_PREC_MASK 0xe0
  40 #endif
  41 
  42 /* true if SO_RCVTIMEO is supported */
  43 jboolean isRcvTimeoutSupported = JNI_TRUE;
  44 
  45 /*
  46  * Table of Windows Sockets errors, the specific exception we
  47  * throw for the error, and the error text.
  48  *
  49  * Note that this table excludes OS dependent errors.
  50  *
  51  * Latest list of Windows Sockets errors can be found at :-
  52  * http://msdn.microsoft.com/library/psdk/winsock/errors_3wc2.htm
  53  */
  54 static struct {
  55     int errCode;
  56     const char *exc;
  57     const char *errString;
  58 } const winsock_errors[] = {
  59     { WSAEACCES,                0,      "Permission denied" },
  60     { WSAEADDRINUSE,            "BindException",        "Address already in use" },
  61     { WSAEADDRNOTAVAIL,         "BindException",        "Cannot assign requested address" },
  62     { WSAEAFNOSUPPORT,          0,      "Address family not supported by protocol family" },
  63     { WSAEALREADY,              0,      "Operation already in progress" },
  64     { WSAECONNABORTED,          0,      "Software caused connection abort" },
  65     { WSAECONNREFUSED,          "ConnectException",     "Connection refused" },
  66     { WSAECONNRESET,            0,      "Connection reset by peer" },
  67     { WSAEDESTADDRREQ,          0,      "Destination address required" },
  68     { WSAEFAULT,                0,      "Bad address" },
  69     { WSAEHOSTDOWN,             0,      "Host is down" },
  70     { WSAEHOSTUNREACH,          "NoRouteToHostException",       "No route to host" },
  71     { WSAEINPROGRESS,           0,      "Operation now in progress" },
  72     { WSAEINTR,                 0,      "Interrupted function call" },
  73     { WSAEINVAL,                0,      "Invalid argument" },
  74     { WSAEISCONN,               0,      "Socket is already connected" },
  75     { WSAEMFILE,                0,      "Too many open files" },
  76     { WSAEMSGSIZE,              0,      "The message is larger than the maximum supported by the underlying transport" },
  77     { WSAENETDOWN,              0,      "Network is down" },
  78     { WSAENETRESET,             0,      "Network dropped connection on reset" },
  79     { WSAENETUNREACH,           0,      "Network is unreachable" },
  80     { WSAENOBUFS,               0,      "No buffer space available (maximum connections reached?)" },
  81     { WSAENOPROTOOPT,           0,      "Bad protocol option" },
  82     { WSAENOTCONN,              0,      "Socket is not connected" },
  83     { WSAENOTSOCK,              0,      "Socket operation on nonsocket" },
  84     { WSAEOPNOTSUPP,            0,      "Operation not supported" },
  85     { WSAEPFNOSUPPORT,          0,      "Protocol family not supported" },
  86     { WSAEPROCLIM,              0,      "Too many processes" },
  87     { WSAEPROTONOSUPPORT,       0,      "Protocol not supported" },
  88     { WSAEPROTOTYPE,            0,      "Protocol wrong type for socket" },
  89     { WSAESHUTDOWN,             0,      "Cannot send after socket shutdown" },
  90     { WSAESOCKTNOSUPPORT,       0,      "Socket type not supported" },
  91     { WSAETIMEDOUT,             "ConnectException",     "Connection timed out" },
  92     { WSATYPE_NOT_FOUND,        0,      "Class type not found" },
  93     { WSAEWOULDBLOCK,           0,      "Resource temporarily unavailable" },
  94     { WSAHOST_NOT_FOUND,        0,      "Host not found" },
  95     { WSA_NOT_ENOUGH_MEMORY,    0,      "Insufficient memory available" },
  96     { WSANOTINITIALISED,        0,      "Successful WSAStartup not yet performed" },
  97     { WSANO_DATA,               0,      "Valid name, no data record of requested type" },
  98     { WSANO_RECOVERY,           0,      "This is a nonrecoverable error" },
  99     { WSASYSNOTREADY,           0,      "Network subsystem is unavailable" },
 100     { WSATRY_AGAIN,             0,      "Nonauthoritative host not found" },
 101     { WSAVERNOTSUPPORTED,       0,      "Winsock.dll version out of range" },
 102     { WSAEDISCON,               0,      "Graceful shutdown in progress" },
 103     { WSA_OPERATION_ABORTED,    0,      "Overlapped operation aborted" },
 104 };
 105 
 106 /*
 107  * Initialize Windows Sockets API support
 108  */
 109 BOOL WINAPI
 110 DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
 111 {
 112     WSADATA wsadata;
 113 
 114     switch (reason) {
 115         case DLL_PROCESS_ATTACH:
 116             if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) {
 117                 return FALSE;
 118             }
 119             break;
 120 
 121         case DLL_PROCESS_DETACH:
 122             WSACleanup();
 123             break;
 124 
 125         default:
 126             break;
 127     }
 128     return TRUE;
 129 }
 130 
 131 void platformInit() {}
 132 void parseExclusiveBindProperty(JNIEnv *env) {}
 133 
 134 /*
 135  * Since winsock doesn't have the equivalent of strerror(errno)
 136  * use table to lookup error text for the error.
 137  */
 138 JNIEXPORT void JNICALL
 139 NET_ThrowNew(JNIEnv *env, int errorNum, char *msg)
 140 {
 141     int i;
 142     int table_size = sizeof(winsock_errors) /
 143                      sizeof(winsock_errors[0]);
 144     char exc[256];
 145     char fullMsg[256];
 146     char *excP = NULL;
 147 
 148     /*
 149      * If exception already throw then don't overwrite it.
 150      */
 151     if ((*env)->ExceptionOccurred(env)) {
 152         return;
 153     }
 154 
 155     /*
 156      * Default message text if not provided
 157      */
 158     if (!msg) {
 159         msg = "no further information";
 160     }
 161 
 162     /*
 163      * Check table for known winsock errors
 164      */
 165     i=0;
 166     while (i < table_size) {
 167         if (errorNum == winsock_errors[i].errCode) {
 168             break;
 169         }
 170         i++;
 171     }
 172 
 173     /*
 174      * If found get pick the specific exception and error
 175      * message corresponding to this error.
 176      */
 177     if (i < table_size) {
 178         excP = (char *)winsock_errors[i].exc;
 179         jio_snprintf(fullMsg, sizeof(fullMsg), "%s: %s",
 180                      (char *)winsock_errors[i].errString, msg);
 181     } else {
 182         jio_snprintf(fullMsg, sizeof(fullMsg),
 183                      "Unrecognized Windows Sockets error: %d: %s",
 184                      errorNum, msg);
 185 
 186     }
 187 
 188     /*
 189      * Throw SocketException if no specific exception for this
 190      * error.
 191      */
 192     if (excP == NULL) {
 193         excP = "SocketException";
 194     }
 195     sprintf(exc, "%s%s", JNU_JAVANETPKG, excP);
 196     JNU_ThrowByName(env, exc, fullMsg);
 197 }
 198 
 199 void
 200 NET_ThrowCurrent(JNIEnv *env, char *msg)
 201 {
 202     NET_ThrowNew(env, WSAGetLastError(), msg);
 203 }
 204 
 205 void
 206 NET_ThrowSocketException(JNIEnv *env, char* msg)
 207 {
 208     static jclass cls = NULL;
 209     if (cls == NULL) {
 210         cls = (*env)->FindClass(env, "java/net/SocketException");
 211         CHECK_NULL(cls);
 212         cls = (*env)->NewGlobalRef(env, cls);
 213         CHECK_NULL(cls);
 214     }
 215     (*env)->ThrowNew(env, cls, msg);
 216 }
 217 
 218 void
 219 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
 220                    const char *defaultDetail) {
 221     char errmsg[255];
 222     sprintf(errmsg, "errno: %d, error: %s\n", WSAGetLastError(), defaultDetail);
 223     JNU_ThrowByNameWithLastError(env, name, errmsg);
 224 }
 225 
 226 jfieldID
 227 NET_GetFileDescriptorID(JNIEnv *env)
 228 {
 229     jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");
 230     CHECK_NULL_RETURN(cls, NULL);
 231     return (*env)->GetFieldID(env, cls, "fd", "I");
 232 }
 233 
 234 jint  IPv6_supported()
 235 {
 236     SOCKET s = socket(AF_INET6, SOCK_STREAM, 0) ;
 237     if (s == INVALID_SOCKET) {
 238         return JNI_FALSE;
 239     }
 240     closesocket(s);
 241 
 242     return JNI_TRUE;
 243 }
 244 
 245 jint reuseport_supported()
 246 {
 247     /* SO_REUSEPORT is not supported onn Windows */
 248     return JNI_FALSE;
 249 }
 250 /*
 251  * Return the default TOS value
 252  */
 253 int NET_GetDefaultTOS() {
 254     static int default_tos = -1;
 255     OSVERSIONINFO ver;
 256     HKEY hKey;
 257     LONG ret;
 258 
 259     /*
 260      * If default ToS already determined then return it
 261      */
 262     if (default_tos >= 0) {
 263         return default_tos;
 264     }
 265 
 266     /*
 267      * Assume default is "normal service"
 268      */
 269     default_tos = 0;
 270 
 271     /*
 272      * Which OS is this?
 273      */
 274     ver.dwOSVersionInfoSize = sizeof(ver);
 275     GetVersionEx(&ver);
 276 
 277     /*
 278      * If 2000 or greater then no default ToS in registry
 279      */
 280     if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
 281         if (ver.dwMajorVersion >= 5) {
 282             return default_tos;
 283         }
 284     }
 285 
 286     /*
 287      * Query the registry to see if a Default ToS has been set.
 288      * Different registry entry for NT vs 95/98/ME.
 289      */
 290     if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
 291         ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 292                            "SYSTEM\\CurrentControlSet\\Services\\Tcp\\Parameters",
 293                            0, KEY_READ, (PHKEY)&hKey);
 294     } else {
 295         ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 296                            "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP\\Parameters",
 297                            0, KEY_READ, (PHKEY)&hKey);
 298     }
 299     if (ret == ERROR_SUCCESS) {
 300         DWORD dwLen;
 301         DWORD dwDefaultTOS;
 302         ULONG ulType;
 303         dwLen = sizeof(dwDefaultTOS);
 304 
 305         ret = RegQueryValueEx(hKey, "DefaultTOS",  NULL, &ulType,
 306                              (LPBYTE)&dwDefaultTOS, &dwLen);
 307         RegCloseKey(hKey);
 308         if (ret == ERROR_SUCCESS) {
 309             default_tos = (int)dwDefaultTOS;
 310         }
 311     }
 312     return default_tos;
 313 }
 314 
 315 /* call NET_MapSocketOptionV6 for the IPv6 fd only
 316  * and NET_MapSocketOption for the IPv4 fd
 317  */
 318 JNIEXPORT int JNICALL
 319 NET_MapSocketOptionV6(jint cmd, int *level, int *optname) {
 320 
 321     switch (cmd) {
 322         case java_net_SocketOptions_IP_MULTICAST_IF:
 323         case java_net_SocketOptions_IP_MULTICAST_IF2:
 324             *level = IPPROTO_IPV6;
 325             *optname = IPV6_MULTICAST_IF;
 326             return 0;
 327 
 328         case java_net_SocketOptions_IP_MULTICAST_LOOP:
 329             *level = IPPROTO_IPV6;
 330             *optname = IPV6_MULTICAST_LOOP;
 331             return 0;
 332     }
 333     return NET_MapSocketOption (cmd, level, optname);
 334 }
 335 
 336 /*
 337  * Map the Java level socket option to the platform specific
 338  * level and option name.
 339  */
 340 
 341 JNIEXPORT int JNICALL
 342 NET_MapSocketOption(jint cmd, int *level, int *optname) {
 343 
 344     typedef struct {
 345         jint cmd;
 346         int level;
 347         int optname;
 348     } sockopts;
 349 
 350     static sockopts opts[] = {
 351         { java_net_SocketOptions_TCP_NODELAY,   IPPROTO_TCP,    TCP_NODELAY },
 352         { java_net_SocketOptions_SO_OOBINLINE,  SOL_SOCKET,     SO_OOBINLINE },
 353         { java_net_SocketOptions_SO_LINGER,     SOL_SOCKET,     SO_LINGER },
 354         { java_net_SocketOptions_SO_SNDBUF,     SOL_SOCKET,     SO_SNDBUF },
 355         { java_net_SocketOptions_SO_RCVBUF,     SOL_SOCKET,     SO_RCVBUF },
 356         { java_net_SocketOptions_SO_KEEPALIVE,  SOL_SOCKET,     SO_KEEPALIVE },
 357         { java_net_SocketOptions_SO_REUSEADDR,  SOL_SOCKET,     SO_REUSEADDR },
 358         { java_net_SocketOptions_SO_BROADCAST,  SOL_SOCKET,     SO_BROADCAST },
 359         { java_net_SocketOptions_IP_MULTICAST_IF,   IPPROTO_IP, IP_MULTICAST_IF },
 360         { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },
 361         { java_net_SocketOptions_IP_TOS,            IPPROTO_IP, IP_TOS },
 362 
 363     };
 364 
 365 
 366     int i;
 367 
 368     /*
 369      * Map the Java level option to the native level
 370      */
 371     for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
 372         if (cmd == opts[i].cmd) {
 373             *level = opts[i].level;
 374             *optname = opts[i].optname;
 375             return 0;
 376         }
 377     }
 378 
 379     /* not found */
 380     return -1;
 381 }
 382 
 383 
 384 /*
 385  * Wrapper for setsockopt dealing with Windows specific issues :-
 386  *
 387  * IP_TOS and IP_MULTICAST_LOOP can't be set on some Windows
 388  * editions.
 389  *
 390  * The value for the type-of-service (TOS) needs to be masked
 391  * to get consistent behaviour with other operating systems.
 392  */
 393 JNIEXPORT int JNICALL
 394 NET_SetSockOpt(int s, int level, int optname, const void *optval,
 395                int optlen)
 396 {
 397     int rv = 0;
 398     int parg = 0;
 399     int plen = sizeof(parg);
 400 
 401     if (level == IPPROTO_IP && optname == IP_TOS) {
 402         int *tos = (int *)optval;
 403         *tos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
 404     }
 405 
 406     if (optname == SO_REUSEADDR) {
 407         /*
 408          * Do not set SO_REUSEADDE if SO_EXCLUSIVEADDUSE is already set
 409          */
 410         rv = NET_GetSockOpt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&parg, &plen);
 411         if (rv == 0 && parg == 1) {
 412             return rv;
 413         }
 414     }
 415 
 416     rv = setsockopt(s, level, optname, optval, optlen);
 417 
 418     if (rv == SOCKET_ERROR) {
 419         /*
 420          * IP_TOS & IP_MULTICAST_LOOP can't be set on some versions
 421          * of Windows.
 422          */
 423         if ((WSAGetLastError() == WSAENOPROTOOPT) &&
 424             (level == IPPROTO_IP) &&
 425             (optname == IP_TOS || optname == IP_MULTICAST_LOOP)) {
 426             rv = 0;
 427         }
 428 
 429         /*
 430          * IP_TOS can't be set on unbound UDP sockets.
 431          */
 432         if ((WSAGetLastError() == WSAEINVAL) &&
 433             (level == IPPROTO_IP) &&
 434             (optname == IP_TOS)) {
 435             rv = 0;
 436         }
 437     }
 438 
 439     return rv;
 440 }
 441 
 442 /*
 443  * Wrapper for setsockopt dealing with Windows specific issues :-
 444  *
 445  * IP_TOS is not supported on some versions of Windows so
 446  * instead return the default value for the OS.
 447  */
 448 JNIEXPORT int JNICALL
 449 NET_GetSockOpt(int s, int level, int optname, void *optval,
 450                int *optlen)
 451 {
 452     int rv;
 453 
 454     if (level == IPPROTO_IPV6 && optname == IPV6_TCLASS) {
 455         int *intopt = (int *)optval;
 456         *intopt = 0;
 457         *optlen = sizeof(*intopt);
 458         return 0;
 459     }
 460 
 461     rv = getsockopt(s, level, optname, optval, optlen);
 462 
 463 
 464     /*
 465      * IPPROTO_IP/IP_TOS is not supported on some Windows
 466      * editions so return the default type-of-service
 467      * value.
 468      */
 469     if (rv == SOCKET_ERROR) {
 470 
 471         if (WSAGetLastError() == WSAENOPROTOOPT &&
 472             level == IPPROTO_IP && optname == IP_TOS) {
 473 
 474             int *tos;
 475             tos = (int *)optval;
 476             *tos = NET_GetDefaultTOS();
 477 
 478             rv = 0;
 479         }
 480     }
 481 
 482     return rv;
 483 }
 484 
 485 /*
 486  * Sets SO_ECLUSIVEADDRUSE if SO_REUSEADDR is not already set.
 487  */
 488 void setExclusiveBind(int fd) {
 489     int parg = 0;
 490     int plen = sizeof(parg);
 491     int rv = 0;
 492     rv = NET_GetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&parg, &plen);
 493     if (rv == 0 && parg == 0) {
 494         parg = 1;
 495         rv = NET_SetSockOpt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&parg, plen);
 496     }
 497 }
 498 
 499 /*
 500  * Wrapper for bind winsock call - transparent converts an
 501  * error related to binding to a port that has exclusive access
 502  * into an error indicating the port is in use (facilitates
 503  * better error reporting).
 504  *
 505  * Should be only called by the wrapper method NET_WinBind
 506  */
 507 JNIEXPORT int JNICALL
 508 NET_Bind(int s, struct sockaddr *him, int len)
 509 {
 510     int rv = 0;
 511     rv = bind(s, him, len);
 512 
 513     if (rv == SOCKET_ERROR) {
 514         /*
 515          * If bind fails with WSAEACCES it means that a privileged
 516          * process has done an exclusive bind (NT SP4/2000/XP only).
 517          */
 518         if (WSAGetLastError() == WSAEACCES) {
 519             WSASetLastError(WSAEADDRINUSE);
 520         }
 521     }
 522 
 523     return rv;
 524 }
 525 
 526 /*
 527  * Wrapper for NET_Bind call. Sets SO_EXCLUSIVEADDRUSE
 528  * if required, and then calls NET_BIND
 529  */
 530 JNIEXPORT int JNICALL
 531 NET_WinBind(int s, struct sockaddr *him, int len, jboolean exclBind)
 532 {
 533     if (exclBind == JNI_TRUE)
 534         setExclusiveBind(s);
 535     return NET_Bind(s, him, len);
 536 }
 537 
 538 JNIEXPORT int JNICALL
 539 NET_SocketClose(int fd) {
 540     struct linger l = {0, 0};
 541     int ret = 0;
 542     int len = sizeof (l);
 543     if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) {
 544         if (l.l_onoff == 0) {
 545             WSASendDisconnect(fd, NULL);
 546         }
 547     }
 548     ret = closesocket (fd);
 549     return ret;
 550 }
 551 
 552 JNIEXPORT int JNICALL
 553 NET_Timeout(int fd, long timeout) {
 554     int ret;
 555     fd_set tbl;
 556     struct timeval t;
 557     t.tv_sec = timeout / 1000;
 558     t.tv_usec = (timeout % 1000) * 1000;
 559     FD_ZERO(&tbl);
 560     FD_SET(fd, &tbl);
 561     ret = select (fd + 1, &tbl, 0, 0, &t);
 562     return ret;
 563 }
 564 
 565 
 566 /*
 567  * differs from NET_Timeout() as follows:
 568  *
 569  * If timeout = -1, it blocks forever.
 570  *
 571  * returns 1 or 2 depending if only one or both sockets
 572  * fire at same time.
 573  *
 574  * *fdret is (one of) the active fds. If both sockets
 575  * fire at same time, *fdret = fd always.
 576  */
 577 JNIEXPORT int JNICALL
 578 NET_Timeout2(int fd, int fd1, long timeout, int *fdret) {
 579     int ret;
 580     fd_set tbl;
 581     struct timeval t, *tP = &t;
 582     if (timeout == -1) {
 583         tP = 0;
 584     } else {
 585         t.tv_sec = timeout / 1000;
 586         t.tv_usec = (timeout % 1000) * 1000;
 587     }
 588     FD_ZERO(&tbl);
 589     FD_SET(fd, &tbl);
 590     FD_SET(fd1, &tbl);
 591     ret = select (0, &tbl, 0, 0, tP);
 592     switch (ret) {
 593     case 0:
 594         return 0; /* timeout */
 595     case 1:
 596         if (FD_ISSET (fd, &tbl)) {
 597             *fdret= fd;
 598         } else {
 599             *fdret= fd1;
 600         }
 601         return 1;
 602     case 2:
 603         *fdret= fd;
 604         return 2;
 605     }
 606     return -1;
 607 }
 608 
 609 
 610 void dumpAddr (char *str, void *addr) {
 611     struct SOCKADDR_IN6 *a = (struct SOCKADDR_IN6 *)addr;
 612     int family = a->sin6_family;
 613     printf ("%s\n", str);
 614     if (family == AF_INET) {
 615         struct sockaddr_in *him = (struct sockaddr_in *)addr;
 616         printf ("AF_INET: port %d: %x\n", ntohs(him->sin_port),
 617                                           ntohl(him->sin_addr.s_addr));
 618     } else {
 619         int i;
 620         struct in6_addr *in = &a->sin6_addr;
 621         printf ("AF_INET6 ");
 622         printf ("port %d ", ntohs (a->sin6_port));
 623         printf ("flow %d ", a->sin6_flowinfo);
 624         printf ("addr ");
 625         for (i=0; i<7; i++) {
 626             printf ("%04x:", ntohs(in->s6_words[i]));
 627         }
 628         printf ("%04x", ntohs(in->s6_words[7]));
 629         printf (" scope %d\n", a->sin6_scope_id);
 630     }
 631 }
 632 
 633 /* Macro, which cleans-up the iv6bind structure,
 634  * closes the two sockets (if open),
 635  * and returns SOCKET_ERROR. Used in NET_BindV6 only.
 636  */
 637 
 638 #define CLOSE_SOCKETS_AND_RETURN do {   \
 639     if (fd != -1) {                     \
 640         closesocket (fd);               \
 641         fd = -1;                        \
 642     }                                   \
 643     if (ofd != -1) {                    \
 644         closesocket (ofd);              \
 645         ofd = -1;                       \
 646     }                                   \
 647     if (close_fd != -1) {               \
 648         closesocket (close_fd);         \
 649         close_fd = -1;                  \
 650     }                                   \
 651     if (close_ofd != -1) {              \
 652         closesocket (close_ofd);        \
 653         close_ofd = -1;                 \
 654     }                                   \
 655     b->ipv4_fd = b->ipv6_fd = -1;       \
 656     return SOCKET_ERROR;                \
 657 } while(0)
 658 
 659 /*
 660  * if ipv6 is available, call NET_BindV6 to bind to the required address/port.
 661  * Because the same port number may need to be reserved in both v4 and v6 space,
 662  * this may require socket(s) to be re-opened. Therefore, all of this information
 663  * is passed in and returned through the ipv6bind structure.
 664  *
 665  * If the request is to bind to a specific address, then this (by definition) means
 666  * only bind in either v4 or v6, and this is just the same as normal. ie. a single
 667  * call to bind() will suffice. The other socket is closed in this case.
 668  *
 669  * The more complicated case is when the requested address is ::0 or 0.0.0.0.
 670  *
 671  * Two further cases:
 672  * 2. If the reqeusted port is 0 (ie. any port) then we try to bind in v4 space
 673  *    first with a wild-card port argument. We then try to bind in v6 space
 674  *    using the returned port number. If this fails, we repeat the process
 675  *    until a free port common to both spaces becomes available.
 676  *
 677  * 3. If the requested port is a specific port, then we just try to get that
 678  *    port in both spaces, and if it is not free in both, then the bind fails.
 679  *
 680  * On failure, sockets are closed and an error returned with CLOSE_SOCKETS_AND_RETURN
 681  */
 682 
 683 JNIEXPORT int JNICALL
 684 NET_BindV6(struct ipv6bind* b, jboolean exclBind) {
 685     int fd=-1, ofd=-1, rv, len;
 686     /* need to defer close until new sockets created */
 687     int close_fd=-1, close_ofd=-1;
 688     SOCKETADDRESS oaddr; /* other address to bind */
 689     int family = b->addr->him.sa_family;
 690     int ofamily;
 691     u_short port; /* requested port parameter */
 692     u_short bound_port;
 693 
 694     if (family == AF_INET && (b->addr->him4.sin_addr.s_addr != INADDR_ANY)) {
 695         /* bind to v4 only */
 696         int ret;
 697         ret = NET_WinBind ((int)b->ipv4_fd, (struct sockaddr *)b->addr,
 698                                 sizeof (struct sockaddr_in), exclBind);
 699         if (ret == SOCKET_ERROR) {
 700             CLOSE_SOCKETS_AND_RETURN;
 701         }
 702         closesocket (b->ipv6_fd);
 703         b->ipv6_fd = -1;
 704         return 0;
 705     }
 706     if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->him6.sin6_addr))) {
 707         /* bind to v6 only */
 708         int ret;
 709         ret = NET_WinBind ((int)b->ipv6_fd, (struct sockaddr *)b->addr,
 710                                 sizeof (struct SOCKADDR_IN6), exclBind);
 711         if (ret == SOCKET_ERROR) {
 712             CLOSE_SOCKETS_AND_RETURN;
 713         }
 714         closesocket (b->ipv4_fd);
 715         b->ipv4_fd = -1;
 716         return 0;
 717     }
 718 
 719     /* We need to bind on both stacks, with the same port number */
 720 
 721     memset (&oaddr, 0, sizeof(oaddr));
 722     if (family == AF_INET) {
 723         ofamily = AF_INET6;
 724         fd = (int)b->ipv4_fd;
 725         ofd = (int)b->ipv6_fd;
 726         port = (u_short)GET_PORT (b->addr);
 727         IN6ADDR_SETANY (&oaddr.him6);
 728         oaddr.him6.sin6_port = port;
 729     } else {
 730         ofamily = AF_INET;
 731         ofd = (int)b->ipv4_fd;
 732         fd = (int)b->ipv6_fd;
 733         port = (u_short)GET_PORT (b->addr);
 734         oaddr.him4.sin_family = AF_INET;
 735         oaddr.him4.sin_port = port;
 736         oaddr.him4.sin_addr.s_addr = INADDR_ANY;
 737     }
 738 
 739     rv = NET_WinBind(fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr), exclBind);
 740     if (rv == SOCKET_ERROR) {
 741         CLOSE_SOCKETS_AND_RETURN;
 742     }
 743 
 744     /* get the port and set it in the other address */
 745     len = SOCKETADDRESS_LEN(b->addr);
 746     if (getsockname(fd, (struct sockaddr *)b->addr, &len) == -1) {
 747         CLOSE_SOCKETS_AND_RETURN;
 748     }
 749     bound_port = GET_PORT (b->addr);
 750     SET_PORT (&oaddr, bound_port);
 751     if ((rv=NET_WinBind (ofd, (struct sockaddr *) &oaddr,
 752                          SOCKETADDRESS_LEN (&oaddr), exclBind)) == SOCKET_ERROR) {
 753         int retries;
 754         int sotype, arglen=sizeof(sotype);
 755 
 756         /* no retries unless, the request was for any free port */
 757 
 758         if (port != 0) {
 759             CLOSE_SOCKETS_AND_RETURN;
 760         }
 761 
 762         getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen);
 763 
 764 #define SOCK_RETRIES 50
 765         /* 50 is an arbitrary limit, just to ensure that this
 766          * cannot be an endless loop. Would expect socket creation to
 767          * succeed sooner.
 768          */
 769         for (retries = 0; retries < SOCK_RETRIES; retries ++) {
 770             int len;
 771             close_fd = fd; fd = -1;
 772             close_ofd = ofd; ofd = -1;
 773             b->ipv4_fd = SOCKET_ERROR;
 774             b->ipv6_fd = SOCKET_ERROR;
 775 
 776             /* create two new sockets */
 777             fd = (int)socket (family, sotype, 0);
 778             if (fd == SOCKET_ERROR) {
 779                 CLOSE_SOCKETS_AND_RETURN;
 780             }
 781             ofd = (int)socket (ofamily, sotype, 0);
 782             if (ofd == SOCKET_ERROR) {
 783                 CLOSE_SOCKETS_AND_RETURN;
 784             }
 785 
 786             /* bind random port on first socket */
 787             SET_PORT (&oaddr, 0);
 788             rv = NET_WinBind (ofd, (struct sockaddr *)&oaddr, SOCKETADDRESS_LEN(&oaddr),
 789                               exclBind);
 790             if (rv == SOCKET_ERROR) {
 791                 CLOSE_SOCKETS_AND_RETURN;
 792             }
 793             /* close the original pair of sockets before continuing */
 794             closesocket (close_fd);
 795             closesocket (close_ofd);
 796             close_fd = close_ofd = -1;
 797 
 798             /* bind new port on second socket */
 799             len = SOCKETADDRESS_LEN(&oaddr);
 800             if (getsockname(ofd, (struct sockaddr *)&oaddr, &len) == -1) {
 801                 CLOSE_SOCKETS_AND_RETURN;
 802             }
 803             bound_port = GET_PORT (&oaddr);
 804             SET_PORT (b->addr, bound_port);
 805             rv = NET_WinBind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr),
 806                               exclBind);
 807 
 808             if (rv != SOCKET_ERROR) {
 809                 if (family == AF_INET) {
 810                     b->ipv4_fd = fd;
 811                     b->ipv6_fd = ofd;
 812                 } else {
 813                     b->ipv4_fd = ofd;
 814                     b->ipv6_fd = fd;
 815                 }
 816                 return 0;
 817             }
 818         }
 819         CLOSE_SOCKETS_AND_RETURN;
 820     }
 821     return 0;
 822 }
 823 
 824 /*
 825  * Determine the default interface for an IPv6 address.
 826  *
 827  * Returns :-
 828  *      0 if error
 829  *      > 0 interface index to use
 830  */
 831 jint getDefaultIPv6Interface(JNIEnv *env, struct SOCKADDR_IN6 *target_addr)
 832 {
 833     int ret;
 834     DWORD b;
 835     struct sockaddr_in6 route;
 836     SOCKET fd = socket(AF_INET6, SOCK_STREAM, 0);
 837     if (fd == INVALID_SOCKET) {
 838         return 0;
 839     }
 840 
 841     ret = WSAIoctl(fd, SIO_ROUTING_INTERFACE_QUERY,
 842                     (void *)target_addr, sizeof(struct sockaddr_in6),
 843                     (void *)&route, sizeof(struct sockaddr_in6),
 844                     &b, 0, 0);
 845     if (ret == SOCKET_ERROR) {
 846         // error
 847         closesocket(fd);
 848         return 0;
 849     } else {
 850         closesocket(fd);
 851         return route.sin6_scope_id;
 852     }
 853 }
 854 
 855 /**
 856  * Enables SIO_LOOPBACK_FAST_PATH
 857  */
 858 JNIEXPORT jint JNICALL
 859 NET_EnableFastTcpLoopback(int fd) {
 860     int enabled = 1;
 861     DWORD result_byte_count = -1;
 862     int result = WSAIoctl(fd,
 863                           SIO_LOOPBACK_FAST_PATH,
 864                           &enabled,
 865                           sizeof(enabled),
 866                           NULL,
 867                           0,
 868                           &result_byte_count,
 869                           NULL,
 870                           NULL);
 871     return result == SOCKET_ERROR ? WSAGetLastError() : 0;
 872 }
 873 
 874 /* If address types is IPv6, then IPv6 must be available. Otherwise
 875  * no address can be generated. In the case of an IPv4 Inetaddress this
 876  * method will return an IPv4 mapped address where IPv6 is available and
 877  * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in
 878  * structure for an IPv4 InetAddress.
 879 */
 880 JNIEXPORT int JNICALL
 881 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
 882                           int *len, jboolean v4MappedAddress) {
 883     jint family, iafam;
 884     iafam = getInetAddress_family(env, iaObj);
 885     family = (iafam == IPv4)? AF_INET : AF_INET6;
 886     if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) {
 887         struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
 888         jbyte caddr[16];
 889         jint address, scopeid = 0;
 890         jint cached_scope_id = 0;
 891 
 892         if (family == AF_INET) { /* will convert to IPv4-mapped address */
 893             memset((char *) caddr, 0, 16);
 894             address = getInetAddress_addr(env, iaObj);
 895             if (address == INADDR_ANY) {
 896                 /* we would always prefer IPv6 wildcard address
 897                 caddr[10] = 0xff;
 898                 caddr[11] = 0xff; */
 899             } else {
 900                 caddr[10] = 0xff;
 901                 caddr[11] = 0xff;
 902                 caddr[12] = ((address >> 24) & 0xff);
 903                 caddr[13] = ((address >> 16) & 0xff);
 904                 caddr[14] = ((address >> 8) & 0xff);
 905                 caddr[15] = (address & 0xff);
 906             }
 907         } else {
 908             getInet6Address_ipaddress(env, iaObj, (char *)caddr);
 909             scopeid = getInet6Address_scopeid(env, iaObj);
 910             cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
 911         }
 912 
 913         memset((char *)him6, 0, sizeof(struct SOCKADDR_IN6));
 914         him6->sin6_port = (u_short) htons((u_short)port);
 915         memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
 916         him6->sin6_family = AF_INET6;
 917         if ((family == AF_INET6) && IN6_IS_ADDR_LINKLOCAL( &(him6->sin6_addr) )
 918             && (!scopeid && !cached_scope_id)) {
 919             cached_scope_id = getDefaultIPv6Interface(env, him6);
 920             (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
 921         }
 922         him6->sin6_scope_id = scopeid != 0 ? scopeid : cached_scope_id;
 923         *len = sizeof(struct SOCKADDR_IN6) ;
 924     } else {
 925         struct sockaddr_in *him4 = (struct sockaddr_in*)him;
 926         jint address;
 927         if (family != AF_INET) {
 928           JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
 929           return -1;
 930         }
 931         memset((char *) him4, 0, sizeof(struct sockaddr_in));
 932         address = getInetAddress_addr(env, iaObj);
 933         him4->sin_port = htons((short) port);
 934         him4->sin_addr.s_addr = (u_long) htonl(address);
 935         him4->sin_family = AF_INET;
 936         *len = sizeof(struct sockaddr_in);
 937     }
 938     return 0;
 939 }
 940 
 941 JNIEXPORT jint JNICALL
 942 NET_GetPortFromSockaddr(struct sockaddr *him) {
 943     if (him->sa_family == AF_INET6) {
 944         return ntohs(((struct sockaddr_in6*)him)->sin6_port);
 945     } else {
 946         return ntohs(((struct sockaddr_in*)him)->sin_port);
 947     }
 948 }
 949 
 950 int
 951 NET_IsIPv4Mapped(jbyte* caddr) {
 952     int i;
 953     for (i = 0; i < 10; i++) {
 954         if (caddr[i] != 0x00) {
 955             return 0; /* false */
 956         }
 957     }
 958 
 959     if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {
 960         return 1; /* true */
 961     }
 962     return 0; /* false */
 963 }
 964 
 965 int
 966 NET_IPv4MappedToIPv4(jbyte* caddr) {
 967     return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
 968         | (caddr[15] & 0xff);
 969 }
 970 
 971 int
 972 NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
 973     int i;
 974     for (i = 0; i < 16; i++) {
 975         if (caddr1[i] != caddr2[i]) {
 976             return 0; /* false */
 977         }
 978     }
 979     return 1;
 980 }
 981 
 982 int getScopeID (struct sockaddr *him) {
 983     struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
 984     return him6->sin6_scope_id;
 985 }
 986 
 987 int cmpScopeID (unsigned int scope, struct sockaddr *him) {
 988     struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
 989     return him6->sin6_scope_id == scope;
 990 }
 991 
 992 /**
 993  * Wrapper for select/poll with timeout on a single file descriptor.
 994  *
 995  * flags (defined in net_util_md.h can be any combination of
 996  * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
 997  *
 998  * The function will return when either the socket is ready for one
 999  * of the specified operation or the timeout expired.
1000  *
1001  * It returns the time left from the timeout, or -1 if it expired.
1002  */
1003 
1004 jint
1005 NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
1006 {
1007     jlong prevTime = JVM_CurrentTimeMillis(env, 0);
1008     jint read_rv;
1009 
1010     while (1) {
1011         jlong newTime;
1012         fd_set rd, wr, ex;
1013         struct timeval t;
1014 
1015         t.tv_sec = timeout / 1000;
1016         t.tv_usec = (timeout % 1000) * 1000;
1017 
1018         FD_ZERO(&rd);
1019         FD_ZERO(&wr);
1020         FD_ZERO(&ex);
1021         if (flags & NET_WAIT_READ) {
1022           FD_SET(fd, &rd);
1023         }
1024         if (flags & NET_WAIT_WRITE) {
1025           FD_SET(fd, &wr);
1026         }
1027         if (flags & NET_WAIT_CONNECT) {
1028           FD_SET(fd, &wr);
1029           FD_SET(fd, &ex);
1030         }
1031 
1032         errno = 0;
1033         read_rv = select(fd+1, &rd, &wr, &ex, &t);
1034 
1035         newTime = JVM_CurrentTimeMillis(env, 0);
1036         timeout -= (jint)(newTime - prevTime);
1037         if (timeout <= 0) {
1038           return read_rv > 0 ? 0 : -1;
1039         }
1040         newTime = prevTime;
1041 
1042         if (read_rv > 0) {
1043           break;
1044         }
1045 
1046 
1047       } /* while */
1048 
1049     return timeout;
1050 }
1051 
1052 int NET_Socket (int domain, int type, int protocol) {
1053     SOCKET sock;
1054     sock = socket (domain, type, protocol);
1055     if (sock != INVALID_SOCKET) {
1056         SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE);
1057     }
1058     return (int)sock;
1059 }