< prev index next >

src/java.base/unix/native/libnet/net_util_md.c

Print this page
rev 59105 : imported patch corelibs


  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 #include <dlfcn.h>
  26 #include <errno.h>
  27 #include <net/if.h>
  28 #include <netinet/tcp.h> // defines TCP_NODELAY
  29 #include <stdlib.h>
  30 #include <string.h>
  31 #include <sys/ioctl.h>
  32 #include <sys/time.h>
  33 
  34 #if defined(__linux__)
  35 #include <arpa/inet.h>
  36 #include <net/route.h>
  37 #include <sys/utsname.h>
  38 #endif
  39 
  40 #if defined(__solaris__)
  41 #include <inet/nd.h>
  42 #include <limits.h>
  43 #include <stropts.h>
  44 #include <sys/filio.h>
  45 #include <sys/sockio.h>
  46 #endif
  47 
  48 #if defined(MACOSX)
  49 #include <sys/sysctl.h>
  50 #endif
  51 
  52 #include "jvm.h"
  53 #include "net_util.h"
  54 
  55 #include "java_net_SocketOptions.h"
  56 #include "java_net_InetAddress.h"
  57 
  58 #if defined(__linux__) && !defined(IPV6_FLOWINFO_SEND)
  59 #define IPV6_FLOWINFO_SEND      33
  60 #endif
  61 
  62 #if defined(__solaris__) && !defined(MAXINT)
  63 #define MAXINT INT_MAX
  64 #endif
  65 
  66 /*
  67  * EXCLBIND socket options only on Solaris
  68  */
  69 #if defined(__solaris__) && !defined(TCP_EXCLBIND)
  70 #define TCP_EXCLBIND            0x21
  71 #endif
  72 #if defined(__solaris__) && !defined(UDP_EXCLBIND)
  73 #define UDP_EXCLBIND            0x0101
  74 #endif
  75 
  76 #define RESTARTABLE(_cmd, _result) do { \
  77     do { \
  78         _result = _cmd; \
  79     } while((_result == -1) && (errno == EINTR)); \
  80 } while(0)
  81 
  82 int NET_SocketAvailable(int s, int *pbytes) {
  83     int result;
  84     RESTARTABLE(ioctl(s, FIONREAD, pbytes), result);
  85     return result;
  86 }
  87 
  88 #ifdef __solaris__
  89 static int init_tcp_max_buf, init_udp_max_buf;
  90 static int tcp_max_buf;
  91 static int udp_max_buf;
  92 static int useExclBind = 0;
  93 
  94 /*
  95  * Get the specified parameter from the specified driver. The value
  96  * of the parameter is assumed to be an 'int'. If the parameter
  97  * cannot be obtained return -1
  98  */
  99 int net_getParam(char *driver, char *param)
 100 {
 101     struct strioctl stri;
 102     char buf [64];
 103     int s;
 104     int value;
 105 
 106     s = open (driver, O_RDWR);
 107     if (s < 0) {
 108         return -1;
 109     }
 110     strncpy (buf, param, sizeof(buf));
 111     stri.ic_cmd = ND_GET;
 112     stri.ic_timout = 0;
 113     stri.ic_dp = buf;
 114     stri.ic_len = sizeof(buf);
 115     if (ioctl (s, I_STR, &stri) < 0) {
 116         value = -1;
 117     } else {
 118         value = atoi(buf);
 119     }
 120     close (s);
 121     return value;
 122 }
 123 
 124 /*
 125  * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
 126  * for Solaris versions that do not support the ioctl() in net_getParam().
 127  * Ugly, but only called once (for each sotype).
 128  *
 129  * As an optimization, we make a guess using the default values for Solaris
 130  * assuming they haven't been modified with ndd.
 131  */
 132 
 133 #define MAX_TCP_GUESS 1024 * 1024
 134 #define MAX_UDP_GUESS 2 * 1024 * 1024
 135 
 136 #define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
 137 
 138 static int findMaxBuf(int fd, int opt, int sotype) {
 139     int a = 0;
 140     int b = MAXINT;
 141     int initial_guess;
 142     int limit = -1;
 143 
 144     if (sotype == SOCK_DGRAM) {
 145         initial_guess = MAX_UDP_GUESS;
 146     } else {
 147         initial_guess = MAX_TCP_GUESS;
 148     }
 149 
 150     if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
 151         initial_guess++;
 152         if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
 153             FAIL_IF_NOT_ENOBUFS;
 154             return initial_guess - 1;
 155         }
 156         a = initial_guess;
 157     } else {
 158         FAIL_IF_NOT_ENOBUFS;
 159         b = initial_guess - 1;
 160     }
 161     do {
 162         int mid = a + (b-a)/2;
 163         if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
 164             limit = mid;
 165             a = mid + 1;
 166         } else {
 167             FAIL_IF_NOT_ENOBUFS;
 168             b = mid - 1;
 169         }
 170     } while (b >= a);
 171 
 172     return limit;
 173 }
 174 #endif
 175 
 176 void
 177 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
 178                    const char *defaultDetail) {
 179     JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);
 180 }
 181 
 182 void
 183 NET_ThrowCurrent(JNIEnv *env, char *msg) {
 184     NET_ThrowNew(env, errno, msg);
 185 }
 186 
 187 void
 188 NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
 189     char fullMsg[512];
 190     if (!msg) {
 191         msg = "no further information";
 192     }
 193     switch(errorNumber) {
 194     case EBADF:
 195         jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);


 266      */
 267 #ifdef __linux__
 268     {
 269         FILE *fP = fopen("/proc/net/if_inet6", "r");
 270         char buf[255];
 271         char *bufP;
 272 
 273         if (fP == NULL) {
 274             close(fd);
 275             return JNI_FALSE;
 276         }
 277         bufP = fgets(buf, sizeof(buf), fP);
 278         fclose(fP);
 279         if (bufP == NULL) {
 280             close(fd);
 281             return JNI_FALSE;
 282         }
 283     }
 284 #endif
 285 
 286     /**
 287      * On Solaris 8 it's possible to create INET6 sockets even
 288      * though IPv6 is not enabled on all interfaces. Thus we
 289      * query the number of IPv6 addresses to verify that IPv6
 290      * has been configured on at least one interface.
 291      *
 292      * On Linux it doesn't matter - if IPv6 is built-in the
 293      * kernel then IPv6 addresses will be bound automatically
 294      * to all interfaces.
 295      */
 296 #ifdef __solaris__
 297 
 298 #ifdef SIOCGLIFNUM
 299     {
 300         struct lifnum numifs;
 301 
 302         numifs.lifn_family = AF_INET6;
 303         numifs.lifn_flags = 0;
 304         if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
 305             /**
 306              * SIOCGLIFNUM failed - assume IPv6 not configured
 307              */
 308             close(fd);
 309             return JNI_FALSE;
 310         }
 311         /**
 312          * If no IPv6 addresses then return false. If count > 0
 313          * it's possible that all IPv6 addresses are "down" but
 314          * that's okay as they may be brought "up" while the
 315          * VM is running.
 316          */
 317         if (numifs.lifn_count == 0) {
 318             close(fd);
 319             return JNI_FALSE;
 320         }
 321     }
 322 #else
 323     /* SIOCGLIFNUM not defined in build environment ??? */
 324     close(fd);
 325     return JNI_FALSE;
 326 #endif
 327 
 328 #endif /* __solaris */
 329 
 330     /*
 331      *  OK we may have the stack available in the kernel,
 332      *  we should also check if the APIs are available.
 333      */
 334     ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
 335     close(fd);
 336     if (ipv6_fn == NULL ) {
 337         return JNI_FALSE;
 338     } else {
 339         return JNI_TRUE;
 340     }
 341 }
 342 #endif /* DONT_ENABLE_IPV6 */
 343 
 344 jint reuseport_supported()
 345 {
 346     /* Do a simple dummy call, and try to figure out from that */
 347     int one = 1;
 348     int rv, s;
 349     s = socket(PF_INET, SOCK_STREAM, 0);


 386         }
 387         free(buf);
 388     }
 389 }
 390 
 391 #if defined(_AIX)
 392 
 393 /* Initialize stubs for blocking I/O workarounds (see src/solaris/native/java/net/linux_close.c) */
 394 extern void aix_close_init();
 395 
 396 void platformInit () {
 397     aix_close_init();
 398 }
 399 
 400 #else
 401 
 402 void platformInit () {}
 403 
 404 #endif
 405 
 406 void parseExclusiveBindProperty(JNIEnv *env) {
 407 #ifdef __solaris__
 408     jstring s, flagSet;
 409     jclass iCls;
 410     jmethodID mid;
 411 
 412     s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
 413     CHECK_NULL(s);
 414     iCls = (*env)->FindClass(env, "java/lang/System");
 415     CHECK_NULL(iCls);
 416     mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
 417                 "(Ljava/lang/String;)Ljava/lang/String;");
 418     CHECK_NULL(mid);
 419     flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
 420     if (flagSet != NULL) {
 421         useExclBind = 1;
 422     }
 423 #endif
 424 }
 425 
 426 JNIEXPORT jint JNICALL
 427 NET_EnableFastTcpLoopback(int fd) {
 428     return 0;
 429 }
 430 
 431 /**
 432  * See net_util.h for documentation
 433  */
 434 JNIEXPORT int JNICALL
 435 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
 436                           SOCKETADDRESS *sa, int *len,
 437                           jboolean v4MappedAddress)
 438 {
 439     jint family = getInetAddress_family(env, iaObj);
 440     JNU_CHECK_EXCEPTION_RETURN(env, -1);
 441     memset((char *)sa, 0, sizeof(SOCKETADDRESS));
 442 
 443     if (ipv6_available() &&
 444         !(family == java_net_InetAddress_IPv4 &&
 445           v4MappedAddress == JNI_FALSE))


 571         { java_net_SocketOptions_IP_MULTICAST_IF,       IPPROTO_IP,     IP_MULTICAST_IF },
 572         { java_net_SocketOptions_IP_MULTICAST_IF2,      IPPROTO_IP,     IP_MULTICAST_IF },
 573         { java_net_SocketOptions_IP_MULTICAST_LOOP,     IPPROTO_IP,     IP_MULTICAST_LOOP },
 574     };
 575 
 576     int i;
 577 
 578     if (ipv6_available()) {
 579         switch (cmd) {
 580             // Different multicast options if IPv6 is enabled
 581             case java_net_SocketOptions_IP_MULTICAST_IF:
 582             case java_net_SocketOptions_IP_MULTICAST_IF2:
 583                 *level = IPPROTO_IPV6;
 584                 *optname = IPV6_MULTICAST_IF;
 585                 return 0;
 586 
 587             case java_net_SocketOptions_IP_MULTICAST_LOOP:
 588                 *level = IPPROTO_IPV6;
 589                 *optname = IPV6_MULTICAST_LOOP;
 590                 return 0;
 591 #if (defined(__solaris__) || defined(MACOSX))
 592             // Map IP_TOS request to IPV6_TCLASS
 593             case java_net_SocketOptions_IP_TOS:
 594                 *level = IPPROTO_IPV6;
 595                 *optname = IPV6_TCLASS;
 596                 return 0;
 597 #endif
 598         }
 599     }
 600 
 601     /*
 602      * Map the Java level option to the native level
 603      */
 604     for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
 605         if (cmd == opts[i].cmd) {
 606             *level = opts[i].level;
 607             *optname = opts[i].optname;
 608             return 0;
 609         }
 610     }
 611 


 720                            (void *)&optval, sizeof(optval)) < 0) {
 721                 return -1;
 722             }
 723            /*
 724             * Let's also set the IPV6_TCLASS flag.
 725             * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set
 726             * This helps in mixed environments where IPv4 and IPv6 sockets
 727             * are connecting.
 728             */
 729            if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
 730                            arg, len) < 0) {
 731                 return -1;
 732             }
 733         }
 734 #endif
 735 
 736         iptos = (int *)arg;
 737         *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
 738     }
 739 
 740     /*
 741      * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
 742      * the value when it exceeds the system limit.
 743      */
 744 #ifdef __solaris__
 745     if (level == SOL_SOCKET) {
 746         if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
 747             int sotype=0;
 748             socklen_t arglen;
 749             int *bufsize, maxbuf;
 750             int ret;
 751 
 752             /* Attempt with the original size */
 753             ret = setsockopt(fd, level, opt, arg, len);
 754             if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
 755                 return ret;
 756 
 757             /* Exceeded system limit so clamp and retry */
 758 
 759             arglen = sizeof(sotype);
 760             if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
 761                            &arglen) < 0) {
 762                 return -1;
 763             }
 764 
 765             /*
 766              * We try to get tcp_maxbuf (and udp_max_buf) using
 767              * an ioctl() that isn't available on all versions of Solaris.
 768              * If that fails, we use the search algorithm in findMaxBuf()
 769              */
 770             if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
 771                 tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");
 772                 if (tcp_max_buf == -1) {
 773                     tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
 774                     if (tcp_max_buf == -1) {
 775                         return -1;
 776                     }
 777                 }
 778                 init_tcp_max_buf = 1;
 779             } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
 780                 udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");
 781                 if (udp_max_buf == -1) {
 782                     udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
 783                     if (udp_max_buf == -1) {
 784                         return -1;
 785                     }
 786                 }
 787                 init_udp_max_buf = 1;
 788             }
 789 
 790             maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
 791             bufsize = (int *)arg;
 792             if (*bufsize > maxbuf) {
 793                 *bufsize = maxbuf;
 794             }
 795         }
 796     }
 797 #endif
 798 
 799 #ifdef _AIX
 800     if (level == SOL_SOCKET) {
 801         if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
 802             /*
 803              * Just try to set the requested size. If it fails we will leave the
 804              * socket option as is. Setting the buffer size means only a hint in
 805              * the jse2/java software layer, see javadoc. In the previous
 806              * solution the buffer has always been truncated to a length of
 807              * 0x100000 Byte, even if the technical limit has not been reached.
 808              * This kind of absolute truncation was unexpected in the jck tests.
 809              */
 810             int ret = setsockopt(fd, level, opt, arg, len);
 811             if ((ret == 0) || (ret == -1 && errno == ENOBUFS)) {
 812                 // Accept failure because of insufficient buffer memory resources.
 813                 return 0;
 814             } else {
 815                 // Deliver all other kinds of errors.
 816                 return ret;
 817             }
 818         }


 891         arglen = sizeof(sotype);
 892         if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
 893             return -1;
 894         }
 895 
 896         if (sotype == SOCK_DGRAM) {
 897             setsockopt(fd, level, SO_REUSEPORT, arg, len);
 898         }
 899     }
 900 #endif
 901 
 902     return setsockopt(fd, level, opt, arg, len);
 903 }
 904 
 905 /*
 906  * Wrapper for bind system call - performs any necessary pre/post
 907  * processing to deal with OS specific issues :-
 908  *
 909  * Linux allows a socket to bind to 127.0.0.255 which must be
 910  * caught.
 911  *
 912  * On Solaris with IPv6 enabled we must use an exclusive
 913  * bind to guarantee a unique port number across the IPv4 and
 914  * IPv6 port spaces.
 915  *
 916  */
 917 int
 918 NET_Bind(int fd, SOCKETADDRESS *sa, int len)
 919 {
 920 #if defined(__solaris__)
 921     int level = -1;
 922     int exclbind = -1;
 923 #endif
 924     int rv;
 925     int arg, alen;
 926 
 927 #ifdef __linux__
 928     /*
 929      * ## get bugId for this issue - goes back to 1.2.2 port ##
 930      * ## When IPv6 is enabled this will be an IPv4-mapped
 931      * ## with family set to AF_INET6
 932      */
 933     if (sa->sa.sa_family == AF_INET) {
 934         if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
 935             errno = EADDRNOTAVAIL;
 936             return -1;
 937         }
 938     }
 939 #endif
 940 
 941 #if defined(__solaris__)
 942     /*
 943      * Solaris has separate IPv4 and IPv6 port spaces so we
 944      * use an exclusive bind when SO_REUSEADDR is not used to
 945      * give the illusion of a unified port space.
 946      * This also avoids problems with IPv6 sockets connecting
 947      * to IPv4 mapped addresses whereby the socket conversion
 948      * results in a late bind that fails because the
 949      * corresponding IPv4 port is in use.
 950      */
 951     alen = sizeof(arg);
 952 
 953     if (useExclBind ||
 954         getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
 955     {
 956         if (useExclBind || arg == 0) {
 957             /*
 958              * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
 959              * property is true so enable TCP_EXCLBIND or
 960              * UDP_EXCLBIND
 961              */
 962             alen = sizeof(arg);
 963             if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
 964             {
 965                 if (arg == SOCK_STREAM) {
 966                     level = IPPROTO_TCP;
 967                     exclbind = TCP_EXCLBIND;
 968                 } else {
 969                     level = IPPROTO_UDP;
 970                     exclbind = UDP_EXCLBIND;
 971                 }
 972             }
 973 
 974             arg = 1;
 975             setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
 976         }
 977     }
 978 
 979 #endif
 980 
 981     rv = bind(fd, &sa->sa, len);
 982 
 983 #if defined(__solaris__)
 984     if (rv < 0) {
 985         int en = errno;
 986         /* Restore *_EXCLBIND if the bind fails */
 987         if (exclbind != -1) {
 988             int arg = 0;
 989             setsockopt(fd, level, exclbind, (char *)&arg,
 990                        sizeof(arg));
 991         }
 992         errno = en;
 993     }
 994 #endif
 995 
 996     return rv;
 997 }
 998 
 999 /**
1000  * Wrapper for poll with timeout on a single file descriptor.
1001  *
1002  * flags (defined in net_util_md.h can be any combination of
1003  * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
1004  *
1005  * The function will return when either the socket is ready for one
1006  * of the specified operations or the timeout expired.
1007  *
1008  * It returns the time left from the timeout (possibly 0), or -1 if it expired.
1009  */
1010 
1011 jint
1012 NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
1013 {
1014     jlong prevNanoTime = JVM_NanoTime(env, 0);




  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 #include <dlfcn.h>
  26 #include <errno.h>
  27 #include <net/if.h>
  28 #include <netinet/tcp.h> // defines TCP_NODELAY
  29 #include <stdlib.h>
  30 #include <string.h>
  31 #include <sys/ioctl.h>
  32 #include <sys/time.h>
  33 
  34 #if defined(__linux__)
  35 #include <arpa/inet.h>
  36 #include <net/route.h>
  37 #include <sys/utsname.h>
  38 #endif
  39 








  40 #if defined(MACOSX)
  41 #include <sys/sysctl.h>
  42 #endif
  43 
  44 #include "jvm.h"
  45 #include "net_util.h"
  46 
  47 #include "java_net_SocketOptions.h"
  48 #include "java_net_InetAddress.h"
  49 
  50 #if defined(__linux__) && !defined(IPV6_FLOWINFO_SEND)
  51 #define IPV6_FLOWINFO_SEND      33
  52 #endif
  53 














  54 #define RESTARTABLE(_cmd, _result) do { \
  55     do { \
  56         _result = _cmd; \
  57     } while((_result == -1) && (errno == EINTR)); \
  58 } while(0)
  59 
  60 int NET_SocketAvailable(int s, int *pbytes) {
  61     int result;
  62     RESTARTABLE(ioctl(s, FIONREAD, pbytes), result);
  63     return result;
  64 }
  65 
























































































  66 void
  67 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
  68                    const char *defaultDetail) {
  69     JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);
  70 }
  71 
  72 void
  73 NET_ThrowCurrent(JNIEnv *env, char *msg) {
  74     NET_ThrowNew(env, errno, msg);
  75 }
  76 
  77 void
  78 NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
  79     char fullMsg[512];
  80     if (!msg) {
  81         msg = "no further information";
  82     }
  83     switch(errorNumber) {
  84     case EBADF:
  85         jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);


 156      */
 157 #ifdef __linux__
 158     {
 159         FILE *fP = fopen("/proc/net/if_inet6", "r");
 160         char buf[255];
 161         char *bufP;
 162 
 163         if (fP == NULL) {
 164             close(fd);
 165             return JNI_FALSE;
 166         }
 167         bufP = fgets(buf, sizeof(buf), fP);
 168         fclose(fP);
 169         if (bufP == NULL) {
 170             close(fd);
 171             return JNI_FALSE;
 172         }
 173     }
 174 #endif
 175 












































 176     /*
 177      *  OK we may have the stack available in the kernel,
 178      *  we should also check if the APIs are available.
 179      */
 180     ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
 181     close(fd);
 182     if (ipv6_fn == NULL ) {
 183         return JNI_FALSE;
 184     } else {
 185         return JNI_TRUE;
 186     }
 187 }
 188 #endif /* DONT_ENABLE_IPV6 */
 189 
 190 jint reuseport_supported()
 191 {
 192     /* Do a simple dummy call, and try to figure out from that */
 193     int one = 1;
 194     int rv, s;
 195     s = socket(PF_INET, SOCK_STREAM, 0);


 232         }
 233         free(buf);
 234     }
 235 }
 236 
 237 #if defined(_AIX)
 238 
 239 /* Initialize stubs for blocking I/O workarounds (see src/solaris/native/java/net/linux_close.c) */
 240 extern void aix_close_init();
 241 
 242 void platformInit () {
 243     aix_close_init();
 244 }
 245 
 246 #else
 247 
 248 void platformInit () {}
 249 
 250 #endif
 251 




















 252 JNIEXPORT jint JNICALL
 253 NET_EnableFastTcpLoopback(int fd) {
 254     return 0;
 255 }
 256 
 257 /**
 258  * See net_util.h for documentation
 259  */
 260 JNIEXPORT int JNICALL
 261 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
 262                           SOCKETADDRESS *sa, int *len,
 263                           jboolean v4MappedAddress)
 264 {
 265     jint family = getInetAddress_family(env, iaObj);
 266     JNU_CHECK_EXCEPTION_RETURN(env, -1);
 267     memset((char *)sa, 0, sizeof(SOCKETADDRESS));
 268 
 269     if (ipv6_available() &&
 270         !(family == java_net_InetAddress_IPv4 &&
 271           v4MappedAddress == JNI_FALSE))


 397         { java_net_SocketOptions_IP_MULTICAST_IF,       IPPROTO_IP,     IP_MULTICAST_IF },
 398         { java_net_SocketOptions_IP_MULTICAST_IF2,      IPPROTO_IP,     IP_MULTICAST_IF },
 399         { java_net_SocketOptions_IP_MULTICAST_LOOP,     IPPROTO_IP,     IP_MULTICAST_LOOP },
 400     };
 401 
 402     int i;
 403 
 404     if (ipv6_available()) {
 405         switch (cmd) {
 406             // Different multicast options if IPv6 is enabled
 407             case java_net_SocketOptions_IP_MULTICAST_IF:
 408             case java_net_SocketOptions_IP_MULTICAST_IF2:
 409                 *level = IPPROTO_IPV6;
 410                 *optname = IPV6_MULTICAST_IF;
 411                 return 0;
 412 
 413             case java_net_SocketOptions_IP_MULTICAST_LOOP:
 414                 *level = IPPROTO_IPV6;
 415                 *optname = IPV6_MULTICAST_LOOP;
 416                 return 0;
 417 #if defined(MACOSX)
 418             // Map IP_TOS request to IPV6_TCLASS
 419             case java_net_SocketOptions_IP_TOS:
 420                 *level = IPPROTO_IPV6;
 421                 *optname = IPV6_TCLASS;
 422                 return 0;
 423 #endif
 424         }
 425     }
 426 
 427     /*
 428      * Map the Java level option to the native level
 429      */
 430     for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
 431         if (cmd == opts[i].cmd) {
 432             *level = opts[i].level;
 433             *optname = opts[i].optname;
 434             return 0;
 435         }
 436     }
 437 


 546                            (void *)&optval, sizeof(optval)) < 0) {
 547                 return -1;
 548             }
 549            /*
 550             * Let's also set the IPV6_TCLASS flag.
 551             * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set
 552             * This helps in mixed environments where IPv4 and IPv6 sockets
 553             * are connecting.
 554             */
 555            if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
 556                            arg, len) < 0) {
 557                 return -1;
 558             }
 559         }
 560 #endif
 561 
 562         iptos = (int *)arg;
 563         *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
 564     }
 565 



























































 566 #ifdef _AIX
 567     if (level == SOL_SOCKET) {
 568         if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
 569             /*
 570              * Just try to set the requested size. If it fails we will leave the
 571              * socket option as is. Setting the buffer size means only a hint in
 572              * the jse2/java software layer, see javadoc. In the previous
 573              * solution the buffer has always been truncated to a length of
 574              * 0x100000 Byte, even if the technical limit has not been reached.
 575              * This kind of absolute truncation was unexpected in the jck tests.
 576              */
 577             int ret = setsockopt(fd, level, opt, arg, len);
 578             if ((ret == 0) || (ret == -1 && errno == ENOBUFS)) {
 579                 // Accept failure because of insufficient buffer memory resources.
 580                 return 0;
 581             } else {
 582                 // Deliver all other kinds of errors.
 583                 return ret;
 584             }
 585         }


 658         arglen = sizeof(sotype);
 659         if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
 660             return -1;
 661         }
 662 
 663         if (sotype == SOCK_DGRAM) {
 664             setsockopt(fd, level, SO_REUSEPORT, arg, len);
 665         }
 666     }
 667 #endif
 668 
 669     return setsockopt(fd, level, opt, arg, len);
 670 }
 671 
 672 /*
 673  * Wrapper for bind system call - performs any necessary pre/post
 674  * processing to deal with OS specific issues :-
 675  *
 676  * Linux allows a socket to bind to 127.0.0.255 which must be
 677  * caught.





 678  */
 679 int
 680 NET_Bind(int fd, SOCKETADDRESS *sa, int len)
 681 {




 682     int rv;
 683     int arg, alen;
 684 
 685 #ifdef __linux__
 686     /*
 687      * ## get bugId for this issue - goes back to 1.2.2 port ##
 688      * ## When IPv6 is enabled this will be an IPv4-mapped
 689      * ## with family set to AF_INET6
 690      */
 691     if (sa->sa.sa_family == AF_INET) {
 692         if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
 693             errno = EADDRNOTAVAIL;
 694             return -1;
 695         }
 696     }
 697 #endif
 698 








































 699     rv = bind(fd, &sa->sa, len);













 700 
 701     return rv;
 702 }
 703 
 704 /**
 705  * Wrapper for poll with timeout on a single file descriptor.
 706  *
 707  * flags (defined in net_util_md.h can be any combination of
 708  * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
 709  *
 710  * The function will return when either the socket is ready for one
 711  * of the specified operations or the timeout expired.
 712  *
 713  * It returns the time left from the timeout (possibly 0), or -1 if it expired.
 714  */
 715 
 716 jint
 717 NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
 718 {
 719     jlong prevNanoTime = JVM_NanoTime(env, 0);


< prev index next >