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 <errno.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/tcp.h>        /* Defines TCP_NODELAY, needed for 2.6 */
31#include <netinet/in.h>
32#include <net/if.h>
33#include <netdb.h>
34#include <stdlib.h>
35#include <dlfcn.h>
36
37#include <limits.h>
38#include <sys/param.h>
39#ifndef MAXINT
40#define MAXINT INT_MAX
41#endif
42#ifdef __BIONIC__
43#include <linux/ipv6_route.h>
44#endif
45
46#ifdef __solaris__
47#include <sys/sockio.h>
48#include <stropts.h>
49#include <inet/nd.h>
50#endif
51
52#ifdef __linux__
53#include <arpa/inet.h>
54#include <net/route.h>
55#include <sys/utsname.h>
56
57#ifndef IPV6_FLOWINFO_SEND
58#define IPV6_FLOWINFO_SEND      33
59#endif
60
61#endif
62
63#include "jni_util.h"
64#include "jvm.h"
65#include "net_util.h"
66
67#include "java_net_SocketOptions.h"
68
69/* needed from libsocket on Solaris 8 */
70
71getaddrinfo_f getaddrinfo_ptr = NULL;
72freeaddrinfo_f freeaddrinfo_ptr = NULL;
73gai_strerror_f gai_strerror_ptr = NULL;
74getnameinfo_f getnameinfo_ptr = NULL;
75
76/*
77 * EXCLBIND socket options only on Solaris
78 */
79#if defined(__solaris__) && !defined(TCP_EXCLBIND)
80#define TCP_EXCLBIND            0x21
81#endif
82#if defined(__solaris__) && !defined(UDP_EXCLBIND)
83#define UDP_EXCLBIND            0x0101
84#endif
85
86void setDefaultScopeID(JNIEnv *env, struct sockaddr *him)
87{
88#ifdef MACOSX
89    static jclass ni_class = NULL;
90    static jfieldID ni_defaultIndexID;
91    if (ni_class == NULL) {
92        jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
93        CHECK_NULL(c);
94        c = (*env)->NewGlobalRef(env, c);
95        CHECK_NULL(c);
96        ni_defaultIndexID = (*env)->GetStaticFieldID(
97            env, c, "defaultIndex", "I");
98        ni_class = c;
99    }
100    int defaultIndex;
101    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)him;
102    if (sin6->sin6_family == AF_INET6 && (sin6->sin6_scope_id == 0)) {
103        defaultIndex = (*env)->GetStaticIntField(env, ni_class,
104                                                 ni_defaultIndexID);
105        sin6->sin6_scope_id = defaultIndex;
106    }
107#endif
108}
109
110int getDefaultScopeID(JNIEnv *env) {
111    static jclass ni_class = NULL;
112    static jfieldID ni_defaultIndexID;
113    if (ni_class == NULL) {
114        jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
115        if (c == NULL) return 0;
116        c = (*env)->NewGlobalRef(env, c);
117        if (c == NULL) return 0;
118        ni_defaultIndexID = (*env)->GetStaticFieldID(
119            env, c, "defaultIndex", "I");
120        ni_class = c;
121    }
122    int defaultIndex = 0;
123    defaultIndex = (*env)->GetStaticIntField(env, ni_class,
124                                                 ni_defaultIndexID);
125    return defaultIndex;
126}
127
128#ifdef __solaris__
129static int init_tcp_max_buf, init_udp_max_buf;
130static int tcp_max_buf;
131static int udp_max_buf;
132static int useExclBind = 0;
133
134/*
135 * Get the specified parameter from the specified driver. The value
136 * of the parameter is assumed to be an 'int'. If the parameter
137 * cannot be obtained return -1
138 */
139static int
140getParam(char *driver, char *param)
141{
142    struct strioctl stri;
143    char buf [64];
144    int s;
145    int value;
146
147    s = open (driver, O_RDWR);
148    if (s < 0) {
149        return -1;
150    }
151    strncpy (buf, param, sizeof(buf));
152    stri.ic_cmd = ND_GET;
153    stri.ic_timout = 0;
154    stri.ic_dp = buf;
155    stri.ic_len = sizeof(buf);
156    if (ioctl (s, I_STR, &stri) < 0) {
157        value = -1;
158    } else {
159        value = atoi(buf);
160    }
161    close (s);
162    return value;
163}
164
165/*
166 * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
167 * for Solaris versions that do not support the ioctl() in getParam().
168 * Ugly, but only called once (for each sotype).
169 *
170 * As an optimisation, we make a guess using the default values for Solaris
171 * assuming they haven't been modified with ndd.
172 */
173
174#define MAX_TCP_GUESS 1024 * 1024
175#define MAX_UDP_GUESS 2 * 1024 * 1024
176
177#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
178
179static int findMaxBuf(int fd, int opt, int sotype) {
180    int a = 0;
181    int b = MAXINT;
182    int initial_guess;
183    int limit = -1;
184
185    if (sotype == SOCK_DGRAM) {
186        initial_guess = MAX_UDP_GUESS;
187    } else {
188        initial_guess = MAX_TCP_GUESS;
189    }
190
191    if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
192        initial_guess++;
193        if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
194            FAIL_IF_NOT_ENOBUFS;
195            return initial_guess - 1;
196        }
197        a = initial_guess;
198    } else {
199        FAIL_IF_NOT_ENOBUFS;
200        b = initial_guess - 1;
201    }
202    do {
203        int mid = a + (b-a)/2;
204        if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
205            limit = mid;
206            a = mid + 1;
207        } else {
208            FAIL_IF_NOT_ENOBUFS;
209            b = mid - 1;
210        }
211    } while (b >= a);
212
213    return limit;
214}
215#endif
216
217#ifdef __linux__
218static int kernelV22 = 0;
219static int vinit = 0;
220
221int kernelIsV22 () {
222    if (!vinit) {
223        struct utsname sysinfo;
224        if (uname(&sysinfo) == 0) {
225            sysinfo.release[3] = '\0';
226            if (strcmp(sysinfo.release, "2.2") == 0) {
227                kernelV22 = JNI_TRUE;
228            }
229        }
230        vinit = 1;
231    }
232    return kernelV22;
233}
234
235static int kernelV24 = 0;
236static int vinit24 = 0;
237
238int kernelIsV24 () {
239    if (!vinit24) {
240        struct utsname sysinfo;
241        if (uname(&sysinfo) == 0) {
242            sysinfo.release[3] = '\0';
243            if (strcmp(sysinfo.release, "2.4") == 0) {
244                kernelV24 = JNI_TRUE;
245            }
246        }
247        vinit24 = 1;
248    }
249    return kernelV24;
250}
251
252int getScopeID (struct sockaddr *him) {
253    struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
254    if (kernelIsV22()) {
255        return 0;
256    }
257    return hext->sin6_scope_id;
258}
259
260int cmpScopeID (unsigned int scope, struct sockaddr *him) {
261    struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
262    if (kernelIsV22()) {
263        return 1;       /* scope is ignored for comparison in 2.2 kernel */
264    }
265    return hext->sin6_scope_id == scope;
266}
267
268#else
269
270int getScopeID (struct sockaddr *him) {
271    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
272    return him6->sin6_scope_id;
273}
274
275int cmpScopeID (unsigned int scope, struct sockaddr *him) {
276    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
277    return him6->sin6_scope_id == scope;
278}
279
280#endif
281
282
283void
284NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
285                   const char *defaultDetail) {
286    char errmsg[255];
287    snprintf(errmsg, sizeof(errmsg), "errno: %d, error: %s\n", errno,
288             defaultDetail);
289    JNU_ThrowByNameWithLastError(env, name, errmsg);
290}
291
292void
293NET_ThrowCurrent(JNIEnv *env, char *msg) {
294    NET_ThrowNew(env, errno, msg);
295}
296
297void
298NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
299    char fullMsg[512];
300    if (!msg) {
301        msg = "no further information";
302    }
303    switch(errorNumber) {
304    case EBADF:
305        jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);
306        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
307        break;
308    case EINTR:
309        JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg);
310        break;
311    default:
312        errno = errorNumber;
313        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg);
314        break;
315    }
316}
317
318
319jfieldID
320NET_GetFileDescriptorID(JNIEnv *env)
321{
322    jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");
323    CHECK_NULL_RETURN(cls, NULL);
324    return (*env)->GetFieldID(env, cls, "descriptor", "I");
325}
326
327#if defined(DONT_ENABLE_IPV6)
328jint  IPv6_supported()
329{
330    return JNI_FALSE;
331}
332
333#else /* !DONT_ENABLE_IPV6 */
334
335jint  IPv6_supported()
336{
337#ifndef AF_INET6
338    return JNI_FALSE;
339#endif
340
341#ifdef AF_INET6
342    int fd;
343    void *ipv6_fn;
344    SOCKADDR sa;
345    socklen_t sa_len = sizeof(sa);
346
347    // This one below is problematic, will fail without proper permissions
348    // and report no ipv6 for some and ipv6 for others.
349    //fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ;
350    //if (fd < 0) {
351        /*
352         *  TODO: We really cant tell since it may be an unrelated error
353         *  for now we will assume that AF_INET6 is not available
354         */
355    //    return JNI_FALSE;
356    //}
357
358    /*
359     * If fd 0 is a socket it means we've been launched from inetd or
360     * xinetd. If it's a socket then check the family - if it's an
361     * IPv4 socket then we need to disable IPv6.
362     */
363    /*if (getsockname(0, (struct sockaddr *)&sa, &sa_len) == 0) {
364        struct sockaddr *saP = (struct sockaddr *)&sa;
365        if (saP->sa_family != AF_INET6) {
366            return JNI_FALSE;
367        }
368      }*/
369
370    /**
371     * Linux - check if any interface has an IPv6 address.
372     * Don't need to parse the line - we just need an indication.
373     */
374#ifdef __linux__
375    /*    {
376        FILE *fP = fopen("/proc/net/if_inet6", "r");
377        char buf[255];
378        char *bufP;
379
380        if (fP == NULL) {
381            close(fd);
382            return JNI_FALSE;
383        }
384        bufP = fgets(buf, sizeof(buf), fP);
385        fclose(fP);
386        if (bufP == NULL) {
387            close(fd);
388            return JNI_FALSE;
389        }
390        }*/
391#endif
392
393    /**
394     * On Solaris 8 it's possible to create INET6 sockets even
395     * though IPv6 is not enabled on all interfaces. Thus we
396     * query the number of IPv6 addresses to verify that IPv6
397     * has been configured on at least one interface.
398     *
399     * On Linux it doesn't matter - if IPv6 is built-in the
400     * kernel then IPv6 addresses will be bound automatically
401     * to all interfaces.
402     */
403#ifdef __solaris__
404
405#ifdef SIOCGLIFNUM
406    {
407        struct lifnum numifs;
408
409        numifs.lifn_family = AF_INET6;
410        numifs.lifn_flags = 0;
411        if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
412            /**
413             * SIOCGLIFNUM failed - assume IPv6 not configured
414             */
415            untagSocket(env, fd);
416            close(fd);
417            return JNI_FALSE;
418        }
419        /**
420         * If no IPv6 addresses then return false. If count > 0
421         * it's possible that all IPv6 addresses are "down" but
422         * that's okay as they may be brought "up" while the
423         * VM is running.
424         */
425        if (numifs.lifn_count == 0) {
426            close(fd);
427            return JNI_FALSE;
428        }
429    }
430#else
431    /* SIOCGLIFNUM not defined in build environment ??? */
432    close(fd);
433    return JNI_FALSE;
434#endif
435
436#endif /* __solaris */
437
438    /*
439     *  OK we may have the stack available in the kernel,
440     *  we should also check if the APIs are available.
441     */
442
443    ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
444    if (ipv6_fn == NULL ) {
445        // close(fd);
446        return JNI_FALSE;
447    }
448
449    /*
450     * We've got the library, let's get the pointers to some
451     * IPV6 specific functions. We have to do that because, at least
452     * on Solaris we may build on a system without IPV6 networking
453     * libraries, therefore we can't have a hard link to these
454     * functions.
455     */
456    getaddrinfo_ptr = (getaddrinfo_f)
457        JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
458
459    freeaddrinfo_ptr = (freeaddrinfo_f)
460        JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
461
462    gai_strerror_ptr = (gai_strerror_f)
463        JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
464
465    getnameinfo_ptr = (getnameinfo_f)
466        JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
467
468    if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
469        /* We need all 3 of them */
470        getaddrinfo_ptr = NULL;
471    }
472
473    //close(fd);
474    return JNI_TRUE;
475#endif /* AF_INET6 */
476}
477#endif /* DONT_ENABLE_IPV6 */
478
479void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
480                                           const char* hostname,
481                                           int gai_error)
482{
483    int size;
484    char *buf;
485    const char *format = "%s: %s";
486    const char *error_string =
487        (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error);
488    if (error_string == NULL)
489        error_string = "unknown error";
490
491    size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
492    buf = (char *) malloc(size);
493    if (buf) {
494        jstring s;
495        snprintf(buf, size, format, hostname, error_string);
496        s = JNU_NewStringPlatform(env, buf);
497        if (s != NULL) {
498            jobject x = JNU_NewObjectByName(env,
499                                            "java/net/UnknownHostException",
500                                            "(Ljava/lang/String;)V", s);
501            if (x != NULL)
502                (*env)->Throw(env, x);
503        }
504        free(buf);
505    }
506}
507
508void
509NET_AllocSockaddr(struct sockaddr **him, int *len) {
510#ifdef AF_INET6
511    if (ipv6_available()) {
512        struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6));
513        *him = (struct sockaddr*)him6;
514        *len = sizeof(struct sockaddr_in6);
515    } else
516#endif /* AF_INET6 */
517        {
518            struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
519            *him = (struct sockaddr*)him4;
520            *len = sizeof(struct sockaddr_in);
521        }
522}
523
524#if defined(__linux__) && defined(AF_INET6)
525
526
527/* following code creates a list of addresses from the kernel
528 * routing table that are routed via the loopback address.
529 * We check all destination addresses against this table
530 * and override the scope_id field to use the relevant value for "lo"
531 * in order to work-around the Linux bug that prevents packets destined
532 * for certain local addresses from being sent via a physical interface.
533 */
534
535struct loopback_route {
536    struct in6_addr addr; /* destination address */
537    int plen; /* prefix length */
538};
539
540static struct loopback_route *loRoutes = 0;
541static int nRoutes = 0; /* number of routes */
542static int loRoutes_size = 16; /* initial size */
543static int lo_scope_id = 0;
544
545static void initLoopbackRoutes();
546
547void printAddr (struct in6_addr *addr) {
548    int i;
549    for (i=0; i<16; i++) {
550        printf ("%02x", addr->s6_addr[i]);
551    }
552    printf ("\n");
553}
554
555static void initLoopbackRoutes() {
556    FILE *f;
557    char srcp[8][5];
558    char hopp[8][5];
559    int dest_plen, src_plen, use, refcnt, metric;
560    unsigned long flags;
561    char dest_str[40];
562    struct in6_addr dest_addr;
563    char device[16];
564
565    if (loRoutes != 0) {
566        free (loRoutes);
567    }
568    loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route));
569    if (loRoutes == 0) {
570        return;
571    }
572    /*
573     * Scan /proc/net/ipv6_route looking for a matching
574     * route.
575     */
576    if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
577        return ;
578    }
579    while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
580                     "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
581                     "%4s%4s%4s%4s%4s%4s%4s%4s "
582                     "%08x %08x %08x %08lx %8s",
583                     dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
584                     &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
585                     &dest_plen,
586                     srcp[0], srcp[1], srcp[2], srcp[3],
587                     srcp[4], srcp[5], srcp[6], srcp[7],
588                     &src_plen,
589                     hopp[0], hopp[1], hopp[2], hopp[3],
590                     hopp[4], hopp[5], hopp[6], hopp[7],
591                     &metric, &use, &refcnt, &flags, device) == 31) {
592
593        /*
594         * Some routes should be ignored
595         */
596        if ( (dest_plen < 0 || dest_plen > 128)  ||
597             (src_plen != 0) ||
598             (flags & (RTF_POLICY | RTF_FLOW)) ||
599             ((flags & RTF_REJECT) && dest_plen == 0) ) {
600            continue;
601        }
602
603        /*
604         * Convert the destination address
605         */
606        dest_str[4] = ':';
607        dest_str[9] = ':';
608        dest_str[14] = ':';
609        dest_str[19] = ':';
610        dest_str[24] = ':';
611        dest_str[29] = ':';
612        dest_str[34] = ':';
613        dest_str[39] = '\0';
614
615        if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
616            /* not an Ipv6 address */
617            continue;
618        }
619        if (strcmp(device, "lo") != 0) {
620            /* Not a loopback route */
621            continue;
622        } else {
623            if (nRoutes == loRoutes_size) {
624                loRoutes = realloc (loRoutes, loRoutes_size *
625                                sizeof (struct loopback_route) * 2);
626                if (loRoutes == 0) {
627                    return ;
628                }
629                loRoutes_size *= 2;
630            }
631            memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr));
632            loRoutes[nRoutes].plen = dest_plen;
633            nRoutes ++;
634        }
635    }
636
637    fclose (f);
638    {
639        /* now find the scope_id for "lo" */
640
641        char devname[21];
642        char addr6p[8][5];
643        int plen, scope, dad_status, if_idx;
644
645        if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
646            while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
647                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
648                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],
649                  &if_idx, &plen, &scope, &dad_status, devname) == 13) {
650
651                if (strcmp(devname, "lo") == 0) {
652                    /*
653                     * Found - so just return the index
654                     */
655                    fclose(f);
656                    lo_scope_id = if_idx;
657                    return;
658                }
659            }
660            fclose(f);
661        }
662    }
663}
664
665/*
666 * Following is used for binding to local addresses. Equivalent
667 * to code above, for bind().
668 */
669
670struct localinterface {
671    int index;
672    char localaddr [16];
673};
674
675static struct localinterface *localifs = 0;
676static int localifsSize = 0;    /* size of array */
677static int nifs = 0;            /* number of entries used in array */
678
679/* not thread safe: make sure called once from one thread */
680
681static void initLocalIfs () {
682    FILE *f;
683    unsigned char staddr [16];
684    char ifname [33];
685    struct localinterface *lif=0;
686    int index, x1, x2, x3;
687    unsigned int u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,ua,ub,uc,ud,ue,uf;
688
689    if ((f = fopen("/proc/net/if_inet6", "r")) == NULL) {
690        return ;
691    }
692    while (fscanf (f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x "
693                "%d %x %x %x %32s",&u0,&u1,&u2,&u3,&u4,&u5,&u6,&u7,
694                &u8,&u9,&ua,&ub,&uc,&ud,&ue,&uf,
695                &index, &x1, &x2, &x3, ifname) == 21) {
696        staddr[0] = (unsigned char)u0;
697        staddr[1] = (unsigned char)u1;
698        staddr[2] = (unsigned char)u2;
699        staddr[3] = (unsigned char)u3;
700        staddr[4] = (unsigned char)u4;
701        staddr[5] = (unsigned char)u5;
702        staddr[6] = (unsigned char)u6;
703        staddr[7] = (unsigned char)u7;
704        staddr[8] = (unsigned char)u8;
705        staddr[9] = (unsigned char)u9;
706        staddr[10] = (unsigned char)ua;
707        staddr[11] = (unsigned char)ub;
708        staddr[12] = (unsigned char)uc;
709        staddr[13] = (unsigned char)ud;
710        staddr[14] = (unsigned char)ue;
711        staddr[15] = (unsigned char)uf;
712        nifs ++;
713        if (nifs > localifsSize) {
714            localifs = (struct localinterface *) realloc (
715                        localifs, sizeof (struct localinterface)* (localifsSize+5));
716            if (localifs == 0) {
717                nifs = 0;
718                fclose (f);
719                return;
720            }
721            lif = localifs + localifsSize;
722            localifsSize += 5;
723        } else {
724            lif ++;
725        }
726        memcpy (lif->localaddr, staddr, 16);
727        lif->index = index;
728    }
729    fclose (f);
730}
731
732void initLocalAddrTable () {
733    initLoopbackRoutes();
734    initLocalIfs();
735}
736
737#else
738
739void initLocalAddrTable () {}
740
741#endif
742
743void parseExclusiveBindProperty(JNIEnv *env) {
744#ifdef __solaris__
745    jstring s, flagSet;
746    jclass iCls;
747    jmethodID mid;
748
749    s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
750    CHECK_NULL(s);
751    iCls = (*env)->FindClass(env, "java/lang/System");
752    CHECK_NULL(iCls);
753    mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
754                "(Ljava/lang/String;)Ljava/lang/String;");
755    CHECK_NULL(mid);
756    flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
757    if (flagSet != NULL) {
758        useExclBind = 1;
759    }
760#endif
761}
762/* In the case of an IPv4 Inetaddress this method will return an
763 * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
764 * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
765*/
766JNIEXPORT int JNICALL
767NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
768                          int *len, jboolean v4MappedAddress) {
769    jint family;
770    family = getInetAddress_family(env, iaObj);
771#ifdef AF_INET6
772    /* needs work. 1. family 2. clean up him6 etc deallocate memory */
773    if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
774        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
775        jbyteArray ipaddress;
776        jbyte caddr[16];
777        jint address;
778
779
780        if (family == IPv4) { /* will convert to IPv4-mapped address */
781            memset((char *) caddr, 0, 16);
782            address = getInetAddress_addr(env, iaObj);
783            if (address == INADDR_ANY) {
784                /* we would always prefer IPv6 wildcard address
785                   caddr[10] = 0xff;
786                   caddr[11] = 0xff; */
787            } else {
788                caddr[10] = 0xff;
789                caddr[11] = 0xff;
790                caddr[12] = ((address >> 24) & 0xff);
791                caddr[13] = ((address >> 16) & 0xff);
792                caddr[14] = ((address >> 8) & 0xff);
793                caddr[15] = (address & 0xff);
794            }
795        } else {
796            ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
797            (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
798        }
799        memset((char *)him6, 0, sizeof(struct sockaddr_in6));
800        him6->sin6_port = htons(port);
801        memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
802        him6->sin6_family = AF_INET6;
803        *len = sizeof(struct sockaddr_in6) ;
804
805#if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)
806// XXXBSD: should we do something with scope id here ? see below linux comment
807/* MMM: Come back to this! */
808#endif
809
810        // Android-changed: Don't try and figure out scope_ids for link local
811        // addresses. Use them only if they're set in java (say, if the Inet6Address
812        // was constructed with a specific scope_id or NetworkInterface).
813        if (family != IPv4) {
814            if (ia6_scopeidID) {
815                int scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_scopeidID);
816                if (scope_id > 0) {
817                    him6->sin6_scope_id = scope_id;
818                }
819            }
820        }
821    } else
822#endif /* AF_INET6 */
823        {
824            struct sockaddr_in *him4 = (struct sockaddr_in*)him;
825            jint address;
826            if (family == IPv6) {
827              JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
828              return -1;
829            }
830            memset((char *) him4, 0, sizeof(struct sockaddr_in));
831            address = getInetAddress_addr(env, iaObj);
832            him4->sin_port = htons((short) port);
833            him4->sin_addr.s_addr = (uint32_t) htonl(address);
834            him4->sin_family = AF_INET;
835            *len = sizeof(struct sockaddr_in);
836        }
837    return 0;
838}
839
840void
841NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
842#ifdef AF_INET6
843    if (him->sa_family == AF_INET6) {
844        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
845        him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
846    }
847#endif /* AF_INET6 */
848}
849
850JNIEXPORT jint JNICALL
851NET_GetPortFromSockaddr(struct sockaddr *him) {
852#ifdef AF_INET6
853    if (him->sa_family == AF_INET6) {
854        return ntohs(((struct sockaddr_in6*)him)->sin6_port);
855
856        } else
857#endif /* AF_INET6 */
858            {
859                return ntohs(((struct sockaddr_in*)him)->sin_port);
860            }
861}
862
863int
864NET_IsIPv4Mapped(jbyte* caddr) {
865    int i;
866    for (i = 0; i < 10; i++) {
867        if (caddr[i] != 0x00) {
868            return 0; /* false */
869        }
870    }
871
872    if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {
873        return 1; /* true */
874    }
875    return 0; /* false */
876}
877
878int
879NET_IPv4MappedToIPv4(jbyte* caddr) {
880    return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
881        | (caddr[15] & 0xff);
882}
883
884int
885NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
886    int i;
887    for (i = 0; i < 16; i++) {
888        if (caddr1[i] != caddr2[i]) {
889            return 0; /* false */
890        }
891    }
892    return 1;
893}
894
895jboolean NET_addrtransAvailable() {
896    return (jboolean)(getaddrinfo_ptr != NULL);
897}
898
899int NET_IsZeroAddr(jbyte* caddr) {
900    int i;
901    for (i = 0; i < 16; i++) {
902        if (caddr[i] != 0) {
903            return 0;
904        }
905    }
906    return 1;
907}
908
909/*
910 * Map the Java level socket option to the platform specific
911 * level and option name.
912 */
913int
914NET_MapSocketOption(jint cmd, int *level, int *optname) {
915    static struct {
916        jint cmd;
917        int level;
918        int optname;
919    } const opts[] = {
920        { java_net_SocketOptions_TCP_NODELAY,           IPPROTO_TCP,    TCP_NODELAY },
921        { java_net_SocketOptions_SO_OOBINLINE,          SOL_SOCKET,     SO_OOBINLINE },
922        { java_net_SocketOptions_SO_LINGER,             SOL_SOCKET,     SO_LINGER },
923        { java_net_SocketOptions_SO_SNDBUF,             SOL_SOCKET,     SO_SNDBUF },
924        { java_net_SocketOptions_SO_RCVBUF,             SOL_SOCKET,     SO_RCVBUF },
925        { java_net_SocketOptions_SO_KEEPALIVE,          SOL_SOCKET,     SO_KEEPALIVE },
926        { java_net_SocketOptions_SO_REUSEADDR,          SOL_SOCKET,     SO_REUSEADDR },
927        { java_net_SocketOptions_SO_BROADCAST,          SOL_SOCKET,     SO_BROADCAST },
928        { java_net_SocketOptions_IP_TOS,                IPPROTO_IP,     IP_TOS },
929        { java_net_SocketOptions_IP_MULTICAST_IF,       IPPROTO_IP,     IP_MULTICAST_IF },
930        { java_net_SocketOptions_IP_MULTICAST_IF2,      IPPROTO_IP,     IP_MULTICAST_IF },
931        { java_net_SocketOptions_IP_MULTICAST_LOOP,     IPPROTO_IP,     IP_MULTICAST_LOOP },
932    };
933
934    int i;
935
936    /*
937     * Different multicast options if IPv6 is enabled
938     */
939#ifdef AF_INET6
940    if (ipv6_available()) {
941        switch (cmd) {
942            case java_net_SocketOptions_IP_MULTICAST_IF:
943            case java_net_SocketOptions_IP_MULTICAST_IF2:
944                *level = IPPROTO_IPV6;
945                *optname = IPV6_MULTICAST_IF;
946                return 0;
947
948            case java_net_SocketOptions_IP_MULTICAST_LOOP:
949                *level = IPPROTO_IPV6;
950                *optname = IPV6_MULTICAST_LOOP;
951                return 0;
952        }
953    }
954#endif
955
956    /*
957     * Map the Java level option to the native level
958     */
959    for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
960        if (cmd == opts[i].cmd) {
961            *level = opts[i].level;
962            *optname = opts[i].optname;
963            return 0;
964        }
965    }
966
967    /* not found */
968    return -1;
969}
970
971/*
972 * Wrapper for getsockopt system routine - does any necessary
973 * pre/post processing to deal with OS specific oddies :-
974 *
975 * IP_TOS is a no-op with IPv6 sockets as it's setup when
976 * the connection is established.
977 *
978 * On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed
979 * to compensate for an incorrect value returned by the kernel.
980 */
981int
982NET_GetSockOpt(int fd, int level, int opt, void *result,
983               int *len)
984{
985    int rv;
986
987#ifdef AF_INET6
988    if ((level == IPPROTO_IP) && (opt == IP_TOS)) {
989        if (ipv6_available()) {
990
991            /*
992             * For IPv6 socket option implemented at Java-level
993             * so return -1.
994             */
995            int *tc = (int *)result;
996            *tc = -1;
997            return 0;
998        }
999    }
1000#endif
1001
1002#ifdef __solaris__
1003    rv = getsockopt(fd, level, opt, result, len);
1004#else
1005    {
1006        socklen_t socklen = *len;
1007        rv = getsockopt(fd, level, opt, result, &socklen);
1008        *len = socklen;
1009    }
1010#endif
1011
1012    if (rv < 0) {
1013        return rv;
1014    }
1015
1016#ifdef __linux__
1017    /*
1018     * On Linux SO_SNDBUF/SO_RCVBUF aren't symmetric. This
1019     * stems from additional socket structures in the send
1020     * and receive buffers.
1021     */
1022    if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF)
1023                                  || (opt == SO_RCVBUF))) {
1024        int n = *((int *)result);
1025        n /= 2;
1026        *((int *)result) = n;
1027    }
1028#endif
1029
1030/* Workaround for Mac OS treating linger value as
1031 *  signed integer
1032 */
1033#ifdef MACOSX
1034    if (level == SOL_SOCKET && opt == SO_LINGER) {
1035        struct linger* to_cast = (struct linger*)result;
1036        to_cast->l_linger = (unsigned short)to_cast->l_linger;
1037    }
1038#endif
1039    return rv;
1040}
1041
1042/*
1043 * Wrapper for setsockopt system routine - performs any
1044 * necessary pre/post processing to deal with OS specific
1045 * issue :-
1046 *
1047 * On Solaris need to limit the suggested value for SO_SNDBUF
1048 * and SO_RCVBUF to the kernel configured limit
1049 *
1050 * For IP_TOS socket option need to mask off bits as this
1051 * aren't automatically masked by the kernel and results in
1052 * an error. In addition IP_TOS is a noop with IPv6 as it
1053 * should be setup as connection time.
1054 */
1055int
1056NET_SetSockOpt(int fd, int level, int  opt, const void *arg,
1057               int len)
1058{
1059#ifndef IPTOS_TOS_MASK
1060#define IPTOS_TOS_MASK 0x1e
1061#endif
1062#ifndef IPTOS_PREC_MASK
1063#define IPTOS_PREC_MASK 0xe0
1064#endif
1065
1066#if defined(_ALLBSD_SOURCE)
1067#if defined(KIPC_MAXSOCKBUF)
1068    int mib[3];
1069    size_t rlen;
1070#endif
1071
1072    int *bufsize;
1073
1074#ifdef __APPLE__
1075    static int maxsockbuf = -1;
1076#else
1077    static long maxsockbuf = -1;
1078#endif
1079
1080    int addopt;
1081    struct linger *ling;
1082#endif
1083
1084    /*
1085     * IPPROTO/IP_TOS :-
1086     * 1. IPv6 on Solaris/Mac OS: no-op and will be set
1087     *    in flowinfo field when connecting TCP socket,
1088     *    or sending UDP packet.
1089     * 2. IPv6 on Linux: By default Linux ignores flowinfo
1090     *    field so enable IPV6_FLOWINFO_SEND so that flowinfo
1091     *    will be examined.
1092     * 3. IPv4: set socket option based on ToS and Precedence
1093     *    fields (otherwise get invalid argument)
1094     */
1095    if (level == IPPROTO_IP && opt == IP_TOS) {
1096        int *iptos;
1097
1098#if defined(AF_INET6) && (defined(__solaris__) || defined(MACOSX))
1099        if (ipv6_available()) {
1100            return 0;
1101        }
1102#endif
1103
1104#if defined(AF_INET6) && defined(__linux__)
1105        if (ipv6_available()) {
1106            int optval = 1;
1107            return setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
1108                              (void *)&optval, sizeof(optval));
1109        }
1110#endif
1111
1112        iptos = (int *)arg;
1113        *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
1114    }
1115
1116    /*
1117     * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
1118     * the value when it exceeds the system limit.
1119     */
1120#ifdef __solaris__
1121    if (level == SOL_SOCKET) {
1122        if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
1123            int sotype=0, arglen;
1124            int *bufsize, maxbuf;
1125            int ret;
1126
1127            /* Attempt with the original size */
1128            ret = setsockopt(fd, level, opt, arg, len);
1129            if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
1130                return ret;
1131
1132            /* Exceeded system limit so clamp and retry */
1133
1134            arglen = sizeof(sotype);
1135            if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
1136                           &arglen) < 0) {
1137                return -1;
1138            }
1139
1140            /*
1141             * We try to get tcp_maxbuf (and udp_max_buf) using
1142             * an ioctl() that isn't available on all versions of Solaris.
1143             * If that fails, we use the search algorithm in findMaxBuf()
1144             */
1145            if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
1146                tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf");
1147                if (tcp_max_buf == -1) {
1148                    tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
1149                    if (tcp_max_buf == -1) {
1150                        return -1;
1151                    }
1152                }
1153                init_tcp_max_buf = 1;
1154            } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
1155                udp_max_buf = getParam("/dev/udp", "udp_max_buf");
1156                if (udp_max_buf == -1) {
1157                    udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
1158                    if (udp_max_buf == -1) {
1159                        return -1;
1160                    }
1161                }
1162                init_udp_max_buf = 1;
1163            }
1164
1165            maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
1166            bufsize = (int *)arg;
1167            if (*bufsize > maxbuf) {
1168                *bufsize = maxbuf;
1169            }
1170        }
1171    }
1172#endif
1173
1174    /*
1175     * On Linux the receive buffer is used for both socket
1176     * structures and the the packet payload. The implication
1177     * is that if SO_RCVBUF is too small then small packets
1178     * must be discard.
1179     */
1180#ifdef __linux__
1181    if (level == SOL_SOCKET && opt == SO_RCVBUF) {
1182        int *bufsize = (int *)arg;
1183        if (*bufsize < 1024) {
1184            *bufsize = 1024;
1185        }
1186    }
1187#endif
1188
1189#if defined(_ALLBSD_SOURCE)
1190    /*
1191     * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to
1192     * ensure that value is <= kern.ipc.maxsockbuf as otherwise we get
1193     * an ENOBUFS error.
1194     */
1195    if (level == SOL_SOCKET) {
1196        if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
1197#ifdef KIPC_MAXSOCKBUF
1198            if (maxsockbuf == -1) {
1199               mib[0] = CTL_KERN;
1200               mib[1] = KERN_IPC;
1201               mib[2] = KIPC_MAXSOCKBUF;
1202               rlen = sizeof(maxsockbuf);
1203               if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1)
1204                   maxsockbuf = 1024;
1205
1206#if 1
1207               /* XXXBSD: This is a hack to workaround mb_max/mb_max_adj
1208                  problem.  It should be removed when kern.ipc.maxsockbuf
1209                  will be real value. */
1210               maxsockbuf = (maxsockbuf/5)*4;
1211#endif
1212           }
1213#elif defined(__OpenBSD__)
1214           maxsockbuf = SB_MAX;
1215#else
1216           maxsockbuf = 64 * 1024;      /* XXX: NetBSD */
1217#endif
1218
1219           bufsize = (int *)arg;
1220           if (*bufsize > maxsockbuf) {
1221               *bufsize = maxsockbuf;
1222           }
1223
1224           if (opt == SO_RCVBUF && *bufsize < 1024) {
1225                *bufsize = 1024;
1226           }
1227
1228        }
1229    }
1230
1231    /*
1232     * On Solaris, SO_REUSEADDR will allow multiple datagram
1233     * sockets to bind to the same port.  The network jck tests
1234     * for this "feature", so we need to emulate it by turning on
1235     * SO_REUSEPORT as well for that combination.
1236     */
1237    if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
1238        int sotype;
1239        socklen_t arglen;
1240
1241        arglen = sizeof(sotype);
1242        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
1243            return -1;
1244        }
1245
1246        if (sotype == SOCK_DGRAM) {
1247            addopt = SO_REUSEPORT;
1248            setsockopt(fd, level, addopt, arg, len);
1249        }
1250    }
1251
1252#endif
1253
1254    return setsockopt(fd, level, opt, arg, len);
1255}
1256
1257/*
1258 * Wrapper for bind system call - performs any necessary pre/post
1259 * processing to deal with OS specific issues :-
1260 *
1261 * Linux allows a socket to bind to 127.0.0.255 which must be
1262 * caught.
1263 *
1264 * On Solaris with IPv6 enabled we must use an exclusive
1265 * bind to guaranteed a unique port number across the IPv4 and
1266 * IPv6 port spaces.
1267 *
1268 */
1269int
1270NET_Bind(int fd, struct sockaddr *him, int len)
1271{
1272#if defined(__solaris__) && defined(AF_INET6)
1273    int level = -1;
1274    int exclbind = -1;
1275#endif
1276    int rv;
1277
1278#ifdef __linux__
1279    /*
1280     * ## get bugId for this issue - goes back to 1.2.2 port ##
1281     * ## When IPv6 is enabled this will be an IPv4-mapped
1282     * ## with family set to AF_INET6
1283     */
1284    if (him->sa_family == AF_INET) {
1285        struct sockaddr_in *sa = (struct sockaddr_in *)him;
1286        if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
1287            errno = EADDRNOTAVAIL;
1288            return -1;
1289        }
1290    }
1291#endif
1292
1293#if defined(__solaris__) && defined(AF_INET6)
1294    /*
1295     * Solaris has seperate IPv4 and IPv6 port spaces so we
1296     * use an exclusive bind when SO_REUSEADDR is not used to
1297     * give the illusion of a unified port space.
1298     * This also avoids problems with IPv6 sockets connecting
1299     * to IPv4 mapped addresses whereby the socket conversion
1300     * results in a late bind that fails because the
1301     * corresponding IPv4 port is in use.
1302     */
1303    if (ipv6_available()) {
1304        int arg, len;
1305
1306        len = sizeof(arg);
1307        if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1308                       (char *)&arg, &len) == 0) {
1309            if (useExclBind || arg == 0) {
1310                /*
1311                 * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
1312                 * property is true so enable TCP_EXCLBIND or
1313                 * UDP_EXCLBIND
1314                 */
1315                len = sizeof(arg);
1316                if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,
1317                               &len) == 0) {
1318                    if (arg == SOCK_STREAM) {
1319                        level = IPPROTO_TCP;
1320                        exclbind = TCP_EXCLBIND;
1321                    } else {
1322                        level = IPPROTO_UDP;
1323                        exclbind = UDP_EXCLBIND;
1324                    }
1325                }
1326
1327                arg = 1;
1328                setsockopt(fd, level, exclbind, (char *)&arg,
1329                           sizeof(arg));
1330            }
1331        }
1332    }
1333
1334#endif
1335
1336    rv = bind(fd, him, len);
1337
1338#if defined(__solaris__) && defined(AF_INET6)
1339    if (rv < 0) {
1340        int en = errno;
1341        /* Restore *_EXCLBIND if the bind fails */
1342        if (exclbind != -1) {
1343            int arg = 0;
1344            setsockopt(fd, level, exclbind, (char *)&arg,
1345                       sizeof(arg));
1346        }
1347        errno = en;
1348    }
1349#endif
1350
1351    return rv;
1352}
1353
1354/**
1355 * Wrapper for select/poll with timeout on a single file descriptor.
1356 *
1357 * flags (defined in net_util_md.h can be any combination of
1358 * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
1359 *
1360 * The function will return when either the socket is ready for one
1361 * of the specified operation or the timeout expired.
1362 *
1363 * It returns the time left from the timeout (possibly 0), or -1 if it expired.
1364 */
1365
1366jint
1367NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
1368{
1369    jlong prevTime = JVM_CurrentTimeMillis(env, 0);
1370    jint read_rv;
1371
1372    while (1) {
1373        jlong newTime;
1374#ifndef USE_SELECT
1375        {
1376          struct pollfd pfd;
1377          pfd.fd = fd;
1378          pfd.events = 0;
1379          if (flags & NET_WAIT_READ)
1380            pfd.events |= POLLIN;
1381          if (flags & NET_WAIT_WRITE)
1382            pfd.events |= POLLOUT;
1383          if (flags & NET_WAIT_CONNECT)
1384            pfd.events |= POLLOUT;
1385
1386          errno = 0;
1387          read_rv = NET_Poll(&pfd, 1, timeout);
1388        }
1389#else
1390        {
1391          fd_set rd, wr, ex;
1392          struct timeval t;
1393
1394          t.tv_sec = timeout / 1000;
1395          t.tv_usec = (timeout % 1000) * 1000;
1396
1397          FD_ZERO(&rd);
1398          FD_ZERO(&wr);
1399          FD_ZERO(&ex);
1400          if (flags & NET_WAIT_READ) {
1401            FD_SET(fd, &rd);
1402          }
1403          if (flags & NET_WAIT_WRITE) {
1404            FD_SET(fd, &wr);
1405          }
1406          if (flags & NET_WAIT_CONNECT) {
1407            FD_SET(fd, &wr);
1408            FD_SET(fd, &ex);
1409          }
1410
1411          errno = 0;
1412          read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);
1413        }
1414#endif
1415
1416        newTime = JVM_CurrentTimeMillis(env, 0);
1417        timeout -= (newTime - prevTime);
1418        if (timeout <= 0) {
1419          return read_rv > 0 ? 0 : -1;
1420        }
1421        prevTime = newTime;
1422
1423        if (read_rv > 0) {
1424          break;
1425        }
1426
1427
1428      } /* while */
1429
1430    return timeout;
1431}
1432
1433// http://b/27301951
1434__attribute__((destructor))
1435static void netUtilCleanUp() {
1436    if (loRoutes != 0) free(loRoutes);
1437    if (localifs != 0) free(localifs);
1438}
1439