232 } |
232 } |
233 vinit24 = 1; |
233 vinit24 = 1; |
234 } |
234 } |
235 return kernelV24; |
235 return kernelV24; |
236 } |
236 } |
237 |
|
238 int getScopeID (struct sockaddr *him) { |
|
239 struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him; |
|
240 return hext->sin6_scope_id; |
|
241 } |
|
242 |
|
243 int cmpScopeID (unsigned int scope, struct sockaddr *him) { |
|
244 struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him; |
|
245 return hext->sin6_scope_id == scope; |
|
246 } |
|
247 |
|
248 #else |
|
249 |
|
250 int getScopeID (struct sockaddr *him) { |
|
251 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; |
|
252 return him6->sin6_scope_id; |
|
253 } |
|
254 |
|
255 int cmpScopeID (unsigned int scope, struct sockaddr *him) { |
|
256 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; |
|
257 return him6->sin6_scope_id == scope; |
|
258 } |
|
259 |
|
260 #endif |
237 #endif |
261 |
238 |
262 void |
239 void |
263 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, |
240 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, |
264 const char *defaultDetail) { |
241 const char *defaultDetail) { |
773 JNIEXPORT jint JNICALL |
750 JNIEXPORT jint JNICALL |
774 NET_EnableFastTcpLoopback(int fd) { |
751 NET_EnableFastTcpLoopback(int fd) { |
775 return 0; |
752 return 0; |
776 } |
753 } |
777 |
754 |
778 /* In the case of an IPv4 Inetaddress this method will return an |
755 /** |
779 * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE. |
756 * See net_util.h for documentation |
780 * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress. |
757 */ |
781 */ |
|
782 JNIEXPORT int JNICALL |
758 JNIEXPORT int JNICALL |
783 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, |
759 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, |
784 int *len, jboolean v4MappedAddress) { |
760 SOCKETADDRESS *sa, int *len, |
785 jint family; |
761 jboolean v4MappedAddress) |
786 family = getInetAddress_family(env, iaObj); |
762 { |
787 /* needs work. 1. family 2. clean up him6 etc deallocate memory */ |
763 jint family = getInetAddress_family(env, iaObj); |
788 if (ipv6_available() && !(family == java_net_InetAddress_IPv4 && |
764 memset((char *)sa, 0, sizeof(SOCKETADDRESS)); |
789 v4MappedAddress == JNI_FALSE)) { |
765 |
790 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; |
766 if (ipv6_available() && |
|
767 !(family == java_net_InetAddress_IPv4 && |
|
768 v4MappedAddress == JNI_FALSE)) |
|
769 { |
791 jbyte caddr[16]; |
770 jbyte caddr[16]; |
792 jint address; |
771 jint address; |
793 |
772 |
794 if (family == java_net_InetAddress_IPv4) { |
773 if (family == java_net_InetAddress_IPv4) { |
795 // convert to IPv4-mapped address |
774 // convert to IPv4-mapped address |
796 memset((char *) caddr, 0, 16); |
775 memset((char *)caddr, 0, 16); |
797 address = getInetAddress_addr(env, iaObj); |
776 address = getInetAddress_addr(env, iaObj); |
798 if (address == INADDR_ANY) { |
777 if (address == INADDR_ANY) { |
799 /* we would always prefer IPv6 wildcard address |
778 /* we would always prefer IPv6 wildcard address |
800 caddr[10] = 0xff; |
779 * caddr[10] = 0xff; |
801 caddr[11] = 0xff; */ |
780 * caddr[11] = 0xff; */ |
802 } else { |
781 } else { |
803 caddr[10] = 0xff; |
782 caddr[10] = 0xff; |
804 caddr[11] = 0xff; |
783 caddr[11] = 0xff; |
805 caddr[12] = ((address >> 24) & 0xff); |
784 caddr[12] = ((address >> 24) & 0xff); |
806 caddr[13] = ((address >> 16) & 0xff); |
785 caddr[13] = ((address >> 16) & 0xff); |
808 caddr[15] = (address & 0xff); |
787 caddr[15] = (address & 0xff); |
809 } |
788 } |
810 } else { |
789 } else { |
811 getInet6Address_ipaddress(env, iaObj, (char *)caddr); |
790 getInet6Address_ipaddress(env, iaObj, (char *)caddr); |
812 } |
791 } |
813 memset((char *)him6, 0, sizeof(struct sockaddr_in6)); |
792 sa->sa6.sin6_port = htons(port); |
814 him6->sin6_port = htons(port); |
793 memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr)); |
815 memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) ); |
794 sa->sa6.sin6_family = AF_INET6; |
816 him6->sin6_family = AF_INET6; |
795 if (len != NULL) { |
817 *len = sizeof(struct sockaddr_in6); |
796 *len = sizeof(struct sockaddr_in6); |
818 |
797 } |
819 #if defined(_ALLBSD_SOURCE) |
798 |
820 // XXXBSD: should we do something with scope id here ? see below linux comment |
799 #ifdef __linux__ |
821 /* MMM: Come back to this! */ |
|
822 #endif |
|
823 |
|
824 /* |
800 /* |
825 * On Linux if we are connecting to a link-local address |
801 * On Linux if we are connecting to a link-local address |
826 * we need to specify the interface in the scope_id (2.4 kernel only) |
802 * we need to specify the interface in the scope_id (2.4 kernel only) |
827 * |
803 * |
828 * If the scope was cached the we use the cached value. If not cached but |
804 * If the scope was cached then we use the cached value. If not cached but |
829 * specified in the Inet6Address we use that, but we first check if the |
805 * specified in the Inet6Address we use that, but we first check if the |
830 * address needs to be routed via the loopback interface. In this case, |
806 * address needs to be routed via the loopback interface. In this case, |
831 * we override the specified value with that of the loopback interface. |
807 * we override the specified value with that of the loopback interface. |
832 * If no cached value exists and no value was specified by user, then |
808 * If no cached value exists and no value was specified by user, then |
833 * we try to determine a value from the routing table. In all these |
809 * we try to determine a value from the routing table. In all these |
834 * cases the used value is cached for further use. |
810 * cases the used value is cached for further use. |
835 */ |
811 */ |
836 #ifdef __linux__ |
812 if (IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr)) { |
837 if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) { |
813 unsigned int cached_scope_id = 0, scope_id = 0; |
838 int cached_scope_id = 0, scope_id = 0; |
|
839 |
814 |
840 if (ia6_cachedscopeidID) { |
815 if (ia6_cachedscopeidID) { |
841 cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); |
816 cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); |
842 /* if cached value exists then use it. Otherwise, check |
817 /* if cached value exists then use it. Otherwise, check |
843 * if scope is set in the address. |
818 * if scope is set in the address. |
848 } |
823 } |
849 if (scope_id != 0) { |
824 if (scope_id != 0) { |
850 /* check user-specified value for loopback case |
825 /* check user-specified value for loopback case |
851 * that needs to be overridden |
826 * that needs to be overridden |
852 */ |
827 */ |
853 if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) { |
828 if (kernelIsV24() && needsLoopbackRoute(&sa->sa6.sin6_addr)) { |
854 cached_scope_id = lo_scope_id; |
829 cached_scope_id = lo_scope_id; |
855 (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); |
830 (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); |
856 } |
831 } |
857 } else { |
832 } else { |
858 /* |
833 /* |
859 * Otherwise consult the IPv6 routing tables to |
834 * Otherwise consult the IPv6 routing tables to |
860 * try determine the appropriate interface. |
835 * try determine the appropriate interface. |
861 */ |
836 */ |
862 if (kernelIsV24()) { |
837 if (kernelIsV24()) { |
863 cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr)); |
838 cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr); |
864 } else { |
839 } else { |
865 cached_scope_id = getLocalScopeID((char *)&(him6->sin6_addr)); |
840 cached_scope_id = getLocalScopeID((char *)&(sa->sa6.sin6_addr)); |
866 if (cached_scope_id == 0) { |
841 if (cached_scope_id == 0) { |
867 cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr)); |
842 cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr); |
868 } |
843 } |
869 } |
844 } |
870 (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); |
845 (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); |
871 } |
846 } |
872 } |
847 } |
874 |
849 |
875 /* |
850 /* |
876 * If we have a scope_id use the extended form |
851 * If we have a scope_id use the extended form |
877 * of sockaddr_in6. |
852 * of sockaddr_in6. |
878 */ |
853 */ |
879 |
854 sa->sa6.sin6_scope_id = cached_scope_id == 0 ? scope_id : cached_scope_id; |
880 struct sockaddr_in6 *him6 = |
|
881 (struct sockaddr_in6 *)him; |
|
882 him6->sin6_scope_id = cached_scope_id != 0 ? |
|
883 cached_scope_id : scope_id; |
|
884 *len = sizeof(struct sockaddr_in6); |
|
885 } |
855 } |
886 #else |
856 #else |
887 /* handle scope_id for solaris */ |
857 /* handle scope_id */ |
888 |
|
889 if (family != java_net_InetAddress_IPv4) { |
858 if (family != java_net_InetAddress_IPv4) { |
890 if (ia6_scopeidID) { |
859 if (ia6_scopeidID) { |
891 him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj); |
860 sa->sa6.sin6_scope_id = getInet6Address_scopeid(env, iaObj); |
892 } |
861 } |
893 } |
862 } |
894 #endif |
863 #endif |
895 } else { |
864 } else { |
896 struct sockaddr_in *him4 = (struct sockaddr_in *)him; |
|
897 jint address; |
865 jint address; |
898 if (family == java_net_InetAddress_IPv6) { |
866 if (family != java_net_InetAddress_IPv4) { |
899 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); |
867 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); |
900 return -1; |
868 return -1; |
901 } |
869 } |
902 memset((char *)him4, 0, sizeof(struct sockaddr_in)); |
|
903 address = getInetAddress_addr(env, iaObj); |
870 address = getInetAddress_addr(env, iaObj); |
904 him4->sin_port = htons((short) port); |
871 sa->sa4.sin_port = htons(port); |
905 him4->sin_addr.s_addr = htonl(address); |
872 sa->sa4.sin_addr.s_addr = htonl(address); |
906 him4->sin_family = AF_INET; |
873 sa->sa4.sin_family = AF_INET; |
907 *len = sizeof(struct sockaddr_in); |
874 if (len != NULL) { |
|
875 *len = sizeof(struct sockaddr_in); |
|
876 } |
908 } |
877 } |
909 return 0; |
878 return 0; |
910 } |
879 } |
911 |
880 |
912 void |
881 void |
913 NET_SetTrafficClass(struct sockaddr *him, int trafficClass) { |
882 NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass) { |
914 if (him->sa_family == AF_INET6) { |
883 if (sa->sa.sa_family == AF_INET6) { |
915 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; |
884 sa->sa6.sin6_flowinfo = htonl((trafficClass & 0xff) << 20); |
916 him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20); |
|
917 } |
|
918 } |
|
919 |
|
920 JNIEXPORT jint JNICALL |
|
921 NET_GetPortFromSockaddr(struct sockaddr *him) { |
|
922 if (him->sa_family == AF_INET6) { |
|
923 return ntohs(((struct sockaddr_in6*)him)->sin6_port); |
|
924 } else { |
|
925 return ntohs(((struct sockaddr_in*)him)->sin_port); |
|
926 } |
885 } |
927 } |
886 } |
928 |
887 |
929 int |
888 int |
930 NET_IsIPv4Mapped(jbyte* caddr) { |
889 NET_IsIPv4Mapped(jbyte* caddr) { |
1501 /* |
1460 /* |
1502 * ## get bugId for this issue - goes back to 1.2.2 port ## |
1461 * ## get bugId for this issue - goes back to 1.2.2 port ## |
1503 * ## When IPv6 is enabled this will be an IPv4-mapped |
1462 * ## When IPv6 is enabled this will be an IPv4-mapped |
1504 * ## with family set to AF_INET6 |
1463 * ## with family set to AF_INET6 |
1505 */ |
1464 */ |
1506 if (him->sa_family == AF_INET) { |
1465 if (sa->sa.sa_family == AF_INET) { |
1507 struct sockaddr_in *sa = (struct sockaddr_in *)him; |
1466 if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) { |
1508 if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) { |
|
1509 errno = EADDRNOTAVAIL; |
1467 errno = EADDRNOTAVAIL; |
1510 return -1; |
1468 return -1; |
1511 } |
1469 } |
1512 } |
1470 } |
1513 #endif |
1471 #endif |
1522 * results in a late bind that fails because the |
1480 * results in a late bind that fails because the |
1523 * corresponding IPv4 port is in use. |
1481 * corresponding IPv4 port is in use. |
1524 */ |
1482 */ |
1525 alen = sizeof(arg); |
1483 alen = sizeof(arg); |
1526 |
1484 |
1527 if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, |
1485 if (useExclBind || |
1528 (char *)&arg, &alen) == 0) { |
1486 getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0) |
|
1487 { |
1529 if (useExclBind || arg == 0) { |
1488 if (useExclBind || arg == 0) { |
1530 /* |
1489 /* |
1531 * SO_REUSEADDR is disabled or sun.net.useExclusiveBind |
1490 * SO_REUSEADDR is disabled or sun.net.useExclusiveBind |
1532 * property is true so enable TCP_EXCLBIND or |
1491 * property is true so enable TCP_EXCLBIND or |
1533 * UDP_EXCLBIND |
1492 * UDP_EXCLBIND |
1534 */ |
1493 */ |
1535 alen = sizeof(arg); |
1494 alen = sizeof(arg); |
1536 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, |
1495 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0) |
1537 &alen) == 0) { |
1496 { |
1538 if (arg == SOCK_STREAM) { |
1497 if (arg == SOCK_STREAM) { |
1539 level = IPPROTO_TCP; |
1498 level = IPPROTO_TCP; |
1540 exclbind = TCP_EXCLBIND; |
1499 exclbind = TCP_EXCLBIND; |
1541 } else { |
1500 } else { |
1542 level = IPPROTO_UDP; |
1501 level = IPPROTO_UDP; |
1543 exclbind = UDP_EXCLBIND; |
1502 exclbind = UDP_EXCLBIND; |
1544 } |
1503 } |
1545 } |
1504 } |
1546 |
1505 |
1547 arg = 1; |
1506 arg = 1; |
1548 setsockopt(fd, level, exclbind, (char *)&arg, |
1507 setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg)); |
1549 sizeof(arg)); |
1508 } |
1550 } |
1509 } |
1551 } |
1510 |
1552 |
1511 #endif |
1553 #endif |
1512 |
1554 |
1513 rv = bind(fd, &sa->sa, len); |
1555 rv = bind(fd, him, len); |
|
1556 |
1514 |
1557 #if defined(__solaris__) |
1515 #if defined(__solaris__) |
1558 if (rv < 0) { |
1516 if (rv < 0) { |
1559 int en = errno; |
1517 int en = errno; |
1560 /* Restore *_EXCLBIND if the bind fails */ |
1518 /* Restore *_EXCLBIND if the bind fails */ |