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