53 #ifndef NI_MAXHOST
54 #define NI_MAXHOST 1025
55 #endif
56
57
58 /************************************************************************
59 * Inet6AddressImpl
60 */
61
62 /*
63 * Class: java_net_Inet6AddressImpl
64 * Method: getLocalHostName
65 * Signature: ()Ljava/lang/String;
66 */
67 JNIEXPORT jstring JNICALL
68 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
69 int ret;
70 char hostname[NI_MAXHOST+1];
71
72 hostname[0] = '\0';
73 ret = JVM_GetHostName(hostname, sizeof(hostname));
74 if (ret) {
75 /* Something went wrong, maybe networking is not setup? */
76 strcpy(hostname, "localhost");
77 } else {
78 // ensure null-terminated
79 hostname[NI_MAXHOST] = '\0';
80 }
81
82 #if defined(__solaris__) && defined(AF_INET6)
83 if (ret == 0) {
84 /* Solaris doesn't want to give us a fully qualified domain name.
85 * We do a reverse lookup to try and get one. This works
86 * if DNS occurs before NIS in /etc/resolv.conf, but fails
87 * if NIS comes first (it still gets only a partial name).
88 * We use thread-safe system calls.
89 */
90 struct addrinfo hints, *res;
91 int error;
92
93 memset(&hints, 0, sizeof(hints));
94 hints.ai_flags = AI_CANONNAME;
123 lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
124 {
125 jobjectArray result = NULL;
126 char myhostname[NI_MAXHOST+1];
127 struct ifaddrs *ifa = NULL;
128 int familyOrder = 0;
129 int count = 0, i, j;
130 int addrs4 = 0, addrs6 = 0, numV4Loopbacks = 0, numV6Loopbacks = 0;
131 jboolean includeLoopback = JNI_FALSE;
132 jobject name;
133
134 initInetAddressIDs(env);
135 JNU_CHECK_EXCEPTION_RETURN(env, NULL);
136
137 /* If the requested name matches this host's hostname, return IP addresses
138 * from all attached interfaces. (#2844683 et al) This prevents undesired
139 * PPP dialup, but may return addresses that don't actually correspond to
140 * the name (if the name actually matches something in DNS etc.
141 */
142 myhostname[0] = '\0';
143 if (JVM_GetHostName(myhostname, NI_MAXHOST)) {
144 /* Something went wrong, maybe networking is not setup? */
145 return NULL;
146 }
147 myhostname[NI_MAXHOST] = '\0';
148
149 if (strcmp(myhostname, hostname) != 0) {
150 // Non-self lookup
151 return NULL;
152 }
153
154 if (getifaddrs(&ifa) != 0) {
155 NET_ThrowNew(env, errno, "Can't get local interface addresses");
156 return NULL;
157 }
158
159 name = (*env)->NewStringUTF(env, hostname);
160 CHECK_NULL_RETURN(name, NULL);
161
162 /* Iterate over the interfaces, and total up the number of IPv4 and IPv6
163 * addresses we have. Also keep a count of loopback addresses. We need to
694 /*
695 * If a network interface was specified, let's create the address
696 * for it.
697 */
698 if (!(IS_NULL(ifArray))) {
699 memset((void *) caddr, 0, 16);
700 memset((void *) &inf6, 0, sizeof(inf6));
701 (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
702 memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
703 inf6.sin6_family = AF_INET6;
704 inf6.sin6_scope_id = if_scope;
705 netif = &inf6;
706 }
707 /*
708 * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
709 * otherwise we'll try a tcp socket to the Echo port (7).
710 * Note that this is empiric, and not connecting could mean it's blocked
711 * or the echo service has been disabled.
712 */
713
714 fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
715
716 if (fd != -1) { /* Good to go, let's do a ping */
717 return ping6(env, fd, &him6, timeout, netif, ttl);
718 }
719
720 /* No good, let's fall back on TCP */
721 fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0);
722 if (fd == JVM_IO_ERR) {
723 /* note: if you run out of fds, you may not be able to load
724 * the exception class, and get a NoClassDefFoundError
725 * instead.
726 */
727 NET_ThrowNew(env, errno, "Can't create socket");
728 return JNI_FALSE;
729 }
730 if (ttl > 0) {
731 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
732 }
733
734 /*
735 * A network interface was specified, so let's bind to it.
736 */
737 if (netif != NULL) {
738 if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
739 NET_ThrowNew(env, errno, "Can't bind socket");
740 close(fd);
741 return JNI_FALSE;
742 }
743 }
744 SET_NONBLOCKING(fd);
745
746 /* no need to use NET_Connect as non-blocking */
747 him6.sin6_port = htons((short) 7); /* Echo port */
748 connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len);
749
750 /**
751 * connection established or refused immediately, either way it means
752 * we were able to reach the host!
753 */
754 if (connect_rv == 0 || errno == ECONNREFUSED) {
755 close(fd);
756 return JNI_TRUE;
757 } else {
758 int optlen;
759
760 switch (errno) {
761 case ENETUNREACH: /* Network Unreachable */
762 case EAFNOSUPPORT: /* Address Family not supported */
763 case EADDRNOTAVAIL: /* address is not available on the remote machine */
764 #ifdef __linux__
765 case EINVAL:
766 case EHOSTUNREACH:
767 /*
768 * On some Linux versions, when a socket is bound to the
769 * loopback interface, connect will fail and errno will
770 * be set to EINVAL or EHOSTUNREACH. When that happens,
771 * don't throw an exception, just return false.
772 */
773 #endif /* __linux__ */
774 close(fd);
775 return JNI_FALSE;
776 }
777
778 if (errno != EINPROGRESS) {
779 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
780 "connect failed");
781 close(fd);
782 return JNI_FALSE;
783 }
784
785 timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
786
787 if (timeout >= 0) {
788 /* has connection been established */
789 optlen = sizeof(connect_rv);
790 if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
791 &optlen) <0) {
792 connect_rv = errno;
793 }
794 if (connect_rv == 0 || ECONNREFUSED) {
795 close(fd);
796 return JNI_TRUE;
797 }
798 }
799 close(fd);
800 return JNI_FALSE;
801 }
802 #else /* AF_INET6 */
803 return JNI_FALSE;
804 #endif /* AF_INET6 */
805 }
|
53 #ifndef NI_MAXHOST
54 #define NI_MAXHOST 1025
55 #endif
56
57
58 /************************************************************************
59 * Inet6AddressImpl
60 */
61
62 /*
63 * Class: java_net_Inet6AddressImpl
64 * Method: getLocalHostName
65 * Signature: ()Ljava/lang/String;
66 */
67 JNIEXPORT jstring JNICALL
68 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
69 int ret;
70 char hostname[NI_MAXHOST+1];
71
72 hostname[0] = '\0';
73 ret = gethostname(hostname, NI_MAXHOST);
74 if (ret == -1) {
75 /* Something went wrong, maybe networking is not setup? */
76 strcpy(hostname, "localhost");
77 } else {
78 // ensure null-terminated
79 hostname[NI_MAXHOST] = '\0';
80 }
81
82 #if defined(__solaris__) && defined(AF_INET6)
83 if (ret == 0) {
84 /* Solaris doesn't want to give us a fully qualified domain name.
85 * We do a reverse lookup to try and get one. This works
86 * if DNS occurs before NIS in /etc/resolv.conf, but fails
87 * if NIS comes first (it still gets only a partial name).
88 * We use thread-safe system calls.
89 */
90 struct addrinfo hints, *res;
91 int error;
92
93 memset(&hints, 0, sizeof(hints));
94 hints.ai_flags = AI_CANONNAME;
123 lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
124 {
125 jobjectArray result = NULL;
126 char myhostname[NI_MAXHOST+1];
127 struct ifaddrs *ifa = NULL;
128 int familyOrder = 0;
129 int count = 0, i, j;
130 int addrs4 = 0, addrs6 = 0, numV4Loopbacks = 0, numV6Loopbacks = 0;
131 jboolean includeLoopback = JNI_FALSE;
132 jobject name;
133
134 initInetAddressIDs(env);
135 JNU_CHECK_EXCEPTION_RETURN(env, NULL);
136
137 /* If the requested name matches this host's hostname, return IP addresses
138 * from all attached interfaces. (#2844683 et al) This prevents undesired
139 * PPP dialup, but may return addresses that don't actually correspond to
140 * the name (if the name actually matches something in DNS etc.
141 */
142 myhostname[0] = '\0';
143 if (gethostname(myhostname, NI_MAXHOST) == -1) {
144 /* Something went wrong, maybe networking is not setup? */
145 return NULL;
146 }
147 myhostname[NI_MAXHOST] = '\0';
148
149 if (strcmp(myhostname, hostname) != 0) {
150 // Non-self lookup
151 return NULL;
152 }
153
154 if (getifaddrs(&ifa) != 0) {
155 NET_ThrowNew(env, errno, "Can't get local interface addresses");
156 return NULL;
157 }
158
159 name = (*env)->NewStringUTF(env, hostname);
160 CHECK_NULL_RETURN(name, NULL);
161
162 /* Iterate over the interfaces, and total up the number of IPv4 and IPv6
163 * addresses we have. Also keep a count of loopback addresses. We need to
694 /*
695 * If a network interface was specified, let's create the address
696 * for it.
697 */
698 if (!(IS_NULL(ifArray))) {
699 memset((void *) caddr, 0, 16);
700 memset((void *) &inf6, 0, sizeof(inf6));
701 (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
702 memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
703 inf6.sin6_family = AF_INET6;
704 inf6.sin6_scope_id = if_scope;
705 netif = &inf6;
706 }
707 /*
708 * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
709 * otherwise we'll try a tcp socket to the Echo port (7).
710 * Note that this is empiric, and not connecting could mean it's blocked
711 * or the echo service has been disabled.
712 */
713
714 fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
715
716 if (fd != -1) { /* Good to go, let's do a ping */
717 return ping6(env, fd, &him6, timeout, netif, ttl);
718 }
719
720 /* No good, let's fall back on TCP */
721 fd = socket(AF_INET6, SOCK_STREAM, 0);
722 if (fd == -1) {
723 /* note: if you run out of fds, you may not be able to load
724 * the exception class, and get a NoClassDefFoundError
725 * instead.
726 */
727 NET_ThrowNew(env, errno, "Can't create socket");
728 return JNI_FALSE;
729 }
730 if (ttl > 0) {
731 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
732 }
733
734 /*
735 * A network interface was specified, so let's bind to it.
736 */
737 if (netif != NULL) {
738 if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
739 NET_ThrowNew(env, errno, "Can't bind socket");
740 close(fd);
741 return JNI_FALSE;
742 }
743 }
744 SET_NONBLOCKING(fd);
745
746 him6.sin6_port = htons((short) 7); /* Echo port */
747 connect_rv = NET_Connect(fd, (struct sockaddr *)&him6, len);
748
749 /**
750 * connection established or refused immediately, either way it means
751 * we were able to reach the host!
752 */
753 if (connect_rv == 0 || errno == ECONNREFUSED) {
754 close(fd);
755 return JNI_TRUE;
756 } else {
757 socklen_t optlen = (socklen_t)sizeof(connect_rv);
758
759 switch (errno) {
760 case ENETUNREACH: /* Network Unreachable */
761 case EAFNOSUPPORT: /* Address Family not supported */
762 case EADDRNOTAVAIL: /* address is not available on the remote machine */
763 #ifdef __linux__
764 case EINVAL:
765 case EHOSTUNREACH:
766 /*
767 * On some Linux versions, when a socket is bound to the
768 * loopback interface, connect will fail and errno will
769 * be set to EINVAL or EHOSTUNREACH. When that happens,
770 * don't throw an exception, just return false.
771 */
772 #endif /* __linux__ */
773 close(fd);
774 return JNI_FALSE;
775 }
776
777 if (errno != EINPROGRESS) {
778 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
779 "connect failed");
780 close(fd);
781 return JNI_FALSE;
782 }
783
784 timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
785
786 if (timeout >= 0) {
787 /* has connection been established */
788 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
789 &optlen) <0) {
790 connect_rv = errno;
791 }
792 if (connect_rv == 0 || ECONNREFUSED) {
793 close(fd);
794 return JNI_TRUE;
795 }
796 }
797 close(fd);
798 return JNI_FALSE;
799 }
800 #else /* AF_INET6 */
801 return JNI_FALSE;
802 #endif /* AF_INET6 */
803 }
|