Mercurial > hg > openjdk > jdk8u > jdk
changeset 11361:d7cc3225f105 jdk8u72-b11
8141260: isReachable crash in windows xp
Reviewed-by: coffeys, msheppar
author | robm |
---|---|
date | Sat, 28 Nov 2015 00:04:47 +0000 |
parents | e84eb2fd892e |
children | bd2c98bb4695 |
files | src/windows/native/java/net/Inet4AddressImpl.c |
diffstat | 1 files changed, 211 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/src/windows/native/java/net/Inet4AddressImpl.c Mon Nov 30 11:51:55 2015 -0800 +++ b/src/windows/native/java/net/Inet4AddressImpl.c Sat Nov 28 00:04:47 2015 +0000 @@ -292,6 +292,175 @@ } + +static BOOL +WindowsVersionCheck(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) { + OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 }; + DWORDLONG const dwlConditionMask = VerSetConditionMask( + VerSetConditionMask( + VerSetConditionMask( + 0, VER_MAJORVERSION, VER_GREATER_EQUAL), + VER_MINORVERSION, VER_GREATER_EQUAL), + VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + + osvi.dwMajorVersion = wMajorVersion; + osvi.dwMinorVersion = wMinorVersion; + osvi.wServicePackMajor = wServicePackMajor; + + return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; +} + +static BOOL +isVistaSP1OrGreater() { + return WindowsVersionCheck(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1); +} + +static jboolean +wxp_ping4(JNIEnv *env, + jbyteArray addrArray, + jint timeout, + jbyteArray ifArray, + jint ttl) +{ + jint addr; + jbyte caddr[4]; + jint fd; + struct sockaddr_in him; + struct sockaddr_in* netif = NULL; + struct sockaddr_in inf; + int len = 0; + WSAEVENT hEvent; + int connect_rv = -1; + int sz; + + /** + * Convert IP address from byte array to integer + */ + sz = (*env)->GetArrayLength(env, addrArray); + if (sz != 4) { + return JNI_FALSE; + } + memset((char *) &him, 0, sizeof(him)); + memset((char *) caddr, 0, sizeof(caddr)); + (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); + addr = ((caddr[0]<<24) & 0xff000000); + addr |= ((caddr[1] <<16) & 0xff0000); + addr |= ((caddr[2] <<8) & 0xff00); + addr |= (caddr[3] & 0xff); + addr = htonl(addr); + /** + * Socket address + */ + him.sin_addr.s_addr = addr; + him.sin_family = AF_INET; + len = sizeof(him); + + /** + * If a network interface was specified, let's convert its address + * as well. + */ + if (!(IS_NULL(ifArray))) { + memset((char *) caddr, 0, sizeof(caddr)); + (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr); + addr = ((caddr[0]<<24) & 0xff000000); + addr |= ((caddr[1] <<16) & 0xff0000); + addr |= ((caddr[2] <<8) & 0xff00); + addr |= (caddr[3] & 0xff); + addr = htonl(addr); + inf.sin_addr.s_addr = addr; + inf.sin_family = AF_INET; + inf.sin_port = 0; + netif = &inf; + } + + /* + * Can't create a raw socket, so let's try a TCP socket + */ + fd = NET_Socket(AF_INET, SOCK_STREAM, 0); + if (fd == JVM_IO_ERR) { + /* note: if you run out of fds, you may not be able to load + * the exception class, and get a NoClassDefFoundError + * instead. + */ + NET_ThrowNew(env, WSAGetLastError(), "Can't create socket"); + return JNI_FALSE; + } + if (ttl > 0) { + setsockopt(fd, IPPROTO_IP, IP_TTL, (const char *)&ttl, sizeof(ttl)); + } + /* + * A network interface was specified, so let's bind to it. + */ + if (netif != NULL) { + if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket"); + closesocket(fd); + return JNI_FALSE; + } + } + + /* + * Make the socket non blocking so we can use select/poll. + */ + hEvent = WSACreateEvent(); + WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE); + + /* no need to use NET_Connect as non-blocking */ + him.sin_port = htons(7); /* Echo */ + connect_rv = connect(fd, (struct sockaddr *)&him, len); + + /** + * connection established or refused immediately, either way it means + * we were able to reach the host! + */ + if (connect_rv == 0 || WSAGetLastError() == WSAECONNREFUSED) { + WSACloseEvent(hEvent); + closesocket(fd); + return JNI_TRUE; + } else { + int optlen; + + switch (WSAGetLastError()) { + case WSAEHOSTUNREACH: /* Host Unreachable */ + case WSAENETUNREACH: /* Network Unreachable */ + case WSAENETDOWN: /* Network is down */ + case WSAEPFNOSUPPORT: /* Protocol Family unsupported */ + WSACloseEvent(hEvent); + closesocket(fd); + return JNI_FALSE; + } + + if (WSAGetLastError() != WSAEWOULDBLOCK) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", + "connect failed"); + WSACloseEvent(hEvent); + closesocket(fd); + return JNI_FALSE; + } + + timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout); + + /* has connection been established */ + + if (timeout >= 0) { + optlen = sizeof(connect_rv); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv, + &optlen) <0) { + connect_rv = WSAGetLastError(); + } + + if (connect_rv == 0 || connect_rv == WSAECONNREFUSED) { + WSACloseEvent(hEvent); + closesocket(fd); + return JNI_TRUE; + } + } + } + WSACloseEvent(hEvent); + closesocket(fd); + return JNI_FALSE; +} + /** * ping implementation. * Send a ICMP_ECHO_REQUEST packet every second until either the timeout @@ -367,43 +536,48 @@ */ JNIEXPORT jboolean JNICALL Java_java_net_Inet4AddressImpl_isReachable0(JNIEnv *env, jobject this, - jbyteArray addrArray, - jint timeout, - jbyteArray ifArray, - jint ttl) { - jint src_addr = 0; - jint dest_addr = 0; - jbyte caddr[4]; - int sz; + jbyteArray addrArray, + jint timeout, + jbyteArray ifArray, + jint ttl) { + + if (isVistaSP1OrGreater()) { + jint src_addr = 0; + jint dest_addr = 0; + jbyte caddr[4]; + int sz; - /** - * Convert IP address from byte array to integer - */ - sz = (*env)->GetArrayLength(env, addrArray); - if (sz != 4) { - return JNI_FALSE; + /** + * Convert IP address from byte array to integer + */ + sz = (*env)->GetArrayLength(env, addrArray); + if (sz != 4) { + return JNI_FALSE; + } + memset((char *) caddr, 0, sizeof(caddr)); + (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); + dest_addr = ((caddr[0]<<24) & 0xff000000); + dest_addr |= ((caddr[1] <<16) & 0xff0000); + dest_addr |= ((caddr[2] <<8) & 0xff00); + dest_addr |= (caddr[3] & 0xff); + dest_addr = htonl(dest_addr); + + /** + * If a network interface was specified, let's convert its address + * as well. + */ + if (!(IS_NULL(ifArray))) { + memset((char *) caddr, 0, sizeof(caddr)); + (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr); + src_addr = ((caddr[0]<<24) & 0xff000000); + src_addr |= ((caddr[1] <<16) & 0xff0000); + src_addr |= ((caddr[2] <<8) & 0xff00); + src_addr |= (caddr[3] & 0xff); + src_addr = htonl(src_addr); + } + + return ping4(env, src_addr, dest_addr, timeout); + } else { + wxp_ping4(env, addrArray, timeout, ifArray, ttl); } - memset((char *) caddr, 0, sizeof(caddr)); - (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); - dest_addr = ((caddr[0]<<24) & 0xff000000); - dest_addr |= ((caddr[1] <<16) & 0xff0000); - dest_addr |= ((caddr[2] <<8) & 0xff00); - dest_addr |= (caddr[3] & 0xff); - dest_addr = htonl(dest_addr); - - /** - * If a network interface was specified, let's convert its address - * as well. - */ - if (!(IS_NULL(ifArray))) { - memset((char *) caddr, 0, sizeof(caddr)); - (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr); - src_addr = ((caddr[0]<<24) & 0xff000000); - src_addr |= ((caddr[1] <<16) & 0xff0000); - src_addr |= ((caddr[2] <<8) & 0xff00); - src_addr |= (caddr[3] & 0xff); - src_addr = htonl(src_addr); - } - - return ping4(env, src_addr, dest_addr, timeout); }