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             close(fd);
    402             return JNI_FALSE;
    403         }
    404         /**
    405          * If no IPv6 addresses then return false. If count > 0
    406          * it's possible that all IPv6 addresses are "down" but
    407          * that's okay as they may be brought "up" while the
    408          * VM is running.
    409          */
    410         if (numifs.lifn_count == 0) {
    411             close(fd);
    412             return JNI_FALSE;
    413         }
    414     }
    415 #else
    416     /* SIOCGLIFNUM not defined in build environment ??? */
    417     close(fd);
    418     return JNI_FALSE;
    419 #endif
    420 
    421 #endif /* __solaris */
    422 
    423     /*
    424      *  OK we may have the stack available in the kernel,
    425      *  we should also check if the APIs are available.
    426      */
    427 
    428     ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
    429     if (ipv6_fn == NULL ) {
    430         // close(fd);
    431         return JNI_FALSE;
    432     }
    433 
    434     /*
    435      * We've got the library, let's get the pointers to some
    436      * IPV6 specific functions. We have to do that because, at least
    437      * on Solaris we may build on a system without IPV6 networking
    438      * libraries, therefore we can't have a hard link to these
    439      * functions.
    440      */
    441     getaddrinfo_ptr = (getaddrinfo_f)
    442         JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
    443 
    444     freeaddrinfo_ptr = (freeaddrinfo_f)
    445         JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
    446 
    447     gai_strerror_ptr = (gai_strerror_f)
    448         JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
    449 
    450     getnameinfo_ptr = (getnameinfo_f)
    451         JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
    452 
    453     if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
    454         /* We need all 3 of them */
    455         getaddrinfo_ptr = NULL;
    456     }
    457 
    458     //close(fd);
    459     return JNI_TRUE;
    460 #endif /* AF_INET6 */
    461 }
    462 #endif /* DONT_ENABLE_IPV6 */
    463 
    464 void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
    465                                            const char* hostname,
    466                                            int gai_error)
    467 {
    468     int size;
    469     char *buf;
    470     const char *format = "%s: %s";
    471     const char *error_string =
    472         (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error);
    473     if (error_string == NULL)
    474         error_string = "unknown error";
    475 
    476     size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
    477     buf = (char *) malloc(size);
    478     if (buf) {
    479         jstring s;
    480         snprintf(buf, size, format, hostname, error_string);
    481         s = JNU_NewStringPlatform(env, buf);
    482         if (s != NULL) {
    483             jobject x = JNU_NewObjectByName(env,
    484                                             "java/net/UnknownHostException",
    485                                             "(Ljava/lang/String;)V", s);
    486             if (x != NULL)
    487                 (*env)->Throw(env, x);
    488         }
    489         free(buf);
    490     }
    491 }
    492 
    493 void
    494 NET_AllocSockaddr(struct sockaddr **him, int *len) {
    495 #ifdef AF_INET6
    496     if (ipv6_available()) {
    497         struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6));
    498         *him = (struct sockaddr*)him6;
    499         *len = sizeof(struct sockaddr_in6);
    500     } else
    501 #endif /* AF_INET6 */
    502         {
    503             struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
    504             *him = (struct sockaddr*)him4;
    505             *len = sizeof(struct sockaddr_in);
    506         }
    507 }
    508 
    509 #if 0
    510 // Android-changed: Stripped out unused code. http://b/33250070
    511 // #if defined(__linux__) && defined(AF_INET6)
    512 
    513 
    514 /* following code creates a list of addresses from the kernel
    515  * routing table that are routed via the loopback address.
    516  * We check all destination addresses against this table
    517  * and override the scope_id field to use the relevant value for "lo"
    518  * in order to work-around the Linux bug that prevents packets destined
    519  * for certain local addresses from being sent via a physical interface.
    520  */
    521 
    522 struct loopback_route {
    523     struct in6_addr addr; /* destination address */
    524     int plen; /* prefix length */
    525 };
    526 
    527 static struct loopback_route *loRoutes = 0;
    528 static int nRoutes = 0; /* number of routes */
    529 static int loRoutes_size = 16; /* initial size */
    530 static int lo_scope_id = 0;
    531 
    532 static void initLoopbackRoutes();
    533 
    534 void printAddr (struct in6_addr *addr) {
    535     int i;
    536     for (i=0; i<16; i++) {
    537         printf ("%02x", addr->s6_addr[i]);
    538     }
    539     printf ("\n");
    540 }
    541 
    542 static void initLoopbackRoutes() {
    543     FILE *f;
    544     char srcp[8][5];
    545     char hopp[8][5];
    546     int dest_plen, src_plen, use, refcnt, metric;
    547     unsigned long flags;
    548     char dest_str[40];
    549     struct in6_addr dest_addr;
    550     char device[16];
    551 
    552     if (loRoutes != 0) {
    553         free (loRoutes);
    554     }
    555     loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route));
    556     if (loRoutes == 0) {
    557         return;
    558     }
    559     /*
    560      * Scan /proc/net/ipv6_route looking for a matching
    561      * route.
    562      */
    563     if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
    564         return ;
    565     }
    566     while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
    567                      "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
    568                      "%4s%4s%4s%4s%4s%4s%4s%4s "
    569                      "%08x %08x %08x %08lx %8s",
    570                      dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
    571                      &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
    572                      &dest_plen,
    573                      srcp[0], srcp[1], srcp[2], srcp[3],
    574                      srcp[4], srcp[5], srcp[6], srcp[7],
    575                      &src_plen,
    576                      hopp[0], hopp[1], hopp[2], hopp[3],
    577                      hopp[4], hopp[5], hopp[6], hopp[7],
    578                      &metric, &use, &refcnt, &flags, device) == 31) {
    579 
    580         /*
    581          * Some routes should be ignored
    582          */
    583         if ( (dest_plen < 0 || dest_plen > 128)  ||
    584              (src_plen != 0) ||
    585              (flags & (RTF_POLICY | RTF_FLOW)) ||
    586              ((flags & RTF_REJECT) && dest_plen == 0) ) {
    587             continue;
    588         }
    589 
    590         /*
    591          * Convert the destination address
    592          */
    593         dest_str[4] = ':';
    594         dest_str[9] = ':';
    595         dest_str[14] = ':';
    596         dest_str[19] = ':';
    597         dest_str[24] = ':';
    598         dest_str[29] = ':';
    599         dest_str[34] = ':';
    600         dest_str[39] = '\0';
    601 
    602         if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
    603             /* not an Ipv6 address */
    604             continue;
    605         }
    606         if (strcmp(device, "lo") != 0) {
    607             /* Not a loopback route */
    608             continue;
    609         } else {
    610             if (nRoutes == loRoutes_size) {
    611                 loRoutes = realloc (loRoutes, loRoutes_size *
    612                                 sizeof (struct loopback_route) * 2);
    613                 if (loRoutes == 0) {
    614                     return ;
    615                 }
    616                 loRoutes_size *= 2;
    617             }
    618             memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr));
    619             loRoutes[nRoutes].plen = dest_plen;
    620             nRoutes ++;
    621         }
    622     }
    623 
    624     fclose (f);
    625     {
    626         /* now find the scope_id for "lo" */
    627 
    628         char devname[21];
    629         char addr6p[8][5];
    630         int plen, scope, dad_status, if_idx;
    631 
    632         if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
    633             while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
    634                       addr6p[0], addr6p[1], addr6p[2], addr6p[3],
    635                       addr6p[4], addr6p[5], addr6p[6], addr6p[7],
    636                   &if_idx, &plen, &scope, &dad_status, devname) == 13) {
    637 
    638                 if (strcmp(devname, "lo") == 0) {
    639                     /*
    640                      * Found - so just return the index
    641                      */
    642                     fclose(f);
    643                     lo_scope_id = if_idx;
    644                     return;
    645                 }
    646             }
    647             fclose(f);
    648         }
    649     }
    650 }
    651 
    652 /*
    653  * Following is used for binding to local addresses. Equivalent
    654  * to code above, for bind().
    655  */
    656 
    657 struct localinterface {
    658     int index;
    659     char localaddr [16];
    660 };
    661 
    662 static struct localinterface *localifs = 0;
    663 static int localifsSize = 0;    /* size of array */
    664 static int nifs = 0;            /* number of entries used in array */
    665 
    666 /* not thread safe: make sure called once from one thread */
    667 
    668 static void initLocalIfs () {
    669     FILE *f;
    670     unsigned char staddr [16];
    671     char ifname [33];
    672     struct localinterface *lif=0;
    673     int index, x1, x2, x3;
    674     unsigned int u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,ua,ub,uc,ud,ue,uf;
    675 
    676     if ((f = fopen("/proc/net/if_inet6", "r")) == NULL) {
    677         return ;
    678     }
    679     while (fscanf (f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x "
    680                 "%d %x %x %x %32s",&u0,&u1,&u2,&u3,&u4,&u5,&u6,&u7,
    681                 &u8,&u9,&ua,&ub,&uc,&ud,&ue,&uf,
    682                 &index, &x1, &x2, &x3, ifname) == 21) {
    683         staddr[0] = (unsigned char)u0;
    684         staddr[1] = (unsigned char)u1;
    685         staddr[2] = (unsigned char)u2;
    686         staddr[3] = (unsigned char)u3;
    687         staddr[4] = (unsigned char)u4;
    688         staddr[5] = (unsigned char)u5;
    689         staddr[6] = (unsigned char)u6;
    690         staddr[7] = (unsigned char)u7;
    691         staddr[8] = (unsigned char)u8;
    692         staddr[9] = (unsigned char)u9;
    693         staddr[10] = (unsigned char)ua;
    694         staddr[11] = (unsigned char)ub;
    695         staddr[12] = (unsigned char)uc;
    696         staddr[13] = (unsigned char)ud;
    697         staddr[14] = (unsigned char)ue;
    698         staddr[15] = (unsigned char)uf;
    699         nifs ++;
    700         if (nifs > localifsSize) {
    701             localifs = (struct localinterface *) realloc (
    702                         localifs, sizeof (struct localinterface)* (localifsSize+5));
    703             if (localifs == 0) {
    704                 nifs = 0;
    705                 fclose (f);
    706                 return;
    707             }
    708             lif = localifs + localifsSize;
    709             localifsSize += 5;
    710         } else {
    711             lif ++;
    712         }
    713         memcpy (lif->localaddr, staddr, 16);
    714         lif->index = index;
    715     }
    716     fclose (f);
    717 }
    718 
    719 void initLocalAddrTable () {
    720     initLoopbackRoutes();
    721     initLocalIfs();
    722 }
    723 
    724 #else
    725 
    726 void initLocalAddrTable () {}
    727 
    728 #endif
    729 
    730 void parseExclusiveBindProperty(JNIEnv *env) {
    731 #ifdef __solaris__
    732     jstring s, flagSet;
    733     jclass iCls;
    734     jmethodID mid;
    735 
    736     s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
    737     CHECK_NULL(s);
    738     iCls = (*env)->FindClass(env, "java/lang/System");
    739     CHECK_NULL(iCls);
    740     mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
    741                 "(Ljava/lang/String;)Ljava/lang/String;");
    742     CHECK_NULL(mid);
    743     flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
    744     if (flagSet != NULL) {
    745         useExclBind = 1;
    746     }
    747 #endif
    748 }
    749 /* In the case of an IPv4 Inetaddress this method will return an
    750  * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
    751  * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
    752 */
    753 JNIEXPORT int JNICALL
    754 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
    755                           int *len, jboolean v4MappedAddress) {
    756     jint family;
    757     family = getInetAddress_family(env, iaObj);
    758 #ifdef AF_INET6
    759     /* needs work. 1. family 2. clean up him6 etc deallocate memory */
    760     if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
    761         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
    762         jbyteArray ipaddress;
    763         jbyte caddr[16];
    764         jint address;
    765 
    766 
    767         if (family == IPv4) { /* will convert to IPv4-mapped address */
    768             memset((char *) caddr, 0, 16);
    769             address = getInetAddress_addr(env, iaObj);
    770             if (address == INADDR_ANY) {
    771                 /* we would always prefer IPv6 wildcard address
    772                    caddr[10] = 0xff;
    773                    caddr[11] = 0xff; */
    774             } else {
    775                 caddr[10] = 0xff;
    776                 caddr[11] = 0xff;
    777                 caddr[12] = ((address >> 24) & 0xff);
    778                 caddr[13] = ((address >> 16) & 0xff);
    779                 caddr[14] = ((address >> 8) & 0xff);
    780                 caddr[15] = (address & 0xff);
    781             }
    782         } else {
    783             getInet6Address_ipaddress(env, iaObj, (char *)caddr);
    784         }
    785         memset((char *)him6, 0, sizeof(struct sockaddr_in6));
    786         him6->sin6_port = htons(port);
    787         memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
    788         him6->sin6_family = AF_INET6;
    789         *len = sizeof(struct sockaddr_in6) ;
    790 
    791 #if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)
    792 // XXXBSD: should we do something with scope id here ? see below linux comment
    793 /* MMM: Come back to this! */
    794 #endif
    795 
    796         // Android-changed: Don't try and figure out scope_ids for link local
    797         // addresses. Use them only if they're set in java (say, if the Inet6Address
    798         // was constructed with a specific scope_id or NetworkInterface).
    799         if (family != IPv4) {
    800             if (ia6_scopeidID) {
    801                 int scope_id = getInet6Address_scopeid(env, iaObj);
    802                 if (scope_id > 0) {
    803                     him6->sin6_scope_id = scope_id;
    804                 }
    805             }
    806         }
    807     } else
    808 #endif /* AF_INET6 */
    809         {
    810             struct sockaddr_in *him4 = (struct sockaddr_in*)him;
    811             jint address;
    812             if (family == IPv6) {
    813               JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
    814               return -1;
    815             }
    816             memset((char *) him4, 0, sizeof(struct sockaddr_in));
    817             address = getInetAddress_addr(env, iaObj);
    818             him4->sin_port = htons((short) port);
    819             him4->sin_addr.s_addr = (uint32_t) htonl(address);
    820             him4->sin_family = AF_INET;
    821             *len = sizeof(struct sockaddr_in);
    822         }
    823     return 0;
    824 }
    825 
    826 // Android-removed: unused
    827 #if 0
    828 void
    829 NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
    830 #ifdef AF_INET6
    831     if (him->sa_family == AF_INET6) {
    832         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
    833         him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
    834     }
    835 #endif /* AF_INET6 */
    836 }
    837 #endif
    838 
    839 JNIEXPORT jint JNICALL
    840 NET_GetPortFromSockaddr(struct sockaddr *him) {
    841 #ifdef AF_INET6
    842     if (him->sa_family == AF_INET6) {
    843         return ntohs(((struct sockaddr_in6*)him)->sin6_port);
    844 
    845         } else
    846 #endif /* AF_INET6 */
    847             {
    848                 return ntohs(((struct sockaddr_in*)him)->sin_port);
    849             }
    850 }
    851 
    852 int
    853 NET_IsIPv4Mapped(jbyte* caddr) {
    854     int i;
    855     for (i = 0; i < 10; i++) {
    856         if (caddr[i] != 0x00) {
    857             return 0; /* false */
    858         }
    859     }
    860 
    861     if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {
    862         return 1; /* true */
    863     }
    864     return 0; /* false */
    865 }
    866 
    867 int
    868 NET_IPv4MappedToIPv4(jbyte* caddr) {
    869     return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
    870         | (caddr[15] & 0xff);
    871 }
    872 
    873 int
    874 NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
    875     int i;
    876     for (i = 0; i < 16; i++) {
    877         if (caddr1[i] != caddr2[i]) {
    878             return 0; /* false */
    879         }
    880     }
    881     return 1;
    882 }
    883 
    884 jboolean NET_addrtransAvailable() {
    885     return (jboolean)(getaddrinfo_ptr != NULL);
    886 }
    887 
    888 // Android-removed: unused
    889 #if 0
    890 int NET_IsZeroAddr(jbyte* caddr) {
    891     int i;
    892     for (i = 0; i < 16; i++) {
    893         if (caddr[i] != 0) {
    894             return 0;
    895         }
    896     }
    897     return 1;
    898 }
    899 #endif
    900 
    901 // Android-removed: unused
    902 #if 0
    903 /*
    904  * Map the Java level socket option to the platform specific
    905  * level and option name.
    906  */
    907 int
    908 NET_MapSocketOption(jint cmd, int *level, int *optname) {
    909     static struct {
    910         jint cmd;
    911         int level;
    912         int optname;
    913     } const opts[] = {
    914         { java_net_SocketOptions_TCP_NODELAY,           IPPROTO_TCP,    TCP_NODELAY },
    915         { java_net_SocketOptions_SO_OOBINLINE,          SOL_SOCKET,     SO_OOBINLINE },
    916         { java_net_SocketOptions_SO_LINGER,             SOL_SOCKET,     SO_LINGER },
    917         { java_net_SocketOptions_SO_SNDBUF,             SOL_SOCKET,     SO_SNDBUF },
    918         { java_net_SocketOptions_SO_RCVBUF,             SOL_SOCKET,     SO_RCVBUF },
    919         { java_net_SocketOptions_SO_KEEPALIVE,          SOL_SOCKET,     SO_KEEPALIVE },
    920         { java_net_SocketOptions_SO_REUSEADDR,          SOL_SOCKET,     SO_REUSEADDR },
    921         { java_net_SocketOptions_SO_BROADCAST,          SOL_SOCKET,     SO_BROADCAST },
    922         { java_net_SocketOptions_IP_TOS,                IPPROTO_IP,     IP_TOS },
    923         { java_net_SocketOptions_IP_MULTICAST_IF,       IPPROTO_IP,     IP_MULTICAST_IF },
    924         { java_net_SocketOptions_IP_MULTICAST_IF2,      IPPROTO_IP,     IP_MULTICAST_IF },
    925         { java_net_SocketOptions_IP_MULTICAST_LOOP,     IPPROTO_IP,     IP_MULTICAST_LOOP },
    926     };
    927 
    928     int i;
    929 
    930 #ifdef AF_INET6
    931     if (ipv6_available()) {
    932         switch (cmd) {
    933             // Different multicast options if IPv6 is enabled
    934             case java_net_SocketOptions_IP_MULTICAST_IF:
    935             case java_net_SocketOptions_IP_MULTICAST_IF2:
    936                 *level = IPPROTO_IPV6;
    937                 *optname = IPV6_MULTICAST_IF;
    938                 return 0;
    939 
    940             case java_net_SocketOptions_IP_MULTICAST_LOOP:
    941                 *level = IPPROTO_IPV6;
    942                 *optname = IPV6_MULTICAST_LOOP;
    943                 return 0;
    944 #if (defined(__solaris__) || defined(MACOSX))
    945             // Map IP_TOS request to IPV6_TCLASS
    946             case java_net_SocketOptions_IP_TOS:
    947                 *level = IPPROTO_IPV6;
    948                 *optname = IPV6_TCLASS;
    949                 return 0;
    950 #endif
    951         }
    952     }
    953 #endif
    954 
    955     /*
    956      * Map the Java level option to the native level
    957      */
    958     for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
    959         if (cmd == opts[i].cmd) {
    960             *level = opts[i].level;
    961             *optname = opts[i].optname;
    962             return 0;
    963         }
    964     }
    965 
    966     /* not found */
    967     return -1;
    968 }
    969 #endif
    970 
    971 /*
    972  * Wrapper for getsockopt system routine - does any necessary
    973  * pre/post processing to deal with OS specific oddities :-
    974  *
    975  * On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed
    976  * to compensate for an incorrect value returned by the kernel.
    977  */
    978 int
    979 NET_GetSockOpt(int fd, int level, int opt, void *result,
    980                int *len)
    981 {
    982     int rv;
    983 
    984 #ifdef __solaris__
    985     rv = getsockopt(fd, level, opt, result, len);
    986 #else
    987     {
    988         socklen_t socklen = *len;
    989         rv = getsockopt(fd, level, opt, result, &socklen);
    990         *len = socklen;
    991     }
    992 #endif
    993 
    994     if (rv < 0) {
    995         return rv;
    996     }
    997 
    998 #ifdef __linux__
    999     /*
   1000      * On Linux SO_SNDBUF/SO_RCVBUF aren't symmetric. This
   1001      * stems from additional socket structures in the send
   1002      * and receive buffers.
   1003      */
   1004     if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF)
   1005                                   || (opt == SO_RCVBUF))) {
   1006         int n = *((int *)result);
   1007         n /= 2;
   1008         *((int *)result) = n;
   1009     }
   1010 #endif
   1011 
   1012 /* Workaround for Mac OS treating linger value as
   1013  *  signed integer
   1014  */
   1015 #ifdef MACOSX
   1016     if (level == SOL_SOCKET && opt == SO_LINGER) {
   1017         struct linger* to_cast = (struct linger*)result;
   1018         to_cast->l_linger = (unsigned short)to_cast->l_linger;
   1019     }
   1020 #endif
   1021     return rv;
   1022 }
   1023 
   1024 /*
   1025  * Wrapper for setsockopt system routine - performs any
   1026  * necessary pre/post processing to deal with OS specific
   1027  * issue :-
   1028  *
   1029  * On Solaris need to limit the suggested value for SO_SNDBUF
   1030  * and SO_RCVBUF to the kernel configured limit
   1031  *
   1032  * For IP_TOS socket option need to mask off bits as this
   1033  * aren't automatically masked by the kernel and results in
   1034  * an error.
   1035  */
   1036 int
   1037 NET_SetSockOpt(int fd, int level, int  opt, const void *arg,
   1038                int len)
   1039 {
   1040 #ifndef IPTOS_TOS_MASK
   1041 #define IPTOS_TOS_MASK 0x1e
   1042 #endif
   1043 #ifndef IPTOS_PREC_MASK
   1044 #define IPTOS_PREC_MASK 0xe0
   1045 #endif
   1046 
   1047 #if defined(_ALLBSD_SOURCE)
   1048 #if defined(KIPC_MAXSOCKBUF)
   1049     int mib[3];
   1050     size_t rlen;
   1051 #endif
   1052 
   1053     int *bufsize;
   1054 
   1055 #ifdef __APPLE__
   1056     static int maxsockbuf = -1;
   1057 #else
   1058     static long maxsockbuf = -1;
   1059 #endif
   1060 #endif
   1061 
   1062     /*
   1063      * IPPROTO/IP_TOS :-
   1064      * 1. IPv6 on Solaris/Mac OS:
   1065      *    Set the TOS OR Traffic Class value to cater for
   1066      *    IPv6 and IPv4 scenarios.
   1067      * 2. IPv6 on Linux: By default Linux ignores flowinfo
   1068      *    field so enable IPV6_FLOWINFO_SEND so that flowinfo
   1069      *    will be examined. We also set the IPv4 TOS option in this case.
   1070      * 3. IPv4: set socket option based on ToS and Precedence
   1071      *    fields (otherwise get invalid argument)
   1072      */
   1073     if (level == IPPROTO_IP && opt == IP_TOS) {
   1074         int *iptos;
   1075 
   1076 #if defined(AF_INET6) && defined(__linux__)
   1077         if (ipv6_available()) {
   1078             int optval = 1;
   1079             if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
   1080                            (void *)&optval, sizeof(optval)) < 0) {
   1081                 return -1;
   1082             }
   1083            /*
   1084             * Let's also set the IPV6_TCLASS flag.
   1085             * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set
   1086             * This helps in mixed environments where IPv4 and IPv6 sockets
   1087             * are connecting.
   1088             */
   1089            if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
   1090                            arg, len) < 0) {
   1091                 return -1;
   1092             }
   1093         }
   1094 #endif
   1095 
   1096         iptos = (int *)arg;
   1097         // Android-changed: This is out-dated RFC 1349 scheme. Modern Linux uses
   1098         // Diffsev/ECN, and this mask is no longer relavant.
   1099         // *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
   1100     }
   1101 
   1102     /*
   1103      * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
   1104      * the value when it exceeds the system limit.
   1105      */
   1106 #ifdef __solaris__
   1107     if (level == SOL_SOCKET) {
   1108         if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
   1109             int sotype=0, arglen;
   1110             int *bufsize, maxbuf;
   1111             int ret;
   1112 
   1113             /* Attempt with the original size */
   1114             ret = setsockopt(fd, level, opt, arg, len);
   1115             if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
   1116                 return ret;
   1117 
   1118             /* Exceeded system limit so clamp and retry */
   1119 
   1120             arglen = sizeof(sotype);
   1121             if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
   1122                            &arglen) < 0) {
   1123                 return -1;
   1124             }
   1125 
   1126             /*
   1127              * We try to get tcp_maxbuf (and udp_max_buf) using
   1128              * an ioctl() that isn't available on all versions of Solaris.
   1129              * If that fails, we use the search algorithm in findMaxBuf()
   1130              */
   1131             if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
   1132                 tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf");
   1133                 if (tcp_max_buf == -1) {
   1134                     tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
   1135                     if (tcp_max_buf == -1) {
   1136                         return -1;
   1137                     }
   1138                 }
   1139                 init_tcp_max_buf = 1;
   1140             } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
   1141                 udp_max_buf = getParam("/dev/udp", "udp_max_buf");
   1142                 if (udp_max_buf == -1) {
   1143                     udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
   1144                     if (udp_max_buf == -1) {
   1145                         return -1;
   1146                     }
   1147                 }
   1148                 init_udp_max_buf = 1;
   1149             }
   1150 
   1151             maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
   1152             bufsize = (int *)arg;
   1153             if (*bufsize > maxbuf) {
   1154                 *bufsize = maxbuf;
   1155             }
   1156         }
   1157     }
   1158 #endif
   1159 
   1160     /*
   1161      * On Linux the receive buffer is used for both socket
   1162      * structures and the the packet payload. The implication
   1163      * is that if SO_RCVBUF is too small then small packets
   1164      * must be discarded.
   1165      */
   1166 #ifdef __linux__
   1167     if (level == SOL_SOCKET && opt == SO_RCVBUF) {
   1168         int *bufsize = (int *)arg;
   1169         if (*bufsize < 1024) {
   1170             *bufsize = 1024;
   1171         }
   1172     }
   1173 #endif
   1174 
   1175 #if defined(_ALLBSD_SOURCE)
   1176     /*
   1177      * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to
   1178      * ensure that value is <= kern.ipc.maxsockbuf as otherwise we get
   1179      * an ENOBUFS error.
   1180      */
   1181     if (level == SOL_SOCKET) {
   1182         if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
   1183 #ifdef KIPC_MAXSOCKBUF
   1184             if (maxsockbuf == -1) {
   1185                mib[0] = CTL_KERN;
   1186                mib[1] = KERN_IPC;
   1187                mib[2] = KIPC_MAXSOCKBUF;
   1188                rlen = sizeof(maxsockbuf);
   1189                if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1)
   1190                    maxsockbuf = 1024;
   1191 
   1192 #if 1
   1193                /* XXXBSD: This is a hack to workaround mb_max/mb_max_adj
   1194                   problem.  It should be removed when kern.ipc.maxsockbuf
   1195                   will be real value. */
   1196                maxsockbuf = (maxsockbuf/5)*4;
   1197 #endif
   1198            }
   1199 #elif defined(__OpenBSD__)
   1200            maxsockbuf = SB_MAX;
   1201 #else
   1202            maxsockbuf = 64 * 1024;      /* XXX: NetBSD */
   1203 #endif
   1204 
   1205            bufsize = (int *)arg;
   1206            if (*bufsize > maxsockbuf) {
   1207                *bufsize = maxsockbuf;
   1208            }
   1209 
   1210            if (opt == SO_RCVBUF && *bufsize < 1024) {
   1211                 *bufsize = 1024;
   1212            }
   1213 
   1214         }
   1215     }
   1216 
   1217     /*
   1218      * On Solaris, SO_REUSEADDR will allow multiple datagram
   1219      * sockets to bind to the same port.  The network jck tests
   1220      * for this "feature", so we need to emulate it by turning on
   1221      * SO_REUSEPORT as well for that combination.
   1222      */
   1223     if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
   1224         int sotype;
   1225         socklen_t arglen;
   1226 
   1227         arglen = sizeof(sotype);
   1228         if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
   1229             return -1;
   1230         }
   1231 
   1232         if (sotype == SOCK_DGRAM) {
   1233             setsockopt(fd, level, SO_REUSEPORT, arg, len);
   1234         }
   1235     }
   1236 
   1237 #endif
   1238 
   1239     return setsockopt(fd, level, opt, arg, len);
   1240 }
   1241 
   1242 /*
   1243  * Wrapper for bind system call - performs any necessary pre/post
   1244  * processing to deal with OS specific issues :-
   1245  *
   1246  * Linux allows a socket to bind to 127.0.0.255 which must be
   1247  * caught.
   1248  *
   1249  * On Solaris with IPv6 enabled we must use an exclusive
   1250  * bind to guaranteed a unique port number across the IPv4 and
   1251  * IPv6 port spaces.
   1252  *
   1253  */
   1254 int
   1255 NET_Bind(int fd, struct sockaddr *him, int len)
   1256 {
   1257 #if defined(__solaris__) && defined(AF_INET6)
   1258     int level = -1;
   1259     int exclbind = -1;
   1260 #endif
   1261     int rv;
   1262 
   1263 #ifdef __linux__
   1264     /*
   1265      * ## get bugId for this issue - goes back to 1.2.2 port ##
   1266      * ## When IPv6 is enabled this will be an IPv4-mapped
   1267      * ## with family set to AF_INET6
   1268      */
   1269     if (him->sa_family == AF_INET) {
   1270         struct sockaddr_in *sa = (struct sockaddr_in *)him;
   1271         if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
   1272             errno = EADDRNOTAVAIL;
   1273             return -1;
   1274         }
   1275     }
   1276 #endif
   1277 
   1278 #if defined(__solaris__) && defined(AF_INET6)
   1279     /*
   1280      * Solaris has seperate IPv4 and IPv6 port spaces so we
   1281      * use an exclusive bind when SO_REUSEADDR is not used to
   1282      * give the illusion of a unified port space.
   1283      * This also avoids problems with IPv6 sockets connecting
   1284      * to IPv4 mapped addresses whereby the socket conversion
   1285      * results in a late bind that fails because the
   1286      * corresponding IPv4 port is in use.
   1287      */
   1288     if (ipv6_available()) {
   1289         int arg, len;
   1290 
   1291         len = sizeof(arg);
   1292         if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
   1293                        (char *)&arg, &len) == 0) {
   1294             if (useExclBind || arg == 0) {
   1295                 /*
   1296                  * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
   1297                  * property is true so enable TCP_EXCLBIND or
   1298                  * UDP_EXCLBIND
   1299                  */
   1300                 len = sizeof(arg);
   1301                 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,
   1302                                &len) == 0) {
   1303                     if (arg == SOCK_STREAM) {
   1304                         level = IPPROTO_TCP;
   1305                         exclbind = TCP_EXCLBIND;
   1306                     } else {
   1307                         level = IPPROTO_UDP;
   1308                         exclbind = UDP_EXCLBIND;
   1309                     }
   1310                 }
   1311 
   1312                 arg = 1;
   1313                 setsockopt(fd, level, exclbind, (char *)&arg,
   1314                            sizeof(arg));
   1315             }
   1316         }
   1317     }
   1318 
   1319 #endif
   1320 
   1321     rv = bind(fd, him, len);
   1322 
   1323 #if defined(__solaris__) && defined(AF_INET6)
   1324     if (rv < 0) {
   1325         int en = errno;
   1326         /* Restore *_EXCLBIND if the bind fails */
   1327         if (exclbind != -1) {
   1328             int arg = 0;
   1329             setsockopt(fd, level, exclbind, (char *)&arg,
   1330                        sizeof(arg));
   1331         }
   1332         errno = en;
   1333     }
   1334 #endif
   1335 
   1336     return rv;
   1337 }
   1338 
   1339 // Android-removed: unused
   1340 #if 0
   1341 /**
   1342  * Wrapper for select/poll with timeout on a single file descriptor.
   1343  *
   1344  * flags (defined in net_util_md.h can be any combination of
   1345  * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
   1346  *
   1347  * The function will return when either the socket is ready for one
   1348  * of the specified operations or the timeout expired.
   1349  *
   1350  * It returns the time left from the timeout (possibly 0), or -1 if it expired.
   1351  */
   1352 
   1353 jint
   1354 NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
   1355 {
   1356     jlong prevTime = JVM_CurrentTimeMillis(env, 0);
   1357     jint read_rv;
   1358 
   1359     while (1) {
   1360         jlong newTime;
   1361 #ifndef USE_SELECT
   1362         {
   1363           struct pollfd pfd;
   1364           pfd.fd = fd;
   1365           pfd.events = 0;
   1366           if (flags & NET_WAIT_READ)
   1367             pfd.events |= POLLIN;
   1368           if (flags & NET_WAIT_WRITE)
   1369             pfd.events |= POLLOUT;
   1370           if (flags & NET_WAIT_CONNECT)
   1371             pfd.events |= POLLOUT;
   1372 
   1373           errno = 0;
   1374           read_rv = NET_Poll(&pfd, 1, timeout);
   1375         }
   1376 #else
   1377         {
   1378           fd_set rd, wr, ex;
   1379           struct timeval t;
   1380 
   1381           t.tv_sec = timeout / 1000;
   1382           t.tv_usec = (timeout % 1000) * 1000;
   1383 
   1384           FD_ZERO(&rd);
   1385           FD_ZERO(&wr);
   1386           FD_ZERO(&ex);
   1387           if (flags & NET_WAIT_READ) {
   1388             FD_SET(fd, &rd);
   1389           }
   1390           if (flags & NET_WAIT_WRITE) {
   1391             FD_SET(fd, &wr);
   1392           }
   1393           if (flags & NET_WAIT_CONNECT) {
   1394             FD_SET(fd, &wr);
   1395             FD_SET(fd, &ex);
   1396           }
   1397 
   1398           errno = 0;
   1399           read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);
   1400         }
   1401 #endif
   1402 
   1403         newTime = JVM_CurrentTimeMillis(env, 0);
   1404         timeout -= (newTime - prevTime);
   1405         if (timeout <= 0) {
   1406           return read_rv > 0 ? 0 : -1;
   1407         }
   1408         prevTime = newTime;
   1409 
   1410         if (read_rv > 0) {
   1411           break;
   1412         }
   1413 
   1414 
   1415       } /* while */
   1416 
   1417     return timeout;
   1418 }
   1419 #endif
   1420 
   1421 #if 0
   1422 // Stripped out unused code.
   1423 // http://b/27301951
   1424 __attribute__((destructor))
   1425 static void netUtilCleanUp() {
   1426     if (loRoutes != 0) free(loRoutes);
   1427     if (localifs != 0) free(localifs);
   1428 }
   1429 #endif
   1430