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