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