750 CLOSE_SOCKETS_AND_RETURN; |
750 CLOSE_SOCKETS_AND_RETURN; |
751 } |
751 } |
752 return 0; |
752 return 0; |
753 } |
753 } |
754 |
754 |
755 /* |
|
756 * Determine the default interface for an IPv6 address. |
|
757 * |
|
758 * Returns :- |
|
759 * 0 if error |
|
760 * > 0 interface index to use |
|
761 */ |
|
762 jint getDefaultIPv6Interface(JNIEnv *env, struct sockaddr_in6 *target_addr) |
|
763 { |
|
764 int ret; |
|
765 DWORD b; |
|
766 struct sockaddr_in6 route; |
|
767 SOCKET fd = socket(AF_INET6, SOCK_STREAM, 0); |
|
768 if (fd == INVALID_SOCKET) { |
|
769 return 0; |
|
770 } |
|
771 |
|
772 ret = WSAIoctl(fd, SIO_ROUTING_INTERFACE_QUERY, |
|
773 (void *)target_addr, sizeof(struct sockaddr_in6), |
|
774 (void *)&route, sizeof(struct sockaddr_in6), |
|
775 &b, 0, 0); |
|
776 if (ret == SOCKET_ERROR) { |
|
777 // error |
|
778 closesocket(fd); |
|
779 return 0; |
|
780 } else { |
|
781 closesocket(fd); |
|
782 return route.sin6_scope_id; |
|
783 } |
|
784 } |
|
785 |
|
786 /** |
755 /** |
787 * Enables SIO_LOOPBACK_FAST_PATH |
756 * Enables SIO_LOOPBACK_FAST_PATH |
788 */ |
757 */ |
789 JNIEXPORT jint JNICALL |
758 JNIEXPORT jint JNICALL |
790 NET_EnableFastTcpLoopback(int fd) { |
759 NET_EnableFastTcpLoopback(int fd) { |
818 !(family == java_net_InetAddress_IPv4 && |
787 !(family == java_net_InetAddress_IPv4 && |
819 v4MappedAddress == JNI_FALSE)) |
788 v4MappedAddress == JNI_FALSE)) |
820 { |
789 { |
821 jbyte caddr[16]; |
790 jbyte caddr[16]; |
822 jint address; |
791 jint address; |
823 unsigned int scopeid = 0, cached_scope_id = 0; |
792 unsigned int scopeid = 0; |
824 |
793 |
825 if (family == java_net_InetAddress_IPv4) { |
794 if (family == java_net_InetAddress_IPv4) { |
826 // convert to IPv4-mapped address |
795 // convert to IPv4-mapped address |
827 memset((char *)caddr, 0, 16); |
796 memset((char *)caddr, 0, 16); |
828 address = getInetAddress_addr(env, iaObj); |
797 address = getInetAddress_addr(env, iaObj); |
840 caddr[15] = (address & 0xff); |
809 caddr[15] = (address & 0xff); |
841 } |
810 } |
842 } else { |
811 } else { |
843 getInet6Address_ipaddress(env, iaObj, (char *)caddr); |
812 getInet6Address_ipaddress(env, iaObj, (char *)caddr); |
844 scopeid = getInet6Address_scopeid(env, iaObj); |
813 scopeid = getInet6Address_scopeid(env, iaObj); |
845 cached_scope_id = (unsigned int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); |
|
846 } |
814 } |
847 sa->sa6.sin6_port = (u_short)htons((u_short)port); |
815 sa->sa6.sin6_port = (u_short)htons((u_short)port); |
848 memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr)); |
816 memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr)); |
849 sa->sa6.sin6_family = AF_INET6; |
817 sa->sa6.sin6_family = AF_INET6; |
850 if ((family == java_net_InetAddress_IPv6) && |
818 sa->sa6.sin6_scope_id = scopeid; |
851 IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr) && |
|
852 (!scopeid && !cached_scope_id)) |
|
853 { |
|
854 cached_scope_id = getDefaultIPv6Interface(env, &sa->sa6); |
|
855 (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); |
|
856 } |
|
857 sa->sa6.sin6_scope_id = scopeid == 0 ? cached_scope_id : scopeid; |
|
858 if (len != NULL) { |
819 if (len != NULL) { |
859 *len = sizeof(struct sockaddr_in6); |
820 *len = sizeof(struct sockaddr_in6); |
860 } |
821 } |
861 } else { |
822 } else { |
862 jint address; |
823 jint address; |