< prev index next >

src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c

Print this page
rev 14890 : 8158023: SocketExceptions contain too little information sometimes
   1 /*
   2  * Copyright (c) 1997, 2015, 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


1696                 ni_class = (*env)->NewGlobalRef(env, c);
1697                 CHECK_NULL(ni_class);
1698             }
1699 
1700             value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value);
1701             if (value == NULL) {
1702                 if (!(*env)->ExceptionOccurred(env)) {
1703                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1704                          "bad argument for IP_MULTICAST_IF"
1705                          ": address not bound to any interface");
1706                 }
1707                 return;
1708             }
1709             opt = java_net_SocketOptions_IP_MULTICAST_IF2;
1710         } else {
1711             struct in_addr in;
1712 
1713             in.s_addr = htonl(getInetAddress_addr(env, value));
1714             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1715                                (const char*)&in, sizeof(in)) < 0) {
1716                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1717                                  "Error setting socket option");
1718             }
1719             return;
1720         }
1721     }
1722 
1723     if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
1724         /*
1725          * value is a NetworkInterface.
1726          * On IPv6 system get the index of the interface and use the
1727          * IPV6_MULTICAST_IF socket option
1728          * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF
1729          * option. For IPv6 both must be done.
1730          */
1731         if (ipv6_supported) {
1732             static jfieldID ni_indexID;
1733             struct in_addr in;
1734             int index;
1735 
1736             if (ni_indexID == NULL) {
1737                 jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
1738                 CHECK_NULL(c);
1739                 ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
1740                 CHECK_NULL(ni_indexID);
1741             }
1742             index = (*env)->GetIntField(env, value, ni_indexID);
1743 
1744             if ( isAdapterIpv6Enabled(env, index) != 0 ) {
1745                 if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1746                                (const char*)&index, sizeof(index)) < 0) {
1747                     if (errno == EINVAL && index > 0) {
1748                         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1749                             "IPV6_MULTICAST_IF failed (interface has IPv4 "
1750                             "address only?)");
1751                     } else {
1752                         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1753                                    "Error setting socket option");
1754                     }
1755                     return;
1756                 }
1757             }
1758             /* If there are any IPv4 addresses on this interface then
1759              * repeat the operation on the IPv4 fd */
1760 
1761             if (getInet4AddrFromIf (env, value, &in) < 0) {
1762                 return;
1763             }
1764             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1765                                (const char*)&in, sizeof(in)) < 0) {
1766                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1767                                  "Error setting socket option");
1768             }
1769             return;
1770         } else {
1771             struct in_addr in;
1772 
1773             if (getInet4AddrFromIf (env, value, &in) < 0) {
1774                 if ((*env)->ExceptionOccurred(env)) {
1775                     return;
1776                 }
1777                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1778                         "no InetAddress instances of requested type");
1779                 return;
1780             }
1781 
1782             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1783                                (const char*)&in, sizeof(in)) < 0) {
1784                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1785                                "Error setting socket option");
1786             }
1787             return;
1788         }
1789     }
1790 }
1791 
1792 /*
1793  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
1794  * Method:    socketNativeSetOption
1795  * Signature: (ILjava/lang/Object;)V
1796  */
1797 JNIEXPORT void JNICALL
1798 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption(JNIEnv *env,jobject this,
1799                                                       jint opt,jobject value) {
1800 
1801     int fd=-1, fd1=-1;
1802     int levelv4 = 0, levelv6 = 0, optnamev4 = 0, optnamev6 = 0, optlen = 0;
1803     union {
1804         int i;
1805         char c;


1915  * ipv4Mode == 0, the context is IPV6 processing
1916  *
1917  */
1918 static jobject getIPv4NetworkInterface (JNIEnv *env, jobject this, int fd, jint opt, int ipv4Mode) {
1919         static jclass inet4_class;
1920         static jmethodID inet4_ctrID;
1921 
1922         static jclass ni_class; static jmethodID ni_ctrID;
1923         static jfieldID ni_indexID;
1924         static jfieldID ni_addrsID;
1925 
1926         jobjectArray addrArray;
1927         jobject addr;
1928         jobject ni;
1929 
1930         struct in_addr in;
1931         struct in_addr *inP = &in;
1932         int len = sizeof(struct in_addr);
1933         if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1934                            (char *)inP, &len) < 0) {
1935             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1936                              "Error getting socket option");
1937             return NULL;
1938         }
1939 
1940         /*
1941          * Construct and populate an Inet4Address
1942          */
1943         if (inet4_class == NULL) {
1944             jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
1945             CHECK_NULL_RETURN(c, NULL);
1946             inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
1947             CHECK_NULL_RETURN(inet4_ctrID, NULL);
1948             inet4_class = (*env)->NewGlobalRef(env, c);
1949             CHECK_NULL_RETURN(inet4_class, NULL);
1950         }
1951         addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0);
1952         CHECK_NULL_RETURN(addr, NULL);
1953 
1954         setInetAddress_addr(env, addr, ntohl(in.s_addr));
1955 
1956         /*


2039     if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
2040         (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
2041 
2042         static jclass ni_class;
2043         static jmethodID ni_ctrID;
2044         static jfieldID ni_indexID;
2045         static jfieldID ni_addrsID;
2046         static jclass ia_class;
2047         static jmethodID ia_anyLocalAddressID;
2048 
2049         int index;
2050         int len = sizeof(index);
2051 
2052         jobjectArray addrArray;
2053         jobject addr;
2054         jobject ni;
2055 
2056         {
2057             if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
2058                                (char*)&index, &len) < 0) {
2059                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
2060                                "Error getting socket option");
2061                 return NULL;
2062             }
2063         }
2064 
2065         if (ni_class == NULL) {
2066             jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
2067             CHECK_NULL_RETURN(c, NULL);
2068             ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
2069             CHECK_NULL_RETURN(ni_ctrID, NULL);
2070             ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
2071             CHECK_NULL_RETURN(ni_indexID, NULL);
2072             ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
2073                                             "[Ljava/net/InetAddress;");
2074             CHECK_NULL_RETURN(ni_addrsID, NULL);
2075 
2076             ia_class = (*env)->FindClass(env, "java/net/InetAddress");
2077             CHECK_NULL_RETURN(ia_class, NULL);
2078             ia_class = (*env)->NewGlobalRef(env, ia_class);
2079             CHECK_NULL_RETURN(ia_class, NULL);
2080             ia_anyLocalAddressID = (*env)->GetStaticMethodID(env,


2271         return NULL;
2272     }
2273 
2274     /* find out local IP address */
2275 
2276     len = sizeof (struct sockaddr_in);
2277 
2278     /* family==-1 when socket is not connected */
2279     if ((family == IPv6) || (family == -1 && fd == -1)) {
2280         fd = fd1; /* must be IPv6 only */
2281         len = sizeof (struct SOCKADDR_IN6);
2282     }
2283 
2284     if (fd == -1) {
2285         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
2286                         "Socket closed");
2287         return NULL;
2288     }
2289 
2290     if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) {
2291         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
2292                        "Error getting socket name");
2293         return NULL;
2294     }
2295     iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
2296 
2297     return iaObj;
2298 }
2299 
2300 /*
2301  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
2302  * Method:    setTimeToLive
2303  * Signature: (I)V
2304  */
2305 JNIEXPORT void JNICALL
2306 Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobject this,
2307                                                     jint ttl) {
2308 
2309     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
2310     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
2311     int fd = -1, fd1 = -1;
2312     int ittl = (int)ttl;


   1 /*
   2  * Copyright (c) 1997, 2016, 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


1696                 ni_class = (*env)->NewGlobalRef(env, c);
1697                 CHECK_NULL(ni_class);
1698             }
1699 
1700             value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value);
1701             if (value == NULL) {
1702                 if (!(*env)->ExceptionOccurred(env)) {
1703                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1704                          "bad argument for IP_MULTICAST_IF"
1705                          ": address not bound to any interface");
1706                 }
1707                 return;
1708             }
1709             opt = java_net_SocketOptions_IP_MULTICAST_IF2;
1710         } else {
1711             struct in_addr in;
1712 
1713             in.s_addr = htonl(getInetAddress_addr(env, value));
1714             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1715                                (const char*)&in, sizeof(in)) < 0) {
1716                 JNU_ThrowByNameWithMessageAndLastError
1717                     (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
1718             }
1719             return;
1720         }
1721     }
1722 
1723     if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
1724         /*
1725          * value is a NetworkInterface.
1726          * On IPv6 system get the index of the interface and use the
1727          * IPV6_MULTICAST_IF socket option
1728          * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF
1729          * option. For IPv6 both must be done.
1730          */
1731         if (ipv6_supported) {
1732             static jfieldID ni_indexID;
1733             struct in_addr in;
1734             int index;
1735 
1736             if (ni_indexID == NULL) {
1737                 jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
1738                 CHECK_NULL(c);
1739                 ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
1740                 CHECK_NULL(ni_indexID);
1741             }
1742             index = (*env)->GetIntField(env, value, ni_indexID);
1743 
1744             if (isAdapterIpv6Enabled(env, index) != 0) {
1745                 if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1746                                (const char*)&index, sizeof(index)) < 0) {
1747                     if (errno == EINVAL && index > 0) {
1748                         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1749                             "IPV6_MULTICAST_IF failed (interface has IPv4 "
1750                             "address only?)");
1751                     } else {
1752                         JNU_ThrowByNameWithMessageAndLastError
1753                             (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
1754                     }
1755                     return;
1756                 }
1757             }
1758             /* If there are any IPv4 addresses on this interface then
1759              * repeat the operation on the IPv4 fd */
1760 
1761             if (getInet4AddrFromIf(env, value, &in) < 0) {
1762                 return;
1763             }
1764             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1765                                (const char*)&in, sizeof(in)) < 0) {
1766                 JNU_ThrowByNameWithMessageAndLastError
1767                     (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
1768             }
1769             return;
1770         } else {
1771             struct in_addr in;
1772 
1773             if (getInet4AddrFromIf (env, value, &in) < 0) {
1774                 if ((*env)->ExceptionOccurred(env)) {
1775                     return;
1776                 }
1777                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1778                         "no InetAddress instances of requested type");
1779                 return;
1780             }
1781 
1782             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1783                                (const char*)&in, sizeof(in)) < 0) {
1784                 JNU_ThrowByNameWithMessageAndLastError
1785                     (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
1786             }
1787             return;
1788         }
1789     }
1790 }
1791 
1792 /*
1793  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
1794  * Method:    socketNativeSetOption
1795  * Signature: (ILjava/lang/Object;)V
1796  */
1797 JNIEXPORT void JNICALL
1798 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption(JNIEnv *env,jobject this,
1799                                                       jint opt,jobject value) {
1800 
1801     int fd=-1, fd1=-1;
1802     int levelv4 = 0, levelv6 = 0, optnamev4 = 0, optnamev6 = 0, optlen = 0;
1803     union {
1804         int i;
1805         char c;


1915  * ipv4Mode == 0, the context is IPV6 processing
1916  *
1917  */
1918 static jobject getIPv4NetworkInterface (JNIEnv *env, jobject this, int fd, jint opt, int ipv4Mode) {
1919         static jclass inet4_class;
1920         static jmethodID inet4_ctrID;
1921 
1922         static jclass ni_class; static jmethodID ni_ctrID;
1923         static jfieldID ni_indexID;
1924         static jfieldID ni_addrsID;
1925 
1926         jobjectArray addrArray;
1927         jobject addr;
1928         jobject ni;
1929 
1930         struct in_addr in;
1931         struct in_addr *inP = &in;
1932         int len = sizeof(struct in_addr);
1933         if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1934                            (char *)inP, &len) < 0) {
1935             JNU_ThrowByNameWithMessageAndLastError
1936                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
1937             return NULL;
1938         }
1939 
1940         /*
1941          * Construct and populate an Inet4Address
1942          */
1943         if (inet4_class == NULL) {
1944             jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
1945             CHECK_NULL_RETURN(c, NULL);
1946             inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
1947             CHECK_NULL_RETURN(inet4_ctrID, NULL);
1948             inet4_class = (*env)->NewGlobalRef(env, c);
1949             CHECK_NULL_RETURN(inet4_class, NULL);
1950         }
1951         addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0);
1952         CHECK_NULL_RETURN(addr, NULL);
1953 
1954         setInetAddress_addr(env, addr, ntohl(in.s_addr));
1955 
1956         /*


2039     if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
2040         (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
2041 
2042         static jclass ni_class;
2043         static jmethodID ni_ctrID;
2044         static jfieldID ni_indexID;
2045         static jfieldID ni_addrsID;
2046         static jclass ia_class;
2047         static jmethodID ia_anyLocalAddressID;
2048 
2049         int index;
2050         int len = sizeof(index);
2051 
2052         jobjectArray addrArray;
2053         jobject addr;
2054         jobject ni;
2055 
2056         {
2057             if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
2058                                (char*)&index, &len) < 0) {
2059                 JNU_ThrowByNameWithMessageAndLastError
2060                     (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
2061                 return NULL;
2062             }
2063         }
2064 
2065         if (ni_class == NULL) {
2066             jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
2067             CHECK_NULL_RETURN(c, NULL);
2068             ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
2069             CHECK_NULL_RETURN(ni_ctrID, NULL);
2070             ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
2071             CHECK_NULL_RETURN(ni_indexID, NULL);
2072             ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
2073                                             "[Ljava/net/InetAddress;");
2074             CHECK_NULL_RETURN(ni_addrsID, NULL);
2075 
2076             ia_class = (*env)->FindClass(env, "java/net/InetAddress");
2077             CHECK_NULL_RETURN(ia_class, NULL);
2078             ia_class = (*env)->NewGlobalRef(env, ia_class);
2079             CHECK_NULL_RETURN(ia_class, NULL);
2080             ia_anyLocalAddressID = (*env)->GetStaticMethodID(env,


2271         return NULL;
2272     }
2273 
2274     /* find out local IP address */
2275 
2276     len = sizeof (struct sockaddr_in);
2277 
2278     /* family==-1 when socket is not connected */
2279     if ((family == IPv6) || (family == -1 && fd == -1)) {
2280         fd = fd1; /* must be IPv6 only */
2281         len = sizeof (struct SOCKADDR_IN6);
2282     }
2283 
2284     if (fd == -1) {
2285         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
2286                         "Socket closed");
2287         return NULL;
2288     }
2289 
2290     if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) {
2291         JNU_ThrowByNameWithMessageAndLastError
2292             (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
2293         return NULL;
2294     }
2295     iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
2296 
2297     return iaObj;
2298 }
2299 
2300 /*
2301  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
2302  * Method:    setTimeToLive
2303  * Signature: (I)V
2304  */
2305 JNIEXPORT void JNICALL
2306 Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobject this,
2307                                                     jint ttl) {
2308 
2309     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
2310     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
2311     int fd = -1, fd1 = -1;
2312     int ittl = (int)ttl;


< prev index next >