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