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

}
Example #2
0
/*
 * 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;
}