< prev index next >

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

Print this page
rev 14410 : 8156521: Minor fixes and cleanups in NetworkInterface.c
Reviewed-by: alanb, chegar, dsamersoff, msheppar
rev 14411 : 8148424: Support IPv6-only Unix environments
Reviewed-by: alanb, chegar


 764       tmp = createNetworkInterface(env, childP);
 765       if (tmp == NULL) {
 766          return NULL;
 767       }
 768       (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
 769       (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
 770       childP = childP->next;
 771     }
 772     (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
 773     (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
 774     (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
 775 
 776     // return the NetworkInterface
 777     return netifObj;
 778 }
 779 
 780 /*
 781  * Enumerates all interfaces
 782  */
 783 static netif *enumInterfaces(JNIEnv *env) {
 784     netif *ifs;
 785     int sock;
 786 
 787     // Enumerate IPv4 addresses
 788     sock = openSocket(env, AF_INET);
 789     if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 790         return NULL;
 791     }
 792 
 793     ifs = enumIPv4Interfaces(env, sock, NULL);

 794     close(sock);
 795 
 796     if (ifs == NULL && (*env)->ExceptionOccurred(env)) {

 797         return NULL;
 798     }

 799 
 800     // return partial list if an exception occurs in the middle of process ???
 801 
 802     // If IPv6 is available then enumerate IPv6 addresses.
 803 #ifdef AF_INET6
 804 
 805         // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
 806         // so we have to call ipv6_available()
 807         if (ipv6_available()) {
 808 
 809            sock = openSocket(env, AF_INET6);
 810            if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 811                freeif(ifs);
 812                return NULL;
 813            }
 814 

 815            ifs = enumIPv6Interfaces(env, sock, ifs);
 816            close(sock);
 817 
 818            if ((*env)->ExceptionOccurred(env)) {
 819               freeif(ifs);
 820               return NULL;
 821            }

 822 
 823        }
 824 #endif
 825 
 826     return ifs;
 827 }
 828 
 829 #define CHECKED_MALLOC3(_pointer, _type, _size) \
 830     do { \
 831         _pointer = (_type)malloc(_size); \
 832         if (_pointer == NULL) { \
 833             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
 834             return ifs; /* return untouched list */ \
 835         } \
 836     } while(0)
 837 
 838 
 839 /*
 840  * Frees an interface list (including any attached addresses)
 841  */


1012         if (addrP->brdcast != NULL) {
1013             tmpaddr->brdcast = (struct sockaddr *)
1014                 ((char *)tmpaddr + sizeof(netaddr) + addr_size);
1015             memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
1016         }
1017 
1018         tmpaddr->next = currif->addr;
1019         currif->addr = tmpaddr;
1020     }
1021 
1022     return ifs;
1023 }
1024 
1025 /*
1026  * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
1027  */
1028 static int openSocket(JNIEnv *env, int proto) {
1029     int sock;
1030 
1031     if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
1032         // If EPROTONOSUPPORT is returned it means we don't have
1033         // support for this proto so don't throw an exception.
1034         if (errno != EPROTONOSUPPORT) {
1035             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1036                                          "Socket creation failed");
1037         }
1038         return -1;
1039     }
1040 
1041     return sock;
1042 }
1043 
1044 
1045 /** Linux, AIX **/
1046 #if defined(__linux__) || defined(_AIX)
1047 
1048 #ifdef AF_INET6
1049 /*
1050  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1051  * if it falls return AF_INET6 socket.
1052  */
1053 // unused arg ifname and struct if2
1054 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1055     int sock;
1056     struct ifreq if2;
1057 
1058     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1059         if (errno == EPROTONOSUPPORT) {
1060             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1061                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1062                                              "IPV6 Socket creation failed");
1063                 return -1;
1064             }
1065         } else { // errno is not NOSUPPORT
1066             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1067                                          "IPV4 Socket creation failed");
1068             return -1;
1069         }
1070     }
1071 
1072     // Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or
1073     // IPv6 socket regardless of type of address of an interface.
1074     return sock;
1075 }
1076 
1077 #else
1078 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1079     return openSocket(env,AF_INET);


1463       *flags = if2.ifr_flags;
1464   }
1465   return 0;
1466 }
1467 
1468 #endif  /* defined(__linux__) || defined(_AIX) */
1469 
1470 /** Solaris **/
1471 #if defined(__solaris__)
1472 
1473 /*
1474  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1475  * if it falls return AF_INET6 socket.
1476  */
1477 #ifdef AF_INET6
1478 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1479     int sock, alreadyV6 = 0;
1480     struct lifreq if2;
1481 
1482     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1483         if (errno == EPROTONOSUPPORT) {
1484             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1485                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1486                                              "IPV6 Socket creation failed");
1487                 return -1;
1488             }
1489 
1490             alreadyV6=1;
1491         } else { // errno is not NOSUPPORT
1492             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1493                                          "IPV4 Socket creation failed");
1494             return -1;
1495         }
1496     }
1497 
1498 
1499     // Solaris requires that we have an IPv6 socket to query an  interface
1500     // without an IPv4 address - check it here. POSIX 1 require the kernel to
1501     // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
1502     // for a device having IPv6 only address but not all devices follow the
1503     // standard so fall back on any error. It's not an ecologically friendly


1836     return 0;
1837 }
1838 
1839 
1840 #endif  /* __solaris__ */
1841 
1842 
1843 /** BSD **/
1844 #ifdef _ALLBSD_SOURCE
1845 
1846 /*
1847  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1848  * if it falls return AF_INET6 socket.
1849  */
1850 #ifdef AF_INET6
1851 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1852     int sock;
1853     struct ifreq if2;
1854 
1855      if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1856          if (errno == EPROTONOSUPPORT) {
1857               if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1858                  NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1859                                               "IPV6 Socket creation failed");
1860                  return -1;
1861               }
1862          }
1863          else{ // errno is not NOSUPPORT
1864              NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1865                                           "IPV4 Socket creation failed");
1866              return -1;
1867          }
1868    }
1869 
1870    return sock;
1871 }
1872 
1873 #else
1874 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1875     return openSocket(env,AF_INET);
1876 }




 764       tmp = createNetworkInterface(env, childP);
 765       if (tmp == NULL) {
 766          return NULL;
 767       }
 768       (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
 769       (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
 770       childP = childP->next;
 771     }
 772     (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
 773     (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
 774     (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
 775 
 776     // return the NetworkInterface
 777     return netifObj;
 778 }
 779 
 780 /*
 781  * Enumerates all interfaces
 782  */
 783 static netif *enumInterfaces(JNIEnv *env) {
 784     netif *ifs = NULL;
 785     int sock;
 786 
 787     // Enumerate IPv4 addresses
 788     sock = openSocket(env, AF_INET);
 789     if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 790         return NULL;
 791     }
 792 
 793     if (sock >= 0) {
 794         ifs = enumIPv4Interfaces(env, sock, ifs);
 795         close(sock);
 796 
 797         if ((*env)->ExceptionOccurred(env)) {
 798             freeif(ifs);
 799             return NULL;
 800         }
 801     }
 802 
 803     // return partial list if an exception occurs in the middle of process ???
 804 
 805     // If IPv6 is available then enumerate IPv6 addresses.
 806 #ifdef AF_INET6
 807 
 808         // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
 809         // so we have to call ipv6_available()
 810         if (ipv6_available()) {
 811 
 812            sock = openSocket(env, AF_INET6);
 813            if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 814                freeif(ifs);
 815                return NULL;
 816            }
 817 
 818            if (sock >= 0) {
 819                ifs = enumIPv6Interfaces(env, sock, ifs);
 820                close(sock);
 821 
 822                if ((*env)->ExceptionOccurred(env)) {
 823                    freeif(ifs);
 824                    return NULL;
 825                }
 826            }
 827 
 828        }
 829 #endif
 830 
 831     return ifs;
 832 }
 833 
 834 #define CHECKED_MALLOC3(_pointer, _type, _size) \
 835     do { \
 836         _pointer = (_type)malloc(_size); \
 837         if (_pointer == NULL) { \
 838             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
 839             return ifs; /* return untouched list */ \
 840         } \
 841     } while(0)
 842 
 843 
 844 /*
 845  * Frees an interface list (including any attached addresses)
 846  */


1017         if (addrP->brdcast != NULL) {
1018             tmpaddr->brdcast = (struct sockaddr *)
1019                 ((char *)tmpaddr + sizeof(netaddr) + addr_size);
1020             memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
1021         }
1022 
1023         tmpaddr->next = currif->addr;
1024         currif->addr = tmpaddr;
1025     }
1026 
1027     return ifs;
1028 }
1029 
1030 /*
1031  * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
1032  */
1033 static int openSocket(JNIEnv *env, int proto) {
1034     int sock;
1035 
1036     if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
1037         // Don't throw an exception if the address family, or protocol, is not
1038         // supported.
1039         if (!(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)) {
1040             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1041                                          "Socket creation failed");
1042         }
1043         return -1;
1044     }
1045 
1046     return sock;
1047 }
1048 
1049 
1050 /** Linux, AIX **/
1051 #if defined(__linux__) || defined(_AIX)
1052 
1053 #ifdef AF_INET6
1054 /*
1055  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1056  * if it falls return AF_INET6 socket.
1057  */
1058 // unused arg ifname and struct if2
1059 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1060     int sock;
1061     struct ifreq if2;
1062 
1063     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1064         if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
1065             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1066                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1067                                              "IPV6 Socket creation failed");
1068                 return -1;
1069             }
1070         } else { // errno is not NOSUPPORT
1071             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1072                                          "IPV4 Socket creation failed");
1073             return -1;
1074         }
1075     }
1076 
1077     // Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or
1078     // IPv6 socket regardless of type of address of an interface.
1079     return sock;
1080 }
1081 
1082 #else
1083 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1084     return openSocket(env,AF_INET);


1468       *flags = if2.ifr_flags;
1469   }
1470   return 0;
1471 }
1472 
1473 #endif  /* defined(__linux__) || defined(_AIX) */
1474 
1475 /** Solaris **/
1476 #if defined(__solaris__)
1477 
1478 /*
1479  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1480  * if it falls return AF_INET6 socket.
1481  */
1482 #ifdef AF_INET6
1483 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1484     int sock, alreadyV6 = 0;
1485     struct lifreq if2;
1486 
1487     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1488         if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
1489             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1490                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1491                                              "IPV6 Socket creation failed");
1492                 return -1;
1493             }
1494 
1495             alreadyV6=1;
1496         } else { // errno is not NOSUPPORT
1497             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1498                                          "IPV4 Socket creation failed");
1499             return -1;
1500         }
1501     }
1502 
1503 
1504     // Solaris requires that we have an IPv6 socket to query an  interface
1505     // without an IPv4 address - check it here. POSIX 1 require the kernel to
1506     // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
1507     // for a device having IPv6 only address but not all devices follow the
1508     // standard so fall back on any error. It's not an ecologically friendly


1841     return 0;
1842 }
1843 
1844 
1845 #endif  /* __solaris__ */
1846 
1847 
1848 /** BSD **/
1849 #ifdef _ALLBSD_SOURCE
1850 
1851 /*
1852  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1853  * if it falls return AF_INET6 socket.
1854  */
1855 #ifdef AF_INET6
1856 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1857     int sock;
1858     struct ifreq if2;
1859 
1860      if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1861          if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
1862               if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1863                  NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1864                                               "IPV6 Socket creation failed");
1865                  return -1;
1866               }
1867          }
1868          else{ // errno is not NOSUPPORT
1869              NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1870                                           "IPV4 Socket creation failed");
1871              return -1;
1872          }
1873    }
1874 
1875    return sock;
1876 }
1877 
1878 #else
1879 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1880     return openSocket(env,AF_INET);
1881 }


< prev index next >