1 /* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 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 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 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 * 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. 24 */ 25 26 #include <errno.h> 27 #include <string.h> 28 #include <sys/types.h> 29 #include <sys/socket.h> 30 #include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */ 31 #include <netinet/in.h> 32 #include <net/if.h> 33 #include <netdb.h> 34 #include <stdlib.h> 35 #include <dlfcn.h> 36 37 #include <limits.h> 38 #include <sys/param.h> 39 #ifndef MAXINT 40 #define MAXINT INT_MAX 41 #endif 42 #ifdef __BIONIC__ 43 #include <linux/ipv6_route.h> 44 #endif 45 46 #ifdef __solaris__ 47 #include <sys/sockio.h> 48 #include <stropts.h> 49 #include <inet/nd.h> 50 #endif 51 52 #ifdef __linux__ 53 #include <arpa/inet.h> 54 #include <net/route.h> 55 #include <sys/utsname.h> 56 57 #ifndef IPV6_FLOWINFO_SEND 58 #define IPV6_FLOWINFO_SEND 33 59 #endif 60 61 #endif 62 63 #include "jni_util.h" 64 #include "jvm.h" 65 #include "net_util.h" 66 67 #include "java_net_SocketOptions.h" 68 69 /* needed from libsocket on Solaris 8 */ 70 71 getaddrinfo_f getaddrinfo_ptr = NULL; 72 freeaddrinfo_f freeaddrinfo_ptr = NULL; 73 gai_strerror_f gai_strerror_ptr = NULL; 74 getnameinfo_f getnameinfo_ptr = NULL; 75 76 /* 77 * EXCLBIND socket options only on Solaris 78 */ 79 #if defined(__solaris__) && !defined(TCP_EXCLBIND) 80 #define TCP_EXCLBIND 0x21 81 #endif 82 #if defined(__solaris__) && !defined(UDP_EXCLBIND) 83 #define UDP_EXCLBIND 0x0101 84 #endif 85 86 void setDefaultScopeID(JNIEnv *env, struct sockaddr *him) 87 { 88 #ifdef MACOSX 89 static jclass ni_class = NULL; 90 static jfieldID ni_defaultIndexID; 91 if (ni_class == NULL) { 92 jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); 93 CHECK_NULL(c); 94 c = (*env)->NewGlobalRef(env, c); 95 CHECK_NULL(c); 96 ni_defaultIndexID = (*env)->GetStaticFieldID( 97 env, c, "defaultIndex", "I"); 98 ni_class = c; 99 } 100 int defaultIndex; 101 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)him; 102 if (sin6->sin6_family == AF_INET6 && (sin6->sin6_scope_id == 0)) { 103 defaultIndex = (*env)->GetStaticIntField(env, ni_class, 104 ni_defaultIndexID); 105 sin6->sin6_scope_id = defaultIndex; 106 } 107 #endif 108 } 109 110 int getDefaultScopeID(JNIEnv *env) { 111 static jclass ni_class = NULL; 112 static jfieldID ni_defaultIndexID; 113 if (ni_class == NULL) { 114 jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); 115 if (c == NULL) return 0; 116 c = (*env)->NewGlobalRef(env, c); 117 if (c == NULL) return 0; 118 ni_defaultIndexID = (*env)->GetStaticFieldID( 119 env, c, "defaultIndex", "I"); 120 ni_class = c; 121 } 122 int defaultIndex = 0; 123 defaultIndex = (*env)->GetStaticIntField(env, ni_class, 124 ni_defaultIndexID); 125 return defaultIndex; 126 } 127 128 #ifdef __solaris__ 129 static int init_tcp_max_buf, init_udp_max_buf; 130 static int tcp_max_buf; 131 static int udp_max_buf; 132 static int useExclBind = 0; 133 134 /* 135 * Get the specified parameter from the specified driver. The value 136 * of the parameter is assumed to be an 'int'. If the parameter 137 * cannot be obtained return -1 138 */ 139 static int 140 getParam(char *driver, char *param) 141 { 142 struct strioctl stri; 143 char buf [64]; 144 int s; 145 int value; 146 147 s = open (driver, O_RDWR); 148 if (s < 0) { 149 return -1; 150 } 151 strncpy (buf, param, sizeof(buf)); 152 stri.ic_cmd = ND_GET; 153 stri.ic_timout = 0; 154 stri.ic_dp = buf; 155 stri.ic_len = sizeof(buf); 156 if (ioctl (s, I_STR, &stri) < 0) { 157 value = -1; 158 } else { 159 value = atoi(buf); 160 } 161 close (s); 162 return value; 163 } 164 165 /* 166 * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF 167 * for Solaris versions that do not support the ioctl() in getParam(). 168 * Ugly, but only called once (for each sotype). 169 * 170 * As an optimization, we make a guess using the default values for Solaris 171 * assuming they haven't been modified with ndd. 172 */ 173 174 #define MAX_TCP_GUESS 1024 * 1024 175 #define MAX_UDP_GUESS 2 * 1024 * 1024 176 177 #define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1 178 179 static int findMaxBuf(int fd, int opt, int sotype) { 180 int a = 0; 181 int b = MAXINT; 182 int initial_guess; 183 int limit = -1; 184 185 if (sotype == SOCK_DGRAM) { 186 initial_guess = MAX_UDP_GUESS; 187 } else { 188 initial_guess = MAX_TCP_GUESS; 189 } 190 191 if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) { 192 initial_guess++; 193 if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) { 194 FAIL_IF_NOT_ENOBUFS; 195 return initial_guess - 1; 196 } 197 a = initial_guess; 198 } else { 199 FAIL_IF_NOT_ENOBUFS; 200 b = initial_guess - 1; 201 } 202 do { 203 int mid = a + (b-a)/2; 204 if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) { 205 limit = mid; 206 a = mid + 1; 207 } else { 208 FAIL_IF_NOT_ENOBUFS; 209 b = mid - 1; 210 } 211 } while (b >= a); 212 213 return limit; 214 } 215 #endif 216 217 #ifdef __linux__ 218 static int vinit = 0; 219 220 static int kernelV24 = 0; 221 static int vinit24 = 0; 222 223 int kernelIsV24 () { 224 if (!vinit24) { 225 struct utsname sysinfo; 226 if (uname(&sysinfo) == 0) { 227 sysinfo.release[3] = '\0'; 228 if (strcmp(sysinfo.release, "2.4") == 0) { 229 kernelV24 = JNI_TRUE; 230 } 231 } 232 vinit24 = 1; 233 } 234 return kernelV24; 235 } 236 237 int getScopeID (struct sockaddr *him) { 238 struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him; 239 return hext->sin6_scope_id; 240 } 241 242 int cmpScopeID (unsigned int scope, struct sockaddr *him) { 243 struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him; 244 return hext->sin6_scope_id == scope; 245 } 246 247 #else 248 249 int getScopeID (struct sockaddr *him) { 250 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; 251 return him6->sin6_scope_id; 252 } 253 254 int cmpScopeID (unsigned int scope, struct sockaddr *him) { 255 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; 256 return him6->sin6_scope_id == scope; 257 } 258 259 #endif 260 261 262 void 263 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, 264 const char *defaultDetail) { 265 char errmsg[255]; 266 snprintf(errmsg, sizeof(errmsg), "errno: %d, error: %s\n", errno, 267 defaultDetail); 268 JNU_ThrowByNameWithLastError(env, name, errmsg); 269 } 270 271 void 272 NET_ThrowCurrent(JNIEnv *env, char *msg) { 273 NET_ThrowNew(env, errno, msg); 274 } 275 276 void 277 NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) { 278 char fullMsg[512]; 279 if (!msg) { 280 msg = "no further information"; 281 } 282 switch(errorNumber) { 283 case EBADF: 284 jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg); 285 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg); 286 break; 287 case EINTR: 288 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg); 289 break; 290 default: 291 errno = errorNumber; 292 JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg); 293 break; 294 } 295 } 296 297 298 jfieldID 299 NET_GetFileDescriptorID(JNIEnv *env) 300 { 301 jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor"); 302 CHECK_NULL_RETURN(cls, NULL); 303 return (*env)->GetFieldID(env, cls, "descriptor", "I"); 304 } 305 306 #if defined(DONT_ENABLE_IPV6) 307 jint IPv6_supported() 308 { 309 return JNI_FALSE; 310 } 311 312 #else /* !DONT_ENABLE_IPV6 */ 313 314 jint IPv6_supported() 315 { 316 #ifndef AF_INET6 317 return JNI_FALSE; 318 #endif 319 320 #ifdef AF_INET6 321 int fd; 322 void *ipv6_fn; 323 SOCKADDR sa; 324 socklen_t sa_len = sizeof(sa); 325 326 // This one below is problematic, will fail without proper permissions 327 // and report no ipv6 for some and ipv6 for others. 328 //fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ; 329 //if (fd < 0) { 330 /* 331 * TODO: We really cant tell since it may be an unrelated error 332 * for now we will assume that AF_INET6 is not available 333 */ 334 // return JNI_FALSE; 335 //} 336 337 /* 338 * If fd 0 is a socket it means we've been launched from inetd or 339 * xinetd. If it's a socket then check the family - if it's an 340 * IPv4 socket then we need to disable IPv6. 341 */ 342 /*if (getsockname(0, (struct sockaddr *)&sa, &sa_len) == 0) { 343 struct sockaddr *saP = (struct sockaddr *)&sa; 344 if (saP->sa_family != AF_INET6) { 345 return JNI_FALSE; 346 } 347 }*/ 348 349 /** 350 * Linux - check if any interface has an IPv6 address. 351 * Don't need to parse the line - we just need an indication. 352 */ 353 #ifdef __linux__ 354 /* { 355 FILE *fP = fopen("/proc/net/if_inet6", "r"); 356 char buf[255]; 357 char *bufP; 358 359 if (fP == NULL) { 360 close(fd); 361 return JNI_FALSE; 362 } 363 bufP = fgets(buf, sizeof(buf), fP); 364 fclose(fP); 365 if (bufP == NULL) { 366 close(fd); 367 return JNI_FALSE; 368 } 369 }*/ 370 #endif 371 372 /** 373 * On Solaris 8 it's possible to create INET6 sockets even 374 * though IPv6 is not enabled on all interfaces. Thus we 375 * query the number of IPv6 addresses to verify that IPv6 376 * has been configured on at least one interface. 377 * 378 * On Linux it doesn't matter - if IPv6 is built-in the 379 * kernel then IPv6 addresses will be bound automatically 380 * to all interfaces. 381 */ 382 #ifdef __solaris__ 383 384 #ifdef SIOCGLIFNUM 385 { 386 struct lifnum numifs; 387 388 numifs.lifn_family = AF_INET6; 389 numifs.lifn_flags = 0; 390 if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) { 391 /** 392 * SIOCGLIFNUM failed - assume IPv6 not configured 393 */ 394 untagSocket(env, fd); 395 close(fd); 396 return JNI_FALSE; 397 } 398 /** 399 * If no IPv6 addresses then return false. If count > 0 400 * it's possible that all IPv6 addresses are "down" but 401 * that's okay as they may be brought "up" while the 402 * VM is running. 403 */ 404 if (numifs.lifn_count == 0) { 405 close(fd); 406 return JNI_FALSE; 407 } 408 } 409 #else 410 /* SIOCGLIFNUM not defined in build environment ??? */ 411 close(fd); 412 return JNI_FALSE; 413 #endif 414 415 #endif /* __solaris */ 416 417 /* 418 * OK we may have the stack available in the kernel, 419 * we should also check if the APIs are available. 420 */ 421 422 ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton"); 423 if (ipv6_fn == NULL ) { 424 // close(fd); 425 return JNI_FALSE; 426 } 427 428 /* 429 * We've got the library, let's get the pointers to some 430 * IPV6 specific functions. We have to do that because, at least 431 * on Solaris we may build on a system without IPV6 networking 432 * libraries, therefore we can't have a hard link to these 433 * functions. 434 */ 435 getaddrinfo_ptr = (getaddrinfo_f) 436 JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo"); 437 438 freeaddrinfo_ptr = (freeaddrinfo_f) 439 JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo"); 440 441 gai_strerror_ptr = (gai_strerror_f) 442 JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror"); 443 444 getnameinfo_ptr = (getnameinfo_f) 445 JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo"); 446 447 if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) { 448 /* We need all 3 of them */ 449 getaddrinfo_ptr = NULL; 450 } 451 452 //close(fd); 453 return JNI_TRUE; 454 #endif /* AF_INET6 */ 455 } 456 #endif /* DONT_ENABLE_IPV6 */ 457 458 void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, 459 const char* hostname, 460 int gai_error) 461 { 462 int size; 463 char *buf; 464 const char *format = "%s: %s"; 465 const char *error_string = 466 (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error); 467 if (error_string == NULL) 468 error_string = "unknown error"; 469 470 size = strlen(format) + strlen(hostname) + strlen(error_string) + 2; 471 buf = (char *) malloc(size); 472 if (buf) { 473 jstring s; 474 snprintf(buf, size, format, hostname, error_string); 475 s = JNU_NewStringPlatform(env, buf); 476 if (s != NULL) { 477 jobject x = JNU_NewObjectByName(env, 478 "java/net/UnknownHostException", 479 "(Ljava/lang/String;)V", s); 480 if (x != NULL) 481 (*env)->Throw(env, x); 482 } 483 free(buf); 484 } 485 } 486 487 void 488 NET_AllocSockaddr(struct sockaddr **him, int *len) { 489 #ifdef AF_INET6 490 if (ipv6_available()) { 491 struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6)); 492 *him = (struct sockaddr*)him6; 493 *len = sizeof(struct sockaddr_in6); 494 } else 495 #endif /* AF_INET6 */ 496 { 497 struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in)); 498 *him = (struct sockaddr*)him4; 499 *len = sizeof(struct sockaddr_in); 500 } 501 } 502 503 #if 0 504 // Android-changed: Stripped out unused code. http://b/33250070 505 // #if defined(__linux__) && defined(AF_INET6) 506 507 508 /* following code creates a list of addresses from the kernel 509 * routing table that are routed via the loopback address. 510 * We check all destination addresses against this table 511 * and override the scope_id field to use the relevant value for "lo" 512 * in order to work-around the Linux bug that prevents packets destined 513 * for certain local addresses from being sent via a physical interface. 514 */ 515 516 struct loopback_route { 517 struct in6_addr addr; /* destination address */ 518 int plen; /* prefix length */ 519 }; 520 521 static struct loopback_route *loRoutes = 0; 522 static int nRoutes = 0; /* number of routes */ 523 static int loRoutes_size = 16; /* initial size */ 524 static int lo_scope_id = 0; 525 526 static void initLoopbackRoutes(); 527 528 void printAddr (struct in6_addr *addr) { 529 int i; 530 for (i=0; i<16; i++) { 531 printf ("%02x", addr->s6_addr[i]); 532 } 533 printf ("\n"); 534 } 535 536 static void initLoopbackRoutes() { 537 FILE *f; 538 char srcp[8][5]; 539 char hopp[8][5]; 540 int dest_plen, src_plen, use, refcnt, metric; 541 unsigned long flags; 542 char dest_str[40]; 543 struct in6_addr dest_addr; 544 char device[16]; 545 546 if (loRoutes != 0) { 547 free (loRoutes); 548 } 549 loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route)); 550 if (loRoutes == 0) { 551 return; 552 } 553 /* 554 * Scan /proc/net/ipv6_route looking for a matching 555 * route. 556 */ 557 if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) { 558 return ; 559 } 560 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x " 561 "%4s%4s%4s%4s%4s%4s%4s%4s %02x " 562 "%4s%4s%4s%4s%4s%4s%4s%4s " 563 "%08x %08x %08x %08lx %8s", 564 dest_str, &dest_str[5], &dest_str[10], &dest_str[15], 565 &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35], 566 &dest_plen, 567 srcp[0], srcp[1], srcp[2], srcp[3], 568 srcp[4], srcp[5], srcp[6], srcp[7], 569 &src_plen, 570 hopp[0], hopp[1], hopp[2], hopp[3], 571 hopp[4], hopp[5], hopp[6], hopp[7], 572 &metric, &use, &refcnt, &flags, device) == 31) { 573 574 /* 575 * Some routes should be ignored 576 */ 577 if ( (dest_plen < 0 || dest_plen > 128) || 578 (src_plen != 0) || 579 (flags & (RTF_POLICY | RTF_FLOW)) || 580 ((flags & RTF_REJECT) && dest_plen == 0) ) { 581 continue; 582 } 583 584 /* 585 * Convert the destination address 586 */ 587 dest_str[4] = ':'; 588 dest_str[9] = ':'; 589 dest_str[14] = ':'; 590 dest_str[19] = ':'; 591 dest_str[24] = ':'; 592 dest_str[29] = ':'; 593 dest_str[34] = ':'; 594 dest_str[39] = '\0'; 595 596 if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) { 597 /* not an Ipv6 address */ 598 continue; 599 } 600 if (strcmp(device, "lo") != 0) { 601 /* Not a loopback route */ 602 continue; 603 } else { 604 if (nRoutes == loRoutes_size) { 605 loRoutes = realloc (loRoutes, loRoutes_size * 606 sizeof (struct loopback_route) * 2); 607 if (loRoutes == 0) { 608 return ; 609 } 610 loRoutes_size *= 2; 611 } 612 memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr)); 613 loRoutes[nRoutes].plen = dest_plen; 614 nRoutes ++; 615 } 616 } 617 618 fclose (f); 619 { 620 /* now find the scope_id for "lo" */ 621 622 char devname[21]; 623 char addr6p[8][5]; 624 int plen, scope, dad_status, if_idx; 625 626 if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) { 627 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", 628 addr6p[0], addr6p[1], addr6p[2], addr6p[3], 629 addr6p[4], addr6p[5], addr6p[6], addr6p[7], 630 &if_idx, &plen, &scope, &dad_status, devname) == 13) { 631 632 if (strcmp(devname, "lo") == 0) { 633 /* 634 * Found - so just return the index 635 */ 636 fclose(f); 637 lo_scope_id = if_idx; 638 return; 639 } 640 } 641 fclose(f); 642 } 643 } 644 } 645 646 /* 647 * Following is used for binding to local addresses. Equivalent 648 * to code above, for bind(). 649 */ 650 651 struct localinterface { 652 int index; 653 char localaddr [16]; 654 }; 655 656 static struct localinterface *localifs = 0; 657 static int localifsSize = 0; /* size of array */ 658 static int nifs = 0; /* number of entries used in array */ 659 660 /* not thread safe: make sure called once from one thread */ 661 662 static void initLocalIfs () { 663 FILE *f; 664 unsigned char staddr [16]; 665 char ifname [33]; 666 struct localinterface *lif=0; 667 int index, x1, x2, x3; 668 unsigned int u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,ua,ub,uc,ud,ue,uf; 669 670 if ((f = fopen("/proc/net/if_inet6", "r")) == NULL) { 671 return ; 672 } 673 while (fscanf (f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x " 674 "%d %x %x %x %32s",&u0,&u1,&u2,&u3,&u4,&u5,&u6,&u7, 675 &u8,&u9,&ua,&ub,&uc,&ud,&ue,&uf, 676 &index, &x1, &x2, &x3, ifname) == 21) { 677 staddr[0] = (unsigned char)u0; 678 staddr[1] = (unsigned char)u1; 679 staddr[2] = (unsigned char)u2; 680 staddr[3] = (unsigned char)u3; 681 staddr[4] = (unsigned char)u4; 682 staddr[5] = (unsigned char)u5; 683 staddr[6] = (unsigned char)u6; 684 staddr[7] = (unsigned char)u7; 685 staddr[8] = (unsigned char)u8; 686 staddr[9] = (unsigned char)u9; 687 staddr[10] = (unsigned char)ua; 688 staddr[11] = (unsigned char)ub; 689 staddr[12] = (unsigned char)uc; 690 staddr[13] = (unsigned char)ud; 691 staddr[14] = (unsigned char)ue; 692 staddr[15] = (unsigned char)uf; 693 nifs ++; 694 if (nifs > localifsSize) { 695 localifs = (struct localinterface *) realloc ( 696 localifs, sizeof (struct localinterface)* (localifsSize+5)); 697 if (localifs == 0) { 698 nifs = 0; 699 fclose (f); 700 return; 701 } 702 lif = localifs + localifsSize; 703 localifsSize += 5; 704 } else { 705 lif ++; 706 } 707 memcpy (lif->localaddr, staddr, 16); 708 lif->index = index; 709 } 710 fclose (f); 711 } 712 713 void initLocalAddrTable () { 714 initLoopbackRoutes(); 715 initLocalIfs(); 716 } 717 718 #else 719 720 void initLocalAddrTable () {} 721 722 #endif 723 724 void parseExclusiveBindProperty(JNIEnv *env) { 725 #ifdef __solaris__ 726 jstring s, flagSet; 727 jclass iCls; 728 jmethodID mid; 729 730 s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind"); 731 CHECK_NULL(s); 732 iCls = (*env)->FindClass(env, "java/lang/System"); 733 CHECK_NULL(iCls); 734 mid = (*env)->GetStaticMethodID(env, iCls, "getProperty", 735 "(Ljava/lang/String;)Ljava/lang/String;"); 736 CHECK_NULL(mid); 737 flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s); 738 if (flagSet != NULL) { 739 useExclBind = 1; 740 } 741 #endif 742 } 743 /* In the case of an IPv4 Inetaddress this method will return an 744 * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE. 745 * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress. 746 */ 747 JNIEXPORT int JNICALL 748 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, 749 int *len, jboolean v4MappedAddress) { 750 jint family; 751 family = getInetAddress_family(env, iaObj); 752 #ifdef AF_INET6 753 /* needs work. 1. family 2. clean up him6 etc deallocate memory */ 754 if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) { 755 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; 756 jbyteArray ipaddress; 757 jbyte caddr[16]; 758 jint address; 759 760 761 if (family == IPv4) { /* will convert to IPv4-mapped address */ 762 memset((char *) caddr, 0, 16); 763 address = getInetAddress_addr(env, iaObj); 764 if (address == INADDR_ANY) { 765 /* we would always prefer IPv6 wildcard address 766 caddr[10] = 0xff; 767 caddr[11] = 0xff; */ 768 } else { 769 caddr[10] = 0xff; 770 caddr[11] = 0xff; 771 caddr[12] = ((address >> 24) & 0xff); 772 caddr[13] = ((address >> 16) & 0xff); 773 caddr[14] = ((address >> 8) & 0xff); 774 caddr[15] = (address & 0xff); 775 } 776 } else { 777 getInet6Address_ipaddress(env, iaObj, (char *)caddr); 778 } 779 memset((char *)him6, 0, sizeof(struct sockaddr_in6)); 780 him6->sin6_port = htons(port); 781 memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) ); 782 him6->sin6_family = AF_INET6; 783 *len = sizeof(struct sockaddr_in6) ; 784 785 #if defined(_ALLBSD_SOURCE) && defined(_AF_INET6) 786 // XXXBSD: should we do something with scope id here ? see below linux comment 787 /* MMM: Come back to this! */ 788 #endif 789 790 // Android-changed: Don't try and figure out scope_ids for link local 791 // addresses. Use them only if they're set in java (say, if the Inet6Address 792 // was constructed with a specific scope_id or NetworkInterface). 793 if (family != IPv4) { 794 if (ia6_scopeidID) { 795 int scope_id = getInet6Address_scopeid(env, iaObj); 796 if (scope_id > 0) { 797 him6->sin6_scope_id = scope_id; 798 } 799 } 800 } 801 } else 802 #endif /* AF_INET6 */ 803 { 804 struct sockaddr_in *him4 = (struct sockaddr_in*)him; 805 jint address; 806 if (family == IPv6) { 807 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); 808 return -1; 809 } 810 memset((char *) him4, 0, sizeof(struct sockaddr_in)); 811 address = getInetAddress_addr(env, iaObj); 812 him4->sin_port = htons((short) port); 813 him4->sin_addr.s_addr = (uint32_t) htonl(address); 814 him4->sin_family = AF_INET; 815 *len = sizeof(struct sockaddr_in); 816 } 817 return 0; 818 } 819 820 void 821 NET_SetTrafficClass(struct sockaddr *him, int trafficClass) { 822 #ifdef AF_INET6 823 if (him->sa_family == AF_INET6) { 824 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; 825 him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20); 826 } 827 #endif /* AF_INET6 */ 828 } 829 830 JNIEXPORT jint JNICALL 831 NET_GetPortFromSockaddr(struct sockaddr *him) { 832 #ifdef AF_INET6 833 if (him->sa_family == AF_INET6) { 834 return ntohs(((struct sockaddr_in6*)him)->sin6_port); 835 836 } else 837 #endif /* AF_INET6 */ 838 { 839 return ntohs(((struct sockaddr_in*)him)->sin_port); 840 } 841 } 842 843 int 844 NET_IsIPv4Mapped(jbyte* caddr) { 845 int i; 846 for (i = 0; i < 10; i++) { 847 if (caddr[i] != 0x00) { 848 return 0; /* false */ 849 } 850 } 851 852 if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) { 853 return 1; /* true */ 854 } 855 return 0; /* false */ 856 } 857 858 int 859 NET_IPv4MappedToIPv4(jbyte* caddr) { 860 return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8) 861 | (caddr[15] & 0xff); 862 } 863 864 int 865 NET_IsEqual(jbyte* caddr1, jbyte* caddr2) { 866 int i; 867 for (i = 0; i < 16; i++) { 868 if (caddr1[i] != caddr2[i]) { 869 return 0; /* false */ 870 } 871 } 872 return 1; 873 } 874 875 jboolean NET_addrtransAvailable() { 876 return (jboolean)(getaddrinfo_ptr != NULL); 877 } 878 879 int NET_IsZeroAddr(jbyte* caddr) { 880 int i; 881 for (i = 0; i < 16; i++) { 882 if (caddr[i] != 0) { 883 return 0; 884 } 885 } 886 return 1; 887 } 888 889 /* 890 * Map the Java level socket option to the platform specific 891 * level and option name. 892 */ 893 int 894 NET_MapSocketOption(jint cmd, int *level, int *optname) { 895 static struct { 896 jint cmd; 897 int level; 898 int optname; 899 } const opts[] = { 900 { java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY }, 901 { java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE }, 902 { java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER }, 903 { java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF }, 904 { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF }, 905 { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE }, 906 { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR }, 907 { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST }, 908 { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS }, 909 { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF }, 910 { java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF }, 911 { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP }, 912 }; 913 914 int i; 915 916 #ifdef AF_INET6 917 if (ipv6_available()) { 918 switch (cmd) { 919 // Different multicast options if IPv6 is enabled 920 case java_net_SocketOptions_IP_MULTICAST_IF: 921 case java_net_SocketOptions_IP_MULTICAST_IF2: 922 *level = IPPROTO_IPV6; 923 *optname = IPV6_MULTICAST_IF; 924 return 0; 925 926 case java_net_SocketOptions_IP_MULTICAST_LOOP: 927 *level = IPPROTO_IPV6; 928 *optname = IPV6_MULTICAST_LOOP; 929 return 0; 930 #if (defined(__solaris__) || defined(MACOSX)) 931 // Map IP_TOS request to IPV6_TCLASS 932 case java_net_SocketOptions_IP_TOS: 933 *level = IPPROTO_IPV6; 934 *optname = IPV6_TCLASS; 935 return 0; 936 #endif 937 } 938 } 939 #endif 940 941 /* 942 * Map the Java level option to the native level 943 */ 944 for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) { 945 if (cmd == opts[i].cmd) { 946 *level = opts[i].level; 947 *optname = opts[i].optname; 948 return 0; 949 } 950 } 951 952 /* not found */ 953 return -1; 954 } 955 956 /* 957 * Wrapper for getsockopt system routine - does any necessary 958 * pre/post processing to deal with OS specific oddities :- 959 * 960 * On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed 961 * to compensate for an incorrect value returned by the kernel. 962 */ 963 int 964 NET_GetSockOpt(int fd, int level, int opt, void *result, 965 int *len) 966 { 967 int rv; 968 969 #ifdef __solaris__ 970 rv = getsockopt(fd, level, opt, result, len); 971 #else 972 { 973 socklen_t socklen = *len; 974 rv = getsockopt(fd, level, opt, result, &socklen); 975 *len = socklen; 976 } 977 #endif 978 979 if (rv < 0) { 980 return rv; 981 } 982 983 #ifdef __linux__ 984 /* 985 * On Linux SO_SNDBUF/SO_RCVBUF aren't symmetric. This 986 * stems from additional socket structures in the send 987 * and receive buffers. 988 */ 989 if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF) 990 || (opt == SO_RCVBUF))) { 991 int n = *((int *)result); 992 n /= 2; 993 *((int *)result) = n; 994 } 995 #endif 996 997 /* Workaround for Mac OS treating linger value as 998 * signed integer 999 */ 1000 #ifdef MACOSX 1001 if (level == SOL_SOCKET && opt == SO_LINGER) { 1002 struct linger* to_cast = (struct linger*)result; 1003 to_cast->l_linger = (unsigned short)to_cast->l_linger; 1004 } 1005 #endif 1006 return rv; 1007 } 1008 1009 /* 1010 * Wrapper for setsockopt system routine - performs any 1011 * necessary pre/post processing to deal with OS specific 1012 * issue :- 1013 * 1014 * On Solaris need to limit the suggested value for SO_SNDBUF 1015 * and SO_RCVBUF to the kernel configured limit 1016 * 1017 * For IP_TOS socket option need to mask off bits as this 1018 * aren't automatically masked by the kernel and results in 1019 * an error. 1020 */ 1021 int 1022 NET_SetSockOpt(int fd, int level, int opt, const void *arg, 1023 int len) 1024 { 1025 #ifndef IPTOS_TOS_MASK 1026 #define IPTOS_TOS_MASK 0x1e 1027 #endif 1028 #ifndef IPTOS_PREC_MASK 1029 #define IPTOS_PREC_MASK 0xe0 1030 #endif 1031 1032 #if defined(_ALLBSD_SOURCE) 1033 #if defined(KIPC_MAXSOCKBUF) 1034 int mib[3]; 1035 size_t rlen; 1036 #endif 1037 1038 int *bufsize; 1039 1040 #ifdef __APPLE__ 1041 static int maxsockbuf = -1; 1042 #else 1043 static long maxsockbuf = -1; 1044 #endif 1045 #endif 1046 1047 /* 1048 * IPPROTO/IP_TOS :- 1049 * 1. IPv6 on Solaris/Mac OS: 1050 * Set the TOS OR Traffic Class value to cater for 1051 * IPv6 and IPv4 scenarios. 1052 * 2. IPv6 on Linux: By default Linux ignores flowinfo 1053 * field so enable IPV6_FLOWINFO_SEND so that flowinfo 1054 * will be examined. We also set the IPv4 TOS option in this case. 1055 * 3. IPv4: set socket option based on ToS and Precedence 1056 * fields (otherwise get invalid argument) 1057 */ 1058 if (level == IPPROTO_IP && opt == IP_TOS) { 1059 int *iptos; 1060 1061 #if defined(AF_INET6) && defined(__linux__) 1062 if (ipv6_available()) { 1063 int optval = 1; 1064 if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, 1065 (void *)&optval, sizeof(optval)) < 0) { 1066 return -1; 1067 } 1068 /* 1069 * Let's also set the IPV6_TCLASS flag. 1070 * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set 1071 * This helps in mixed environments where IPv4 and IPv6 sockets 1072 * are connecting. 1073 */ 1074 if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, 1075 arg, len) < 0) { 1076 return -1; 1077 } 1078 } 1079 #endif 1080 1081 iptos = (int *)arg; 1082 // Android-changed: This is out-dated RFC 1349 scheme. Modern Linux uses 1083 // Diffsev/ECN, and this mask is no longer relavant. 1084 // *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK); 1085 } 1086 1087 /* 1088 * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp 1089 * the value when it exceeds the system limit. 1090 */ 1091 #ifdef __solaris__ 1092 if (level == SOL_SOCKET) { 1093 if (opt == SO_SNDBUF || opt == SO_RCVBUF) { 1094 int sotype=0, arglen; 1095 int *bufsize, maxbuf; 1096 int ret; 1097 1098 /* Attempt with the original size */ 1099 ret = setsockopt(fd, level, opt, arg, len); 1100 if ((ret == 0) || (ret == -1 && errno != ENOBUFS)) 1101 return ret; 1102 1103 /* Exceeded system limit so clamp and retry */ 1104 1105 arglen = sizeof(sotype); 1106 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, 1107 &arglen) < 0) { 1108 return -1; 1109 } 1110 1111 /* 1112 * We try to get tcp_maxbuf (and udp_max_buf) using 1113 * an ioctl() that isn't available on all versions of Solaris. 1114 * If that fails, we use the search algorithm in findMaxBuf() 1115 */ 1116 if (!init_tcp_max_buf && sotype == SOCK_STREAM) { 1117 tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf"); 1118 if (tcp_max_buf == -1) { 1119 tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM); 1120 if (tcp_max_buf == -1) { 1121 return -1; 1122 } 1123 } 1124 init_tcp_max_buf = 1; 1125 } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) { 1126 udp_max_buf = getParam("/dev/udp", "udp_max_buf"); 1127 if (udp_max_buf == -1) { 1128 udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM); 1129 if (udp_max_buf == -1) { 1130 return -1; 1131 } 1132 } 1133 init_udp_max_buf = 1; 1134 } 1135 1136 maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf; 1137 bufsize = (int *)arg; 1138 if (*bufsize > maxbuf) { 1139 *bufsize = maxbuf; 1140 } 1141 } 1142 } 1143 #endif 1144 1145 /* 1146 * On Linux the receive buffer is used for both socket 1147 * structures and the the packet payload. The implication 1148 * is that if SO_RCVBUF is too small then small packets 1149 * must be discarded. 1150 */ 1151 #ifdef __linux__ 1152 if (level == SOL_SOCKET && opt == SO_RCVBUF) { 1153 int *bufsize = (int *)arg; 1154 if (*bufsize < 1024) { 1155 *bufsize = 1024; 1156 } 1157 } 1158 #endif 1159 1160 #if defined(_ALLBSD_SOURCE) 1161 /* 1162 * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to 1163 * ensure that value is <= kern.ipc.maxsockbuf as otherwise we get 1164 * an ENOBUFS error. 1165 */ 1166 if (level == SOL_SOCKET) { 1167 if (opt == SO_SNDBUF || opt == SO_RCVBUF) { 1168 #ifdef KIPC_MAXSOCKBUF 1169 if (maxsockbuf == -1) { 1170 mib[0] = CTL_KERN; 1171 mib[1] = KERN_IPC; 1172 mib[2] = KIPC_MAXSOCKBUF; 1173 rlen = sizeof(maxsockbuf); 1174 if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1) 1175 maxsockbuf = 1024; 1176 1177 #if 1 1178 /* XXXBSD: This is a hack to workaround mb_max/mb_max_adj 1179 problem. It should be removed when kern.ipc.maxsockbuf 1180 will be real value. */ 1181 maxsockbuf = (maxsockbuf/5)*4; 1182 #endif 1183 } 1184 #elif defined(__OpenBSD__) 1185 maxsockbuf = SB_MAX; 1186 #else 1187 maxsockbuf = 64 * 1024; /* XXX: NetBSD */ 1188 #endif 1189 1190 bufsize = (int *)arg; 1191 if (*bufsize > maxsockbuf) { 1192 *bufsize = maxsockbuf; 1193 } 1194 1195 if (opt == SO_RCVBUF && *bufsize < 1024) { 1196 *bufsize = 1024; 1197 } 1198 1199 } 1200 } 1201 1202 /* 1203 * On Solaris, SO_REUSEADDR will allow multiple datagram 1204 * sockets to bind to the same port. The network jck tests 1205 * for this "feature", so we need to emulate it by turning on 1206 * SO_REUSEPORT as well for that combination. 1207 */ 1208 if (level == SOL_SOCKET && opt == SO_REUSEADDR) { 1209 int sotype; 1210 socklen_t arglen; 1211 1212 arglen = sizeof(sotype); 1213 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) { 1214 return -1; 1215 } 1216 1217 if (sotype == SOCK_DGRAM) { 1218 setsockopt(fd, level, SO_REUSEPORT, arg, len); 1219 } 1220 } 1221 1222 #endif 1223 1224 return setsockopt(fd, level, opt, arg, len); 1225 } 1226 1227 /* 1228 * Wrapper for bind system call - performs any necessary pre/post 1229 * processing to deal with OS specific issues :- 1230 * 1231 * Linux allows a socket to bind to 127.0.0.255 which must be 1232 * caught. 1233 * 1234 * On Solaris with IPv6 enabled we must use an exclusive 1235 * bind to guaranteed a unique port number across the IPv4 and 1236 * IPv6 port spaces. 1237 * 1238 */ 1239 int 1240 NET_Bind(int fd, struct sockaddr *him, int len) 1241 { 1242 #if defined(__solaris__) && defined(AF_INET6) 1243 int level = -1; 1244 int exclbind = -1; 1245 #endif 1246 int rv; 1247 1248 #ifdef __linux__ 1249 /* 1250 * ## get bugId for this issue - goes back to 1.2.2 port ## 1251 * ## When IPv6 is enabled this will be an IPv4-mapped 1252 * ## with family set to AF_INET6 1253 */ 1254 if (him->sa_family == AF_INET) { 1255 struct sockaddr_in *sa = (struct sockaddr_in *)him; 1256 if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) { 1257 errno = EADDRNOTAVAIL; 1258 return -1; 1259 } 1260 } 1261 #endif 1262 1263 #if defined(__solaris__) && defined(AF_INET6) 1264 /* 1265 * Solaris has seperate IPv4 and IPv6 port spaces so we 1266 * use an exclusive bind when SO_REUSEADDR is not used to 1267 * give the illusion of a unified port space. 1268 * This also avoids problems with IPv6 sockets connecting 1269 * to IPv4 mapped addresses whereby the socket conversion 1270 * results in a late bind that fails because the 1271 * corresponding IPv4 port is in use. 1272 */ 1273 if (ipv6_available()) { 1274 int arg, len; 1275 1276 len = sizeof(arg); 1277 if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1278 (char *)&arg, &len) == 0) { 1279 if (useExclBind || arg == 0) { 1280 /* 1281 * SO_REUSEADDR is disabled or sun.net.useExclusiveBind 1282 * property is true so enable TCP_EXCLBIND or 1283 * UDP_EXCLBIND 1284 */ 1285 len = sizeof(arg); 1286 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, 1287 &len) == 0) { 1288 if (arg == SOCK_STREAM) { 1289 level = IPPROTO_TCP; 1290 exclbind = TCP_EXCLBIND; 1291 } else { 1292 level = IPPROTO_UDP; 1293 exclbind = UDP_EXCLBIND; 1294 } 1295 } 1296 1297 arg = 1; 1298 setsockopt(fd, level, exclbind, (char *)&arg, 1299 sizeof(arg)); 1300 } 1301 } 1302 } 1303 1304 #endif 1305 1306 rv = bind(fd, him, len); 1307 1308 #if defined(__solaris__) && defined(AF_INET6) 1309 if (rv < 0) { 1310 int en = errno; 1311 /* Restore *_EXCLBIND if the bind fails */ 1312 if (exclbind != -1) { 1313 int arg = 0; 1314 setsockopt(fd, level, exclbind, (char *)&arg, 1315 sizeof(arg)); 1316 } 1317 errno = en; 1318 } 1319 #endif 1320 1321 return rv; 1322 } 1323 1324 /** 1325 * Wrapper for select/poll with timeout on a single file descriptor. 1326 * 1327 * flags (defined in net_util_md.h can be any combination of 1328 * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT. 1329 * 1330 * The function will return when either the socket is ready for one 1331 * of the specified operations or the timeout expired. 1332 * 1333 * It returns the time left from the timeout (possibly 0), or -1 if it expired. 1334 */ 1335 1336 jint 1337 NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) 1338 { 1339 jlong prevTime = JVM_CurrentTimeMillis(env, 0); 1340 jint read_rv; 1341 1342 while (1) { 1343 jlong newTime; 1344 #ifndef USE_SELECT 1345 { 1346 struct pollfd pfd; 1347 pfd.fd = fd; 1348 pfd.events = 0; 1349 if (flags & NET_WAIT_READ) 1350 pfd.events |= POLLIN; 1351 if (flags & NET_WAIT_WRITE) 1352 pfd.events |= POLLOUT; 1353 if (flags & NET_WAIT_CONNECT) 1354 pfd.events |= POLLOUT; 1355 1356 errno = 0; 1357 read_rv = NET_Poll(&pfd, 1, timeout); 1358 } 1359 #else 1360 { 1361 fd_set rd, wr, ex; 1362 struct timeval t; 1363 1364 t.tv_sec = timeout / 1000; 1365 t.tv_usec = (timeout % 1000) * 1000; 1366 1367 FD_ZERO(&rd); 1368 FD_ZERO(&wr); 1369 FD_ZERO(&ex); 1370 if (flags & NET_WAIT_READ) { 1371 FD_SET(fd, &rd); 1372 } 1373 if (flags & NET_WAIT_WRITE) { 1374 FD_SET(fd, &wr); 1375 } 1376 if (flags & NET_WAIT_CONNECT) { 1377 FD_SET(fd, &wr); 1378 FD_SET(fd, &ex); 1379 } 1380 1381 errno = 0; 1382 read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t); 1383 } 1384 #endif 1385 1386 newTime = JVM_CurrentTimeMillis(env, 0); 1387 timeout -= (newTime - prevTime); 1388 if (timeout <= 0) { 1389 return read_rv > 0 ? 0 : -1; 1390 } 1391 prevTime = newTime; 1392 1393 if (read_rv > 0) { 1394 break; 1395 } 1396 1397 1398 } /* while */ 1399 1400 return timeout; 1401 } 1402 1403 #if 0 1404 // Stripped out unused code. 1405 // http://b/27301951 1406 __attribute__((destructor)) 1407 static void netUtilCleanUp() { 1408 if (loRoutes != 0) free(loRoutes); 1409 if (localifs != 0) free(localifs); 1410 } 1411 #endif 1412