提交 c872b120 编写于 作者: C chegar

7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)

Reviewed-by: alanb, mduigou
上级 9c787302
......@@ -37,10 +37,6 @@ include FILES_c.gmk
AUTO_FILES_JAVA_DIRS = java/net
ifeq ($(PLATFORM), windows)
# Windows 9x module only needed on 32-bit build
ifeq ($(ARCH_DATA_MODEL), 32)
FILES_c += NetworkInterface_win9x.c
endif
FILES_c += NTLMAuthSequence.c
FILES_c += NetworkInterface_winXP.c
else
......@@ -96,7 +92,9 @@ include $(BUILDDIR)/common/Mapfile-vers.gmk
include $(BUILDDIR)/common/Library.gmk
ifeq ($(PLATFORM), windows)
OTHER_LDLIBS = ws2_32.lib $(JVMLIB)
OTHER_LDLIBS = ws2_32.lib $(JVMLIB) \
secur32.lib iphlpapi.lib delayimp.lib \
/DELAYLOAD:secur32.dll /DELAYLOAD:iphlpapi.dll
else
OTHER_LDLIBS = $(LIBSOCKET) $(LIBNSL) -ldl $(JVMLIB)
endif
......
......@@ -90,6 +90,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
jobjectArray ret = 0;
int retLen = 0;
jboolean preferIPv6Address;
static jfieldID ia_preferIPv6AddressID;
int error=0;
struct addrinfo hints, *res, *resNew = NULL;
......@@ -116,166 +117,163 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
CHECK_NULL_RETURN(hostname, NULL);
if (NET_addrtransAvailable()) {
static jfieldID ia_preferIPv6AddressID;
if (ia_preferIPv6AddressID == NULL) {
jclass c = (*env)->FindClass(env,"java/net/InetAddress");
if (c) {
ia_preferIPv6AddressID =
(*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
}
if (ia_preferIPv6AddressID == NULL) {
jclass c = (*env)->FindClass(env,"java/net/InetAddress");
if (c) {
ia_preferIPv6AddressID =
(*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
}
if (ia_preferIPv6AddressID == NULL) {
JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL;
}
JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL;
}
/* get the address preference */
preferIPv6Address
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
}
/* get the address preference */
preferIPv6Address
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
/* Try once, with our static buffer. */
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC;
/* Try once, with our static buffer. */
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC;
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
error = getaddrinfo(hostname, NULL, &hints, &res);
if (error) {
/* report error */
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
(char *)hostname);
JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL;
} else {
int i = 0;
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
struct addrinfo *itr, *last, *iterator = res;
while (iterator != NULL) {
int skip = 0;
itr = resNew;
while (itr != NULL) {
if (iterator->ai_family == itr->ai_family &&
iterator->ai_addrlen == itr->ai_addrlen) {
if (itr->ai_family == AF_INET) { /* AF_INET */
struct sockaddr_in *addr1, *addr2;
addr1 = (struct sockaddr_in *)iterator->ai_addr;
addr2 = (struct sockaddr_in *)itr->ai_addr;
if (addr1->sin_addr.s_addr ==
addr2->sin_addr.s_addr) {
skip = 1;
if (error) {
/* report error */
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
(char *)hostname);
JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL;
} else {
int i = 0;
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
struct addrinfo *itr, *last, *iterator = res;
while (iterator != NULL) {
int skip = 0;
itr = resNew;
while (itr != NULL) {
if (iterator->ai_family == itr->ai_family &&
iterator->ai_addrlen == itr->ai_addrlen) {
if (itr->ai_family == AF_INET) { /* AF_INET */
struct sockaddr_in *addr1, *addr2;
addr1 = (struct sockaddr_in *)iterator->ai_addr;
addr2 = (struct sockaddr_in *)itr->ai_addr;
if (addr1->sin_addr.s_addr ==
addr2->sin_addr.s_addr) {
skip = 1;
break;
}
} else {
int t;
struct sockaddr_in6 *addr1, *addr2;
addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
addr2 = (struct sockaddr_in6 *)itr->ai_addr;
for (t = 0; t < 16; t++) {
if (addr1->sin6_addr.s6_addr[t] !=
addr2->sin6_addr.s6_addr[t]) {
break;
}
}
if (t < 16) {
itr = itr->ai_next;
continue;
} else {
int t;
struct sockaddr_in6 *addr1, *addr2;
addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
addr2 = (struct sockaddr_in6 *)itr->ai_addr;
for (t = 0; t < 16; t++) {
if (addr1->sin6_addr.s6_addr[t] !=
addr2->sin6_addr.s6_addr[t]) {
break;
}
}
if (t < 16) {
itr = itr->ai_next;
continue;
} else {
skip = 1;
break;
}
skip = 1;
break;
}
} else if (iterator->ai_family != AF_INET &&
iterator->ai_family != AF_INET6) {
/* we can't handle other family types */
skip = 1;
break;
}
itr = itr->ai_next;
} else if (iterator->ai_family != AF_INET &&
iterator->ai_family != AF_INET6) {
/* we can't handle other family types */
skip = 1;
break;
}
if (!skip) {
struct addrinfo *next
= (struct addrinfo*) malloc(sizeof(struct addrinfo));
if (!next) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
ret = NULL;
goto cleanupAndReturn;
}
memcpy(next, iterator, sizeof(struct addrinfo));
next->ai_next = NULL;
if (resNew == NULL) {
resNew = next;
} else {
last->ai_next = next;
}
last = next;
i++;
if (iterator->ai_family == AF_INET) {
inetCount ++;
} else if (iterator->ai_family == AF_INET6) {
inet6Count ++;
}
}
iterator = iterator->ai_next;
}
retLen = i;
iterator = resNew;
i = 0;
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
if (IS_NULL(ret)) {
/* we may have memory to free at the end of this */
goto cleanupAndReturn;
itr = itr->ai_next;
}
if (preferIPv6Address) {
inetIndex = inet6Count;
inet6Index = 0;
} else {
inetIndex = 0;
inet6Index = inetCount;
}
while (iterator != NULL) {
if (iterator->ai_family == AF_INET) {
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (IS_NULL(iaObj)) {
if (!skip) {
struct addrinfo *next
= (struct addrinfo*) malloc(sizeof(struct addrinfo));
if (!next) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
ret = NULL;
goto cleanupAndReturn;
}
(*env)->SetIntField(env, iaObj, ni_iaaddressID,
ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
inetIndex ++;
}
memcpy(next, iterator, sizeof(struct addrinfo));
next->ai_next = NULL;
if (resNew == NULL) {
resNew = next;
} else {
last->ai_next = next;
}
last = next;
i++;
if (iterator->ai_family == AF_INET) {
inetCount ++;
} else if (iterator->ai_family == AF_INET6) {
jint scope = 0;
jbyteArray ipaddress;
jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
if (IS_NULL(iaObj)) {
ret = NULL;
goto cleanupAndReturn;
}
ipaddress = (*env)->NewByteArray(env, 16);
if (IS_NULL(ipaddress)) {
ret = NULL;
goto cleanupAndReturn;
}
(*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
(jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
if (scope != 0) { /* zero is default value, no need to set */
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
}
(*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
inet6Index ++;
inet6Count ++;
}
iterator = iterator->ai_next;
}
iterator = iterator->ai_next;
}
retLen = i;
iterator = resNew;
i = 0;
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
if (IS_NULL(ret)) {
/* we may have memory to free at the end of this */
goto cleanupAndReturn;
}
if (preferIPv6Address) {
inetIndex = inet6Count;
inet6Index = 0;
} else {
inetIndex = 0;
inet6Index = inetCount;
}
while (iterator != NULL) {
if (iterator->ai_family == AF_INET) {
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (IS_NULL(iaObj)) {
ret = NULL;
goto cleanupAndReturn;
}
(*env)->SetIntField(env, iaObj, ni_iaaddressID,
ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
inetIndex ++;
} else if (iterator->ai_family == AF_INET6) {
jint scope = 0;
jbyteArray ipaddress;
jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
if (IS_NULL(iaObj)) {
ret = NULL;
goto cleanupAndReturn;
}
ipaddress = (*env)->NewByteArray(env, 16);
if (IS_NULL(ipaddress)) {
ret = NULL;
goto cleanupAndReturn;
}
(*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
(jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
if (scope != 0) { /* zero is default value, no need to set */
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
}
(*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
inet6Index ++;
}
iterator = iterator->ai_next;
}
}
......@@ -291,8 +289,7 @@ cleanupAndReturn:
JNU_ReleaseStringPlatformChars(env, host, hostname);
}
if (NET_addrtransAvailable())
(*freeaddrinfo_ptr)(res);
freeaddrinfo(res);
return ret;
}
......@@ -312,44 +309,41 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
int len = 0;
jbyte caddr[16];
if (NET_addrtransAvailable()) {
struct sockaddr_in him4;
struct sockaddr_in6 him6;
struct sockaddr *sa;
struct sockaddr_in him4;
struct sockaddr_in6 him6;
struct sockaddr *sa;
/*
* For IPv4 addresses construct a sockaddr_in structure.
*/
if ((*env)->GetArrayLength(env, addrArray) == 4) {
jint addr;
(*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);
memset((char *) &him4, 0, sizeof(him4));
him4.sin_addr.s_addr = (uint32_t) htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
} else {
/*
* For IPv4 addresses construct a sockaddr_in structure.
* For IPv6 address construct a sockaddr_in6 structure.
*/
if ((*env)->GetArrayLength(env, addrArray) == 4) {
jint addr;
(*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);
memset((char *) &him4, 0, sizeof(him4));
him4.sin_addr.s_addr = (uint32_t) htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
} else {
/*
* For IPv6 address construct a sockaddr_in6 structure.
*/
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
memset((char *) &him6, 0, sizeof(him6));
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
him6.sin6_family = AF_INET6;
sa = (struct sockaddr *) &him6 ;
len = sizeof(him6) ;
}
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
memset((char *) &him6, 0, sizeof(him6));
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
him6.sin6_family = AF_INET6;
sa = (struct sockaddr *) &him6 ;
len = sizeof(him6) ;
}
error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0,
NI_NAMEREQD);
error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
}
if (!error) {
ret = (*env)->NewStringUTF(env, host);
}
if (ret == NULL) {
......
......@@ -53,36 +53,6 @@
* order and this ensures consistent device number across invocations.
*/
/* IP helper library routines */
int (PASCAL FAR *GetIpAddrTable_fn)();
int (PASCAL FAR *GetIfTable_fn)();
int (PASCAL FAR *GetFriendlyIfIndex_fn)();
int (PASCAL FAR *GetAdaptersAddresses_fn)();
int (PASCAL FAR *GetAdaptersInfo_fn)();
int (PASCAL FAR *GetNumberOfInterfaces_fn)();
/* Enumeration routines */
typedef int (*EnumerateNetInterfaces)(JNIEnv *, netif **);
typedef int(*EnumerateNetAddresses)(JNIEnv *, netif *, netaddr **);
static EnumerateNetInterfaces enumInterfaces_fn;
static EnumerateNetAddresses enumAddresses_fn;
/* Windows 9x routines are external (not needed on 64-bit) */
#ifndef _WIN64
extern int enumInterfaces_win9x(JNIEnv *, netif **);
extern int enumAddresses_win9x(JNIEnv *, netif *, netaddr **);
extern int init_win9x(void);
#endif
/* Windows 95/98/ME running */
static jboolean isW9x;
/* Windows version supports */
static jboolean os_supports_ipv6;
/* various JNI ids */
jclass ni_class; /* NetworkInterface */
......@@ -154,10 +124,10 @@ MIB_IFROW *getIF(jint index) {
*/
size = sizeof(MIB_IFTABLE);
tableP = (MIB_IFTABLE *)malloc(size);
count = (*GetIfTable_fn)(tableP, &size, TRUE);
count = GetIfTable(tableP, &size, TRUE);
if (count == ERROR_INSUFFICIENT_BUFFER || count == ERROR_BUFFER_OVERFLOW) {
tableP = (MIB_IFTABLE *)realloc(tableP, size);
count = (*GetIfTable_fn)(tableP, &size, TRUE);
count = GetIfTable(tableP, &size, TRUE);
}
if (count != NO_ERROR) {
......@@ -172,7 +142,7 @@ MIB_IFROW *getIF(jint index) {
/*
* Warning the real index is obtained by GetFriendlyIfIndex()
*/
ifindex = (*GetFriendlyIfIndex_fn)(ifrowP->dwIndex);
ifindex = GetFriendlyIfIndex(ifrowP->dwIndex);
if (ifindex == index) {
/*
* Create a copy of the entry so that we can free the table.
......@@ -199,7 +169,7 @@ MIB_IFROW *getIF(jint index) {
* occurs then netifPP be returned as list of netif structures or NULL
* if no interfaces are found.
*/
int enumInterfaces_win(JNIEnv *env, netif **netifPP)
int enumInterfaces(JNIEnv *env, netif **netifPP)
{
MIB_IFTABLE *tableP;
MIB_IFROW *ifrowP;
......@@ -215,32 +185,16 @@ int enumInterfaces_win(JNIEnv *env, netif **netifPP)
*/
size = sizeof(MIB_IFTABLE);
tableP = (MIB_IFTABLE *)malloc(size);
ret = (*GetIfTable_fn)(tableP, &size, TRUE);
ret = GetIfTable(tableP, &size, TRUE);
if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {
tableP = (MIB_IFTABLE *)realloc(tableP, size);
ret = (*GetIfTable_fn)(tableP, &size, TRUE);
ret = GetIfTable(tableP, &size, TRUE);
}
if (ret != NO_ERROR) {
if (tableP != NULL)
free(tableP);
#ifndef _WIN64
if (isW9x && ret == ERROR_NOT_SUPPORTED) {
/*
* If ERROR_NOT_SUPPORTED is returned on Windows 98 it means that
* IE5.0 has been installed. In this case we revert to the Windows 95
* approach and avoid using the IP Helper Library.
* See: http://support.microsoft.com/support/kb/articles/q234/5/73.asp
*/
enumInterfaces_fn = enumInterfaces_win9x;
enumAddresses_fn = enumAddresses_win9x;
init_win9x();
return (*enumInterfaces_fn)(env, netifPP);
}
#endif
JNU_ThrowByName(env, "java/lang/Error",
"IP Helper Library GetIfTable function failed");
......@@ -328,7 +282,7 @@ int enumInterfaces_win(JNIEnv *env, netif **netifPP)
curr->displayName[ifrowP->dwDescrLen] = '\0';
curr->dwIndex = ifrowP->dwIndex;
curr->ifType = ifrowP->dwType;
curr->index = (*GetFriendlyIfIndex_fn)(ifrowP->dwIndex);
curr->index = GetFriendlyIfIndex(ifrowP->dwIndex);
/*
* Put the interface at tail of list as GetIfTable(,,TRUE) is
......@@ -384,10 +338,10 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
size = sizeof(MIB_IPADDRTABLE);
tableP = (MIB_IPADDRTABLE *)malloc(size);
ret = (*GetIpAddrTable_fn)(&tableP, &size, FALSE);
ret = GetIpAddrTable(tableP, &size, FALSE);
if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {
tableP = (MIB_IPADDRTABLE *)realloc(tableP, size);
ret = (*GetIpAddrTable_fn)(tableP, &size, FALSE);
ret = GetIpAddrTable(tableP, &size, FALSE);
}
if (ret != NO_ERROR) {
if (tableP) {
......@@ -477,71 +431,6 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
JNIEXPORT void JNICALL
Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls)
{
OSVERSIONINFO ver;
HANDLE h;
/*
* First check if this is a Windows 9x machine.
*/
ver.dwOSVersionInfoSize = sizeof(ver);
GetVersionEx(&ver);
if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && ver.dwMajorVersion == 4) {
isW9x = JNI_TRUE;
}
/*
* Try to load the IP Helper Library and obtain the entry points we
* require. This will succeed on 98, NT SP4+, 2000 & XP. It will
* fail on Windows 95 (if IE hasn't been updated) and old versions
* of NT (IP helper library only appeared at SP4). If it fails on
* Windows 9x we will use the registry approach, otherwise if it
* fails we throw an Error indicating that we have an incompatible
* IP helper library.
*/
h = LoadLibrary("iphlpapi.dll");
if (h != NULL) {
GetIpAddrTable_fn =
(int (PASCAL FAR *)())GetProcAddress(h, "GetIpAddrTable");
GetIfTable_fn =
(int (PASCAL FAR *)())GetProcAddress(h, "GetIfTable");
GetFriendlyIfIndex_fn =
(int (PASCAL FAR *)())GetProcAddress(h, "GetFriendlyIfIndex");
GetNumberOfInterfaces_fn =
(int (PASCAL FAR *)())GetProcAddress(h, "GetNumberOfInterfaces");
GetAdaptersAddresses_fn =
(int (PASCAL FAR *)())GetProcAddress(h, "GetAdaptersAddresses");
GetAdaptersInfo_fn =
(int (PASCAL FAR *)())GetProcAddress(h, "GetAdaptersInfo");
}
/* IPv6 is supported on Windows versions if the following APIs avail */
os_supports_ipv6 = (GetAdaptersAddresses_fn != NULL) &&
(GetNumberOfInterfaces_fn != NULL) &&
(GetAdaptersInfo_fn != NULL);
if (GetIpAddrTable_fn == NULL ||
GetIfTable_fn == NULL ||
GetFriendlyIfIndex_fn == NULL) {
#ifndef _WIN64
if (isW9x) {
/* Use Windows 9x registry approach which requires initialization */
enumInterfaces_fn = enumInterfaces_win9x;
enumAddresses_fn = enumAddresses_win9x;
init_win9x();
} else
#endif
{
JNU_ThrowByName(env, "java/lang/Error",
"Incompatible IP helper library (iphlpapi.dll)");
return;
}
} else {
enumInterfaces_fn = enumInterfaces_win;
enumAddresses_fn = enumAddresses_win;
}
/*
* Get the various JNI ids that we require
*/
......@@ -581,7 +470,8 @@ Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls)
* populate the InetAddress array based on the IP addresses for this
* interface.
*/
jobject createNetworkInterface(JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP)
jobject createNetworkInterface
(JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP)
{
jobject netifObj;
jobject name, displayName;
......@@ -596,7 +486,8 @@ jobject createNetworkInterface(JNIEnv *env, netif *ifs, int netaddrCount, netadd
netifObj = (*env)->NewObject(env, ni_class, ni_ctor);
name = (*env)->NewStringUTF(env, ifs->name);
if (ifs->dNameIsUnicode) {
displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, wcslen ((PWCHAR)ifs->displayName));
displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,
(jsize)wcslen ((PWCHAR)ifs->displayName));
} else {
displayName = (*env)->NewStringUTF(env, ifs->displayName);
}
......@@ -612,7 +503,7 @@ jobject createNetworkInterface(JNIEnv *env, netif *ifs, int netaddrCount, netadd
* Note that 0 is a valid number of addresses.
*/
if (netaddrCount < 0) {
netaddrCount = (*enumAddresses_fn)(env, ifs, &netaddrP);
netaddrCount = enumAddresses_win(env, ifs, &netaddrP);
if ((*env)->ExceptionOccurred(env)) {
free_netaddr(netaddrP);
return NULL;
......@@ -725,12 +616,13 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
const char *name_utf;
jobject netifObj = NULL;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_getByName0_XP (env, cls, name);
}
/* get the list of interfaces */
if ((*enumInterfaces_fn)(env, &ifList) < 0) {
if (enumInterfaces(env, &ifList) < 0) {
return NULL;
}
......@@ -771,12 +663,13 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
netif *ifList, *curr;
jobject netifObj = NULL;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_getByIndex0_XP (env, cls, index);
}
/* get the list of interfaces */
if ((*enumInterfaces_fn)(env, &ifList) < 0) {
if (enumInterfaces(env, &ifList) < 0) {
return NULL;
}
......@@ -812,12 +705,13 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
jint addr = (*env)->GetIntField(env, iaObj, ni_iaAddr);
jobject netifObj = NULL;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);
}
/* get the list of interfaces */
if ((*enumInterfaces_fn)(env, &ifList) < 0) {
if (enumInterfaces(env, &ifList) < 0) {
return NULL;
}
......@@ -832,7 +726,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
netaddr *addrP;
/* enumerate the addresses on this interface */
count = (*enumAddresses_fn)(env, curr, &addrList);
count = enumAddresses_win(env, curr, &addrList);
if (count < 0) {
free_netif(ifList);
return NULL;
......@@ -881,14 +775,15 @@ JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
jobjectArray netIFArr;
jint arr_index;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_getAll_XP (env, cls);
}
/*
* Get list of interfaces
*/
count = (*enumInterfaces_fn)(env, &ifList);
count = enumInterfaces(env, &ifList);
if (count < 0) {
return NULL;
}
......@@ -934,13 +829,16 @@ JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
(JNIEnv *env, jclass cls, jstring name, jint index) {
jboolean ret = JNI_FALSE;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_isUp0_XP(env, cls, name, index);
} else {
MIB_IFROW *ifRowP;
ifRowP = getIF(index);
if (ifRowP != NULL) {
ret = ifRowP->dwAdminStatus == 1 && (ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL || ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED);
ret = ifRowP->dwAdminStatus == 1 &&
(ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL ||
ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED);
free(ifRowP);
}
}
......@@ -952,11 +850,13 @@ JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
* Method: isP2P0
* Signature: (Ljava/lang/String;I)Z
*/
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
(JNIEnv *env, jclass cls, jstring name, jint index) {
MIB_IFROW *ifRowP;
jboolean ret = JNI_FALSE;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_isP2P0_XP(env, cls, name, index);
} else {
ifRowP = getIF(index);
......@@ -983,7 +883,8 @@ JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
MIB_IFROW *ifRowP;
jboolean ret = JNI_FALSE;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_isLoopback0_XP(env, cls, name, index);
} else {
ifRowP = getIF(index);
......@@ -1003,22 +904,8 @@ JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
*/
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
(JNIEnv *env, jclass cls, jstring name, jint index) {
MIB_IFROW *ifRowP;
jboolean ret = JNI_TRUE;
// Let's try to use the newer API (XP & 2003 only)
if (GetAdaptersAddresses_fn != NULL) {
ret = Java_java_net_NetworkInterface_supportsMulticast0_XP(env, cls,
return Java_java_net_NetworkInterface_supportsMulticast0_XP(env, cls,
name, index);
return ret;
}
ifRowP = getIF(index);
if (ifRowP != NULL) {
if (ifRowP->dwType == MIB_IF_TYPE_LOOPBACK)
ret = JNI_FALSE;
free(ifRowP);
}
return ret;
}
/*
......@@ -1026,12 +913,14 @@ JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
* Method: getMacAddr0
* Signature: ([bLjava/lang/String;I)[b
*/
JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
jbyteArray ret = NULL;
int len;
MIB_IFROW *ifRowP;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_getMacAddr0_XP(env, class, name, index);
} else {
ifRowP = getIF(index);
......@@ -1058,11 +947,13 @@ JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *
* Method: getMTU0
* Signature: ([bLjava/lang/String;I)I
*/
JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0
(JNIEnv *env, jclass class, jstring name, jint index) {
jint ret = -1;
MIB_IFROW *ifRowP;
if (os_supports_ipv6 && ipv6_available()) {
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
if (ipv6_available()) {
return Java_java_net_NetworkInterface_getMTU0_XP(env, class, name, index);
} else {
ifRowP = getIF(index);
......
......@@ -87,338 +87,6 @@ extern jfieldID ni_ibaddressID; /* InterfaceAddress.address */
extern jfieldID ni_ibbroadcastID; /* InterfaceAddress.broadcast */
extern jfieldID ni_ibmaskID; /* InterfaceAddress.maskLength */
int enumInterfaces_win(JNIEnv *env, netif **netifPP);
/* We have included iphlpapi.h which includes iptypes.h which has the definition
* for MAX_ADAPTER_DESCRIPTION_LENGTH (along with the other definitions in this
* ifndef block). Therefore if MAX_ADAPTER_DESCRIPTION_LENGTH is defined we can
* be sure that the other definitions are also defined */
#ifndef MAX_ADAPTER_DESCRIPTION_LENGTH
/*
* Following includes come from iptypes.h
*/
#pragma warning(push)
#pragma warning(disable:4201)
#include <time.h>
// Definitions and structures used by getnetworkparams and getadaptersinfo apis
#define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arb.
#define MAX_ADAPTER_NAME_LENGTH 256 // arb.
#define MAX_ADAPTER_ADDRESS_LENGTH 8 // arb.
#define DEFAULT_MINIMUM_ENTITIES 32 // arb.
#define MAX_HOSTNAME_LEN 128 // arb.
#define MAX_DOMAIN_NAME_LEN 128 // arb.
#define MAX_SCOPE_ID_LEN 256 // arb.
//
// types
//
// Node Type
#define BROADCAST_NODETYPE 1
#define PEER_TO_PEER_NODETYPE 2
#define MIXED_NODETYPE 4
#define HYBRID_NODETYPE 8
//
// IP_ADDRESS_STRING - store an IP address as a dotted decimal string
//
typedef struct {
char String[4 * 4];
} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
//
// IP_ADDR_STRING - store an IP address with its corresponding subnet mask,
// both as dotted decimal strings
//
typedef struct _IP_ADDR_STRING {
struct _IP_ADDR_STRING* Next;
IP_ADDRESS_STRING IpAddress;
IP_MASK_STRING IpMask;
DWORD Context;
} IP_ADDR_STRING, *PIP_ADDR_STRING;
//
// ADAPTER_INFO - per-adapter information. All IP addresses are stored as
// strings
//
typedef struct _IP_ADAPTER_INFO {
struct _IP_ADAPTER_INFO* Next;
DWORD ComboIndex;
char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
UINT AddressLength;
BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD Index;
UINT Type;
UINT DhcpEnabled;
PIP_ADDR_STRING CurrentIpAddress;
IP_ADDR_STRING IpAddressList;
IP_ADDR_STRING GatewayList;
IP_ADDR_STRING DhcpServer;
BOOL HaveWins;
IP_ADDR_STRING PrimaryWinsServer;
IP_ADDR_STRING SecondaryWinsServer;
time_t LeaseObtained;
time_t LeaseExpires;
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
#ifdef _WINSOCK2API_
//
// The following types require Winsock2.
//
typedef enum {
IpPrefixOriginOther = 0,
IpPrefixOriginManual,
IpPrefixOriginWellKnown,
IpPrefixOriginDhcp,
IpPrefixOriginRouterAdvertisement,
} IP_PREFIX_ORIGIN;
typedef enum {
IpSuffixOriginOther = 0,
IpSuffixOriginManual,
IpSuffixOriginWellKnown,
IpSuffixOriginDhcp,
IpSuffixOriginLinkLayerAddress,
IpSuffixOriginRandom,
} IP_SUFFIX_ORIGIN;
typedef enum {
IpDadStateInvalid = 0,
IpDadStateTentative,
IpDadStateDuplicate,
IpDadStateDeprecated,
IpDadStatePreferred,
} IP_DAD_STATE;
typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD Flags;
};
};
struct _IP_ADAPTER_UNICAST_ADDRESS *Next;
SOCKET_ADDRESS Address;
IP_PREFIX_ORIGIN PrefixOrigin;
IP_SUFFIX_ORIGIN SuffixOrigin;
IP_DAD_STATE DadState;
ULONG ValidLifetime;
ULONG PreferredLifetime;
ULONG LeaseLifetime;
} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;
typedef struct _IP_ADAPTER_ANYCAST_ADDRESS {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD Flags;
};
};
struct _IP_ADAPTER_ANYCAST_ADDRESS *Next;
SOCKET_ADDRESS Address;
} IP_ADAPTER_ANYCAST_ADDRESS, *PIP_ADAPTER_ANYCAST_ADDRESS;
typedef struct _IP_ADAPTER_MULTICAST_ADDRESS {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD Flags;
};
};
struct _IP_ADAPTER_MULTICAST_ADDRESS *Next;
SOCKET_ADDRESS Address;
} IP_ADAPTER_MULTICAST_ADDRESS, *PIP_ADAPTER_MULTICAST_ADDRESS;
//
// Per-address Flags
//
#define IP_ADAPTER_ADDRESS_DNS_ELIGIBLE 0x01
#define IP_ADAPTER_ADDRESS_TRANSIENT 0x02
typedef struct _IP_ADAPTER_DNS_SERVER_ADDRESS {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD Reserved;
};
};
struct _IP_ADAPTER_DNS_SERVER_ADDRESS *Next;
SOCKET_ADDRESS Address;
} IP_ADAPTER_DNS_SERVER_ADDRESS, *PIP_ADAPTER_DNS_SERVER_ADDRESS;
typedef struct _IP_ADAPTER_PREFIX {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD Flags;
};
};
struct _IP_ADAPTER_PREFIX *Next;
SOCKET_ADDRESS Address;
ULONG PrefixLength;
} IP_ADAPTER_PREFIX, *PIP_ADAPTER_PREFIX;
//
// Per-adapter Flags
//
#define IP_ADAPTER_DDNS_ENABLED 0x01
#define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX 0x02
#define IP_ADAPTER_DHCP_ENABLED 0x04
#define IP_ADAPTER_RECEIVE_ONLY 0x08
#define IP_ADAPTER_NO_MULTICAST 0x10
#define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20
//
// OperStatus values from RFC 2863
//
typedef enum {
IfOperStatusUp = 1,
IfOperStatusDown,
IfOperStatusTesting,
IfOperStatusUnknown,
IfOperStatusDormant,
IfOperStatusNotPresent,
IfOperStatusLowerLayerDown
} IF_OPER_STATUS;
//
// Scope levels from RFC 2373 used with ZoneIndices array.
//
typedef enum {
ScopeLevelInterface = 1,
ScopeLevelLink = 2,
ScopeLevelSubnet = 3,
ScopeLevelAdmin = 4,
ScopeLevelSite = 5,
ScopeLevelOrganization = 8,
ScopeLevelGlobal = 14
} SCOPE_LEVEL;
typedef struct _IP_ADAPTER_ADDRESSES {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD IfIndex;
};
};
struct _IP_ADAPTER_ADDRESSES *Next;
PCHAR AdapterName;
PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
PWCHAR DnsSuffix;
PWCHAR Description;
PWCHAR FriendlyName;
BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD PhysicalAddressLength;
DWORD Flags;
DWORD Mtu;
DWORD IfType;
IF_OPER_STATUS OperStatus;
DWORD Ipv6IfIndex;
DWORD ZoneIndices[16];
PIP_ADAPTER_PREFIX FirstPrefix;
} IP_ADAPTER_ADDRESSES, *PIP_ADAPTER_ADDRESSES;
//
// Flags used as argument to GetAdaptersAddresses().
// "SKIP" flags are added when the default is to include the information.
// "INCLUDE" flags are added when the default is to skip the information.
//
#define GAA_FLAG_SKIP_UNICAST 0x0001
#define GAA_FLAG_SKIP_ANYCAST 0x0002
#define GAA_FLAG_SKIP_MULTICAST 0x0004
#define GAA_FLAG_SKIP_DNS_SERVER 0x0008
#define GAA_FLAG_INCLUDE_PREFIX 0x0010
#define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
#endif /* _WINSOCK2API_ */
//
// IP_PER_ADAPTER_INFO - per-adapter IP information such as DNS server list.
//
typedef struct _IP_PER_ADAPTER_INFO {
UINT AutoconfigEnabled;
UINT AutoconfigActive;
PIP_ADDR_STRING CurrentDnsServer;
IP_ADDR_STRING DnsServerList;
} IP_PER_ADAPTER_INFO, *PIP_PER_ADAPTER_INFO;
//
// FIXED_INFO - the set of IP-related information which does not depend on DHCP
//
typedef struct {
char HostName[MAX_HOSTNAME_LEN + 4] ;
char DomainName[MAX_DOMAIN_NAME_LEN + 4];
PIP_ADDR_STRING CurrentDnsServer;
IP_ADDR_STRING DnsServerList;
UINT NodeType;
char ScopeId[MAX_SCOPE_ID_LEN + 4];
UINT EnableRouting;
UINT EnableProxy;
UINT EnableDns;
} FIXED_INFO, *PFIXED_INFO;
#pragma warning(pop)
#endif /*!MAX_ADAPTER_DESCRIPTION_LENGTH*/
#ifndef IP_INTERFACE_NAME_INFO_DEFINED
#define IP_INTERFACE_NAME_INFO_DEFINED
typedef struct ip_interface_name_info {
ULONG Index; // Interface Index
ULONG MediaType; // Interface Types - see ipifcons.h
UCHAR ConnectionType;
UCHAR AccessType;
GUID DeviceGuid; // Device GUID is the guid of the device
// that IP exposes
GUID InterfaceGuid; // Interface GUID, if not GUID_NULL is the
// GUID for the interface mapped to the device.
} IP_INTERFACE_NAME_INFO, *PIP_INTERFACE_NAME_INFO;
#endif
/* from ipifcons.h */
#ifndef IF_TYPE_PPP
#define IF_TYPE_PPP 23
#endif
#ifndef IF_TYPE_SOFTWARE_LOOPBACK
#define IF_TYPE_SOFTWARE_LOOPBACK 24
#endif
#ifndef IF_TYPE_SLIP
#define IF_TYPE_SLIP 28
#endif
#ifndef IF_TYPE_TUNNEL
#define IF_TYPE_TUNNEL 131
#endif
int enumInterfaces(JNIEnv *env, netif **netifPP);
#endif
/*
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <windows.h>
#include <winsock2.h>
#include <assert.h>
#include "jni_util.h"
#include "NetworkInterface.h"
/*
* Windows 9x specific routines to enumerate network interfaces and the
* IP addresses bound to those interfaces.
*
* Windows 95 does not include IP helper library support by default.
* Additionally Windows 98 can have its IP helper library support
* trashed by certain IE installations. For these environments we
* combine information from the registry with the list of IP addresses
* obtained via SIO_GET_INTERFACE_LIST.
*/
/*
* Header files are missing these
*/
#if !defined(SIO_GET_INTERFACE_LIST)
#define SIO_GET_INTERFACE_LIST _IOR('t', 127, u_long)
struct in_addr6 {
u_char s6_addr[16];
};
struct sockaddr_in6 {
short sin6_family;
u_short sin6_port;
u_long sin6_flowinfo;
struct in_addr6 sin6_addr;
};
typedef union sockaddr_gen{
struct sockaddr Address;
struct sockaddr_in AddressIn;
struct sockaddr_in6 AddressIn6;
} sockaddr_gen;
typedef struct _INTERFACE_INFO
{
u_long iiFlags;
sockaddr_gen iiAddress;
sockaddr_gen iiBroadcastAddress;
sockaddr_gen iiNetmask;
} INTERFACE_INFO;
#define IFF_UP 0x00000001
#endif
#define MAX_STR_LEN 256
/*
* A network adapter (similiar to the netif structure except contains
* Windows 9x specific fields).
*/
typedef struct _adapter {
char *name;
char *displayName;
int index;
char *reg_key;
int is_wan_driver;
netaddr *addrs;
struct _adapter *next;
} adapter;
/*
* Cached adapter list.
*/
static CRITICAL_SECTION cacheLock;
static adapter *cachedAdapterList;
/*
* Initialize cache
*/
void init_win9x() {
InitializeCriticalSection(&cacheLock);
}
/*
* Free adapter list and any addresses bound to the adpater.
*/
static void free_adapters(adapter *adapterP) {
adapter *curr = adapterP;
while (curr != NULL) {
if (curr->name != NULL)
free(curr->name);
if (curr->displayName != NULL)
free(curr->displayName);
if (curr->reg_key != NULL)
free(curr->reg_key);
if (curr->addrs != NULL)
free_netaddr(curr->addrs);
adapterP = adapterP->next;
free(curr);
curr = adapterP;
}
}
/*
* Returns the SIO_GET_INTERFACE_LIST output
*/
static int getInterfaceList(JNIEnv *env, INTERFACE_INFO *infoP, DWORD dwSize) {
SOCKET sock;
DWORD ret;
/* create a socket and do the ioctl */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
JNU_ThrowByName(env, "java/lang/Error", "socket failed");
return -1;
}
ret = WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0,
infoP, dwSize, &dwSize, NULL, NULL);
closesocket(sock);
if (ret == SOCKET_ERROR) {
JNU_ThrowByName(env, "java/lang/Error", "WSAIoctl failed");
return -1;
}
return dwSize;
}
/*
* Gross, ugly, and crude way of guessing if this is a WAN (dial-up) driver.
* Returns 1 if it's the normal PPCMAC VxD, otherwise 0.
*/
static int isWanDriver(char *driver) {
LONG ret;
HKEY hKey;
DWORD dwLen;
ULONG ulType;
char key[MAX_STR_LEN];
char vxd[MAX_STR_LEN];
sprintf(key, "System\\CurrentControlSet\\Services\\Class\\%s", driver);
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, (PHKEY)&hKey);
if (ret != ERROR_SUCCESS) {
return 0;
}
dwLen = sizeof(vxd);
ret = RegQueryValueEx(hKey, "DeviceVxDs", NULL, &ulType,
(LPBYTE)vxd, &dwLen);
RegCloseKey(hKey);
if (ret != ERROR_SUCCESS) {
return 0;
}
return (strcmp(vxd, "pppmac.vxd") == 0);
}
/*
* Windows 9x routine to get the network adapters using the registry.
* We enumerate HKEY_LOCAL_MACHINE\Enum and iterate through the tree
* looking for devices of class "Net". As these devices may not have a
* unique name we assign them a generated name.
*
* Returns a list of adapters without IP addresses (addrs member is NULL).
*/
static int getAdapters(JNIEnv *env, adapter **adapterPP)
{
LONG ret;
HKEY enumKey;
DWORD dwLen;
DWORD dwEnumKeys;
DWORD enumIndex;
ULONG ulType;
int adapterCount = 0;
adapter *adapterP = NULL;
adapter *curr;
/*
* Start at HKEY_LOCAL_MACHINE\Enum
*/
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Enum", 0, KEY_READ, (PHKEY)&enumKey);
if (ret != ERROR_SUCCESS) {
return -1;
}
ret = RegQueryInfoKey(enumKey, NULL, NULL, NULL, &dwEnumKeys,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
RegCloseKey(enumKey);
return -1;
}
/*
* Iterate through the sub-keys (PCI, Root, ...)
*/
for(enumIndex = 0; enumIndex<dwEnumKeys; enumIndex++) {
TCHAR deviceType[MAX_STR_LEN];
HKEY deviceKey;
DWORD deviceIndex;
DWORD dwDeviceKeys;
dwLen = sizeof(deviceType);
ret = RegEnumKeyEx(enumKey, enumIndex, deviceType, &dwLen, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
/* ignore this tree */
continue;
}
ret = RegOpenKeyEx(enumKey, deviceType, 0, KEY_READ, (PHKEY)&deviceKey);
if (ret != ERROR_SUCCESS) {
/* ignore this tree */
continue;
}
ret = RegQueryInfoKey(deviceKey, NULL, NULL, NULL, &dwDeviceKeys,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
/* ignore this tree */
RegCloseKey(deviceKey);
continue;
}
/*
* Iterate through each of the sub-keys under PCI, Root, ...
*/
for (deviceIndex=0; deviceIndex<dwDeviceKeys; deviceIndex++) {
TCHAR name[MAX_STR_LEN];
HKEY nameKey;
DWORD nameIndex;
DWORD dwNameKeys;
dwLen = sizeof(name);
ret = RegEnumKeyEx(deviceKey, deviceIndex, name, &dwLen, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
/* ignore this sub-tree */
continue;
}
ret = RegOpenKeyEx(deviceKey, name, 0, KEY_READ, (PHKEY)&nameKey);
if (ret != ERROR_SUCCESS) {
/* ignore this sub-tree */
continue;
}
ret = RegQueryInfoKey(nameKey, NULL, NULL, NULL, &dwNameKeys,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
RegCloseKey(nameKey);
/* ignore this sub-tree */
continue;
}
/*
* Finally iterate through the Enum\Root\Net level keys
*/
for (nameIndex=0; nameIndex<dwNameKeys; nameIndex++) {
TCHAR dev[MAX_STR_LEN];
TCHAR cls[MAX_STR_LEN];
HKEY clsKey;
dwLen = sizeof(dev);
ret = RegEnumKeyEx(nameKey, nameIndex, dev, &dwLen, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
continue;
}
ret = RegOpenKeyEx(nameKey, dev, 0, KEY_READ, (PHKEY)&clsKey);
if (ret == ERROR_SUCCESS) {
dwLen = sizeof(cls);
ret = RegQueryValueEx(clsKey, "Class", NULL, &ulType,
(LPBYTE)cls, &dwLen);
if (ret == ERROR_SUCCESS) {
if (strcmp(cls, "Net") == 0) {
TCHAR deviceDesc[MAX_STR_LEN];
dwLen = sizeof(deviceDesc);
ret = RegQueryValueEx(clsKey, "DeviceDesc", NULL, &ulType,
(LPBYTE)deviceDesc, &dwLen);
if (ret == ERROR_SUCCESS) {
char key_name[MAX_STR_LEN];
char ps_name[8];
char driver[MAX_STR_LEN];
int wan_device;
/*
* Generate a pseudo device name
*/
sprintf(ps_name, "net%d", adapterCount);
/*
* Try to determine if this a WAN adapter. This is
* useful when we try to eliminate WAN adapters from
* the interface list when probing for DHCP info
*/
dwLen = sizeof(driver);
ret = RegQueryValueEx(clsKey, "Driver", NULL,
&ulType, (LPBYTE)driver, &dwLen);
if (ret == ERROR_SUCCESS) {
wan_device = isWanDriver(driver);
} else {
wan_device = 0;
}
/*
* We have found a Net device. In order to get the
* static IP addresses we must note the key.
*/
sprintf(key_name, "Enum\\%s\\%s\\%s", deviceType, name, dev);
/*
* Create the net adapter
*/
curr = (adapter *)calloc(1, sizeof(adapter));
if (curr != NULL) {
curr->is_wan_driver = wan_device;
curr->name = (char *)malloc(strlen(ps_name) + 1);
if (curr->name) {
curr->displayName = (char *)malloc(strlen(deviceDesc) + 1);
if (curr->displayName) {
curr->reg_key = (char *)malloc(strlen(key_name)+1);
if (curr->reg_key == NULL) {
free(curr->displayName);
free(curr->name);
free(curr);
curr = NULL;
}
} else {
free(curr->name);
free(curr);
curr = NULL;
}
} else {
free(curr);
curr = NULL;
}
}
/* At OutOfMemory occurred */
if (curr == NULL) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
free_adapters(adapterP);
RegCloseKey(clsKey);
RegCloseKey(nameKey);
RegCloseKey(deviceKey);
RegCloseKey(enumKey);
return -1;
}
/* index starts at 1 (not 0) */
curr->index = ++adapterCount;
strcpy(curr->name, ps_name);
strcpy(curr->displayName, deviceDesc);
strcpy(curr->reg_key, key_name);
/*
* Put the adapter at the end of the list.
*/
if (adapterP == NULL) {
adapterP = curr;
} else {
adapter *tail = adapterP;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = curr;
}
}
}
}
}
RegCloseKey(clsKey);
}
RegCloseKey(nameKey);
}
RegCloseKey(deviceKey);
}
RegCloseKey(enumKey);
/*
* Insert an entry for the loopback interface
*/
curr = (adapter *)calloc(1, sizeof(adapter));
if (curr == NULL) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
free_adapters(adapterP);
return -1;
}
curr->index = ++adapterCount;
curr->name = _strdup("lo");
curr->displayName = _strdup("TCP Loopback interface");
curr->next = adapterP;
*adapterPP = curr;
return adapterCount;
}
/*
* Windows 9x routine to obtain any static addresses for a specified
* TCP/IP binding.
*
* We first open Enum\Network\${binding} and check that the driver
* is TCP/IP. If so we pick up the driver and check for any IP addresses
* in System\\CurrentControlSet\\Services\\Class\\${driver}
*
* Returns 0 if found, otherwise -1.
*/
static int getStaticAddressEntry(char *binding, char *addresses) {
LONG ret;
HKEY hKey;
char name[255];
char desc[255];
char driver[255];
char ipaddr[255];
DWORD dwName;
ULONG ulType;
/* assume nothing will be returned */
strcpy(addresses, "");
/*
* Open the binding and check that it's TCP/IP
*/
sprintf(name, "Enum\\Network\\%s", binding);
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, name, 0, KEY_READ, (PHKEY)&hKey);
if (ret != ERROR_SUCCESS) {
return -1;
}
dwName = sizeof(desc);
ret = RegQueryValueEx(hKey, "DeviceDesc", NULL, &ulType,
(LPBYTE)desc, &dwName);
if (ret != ERROR_SUCCESS) {
RegCloseKey(hKey);
return -1;
}
if (strcmp(desc, "TCP/IP") != 0) {
/* ignore non-TCP/IP bindings */
RegCloseKey(hKey);
return -1;
}
/*
* Get the driver for this TCP/IP binding
*/
dwName = sizeof(driver);
ret = RegQueryValueEx(hKey, "Driver", NULL, &ulType,
(LPBYTE)driver, &dwName);
RegCloseKey(hKey);
if (ret != ERROR_SUCCESS) {
return -1;
}
/*
* Finally check if there is an IPAddress value for this driver.
*/
sprintf(name, "System\\CurrentControlSet\\Services\\Class\\%s", driver);
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, name, 0, KEY_READ, (PHKEY)&hKey);
if (ret != ERROR_SUCCESS) {
return -1;
}
dwName = sizeof(ipaddr);
ret = RegQueryValueEx(hKey, "IPAddress", NULL, &ulType,
(LPBYTE)ipaddr, &dwName);
RegCloseKey(hKey);
if (ret != ERROR_SUCCESS) {
return -1;
}
/* Return the address(es) */
strcpy( addresses, ipaddr );
return 0;
}
/*
* Windows 9x routine to enumerate the static IP addresses on a
* particular interface using the registry.
*
* Returns a count of the number of addresses found.
*/
static int getStaticAddresses(JNIEnv *env, char *reg_key, netaddr **netaddrPP)
{
LONG ret;
HKEY enumKey, bindingKey;
DWORD dwLen;
ULONG ulType;
char addresses[MAX_STR_LEN];
unsigned long addr; /* IPv4 address */
unsigned char byte;
netaddr *netaddrP, *curr;
int i, addrCount;
/*
* Open the HKEY_LOCAL_MACHINE\Enum\%s\%s\%s key
*/
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_key, 0, KEY_READ,
(PHKEY)&enumKey);
if (ret != ERROR_SUCCESS) {
/* interface has been removed */
*netaddrPP = NULL;
return 0;
}
/*
* Iterate through each of the bindings to find any TCP/IP bindings
* and any static address assoicated with the binding.
*/
strcpy(addresses, "");
addrCount = 0;
netaddrP = NULL;
ret = RegOpenKeyEx(enumKey, "Bindings", 0, KEY_READ, (PHKEY)&bindingKey);
if (ret == ERROR_SUCCESS) {
DWORD dwBindingKeys;
DWORD dwBindingIndex;
ret = RegQueryInfoKey(bindingKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwBindingKeys,
NULL, NULL, NULL, NULL);
if (ret == ERROR_SUCCESS) {
TCHAR binding[MAX_STR_LEN];
dwBindingIndex=0;
while (dwBindingIndex<dwBindingKeys) {
dwLen = sizeof(binding);
ret = RegEnumValue(bindingKey, dwBindingIndex, binding, &dwLen,
NULL, &ulType, NULL, NULL);
if (ret == ERROR_SUCCESS) {
if (getStaticAddressEntry(binding, addresses) == 0) {
/*
* On Windows 9x IP addresses are strings. Multi-homed hosts have
* the IP addresses seperated by commas.
*/
addr = 0;
byte = 0;
i = 0;
while ((DWORD)i < strlen(addresses)+1) {
/* eof or seperator */
if (addresses[i] == ',' || addresses[i] == 0) {
if (addr != 0) {
addr = (addr << 8) | byte;
curr = (netaddr *)malloc(sizeof(netaddr));
if (curr == NULL) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
free_netaddr(netaddrP);
RegCloseKey(enumKey);
return -1;
}
curr->addr.him4.sin_family = AF_INET;
curr->addr.him4.sin_addr.s_addr = htonl(addr);
curr->next = netaddrP;
netaddrP = curr;
addrCount++;
/* reset the address for the next iteration */
addr = 0;
}
byte = 0;
} else {
if (addresses[i] == '.') {
addr = (addr << 8) | byte;
byte = 0;
} else {
byte = (byte * 10) + (addresses[i] - '0');
}
}
i++;
}
}
}
if (addrCount > 0) {
break;
}
dwBindingIndex++;
}
}
RegCloseKey(bindingKey);
}
/* close the registry */
RegCloseKey(enumKey);
/* return the list */
*netaddrPP = netaddrP;
return addrCount;
}
/*
* Windows 9x routine to probe the registry for a DHCP allocated address.
* This routine is only useful if we know that only one interface has its
* address allocated using DHCP. Returns 0.0.0.0 if none or multiple
* addresses found.0
*/
static DWORD getDHCPAddress()
{
LONG ret;
HKEY hKey;
DWORD dwLen;
ULONG ulType;
char key[MAX_STR_LEN];
int index;
DWORD dhcp_addr = 0;
index = 0;
while (index < 99) {
DWORD addr;
sprintf(key, "SYSTEM\\CurrentControlSet\\Services\\VxD\\DHCP\\DhcpInfo%02d", index);
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, (PHKEY)&hKey);
if (ret != ERROR_SUCCESS) {
return dhcp_addr;
}
/*
* On Windows 9x the DHCP address is in the DhcpIPAddress key. We
* are assuming here that this is Windows Socket 2. If Windows
* Sockets is the original 1.1 release then this doesn't work because
* the IP address if in the DhcpInfo key (a blob with the first 4
* bytes set to the IP address).
*/
dwLen = sizeof(addr);
ret = RegQueryValueEx(hKey, "DhcpIPAddress", NULL, &ulType,
(LPBYTE)&addr, &dwLen);
RegCloseKey(hKey);
if (ret == ERROR_SUCCESS) {
if (addr) {
/* more than 1 DHCP address in registry */
if (dhcp_addr) {
return 0;
}
dhcp_addr = htonl(addr);
}
}
index++;
}
/* if we get here it means we've examined 100 registry entries */
return 0;
}
/*
* Attempt to allocate the remaining addresses on addrList to the adpaters
* on adapterList. Returns the number of address remaining.
*/
int allocateRemaining(adapter *adapterList, int address_count, netaddr *addrList) {
adapter *adapterP = adapterList;
adapter *nobindingsP = NULL;
/*
* If all addresses have been assigned there's nothing to do.
*/
if (address_count == 0) {
return 0;
}
/*
* Determine if there is only one adapter without an address
*/
while (adapterP != NULL) {
if (adapterP->addrs == NULL) {
if (nobindingsP == NULL) {
nobindingsP = adapterP;
} else {
nobindingsP = NULL;
break;
}
}
adapterP = adapterP->next;
}
/*
* Found (only one)
*/
if (nobindingsP) {
nobindingsP->addrs = addrList;
address_count = 0;
}
return address_count;
}
/*
* 1. Network adapters are enumerated by traversing through the
* HKEY_LOCAL_MACHINE\Enum tree and picking out class "Net" devices.
*
* 2. Address enumeration starts with the list of IP addresses returned
* by SIO_GET_INTERFACE_LIST and then we "allocate" the addresses to
* the network adapters enumerated in step 1. Allocation works as
* follows :-
*
* i. Loopback address is assigned to the loopback interface. If there
* is one network adapter then all other addresses must be bound
* to that adapter.
*
* ii. Enumerate all static IP addresses using the registry. This allows
* us to allocate all static IP address to the corresponding adapter.
*
* iii. After step ii. if there is one network adapter that has not been
* allocated an IP address then we know that the remaining IP addresses
* must be bound to this adapter.
*
* iv. If we get to this step it means we are dealing with a complex
* configuration whereby multiple network adapters have their address
* configured dynamically (eg: NIC using DHCP plus modem using PPP).
* We employ a gross hack based on a crude determination done in step 1.
* If there is a DHCP address configured and if one remaining
* network adapter that is not a WAN adapter then the DHCP address
* must be bound to it.
*/
static adapter *loadConfig(JNIEnv *env) {
adapter *adapterList;
int adapter_count;
INTERFACE_INFO interfaceInfo[8];
DWORD dwSize;
int address_count, i;
netaddr *addrList;
/*
* Enumerate the network adapters
*/
adapter_count = getAdapters(env, &adapterList);
if (adapter_count < 0) {
return NULL;
}
/* minimum of loopback interface */
assert(adapter_count >= 1);
/*
* Enumerate all IP addresses as known to winsock
*/
dwSize = getInterfaceList(env, interfaceInfo, sizeof(interfaceInfo));
if (dwSize < 0) {
free_adapters(adapterList);
return NULL;
}
address_count = dwSize/sizeof(INTERFACE_INFO);
/* minimum of loopback address */
assert(address_count >= 1);
/*
* Create an address list (addrList) from the INTERFACE_INFO
* structure.
*/
addrList = NULL;
for (i=0; i<address_count; i++) {
netaddr *addrP = (netaddr *)calloc(1, sizeof(netaddr));
if (addrP == NULL) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
free_netaddr(addrList);
free(adapterList);
return NULL;
}
addrP->addr.him4.sin_family = AF_INET;
addrP->addr.him4.sin_addr.s_addr =
((SOCKADDR_IN *)&(interfaceInfo[i].iiAddress))->sin_addr.S_un.S_addr;
addrP->next = addrList;
addrList = addrP;
}
/*
* First we assign the loopback address to the lo adapter.
* If lo is the only adapter then we are done.
*/
{
adapter *loopbackAdapter;
netaddr *addrP, *prevP;
/* find the loopback adapter */
loopbackAdapter = adapterList;
while (strcmp(loopbackAdapter->name, "lo") != 0) {
loopbackAdapter = loopbackAdapter->next;
}
assert(loopbackAdapter != NULL);
/* find the loopback address and move it to the loopback adapter */
addrP = addrList;
prevP = NULL;
while (addrP != NULL) {
if (addrP->addr.him4.sin_addr.s_addr == htonl(0x7f000001)) {
loopbackAdapter->addrs = addrP;
if (prevP == NULL) {
addrList = addrP->next;
} else {
prevP->next = addrP->next;
}
loopbackAdapter->addrs->next = NULL;
address_count--;
break;
}
prevP = addrP;
addrP = addrP->next;
}
}
/*
* Special case. If there's only one network adapter then all remaining
* IP addresses must be bound to that adapter.
*/
address_count = allocateRemaining(adapterList, address_count, addrList);
if (address_count == 0) {
return adapterList;
}
/*
* Locate any static IP addresses defined in the registry. Validate the
* addresses against the SIO_GET_INTERFACE_LIST (as registry may have
* stale settings). If valid we move the addresses from addrList to
* the adapter.
*/
{
adapter *adapterP;
adapterP = adapterList;
while (adapterP != NULL) {
int cnt;
netaddr *static_addrP;
/*
* Skip loopback
*/
if (strcmp(adapterP->name, "lo") == 0) {
adapterP = adapterP->next;
continue;
}
/*
* Get the static addresses for this adapter.
*/
cnt = getStaticAddresses(env, adapterP->reg_key, &static_addrP);
if (cnt < 0) {
free_netaddr(addrList);
free(adapterList);
return NULL;
}
/*
* Validate against the SIO_GET_INTERFACE_LIST.
* (avoids stale registry settings).
*/
while (static_addrP != NULL) {
netaddr *addrP = addrList;
netaddr *prev = NULL;
while (addrP != NULL) {
if (addrP->addr.him4.sin_addr.s_addr == static_addrP->addr.him4.sin_addr.s_addr)
break;
prev = addrP;
addrP = addrP->next;
}
/*
* if addrP is not NULL it means we have a match
* (ie: address from the registry is valid).
*/
if (addrP != NULL) {
/* remove from addrList */
if (prev == NULL) {
addrList = addrP->next;
} else {
prev->next = addrP->next;
}
address_count--;
/* add to adapter list */
addrP->next = adapterP->addrs;
adapterP->addrs = addrP;
}
/*
* On the next static address.
*/
static_addrP = static_addrP->next;
}
/* not needed */
free_netaddr(static_addrP);
adapterP = adapterP->next;
}
}
/*
* Static addresses are now assigned so try again to allocate the
* remaining addresses. This will succeed if there is one adapter
* with a dynamically assigned address (DHCP or PPP).
*/
address_count = allocateRemaining(adapterList, address_count, addrList);
if (address_count == 0) {
return adapterList;
}
/*
* Next we see if there is a DHCP address in the registry. If there is
* an address (and it's valid) then we know it must be bound to a LAN
* adapter. Additionally, when we enumerate the network adapters
* we made a crude determination on if an adapter is dial-up. Thus if
* we know there is one remaining LAN adapter without an IP address
* then the DHCP address must be bound to it.
*/
{
long dhcp_addr = getDHCPAddress(); /* returns in network order */
if (dhcp_addr) {
netaddr *addrP, *prevP;
/*
* Check that the DHCP address is valid
*/
addrP = addrList;
prevP = NULL;
while (addrP != NULL) {
if (addrP->addr.him4.sin_addr.s_addr == dhcp_addr) {
break;
}
prevP = addrP;
addrP = addrP->next;
}
/*
* Address is valid - now check how many non-WAN adapters
* don't have addresses yet.
*/
if (addrP != NULL) {
adapter *adapterP = adapterList;
adapter *nobindingsP = NULL;
while (adapterP != NULL) {
if (adapterP->addrs == NULL && !adapterP->is_wan_driver) {
if (nobindingsP == NULL) {
nobindingsP = adapterP;
} else {
/* already found one */
nobindingsP = NULL;
break;
}
}
adapterP = adapterP->next;
}
/*
* One non-WAN adapter remaining
*/
if (nobindingsP != NULL) {
nobindingsP->addrs = addrP;
/* remove from addrList */
if (prevP == NULL) {
addrList = addrP->next;
} else {
prevP->next = addrP->next;
}
addrP->next = NULL;
address_count--;
}
}
}
}
/*
* Finally we do one final attempt to re-assign any remaining
* addresses. This catches the case of 2 adapters that have their
* addresses dynamically assigned (specifically NIC with DHCP, and
* Modem using RAS/PPP).
*/
address_count = allocateRemaining(adapterList, address_count, addrList);
if (address_count == 0) {
return adapterList;
}
/*
* Free any unallocated addresses
*/
if (address_count > 0) {
free_netaddr(addrList);
}
/*
* Return the adapter List.
*/
return adapterList;
}
/*
* Enumerate network interfaces. If successful returns the number of
* network interfaces and netifPP returning a list of netif structures.
* Returns -1 with exception thrown if error.
*/
int enumInterfaces_win9x(JNIEnv *env, netif **netifPP) {
adapter *adapters, *adapterP;
int cnt = 0;
netif *netifP = NULL;
/* enumerate network configuration */
adapters = loadConfig(env);
if (adapters == NULL) {
return -1;
}
/*
* loadConfig returns an adapter list - we need to create a corresponding
* list of netif structures.
*/
adapterP = adapters;
while (adapterP != NULL) {
netif *ifs = (netif *)calloc(1, sizeof(netif));
if (ifs == NULL) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
free_adapters(adapters);
free_netif(netifP);
return -1;
}
ifs->name = _strdup(adapterP->name);
ifs->displayName = _strdup(adapterP->displayName);
ifs->dwIndex = adapterP->index;
ifs->index = adapterP->index;
ifs->next = netifP;
netifP = ifs;
if (ifs->name == NULL || ifs->displayName == NULL) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
free_adapters(adapters);
free_netif(netifP);
return -1;
}
cnt++;
adapterP = adapterP->next;
}
/*
* Put the adapter list in the cache
*/
EnterCriticalSection(&cacheLock);
{
if (cachedAdapterList != NULL) {
free_adapters(cachedAdapterList);
}
cachedAdapterList = adapters;
}
LeaveCriticalSection(&cacheLock);
/*
* Return the netif list
*/
*netifPP = netifP;
return cnt;
}
/*
* Enumerate the addresses for the specified network interface. If successful
* returns the number of addresses bound to the interface and sets netaddrPP
* to be a list of netaddr structures. Returns -1 if error.
*/
int enumAddresses_win9x(JNIEnv *env, netif *netifP, netaddr **netaddrPP) {
EnterCriticalSection(&cacheLock);
{
adapter *adapterP = cachedAdapterList;
while (adapterP != NULL) {
if (strcmp(adapterP->name, netifP->name) == 0) {
netaddr *newlist = NULL;
netaddr *curr = adapterP->addrs;
int cnt = 0;
while (curr != NULL) {
/*
* Clone the netaddr and add it to newlist.
*/
netaddr *tmp = (netaddr *)calloc(1, sizeof(netaddr));
if (tmp == NULL) {
LeaveCriticalSection(&cacheLock);
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
free_netaddr(newlist);
return -1;
}
tmp->addr = curr->addr;
tmp->next = newlist;
newlist = tmp;
cnt++;
curr = curr->next;
}
*netaddrPP = newlist;
LeaveCriticalSection(&cacheLock);
return cnt;
}
adapterP = adapterP->next;
}
}
LeaveCriticalSection(&cacheLock);
*netaddrPP = NULL;
return 0;
}
......@@ -43,14 +43,6 @@
extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);
/* IP helper library routines */
int (PASCAL FAR *GetIpAddrTable_fn)();
int (PASCAL FAR *GetIfTable_fn)();
int (PASCAL FAR *GetFriendlyIfIndex_fn)();
int (PASCAL FAR *GetAdaptersAddresses_fn)();
int (PASCAL FAR *GetAdaptersInfo_fn)();
int (PASCAL FAR *GetNumberOfInterfaces_fn)();
#ifdef DEBUG
void printnif (netif *nif) {
#ifdef _WIN64
......@@ -96,14 +88,14 @@ static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) {
flags = GAA_FLAG_SKIP_DNS_SERVER;
flags |= GAA_FLAG_SKIP_MULTICAST;
flags |= GAA_FLAG_INCLUDE_PREFIX;
ret = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
if (ret == ERROR_BUFFER_OVERFLOW) {
adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
if (adapterInfo == 0) {
return -1;
}
bufsize = len;
ret = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
}
if (ret != ERROR_SUCCESS) {
free (adapterInfo);
......@@ -133,7 +125,7 @@ IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) {
flags = GAA_FLAG_SKIP_DNS_SERVER;
flags |= GAA_FLAG_SKIP_MULTICAST;
flags |= GAA_FLAG_INCLUDE_PREFIX;
val = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
if (val == ERROR_BUFFER_OVERFLOW) {
adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
if (adapterInfo == 0) {
......@@ -141,7 +133,7 @@ IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) {
return NULL;
}
bufsize = len;
val = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
}
if (val != ERROR_SUCCESS) {
free (adapterInfo);
......@@ -182,7 +174,7 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
* as what previous JDK versions would return.
*/
ret = enumInterfaces_win (env, netifPP);
ret = enumInterfaces(env, netifPP);
if (ret == -1) {
return -1;
} else {
......@@ -221,7 +213,7 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
* (b) IPv6 information for IPv6 only interfaces (probably tunnels)
*
* For compatibility with previous releases we use the naming
* information gotten from enumInterfaces_win() for (a) entries
* information gotten from enumInterfaces() for (a) entries
* However, the index numbers are taken from the new API.
*
* The procedure is to go through the list of adapters returned
......@@ -439,7 +431,8 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
netifObj = (*env)->NewObject(env, ni_class, ni_ctor);
name = (*env)->NewStringUTF(env, ifs->name);
if (ifs->dNameIsUnicode) {
displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, wcslen ((PWCHAR)ifs->displayName));
displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,
(jsize)wcslen ((PWCHAR)ifs->displayName));
} else {
displayName = (*env)->NewStringUTF(env, ifs->displayName);
}
......
......@@ -39,10 +39,6 @@
/* true if SO_RCVTIMEO is supported */
jboolean isRcvTimeoutSupported = JNI_TRUE;
LPFN_GETADDRINFO getaddrinfo_ptr = NULL;
LPFN_FREEADDRINFO freaddrinfo_ptr = NULL;
LPFN_GETNAMEINFO getnameinfo_ptr = NULL;
/*
* Table of Windows Sockets errors, the specific exception we
* throw for the error, and the error text.
......@@ -233,38 +229,15 @@ NET_GetFileDescriptorID(JNIEnv *env)
jint IPv6_supported()
{
HMODULE lib;
int fd = socket(AF_INET6, SOCK_STREAM, 0) ;
if (fd < 0) {
return JNI_FALSE;
}
closesocket (fd);
if ((lib = LoadLibrary ("ws2_32.dll")) == NULL) {
return JNI_FALSE;
}
if ((getaddrinfo_ptr = (LPFN_GETADDRINFO)GetProcAddress (lib, "getaddrinfo")) == NULL) {
FreeLibrary (lib);
SOCKET s = socket(AF_INET6, SOCK_STREAM, 0) ;
if (s < 0) {
return JNI_FALSE;
}
if ((freeaddrinfo_ptr = (LPFN_FREEADDRINFO)GetProcAddress (lib, "freeaddrinfo")) == NULL) {
FreeLibrary (lib);
return JNI_FALSE;
}
if ((getnameinfo_ptr = (LPFN_GETNAMEINFO)GetProcAddress (lib, "getnameinfo")) == NULL) {
FreeLibrary (lib);
return JNI_FALSE;
}
FreeLibrary(lib);
closesocket(s);
return JNI_TRUE;
}
jboolean NET_addrtransAvailable() {
return (jboolean)(getaddrinfo_ptr != NULL);
}
/*
* Return the default TOS value
*/
......@@ -664,7 +637,7 @@ NET_BindV6(struct ipv6bind* b) {
if (family == AF_INET && (b->addr->him4.sin_addr.s_addr != INADDR_ANY)) {
/* bind to v4 only */
int ret;
ret = NET_Bind (b->ipv4_fd, (struct sockaddr *)b->addr,
ret = NET_Bind ((int)b->ipv4_fd, (struct sockaddr *)b->addr,
sizeof (struct sockaddr_in));
if (ret == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
......@@ -676,7 +649,7 @@ NET_BindV6(struct ipv6bind* b) {
if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->him6.sin6_addr))) {
/* bind to v6 only */
int ret;
ret = NET_Bind (b->ipv6_fd, (struct sockaddr *)b->addr,
ret = NET_Bind ((int)b->ipv6_fd, (struct sockaddr *)b->addr,
sizeof (struct SOCKADDR_IN6));
if (ret == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
......@@ -691,15 +664,15 @@ NET_BindV6(struct ipv6bind* b) {
memset (&oaddr, 0, sizeof(oaddr));
if (family == AF_INET) {
ofamily = AF_INET6;
fd = b->ipv4_fd;
ofd = b->ipv6_fd;
fd = (int)b->ipv4_fd;
ofd = (int)b->ipv6_fd;
port = (u_short)GET_PORT (b->addr);
IN6ADDR_SETANY (&oaddr.him6);
oaddr.him6.sin6_port = port;
} else {
ofamily = AF_INET;
ofd = b->ipv4_fd;
fd = b->ipv6_fd;
ofd = (int)b->ipv4_fd;
fd = (int)b->ipv6_fd;
port = (u_short)GET_PORT (b->addr);
oaddr.him4.sin_family = AF_INET;
oaddr.him4.sin_port = port;
......@@ -744,11 +717,11 @@ NET_BindV6(struct ipv6bind* b) {
b->ipv6_fd = SOCKET_ERROR;
/* create two new sockets */
fd = socket (family, sotype, 0);
fd = (int)socket (family, sotype, 0);
if (fd == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
}
ofd = socket (ofamily, sotype, 0);
ofd = (int)socket (ofamily, sotype, 0);
if (ofd == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
}
......@@ -1001,10 +974,10 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
}
int NET_Socket (int domain, int type, int protocol) {
int sock;
SOCKET sock;
sock = socket (domain, type, protocol);
if (sock != INVALID_SOCKET) {
SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE);
}
return sock;
return (int)sock;
}
......@@ -209,10 +209,6 @@ int
);
#endif
LPFN_GETADDRINFO getaddrinfo_ptr;
LPFN_FREEADDRINFO freeaddrinfo_ptr;
LPFN_GETNAMEINFO getnameinfo_ptr;
/* used to disable connection reset messages on Windows XP */
#ifndef SIO_UDP_CONNRESET
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
......@@ -302,8 +298,6 @@ void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
void NET_ThrowSocketException(JNIEnv *env, char* msg);
jboolean NET_addrtransAvailable();
/*
* differs from NET_Timeout() as follows:
*
......
/*
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -30,6 +30,7 @@
#include <iprtrmib.h>
#include <time.h>
#include <assert.h>
#include <iphlpapi.h>
#include "jni_util.h"
......@@ -42,93 +43,17 @@
#define IS_SL_FOUND(sts) (sts & STS_SL_FOUND)
#define IS_NS_FOUND(sts) (sts & STS_NS_FOUND)
/*
* Visual C++ SP3 (as required by J2SE 1.4.0) is missing some of
* the definitions required for the IP helper library routines that
* were added in Windows 98 & Windows 2000.
*/
#ifndef MAX_ADAPTER_NAME_LENGTH
#define MAX_ADAPTER_ADDRESS_LENGTH 8
#define MAX_ADAPTER_DESCRIPTION_LENGTH 128
#define MAX_ADAPTER_NAME_LENGTH 256
#define MAX_HOSTNAME_LEN 128
#define MAX_DOMAIN_NAME_LEN 128
#define MAX_SCOPE_ID_LEN 256
typedef struct {
char String[4 * 4];
} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
typedef struct _IP_ADDR_STRING {
struct _IP_ADDR_STRING* Next;
IP_ADDRESS_STRING IpAddress;
IP_MASK_STRING IpMask;
DWORD Context;
} IP_ADDR_STRING, *PIP_ADDR_STRING;
typedef struct _IP_ADAPTER_INFO {
struct _IP_ADAPTER_INFO* Next;
DWORD ComboIndex;
char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
UINT AddressLength;
BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD Index;
UINT Type;
UINT DhcpEnabled;
PIP_ADDR_STRING CurrentIpAddress;
IP_ADDR_STRING IpAddressList;
IP_ADDR_STRING GatewayList;
IP_ADDR_STRING DhcpServer;
BOOL HaveWins;
IP_ADDR_STRING PrimaryWinsServer;
IP_ADDR_STRING SecondaryWinsServer;
time_t LeaseObtained;
time_t LeaseExpires;
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
typedef struct _FIXED_INFO {
char HostName[MAX_HOSTNAME_LEN + 4] ;
char DomainName[MAX_DOMAIN_NAME_LEN + 4];
PIP_ADDR_STRING CurrentDnsServer;
IP_ADDR_STRING DnsServerList;
UINT NodeType;
char ScopeId[MAX_SCOPE_ID_LEN + 4];
UINT EnableRouting;
UINT EnableProxy;
UINT EnableDns;
} FIXED_INFO, *PFIXED_INFO;
#endif
/* IP helper library routine used on 98/2000/XP */
static int (PASCAL FAR *GetNetworkParams_fn)();
static int (PASCAL FAR *GetAdaptersInfo_fn)();
static int (PASCAL FAR *NotifyAddrChange_fn)();
/*
* Routines to obtain domain name and name servers are OS specific
*/
typedef int (*LoadConfig)(char *sl, char *ns);
static LoadConfig loadconfig_fn;
/*
* JNI ids
*/
/* JNI ids */
static jfieldID searchlistID;
static jfieldID nameserversID;
/*
* Utility routine to append s2 to s1 with a space delimiter.
* strappend(s1="abc", "def") => "abc def"
* strappend(s1="", "def") => "def
*/
void strappend(char *s1, char *s2) {
int len;
size_t len;
if (s2[0] == '\0') /* nothing to append */
return;
......@@ -145,356 +70,6 @@ void strappend(char *s1, char *s2) {
strcat(s1, s2);
}
/*
* Windows 95/98/ME for static TCP/IP configuration.
*
* Use registry approach for statically configured TCP/IP settings.
* Registry entries described in "MS TCP/IP and Windows 95 Networking"
* (Microsoft TechNet site).
*/
static int loadStaticConfig9x(char *sl, char *ns) {
LONG ret;
HANDLE hKey;
DWORD dwLen;
ULONG ulType;
char result[MAX_STR_LEN];
int sts = STS_NO_CONFIG;
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP",
0,
KEY_READ,
(PHKEY)&hKey);
if (ret == ERROR_SUCCESS) {
/*
* Determine suffix list
*/
result[0] = '\0';
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "SearchList", NULL, &ulType,
(LPBYTE)&result, &dwLen);
if ((ret != ERROR_SUCCESS) || (strlen(result) == 0)) {
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "Domain", NULL, &ulType,
(LPBYTE)&result, &dwLen);
}
if (ret == ERROR_SUCCESS) {
assert(ulType == REG_SZ);
if (strlen(result) > 0) {
strappend(sl, result);
sts |= STS_SL_FOUND;
}
}
/*
* Determine DNS name server(s)
*/
result[0] = '\0';
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "NameServer", NULL, &ulType,
(LPBYTE)&result, &dwLen);
if (ret == ERROR_SUCCESS) {
assert(ulType == REG_SZ);
if (strlen(result) > 0) {
strappend(ns, result);
sts |= STS_NS_FOUND;
}
}
RegCloseKey(hKey);
}
return sts;
}
/*
* Windows 95
*
* Use registry approach for statically configured TCP/IP settings
* (see loadStaticConfig9x).
*
* If DHCP is used we examine the DHCP vendor specific extensions. We parse
* this based on format described in RFC 2132.
*
* If Dial-up Networking (DUN) is used then this TCP/IP settings cannot
* be determined here.
*/
static int loadConfig95(char *sl, char *ns) {
int sts;
int index;
LONG ret;
HANDLE hKey;
DWORD dwLen;
ULONG ulType;
char optionInfo[MAX_STR_LEN];
/*
* First try static configuration - if found we are done.
*/
sts = loadStaticConfig9x(sl, ns);
if (IS_SL_FOUND(sts) && IS_NS_FOUND(sts)) {
return sts;
}
/*
* Try DHCP. DHCP information is stored in :-
* SYSTEM\CurrentControlSet\Services\VxD\DHCP\DhcpInfoXX
*
* The key is normally DhcpInfo00\OptionInfo (see Article Q255245 on
* Microsoft site). However when multiple cards are added & removed we
* have observed that it can be located in DhcpInfo{01,02, ...}.
* As a hack we search all DhcpInfoXX keys until we find OptionInfo.
*/
for (index=0; index<99; index++) {
char key[MAX_STR_LEN];
sprintf(key, "SYSTEM\\CurrentControlSet\\Services\\VxD\\DHCP\\DhcpInfo%02d",
index);
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, (PHKEY)&hKey);
if (ret != ERROR_SUCCESS) {
/* end of DhcpInfoXX entries */
break;
}
dwLen = sizeof(optionInfo);
ret = RegQueryValueEx(hKey, "OptionInfo", NULL, &ulType,
(LPBYTE)optionInfo, &dwLen);
RegCloseKey(hKey);
if (ret == ERROR_SUCCESS) {
/* OptionInfo found */
break;
}
}
/*
* If OptionInfo was found then we parse (as the 'options' field of
* the DHCP packet - see RFC 2132).
*/
if (ret == ERROR_SUCCESS) {
unsigned int pos = 0;
while (pos < dwLen) {
int code, len;
code = optionInfo[pos];
pos++;
if (pos >= dwLen) break; /* bad packet */
len = optionInfo[pos];
pos++;
if (pos+len > dwLen) break; /* bad packet */
/*
* Domain Name - see RFC 2132 section 3.17
*/
if (!IS_SL_FOUND(sts)) {
if (code == 0xf) {
char domain[MAX_STR_LEN];
assert(len < MAX_STR_LEN);
memcpy((void *)domain, (void *)&(optionInfo[pos]), (size_t)len);
domain[len] = '\0';
strappend(sl, domain);
sts |= STS_SL_FOUND;
}
}
/*
* DNS Option - see RFC 2132 section 3.8
*/
if (!IS_NS_FOUND(sts)) {
if (code == 6 && (len % 4) == 0) {
while (len > 0 && pos < dwLen) {
char addr[32];
sprintf(addr, "%d.%d.%d.%d",
(unsigned char)optionInfo[pos],
(unsigned char)optionInfo[pos+1],
(unsigned char)optionInfo[pos+2],
(unsigned char)optionInfo[pos+3]);
pos += 4;
len -= 4;
/*
* Append to list of name servers
*/
strappend(ns, addr);
sts |= STS_NS_FOUND;
}
}
}
/*
* Onto the next options
*/
pos += len;
}
}
return sts;
}
/*
* Windows 98/ME
*
* Use registry approach for statically configured TCP/IP settings
* (see loadStaticConfig9x).
*
* If configuration is not static then use IP helper library routine
* GetNetworkParams to obtain the network settings which include the
* domain name and the DNS servers. Note that we use the registry in
* preference to GetNetworkParams as the domain name is not populated
* by GetNetworkParams if the configuration is static.
*/
static int loadConfig98(char *sl, char *ns) {
FIXED_INFO *infoP;
ULONG size;
DWORD ret;
int sts;
/*
* Use registry approach to pick up static configuation.
*/
sts = loadStaticConfig9x(sl, ns);
if (IS_SL_FOUND(sts) && IS_NS_FOUND(sts)) {
return sts;
}
/*
* Use IP helper library to obtain dynamic configuration (DHCP and
* DUN).
*/
size = sizeof(FIXED_INFO);
infoP = (FIXED_INFO *)malloc(size);
if (infoP) {
ret = (*GetNetworkParams_fn)(infoP, &size);
if (ret == ERROR_BUFFER_OVERFLOW) {
infoP = (FIXED_INFO *)realloc(infoP, size);
if (infoP != NULL)
ret = (*GetNetworkParams_fn)(infoP, &size);
}
}
if (infoP == NULL) {
return sts;
}
if (ret == ERROR_SUCCESS) {
/*
* Use DomainName if search-list not specified.
*/
if (!IS_SL_FOUND(sts)) {
strappend(sl, infoP->DomainName);
sts |= STS_SL_FOUND;
}
/*
* Use DnsServerList if not statically configured.
*/
if (!IS_NS_FOUND(sts)) {
PIP_ADDR_STRING dnsP = &(infoP->DnsServerList);
do {
strappend(ns, (char *)&(dnsP->IpAddress));
dnsP = dnsP->Next;
} while (dnsP != NULL);
sts |= STS_NS_FOUND;
}
}
free(infoP);
return sts;
}
/*
* Windows NT
*
* Use registry approach based on settings described in "TCP/IP and
* NBT Configuration Parameters for Windows" - Article Q12062 on
* Microsoft site.
*
* All non-RAS TCP/IP settings are stored in HKEY_LOCAL_MACHINE in
* the SYSTEM\CurrentControlSet\Services\Tcpip\Parameters key.
*
* If SearchList if not provided then return Domain or DhcpDomain.
* If Domain is specified it overrides DhcpDomain even if DHCP is
* enabled.
*
* DNS name servers based on NameServer or DhcpNameServer settings.
* NameServer overrides DhcpNameServer even if DHCP is enabled.
*/
static int loadConfigNT(char *sl, char *ns) {
LONG ret;
HANDLE hKey;
DWORD dwLen;
ULONG ulType;
char result[MAX_STR_LEN];
int sts = STS_NO_CONFIG;
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
0,
KEY_READ,
(PHKEY)&hKey);
if (ret != ERROR_SUCCESS) {
return sts;
}
/*
* Determine search list
*/
result[0] = '\0';
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "SearchList", NULL, &ulType,
(LPBYTE)&result, &dwLen);
if ((ret != ERROR_SUCCESS) || (strlen(result) == 0)) {
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "Domain", NULL, &ulType,
(LPBYTE)&result, &dwLen);
if ((ret != ERROR_SUCCESS) || (strlen(result) == 0)) {
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "DhcpDomain", NULL, &ulType,
(LPBYTE)&result, &dwLen);
}
}
if (ret == ERROR_SUCCESS) {
assert(ulType == REG_SZ);
if (strlen(result) > 0) {
strappend(sl, result);
sts |= STS_SL_FOUND;
}
}
/*
* Determine DNS name server(s)
*/
result[0] = '\0';
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "NameServer", NULL, &ulType,
(LPBYTE)&result, &dwLen);
if ((ret != ERROR_SUCCESS) || (strlen(result) == 0)) {
dwLen = sizeof(result);
ret = RegQueryValueEx(hKey, "DhcpNameServer", NULL, &ulType,
(LPBYTE)&result, &dwLen);
}
if (ret == ERROR_SUCCESS) {
assert(ulType == REG_SZ);
if (strlen(result) > 0) {
strappend(ns, result);
sts |= STS_NS_FOUND;
}
}
RegCloseKey(hKey);
return sts;
}
/*
* Windows 2000/XP
*
......@@ -510,7 +85,7 @@ static int loadConfigNT(char *sl, char *ns) {
* names of each adapter and then query the corresponding registry
* settings to obtain NameServer/DhcpNameServer and Domain/DhcpDomain.
*/
static int loadConfig2000(char *sl, char *ns) {
static int loadConfig(char *sl, char *ns) {
IP_ADAPTER_INFO *adapterP;
ULONG size;
DWORD ret;
......@@ -547,10 +122,10 @@ static int loadConfig2000(char *sl, char *ns) {
*/
size = sizeof(IP_ADAPTER_INFO);
adapterP = (IP_ADAPTER_INFO *)malloc(size);
ret = (*GetAdaptersInfo_fn)(adapterP, &size);
ret = GetAdaptersInfo(adapterP, &size);
if (ret == ERROR_BUFFER_OVERFLOW) {
adapterP = (IP_ADAPTER_INFO *)realloc(adapterP, size);
ret = (*GetAdaptersInfo_fn)(adapterP, &size);
ret = GetAdaptersInfo(adapterP, &size);
}
/*
......@@ -648,87 +223,15 @@ static int loadConfig2000(char *sl, char *ns) {
/*
* Initialization :-
*
* 1. Based on OS version set the function pointer for OS specific load
* configuration routine.
*
* 2. On 98/2000/XP load the IP helper library.
*
* 3. Initialize JNI field IDs.
*
* Initialize JNI field IDs.
*/
JNIEXPORT void JNICALL
Java_sun_net_dns_ResolverConfigurationImpl_init0(JNIEnv *env, jclass cls)
{
OSVERSIONINFO ver;
jboolean loadHelperLibrary = JNI_TRUE;
/*
* First we figure out which OS is running
*/
ver.dwOSVersionInfoSize = sizeof(ver);
GetVersionEx(&ver);
if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
if ((ver.dwMajorVersion == 4) && (ver.dwMinorVersion == 0)) {
/*
* Windows 95
*/
loadHelperLibrary = JNI_FALSE;
loadconfig_fn = loadConfig95;
} else {
/*
* Windows 98/ME
*/
loadHelperLibrary = JNI_TRUE;
loadconfig_fn = loadConfig98;
}
}
if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
if (ver.dwMajorVersion <= 4) {
/*
* Windows NT
*/
loadHelperLibrary = JNI_FALSE;
loadconfig_fn = loadConfigNT;
} else {
/*
* Windows 2000/XP
*/
loadHelperLibrary = JNI_TRUE;
loadconfig_fn = loadConfig2000;
}
}
/*
* On 98/2000/XP we load the IP Helper Library.
*/
if (loadHelperLibrary) {
HANDLE h = LoadLibrary("iphlpapi.dll");
if (h != NULL) {
GetNetworkParams_fn = (int (PASCAL FAR *)())GetProcAddress(h, "GetNetworkParams");
GetAdaptersInfo_fn = (int (PASCAL FAR *)())GetProcAddress(h, "GetAdaptersInfo");
NotifyAddrChange_fn = (int (PASCAL FAR *)())GetProcAddress(h, "NotifyAddrChange");
}
if (GetNetworkParams_fn == NULL || GetAdaptersInfo_fn == NULL) {
JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", "iphlpapi.dll");
return;
}
}
/*
* Get JNI ids
*/
searchlistID = (*env)->GetStaticFieldID(env, cls, "os_searchlist",
"Ljava/lang/String;");
nameserversID = (*env)->GetStaticFieldID(env, cls, "os_nameservers",
"Ljava/lang/String;");
}
/*
......@@ -746,8 +249,7 @@ Java_sun_net_dns_ResolverConfigurationImpl_loadDNSconfig0(JNIEnv *env, jclass cl
searchlist[0] = '\0';
nameservers[0] = '\0';
/* call OS specific routine */
(void)(*loadconfig_fn)(searchlist, nameservers);
loadConfig(searchlist, nameservers);
/*
* Populate static fields in sun.net.DefaultResolverConfiguration
......@@ -772,17 +274,15 @@ Java_sun_net_dns_ResolverConfigurationImpl_notifyAddrChange0(JNIEnv *env, jclass
HANDLE h;
DWORD rc, xfer;
if (NotifyAddrChange_fn != NULL) {
ol.hEvent = (HANDLE)0;
rc = (*NotifyAddrChange_fn)(&h, &ol);
if (rc == ERROR_IO_PENDING) {
rc = GetOverlappedResult(h, &ol, &xfer, TRUE);
if (rc != 0) {
return 0; /* address changed */
}
ol.hEvent = (HANDLE)0;
rc = NotifyAddrChange(&h, &ol);
if (rc == ERROR_IO_PENDING) {
rc = GetOverlappedResult(h, &ol, &xfer, TRUE);
if (rc != 0) {
return 0; /* address changed */
}
}
/* NotifyAddrChange not support or error */
/* error */
return -1;
}
......@@ -41,18 +41,6 @@
#define SECURITY_WIN32
#include "sspi.h"
/*
* OS calls loaded from DLL on intialization
*/
static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
static ACQUIRE_CREDENTIALS_HANDLE_FN pAcquireCredentialsHandle;
static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
static INITIALIZE_SECURITY_CONTEXT_FN pInitializeSecurityContext;
static COMPLETE_AUTH_TOKEN_FN pCompleteAuthToken;
static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle);
static jfieldID ntlm_ctxHandleID;
......@@ -63,48 +51,8 @@ static HINSTANCE lib = NULL;
JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst
(JNIEnv *env, jclass clazz)
{
OSVERSIONINFO version;
UCHAR libName[MAX_PATH];
ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&version);
if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
strcpy (libName, "security.dll" );
}
else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
strcpy (libName, "secur32.dll" );
}
lib = LoadLibrary (libName);
pFreeCredentialsHandle
= (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(
lib, "FreeCredentialsHandle" );
pAcquireCredentialsHandle
= (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(
lib, "AcquireCredentialsHandleA" );
pFreeContextBuffer
= (FREE_CONTEXT_BUFFER_FN) GetProcAddress(
lib, "FreeContextBuffer" );
pInitializeSecurityContext
= (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(
lib, "InitializeSecurityContextA" );
pCompleteAuthToken
= (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(
lib, "CompleteAuthToken" );
pDeleteSecurityContext
= (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(
lib, "DeleteSecurityContext" );
}
/*
......@@ -158,17 +106,17 @@ JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_get
if ( pUser != NULL ) {
AuthId.User = (unsigned char *) pUser;
AuthId.UserLength = strlen( pUser );
AuthId.UserLength = (unsigned long) strlen( pUser );
}
if ( pPassword != NULL ) {
AuthId.Password = (unsigned char *) pPassword;
AuthId.PasswordLength = strlen( pPassword );
AuthId.PasswordLength = (unsigned long) strlen( pPassword );
}
if ( pDomain != NULL ) {
AuthId.Domain = (unsigned char *) pDomain;
AuthId.DomainLength = strlen( pDomain );
AuthId.DomainLength = (unsigned long) strlen( pDomain );
}
AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
......@@ -176,7 +124,7 @@ JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_get
pAuthId = NULL;
}
ss = pAcquireCredentialsHandle(
ss = AcquireCredentialsHandleA(
NULL, "NTLM", SECPKG_CRED_OUTBOUND,
NULL, pAuthId, NULL, NULL,
pCred, &ltime
......@@ -258,7 +206,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequenc
* need to send the out buffer if there are bytes to send
*/
ss = pInitializeSecurityContext(
ss = InitializeSecurityContextA(
pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
&ContextAttributes, &ltime
......@@ -274,7 +222,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequenc
}
if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
ss = pCompleteAuthToken( pCtx, &OutBuffDesc );
ss = CompleteAuthToken( pCtx, &OutBuffDesc );
if (ss < 0) {
endSequence (pCred, pCtx);
......@@ -300,12 +248,12 @@ JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequenc
static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle) {
if (credHand != 0) {
pFreeCredentialsHandle (credHand);
free (credHand);
FreeCredentialsHandle(credHand);
free(credHand);
}
if (ctxHandle != 0) {
pDeleteSecurityContext(ctxHandle);
free (ctxHandle);
DeleteSecurityContext(ctxHandle);
free(ctxHandle);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册