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