author | michaelm |
Wed, 13 Feb 2013 10:40:31 +0000 | |
changeset 16870 | f35b2bd19761 |
parent 14342 | 8435a30053c1 |
child 20821 | e0d0a585aa49 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
14342
8435a30053c1
7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents:
13245
diff
changeset
|
2 |
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
#include <windows.h> |
|
27 |
#include <winsock2.h> |
|
28 |
#include <ctype.h> |
|
29 |
#include <stdio.h> |
|
30 |
#include <stdlib.h> |
|
31 |
#include <malloc.h> |
|
32 |
#include <sys/types.h> |
|
910 | 33 |
#include <process.h> |
2 | 34 |
|
35 |
#include "java_net_InetAddress.h" |
|
36 |
#include "java_net_Inet4AddressImpl.h" |
|
37 |
#include "java_net_Inet6AddressImpl.h" |
|
38 |
#include "net_util.h" |
|
39 |
#include "icmp.h" |
|
40 |
||
41 |
#ifdef WIN32 |
|
42 |
#ifndef _WIN64 |
|
43 |
||
44 |
/* Retain this code a little longer to support building in |
|
45 |
* old environments. _MSC_VER is defined as: |
|
46 |
* 1200 for MSVC++ 6.0 |
|
47 |
* 1310 for Vc7 |
|
48 |
*/ |
|
49 |
#if defined(_MSC_VER) && _MSC_VER < 1310 |
|
50 |
#define sockaddr_in6 SOCKADDR_IN6 |
|
51 |
#endif |
|
52 |
#endif |
|
53 |
#define uint32_t UINT32 |
|
54 |
#endif |
|
55 |
||
56 |
/* |
|
57 |
* Inet6AddressImpl |
|
58 |
*/ |
|
59 |
||
60 |
/* |
|
61 |
* Class: java_net_Inet6AddressImpl |
|
62 |
* Method: getLocalHostName |
|
63 |
* Signature: ()Ljava/lang/String; |
|
64 |
*/ |
|
65 |
JNIEXPORT jstring JNICALL |
|
66 |
Java_java_net_Inet6AddressImpl_getLocalHostName (JNIEnv *env, jobject this) { |
|
67 |
char hostname [256]; |
|
68 |
||
69 |
if (gethostname (hostname, sizeof (hostname)) == -1) { |
|
70 |
strcpy (hostname, "localhost"); |
|
71 |
} |
|
72 |
return JNU_NewStringPlatform (env, hostname); |
|
73 |
} |
|
74 |
||
75 |
static jclass ni_iacls; |
|
76 |
static jclass ni_ia4cls; |
|
77 |
static jclass ni_ia6cls; |
|
78 |
static jmethodID ni_ia4ctrID; |
|
79 |
static jmethodID ni_ia6ctrID; |
|
80 |
static jfieldID ni_ia6ipaddressID; |
|
81 |
static int initialized = 0; |
|
82 |
||
83 |
JNIEXPORT jobjectArray JNICALL |
|
84 |
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, |
|
85 |
jstring host) { |
|
86 |
const char *hostname; |
|
87 |
jobjectArray ret = 0; |
|
88 |
int retLen = 0; |
|
89 |
jboolean preferIPv6Address; |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
90 |
static jfieldID ia_preferIPv6AddressID; |
2 | 91 |
|
92 |
int error=0; |
|
93 |
struct addrinfo hints, *res, *resNew = NULL; |
|
94 |
||
95 |
if (!initialized) { |
|
96 |
ni_iacls = (*env)->FindClass(env, "java/net/InetAddress"); |
|
97 |
ni_iacls = (*env)->NewGlobalRef(env, ni_iacls); |
|
98 |
ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address"); |
|
99 |
ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls); |
|
100 |
ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address"); |
|
101 |
ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls); |
|
102 |
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V"); |
|
103 |
ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V"); |
|
104 |
ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B"); |
|
105 |
initialized = 1; |
|
106 |
} |
|
107 |
if (IS_NULL(host)) { |
|
108 |
JNU_ThrowNullPointerException(env, "host is null"); |
|
109 |
return 0; |
|
110 |
} |
|
111 |
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); |
|
112 |
CHECK_NULL_RETURN(hostname, NULL); |
|
113 |
||
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
114 |
if (ia_preferIPv6AddressID == NULL) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
115 |
jclass c = (*env)->FindClass(env,"java/net/InetAddress"); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
116 |
if (c) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
117 |
ia_preferIPv6AddressID = |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
118 |
(*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z"); |
2 | 119 |
} |
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
120 |
if (ia_preferIPv6AddressID == NULL) { |
2 | 121 |
JNU_ReleaseStringPlatformChars(env, host, hostname); |
122 |
return NULL; |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
123 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
124 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
125 |
/* get the address preference */ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
126 |
preferIPv6Address |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
127 |
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
128 |
|
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
129 |
/* Try once, with our static buffer. */ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
130 |
memset(&hints, 0, sizeof(hints)); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
131 |
hints.ai_flags = AI_CANONNAME; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
132 |
hints.ai_family = AF_UNSPEC; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
133 |
|
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
134 |
error = getaddrinfo(hostname, NULL, &hints, &res); |
2 | 135 |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
136 |
if (error) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
137 |
/* report error */ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
138 |
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
139 |
(char *)hostname); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
140 |
JNU_ReleaseStringPlatformChars(env, host, hostname); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
141 |
return NULL; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
142 |
} else { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
143 |
int i = 0; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
144 |
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
145 |
struct addrinfo *itr, *last, *iterator = res; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
146 |
while (iterator != NULL) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
147 |
int skip = 0; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
148 |
itr = resNew; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
149 |
while (itr != NULL) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
150 |
if (iterator->ai_family == itr->ai_family && |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
151 |
iterator->ai_addrlen == itr->ai_addrlen) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
152 |
if (itr->ai_family == AF_INET) { /* AF_INET */ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
153 |
struct sockaddr_in *addr1, *addr2; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
154 |
addr1 = (struct sockaddr_in *)iterator->ai_addr; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
155 |
addr2 = (struct sockaddr_in *)itr->ai_addr; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
156 |
if (addr1->sin_addr.s_addr == |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
157 |
addr2->sin_addr.s_addr) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
158 |
skip = 1; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
159 |
break; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
160 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
161 |
} else { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
162 |
int t; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
163 |
struct sockaddr_in6 *addr1, *addr2; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
164 |
addr1 = (struct sockaddr_in6 *)iterator->ai_addr; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
165 |
addr2 = (struct sockaddr_in6 *)itr->ai_addr; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
166 |
|
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
167 |
for (t = 0; t < 16; t++) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
168 |
if (addr1->sin6_addr.s6_addr[t] != |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
169 |
addr2->sin6_addr.s6_addr[t]) { |
2 | 170 |
break; |
171 |
} |
|
172 |
} |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
173 |
if (t < 16) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
174 |
itr = itr->ai_next; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
175 |
continue; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
176 |
} else { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
177 |
skip = 1; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
178 |
break; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
179 |
} |
2 | 180 |
} |
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
181 |
} else if (iterator->ai_family != AF_INET && |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
182 |
iterator->ai_family != AF_INET6) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
183 |
/* we can't handle other family types */ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
184 |
skip = 1; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
185 |
break; |
2 | 186 |
} |
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
187 |
itr = itr->ai_next; |
2 | 188 |
} |
189 |
||
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
190 |
if (!skip) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
191 |
struct addrinfo *next |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
192 |
= (struct addrinfo*) malloc(sizeof(struct addrinfo)); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
193 |
if (!next) { |
13245
7ab3ef5b9520
7181353: Update error message to distinguish native OOM and java OOM in net
zhouyx
parents:
9050
diff
changeset
|
194 |
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); |
2 | 195 |
ret = NULL; |
196 |
goto cleanupAndReturn; |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
197 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
198 |
memcpy(next, iterator, sizeof(struct addrinfo)); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
199 |
next->ai_next = NULL; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
200 |
if (resNew == NULL) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
201 |
resNew = next; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
202 |
} else { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
203 |
last->ai_next = next; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
204 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
205 |
last = next; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
206 |
i++; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
207 |
if (iterator->ai_family == AF_INET) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
208 |
inetCount ++; |
2 | 209 |
} else if (iterator->ai_family == AF_INET6) { |
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
210 |
inet6Count ++; |
2 | 211 |
} |
212 |
} |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
213 |
iterator = iterator->ai_next; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
214 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
215 |
retLen = i; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
216 |
iterator = resNew; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
217 |
i = 0; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
218 |
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
219 |
|
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
220 |
if (IS_NULL(ret)) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
221 |
/* we may have memory to free at the end of this */ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
222 |
goto cleanupAndReturn; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
223 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
224 |
|
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
225 |
if (preferIPv6Address) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
226 |
inetIndex = inet6Count; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
227 |
inet6Index = 0; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
228 |
} else { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
229 |
inetIndex = 0; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
230 |
inet6Index = inetCount; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
231 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
232 |
|
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
233 |
while (iterator != NULL) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
234 |
if (iterator->ai_family == AF_INET) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
235 |
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
236 |
if (IS_NULL(iaObj)) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
237 |
ret = NULL; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
238 |
goto cleanupAndReturn; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
239 |
} |
16870 | 240 |
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr)); |
241 |
setInetAddress_hostName(env, iaObj, host); |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
242 |
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
243 |
inetIndex ++; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
244 |
} else if (iterator->ai_family == AF_INET6) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
245 |
jint scope = 0; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
246 |
jbyteArray ipaddress; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
247 |
jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
248 |
if (IS_NULL(iaObj)) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
249 |
ret = NULL; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
250 |
goto cleanupAndReturn; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
251 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
252 |
ipaddress = (*env)->NewByteArray(env, 16); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
253 |
if (IS_NULL(ipaddress)) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
254 |
ret = NULL; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
255 |
goto cleanupAndReturn; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
256 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
257 |
(*env)->SetByteArrayRegion(env, ipaddress, 0, 16, |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
258 |
(jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
259 |
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
260 |
if (scope != 0) { /* zero is default value, no need to set */ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
261 |
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
262 |
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
263 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
264 |
(*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); |
16870 | 265 |
setInetAddress_hostName(env, iaObj, host); |
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
266 |
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
267 |
inet6Index ++; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
268 |
} |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
269 |
iterator = iterator->ai_next; |
2 | 270 |
} |
271 |
} |
|
272 |
||
273 |
cleanupAndReturn: |
|
274 |
{ |
|
275 |
struct addrinfo *iterator, *tmp; |
|
276 |
iterator = resNew; |
|
277 |
while (iterator != NULL) { |
|
278 |
tmp = iterator; |
|
279 |
iterator = iterator->ai_next; |
|
280 |
free(tmp); |
|
281 |
} |
|
282 |
JNU_ReleaseStringPlatformChars(env, host, hostname); |
|
283 |
} |
|
284 |
||
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
285 |
freeaddrinfo(res); |
2 | 286 |
|
287 |
return ret; |
|
288 |
} |
|
289 |
||
290 |
/* |
|
291 |
* Class: java_net_Inet6AddressImpl |
|
292 |
* Method: getHostByAddr |
|
293 |
* Signature: (I)Ljava/lang/String; |
|
294 |
*/ |
|
295 |
JNIEXPORT jstring JNICALL |
|
296 |
Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, |
|
297 |
jbyteArray addrArray) { |
|
298 |
jstring ret = NULL; |
|
299 |
||
300 |
char host[NI_MAXHOST+1]; |
|
301 |
int error = 0; |
|
302 |
int len = 0; |
|
303 |
jbyte caddr[16]; |
|
304 |
||
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
305 |
struct sockaddr_in him4; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
306 |
struct sockaddr_in6 him6; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
307 |
struct sockaddr *sa; |
2 | 308 |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
309 |
/* |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
310 |
* For IPv4 addresses construct a sockaddr_in structure. |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
311 |
*/ |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
312 |
if ((*env)->GetArrayLength(env, addrArray) == 4) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
313 |
jint addr; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
314 |
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
315 |
addr = ((caddr[0]<<24) & 0xff000000); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
316 |
addr |= ((caddr[1] <<16) & 0xff0000); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
317 |
addr |= ((caddr[2] <<8) & 0xff00); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
318 |
addr |= (caddr[3] & 0xff); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
319 |
memset((char *) &him4, 0, sizeof(him4)); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
320 |
him4.sin_addr.s_addr = (uint32_t) htonl(addr); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
321 |
him4.sin_family = AF_INET; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
322 |
sa = (struct sockaddr *) &him4; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
323 |
len = sizeof(him4); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
324 |
} else { |
2 | 325 |
/* |
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
326 |
* For IPv6 address construct a sockaddr_in6 structure. |
2 | 327 |
*/ |
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
328 |
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
329 |
memset((char *) &him6, 0, sizeof(him6)); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
330 |
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
331 |
him6.sin6_family = AF_INET6; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
332 |
sa = (struct sockaddr *) &him6 ; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
333 |
len = sizeof(him6) ; |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
334 |
} |
2 | 335 |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
336 |
error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD); |
2 | 337 |
|
9003
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
338 |
if (!error) { |
e1b0f0099915
7030256: Cleanup/Remove code supporting old Windows versions (98, NT, 2000, etc)
chegar
parents:
7814
diff
changeset
|
339 |
ret = (*env)->NewStringUTF(env, host); |
2 | 340 |
} |
341 |
||
342 |
if (ret == NULL) { |
|
343 |
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL); |
|
344 |
} |
|
345 |
||
346 |
return ret; |
|
347 |
} |
|
348 |
||
349 |
#ifdef AF_INET6 |
|
350 |
||
351 |
||
352 |
/** |
|
353 |
* ping implementation. |
|
354 |
* Send a ICMP_ECHO_REQUEST packet every second until either the timeout |
|
355 |
* expires or a answer is received. |
|
356 |
* Returns true is an ECHO_REPLY is received, otherwise, false. |
|
357 |
*/ |
|
358 |
static jboolean |
|
359 |
ping6(JNIEnv *env, jint fd, struct SOCKADDR_IN6* him, jint timeout, |
|
360 |
struct SOCKADDR_IN6* netif, jint ttl) { |
|
361 |
jint size; |
|
910 | 362 |
jint n, len, i; |
2 | 363 |
char sendbuf[1500]; |
364 |
char auxbuf[1500]; |
|
365 |
unsigned char recvbuf[1500]; |
|
366 |
struct icmp6_hdr *icmp6; |
|
367 |
struct SOCKADDR_IN6 sa_recv; |
|
368 |
unsigned short pid, seq; |
|
369 |
int read_rv = 0; |
|
370 |
WSAEVENT hEvent; |
|
371 |
struct ip6_pseudo_hdr *pseudo_ip6; |
|
372 |
int timestamp; |
|
373 |
int tmout2; |
|
374 |
||
375 |
/* Initialize the sequence number to a suitable random number and |
|
376 |
shift right one place to allow sufficient room for increamenting. */ |
|
377 |
seq = ((unsigned short)rand()) >> 1; |
|
378 |
||
379 |
/* icmp_id is a 16 bit data type, therefore down cast the pid */ |
|
910 | 380 |
pid = (unsigned short) _getpid(); |
2 | 381 |
|
382 |
size = 60*1024; |
|
383 |
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&size, sizeof(size)); |
|
384 |
/** |
|
385 |
* A TTL was specified, let's set the socket option. |
|
386 |
*/ |
|
387 |
if (ttl > 0) { |
|
388 |
setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const char *) &ttl, sizeof(ttl)); |
|
389 |
} |
|
390 |
||
391 |
/** |
|
392 |
* A network interface was specified, let's bind to it. |
|
393 |
*/ |
|
394 |
if (netif != NULL) { |
|
395 |
if (NET_Bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) < 0){ |
|
396 |
NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket to interface"); |
|
397 |
closesocket(fd); |
|
398 |
return JNI_FALSE; |
|
399 |
} |
|
400 |
} |
|
401 |
||
402 |
/* |
|
403 |
* Make the socket non blocking |
|
404 |
*/ |
|
405 |
hEvent = WSACreateEvent(); |
|
406 |
WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE); |
|
407 |
||
408 |
/** |
|
409 |
* send 1 ICMP REQUEST every second until either we get a valid reply |
|
410 |
* or the timeout expired. |
|
411 |
*/ |
|
412 |
do { |
|
413 |
/* let's tag the ECHO packet with our pid so we can identify it */ |
|
414 |
timestamp = GetCurrentTime(); |
|
415 |
memset(sendbuf, 0, 1500); |
|
416 |
icmp6 = (struct icmp6_hdr *) sendbuf; |
|
417 |
icmp6->icmp6_type = ICMP6_ECHO_REQUEST; |
|
418 |
icmp6->icmp6_code = 0; |
|
419 |
icmp6->icmp6_id = htons(pid); |
|
420 |
icmp6->icmp6_seq = htons(seq); |
|
421 |
icmp6->icmp6_cksum = 0; |
|
422 |
memcpy((icmp6 + 1), ×tamp, sizeof(int)); |
|
423 |
if (netif != NULL) { |
|
424 |
memset(auxbuf, 0, 1500); |
|
425 |
pseudo_ip6 = (struct ip6_pseudo_hdr*) auxbuf; |
|
426 |
memcpy(&pseudo_ip6->ip6_src, &netif->sin6_addr, sizeof(struct in6_addr)); |
|
427 |
memcpy(&pseudo_ip6->ip6_dst, &him->sin6_addr, sizeof(struct in6_addr)); |
|
428 |
pseudo_ip6->ip6_plen= htonl( 64 ); |
|
429 |
pseudo_ip6->ip6_nxt = htonl( IPPROTO_ICMPV6 ); |
|
430 |
memcpy(auxbuf + sizeof(struct ip6_pseudo_hdr), icmp6, 64); |
|
431 |
/** |
|
432 |
* We shouldn't have to do that as computing the checksum is supposed |
|
433 |
* to be done by the IPv6 stack. Unfortunately windows, here too, is |
|
434 |
* uterly broken, or non compliant, so let's do it. |
|
435 |
* Problem is to compute the checksum I need to know the source address |
|
436 |
* which happens only if I know the interface to be used... |
|
437 |
*/ |
|
438 |
icmp6->icmp6_cksum = in_cksum((u_short *)pseudo_ip6, sizeof(struct ip6_pseudo_hdr) + 64); |
|
439 |
} |
|
440 |
||
441 |
/** |
|
442 |
* Ping! |
|
443 |
*/ |
|
444 |
n = sendto(fd, sendbuf, 64, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6)); |
|
445 |
if (n < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEADDRNOTAVAIL)) { |
|
446 |
// Happens when using a "tunnel interface" for instance. |
|
447 |
// Or trying to send a packet on a different scope. |
|
448 |
closesocket(fd); |
|
449 |
WSACloseEvent(hEvent); |
|
450 |
return JNI_FALSE; |
|
451 |
} |
|
452 |
if (n < 0 && WSAGetLastError() != WSAEWOULDBLOCK) { |
|
453 |
NET_ThrowNew(env, WSAGetLastError(), "Can't send ICMP packet"); |
|
454 |
closesocket(fd); |
|
455 |
WSACloseEvent(hEvent); |
|
456 |
return JNI_FALSE; |
|
457 |
} |
|
458 |
||
459 |
tmout2 = timeout > 1000 ? 1000 : timeout; |
|
460 |
do { |
|
461 |
tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2); |
|
462 |
||
463 |
if (tmout2 >= 0) { |
|
464 |
len = sizeof(sa_recv); |
|
465 |
memset(recvbuf, 0, 1500); |
|
466 |
/** |
|
467 |
* For some unknown reason, besides plain stupidity, windows |
|
468 |
* truncates the first 4 bytes of the icmpv6 header some we can't |
|
469 |
* check for the ICMP_ECHOREPLY value. |
|
470 |
* we'll check the other values, though |
|
471 |
*/ |
|
472 |
n = recvfrom(fd, recvbuf + 4, sizeof(recvbuf) - 4, 0, (struct sockaddr*) &sa_recv, &len); |
|
473 |
icmp6 = (struct icmp6_hdr *) (recvbuf); |
|
474 |
memcpy(&i, (icmp6 + 1), sizeof(int)); |
|
475 |
/** |
|
476 |
* Is that the reply we were expecting? |
|
477 |
*/ |
|
478 |
if (n >= 8 && ntohs(icmp6->icmp6_seq) == seq && |
|
479 |
ntohs(icmp6->icmp6_id) == pid && i == timestamp) { |
|
480 |
closesocket(fd); |
|
481 |
WSACloseEvent(hEvent); |
|
482 |
return JNI_TRUE; |
|
483 |
} |
|
484 |
} |
|
485 |
} while (tmout2 > 0); |
|
486 |
timeout -= 1000; |
|
487 |
seq++; |
|
488 |
} while (timeout > 0); |
|
489 |
closesocket(fd); |
|
490 |
WSACloseEvent(hEvent); |
|
491 |
return JNI_FALSE; |
|
492 |
} |
|
493 |
#endif /* AF_INET6 */ |
|
494 |
||
495 |
/* |
|
496 |
* Class: java_net_Inet6AddressImpl |
|
497 |
* Method: isReachable0 |
|
498 |
* Signature: ([bII[bI)Z |
|
499 |
*/ |
|
500 |
JNIEXPORT jboolean JNICALL |
|
501 |
Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this, |
|
502 |
jbyteArray addrArray, |
|
503 |
jint scope, |
|
504 |
jint timeout, |
|
505 |
jbyteArray ifArray, |
|
506 |
jint ttl, jint if_scope) { |
|
507 |
#ifdef AF_INET6 |
|
508 |
jbyte caddr[16]; |
|
509 |
jint fd, sz; |
|
510 |
struct sockaddr_in6 him6; |
|
511 |
struct sockaddr_in6* netif = NULL; |
|
512 |
struct sockaddr_in6 inf6; |
|
513 |
WSAEVENT hEvent; |
|
514 |
int len = 0; |
|
515 |
int connect_rv = -1; |
|
516 |
||
517 |
/* |
|
518 |
* If IPv6 is not enable, then we can't reach an IPv6 address, can we? |
|
519 |
* Actually, we probably shouldn't even get here. |
|
520 |
*/ |
|
521 |
if (!ipv6_available()) { |
|
522 |
return JNI_FALSE; |
|
523 |
} |
|
524 |
/* |
|
525 |
* If it's an IPv4 address, ICMP won't work with IPv4 mapped address, |
|
526 |
* therefore, let's delegate to the Inet4Address method. |
|
527 |
*/ |
|
528 |
sz = (*env)->GetArrayLength(env, addrArray); |
|
529 |
if (sz == 4) { |
|
530 |
return Java_java_net_Inet4AddressImpl_isReachable0(env, this, |
|
531 |
addrArray, |
|
532 |
timeout, |
|
533 |
ifArray, ttl); |
|
534 |
} |
|
535 |
||
536 |
memset((char *) caddr, 0, 16); |
|
537 |
memset((char *) &him6, 0, sizeof(him6)); |
|
538 |
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); |
|
539 |
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); |
|
540 |
him6.sin6_family = AF_INET6; |
|
541 |
if (scope > 0) { |
|
542 |
him6.sin6_scope_id = scope; |
|
543 |
} |
|
544 |
len = sizeof(struct sockaddr_in6); |
|
545 |
/** |
|
546 |
* A network interface was specified, let's convert the address |
|
547 |
*/ |
|
548 |
if (!(IS_NULL(ifArray))) { |
|
549 |
memset((char *) caddr, 0, 16); |
|
550 |
memset((char *) &inf6, 0, sizeof(inf6)); |
|
551 |
(*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr); |
|
552 |
memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) ); |
|
553 |
inf6.sin6_family = AF_INET6; |
|
554 |
inf6.sin6_port = 0; |
|
555 |
inf6.sin6_scope_id = if_scope; |
|
556 |
netif = &inf6; |
|
557 |
} |
|
558 |
||
559 |
#if 0 |
|
560 |
/* |
|
561 |
* Windows implementation of ICMP & RAW sockets is too unreliable for now. |
|
562 |
* Therefore it's best not to try it at all and rely only on TCP |
|
563 |
* We may revisit and enable this code in the future. |
|
564 |
*/ |
|
565 |
||
566 |
/* |
|
567 |
* Right now, windows doesn't generate the ICMP checksum automatically |
|
568 |
* so we have to compute it, but we can do it only if we know which |
|
569 |
* interface will be used. Therefore, don't try to use ICMP if no |
|
570 |
* interface was specified. |
|
571 |
* When ICMPv6 support improves in windows, we may change this. |
|
572 |
*/ |
|
573 |
if (!(IS_NULL(ifArray))) { |
|
574 |
/* |
|
575 |
* If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST |
|
576 |
* otherwise we'll try a tcp socket to the Echo port (7). |
|
577 |
* Note that this is empiric, and not connecting could mean it's blocked |
|
578 |
* or the echo servioe has been disabled. |
|
579 |
*/ |
|
580 |
fd = NET_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); |
|
581 |
||
582 |
if (fd != -1) { /* Good to go, let's do a ping */ |
|
583 |
return ping6(env, fd, &him6, timeout, netif, ttl); |
|
584 |
} |
|
585 |
} |
|
586 |
#endif |
|
587 |
||
588 |
/* No good, let's fall back on TCP */ |
|
589 |
fd = NET_Socket(AF_INET6, SOCK_STREAM, 0); |
|
590 |
if (fd == JVM_IO_ERR) { |
|
591 |
/* note: if you run out of fds, you may not be able to load |
|
592 |
* the exception class, and get a NoClassDefFoundError |
|
593 |
* instead. |
|
594 |
*/ |
|
595 |
NET_ThrowNew(env, errno, "Can't create socket"); |
|
596 |
return JNI_FALSE; |
|
597 |
} |
|
598 |
||
599 |
/** |
|
600 |
* A TTL was specified, let's set the socket option. |
|
601 |
*/ |
|
602 |
if (ttl > 0) { |
|
603 |
setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const char *)&ttl, sizeof(ttl)); |
|
604 |
} |
|
605 |
||
606 |
/** |
|
607 |
* A network interface was specified, let's bind to it. |
|
608 |
*/ |
|
609 |
if (netif != NULL) { |
|
610 |
if (NET_Bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) < 0) { |
|
611 |
NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket to interface"); |
|
612 |
closesocket(fd); |
|
613 |
return JNI_FALSE; |
|
614 |
} |
|
615 |
} |
|
616 |
||
617 |
/** |
|
618 |
* Make the socket non blocking. |
|
619 |
*/ |
|
620 |
hEvent = WSACreateEvent(); |
|
621 |
WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE); |
|
622 |
||
623 |
/* no need to use NET_Connect as non-blocking */ |
|
624 |
him6.sin6_port = htons((short) 7); /* Echo port */ |
|
625 |
connect_rv = connect(fd, (struct sockaddr *)&him6, len); |
|
626 |
||
627 |
/** |
|
628 |
* connection established or refused immediately, either way it means |
|
629 |
* we were able to reach the host! |
|
630 |
*/ |
|
631 |
if (connect_rv == 0 || WSAGetLastError() == WSAECONNREFUSED) { |
|
632 |
WSACloseEvent(hEvent); |
|
633 |
closesocket(fd); |
|
634 |
return JNI_TRUE; |
|
635 |
} else { |
|
636 |
int optlen; |
|
637 |
||
638 |
switch (WSAGetLastError()) { |
|
639 |
case WSAEHOSTUNREACH: /* Host Unreachable */ |
|
640 |
case WSAENETUNREACH: /* Network Unreachable */ |
|
641 |
case WSAENETDOWN: /* Network is down */ |
|
642 |
case WSAEPFNOSUPPORT: /* Protocol Family unsupported */ |
|
643 |
WSACloseEvent(hEvent); |
|
644 |
closesocket(fd); |
|
645 |
return JNI_FALSE; |
|
646 |
} |
|
647 |
||
648 |
if (WSAGetLastError() != WSAEWOULDBLOCK) { |
|
649 |
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", |
|
650 |
"connect failed"); |
|
651 |
WSACloseEvent(hEvent); |
|
652 |
closesocket(fd); |
|
653 |
return JNI_FALSE; |
|
654 |
} |
|
655 |
||
656 |
timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout); |
|
657 |
||
658 |
if (timeout >= 0) { |
|
659 |
/* has connection been established? */ |
|
660 |
optlen = sizeof(connect_rv); |
|
7814
dff0b40f9ac8
7010192: InetAddress.isReachable hits ShouldNotReachHere with hs20-b04 (win)
alanb
parents:
5506
diff
changeset
|
661 |
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv, |
dff0b40f9ac8
7010192: InetAddress.isReachable hits ShouldNotReachHere with hs20-b04 (win)
alanb
parents:
5506
diff
changeset
|
662 |
&optlen) <0) { |
2 | 663 |
connect_rv = WSAGetLastError(); |
664 |
} |
|
665 |
||
666 |
if (connect_rv == 0 || connect_rv == WSAECONNREFUSED) { |
|
667 |
WSACloseEvent(hEvent); |
|
668 |
closesocket(fd); |
|
669 |
return JNI_TRUE; |
|
670 |
} |
|
671 |
} |
|
672 |
} |
|
673 |
WSACloseEvent(hEvent); |
|
674 |
closesocket(fd); |
|
675 |
#endif /* AF_INET6 */ |
|
676 |
return JNI_FALSE; |
|
677 |
} |