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