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