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 #include "java_net_SocketOptions.h"
     68 
     69 /* needed from libsocket on Solaris 8 */
     70 
     71 getaddrinfo_f getaddrinfo_ptr = NULL;
     72 freeaddrinfo_f freeaddrinfo_ptr = NULL;
     73 gai_strerror_f gai_strerror_ptr = NULL;
     74 getnameinfo_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 
     86 void 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 
    110 int 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__
    129 static int init_tcp_max_buf, init_udp_max_buf;
    130 static int tcp_max_buf;
    131 static int udp_max_buf;
    132 static 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  */
    139 static int
    140 getParam(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 
    179 static 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__
    218 static int kernelV22 = 0;
    219 static int vinit = 0;
    220 
    221 int 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 
    235 static int kernelV24 = 0;
    236 static int vinit24 = 0;
    237 
    238 int 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 
    252 int 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 
    260 int 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 
    270 int getScopeID (struct sockaddr *him) {
    271     struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
    272     return him6->sin6_scope_id;
    273 }
    274 
    275 int 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 
    283 void
    284 NET_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 
    292 void
    293 NET_ThrowCurrent(JNIEnv *env, char *msg) {
    294     NET_ThrowNew(env, errno, msg);
    295 }
    296 
    297 void
    298 NET_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 
    319 jfieldID
    320 NET_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)
    328 jint  IPv6_supported()
    329 {
    330     return JNI_FALSE;
    331 }
    332 
    333 #else /* !DONT_ENABLE_IPV6 */
    334 
    335 jint  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 
    479 void 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 
    508 void
    509 NET_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 
    535 struct loopback_route {
    536     struct in6_addr addr; /* destination address */
    537     int plen; /* prefix length */
    538 };
    539 
    540 static struct loopback_route *loRoutes = 0;
    541 static int nRoutes = 0; /* number of routes */
    542 static int loRoutes_size = 16; /* initial size */
    543 static int lo_scope_id = 0;
    544 
    545 static void initLoopbackRoutes();
    546 
    547 void 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 
    555 static 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 
    670 struct localinterface {
    671     int index;
    672     char localaddr [16];
    673 };
    674 
    675 static struct localinterface *localifs = 0;
    676 static int localifsSize = 0;    /* size of array */
    677 static int nifs = 0;            /* number of entries used in array */
    678 
    679 /* not thread safe: make sure called once from one thread */
    680 
    681 static 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 
    732 void initLocalAddrTable () {
    733     initLoopbackRoutes();
    734     initLocalIfs();
    735 }
    736 
    737 #else
    738 
    739 void initLocalAddrTable () {}
    740 
    741 #endif
    742 
    743 void 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 */
    766 JNIEXPORT int JNICALL
    767 NET_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 
    840 void
    841 NET_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 
    850 JNIEXPORT jint JNICALL
    851 NET_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 
    863 int
    864 NET_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 
    878 int
    879 NET_IPv4MappedToIPv4(jbyte* caddr) {
    880     return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
    881         | (caddr[15] & 0xff);
    882 }
    883 
    884 int
    885 NET_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 
    895 jboolean NET_addrtransAvailable() {
    896     return (jboolean)(getaddrinfo_ptr != NULL);
    897 }
    898 
    899 int 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  */
    913 int
    914 NET_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  */
    981 int
    982 NET_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  */
   1055 int
   1056 NET_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  */
   1269 int
   1270 NET_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 
   1366 jint
   1367 NET_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))
   1435 static void netUtilCleanUp() {
   1436     if (loRoutes != 0) free(loRoutes);
   1437     if (localifs != 0) free(localifs);
   1438 }
   1439