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