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