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