< prev index next >

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

Print this page
rev 14618 : 8158023: SocketExceptions contain too little information sometimes


 602         JNU_ThrowNullPointerException(env, "network interface name is NULL");
 603         return -1;
 604     }
 605 
 606     if (name_utf == NULL) {
 607        if (!(*env)->ExceptionCheck(env))
 608            JNU_ThrowOutOfMemoryError(env, NULL);
 609        return -1;
 610     }
 611     if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
 612         (*env)->ReleaseStringUTFChars(env, name, name_utf);
 613         return -1;
 614     }
 615 
 616     ret = getFlags(sock, name_utf, &flags);
 617 
 618     close(sock);
 619     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 620 
 621     if (ret < 0) {
 622         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
 623                                      "ioctl SIOCGLIFFLAGS failed");
 624         return -1;
 625     }
 626 
 627     return flags;
 628 }
 629 
 630 /*
 631  * Creates a NetworkInterface object, populates the name, the index, and
 632  * populates the InetAddress array based on the IP addresses for this
 633  * interface.
 634  */
 635 jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
 636     jobject netifObj;
 637     jobject name;
 638     jobjectArray addrArr;
 639     jobjectArray bindArr;
 640     jobjectArray childArr;
 641     netaddr *addrs;
 642     jint addr_index, addr_count, bind_index;
 643     jint child_count, child_index;


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         }


1193 
1194 
1195 #if defined(AF_INET6) && defined(_AIX)
1196 
1197 /*
1198  * Enumerates and returns all IPv6 interfaces on AIX.
1199  */
1200 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1201     struct ifconf ifc;
1202     struct ifreq *ifreqP;
1203     char *buf;
1204     int numifs;
1205     unsigned i;
1206     unsigned bufsize;
1207     char *cp, *cplimit;
1208 
1209     // use SIOCGSIZIFCONF to get size for  SIOCGIFCONF
1210 
1211     ifc.ifc_buf = NULL;
1212     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1213         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1214                                     "ioctl SIOCGSIZIFCONF failed");
1215         return ifs;
1216     }
1217     bufsize = ifc.ifc_len;
1218 
1219     buf = (char *)malloc(bufsize);
1220     if (!buf) {
1221         JNU_ThrowOutOfMemoryError(env, "Network interface native buffer allocation failed");
1222         return ifs;
1223     }
1224     ifc.ifc_len = bufsize;
1225     ifc.ifc_buf = buf;
1226     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1227         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1228                                      "ioctl CSIOCGIFCONF failed");
1229         free(buf);
1230         return ifs;
1231     }
1232 
1233     // Iterate through each interface
1234     ifreqP = ifc.ifc_req;
1235     cp = (char *)ifc.ifc_req;
1236     cplimit = cp + ifc.ifc_len;
1237 
1238     for (; cp < cplimit;
1239         cp += (sizeof(ifreqP->ifr_name) +
1240                MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr))))
1241     {
1242         ifreqP = (struct ifreq *)cp;
1243         struct ifreq if2;
1244         memset((char *)&if2, 0, sizeof(if2));
1245         strncpy(if2.ifr_name, ifreqP->ifr_name, sizeof(if2.ifr_name) - 1);
1246 
1247         // Skip interface that aren't UP
1248         if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {


1292     }
1293 
1294     return if2.ifr_ifindex;
1295 #endif
1296 }
1297 
1298 /*
1299  * Returns the IPv4 broadcast address of a named interface, if it exists.
1300  * Returns 0 if it doesn't have one.
1301  */
1302 static struct sockaddr *getBroadcast
1303   (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
1304 {
1305     struct sockaddr *ret = NULL;
1306     struct ifreq if2;
1307     memset((char *)&if2, 0, sizeof(if2));
1308     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1309 
1310     // Let's make sure the interface does have a broadcast address.
1311     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
1312         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1313                                      "ioctl SIOCGIFFLAGS failed");
1314         return ret;
1315     }
1316 
1317     if (if2.ifr_flags & IFF_BROADCAST) {
1318         // It does, let's retrieve it
1319         if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
1320             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1321                                          "ioctl SIOCGIFBRDADDR failed");
1322             return ret;
1323         }
1324 
1325         ret = brdcast_store;
1326         memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
1327     }
1328 
1329     return ret;
1330 }
1331 
1332 /*
1333  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1334  * interface, if it has one, otherwise return -1.
1335  */
1336 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1337     unsigned int mask;
1338     short ret;
1339     struct ifreq if2;
1340     memset((char *)&if2, 0, sizeof(if2));
1341     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1342 
1343     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
1344         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1345                                      "ioctl SIOCGIFNETMASK failed");
1346         return -1;
1347     }
1348 
1349     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1350     ret = 0;
1351     while (mask) {
1352        mask <<= 1;
1353        ret++;
1354     }
1355 
1356     return ret;
1357 }
1358 
1359 /*
1360  * Gets the Hardware address (usually MAC address) for the named interface.
1361  * On return puts the data in buf, and returns the length, in byte, of the
1362  * MAC address. Returns -1 if there is no hardware address on that interface.
1363  */
1364 static int getMacAddress
1365   (JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr,


1394     }
1395 
1396     end = (void *)nddp + size;
1397     while ((void *)nddp < end) {
1398         if (!strcmp(nddp->ndd_alias, ifname) ||
1399                 !strcmp(nddp->ndd_name, ifname)) {
1400             bcopy(nddp->ndd_addr, buf, 6);
1401             return 6;
1402         } else {
1403             nddp++;
1404         }
1405     }
1406 
1407     return -1;
1408 #elif defined(__linux__)
1409     static struct ifreq ifr;
1410     int i;
1411     memset((char *)&ifr, 0, sizeof(ifr));
1412     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
1413     if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1414         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1415                                      "ioctl SIOCGIFHWADDR failed");
1416         return -1;
1417     }
1418 
1419     memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1420 
1421     // All bytes to 0 means no hardware address.
1422 
1423     for (i = 0; i < IFHWADDRLEN; i++) {
1424         if (buf[i] != 0)
1425             return IFHWADDRLEN;
1426     }
1427 
1428     return -1;
1429 #endif
1430 }
1431 
1432 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1433     struct ifreq if2;
1434     memset((char *)&if2, 0, sizeof(if2));
1435 
1436     if (ifname != NULL) {
1437         strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1438     } else {
1439         JNU_ThrowNullPointerException(env, "network interface name is NULL");
1440         return -1;
1441     }
1442 
1443     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1444         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1445                                      "ioctl SIOCGIFMTU failed");
1446         return -1;
1447     }
1448 
1449     return  if2.ifr_mtu;
1450 }
1451 
1452 static int getFlags(int sock, const char *ifname, int *flags) {
1453   struct ifreq if2;
1454   memset((char *)&if2, 0, sizeof(if2));
1455   strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1456 
1457   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1458       return -1;
1459   }
1460 
1461   if (sizeof(if2.ifr_flags) == sizeof(short)) {
1462       *flags = (if2.ifr_flags & 0xffff);
1463   } else {
1464       *flags = if2.ifr_flags;
1465   }
1466   return 0;
1467 }
1468 
1469 #endif  /* defined(__linux__) || defined(_AIX) */
1470 
1471 /** Solaris **/
1472 #if defined(__solaris__)
1473 
1474 /*
1475  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1476  * if it falls return AF_INET6 socket.
1477  */
1478 #ifdef AF_INET6
1479 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1480     int sock, alreadyV6 = 0;
1481     struct lifreq if2;
1482 
1483     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1484         if (errno == EPROTONOSUPPORT) {
1485             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1486                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1487                                              "IPV6 Socket creation failed");
1488                 return -1;
1489             }
1490 
1491             alreadyV6=1;
1492         } else { // errno is not NOSUPPORT
1493             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1494                                          "IPV4 Socket creation failed");
1495             return -1;
1496         }
1497     }
1498 
1499 
1500     // Solaris requires that we have an IPv6 socket to query an  interface
1501     // without an IPv4 address - check it here. POSIX 1 require the kernel to
1502     // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
1503     // for a device having IPv6 only address but not all devices follow the
1504     // standard so fall back on any error. It's not an ecologically friendly
1505     // gesture but more reliable.
1506 
1507     if (!alreadyV6) {
1508         memset((char *)&if2, 0, sizeof(if2));
1509         strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1510         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1511             close(sock);
1512             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1513                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1514                                              "IPV6 Socket creation failed");
1515                 return -1;
1516             }
1517         }
1518     }
1519 
1520     return sock;
1521 }
1522 
1523 #else
1524 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1525     return openSocket(env,AF_INET);
1526 }
1527 #endif
1528 
1529 /*
1530  * Enumerates and returns all IPv4 interfaces.
1531  */
1532 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1533     return enumIPvXInterfaces(env,sock, ifs, AF_INET);
1534 }


1538     return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
1539 }
1540 #endif
1541 
1542 /*
1543  * Enumerates and returns all interfaces on Solaris.
1544  * Uses the same code for IPv4 and IPv6.
1545  */
1546 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
1547     struct lifconf ifc;
1548     struct lifreq *ifr;
1549     int n;
1550     char *buf;
1551     struct lifnum numifs;
1552     unsigned bufsize;
1553 
1554     // Get the interface count
1555     numifs.lifn_family = family;
1556     numifs.lifn_flags = 0;
1557     if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
1558         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1559                                      "ioctl SIOCGLIFNUM failed");
1560         return ifs;
1561     }
1562 
1563     //  Enumerate the interface configurations
1564     bufsize = numifs.lifn_count * sizeof (struct lifreq);
1565     CHECKED_MALLOC3(buf, char *, bufsize);
1566 
1567     ifc.lifc_family = family;
1568     ifc.lifc_flags = 0;
1569     ifc.lifc_len = bufsize;
1570     ifc.lifc_buf = buf;
1571     if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
1572         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1573                                      "ioctl SIOCGLIFCONF failed");
1574         free(buf);
1575         return ifs;
1576     }
1577 
1578     // Iterate through each interface
1579     ifr = ifc.lifc_req;
1580     for (n=0; n<numifs.lifn_count; n++, ifr++) {
1581         int index = -1;
1582         struct lifreq if2;
1583 
1584         // Ignore either IPv4 or IPv6 addresses
1585         if (ifr->lifr_addr.ss_family != family) {
1586             continue;
1587         }
1588 
1589 #ifdef AF_INET6
1590         if (ifr->lifr_addr.ss_family == AF_INET6) {
1591             struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
1592             s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
1593         }


1620         return -1;
1621     }
1622 
1623     return if2.lifr_index;
1624 }
1625 
1626 /*
1627  * Returns the IPv4 broadcast address of a named interface, if it exists.
1628  * Returns 0 if it doesn't have one.
1629  */
1630 static struct sockaddr *getBroadcast
1631   (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
1632 {
1633     struct sockaddr *ret = NULL;
1634     struct lifreq if2;
1635     memset((char *)&if2, 0, sizeof(if2));
1636     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1637 
1638     // Let's make sure the interface does have a broadcast address
1639     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
1640         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1641                                      "ioctl SIOCGLIFFLAGS failed");
1642         return ret;
1643     }
1644 
1645     if (if2.lifr_flags & IFF_BROADCAST) {
1646         // It does, let's retrieve it
1647         if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
1648             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1649                                          "ioctl SIOCGLIFBRDADDR failed");
1650             return ret;
1651         }
1652 
1653         ret = brdcast_store;
1654         memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
1655     }
1656 
1657     return ret;
1658 }
1659 
1660 /*
1661  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1662  * interface, if it has one, otherwise return -1.
1663  */
1664 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1665     unsigned int mask;
1666     short ret;
1667     struct lifreq if2;
1668     memset((char *)&if2, 0, sizeof(if2));
1669     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1670 
1671     if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1672         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1673                                      "ioctl SIOCGLIFNETMASK failed");
1674         return -1;
1675     }
1676 
1677     mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
1678     ret = 0;
1679 
1680     while (mask) {
1681        mask <<= 1;
1682        ret++;
1683     }
1684 
1685     return ret;
1686 }
1687 
1688 
1689 #define DEV_PREFIX  "/dev/"
1690 
1691 /*
1692  * Solaris specific DLPI code to get hardware address from a device.
1693  * Unfortunately, at least up to Solaris X, you have to have special


1703     struct strbuf msg;
1704     char buf[128];
1705     int flags = 0;
1706 
1707     // Device is in /dev.  e.g.: /dev/bge0
1708     strcpy(style1dev, DEV_PREFIX);
1709     strcat(style1dev, ifname);
1710     if ((fd = open(style1dev, O_RDWR)) < 0) {
1711          // Can't open it. We probably are missing the privilege.
1712          // We'll have to try something else
1713          return 0;
1714     }
1715 
1716     dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
1717     dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
1718 
1719     msg.buf = (char *)&dlpareq;
1720     msg.len = DL_PHYS_ADDR_REQ_SIZE;
1721 
1722     if (putmsg(fd, &msg, NULL, 0) < 0) {
1723         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1724                                      "putmsg failed");
1725         return -1;
1726     }
1727 
1728     dlpaack = (dl_phys_addr_ack_t *)buf;
1729 
1730     msg.buf = (char *)buf;
1731     msg.len = 0;
1732     msg.maxlen = sizeof (buf);
1733     if (getmsg(fd, &msg, NULL, &flags) < 0) {
1734         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1735                                      "getmsg failed");
1736         return -1;
1737     }
1738 
1739     if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
1740         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1741                         "Couldn't obtain phys addr\n");
1742         return -1;
1743     }
1744 
1745     memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
1746     return dlpaack->dl_addr_length;
1747 }
1748 
1749 /*
1750  * Gets the Hardware address (usually MAC address) for the named interface.
1751  * On return puts the data in buf, and returns the length, in byte, of the
1752  * MAC address. Returns -1 if there is no hardware address on that interface.
1753  */
1754 static int getMacAddress
1755   (JNIEnv *env, int sock, const char *ifname, const struct in_addr* addr,


1799          }
1800 
1801          memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
1802     }
1803 
1804     // All bytes to 0 means no hardware address.
1805     for (i = 0; i < len; i++) {
1806       if (buf[i] != 0)
1807          return len;
1808     }
1809 
1810     return -1;
1811 }
1812 
1813 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1814     struct lifreq if2;
1815     memset((char *)&if2, 0, sizeof(if2));
1816     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1817 
1818     if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
1819         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1820                                     "ioctl SIOCGLIFMTU failed");
1821         return -1;
1822     }
1823 
1824     return if2.lifr_mtu;
1825 }
1826 
1827 static int getFlags(int sock, const char *ifname, int *flags) {
1828     struct lifreq if2;
1829     memset((char *)&if2, 0, sizeof(if2));
1830     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1831 
1832     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
1833         return -1;
1834     }
1835 
1836     *flags = if2.lifr_flags;
1837     return 0;
1838 }
1839 
1840 
1841 #endif  /* __solaris__ */
1842 
1843 
1844 /** BSD **/
1845 #ifdef _ALLBSD_SOURCE
1846 
1847 /*
1848  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1849  * if it falls return AF_INET6 socket.
1850  */
1851 #ifdef AF_INET6
1852 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1853     int sock;
1854     struct ifreq if2;
1855 
1856      if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1857          if (errno == EPROTONOSUPPORT) {
1858               if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1859                  NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1860                                               "IPV6 Socket creation failed");
1861                  return -1;
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 


1928             break;
1929     for (; bit != 0; bit--)
1930         if (name[byte] & (1 << bit))
1931             return (0);
1932     byte++;
1933     for (; byte < size; byte++)
1934         if (name[byte])
1935             return (0);
1936     return prefix;
1937 }
1938 
1939 /*
1940  * Enumerates and returns all IPv6 interfaces on BSD.
1941  */
1942 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1943     struct ifaddrs *ifa, *origifa;
1944     struct sockaddr_in6 *sin6;
1945     struct in6_ifreq ifr6;
1946 
1947     if (getifaddrs(&origifa) != 0) {
1948         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1949                                      "getifaddrs() function failed");
1950         return ifs;
1951     }
1952 
1953     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1954 
1955         // Skip non-AF_INET6 entries.
1956         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
1957             continue;
1958 
1959         memset(&ifr6, 0, sizeof(ifr6));
1960         strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
1961         memcpy(&ifr6.ifr_addr, ifa->ifa_addr,
1962                MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
1963 
1964         if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
1965             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1966                                          "ioctl SIOCGIFNETMASK_IN6 failed");
1967             freeifaddrs(origifa);
1968             freeif(ifs);
1969             return NULL;
1970         }
1971 
1972         // Add to the list.
1973         sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
1974         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6,
1975             (short)prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
1976 
1977         // If an exception occurred then free the list.
1978         if ((*env)->ExceptionOccurred(env)) {
1979             freeifaddrs(origifa);
1980             freeif(ifs);
1981             return NULL;
1982         }
1983     }
1984 
1985     // Free socket and ifaddrs buffer
1986     freeifaddrs(origifa);


2005     // Try to get the interface index using BSD specific if_nametoindex
2006     int index = if_nametoindex(name);
2007     return (index == 0) ? -1 : index;
2008 #endif
2009 }
2010 
2011 /*
2012  * Returns the IPv4 broadcast address of a named interface, if it exists.
2013  * Returns 0 if it doesn't have one.
2014  */
2015 static struct sockaddr *getBroadcast
2016   (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
2017 {
2018     struct sockaddr *ret = NULL;
2019     struct ifreq if2;
2020     memset((char *)&if2, 0, sizeof(if2));
2021     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2022 
2023     // Make sure the interface does have a broadcast address
2024     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
2025         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
2026                                      "ioctl SIOCGIFFLAGS failed");
2027         return ret;
2028     }
2029 
2030     if (if2.ifr_flags & IFF_BROADCAST) {
2031         // It does, let's retrieve it
2032         if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
2033             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
2034                                          "ioctl SIOCGIFBRDADDR failed");
2035             return ret;
2036         }
2037 
2038         ret = brdcast_store;
2039         memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
2040     }
2041 
2042     return ret;
2043 }
2044 
2045 /*
2046  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
2047  * interface, if it has one, otherwise return -1.
2048  */
2049 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
2050     unsigned int mask;
2051     short ret;
2052     struct ifreq if2;
2053     memset((char *)&if2, 0, sizeof(if2));
2054     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2055 
2056     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
2057         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
2058                                      "ioctl SIOCGIFNETMASK failed");
2059         return -1;
2060     }
2061 
2062     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
2063     ret = 0;
2064     while (mask) {
2065        mask <<= 1;
2066        ret++;
2067     }
2068 
2069     return ret;
2070 }
2071 
2072 /*
2073  * Gets the Hardware address (usually MAC address) for the named interface.
2074  * return puts the data in buf, and returns the length, in byte, of the
2075  * MAC address. Returns -1 if there is no hardware address on that interface.
2076  */
2077 static int getMacAddress
2078   (JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr,


2093                 // Check the address is the correct length
2094                 if (sadl->sdl_alen == ETHER_ADDR_LEN) {
2095                     memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
2096                     freeifaddrs(ifa0);
2097                     return ETHER_ADDR_LEN;
2098                 }
2099             }
2100         }
2101         freeifaddrs(ifa0);
2102     }
2103 
2104     return -1;
2105 }
2106 
2107 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
2108     struct ifreq if2;
2109     memset((char *)&if2, 0, sizeof(if2));
2110     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2111 
2112     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
2113         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
2114                                      "ioctl SIOCGIFMTU failed");
2115         return -1;
2116     }
2117 
2118     return  if2.ifr_mtu;
2119 }
2120 
2121 static int getFlags(int sock, const char *ifname, int *flags) {
2122     struct ifreq if2;
2123     int ret = -1;
2124     memset((char *)&if2, 0, sizeof(if2));
2125     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2126 
2127     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
2128         return -1;
2129     }
2130 
2131     if (sizeof(if2.ifr_flags) == sizeof(short)) {
2132         *flags = (if2.ifr_flags & 0xffff);
2133     } else {
2134         *flags = if2.ifr_flags;


 602         JNU_ThrowNullPointerException(env, "network interface name is NULL");
 603         return -1;
 604     }
 605 
 606     if (name_utf == NULL) {
 607        if (!(*env)->ExceptionCheck(env))
 608            JNU_ThrowOutOfMemoryError(env, NULL);
 609        return -1;
 610     }
 611     if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
 612         (*env)->ReleaseStringUTFChars(env, name, name_utf);
 613         return -1;
 614     }
 615 
 616     ret = getFlags(sock, name_utf, &flags);
 617 
 618     close(sock);
 619     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 620 
 621     if (ret < 0) {
 622         JNU_ThrowByNameWithMessageAndLastError
 623             (env, JNU_JAVANETPKG "SocketException", "getFlags() failed");
 624         return -1;
 625     }
 626 
 627     return flags;
 628 }
 629 
 630 /*
 631  * Creates a NetworkInterface object, populates the name, the index, and
 632  * populates the InetAddress array based on the IP addresses for this
 633  * interface.
 634  */
 635 jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
 636     jobject netifObj;
 637     jobject name;
 638     jobjectArray addrArr;
 639     jobjectArray bindArr;
 640     jobjectArray childArr;
 641     netaddr *addrs;
 642     jint addr_index, addr_count, bind_index;
 643     jint child_count, child_index;


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             JNU_ThrowByNameWithMessageAndLastError
1037                 (env, JNU_JAVANETPKG "SocketException", "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                 JNU_ThrowByNameWithMessageAndLastError
1063                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1064                 return -1;
1065             }
1066         } else { // errno is not NOSUPPORT
1067             JNU_ThrowByNameWithMessageAndLastError
1068                 (env, JNU_JAVANETPKG "SocketException", "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         JNU_ThrowByNameWithMessageAndLastError
1098             (env, JNU_JAVANETPKG "SocketException", "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         JNU_ThrowByNameWithMessageAndLastError
1105             (env, JNU_JAVANETPKG "SocketException", "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         JNU_ThrowByNameWithMessageAndLastError
1118             (env, JNU_JAVANETPKG "SocketException", "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         }


1193 
1194 
1195 #if defined(AF_INET6) && defined(_AIX)
1196 
1197 /*
1198  * Enumerates and returns all IPv6 interfaces on AIX.
1199  */
1200 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1201     struct ifconf ifc;
1202     struct ifreq *ifreqP;
1203     char *buf;
1204     int numifs;
1205     unsigned i;
1206     unsigned bufsize;
1207     char *cp, *cplimit;
1208 
1209     // use SIOCGSIZIFCONF to get size for  SIOCGIFCONF
1210 
1211     ifc.ifc_buf = NULL;
1212     if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1213         JNU_ThrowByNameWithMessageAndLastError
1214             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed");
1215         return ifs;
1216     }
1217     bufsize = ifc.ifc_len;
1218 
1219     buf = (char *)malloc(bufsize);
1220     if (!buf) {
1221         JNU_ThrowOutOfMemoryError(env, "Network interface native buffer allocation failed");
1222         return ifs;
1223     }
1224     ifc.ifc_len = bufsize;
1225     ifc.ifc_buf = buf;
1226     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1227         JNU_ThrowByNameWithMessageAndLastError
1228             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed");
1229         free(buf);
1230         return ifs;
1231     }
1232 
1233     // Iterate through each interface
1234     ifreqP = ifc.ifc_req;
1235     cp = (char *)ifc.ifc_req;
1236     cplimit = cp + ifc.ifc_len;
1237 
1238     for (; cp < cplimit;
1239         cp += (sizeof(ifreqP->ifr_name) +
1240                MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr))))
1241     {
1242         ifreqP = (struct ifreq *)cp;
1243         struct ifreq if2;
1244         memset((char *)&if2, 0, sizeof(if2));
1245         strncpy(if2.ifr_name, ifreqP->ifr_name, sizeof(if2.ifr_name) - 1);
1246 
1247         // Skip interface that aren't UP
1248         if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {


1292     }
1293 
1294     return if2.ifr_ifindex;
1295 #endif
1296 }
1297 
1298 /*
1299  * Returns the IPv4 broadcast address of a named interface, if it exists.
1300  * Returns 0 if it doesn't have one.
1301  */
1302 static struct sockaddr *getBroadcast
1303   (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
1304 {
1305     struct sockaddr *ret = NULL;
1306     struct ifreq if2;
1307     memset((char *)&if2, 0, sizeof(if2));
1308     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1309 
1310     // Let's make sure the interface does have a broadcast address.
1311     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
1312         JNU_ThrowByNameWithMessageAndLastError
1313             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFFLAGS) failed");
1314         return ret;
1315     }
1316 
1317     if (if2.ifr_flags & IFF_BROADCAST) {
1318         // It does, let's retrieve it
1319         if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
1320             JNU_ThrowByNameWithMessageAndLastError
1321                 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFBRDADDR) failed");
1322             return ret;
1323         }
1324 
1325         ret = brdcast_store;
1326         memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
1327     }
1328 
1329     return ret;
1330 }
1331 
1332 /*
1333  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1334  * interface, if it has one, otherwise return -1.
1335  */
1336 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1337     unsigned int mask;
1338     short ret;
1339     struct ifreq if2;
1340     memset((char *)&if2, 0, sizeof(if2));
1341     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1342 
1343     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
1344         JNU_ThrowByNameWithMessageAndLastError
1345             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFNETMASK) failed");
1346         return -1;
1347     }
1348 
1349     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1350     ret = 0;
1351     while (mask) {
1352        mask <<= 1;
1353        ret++;
1354     }
1355 
1356     return ret;
1357 }
1358 
1359 /*
1360  * Gets the Hardware address (usually MAC address) for the named interface.
1361  * On return puts the data in buf, and returns the length, in byte, of the
1362  * MAC address. Returns -1 if there is no hardware address on that interface.
1363  */
1364 static int getMacAddress
1365   (JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr,


1394     }
1395 
1396     end = (void *)nddp + size;
1397     while ((void *)nddp < end) {
1398         if (!strcmp(nddp->ndd_alias, ifname) ||
1399                 !strcmp(nddp->ndd_name, ifname)) {
1400             bcopy(nddp->ndd_addr, buf, 6);
1401             return 6;
1402         } else {
1403             nddp++;
1404         }
1405     }
1406 
1407     return -1;
1408 #elif defined(__linux__)
1409     static struct ifreq ifr;
1410     int i;
1411     memset((char *)&ifr, 0, sizeof(ifr));
1412     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
1413     if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1414         JNU_ThrowByNameWithMessageAndLastError
1415             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFHWADDR) failed");
1416         return -1;
1417     }
1418 
1419     memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1420 
1421     // All bytes to 0 means no hardware address.
1422 
1423     for (i = 0; i < IFHWADDRLEN; i++) {
1424         if (buf[i] != 0)
1425             return IFHWADDRLEN;
1426     }
1427 
1428     return -1;
1429 #endif
1430 }
1431 
1432 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1433     struct ifreq if2;
1434     memset((char *)&if2, 0, sizeof(if2));
1435 
1436     if (ifname != NULL) {
1437         strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1438     } else {
1439         JNU_ThrowNullPointerException(env, "network interface name is NULL");
1440         return -1;
1441     }
1442 
1443     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1444         JNU_ThrowByNameWithMessageAndLastError
1445             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1446         return -1;
1447     }
1448 
1449     return  if2.ifr_mtu;
1450 }
1451 
1452 static int getFlags(int sock, const char *ifname, int *flags) {
1453   struct ifreq if2;
1454   memset((char *)&if2, 0, sizeof(if2));
1455   strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1456 
1457   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1458       return -1;
1459   }
1460 
1461   if (sizeof(if2.ifr_flags) == sizeof(short)) {
1462       *flags = (if2.ifr_flags & 0xffff);
1463   } else {
1464       *flags = if2.ifr_flags;
1465   }
1466   return 0;
1467 }
1468 
1469 #endif  /* defined(__linux__) || defined(_AIX) */
1470 
1471 /** Solaris **/
1472 #if defined(__solaris__)
1473 
1474 /*
1475  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1476  * if it falls return AF_INET6 socket.
1477  */
1478 #ifdef AF_INET6
1479 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1480     int sock, alreadyV6 = 0;
1481     struct lifreq if2;
1482 
1483     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1484         if (errno == EPROTONOSUPPORT) {
1485             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1486                 JNU_ThrowByNameWithMessageAndLastError
1487                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1488                 return -1;
1489             }
1490 
1491             alreadyV6=1;
1492         } else { // errno is not NOSUPPORT
1493             JNU_ThrowByNameWithMessageAndLastError
1494                 (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1495             return -1;
1496         }
1497     }
1498 
1499 
1500     // Solaris requires that we have an IPv6 socket to query an  interface
1501     // without an IPv4 address - check it here. POSIX 1 require the kernel to
1502     // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
1503     // for a device having IPv6 only address but not all devices follow the
1504     // standard so fall back on any error. It's not an ecologically friendly
1505     // gesture but more reliable.
1506 
1507     if (!alreadyV6) {
1508         memset((char *)&if2, 0, sizeof(if2));
1509         strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1510         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1511             close(sock);
1512             if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1513                 JNU_ThrowByNameWithMessageAndLastError
1514                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1515                 return -1;
1516             }
1517         }
1518     }
1519 
1520     return sock;
1521 }
1522 
1523 #else
1524 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1525     return openSocket(env,AF_INET);
1526 }
1527 #endif
1528 
1529 /*
1530  * Enumerates and returns all IPv4 interfaces.
1531  */
1532 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1533     return enumIPvXInterfaces(env,sock, ifs, AF_INET);
1534 }


1538     return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
1539 }
1540 #endif
1541 
1542 /*
1543  * Enumerates and returns all interfaces on Solaris.
1544  * Uses the same code for IPv4 and IPv6.
1545  */
1546 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
1547     struct lifconf ifc;
1548     struct lifreq *ifr;
1549     int n;
1550     char *buf;
1551     struct lifnum numifs;
1552     unsigned bufsize;
1553 
1554     // Get the interface count
1555     numifs.lifn_family = family;
1556     numifs.lifn_flags = 0;
1557     if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
1558         JNU_ThrowByNameWithMessageAndLastError
1559             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
1560         return ifs;
1561     }
1562 
1563     //  Enumerate the interface configurations
1564     bufsize = numifs.lifn_count * sizeof (struct lifreq);
1565     CHECKED_MALLOC3(buf, char *, bufsize);
1566 
1567     ifc.lifc_family = family;
1568     ifc.lifc_flags = 0;
1569     ifc.lifc_len = bufsize;
1570     ifc.lifc_buf = buf;
1571     if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
1572         JNU_ThrowByNameWithMessageAndLastError
1573             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
1574         free(buf);
1575         return ifs;
1576     }
1577 
1578     // Iterate through each interface
1579     ifr = ifc.lifc_req;
1580     for (n=0; n<numifs.lifn_count; n++, ifr++) {
1581         int index = -1;
1582         struct lifreq if2;
1583 
1584         // Ignore either IPv4 or IPv6 addresses
1585         if (ifr->lifr_addr.ss_family != family) {
1586             continue;
1587         }
1588 
1589 #ifdef AF_INET6
1590         if (ifr->lifr_addr.ss_family == AF_INET6) {
1591             struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
1592             s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
1593         }


1620         return -1;
1621     }
1622 
1623     return if2.lifr_index;
1624 }
1625 
1626 /*
1627  * Returns the IPv4 broadcast address of a named interface, if it exists.
1628  * Returns 0 if it doesn't have one.
1629  */
1630 static struct sockaddr *getBroadcast
1631   (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
1632 {
1633     struct sockaddr *ret = NULL;
1634     struct lifreq if2;
1635     memset((char *)&if2, 0, sizeof(if2));
1636     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1637 
1638     // Let's make sure the interface does have a broadcast address
1639     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
1640         JNU_ThrowByNameWithMessageAndLastError
1641             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFFLAGS) failed");
1642         return ret;
1643     }
1644 
1645     if (if2.lifr_flags & IFF_BROADCAST) {
1646         // It does, let's retrieve it
1647         if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
1648             JNU_ThrowByNameWithMessageAndLastError
1649                 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFBRDADDR) failed");
1650             return ret;
1651         }
1652 
1653         ret = brdcast_store;
1654         memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
1655     }
1656 
1657     return ret;
1658 }
1659 
1660 /*
1661  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1662  * interface, if it has one, otherwise return -1.
1663  */
1664 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1665     unsigned int mask;
1666     short ret;
1667     struct lifreq if2;
1668     memset((char *)&if2, 0, sizeof(if2));
1669     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1670 
1671     if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1672         JNU_ThrowByNameWithMessageAndLastError
1673             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNETMASK) failed");
1674         return -1;
1675     }
1676 
1677     mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
1678     ret = 0;
1679 
1680     while (mask) {
1681        mask <<= 1;
1682        ret++;
1683     }
1684 
1685     return ret;
1686 }
1687 
1688 
1689 #define DEV_PREFIX  "/dev/"
1690 
1691 /*
1692  * Solaris specific DLPI code to get hardware address from a device.
1693  * Unfortunately, at least up to Solaris X, you have to have special


1703     struct strbuf msg;
1704     char buf[128];
1705     int flags = 0;
1706 
1707     // Device is in /dev.  e.g.: /dev/bge0
1708     strcpy(style1dev, DEV_PREFIX);
1709     strcat(style1dev, ifname);
1710     if ((fd = open(style1dev, O_RDWR)) < 0) {
1711          // Can't open it. We probably are missing the privilege.
1712          // We'll have to try something else
1713          return 0;
1714     }
1715 
1716     dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
1717     dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
1718 
1719     msg.buf = (char *)&dlpareq;
1720     msg.len = DL_PHYS_ADDR_REQ_SIZE;
1721 
1722     if (putmsg(fd, &msg, NULL, 0) < 0) {
1723         JNU_ThrowByNameWithMessageAndLastError
1724             (env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
1725         return -1;
1726     }
1727 
1728     dlpaack = (dl_phys_addr_ack_t *)buf;
1729 
1730     msg.buf = (char *)buf;
1731     msg.len = 0;
1732     msg.maxlen = sizeof (buf);
1733     if (getmsg(fd, &msg, NULL, &flags) < 0) {
1734         JNU_ThrowByNameWithMessageAndLastError
1735             (env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
1736         return -1;
1737     }
1738 
1739     if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
1740         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1741                         "Couldn't obtain phys addr\n");
1742         return -1;
1743     }
1744 
1745     memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
1746     return dlpaack->dl_addr_length;
1747 }
1748 
1749 /*
1750  * Gets the Hardware address (usually MAC address) for the named interface.
1751  * On return puts the data in buf, and returns the length, in byte, of the
1752  * MAC address. Returns -1 if there is no hardware address on that interface.
1753  */
1754 static int getMacAddress
1755   (JNIEnv *env, int sock, const char *ifname, const struct in_addr* addr,


1799          }
1800 
1801          memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
1802     }
1803 
1804     // All bytes to 0 means no hardware address.
1805     for (i = 0; i < len; i++) {
1806       if (buf[i] != 0)
1807          return len;
1808     }
1809 
1810     return -1;
1811 }
1812 
1813 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1814     struct lifreq if2;
1815     memset((char *)&if2, 0, sizeof(if2));
1816     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1817 
1818     if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
1819         JNU_ThrowByNameWithMessageAndLastError
1820             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
1821         return -1;
1822     }
1823 
1824     return if2.lifr_mtu;
1825 }
1826 
1827 static int getFlags(int sock, const char *ifname, int *flags) {
1828     struct lifreq if2;
1829     memset((char *)&if2, 0, sizeof(if2));
1830     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
1831 
1832     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
1833         return -1;
1834     }
1835 
1836     *flags = if2.lifr_flags;
1837     return 0;
1838 }
1839 
1840 
1841 #endif  /* __solaris__ */
1842 
1843 
1844 /** BSD **/
1845 #ifdef _ALLBSD_SOURCE
1846 
1847 /*
1848  * Opens a socket for further ioct calls. Tries AF_INET socket first and
1849  * if it falls return AF_INET6 socket.
1850  */
1851 #ifdef AF_INET6
1852 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1853     int sock;
1854     struct ifreq if2;
1855 
1856      if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1857          if (errno == EPROTONOSUPPORT) {
1858               if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1859                  JNU_ThrowByNameWithMessageAndLastError
1860                      (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1861                  return -1;
1862               }
1863          } else { // errno is not NOSUPPORT
1864              JNU_ThrowByNameWithMessageAndLastError
1865                  (env, JNU_JAVANETPKG "SocketException", "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         JNU_ThrowByNameWithMessageAndLastError
1887             (env, JNU_JAVANETPKG "SocketException", "getifaddrs() 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 


1928             break;
1929     for (; bit != 0; bit--)
1930         if (name[byte] & (1 << bit))
1931             return (0);
1932     byte++;
1933     for (; byte < size; byte++)
1934         if (name[byte])
1935             return (0);
1936     return prefix;
1937 }
1938 
1939 /*
1940  * Enumerates and returns all IPv6 interfaces on BSD.
1941  */
1942 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1943     struct ifaddrs *ifa, *origifa;
1944     struct sockaddr_in6 *sin6;
1945     struct in6_ifreq ifr6;
1946 
1947     if (getifaddrs(&origifa) != 0) {
1948         JNU_ThrowByNameWithMessageAndLastError
1949             (env, JNU_JAVANETPKG "SocketException", "getifaddrs() failed");
1950         return ifs;
1951     }
1952 
1953     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1954 
1955         // Skip non-AF_INET6 entries.
1956         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
1957             continue;
1958 
1959         memset(&ifr6, 0, sizeof(ifr6));
1960         strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
1961         memcpy(&ifr6.ifr_addr, ifa->ifa_addr,
1962                MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
1963 
1964         if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
1965             JNU_ThrowByNameWithMessageAndLastError
1966                 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFNETMASK_IN6) failed");
1967             freeifaddrs(origifa);
1968             freeif(ifs);
1969             return NULL;
1970         }
1971 
1972         // Add to the list.
1973         sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
1974         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6,
1975             (short)prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
1976 
1977         // If an exception occurred then free the list.
1978         if ((*env)->ExceptionOccurred(env)) {
1979             freeifaddrs(origifa);
1980             freeif(ifs);
1981             return NULL;
1982         }
1983     }
1984 
1985     // Free socket and ifaddrs buffer
1986     freeifaddrs(origifa);


2005     // Try to get the interface index using BSD specific if_nametoindex
2006     int index = if_nametoindex(name);
2007     return (index == 0) ? -1 : index;
2008 #endif
2009 }
2010 
2011 /*
2012  * Returns the IPv4 broadcast address of a named interface, if it exists.
2013  * Returns 0 if it doesn't have one.
2014  */
2015 static struct sockaddr *getBroadcast
2016   (JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store)
2017 {
2018     struct sockaddr *ret = NULL;
2019     struct ifreq if2;
2020     memset((char *)&if2, 0, sizeof(if2));
2021     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2022 
2023     // Make sure the interface does have a broadcast address
2024     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
2025         JNU_ThrowByNameWithMessageAndLastError
2026             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFFLAGS) failed");
2027         return ret;
2028     }
2029 
2030     if (if2.ifr_flags & IFF_BROADCAST) {
2031         // It does, let's retrieve it
2032         if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
2033             JNU_ThrowByNameWithMessageAndLastError
2034                 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFBRDADDR) failed");
2035             return ret;
2036         }
2037 
2038         ret = brdcast_store;
2039         memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
2040     }
2041 
2042     return ret;
2043 }
2044 
2045 /*
2046  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
2047  * interface, if it has one, otherwise return -1.
2048  */
2049 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
2050     unsigned int mask;
2051     short ret;
2052     struct ifreq if2;
2053     memset((char *)&if2, 0, sizeof(if2));
2054     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2055 
2056     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
2057         JNU_ThrowByNameWithMessageAndLastError
2058             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFNETMASK) failed");
2059         return -1;
2060     }
2061 
2062     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
2063     ret = 0;
2064     while (mask) {
2065        mask <<= 1;
2066        ret++;
2067     }
2068 
2069     return ret;
2070 }
2071 
2072 /*
2073  * Gets the Hardware address (usually MAC address) for the named interface.
2074  * return puts the data in buf, and returns the length, in byte, of the
2075  * MAC address. Returns -1 if there is no hardware address on that interface.
2076  */
2077 static int getMacAddress
2078   (JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr,


2093                 // Check the address is the correct length
2094                 if (sadl->sdl_alen == ETHER_ADDR_LEN) {
2095                     memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
2096                     freeifaddrs(ifa0);
2097                     return ETHER_ADDR_LEN;
2098                 }
2099             }
2100         }
2101         freeifaddrs(ifa0);
2102     }
2103 
2104     return -1;
2105 }
2106 
2107 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
2108     struct ifreq if2;
2109     memset((char *)&if2, 0, sizeof(if2));
2110     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2111 
2112     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
2113         JNU_ThrowByNameWithMessageAndLastError
2114             (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
2115         return -1;
2116     }
2117 
2118     return  if2.ifr_mtu;
2119 }
2120 
2121 static int getFlags(int sock, const char *ifname, int *flags) {
2122     struct ifreq if2;
2123     int ret = -1;
2124     memset((char *)&if2, 0, sizeof(if2));
2125     strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
2126 
2127     if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
2128         return -1;
2129     }
2130 
2131     if (sizeof(if2.ifr_flags) == sizeof(short)) {
2132         *flags = (if2.ifr_flags & 0xffff);
2133     } else {
2134         *flags = if2.ifr_flags;
< prev index next >