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