< prev index next >

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

Print this page
rev 14637 : Fix for incorrectly reported network mask and broadcast address on Linux,
when there are more then on IP address on an interface.
Fix is implemented using getifaddrs.


  32 #include <stdlib.h>
  33 #include <string.h>
  34 #include <sys/types.h>
  35 #include <sys/socket.h>
  36 #include <arpa/inet.h>
  37 #include <net/if.h>
  38 #include <net/if_arp.h>
  39 
  40 #if defined(__solaris__)
  41 #include <sys/dlpi.h>
  42 #include <fcntl.h>
  43 #include <stropts.h>
  44 #include <sys/sockio.h>
  45 #endif
  46 
  47 #if defined(__linux__)
  48 #include <sys/ioctl.h>
  49 #include <bits/ioctls.h>
  50 #include <sys/utsname.h>
  51 #include <stdio.h>

  52 #endif
  53 
  54 #if defined(_AIX)
  55 #include <sys/ioctl.h>
  56 #include <netinet/in6_var.h>
  57 #include <sys/ndd_var.h>
  58 #include <sys/kinfo.h>
  59 #endif
  60 
  61 #if defined(_ALLBSD_SOURCE)
  62 #include <sys/param.h>
  63 #include <sys/ioctl.h>
  64 #include <sys/sockio.h>
  65 #if defined(__APPLE__)
  66 #include <net/ethernet.h>
  67 #include <net/if_var.h>
  68 #include <net/if_dl.h>
  69 #include <netinet/in_var.h>
  70 #include <ifaddrs.h>
  71 #endif


 119 
 120 static jclass ni_ibcls;
 121 static jmethodID ni_ibctrID;
 122 static jfieldID ni_ibaddressID;
 123 static jfieldID ni_ib4broadcastID;
 124 static jfieldID ni_ib4maskID;
 125 
 126 /** Private methods declarations **/
 127 static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
 128 static int     getFlags0(JNIEnv *env, jstring  ifname);
 129 
 130 static netif  *enumInterfaces(JNIEnv *env);
 131 static netif  *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
 132 
 133 #ifdef AF_INET6
 134 static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
 135 #endif
 136 
 137 static netif  *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
 138                      struct sockaddr *ifr_addrP, int family, short prefix);



 139 static void    freeif(netif *ifs);
 140 
 141 static int     openSocket(JNIEnv *env, int proto);
 142 static int     openSocketWithFallback(JNIEnv *env, const char *ifname);
 143 
 144 
 145 static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name,
 146                                       struct sockaddr *brdcast_store);
 147 static short   getSubnet(JNIEnv *env, int sock, const char *ifname);

 148 static int     getIndex(int sock, const char *ifname);
 149 
 150 static int     getFlags(int sock, const char *ifname, int *flags);
 151 static int     getMacAddress(JNIEnv *env, int sock,  const char *ifname,
 152                              const struct in_addr *addr, unsigned char *buf);
 153 static int     getMTU(JNIEnv *env, int sock, const char *ifname);
 154 
 155 
 156 #if defined(__solaris__)
 157 static netif  *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
 158 static int     getMacFromDevice(JNIEnv *env, const char *ifname,
 159                                 unsigned char *retbuf);
 160 
 161 #ifndef SIOCGLIFHWADDR
 162 #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
 163 #endif
 164 
 165 #endif
 166 
 167 /******************* Java entry points *****************************/


 846 
 847     while (currif != NULL) {
 848         netaddr *addrP = currif->addr;
 849         while (addrP != NULL) {
 850             netaddr *next = addrP->next;
 851             free(addrP);
 852             addrP = next;
 853         }
 854 
 855         // Don't forget to free the sub-interfaces.
 856         if (currif->childs != NULL) {
 857             freeif(currif->childs);
 858         }
 859 
 860         ifs = currif->next;
 861         free(currif);
 862         currif = ifs;
 863     }
 864 }
 865 
 866 netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
 867              struct sockaddr *ifr_addrP, int family, short prefix)

 868 {
 869     netif *currif = ifs, *parent;
 870     netaddr *addrP;
 871 
 872 #ifdef LIFNAMSIZ
 873     int ifnam_size = LIFNAMSIZ;
 874     char name[LIFNAMSIZ], vname[LIFNAMSIZ];
 875 #else
 876     int ifnam_size = IFNAMSIZ;
 877     char name[IFNAMSIZ], vname[IFNAMSIZ];
 878 #endif
 879 
 880     char *name_colonP;
 881     int mask;
 882     int isVirtual = 0;
 883     int addr_size;
 884     int flags = 0;
 885 
 886     // If the interface name is a logical interface then we remove the unit
 887     // number so that we have the physical interface (eg: hme0:1 -> hme0).


 898 
 899 #ifdef AF_INET6
 900     addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in)
 901                                     : sizeof(struct sockaddr_in6);
 902 #else
 903     addr_size = sizeof(struct sockaddr_in);
 904 #endif
 905 
 906     CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size);
 907     addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr));
 908     memcpy(addrP->addr, ifr_addrP, addr_size);
 909 
 910     addrP->family = family;
 911     addrP->brdcast = NULL;
 912     addrP->mask = prefix;
 913     addrP->next = 0;
 914     if (family == AF_INET) {
 915        // Deal with broadcast addr & subnet mask
 916        struct sockaddr *brdcast_to =
 917               (struct sockaddr *) ((char *)addrP + sizeof(netaddr) + addr_size);





 918        addrP->brdcast = getBroadcast(env, sock, name, brdcast_to);
 919        if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
 920            return ifs;
 921        }
 922        if ((mask = getSubnet(env, sock, name)) != -1) {
 923            addrP->mask = mask;
 924        } else if((*env)->ExceptionCheck(env)) {
 925            return ifs;
 926        }

 927      }
 928 
 929     // Deal with virtual interface with colon notation e.g. eth0:1
 930     name_colonP = strchr(name, ':');
 931     if (name_colonP != NULL) {
 932         // This is a virtual interface. If we are able to access the parent
 933         // we need to create a new entry if it doesn't exist yet *and* update
 934         // the 'parent' interface with the new records.
 935         *name_colonP = 0;
 936         if (getFlags(sock, name, &flags) < 0 || flags < 0) {
 937              // failed to access parent interface do not create parent.
 938              // We are a virtual interface with no parent.
 939              isVirtual = 1;
 940              *name_colonP = ':';
 941         } else {
 942              // Got access to parent, so create it if necessary.
 943              // Save original name to vname and truncate name by ':'
 944              memcpy(vname, name, sizeof(vname) );
 945              vname[name_colonP - name] = ':';
 946         }


1006         memcpy(tmpaddr, addrP, sizeof(netaddr));
1007         if (addrP->addr != NULL) {
1008             tmpaddr->addr = (struct sockaddr *)
1009                 ((char*)tmpaddr + sizeof(netaddr));
1010             memcpy(tmpaddr->addr, addrP->addr, addr_size);
1011         }
1012 
1013         if (addrP->brdcast != NULL) {
1014             tmpaddr->brdcast = (struct sockaddr *)
1015                 ((char *)tmpaddr + sizeof(netaddr) + addr_size);
1016             memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
1017         }
1018 
1019         tmpaddr->next = currif->addr;
1020         currif->addr = tmpaddr;
1021     }
1022 
1023     return ifs;
1024 }
1025 






1026 /*
1027  * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
1028  */
1029 static int openSocket(JNIEnv *env, int proto) {
1030     int sock;
1031 
1032     if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
1033         // If EPROTONOSUPPORT is returned it means we don't have
1034         // support for this proto so don't throw an exception.
1035         if (errno != EPROTONOSUPPORT) {
1036             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1037                                          "Socket creation failed");
1038         }
1039         return -1;
1040     }
1041 
1042     return sock;
1043 }
1044 



























































1045 
1046 /** Linux, AIX **/
1047 #if defined(__linux__) || defined(_AIX)
1048 
1049 #ifdef AF_INET6
1050 /*
1051  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1052  * if it falls return AF_INET6 socket.
1053  */
1054 // unused arg ifname and struct if2
1055 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1056     int sock;
1057     struct ifreq if2;
1058 
1059     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1060         if (errno == EPROTONOSUPPORT) {
1061             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1062                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1063                                              "IPV6 Socket creation failed");
1064                 return -1;
1065             }
1066         } else { // errno is not NOSUPPORT
1067             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1068                                          "IPV4 Socket creation failed");
1069             return -1;
1070         }
1071     }
1072 
1073     // Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or
1074     // IPv6 socket regardless of type of address of an interface.
1075     return sock;
1076 }
1077 
1078 #else
1079 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1080     return openSocket(env,AF_INET);
1081 }
1082 #endif
1083 

1084 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1085     struct ifconf ifc;
1086     struct ifreq *ifreqP;
1087     char *buf = NULL;
1088     int numifs;
1089     unsigned i;
1090     int siocgifconfRequest = SIOCGIFCONF;
1091 
1092 #if defined(__linux__)
1093     // need to do a dummy SIOCGIFCONF to determine the buffer size.
1094     // SIOCGIFCOUNT doesn't work
1095     ifc.ifc_buf = NULL;
1096     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1097         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1098                                      "ioctl SIOCGIFCONF failed");
1099         return ifs;
1100     }
1101 #elif defined(_AIX)
1102     ifc.ifc_buf = NULL;
1103     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1104         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1105                                      "ioctl SIOCGSIZIFCONF failed");
1106         return ifs;
1107     }
1108 #endif /* __linux__ */
1109 
1110     CHECKED_MALLOC3(buf, char *, ifc.ifc_len);
1111 
1112     ifc.ifc_buf = buf;
1113 #if defined(_AIX)
1114     siocgifconfRequest = CSIOCGIFCONF;
1115 #endif
1116     if (ioctl(sock, siocgifconfRequest, (char *)&ifc) < 0) {
1117         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1118                                      "ioctl SIOCGIFCONF failed");
1119         free(buf);
1120         return ifs;
1121     }
1122 
1123     // Iterate through each interface
1124     ifreqP = ifc.ifc_req;
1125     for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) {
1126 #if defined(_AIX)
1127         if (ifreqP->ifr_addr.sa_family != AF_INET) continue;
1128 #endif
1129         // Add to the list
1130         ifs = addif(env, sock, ifreqP->ifr_name, ifs,
1131                     (struct sockaddr *)&(ifreqP->ifr_addr), AF_INET, 0);
1132 
1133         // If an exception occurred then free the list
1134         if ((*env)->ExceptionOccurred(env)) {
1135             free(buf);
1136             freeif(ifs);
1137             return NULL;
1138         }
1139     }
1140 
1141     // Free socket and buffer
1142     free(buf);
1143     return ifs;
1144 }

1145 
1146 
1147 #if defined(AF_INET6) && defined(__linux__)
1148 
1149 /*
1150  * Enumerates and returns all IPv6 interfaces on Linux.
1151  */
1152 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1153     FILE *f;
1154     char addr6[40], devname[21];
1155     char addr6p[8][5];
1156     int prefix, scope, dad_status, if_idx;
1157     uint8_t ipv6addr[16];
1158 
1159     if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1160         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1161                       addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1162                       addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1163                       &if_idx, &prefix, &scope, &dad_status, devname) != EOF) {
1164 


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 }
1877 #endif
1878 
1879 /*
1880  * Enumerates and returns all IPv4 interfaces.
1881  */
1882 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1883     struct ifaddrs *ifa, *origifa;
1884 
1885     if (getifaddrs(&origifa) != 0) {
1886         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1887                                      "getifaddrs() function failed");
1888         return ifs;
1889     }
1890 
1891     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1892 
1893         // Skip non-AF_INET entries.
1894         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
1895             continue;
1896 
1897         // Add to the list.
1898         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0);
1899 
1900         // If an exception occurred then free the list.
1901         if ((*env)->ExceptionOccurred(env)) {
1902             freeifaddrs(origifa);
1903             freeif(ifs);
1904             return NULL;
1905         }
1906     }
1907 
1908     // Free socket and buffer
1909     freeifaddrs(origifa);
1910     return ifs;
1911 }
1912 
1913 #ifdef AF_INET6
1914 /*
1915  * Determines the prefix on BSD for IPv6 interfaces.
1916  */
1917 static int prefix(void *val, int size) {
1918     u_char *name = (u_char *)val;
1919     int byte, bit, prefix = 0;
1920 
1921     for (byte = 0; byte < size; byte++, prefix += 8)
1922         if (name[byte] != 0xff)
1923             break;
1924     if (byte == size)
1925         return prefix;
1926     for (bit = 7; bit != 0; bit--, prefix++)
1927         if (!(name[byte] & (1 << bit)))
1928             break;
1929     for (; bit != 0; bit--)
1930         if (name[byte] & (1 << bit))
1931             return (0);




  32 #include <stdlib.h>
  33 #include <string.h>
  34 #include <sys/types.h>
  35 #include <sys/socket.h>
  36 #include <arpa/inet.h>
  37 #include <net/if.h>
  38 #include <net/if_arp.h>
  39 
  40 #if defined(__solaris__)
  41 #include <sys/dlpi.h>
  42 #include <fcntl.h>
  43 #include <stropts.h>
  44 #include <sys/sockio.h>
  45 #endif
  46 
  47 #if defined(__linux__)
  48 #include <sys/ioctl.h>
  49 #include <bits/ioctls.h>
  50 #include <sys/utsname.h>
  51 #include <stdio.h>
  52 #include <ifaddrs.h>
  53 #endif
  54 
  55 #if defined(_AIX)
  56 #include <sys/ioctl.h>
  57 #include <netinet/in6_var.h>
  58 #include <sys/ndd_var.h>
  59 #include <sys/kinfo.h>
  60 #endif
  61 
  62 #if defined(_ALLBSD_SOURCE)
  63 #include <sys/param.h>
  64 #include <sys/ioctl.h>
  65 #include <sys/sockio.h>
  66 #if defined(__APPLE__)
  67 #include <net/ethernet.h>
  68 #include <net/if_var.h>
  69 #include <net/if_dl.h>
  70 #include <netinet/in_var.h>
  71 #include <ifaddrs.h>
  72 #endif


 120 
 121 static jclass ni_ibcls;
 122 static jmethodID ni_ibctrID;
 123 static jfieldID ni_ibaddressID;
 124 static jfieldID ni_ib4broadcastID;
 125 static jfieldID ni_ib4maskID;
 126 
 127 /** Private methods declarations **/
 128 static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
 129 static int     getFlags0(JNIEnv *env, jstring  ifname);
 130 
 131 static netif  *enumInterfaces(JNIEnv *env);
 132 static netif  *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
 133 
 134 #ifdef AF_INET6
 135 static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
 136 #endif
 137 
 138 static netif  *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
 139                      struct sockaddr *ifr_addrP, int family, short prefix);
 140 static netif  *addif2(JNIEnv *env, int sock, const char *if_name, netif *ifs, 
 141                       struct sockaddr *ifr_addrP, int family, short prefix,
 142                       struct sockaddr *brdcast);
 143 static void    freeif(netif *ifs);
 144 
 145 static int     openSocket(JNIEnv *env, int proto);
 146 static int     openSocketWithFallback(JNIEnv *env, const char *ifname);
 147 
 148 
 149 static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name,
 150                                       struct sockaddr *brdcast_store);
 151 static short   getSubnet(JNIEnv *env, int sock, const char *ifname);
 152 static short   getSubnetFromMaskAddr(const struct sockaddr_in * netmask_addrP);
 153 static int     getIndex(int sock, const char *ifname);
 154 
 155 static int     getFlags(int sock, const char *ifname, int *flags);
 156 static int     getMacAddress(JNIEnv *env, int sock,  const char *ifname,
 157                              const struct in_addr *addr, unsigned char *buf);
 158 static int     getMTU(JNIEnv *env, int sock, const char *ifname);
 159 
 160 
 161 #if defined(__solaris__)
 162 static netif  *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
 163 static int     getMacFromDevice(JNIEnv *env, const char *ifname,
 164                                 unsigned char *retbuf);
 165 
 166 #ifndef SIOCGLIFHWADDR
 167 #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
 168 #endif
 169 
 170 #endif
 171 
 172 /******************* Java entry points *****************************/


 851 
 852     while (currif != NULL) {
 853         netaddr *addrP = currif->addr;
 854         while (addrP != NULL) {
 855             netaddr *next = addrP->next;
 856             free(addrP);
 857             addrP = next;
 858         }
 859 
 860         // Don't forget to free the sub-interfaces.
 861         if (currif->childs != NULL) {
 862             freeif(currif->childs);
 863         }
 864 
 865         ifs = currif->next;
 866         free(currif);
 867         currif = ifs;
 868     }
 869 }
 870 
 871 netif *addif2(JNIEnv *env, int sock, const char *if_name, netif *ifs,
 872              struct sockaddr *ifr_addrP, int family, short prefix,
 873              struct sockaddr *brdcast)
 874 {
 875     netif *currif = ifs, *parent;
 876     netaddr *addrP;
 877 
 878 #ifdef LIFNAMSIZ
 879     int ifnam_size = LIFNAMSIZ;
 880     char name[LIFNAMSIZ], vname[LIFNAMSIZ];
 881 #else
 882     int ifnam_size = IFNAMSIZ;
 883     char name[IFNAMSIZ], vname[IFNAMSIZ];
 884 #endif
 885 
 886     char *name_colonP;
 887     int mask;
 888     int isVirtual = 0;
 889     int addr_size;
 890     int flags = 0;
 891 
 892     // If the interface name is a logical interface then we remove the unit
 893     // number so that we have the physical interface (eg: hme0:1 -> hme0).


 904 
 905 #ifdef AF_INET6
 906     addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in)
 907                                     : sizeof(struct sockaddr_in6);
 908 #else
 909     addr_size = sizeof(struct sockaddr_in);
 910 #endif
 911 
 912     CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size);
 913     addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr));
 914     memcpy(addrP->addr, ifr_addrP, addr_size);
 915 
 916     addrP->family = family;
 917     addrP->brdcast = NULL;
 918     addrP->mask = prefix;
 919     addrP->next = 0;
 920     if (family == AF_INET) {
 921        // Deal with broadcast addr & subnet mask
 922        struct sockaddr *brdcast_to =
 923               (struct sockaddr *) ((char *)addrP + sizeof(netaddr) + addr_size);
 924 #if defined(__linux__)
 925        if (brdcast != NULL) {
 926            addrP->brdcast = memcpy(brdcast_to, brdcast, addr_size);
 927        }
 928 #else
 929        addrP->brdcast = getBroadcast(env, sock, name, brdcast_to);
 930        if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
 931            return ifs;
 932        }
 933        if ((mask = getSubnet(env, sock, name)) != -1) {
 934            addrP->mask = mask;
 935        } else if((*env)->ExceptionCheck(env)) {
 936            return ifs;
 937        }
 938 #endif
 939      }
 940 
 941     // Deal with virtual interface with colon notation e.g. eth0:1
 942     name_colonP = strchr(name, ':');
 943     if (name_colonP != NULL) {
 944         // This is a virtual interface. If we are able to access the parent
 945         // we need to create a new entry if it doesn't exist yet *and* update
 946         // the 'parent' interface with the new records.
 947         *name_colonP = 0;
 948         if (getFlags(sock, name, &flags) < 0 || flags < 0) {
 949              // failed to access parent interface do not create parent.
 950              // We are a virtual interface with no parent.
 951              isVirtual = 1;
 952              *name_colonP = ':';
 953         } else {
 954              // Got access to parent, so create it if necessary.
 955              // Save original name to vname and truncate name by ':'
 956              memcpy(vname, name, sizeof(vname) );
 957              vname[name_colonP - name] = ':';
 958         }


1018         memcpy(tmpaddr, addrP, sizeof(netaddr));
1019         if (addrP->addr != NULL) {
1020             tmpaddr->addr = (struct sockaddr *)
1021                 ((char*)tmpaddr + sizeof(netaddr));
1022             memcpy(tmpaddr->addr, addrP->addr, addr_size);
1023         }
1024 
1025         if (addrP->brdcast != NULL) {
1026             tmpaddr->brdcast = (struct sockaddr *)
1027                 ((char *)tmpaddr + sizeof(netaddr) + addr_size);
1028             memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
1029         }
1030 
1031         tmpaddr->next = currif->addr;
1032         currif->addr = tmpaddr;
1033     }
1034 
1035     return ifs;
1036 }
1037 
1038 netif *addif(JNIEnv *env, int sock, const char * if_name,
1039              netif *ifs, struct sockaddr* ifr_addrP, int family,
1040              short prefix) {
1041     return addif2(env, sock, if_name, ifs, ifr_addrP, family, prefix, NULL);
1042 }
1043 
1044 /*
1045  * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
1046  */
1047 static int openSocket(JNIEnv *env, int proto) {
1048     int sock;
1049 
1050     if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
1051         // If EPROTONOSUPPORT is returned it means we don't have
1052         // support for this proto so don't throw an exception.
1053         if (errno != EPROTONOSUPPORT) {
1054             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1055                                          "Socket creation failed");
1056         }
1057         return -1;
1058     }
1059 
1060     return sock;
1061 }
1062 
1063 /*
1064  * Count the number of non-zero bits
1065  */
1066 static inline short mask2subnet(uint32_t mask) {
1067     short ret = 0;
1068 
1069     for (; mask; mask <<= 1) {
1070         ++ret;
1071     }
1072 
1073     return ret;
1074 }
1075 
1076 static inline short getSubnetFromMaskAddr(const struct sockaddr_in * netmask_addrP) {
1077     return (netmask_addrP != NULL) ? mask2subnet(ntohl(netmask_addrP->sin_addr.s_addr)) : 0;
1078 }
1079 
1080 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
1081 /*
1082  * Enumerates and returns all IPv4 interfaces
1083  */
1084 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1085     struct ifaddrs *ifa, *origifa;
1086     struct sockaddr *ba = NULL;
1087     short subnet = 0;
1088 
1089     if (getifaddrs(&origifa) != 0) {
1090         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1091                          "getifaddrs() function failed");
1092         return ifs;
1093     }
1094 
1095     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1096         /* Skip non-AF_INET entries */
1097         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET) {
1098             continue;
1099         }
1100 
1101 #if defined(__linux__)
1102         ba = (ifa->ifa_flags & IFF_BROADCAST) ? ifa->ifa_broadaddr : NULL;
1103         subnet = getSubnetFromMaskAddr(((const struct sockaddr_in *)ifa->ifa_netmask));
1104 #endif
1105 
1106         /* Add to the list */
1107         ifs = addif2(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, subnet, ba);
1108 
1109         /* If an exception occurred then free the list */
1110         if ((*env)->ExceptionOccurred(env)) {
1111             freeifaddrs(origifa);
1112             freeif(ifs);
1113             return NULL;
1114         }
1115     }
1116 
1117     /* Free socket and buffer */
1118     freeifaddrs(origifa);
1119     return ifs;
1120 }
1121 #endif /* __linux__ || _ALLBSD_SOURCE */
1122 
1123 /** Linux, AIX **/
1124 #if defined(__linux__) || defined(_AIX)
1125 
1126 #ifdef AF_INET6
1127 /*
1128  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1129  * if it falls return AF_INET6 socket.
1130  */
1131 // unused arg ifname and struct if2
1132 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1133     int sock;
1134     struct ifreq if2;
1135 
1136     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1137         if (errno == EPROTONOSUPPORT) {
1138             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1139                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1140                                              "IPV6 Socket creation failed");
1141                 return -1;
1142             }
1143         } else { // errno is not NOSUPPORT
1144             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1145                                          "IPV4 Socket creation failed");
1146             return -1;
1147         }
1148     }
1149 
1150     // Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or
1151     // IPv6 socket regardless of type of address of an interface.
1152     return sock;
1153 }
1154 
1155 #else
1156 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1157     return openSocket(env,AF_INET);
1158 }
1159 #endif
1160 
1161 #if defined(_AIX)
1162 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1163     struct ifconf ifc;
1164     struct ifreq *ifreqP;
1165     char *buf = NULL;
1166     int numifs;
1167     unsigned i;
1168     int siocgifconfRequest = SIOCGIFCONF;
1169 










1170     ifc.ifc_buf = NULL;
1171     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1172         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1173                                      "ioctl SIOCGSIZIFCONF failed");
1174         return ifs;
1175     }

1176 
1177     CHECKED_MALLOC3(buf, char *, ifc.ifc_len);
1178 
1179     ifc.ifc_buf = buf;

1180     siocgifconfRequest = CSIOCGIFCONF;
1181 
1182     if (ioctl(sock, siocgifconfRequest, (char *)&ifc) < 0) {
1183         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1184                                      "ioctl SIOCGIFCONF failed");
1185         free(buf);
1186         return ifs;
1187     }
1188 
1189     // Iterate through each interface
1190     ifreqP = ifc.ifc_req;
1191     for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) {

1192         if (ifreqP->ifr_addr.sa_family != AF_INET) continue;

1193         // Add to the list
1194         ifs = addif(env, sock, ifreqP->ifr_name, ifs,
1195                     (struct sockaddr *)&(ifreqP->ifr_addr), AF_INET, 0);
1196 
1197         // If an exception occurred then free the list
1198         if ((*env)->ExceptionOccurred(env)) {
1199             free(buf);
1200             freeif(ifs);
1201             return NULL;
1202         }
1203     }
1204 
1205     // Free socket and buffer
1206     free(buf);
1207     return ifs;
1208 }
1209 #endif /* _AIX */
1210 
1211 
1212 #if defined(AF_INET6) && defined(__linux__)
1213 
1214 /*
1215  * Enumerates and returns all IPv6 interfaces on Linux.
1216  */
1217 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1218     FILE *f;
1219     char addr6[40], devname[21];
1220     char addr6p[8][5];
1221     int prefix, scope, dad_status, if_idx;
1222     uint8_t ipv6addr[16];
1223 
1224     if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1225         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1226                       addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1227                       addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1228                       &if_idx, &prefix, &scope, &dad_status, devname) != EOF) {
1229 


1927               }
1928          } else { // errno is not NOSUPPORT
1929              NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1930                                           "IPV4 Socket creation failed");
1931              return -1;
1932          }
1933    }
1934 
1935    return sock;
1936 }
1937 
1938 #else
1939 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1940     return openSocket(env,AF_INET);
1941 }
1942 #endif
1943 
1944 /*
1945  * Enumerates and returns all IPv4 interfaces.
1946  */






























1947 
1948 #ifdef AF_INET6
1949 /*
1950  * Determines the prefix on BSD for IPv6 interfaces.
1951  */
1952 static int prefix(void *val, int size) {
1953     u_char *name = (u_char *)val;
1954     int byte, bit, prefix = 0;
1955 
1956     for (byte = 0; byte < size; byte++, prefix += 8)
1957         if (name[byte] != 0xff)
1958             break;
1959     if (byte == size)
1960         return prefix;
1961     for (bit = 7; bit != 0; bit--, prefix++)
1962         if (!(name[byte] & (1 << bit)))
1963             break;
1964     for (; bit != 0; bit--)
1965         if (name[byte] & (1 << bit))
1966             return (0);


< prev index next >