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