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