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;
|