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