/* * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/ #include <arpa/inet.h> #include <errno.h> #include <net/if.h> #include <net/if_arp.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h>
// search the list of interfaces based on index
curr = ifs; while (curr != NULL) { if (index == curr->index) { break;
}
curr = curr->next;
}
// if found create a NetworkInterface if (curr != NULL) {
obj = createNetworkInterface(env, curr);
}
// release the interface list
freeif(ifs);
return obj;
}
// Return the interface in ifs that iaObj is bound to, if any - otherwise NULL static netif* find_bound_interface(JNIEnv *env, netif* ifs, jobject iaObj, int family) {
netif* curr = ifs; while (curr != NULL) {
netaddr *addrP = curr->addr;
// iterate through each address on the interface while (addrP != NULL) {
if (family == addrP->family) { if (family == AF_INET) { int address1 = htonl(
((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr); int address2 = getInetAddress_addr(env, iaObj); if ((*env)->ExceptionCheck(env)) { return NULL;
} if (address1 == address2) { return curr;
}
} elseif (family == AF_INET6) {
jbyte *bytes = (jbyte *)&(
((struct sockaddr_in6*)addrP->addr)->sin6_addr);
jbyte caddr[16]; int i; unsignedint scopeid;
getInet6Address_ipaddress(env, iaObj, (char *)caddr);
scopeid = (unsignedint)getInet6Address_scopeid(env, iaObj); if (scopeid != 0 && scopeid != ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id) break;
i = 0; while (i < 16) { if (caddr[i] != bytes[i]) { break;
}
i++;
} if (i >= 16) { return curr;
}
}
}
if ((*env)->ExceptionOccurred(env)) { goto cleanup;
}
} if (find_bound_interface(env, ifs, iaObj, family) != NULL)
bound = JNI_TRUE;
} elseif (ipv6_available()) { // If IPv6 is available then enumerate IPv6 addresses. // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true, // so we have to call ipv6_available()
sock = openSocket(env, AF_INET6); if (sock < 0) { return JNI_FALSE;
}
// count the interfaces
ifCount = 0;
curr = ifs; while (curr != NULL) {
ifCount++;
curr = curr->next;
}
// allocate a NetworkInterface array
netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL); if (netIFArr == NULL) {
freeif(ifs); return NULL;
}
// iterate through the interfaces, create a NetworkInterface instance // for each array element and populate the object
curr = ifs;
arr_index = 0; while (curr != NULL) {
jobject netifObj;
// see if there is any virtual interface attached to this one.
child_count = 0;
childP = ifs->childs; while (childP) {
child_count++;
childP = childP->next;
}
if ((*env)->ExceptionOccurred(env)) {
freeif(ifs); return NULL;
}
}
// If IPv6 is available then enumerate IPv6 addresses. // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true, // so we have to call ipv6_available() if (ipv6_available()) {
sock = openSocket(env, AF_INET6); if (sock < 0) {
freeif(ifs); return NULL;
}
static netif *addif(JNIEnv *env, int sock, constchar *if_name, netif *ifs, struct sockaddr *ifr_addrP, struct sockaddr *ifr_broadaddrP, int family, short prefix)
{
netif *currif = ifs, *parent;
netaddr *addrP; char name[IFNAMESIZE], vname[IFNAMESIZE]; char *name_colonP; int isVirtual = 0; int addr_size;
// If the interface name is a logical interface then we remove the unit // number so that we have the physical interface (eg: hme0:1 -> hme0). // NetworkInterface currently doesn't have any concept of physical vs. // logical interfaces.
strncpy(name, if_name, IFNAMESIZE);
name[IFNAMESIZE - 1] = '\0';
*vname = 0;
// Create and populate the netaddr node. If allocation fails // return an un-updated list.
// Deal with virtual interface with colon notation e.g. eth0:1
name_colonP = strchr(name, ':'); if (name_colonP != NULL) { int flags = 0; // This is a virtual interface. If we are able to access the parent // we need to create a new entry if it doesn't exist yet *and* update // the 'parent' interface with the new records.
*name_colonP = 0; if (getFlags(sock, name, &flags) < 0 || flags < 0) { // failed to access parent interface do not create parent. // We are a virtual interface with no parent.
isVirtual = 1;
*name_colonP = ':';
} else { // Got access to parent, so create it if necessary. // Save original name to vname and truncate name by ':'
memcpy(vname, name, sizeof(vname));
vname[name_colonP - name] = ':';
}
}
// Check if this is a "new" interface. Use the interface name for // matching because index isn't supported on Solaris 2.6 & 7. while (currif != NULL) { if (strcmp(name, currif->name) == 0) { break;
}
currif = currif->next;
}
// If "new" then create a netif structure and insert it into the list. if (currif == NULL) {
CHECKED_MALLOC3(currif, netif *, sizeof(netif) + IFNAMESIZE);
currif->name = (char *)currif + sizeof(netif);
strncpy(currif->name, name, IFNAMESIZE);
currif->name[IFNAMESIZE - 1] = '\0';
currif->index = getIndex(sock, name);
currif->addr = NULL;
currif->childs = NULL;
currif->virtual = isVirtual;
currif->next = ifs;
ifs = currif;
}
// Finally insert the address on the interface
addrP->next = currif->addr;
currif->addr = addrP;
parent = currif;
// Deal with the virtual interface now. if (vname[0]) {
netaddr *tmpaddr;
currif = parent->childs;
while (currif != NULL) { if (strcmp(vname, currif->name) == 0) { break;
}
currif = currif->next;
}
/* * Determines the prefix value for an AF_INET subnet address.
*/ staticshort translateIPv4AddressToPrefix(struct sockaddr_in *addr) { short prefix = 0; unsignedint mask; if (addr == NULL) { return 0;
}
mask = ntohl(addr->sin_addr.s_addr); while (mask) {
mask <<= 1;
prefix++;
} return prefix;
}
/* * Determines the prefix value for an AF_INET6 subnet address.
*/ staticshort translateIPv6AddressToPrefix(struct sockaddr_in6 *addr) { short prefix = 0;
u_char *addrBytes; if (addr == NULL) { return 0;
}
addrBytes = (u_char *)&(addr->sin6_addr); unsignedint byte, bit;
for (byte = 0; byte < sizeof(struct in6_addr); byte++, prefix += 8) { if (addrBytes[byte] != 0xff) { break;
}
} if (byte != sizeof(struct in6_addr)) { for (bit = 7; bit != 0; bit--, prefix++) { if (!(addrBytes[byte] & (1 << bit))) { break;
}
} for (; bit != 0; bit--) { if (addrBytes[byte] & (1 << bit)) {
prefix = 0; break;
}
} if (prefix > 0) {
byte++; for (; byte < sizeof(struct in6_addr); byte++) { if (addrBytes[byte]) {
prefix = 0;
}
}
}
}
return prefix;
}
/* * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
*/ staticint openSocket(JNIEnv *env, int proto) { int sock;
if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) { // If we lack support for this address family or protocol, // don't throw an exception. if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Socket creation failed");
} return -1;
}
return sock;
}
/** Linux **/ #ifdefined(__linux__)
/* * Opens a socket for further ioctl calls. Tries AF_INET socket first and * if it fails return AF_INET6 socket.
*/ staticint openSocketWithFallback(JNIEnv *env, constchar *ifname) { int sock;
/* * Gets the Hardware address (usually MAC address) for the named interface. * On return puts the data in buf, and returns the length, in byte, of the * MAC address. Returns -1 if there is no hardware address on that interface.
*/ staticint getMacAddress
(JNIEnv *env, constchar *ifname, conststruct in_addr *addr, unsignedchar *buf)
{ struct ifreq ifr; int i, sock;
/* seems getkerninfo is guarded by _KERNEL in the system headers */ /* see net/proto_uipc.h */ int getkerninfo(int, char *, int *, int32long64_t);
/* * Opens a socket for further ioctl calls. Tries AF_INET socket first and * if it fails return AF_INET6 socket.
*/ staticint openSocketWithFallback(JNIEnv *env, constchar *ifname) { int sock;
/* * Enumerates and returns all IPv4 interfaces on AIX.
*/ static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { struct ifconf ifc; struct ifreq *ifreqP; char *buf = NULL; unsigned i;
// call SIOCGSIZIFCONF to get the size of SIOCGIFCONF buffer if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed"); return ifs;
}
// call CSIOCGIFCONF instead of SIOCGIFCONF where interface // records will always have sizeof(struct ifreq) length. // Be aware that only IPv4 data is complete this way.
CHECKED_MALLOC3(buf, char *, ifc.ifc_len);
ifc.ifc_buf = buf; if (ioctl(sock, CSIOCGIFCONF, (char *)&ifc) < 0) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "ioctl(CSIOCGIFCONF) failed");
free(buf); return ifs;
}
// iterate through each interface
ifreqP = ifc.ifc_req; for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) { struct sockaddr addr, broadaddr, *broadaddrP = NULL; short prefix = 0;
// ignore non IPv4 addresses if (ifreqP->ifr_addr.sa_family != AF_INET) { continue;
}
// save socket address
memcpy(&addr, &(ifreqP->ifr_addr), sizeof(struct sockaddr));
// determine broadcast address, if applicable if ((ioctl(sock, SIOCGIFFLAGS, ifreqP) == 0) &&
ifreqP->ifr_flags & IFF_BROADCAST) {
// restore socket address to ifreqP
memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr));
// set scope ID to interface index
((struct sockaddr_in6 *)&(ifreqP->ifr_addr))->sin6_scope_id =
getIndex(sock, ifreqP->ifr_name);
// add interface to the list
ifs = addif(env, sock, ifreqP->ifr_name, ifs,
(struct sockaddr *)&(ifreqP->ifr_addr),
NULL, AF_INET6, prefix);
// if an exception occurred then free the list if ((*env)->ExceptionOccurred(env)) {
free(buf);
freeif(ifs); return NULL;
}
}
// free buffer
free(buf); return ifs;
}
/* * Try to get the interface index.
*/ staticint getIndex(int sock, constchar *name) { int index = if_nametoindex(name); return (index == 0) ? -1 : index;
}
/* * Gets the Hardware address (usually MAC address) for the named interface. * On return puts the data in buf, and returns the length, in byte, of the * MAC address. Returns -1 if there is no hardware address on that interface.
*/ staticint getMacAddress
(JNIEnv *env, constchar *ifname, conststruct in_addr *addr, unsignedchar *buf)
{ int size; struct kinfo_ndd *nddp; void *end;
/* * Opens a socket for further ioctl calls. Tries AF_INET socket first and * if it fails return AF_INET6 socket.
*/ staticint openSocketWithFallback(JNIEnv *env, constchar *ifname) { int sock;
for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) { struct sockaddr *broadaddrP = NULL;
// ignore non IPv4 addresses if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET) continue;
// set ifa_broadaddr, if there is one if ((ifa->ifa_flags & IFF_POINTOPOINT) == 0 &&
ifa->ifa_flags & IFF_BROADCAST) {
broadaddrP = ifa->ifa_dstaddr;
}
// add interface to the list
ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr,
broadaddrP, AF_INET,
translateIPv4AddressToPrefix((struct sockaddr_in *)
ifa->ifa_netmask));
// if an exception occurred then free the list if ((*env)->ExceptionOccurred(env)) {
freeifaddrs(origifa);
freeif(ifs); return NULL;
}
}
for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) { // ignore non IPv6 addresses if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6) continue;
// set scope ID to interface index
((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id =
getIndex(sock, ifa->ifa_name);
// add interface to the list
ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, NULL,
AF_INET6,
translateIPv6AddressToPrefix((struct sockaddr_in6 *)
ifa->ifa_netmask));
// if an exception occurred then free the list if ((*env)->ExceptionOccurred(env)) {
freeifaddrs(origifa);
freeif(ifs); return NULL;
}
}
/* * Gets the Hardware address (usually MAC address) for the named interface. * On return puts the data in buf, and returns the length, in byte, of the * MAC address. Returns -1 if there is no hardware address on that interface.
*/ staticint getMacAddress
(JNIEnv *env, constchar *ifname, conststruct in_addr *addr, unsignedchar *buf)
{ struct ifaddrs *ifa0, *ifa; struct sockaddr *saddr; int i;
// grab the interface list if (!getifaddrs(&ifa0)) { // cycle through the interfaces for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
saddr = ifa->ifa_addr; if (saddr != NULL) { // link layer contains the MAC address if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) { struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr; // check the address has the correct length if (sadl->sdl_alen == ETHER_ADDR_LEN) {
memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
freeifaddrs(ifa0); return ETHER_ADDR_LEN;
}
}
}
}
freeifaddrs(ifa0);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.87Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.