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