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