< prev index next >

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

Print this page
rev 59383 : [mq]: final

*** 35,50 **** #include <sys/ndd_var.h> #include <sys/kinfo.h> #include <strings.h> #endif - #if defined(__solaris__) - #include <stropts.h> - #include <sys/dlpi.h> - #include <sys/sockio.h> - #endif - #if defined(_ALLBSD_SOURCE) #include <net/ethernet.h> #include <net/if_dl.h> #include <ifaddrs.h> #endif --- 35,44 ----
*** 53,67 **** #include "java_net_InetAddress.h" #if defined(__linux__) #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" - #elif defined(__solaris__) - #ifndef SIOCGLIFHWADDR - #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq) - #endif - #define DEV_PREFIX "/dev/" #endif #ifdef LIFNAMSIZ #define IFNAMESIZE LIFNAMSIZ #else --- 47,56 ----
*** 145,159 **** static int getFlags(int sock, const char *ifname, int *flags); static int getMacAddress(JNIEnv *env, const char *ifname, const struct in_addr *addr, unsigned char *buf); static int getMTU(JNIEnv *env, int sock, const char *ifname); - #if defined(__solaris__) - static int getMacFromDevice(JNIEnv *env, const char *ifname, - unsigned char *retbuf); - #endif - /******************* Java entry points *****************************/ /* * Class: java_net_NetworkInterface * Method: init --- 134,143 ----
*** 1670,2045 **** return 0; } #endif /* _AIX */ - /** Solaris **/ - #if defined(__solaris__) - - /* - * Opens a socket for further ioctl calls. Tries AF_INET socket first and - * if it fails return AF_INET6 socket. - */ - static int openSocketWithFallback(JNIEnv *env, const char *ifname) { - int sock, alreadyV6 = 0; - struct lifreq if2; - - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) { - if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); - return -1; - } - alreadyV6 = 1; - } else { // errno is not NOSUPPORT - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); - return -1; - } - } - - // Solaris requires that we have an IPv6 socket to query an interface - // without an IPv4 address - check it here. POSIX 1 require the kernel to - // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK - // for a device having IPv6 only address but not all devices follow the - // standard so fall back on any error. It's not an ecologically friendly - // gesture but more reliable. - if (!alreadyV6) { - memset((char *)&if2, 0, sizeof(if2)); - strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); - if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) { - close(sock); - if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); - return -1; - } - } - } - - return sock; - } - - /* - * Enumerates and returns all IPv4 interfaces on Solaris. - */ - static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { - struct lifconf ifc; - struct lifreq *ifreqP; - struct lifnum numifs; - char *buf = NULL; - unsigned i; - - // call SIOCGLIFNUM to get the interface count - numifs.lifn_family = AF_INET; - numifs.lifn_flags = 0; - if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed"); - return ifs; - } - - // call SIOCGLIFCONF to enumerate the interfaces - ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq); - CHECKED_MALLOC3(buf, char *, ifc.lifc_len); - ifc.lifc_buf = buf; - ifc.lifc_family = AF_INET; - ifc.lifc_flags = 0; - if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed"); - free(buf); - return ifs; - } - - // iterate through each interface - ifreqP = ifc.lifc_req; - for (i = 0; i < numifs.lifn_count; i++, ifreqP++) { - struct sockaddr addr, *broadaddrP = NULL; - - // ignore non IPv4 addresses - if (ifreqP->lifr_addr.ss_family != AF_INET) { - continue; - } - - // save socket address - memcpy(&addr, &(ifreqP->lifr_addr), sizeof(struct sockaddr)); - - // determine broadcast address, if applicable - if ((ioctl(sock, SIOCGLIFFLAGS, ifreqP) == 0) && - ifreqP->lifr_flags & IFF_BROADCAST) { - - // restore socket address to ifreqP - memcpy(&(ifreqP->lifr_addr), &addr, sizeof(struct sockaddr)); - - // query broadcast address and set pointer to it - if (ioctl(sock, SIOCGLIFBRDADDR, ifreqP) == 0) { - broadaddrP = (struct sockaddr *)&(ifreqP->lifr_broadaddr); - } - } - - // add to the list - ifs = addif(env, sock, ifreqP->lifr_name, ifs, - &addr, broadaddrP, AF_INET, (short)ifreqP->lifr_addrlen); - - // if an exception occurred we return immediately - if ((*env)->ExceptionOccurred(env)) { - free(buf); - return ifs; - } - } - - // free buffer - free(buf); - return ifs; - } - - /* - * Enumerates and returns all IPv6 interfaces on Solaris. - */ - static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { - struct lifconf ifc; - struct lifreq *ifreqP; - struct lifnum numifs; - char *buf = NULL; - unsigned i; - - // call SIOCGLIFNUM to get the interface count - numifs.lifn_family = AF_INET6; - numifs.lifn_flags = 0; - if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed"); - return ifs; - } - - // call SIOCGLIFCONF to enumerate the interfaces - ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq); - CHECKED_MALLOC3(buf, char *, ifc.lifc_len); - ifc.lifc_buf = buf; - ifc.lifc_family = AF_INET6; - ifc.lifc_flags = 0; - if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed"); - free(buf); - return ifs; - } - - // iterate through each interface - ifreqP = ifc.lifc_req; - for (i = 0; i < numifs.lifn_count; i++, ifreqP++) { - - // ignore non IPv6 addresses - if (ifreqP->lifr_addr.ss_family != AF_INET6) { - continue; - } - - // set scope ID to interface index - ((struct sockaddr_in6 *)&(ifreqP->lifr_addr))->sin6_scope_id = - getIndex(sock, ifreqP->lifr_name); - - // add to the list - ifs = addif(env, sock, ifreqP->lifr_name, ifs, - (struct sockaddr *)&(ifreqP->lifr_addr), - NULL, AF_INET6, (short)ifreqP->lifr_addrlen); - - // if an exception occurred we return immediately - if ((*env)->ExceptionOccurred(env)) { - free(buf); - return ifs; - } - } - - // free buffer - free(buf); - return ifs; - } - - /* - * Try to get the interface index. - * (Not supported on Solaris 2.6 or 7) - */ - static int getIndex(int sock, const char *name) { - struct lifreq if2; - memset((char *)&if2, 0, sizeof(if2)); - strncpy(if2.lifr_name, name, sizeof(if2.lifr_name) - 1); - - if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) { - return -1; - } - - return if2.lifr_index; - } - - /* - * Solaris specific DLPI code to get hardware address from a device. - * Unfortunately, at least up to Solaris X, you have to have special - * privileges (i.e. be root). - */ - static int getMacFromDevice - (JNIEnv *env, const char *ifname, unsigned char *retbuf) - { - char style1dev[MAXPATHLEN]; - int fd; - dl_phys_addr_req_t dlpareq; - dl_phys_addr_ack_t *dlpaack; - dl_error_ack_t *dlerack; - struct strbuf msg; - char buf[128]; - int flags = 0; - - // Device is in /dev. e.g.: /dev/bge0 - strcpy(style1dev, DEV_PREFIX); - strcat(style1dev, ifname); - if ((fd = open(style1dev, O_RDWR)) < 0) { - // Can't open it. We probably are missing the privilege. - // We'll have to try something else - return 0; - } - - dlpareq.dl_primitive = DL_PHYS_ADDR_REQ; - dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR; - - msg.buf = (char *)&dlpareq; - msg.len = DL_PHYS_ADDR_REQ_SIZE; - - if (putmsg(fd, &msg, NULL, 0) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "putmsg() failed"); - return -1; - } - - dlpaack = (dl_phys_addr_ack_t *)buf; - - msg.buf = (char *)buf; - msg.len = 0; - msg.maxlen = sizeof (buf); - if (getmsg(fd, &msg, NULL, &flags) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "getmsg() failed"); - return -1; - } - - if (dlpaack->dl_primitive == DL_ERROR_ACK) { - dlerack = (dl_error_ack_t *)buf; - if (dlerack->dl_error_primitive != DL_PHYS_ADDR_REQ) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Couldn't obtain physical address\n"); - return -1; - } - if (dlerack->dl_errno == DL_UNSUPPORTED) { - // fallback to lookup in the ARP table - return 0; - } - } - - if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Couldn't obtain phys addr\n"); - return -1; - } - - memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length); - return dlpaack->dl_addr_length; - } - - /* - * 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. - */ - static int getMacAddress - (JNIEnv *env, const char *ifname, const struct in_addr *addr, - unsigned char *buf) - { - struct lifreq if2; - int len, i, sock; - - if ((sock = openSocketWithFallback(env, ifname)) < 0) { - return -1; - } - - // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails - // try the old way. - memset((char *)&if2, 0, sizeof(if2)); - strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); - - if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) { - struct sockaddr_dl *sp; - sp = (struct sockaddr_dl *)&if2.lifr_addr; - memcpy(buf, &sp->sdl_data[0], sp->sdl_alen); - close(sock); - return sp->sdl_alen; - } - - // On Solaris we have to use DLPI, but it will only work if we have - // privileged access (i.e. root). If that fails, we try a lookup - // in the ARP table, which requires an IPv4 address. - if (((len = getMacFromDevice(env, ifname, buf)) == 0) && (addr != NULL)) { - struct arpreq arpreq; - struct sockaddr_in *sin; - struct sockaddr_in ipAddr; - - len = 6; //??? - - sin = (struct sockaddr_in *)&arpreq.arp_pa; - memset((char *)&arpreq, 0, sizeof(struct arpreq)); - ipAddr.sin_port = 0; - ipAddr.sin_family = AF_INET; - memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr)); - memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); - arpreq.arp_flags= ATF_PUBL; - - if (ioctl(sock, SIOCGARP, &arpreq) < 0) { - close(sock); - return -1; - } - - memcpy(buf, &arpreq.arp_ha.sa_data[0], len); - } - close(sock); - - // all bytes to 0 means no hardware address - for (i = 0; i < len; i++) { - if (buf[i] != 0) - return len; - } - - return -1; - } - - static int getMTU(JNIEnv *env, int sock, const char *ifname) { - struct lifreq if2; - memset((char *)&if2, 0, sizeof(if2)); - strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); - - if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) { - JNU_ThrowByNameWithMessageAndLastError - (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed"); - return -1; - } - - return if2.lifr_mtu; - } - - static int getFlags(int sock, const char *ifname, int *flags) { - struct lifreq if2; - memset((char *)&if2, 0, sizeof(if2)); - strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); - - if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) { - return -1; - } - - *flags = if2.lifr_flags; - return 0; - } - - #endif /* __solaris__ */ - /** BSD **/ #if defined(_ALLBSD_SOURCE) /* * Opens a socket for further ioctl calls. Tries AF_INET socket first and --- 1654,1663 ----
< prev index next >