Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/java/net/net_util_md.c
32287 views
/*1* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <errno.h>26#include <string.h>27#include <sys/types.h>28#include <sys/socket.h>29#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */30#include <netinet/in.h>31#include <net/if.h>32#include <netdb.h>33#include <stdlib.h>34#include <dlfcn.h>35#include <sys/time.h>3637#ifndef _ALLBSD_SOURCE38# ifndef __ANDROID__39# include <values.h>40# else41# include "values.h"42# endif43#else44#include <limits.h>45#include <sys/param.h>46#include <sys/sysctl.h>47#ifndef MAXINT48#define MAXINT INT_MAX49#endif50#endif5152#ifdef __solaris__53#include <sys/sockio.h>54#include <stropts.h>55#include <inet/nd.h>56#endif5758#if defined(__linux__) || defined(__ANDROID__)59#include <arpa/inet.h>60#include <net/route.h>61#include <sys/utsname.h>6263#ifndef IPV6_FLOWINFO_SEND64#define IPV6_FLOWINFO_SEND 3365#endif6667#endif6869#include "jni_util.h"70#include "jvm.h"71#include "net_util.h"7273#include "java_net_SocketOptions.h"7475/*76* EXCLBIND socket options only on Solaris77*/78#if defined(__solaris__) && !defined(TCP_EXCLBIND)79#define TCP_EXCLBIND 0x2180#endif81#if defined(__solaris__) && !defined(UDP_EXCLBIND)82#define UDP_EXCLBIND 0x010183#endif8485void setDefaultScopeID(JNIEnv *env, struct sockaddr *him)86{87#ifdef MACOSX88static jclass ni_class = NULL;89static jfieldID ni_defaultIndexID;90if (ni_class == NULL) {91jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");92CHECK_NULL(c);93c = (*env)->NewGlobalRef(env, c);94CHECK_NULL(c);95ni_defaultIndexID = (*env)->GetStaticFieldID(96env, c, "defaultIndex", "I");97CHECK_NULL(ni_defaultIndexID);98ni_class = c;99}100int defaultIndex;101struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)him;102if (sin6->sin6_family == AF_INET6 && (sin6->sin6_scope_id == 0) &&103(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||104IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {105defaultIndex = (*env)->GetStaticIntField(env, ni_class,106ni_defaultIndexID);107sin6->sin6_scope_id = defaultIndex;108}109#endif110}111112int getDefaultScopeID(JNIEnv *env) {113static jclass ni_class = NULL;114static jfieldID ni_defaultIndexID;115int defaultIndex = 0;116117if (ni_class == NULL) {118jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");119CHECK_NULL_RETURN(c, 0);120c = (*env)->NewGlobalRef(env, c);121CHECK_NULL_RETURN(c, 0);122ni_defaultIndexID = (*env)->GetStaticFieldID(env, c,123"defaultIndex", "I");124CHECK_NULL_RETURN(ni_defaultIndexID, 0);125ni_class = c;126}127defaultIndex = (*env)->GetStaticIntField(env, ni_class,128ni_defaultIndexID);129return defaultIndex;130}131132#ifdef __solaris__133static int init_tcp_max_buf, init_udp_max_buf;134static int tcp_max_buf;135static int udp_max_buf;136static int useExclBind = 0;137138/*139* Get the specified parameter from the specified driver. The value140* of the parameter is assumed to be an 'int'. If the parameter141* cannot be obtained return -1142*/143int net_getParam(char *driver, char *param)144{145struct strioctl stri;146char buf [64];147int s;148int value;149150s = open (driver, O_RDWR);151if (s < 0) {152return -1;153}154strncpy (buf, param, sizeof(buf));155stri.ic_cmd = ND_GET;156stri.ic_timout = 0;157stri.ic_dp = buf;158stri.ic_len = sizeof(buf);159if (ioctl (s, I_STR, &stri) < 0) {160value = -1;161} else {162value = atoi(buf);163}164close (s);165return value;166}167168/*169* Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF170* for Solaris versions that do not support the ioctl() in net_getParam().171* Ugly, but only called once (for each sotype).172*173* As an optimization, we make a guess using the default values for Solaris174* assuming they haven't been modified with ndd.175*/176177#define MAX_TCP_GUESS 1024 * 1024178#define MAX_UDP_GUESS 2 * 1024 * 1024179180#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1181182static int findMaxBuf(int fd, int opt, int sotype) {183int a = 0;184int b = MAXINT;185int initial_guess;186int limit = -1;187188if (sotype == SOCK_DGRAM) {189initial_guess = MAX_UDP_GUESS;190} else {191initial_guess = MAX_TCP_GUESS;192}193194if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {195initial_guess++;196if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {197FAIL_IF_NOT_ENOBUFS;198return initial_guess - 1;199}200a = initial_guess;201} else {202FAIL_IF_NOT_ENOBUFS;203b = initial_guess - 1;204}205do {206int mid = a + (b-a)/2;207if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {208limit = mid;209a = mid + 1;210} else {211FAIL_IF_NOT_ENOBUFS;212b = mid - 1;213}214} while (b >= a);215216return limit;217}218#endif219220#ifdef __linux__221static int vinit = 0;222static int kernelV24 = 0;223static int vinit24 = 0;224225int kernelIsV24 () {226if (!vinit24) {227struct utsname sysinfo;228if (uname(&sysinfo) == 0) {229sysinfo.release[3] = '\0';230if (strcmp(sysinfo.release, "2.4") == 0) {231kernelV24 = JNI_TRUE;232}233}234vinit24 = 1;235}236return kernelV24;237}238239int getScopeID (struct sockaddr *him) {240struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;241return hext->sin6_scope_id;242}243244int cmpScopeID (unsigned int scope, struct sockaddr *him) {245struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;246return hext->sin6_scope_id == scope;247}248249#else250251int getScopeID (struct sockaddr *him) {252struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;253return him6->sin6_scope_id;254}255256int cmpScopeID (unsigned int scope, struct sockaddr *him) {257struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;258return him6->sin6_scope_id == scope;259}260261#endif262263264void265NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,266const char *defaultDetail) {267JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);268}269270void271NET_ThrowCurrent(JNIEnv *env, char *msg) {272NET_ThrowNew(env, errno, msg);273}274275void276NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {277char fullMsg[512];278if (!msg) {279msg = "no further information";280}281switch(errorNumber) {282case EBADF:283jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);284JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);285break;286case EINTR:287JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg);288break;289default:290errno = errorNumber;291JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg);292break;293}294}295296297jfieldID298NET_GetFileDescriptorID(JNIEnv *env)299{300jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");301CHECK_NULL_RETURN(cls, NULL);302return (*env)->GetFieldID(env, cls, "fd", "I");303}304305#if defined(DONT_ENABLE_IPV6)306jint IPv6_supported()307{308return JNI_FALSE;309}310311#else /* !DONT_ENABLE_IPV6 */312313jint IPv6_supported()314{315#ifndef AF_INET6316return JNI_FALSE;317#endif318319#ifdef AF_INET6320int fd;321void *ipv6_fn;322SOCKADDR sa;323socklen_t sa_len = sizeof(sa);324325fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ;326if (fd < 0) {327/*328* TODO: We really cant tell since it may be an unrelated error329* for now we will assume that AF_INET6 is not available330*/331return JNI_FALSE;332}333334/*335* If fd 0 is a socket it means we've been launched from inetd or336* xinetd. If it's a socket then check the family - if it's an337* IPv4 socket then we need to disable IPv6.338*/339if (getsockname(0, (struct sockaddr *)&sa, &sa_len) == 0) {340struct sockaddr *saP = (struct sockaddr *)&sa;341if (saP->sa_family != AF_INET6) {342close(fd);343return JNI_FALSE;344}345}346347/**348* Linux - check if any interface has an IPv6 address.349* Don't need to parse the line - we just need an indication.350*/351#ifdef __linux__352{353FILE *fP = fopen("/proc/net/if_inet6", "r");354char buf[255];355char *bufP;356357if (fP == NULL) {358close(fd);359return JNI_FALSE;360}361bufP = fgets(buf, sizeof(buf), fP);362fclose(fP);363if (bufP == NULL) {364close(fd);365return JNI_FALSE;366}367}368#endif369370/**371* On Solaris 8 it's possible to create INET6 sockets even372* though IPv6 is not enabled on all interfaces. Thus we373* query the number of IPv6 addresses to verify that IPv6374* has been configured on at least one interface.375*376* On Linux it doesn't matter - if IPv6 is built-in the377* kernel then IPv6 addresses will be bound automatically378* to all interfaces.379*/380#ifdef __solaris__381382#ifdef SIOCGLIFNUM383{384struct lifnum numifs;385386numifs.lifn_family = AF_INET6;387numifs.lifn_flags = 0;388if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {389/**390* SIOCGLIFNUM failed - assume IPv6 not configured391*/392close(fd);393return JNI_FALSE;394}395/**396* If no IPv6 addresses then return false. If count > 0397* it's possible that all IPv6 addresses are "down" but398* that's okay as they may be brought "up" while the399* VM is running.400*/401if (numifs.lifn_count == 0) {402close(fd);403return JNI_FALSE;404}405}406#else407/* SIOCGLIFNUM not defined in build environment ??? */408close(fd);409return JNI_FALSE;410#endif411412#endif /* __solaris */413414/*415* OK we may have the stack available in the kernel,416* we should also check if the APIs are available.417*/418ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");419close(fd);420if (ipv6_fn == NULL ) {421return JNI_FALSE;422} else {423return JNI_TRUE;424}425#endif /* AF_INET6 */426}427#endif /* DONT_ENABLE_IPV6 */428429void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,430const char* hostname,431int gai_error)432{433int size;434char *buf;435const char *format = "%s: %s";436const char *error_string = gai_strerror(gai_error);437if (error_string == NULL)438error_string = "unknown error";439440size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;441buf = (char *) malloc(size);442if (buf) {443jstring s;444sprintf(buf, format, hostname, error_string);445s = JNU_NewStringPlatform(env, buf);446if (s != NULL) {447jobject x = JNU_NewObjectByName(env,448"java/net/UnknownHostException",449"(Ljava/lang/String;)V", s);450if (x != NULL)451(*env)->Throw(env, x);452}453free(buf);454}455}456457void458NET_AllocSockaddr(struct sockaddr **him, int *len) {459#ifdef AF_INET6460if (ipv6_available()) {461struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6));462*him = (struct sockaddr*)him6;463*len = sizeof(struct sockaddr_in6);464} else465#endif /* AF_INET6 */466{467struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));468*him = (struct sockaddr*)him4;469*len = sizeof(struct sockaddr_in);470}471}472473#if defined(__linux__) && defined(AF_INET6)474475476/* following code creates a list of addresses from the kernel477* routing table that are routed via the loopback address.478* We check all destination addresses against this table479* and override the scope_id field to use the relevant value for "lo"480* in order to work-around the Linux bug that prevents packets destined481* for certain local addresses from being sent via a physical interface.482*/483484struct loopback_route {485struct in6_addr addr; /* destination address */486int plen; /* prefix length */487};488489static struct loopback_route *loRoutes = 0;490static int nRoutes = 0; /* number of routes */491static int loRoutes_size = 16; /* initial size */492static int lo_scope_id = 0;493494static void initLoopbackRoutes();495496void printAddr (struct in6_addr *addr) {497int i;498for (i=0; i<16; i++) {499printf ("%02x", addr->s6_addr[i]);500}501printf ("\n");502}503504static jboolean needsLoopbackRoute (struct in6_addr* dest_addr) {505int byte_count;506int extra_bits, i;507struct loopback_route *ptr;508509if (loRoutes == 0) {510initLoopbackRoutes();511}512513for (ptr = loRoutes, i=0; i<nRoutes; i++, ptr++) {514struct in6_addr *target_addr=&ptr->addr;515int dest_plen = ptr->plen;516byte_count = dest_plen >> 3;517extra_bits = dest_plen & 0x3;518519if (byte_count > 0) {520if (memcmp(target_addr, dest_addr, byte_count)) {521continue; /* no match */522}523}524525if (extra_bits > 0) {526unsigned char c1 = ((unsigned char *)target_addr)[byte_count];527unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];528unsigned char mask = 0xff << (8 - extra_bits);529if ((c1 & mask) != (c2 & mask)) {530continue;531}532}533return JNI_TRUE;534}535return JNI_FALSE;536}537538539static void initLoopbackRoutes() {540FILE *f;541char srcp[8][5];542char hopp[8][5];543int dest_plen, src_plen, use, refcnt, metric;544unsigned long flags;545char dest_str[40];546struct in6_addr dest_addr;547char device[16];548struct loopback_route *loRoutesTemp;549550if (loRoutes != 0) {551free (loRoutes);552}553loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route));554if (loRoutes == 0) {555return;556}557/*558* Scan /proc/net/ipv6_route looking for a matching559* route.560*/561if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {562return ;563}564while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "565"%4s%4s%4s%4s%4s%4s%4s%4s %02x "566"%4s%4s%4s%4s%4s%4s%4s%4s "567"%08x %08x %08x %08lx %8s",568dest_str, &dest_str[5], &dest_str[10], &dest_str[15],569&dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],570&dest_plen,571srcp[0], srcp[1], srcp[2], srcp[3],572srcp[4], srcp[5], srcp[6], srcp[7],573&src_plen,574hopp[0], hopp[1], hopp[2], hopp[3],575hopp[4], hopp[5], hopp[6], hopp[7],576&metric, &use, &refcnt, &flags, device) == 31) {577578/*579* Some routes should be ignored580*/581if ( (dest_plen < 0 || dest_plen > 128) ||582(src_plen != 0) ||583#ifndef __ANDROID__584(flags & (RTF_POLICY | RTF_FLOW)) ||585#endif586((flags & RTF_REJECT) && dest_plen == 0) ) {587continue;588}589590/*591* Convert the destination address592*/593dest_str[4] = ':';594dest_str[9] = ':';595dest_str[14] = ':';596dest_str[19] = ':';597dest_str[24] = ':';598dest_str[29] = ':';599dest_str[34] = ':';600dest_str[39] = '\0';601602if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {603/* not an Ipv6 address */604continue;605}606if (strcmp(device, "lo") != 0) {607/* Not a loopback route */608continue;609} else {610if (nRoutes == loRoutes_size) {611loRoutesTemp = realloc (loRoutes, loRoutes_size *612sizeof (struct loopback_route) * 2);613614if (loRoutesTemp == 0) {615free(loRoutes);616loRoutes = NULL;617nRoutes = 0;618fclose (f);619return;620}621loRoutes=loRoutesTemp;622loRoutes_size *= 2;623}624memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr));625loRoutes[nRoutes].plen = dest_plen;626nRoutes ++;627}628}629630fclose (f);631{632/* now find the scope_id for "lo" */633634char devname[21];635char addr6p[8][5];636int plen, scope, dad_status, if_idx;637638if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {639while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",640addr6p[0], addr6p[1], addr6p[2], addr6p[3],641addr6p[4], addr6p[5], addr6p[6], addr6p[7],642&if_idx, &plen, &scope, &dad_status, devname) == 13) {643644if (strcmp(devname, "lo") == 0) {645/*646* Found - so just return the index647*/648fclose(f);649lo_scope_id = if_idx;650return;651}652}653fclose(f);654}655}656}657658/*659* Following is used for binding to local addresses. Equivalent660* to code above, for bind().661*/662663struct localinterface {664int index;665char localaddr [16];666};667668static struct localinterface *localifs = 0;669static int localifsSize = 0; /* size of array */670static int nifs = 0; /* number of entries used in array */671672/* not thread safe: make sure called once from one thread */673674static void initLocalIfs () {675/* Android port:676* - Android 5.x cause crashes.677* - Android 6+ read /proc/net/if_inet6 gives "permission denied", so it skips.678* So, skip them to fix Android 5.x crashes.679*/680#ifndef __ANDROID__681FILE *f;682unsigned char staddr [16];683char ifname [33];684struct localinterface *lif=0;685int index, x1, x2, x3;686unsigned int u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,ua,ub,uc,ud,ue,uf;687688if ((f = fopen("/proc/net/if_inet6", "r")) == NULL) {689return ;690}691while (fscanf (f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x "692"%d %x %x %x %32s",&u0,&u1,&u2,&u3,&u4,&u5,&u6,&u7,693&u8,&u9,&ua,&ub,&uc,&ud,&ue,&uf,694&index, &x1, &x2, &x3, ifname) == 21) {695staddr[0] = (unsigned char)u0;696staddr[1] = (unsigned char)u1;697staddr[2] = (unsigned char)u2;698staddr[3] = (unsigned char)u3;699staddr[4] = (unsigned char)u4;700staddr[5] = (unsigned char)u5;701staddr[6] = (unsigned char)u6;702staddr[7] = (unsigned char)u7;703staddr[8] = (unsigned char)u8;704staddr[9] = (unsigned char)u9;705staddr[10] = (unsigned char)ua;706staddr[11] = (unsigned char)ub;707staddr[12] = (unsigned char)uc;708staddr[13] = (unsigned char)ud;709staddr[14] = (unsigned char)ue;710staddr[15] = (unsigned char)uf;711nifs ++;712if (nifs > localifsSize) {713localifs = (struct localinterface *) realloc (714localifs, sizeof (struct localinterface)* (localifsSize+5));715if (localifs == 0) {716nifs = 0;717fclose (f);718return;719}720lif = localifs + localifsSize;721localifsSize += 5;722} else {723lif ++;724}725memcpy (lif->localaddr, staddr, 16);726lif->index = index;727}728fclose (f);729#endif730}731732/* return the scope_id (interface index) of the733* interface corresponding to the given address734* returns 0 if no match found735*/736737static int getLocalScopeID (char *addr) {738struct localinterface *lif;739int i;740if (localifs == 0) {741initLocalIfs();742}743for (i=0, lif=localifs; i<nifs; i++, lif++) {744if (memcmp (addr, lif->localaddr, 16) == 0) {745return lif->index;746}747}748return 0;749}750751void platformInit () {752initLoopbackRoutes();753initLocalIfs();754}755756#elif defined(_AIX)757758/* Initialize stubs for blocking I/O workarounds (see src/solaris/native/java/net/linux_close.c) */759extern void aix_close_init();760761void platformInit () {762aix_close_init();763}764765#else766767void platformInit () {}768769#endif770771void parseExclusiveBindProperty(JNIEnv *env) {772#ifdef __solaris__773jstring s, flagSet;774jclass iCls;775jmethodID mid;776777s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");778CHECK_NULL(s);779iCls = (*env)->FindClass(env, "java/lang/System");780CHECK_NULL(iCls);781mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",782"(Ljava/lang/String;)Ljava/lang/String;");783CHECK_NULL(mid);784flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);785if (flagSet != NULL) {786useExclBind = 1;787}788#endif789}790791JNIEXPORT jint JNICALL792NET_EnableFastTcpLoopback(int fd) {793return 0;794}795796/* In the case of an IPv4 Inetaddress this method will return an797* IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.798* Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.799*/800JNIEXPORT int JNICALL801NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,802int *len, jboolean v4MappedAddress) {803jint family;804family = getInetAddress_family(env, iaObj);805JNU_CHECK_EXCEPTION_RETURN(env, -1);806#ifdef AF_INET6807/* needs work. 1. family 2. clean up him6 etc deallocate memory */808if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {809struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;810jbyte caddr[16];811jint address;812813814if (family == IPv4) { /* will convert to IPv4-mapped address */815memset((char *) caddr, 0, 16);816address = getInetAddress_addr(env, iaObj);817JNU_CHECK_EXCEPTION_RETURN(env, -1);818if (address == INADDR_ANY) {819/* we would always prefer IPv6 wildcard address820caddr[10] = 0xff;821caddr[11] = 0xff; */822} else {823caddr[10] = 0xff;824caddr[11] = 0xff;825caddr[12] = ((address >> 24) & 0xff);826caddr[13] = ((address >> 16) & 0xff);827caddr[14] = ((address >> 8) & 0xff);828caddr[15] = (address & 0xff);829}830} else {831getInet6Address_ipaddress(env, iaObj, (char *)caddr);832}833memset((char *)him6, 0, sizeof(struct sockaddr_in6));834him6->sin6_port = htons(port);835memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );836him6->sin6_family = AF_INET6;837*len = sizeof(struct sockaddr_in6) ;838839#if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)840// XXXBSD: should we do something with scope id here ? see below linux comment841/* MMM: Come back to this! */842#endif843844/*845* On Linux if we are connecting to a link-local address846* we need to specify the interface in the scope_id (2.4 kernel only)847*848* If the scope was cached the we use the cached value. If not cached but849* specified in the Inet6Address we use that, but we first check if the850* address needs to be routed via the loopback interface. In this case,851* we override the specified value with that of the loopback interface.852* If no cached value exists and no value was specified by user, then853* we try to determine a value from the routing table. In all these854* cases the used value is cached for further use.855*/856#ifdef __linux__857if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) {858int cached_scope_id = 0, scope_id = 0;859860if (ia6_cachedscopeidID) {861cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);862/* if cached value exists then use it. Otherwise, check863* if scope is set in the address.864*/865if (!cached_scope_id) {866if (ia6_scopeidID) {867scope_id = getInet6Address_scopeid(env, iaObj);868}869if (scope_id != 0) {870/* check user-specified value for loopback case871* that needs to be overridden872*/873if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) {874cached_scope_id = lo_scope_id;875(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);876}877} else {878/*879* Otherwise consult the IPv6 routing tables to880* try determine the appropriate interface.881*/882if (kernelIsV24()) {883cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );884} else {885cached_scope_id = getLocalScopeID( (char *)&(him6->sin6_addr) );886if (cached_scope_id == 0) {887cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );888}889}890(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);891}892}893}894895/*896* If we have a scope_id use the extended form897* of sockaddr_in6.898*/899900struct sockaddr_in6 *him6 =901(struct sockaddr_in6 *)him;902him6->sin6_scope_id = cached_scope_id != 0 ?903cached_scope_id : scope_id;904*len = sizeof(struct sockaddr_in6);905}906#else907/* handle scope_id for solaris */908909if (family != IPv4) {910if (ia6_scopeidID) {911him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);912}913}914#endif915} else916#endif /* AF_INET6 */917{918struct sockaddr_in *him4 = (struct sockaddr_in*)him;919jint address;920if (family == IPv6) {921JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");922return -1;923}924memset((char *) him4, 0, sizeof(struct sockaddr_in));925address = getInetAddress_addr(env, iaObj);926JNU_CHECK_EXCEPTION_RETURN(env, -1);927him4->sin_port = htons((short) port);928him4->sin_addr.s_addr = (uint32_t) htonl(address);929him4->sin_family = AF_INET;930*len = sizeof(struct sockaddr_in);931}932return 0;933}934935void936NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {937#ifdef AF_INET6938if (him->sa_family == AF_INET6) {939struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;940him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);941}942#endif /* AF_INET6 */943}944945JNIEXPORT jint JNICALL946NET_GetPortFromSockaddr(struct sockaddr *him) {947#ifdef AF_INET6948if (him->sa_family == AF_INET6) {949return ntohs(((struct sockaddr_in6*)him)->sin6_port);950951} else952#endif /* AF_INET6 */953{954return ntohs(((struct sockaddr_in*)him)->sin_port);955}956}957958int959NET_IsIPv4Mapped(jbyte* caddr) {960int i;961for (i = 0; i < 10; i++) {962if (caddr[i] != 0x00) {963return 0; /* false */964}965}966967if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {968return 1; /* true */969}970return 0; /* false */971}972973int974NET_IPv4MappedToIPv4(jbyte* caddr) {975return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)976| (caddr[15] & 0xff);977}978979int980NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {981int i;982for (i = 0; i < 16; i++) {983if (caddr1[i] != caddr2[i]) {984return 0; /* false */985}986}987return 1;988}989990int NET_IsZeroAddr(jbyte* caddr) {991int i;992for (i = 0; i < 16; i++) {993if (caddr[i] != 0) {994return 0;995}996}997return 1;998}9991000/*1001* Map the Java level socket option to the platform specific1002* level and option name.1003*/1004int1005NET_MapSocketOption(jint cmd, int *level, int *optname) {1006static struct {1007jint cmd;1008int level;1009int optname;1010} const opts[] = {1011{ java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY },1012{ java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE },1013{ java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER },1014{ java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },1015{ java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },1016{ java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE },1017{ java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR },1018{ java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST },1019{ java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS },1020{ java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },1021{ java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF },1022{ java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },1023};10241025int i;10261027#ifdef AF_INET61028if (ipv6_available()) {1029switch (cmd) {1030// Different multicast options if IPv6 is enabled1031case java_net_SocketOptions_IP_MULTICAST_IF:1032case java_net_SocketOptions_IP_MULTICAST_IF2:1033*level = IPPROTO_IPV6;1034*optname = IPV6_MULTICAST_IF;1035return 0;10361037case java_net_SocketOptions_IP_MULTICAST_LOOP:1038*level = IPPROTO_IPV6;1039*optname = IPV6_MULTICAST_LOOP;1040return 0;1041#if (defined(__solaris__) || defined(MACOSX))1042// Map IP_TOS request to IPV6_TCLASS1043case java_net_SocketOptions_IP_TOS:1044*level = IPPROTO_IPV6;1045*optname = IPV6_TCLASS;1046return 0;1047#endif1048}1049}1050#endif10511052/*1053* Map the Java level option to the native level1054*/1055for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {1056if (cmd == opts[i].cmd) {1057*level = opts[i].level;1058*optname = opts[i].optname;1059return 0;1060}1061}10621063/* not found */1064return -1;1065}10661067/*1068* Determine the default interface for an IPv6 address.1069*1070* 1. Scans /proc/net/ipv6_route for a matching route1071* (eg: fe80::/10 or a route for the specific address).1072* This will tell us the interface to use (eg: "eth0").1073*1074* 2. Lookup /proc/net/if_inet6 to map the interface1075* name to an interface index.1076*1077* Returns :-1078* -1 if error1079* 0 if no matching interface1080* >1 interface index to use for the link-local address.1081*/1082#if defined(__linux__) && defined(AF_INET6)1083int getDefaultIPv6Interface(struct in6_addr *target_addr) {1084FILE *f;1085char srcp[8][5];1086char hopp[8][5];1087int dest_plen, src_plen, use, refcnt, metric;1088unsigned long flags;1089char dest_str[40];1090struct in6_addr dest_addr;1091char device[16];1092jboolean match = JNI_FALSE;10931094/*1095* Scan /proc/net/ipv6_route looking for a matching1096* route.1097*/1098if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {1099return -1;1100}1101while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "1102"%4s%4s%4s%4s%4s%4s%4s%4s %02x "1103"%4s%4s%4s%4s%4s%4s%4s%4s "1104"%08x %08x %08x %08lx %8s",1105dest_str, &dest_str[5], &dest_str[10], &dest_str[15],1106&dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],1107&dest_plen,1108srcp[0], srcp[1], srcp[2], srcp[3],1109srcp[4], srcp[5], srcp[6], srcp[7],1110&src_plen,1111hopp[0], hopp[1], hopp[2], hopp[3],1112hopp[4], hopp[5], hopp[6], hopp[7],1113&metric, &use, &refcnt, &flags, device) == 31) {11141115/*1116* Some routes should be ignored1117*/1118if ( (dest_plen < 0 || dest_plen > 128) ||1119(src_plen != 0) ||1120#ifndef __ANDROID__1121(flags & (RTF_POLICY | RTF_FLOW)) ||1122#endif1123((flags & RTF_REJECT) && dest_plen == 0) ) {1124continue;1125}11261127/*1128* Convert the destination address1129*/1130dest_str[4] = ':';1131dest_str[9] = ':';1132dest_str[14] = ':';1133dest_str[19] = ':';1134dest_str[24] = ':';1135dest_str[29] = ':';1136dest_str[34] = ':';1137dest_str[39] = '\0';11381139if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {1140/* not an Ipv6 address */1141continue;1142} else {1143/*1144* The prefix len (dest_plen) indicates the number of bits we1145* need to match on.1146*1147* dest_plen / 8 => number of bytes to match1148* dest_plen % 8 => number of additional bits to match1149*1150* eg: fe80::/10 => match 1 byte + 2 additional bits in the1151* the next byte.1152*/1153int byte_count = dest_plen >> 3;1154int extra_bits = dest_plen & 0x3;11551156if (byte_count > 0) {1157if (memcmp(target_addr, &dest_addr, byte_count)) {1158continue; /* no match */1159}1160}11611162if (extra_bits > 0) {1163unsigned char c1 = ((unsigned char *)target_addr)[byte_count];1164unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];1165unsigned char mask = 0xff << (8 - extra_bits);1166if ((c1 & mask) != (c2 & mask)) {1167continue;1168}1169}11701171/*1172* We have a match1173*/1174match = JNI_TRUE;1175break;1176}1177}1178fclose(f);11791180/*1181* If there's a match then we lookup the interface1182* index.1183*/1184if (match) {1185char devname[21];1186char addr6p[8][5];1187int plen, scope, dad_status, if_idx;11881189if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {1190while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",1191addr6p[0], addr6p[1], addr6p[2], addr6p[3],1192addr6p[4], addr6p[5], addr6p[6], addr6p[7],1193&if_idx, &plen, &scope, &dad_status, devname) == 13) {11941195if (strcmp(devname, device) == 0) {1196/*1197* Found - so just return the index1198*/1199fclose(f);1200return if_idx;1201}1202}1203fclose(f);1204} else {1205/*1206* Couldn't open /proc/net/if_inet61207*/1208return -1;1209}1210}12111212/*1213* If we get here it means we didn't there wasn't any1214* route or we couldn't get the index of the interface.1215*/1216return 0;1217}1218#endif121912201221/*1222* Wrapper for getsockopt system routine - does any necessary1223* pre/post processing to deal with OS specific oddities :-1224*1225* On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed1226* to compensate for an incorrect value returned by the kernel.1227*/1228int1229NET_GetSockOpt(int fd, int level, int opt, void *result,1230int *len)1231{1232int rv;1233socklen_t socklen = *len;12341235rv = getsockopt(fd, level, opt, result, &socklen);1236*len = socklen;12371238if (rv < 0) {1239return rv;1240}12411242#ifdef __linux__1243/*1244* On Linux SO_SNDBUF/SO_RCVBUF aren't symmetric. This1245* stems from additional socket structures in the send1246* and receive buffers.1247*/1248if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF)1249|| (opt == SO_RCVBUF))) {1250int n = *((int *)result);1251n /= 2;1252*((int *)result) = n;1253}1254#endif12551256/* Workaround for Mac OS treating linger value as1257* signed integer1258*/1259#ifdef MACOSX1260if (level == SOL_SOCKET && opt == SO_LINGER) {1261struct linger* to_cast = (struct linger*)result;1262to_cast->l_linger = (unsigned short)to_cast->l_linger;1263}1264#endif1265return rv;1266}12671268/*1269* Wrapper for setsockopt system routine - performs any1270* necessary pre/post processing to deal with OS specific1271* issue :-1272*1273* On Solaris need to limit the suggested value for SO_SNDBUF1274* and SO_RCVBUF to the kernel configured limit1275*1276* For IP_TOS socket option need to mask off bits as this1277* aren't automatically masked by the kernel and results in1278* an error.1279*/1280int1281NET_SetSockOpt(int fd, int level, int opt, const void *arg,1282int len)1283{12841285#ifndef IPTOS_TOS_MASK1286#define IPTOS_TOS_MASK 0x1e1287#endif1288#ifndef IPTOS_PREC_MASK1289#define IPTOS_PREC_MASK 0xe01290#endif12911292#if defined(_ALLBSD_SOURCE)1293#if defined(KIPC_MAXSOCKBUF)1294int mib[3];1295size_t rlen;1296#endif12971298int *bufsize;12991300#ifdef __APPLE__1301static int maxsockbuf = -1;1302#else1303static long maxsockbuf = -1;1304#endif1305#endif13061307/*1308* IPPROTO/IP_TOS :-1309* 1. IPv6 on Solaris/Mac OS:1310* Set the TOS OR Traffic Class value to cater for1311* IPv6 and IPv4 scenarios.1312* 2. IPv6 on Linux: By default Linux ignores flowinfo1313* field so enable IPV6_FLOWINFO_SEND so that flowinfo1314* will be examined. We also set the IPv4 TOS option in this case.1315* 3. IPv4: set socket option based on ToS and Precedence1316* fields (otherwise get invalid argument)1317*/1318if (level == IPPROTO_IP && opt == IP_TOS) {1319int *iptos;13201321#if defined(AF_INET6) && defined(__linux__)1322if (ipv6_available()) {1323int optval = 1;1324if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,1325(void *)&optval, sizeof(optval)) < 0) {1326return -1;1327}1328/*1329* Let's also set the IPV6_TCLASS flag.1330* Linux appears to allow both IP_TOS and IPV6_TCLASS to be set1331* This helps in mixed environments where IPv4 and IPv6 sockets1332* are connecting.1333*/1334if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,1335arg, len) < 0) {1336return -1;1337}1338}1339#endif13401341iptos = (int *)arg;1342*iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);1343}13441345/*1346* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp1347* the value when it exceeds the system limit.1348*/1349#ifdef __solaris__1350if (level == SOL_SOCKET) {1351if (opt == SO_SNDBUF || opt == SO_RCVBUF) {1352int sotype=0, arglen;1353int *bufsize, maxbuf;1354int ret;13551356/* Attempt with the original size */1357ret = setsockopt(fd, level, opt, arg, len);1358if ((ret == 0) || (ret == -1 && errno != ENOBUFS))1359return ret;13601361/* Exceeded system limit so clamp and retry */13621363arglen = sizeof(sotype);1364if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,1365&arglen) < 0) {1366return -1;1367}13681369/*1370* We try to get tcp_maxbuf (and udp_max_buf) using1371* an ioctl() that isn't available on all versions of Solaris.1372* If that fails, we use the search algorithm in findMaxBuf()1373*/1374if (!init_tcp_max_buf && sotype == SOCK_STREAM) {1375tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");1376if (tcp_max_buf == -1) {1377tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);1378if (tcp_max_buf == -1) {1379return -1;1380}1381}1382init_tcp_max_buf = 1;1383} else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {1384udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");1385if (udp_max_buf == -1) {1386udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);1387if (udp_max_buf == -1) {1388return -1;1389}1390}1391init_udp_max_buf = 1;1392}13931394maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;1395bufsize = (int *)arg;1396if (*bufsize > maxbuf) {1397*bufsize = maxbuf;1398}1399}1400}1401#endif14021403#ifdef _AIX1404if (level == SOL_SOCKET) {1405if (opt == SO_SNDBUF || opt == SO_RCVBUF) {1406/*1407* Just try to set the requested size. If it fails we will leave the1408* socket option as is. Setting the buffer size means only a hint in1409* the jse2/java software layer, see javadoc. In the previous1410* solution the buffer has always been truncated to a length of1411* 0x100000 Byte, even if the technical limit has not been reached.1412* This kind of absolute truncation was unexpected in the jck tests.1413*/1414int ret = setsockopt(fd, level, opt, arg, len);1415if ((ret == 0) || (ret == -1 && errno == ENOBUFS)) {1416// Accept failure because of insufficient buffer memory resources.1417return 0;1418} else {1419// Deliver all other kinds of errors.1420return ret;1421}1422}1423}1424#endif14251426/*1427* On Linux the receive buffer is used for both socket1428* structures and the the packet payload. The implication1429* is that if SO_RCVBUF is too small then small packets1430* must be discarded.1431*/1432#ifdef __linux__1433if (level == SOL_SOCKET && opt == SO_RCVBUF) {1434int *bufsize = (int *)arg;1435if (*bufsize < 1024) {1436*bufsize = 1024;1437}1438}1439#endif14401441#if defined(_ALLBSD_SOURCE)1442/*1443* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to1444* ensure that value is <= kern.ipc.maxsockbuf as otherwise we get1445* an ENOBUFS error.1446*/1447if (level == SOL_SOCKET) {1448if (opt == SO_SNDBUF || opt == SO_RCVBUF) {1449#ifdef KIPC_MAXSOCKBUF1450if (maxsockbuf == -1) {1451mib[0] = CTL_KERN;1452mib[1] = KERN_IPC;1453mib[2] = KIPC_MAXSOCKBUF;1454rlen = sizeof(maxsockbuf);1455if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1)1456maxsockbuf = 1024;14571458#if 11459/* XXXBSD: This is a hack to workaround mb_max/mb_max_adj1460problem. It should be removed when kern.ipc.maxsockbuf1461will be real value. */1462maxsockbuf = (maxsockbuf/5)*4;1463#endif1464}1465#elif defined(__OpenBSD__)1466maxsockbuf = SB_MAX;1467#else1468maxsockbuf = 64 * 1024; /* XXX: NetBSD */1469#endif14701471bufsize = (int *)arg;1472if (*bufsize > maxsockbuf) {1473*bufsize = maxsockbuf;1474}14751476if (opt == SO_RCVBUF && *bufsize < 1024) {1477*bufsize = 1024;1478}14791480}1481}1482#endif14831484#if defined(_ALLBSD_SOURCE) || defined(_AIX)1485/*1486* On Solaris, SO_REUSEADDR will allow multiple datagram1487* sockets to bind to the same port. The network jck tests check1488* for this "feature", so we need to emulate it by turning on1489* SO_REUSEPORT as well for that combination.1490*/1491if (level == SOL_SOCKET && opt == SO_REUSEADDR) {1492int sotype;1493socklen_t arglen;14941495arglen = sizeof(sotype);1496if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {1497return -1;1498}14991500if (sotype == SOCK_DGRAM) {1501setsockopt(fd, level, SO_REUSEPORT, arg, len);1502}1503}1504#endif15051506return setsockopt(fd, level, opt, arg, len);1507}15081509/*1510* Wrapper for bind system call - performs any necessary pre/post1511* processing to deal with OS specific issues :-1512*1513* Linux allows a socket to bind to 127.0.0.255 which must be1514* caught.1515*1516* On Solaris with IPv6 enabled we must use an exclusive1517* bind to guarantee a unique port number across the IPv4 and1518* IPv6 port spaces.1519*1520*/1521int1522NET_Bind(int fd, struct sockaddr *him, int len)1523{1524#if defined(__solaris__) && defined(AF_INET6)1525int level = -1;1526int exclbind = -1;1527#endif1528int rv;1529int arg, alen;15301531#ifdef __linux__1532/*1533* ## get bugId for this issue - goes back to 1.2.2 port ##1534* ## When IPv6 is enabled this will be an IPv4-mapped1535* ## with family set to AF_INET61536*/1537if (him->sa_family == AF_INET) {1538struct sockaddr_in *sa = (struct sockaddr_in *)him;1539if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {1540errno = EADDRNOTAVAIL;1541return -1;1542}1543}1544#endif15451546#if defined(__solaris__)1547/*1548* Solaris has separate IPv4 and IPv6 port spaces so we1549* use an exclusive bind when SO_REUSEADDR is not used to1550* give the illusion of a unified port space.1551* This also avoids problems with IPv6 sockets connecting1552* to IPv4 mapped addresses whereby the socket conversion1553* results in a late bind that fails because the1554* corresponding IPv4 port is in use.1555*/1556alen = sizeof(arg);1557if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,1558(char *)&arg, &alen) == 0) {1559if (useExclBind || arg == 0) {1560/*1561* SO_REUSEADDR is disabled or sun.net.useExclusiveBind1562* property is true so enable TCP_EXCLBIND or1563* UDP_EXCLBIND1564*/1565alen = sizeof(arg);1566if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,1567&alen) == 0) {1568if (arg == SOCK_STREAM) {1569level = IPPROTO_TCP;1570exclbind = TCP_EXCLBIND;1571} else {1572level = IPPROTO_UDP;1573exclbind = UDP_EXCLBIND;1574}1575}15761577arg = 1;1578setsockopt(fd, level, exclbind, (char *)&arg,1579sizeof(arg));1580}1581}15821583#endif15841585rv = bind(fd, him, len);15861587#if defined(__solaris__) && defined(AF_INET6)1588if (rv < 0) {1589int en = errno;1590/* Restore *_EXCLBIND if the bind fails */1591if (exclbind != -1) {1592int arg = 0;1593setsockopt(fd, level, exclbind, (char *)&arg,1594sizeof(arg));1595}1596errno = en;1597}1598#endif15991600return rv;1601}16021603/**1604* Wrapper for select/poll with timeout on a single file descriptor.1605*1606* flags (defined in net_util_md.h can be any combination of1607* NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.1608*1609* The function will return when either the socket is ready for one1610* of the specified operations or the timeout expired.1611*1612* It returns the time left from the timeout (possibly 0), or -1 if it expired.1613*/16141615jint1616NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)1617{1618jlong prevTime = JVM_CurrentTimeMillis(env, 0);1619jint read_rv;16201621while (1) {1622jlong newTime;1623#ifndef USE_SELECT1624{1625struct pollfd pfd;1626pfd.fd = fd;1627pfd.events = 0;1628if (flags & NET_WAIT_READ)1629pfd.events |= POLLIN;1630if (flags & NET_WAIT_WRITE)1631pfd.events |= POLLOUT;1632if (flags & NET_WAIT_CONNECT)1633pfd.events |= POLLOUT;16341635errno = 0;1636read_rv = NET_Poll(&pfd, 1, timeout);1637}1638#else1639{1640fd_set rd, wr, ex;1641struct timeval t;16421643t.tv_sec = timeout / 1000;1644t.tv_usec = (timeout % 1000) * 1000;16451646FD_ZERO(&rd);1647FD_ZERO(&wr);1648FD_ZERO(&ex);1649if (flags & NET_WAIT_READ) {1650FD_SET(fd, &rd);1651}1652if (flags & NET_WAIT_WRITE) {1653FD_SET(fd, &wr);1654}1655if (flags & NET_WAIT_CONNECT) {1656FD_SET(fd, &wr);1657FD_SET(fd, &ex);1658}16591660errno = 0;1661read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);1662}1663#endif16641665newTime = JVM_CurrentTimeMillis(env, 0);1666timeout -= (newTime - prevTime);1667if (timeout <= 0) {1668return read_rv > 0 ? 0 : -1;1669}1670prevTime = newTime;16711672if (read_rv > 0) {1673break;1674}167516761677} /* while */16781679return timeout;1680}16811682#if !defined(__solaris__)1683long NET_GetCurrentTime() {1684struct timeval time;1685gettimeofday(&time, NULL);1686return (time.tv_sec * 1000 + time.tv_usec / 1000);1687}16881689int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime) {1690return NET_Timeout0(s, timeout, currentTime);1691}16921693int NET_Timeout(int s, long timeout) {1694long currentTime = (timeout > 0) ? NET_GetCurrentTime() : 0;1695return NET_Timeout0(s, timeout, currentTime);1696}1697#endif169816991700