/* * Enumerates and returns all IPv6 interfaces on Solaris */ static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) { int sock; struct lifconf ifc; struct lifreq *ifr; int n; char *buf; struct lifnum numifs; unsigned bufsize; sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0); if (sock < 0) { NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Failed to create IPv6 socket"); return ifs; } /* * Get the interface count */ numifs.lifn_family = AF_UNSPEC; numifs.lifn_flags = 0; if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) { NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed"); close(sock); return ifs; } /* * Enumerate the interface configurations */ bufsize = numifs.lifn_count * sizeof (struct lifreq); buf = (char *)malloc(bufsize); if (!buf) { JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); (void) close(sock); return ifs; } ifc.lifc_family = AF_UNSPEC; ifc.lifc_flags = 0; ifc.lifc_len = bufsize; ifc.lifc_buf = buf; if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) { NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed"); close(sock); free(buf); return ifs; } /* * Iterate through each interface */ ifr = ifc.lifc_req; for (n=0; n<numifs.lifn_count; n++, ifr++) { int index = -1; struct lifreq if2; /* * Ignore non-IPv6 addresses */ if (ifr->lifr_addr.ss_family != AF_INET6) { continue; } /* * Get the index */ memset((char *)&if2, 0, sizeof(if2)); strcpy(if2.lifr_name, ifr->lifr_name); if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) >= 0) { index = if2.lifr_index; } /* add to the list */ ifs = addif(env, ifs, ifr->lifr_name, index, AF_INET6, (struct sockaddr *)&(ifr->lifr_addr), sizeof(struct sockaddr_in6)); /* * If an exception occurred we return */ if ((*env)->ExceptionOccurred(env)) { close(sock); free(buf); return ifs; } } close(sock); free(buf); return ifs; }
/* * Create the marker file descriptor by establishing a loopback connection * which we shutdown but do not close the fd. The result is an fd that * can be used for read/write. */ static int getMarkerFD() { int server_fd, child_fd, connect_fd; SOCKADDR him; int type, len, port; type = AF_INET; #ifdef AF_INET6 if (ipv6_available()) { type = AF_INET6; } #endif /* * Create listener on any port */ server_fd = JVM_Socket(type, SOCK_STREAM, 0); if (server_fd < 0) { return -1; } if (JVM_Listen(server_fd, 1) == -1) { JVM_SocketClose(server_fd); return -1; } len = SOCKADDR_LEN; if (JVM_GetSockName(server_fd, (struct sockaddr *)&him, &len) == -1) { JVM_SocketClose(server_fd); return -1; } port = NET_GetPortFromSockaddr((struct sockaddr *)&him); /* * Establish connection from client socket. * Server is bound to 0.0.0.0/X or ::/X * We connect to 127.0.0.1/X or ::1/X */ #ifdef AF_INET6 if (ipv6_available()) { struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)&him; jbyte caddr[16]; memset((char *) caddr, 0, 16); caddr[15] = 1; memset((char *)him6, 0, sizeof(struct sockaddr_in6)); memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) ); him6->sin6_port = htons((short) port); him6->sin6_family = AF_INET6; len = sizeof(struct sockaddr_in6) ; } else #endif /* AF_INET6 */ { struct sockaddr_in *him4 = (struct sockaddr_in*)&him; memset((char *) him4, 0, sizeof(struct sockaddr_in)); him4->sin_port = htons((short) port); him4->sin_addr.s_addr = (uint32_t) htonl(0x7f000001); him4->sin_family = AF_INET; len = sizeof(struct sockaddr_in); } connect_fd = JVM_Socket(type, SOCK_STREAM, 0); if (connect_fd < 0) { JVM_SocketClose(server_fd); return -1; } if (JVM_Connect(connect_fd, (struct sockaddr *) &him, len) == -1) { JVM_SocketClose(server_fd); JVM_SocketClose(connect_fd); return -1; } /* * Server accepts connection - do in in non-blocking mode to avoid * hanging if there's an error (should never happen!!!) */ SET_NONBLOCKING(server_fd); len = SOCKADDR_LEN; child_fd = JVM_Accept(server_fd, (struct sockaddr *)&him, (jint *)&len); if (child_fd == -1) { JVM_SocketClose(server_fd); JVM_SocketClose(connect_fd); return -1; } /* * Finally shutdown connect_fd (any reads to this fd will get * EOF; any writes will get an error). */ JVM_SocketShutdown(connect_fd, 2); JVM_SocketClose(child_fd); JVM_SocketClose(server_fd); return connect_fd; }
/* * Enumerates and returns all IPv4 interfaces */ static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs) { int sock; struct ifconf ifc; struct ifreq *ifreqP; char *buf; int numifs; unsigned i; unsigned bufsize; sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { /* * If EPROTONOSUPPORT is returned it means we don't have * IPv4 support so don't throw an exception. */ if (errno != EPROTONOSUPPORT) { NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed"); } return ifs; } #ifdef __linux__ /* need to do a dummy SIOCGIFCONF to determine the buffer size. * SIOCGIFCOUNT doesn't work */ ifc.ifc_buf = NULL; if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); close(sock); return ifs; } bufsize = ifc.ifc_len; #else if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) { NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFNUM failed"); close(sock); return ifs; } bufsize = numifs * sizeof (struct ifreq); #endif /* __linux__ */ buf = (char *)malloc(bufsize); if (!buf) { JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); (void) close(sock); return ifs; } ifc.ifc_len = bufsize; ifc.ifc_buf = buf; if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); (void) close(sock); (void) free(buf); return ifs; } /* * Iterate through each interface */ ifreqP = ifc.ifc_req; for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) { int index; struct ifreq if2; memset((char *)&if2, 0, sizeof(if2)); strcpy(if2.ifr_name, ifreqP->ifr_name); /* * Try to get the interface index * (Not supported on Solaris 2.6 or 7) */ if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) >= 0) { index = if2.ifr_index; } else { index = -1; } /* * Add to the list */ ifs = addif(env, ifs, ifreqP->ifr_name, index, AF_INET, (struct sockaddr *)&(ifreqP->ifr_addr), sizeof(struct sockaddr_in)); /* * If an exception occurred then free the list */ if ((*env)->ExceptionOccurred(env)) { close(sock); free(buf); freeif(ifs); return NULL; } } /* * Free socket and buffer */ close(sock); free(buf); return ifs; }