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