src/solaris/native/java/net/Inet6AddressImpl.c

Print this page




  53 #ifndef NI_MAXHOST
  54 #define NI_MAXHOST 1025
  55 #endif
  56 
  57 
  58 /************************************************************************
  59  * Inet6AddressImpl
  60  */
  61 
  62 /*
  63  * Class:     java_net_Inet6AddressImpl
  64  * Method:    getLocalHostName
  65  * Signature: ()Ljava/lang/String;
  66  */
  67 JNIEXPORT jstring JNICALL
  68 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
  69     int ret;
  70     char hostname[NI_MAXHOST+1];
  71 
  72     hostname[0] = '\0';
  73     ret = JVM_GetHostName(hostname, sizeof(hostname));
  74     if (ret) {
  75         /* Something went wrong, maybe networking is not setup? */
  76         strcpy(hostname, "localhost");
  77     } else {
  78         // ensure null-terminated
  79         hostname[NI_MAXHOST] = '\0';
  80     }
  81 
  82 #if defined(__solaris__) && defined(AF_INET6)
  83     if (ret == 0) {
  84         /* Solaris doesn't want to give us a fully qualified domain name.
  85          * We do a reverse lookup to try and get one.  This works
  86          * if DNS occurs before NIS in /etc/resolv.conf, but fails
  87          * if NIS comes first (it still gets only a partial name).
  88          * We use thread-safe system calls.
  89          */
  90         struct addrinfo  hints, *res;
  91         int error;
  92 
  93         memset(&hints, 0, sizeof(hints));
  94         hints.ai_flags = AI_CANONNAME;


 123 lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
 124 {
 125     jobjectArray result = NULL;
 126     char myhostname[NI_MAXHOST+1];
 127     struct ifaddrs *ifa = NULL;
 128     int familyOrder = 0;
 129     int count = 0, i, j;
 130     int addrs4 = 0, addrs6 = 0, numV4Loopbacks = 0, numV6Loopbacks = 0;
 131     jboolean includeLoopback = JNI_FALSE;
 132     jobject name;
 133 
 134     initInetAddressIDs(env);
 135     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 136 
 137     /* If the requested name matches this host's hostname, return IP addresses
 138      * from all attached interfaces. (#2844683 et al) This prevents undesired
 139      * PPP dialup, but may return addresses that don't actually correspond to
 140      * the name (if the name actually matches something in DNS etc.
 141      */
 142     myhostname[0] = '\0';
 143     if (JVM_GetHostName(myhostname, NI_MAXHOST)) {
 144         /* Something went wrong, maybe networking is not setup? */
 145         return NULL;
 146     }
 147     myhostname[NI_MAXHOST] = '\0';
 148 
 149     if (strcmp(myhostname, hostname) != 0) {
 150         // Non-self lookup
 151         return NULL;
 152     }
 153 
 154     if (getifaddrs(&ifa) != 0) {
 155         NET_ThrowNew(env, errno, "Can't get local interface addresses");
 156         return NULL;
 157     }
 158 
 159     name = (*env)->NewStringUTF(env, hostname);
 160     CHECK_NULL_RETURN(name, NULL);
 161 
 162     /* Iterate over the interfaces, and total up the number of IPv4 and IPv6
 163      * addresses we have. Also keep a count of loopback addresses. We need to


 694     /*
 695      * If a network interface was specified, let's create the address
 696      * for it.
 697      */
 698     if (!(IS_NULL(ifArray))) {
 699       memset((void *) caddr, 0, 16);
 700       memset((void *) &inf6, 0, sizeof(inf6));
 701       (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
 702       memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
 703       inf6.sin6_family = AF_INET6;
 704       inf6.sin6_scope_id = if_scope;
 705       netif = &inf6;
 706     }
 707     /*
 708      * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
 709      * otherwise we'll try a tcp socket to the Echo port (7).
 710      * Note that this is empiric, and not connecting could mean it's blocked
 711      * or the echo service has been disabled.
 712      */
 713 
 714     fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
 715 
 716     if (fd != -1) { /* Good to go, let's do a ping */
 717         return ping6(env, fd, &him6, timeout, netif, ttl);
 718     }
 719 
 720     /* No good, let's fall back on TCP */
 721     fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0);
 722     if (fd == JVM_IO_ERR) {
 723         /* note: if you run out of fds, you may not be able to load
 724          * the exception class, and get a NoClassDefFoundError
 725          * instead.
 726          */
 727         NET_ThrowNew(env, errno, "Can't create socket");
 728         return JNI_FALSE;
 729     }
 730     if (ttl > 0) {
 731       setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
 732     }
 733 
 734     /*
 735      * A network interface was specified, so let's bind to it.
 736      */
 737     if (netif != NULL) {
 738       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
 739         NET_ThrowNew(env, errno, "Can't bind socket");
 740         close(fd);
 741         return JNI_FALSE;
 742       }
 743     }
 744     SET_NONBLOCKING(fd);
 745 
 746     /* no need to use NET_Connect as non-blocking */
 747     him6.sin6_port = htons((short) 7); /* Echo port */
 748     connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len);
 749 
 750     /**
 751      * connection established or refused immediately, either way it means
 752      * we were able to reach the host!
 753      */
 754     if (connect_rv == 0 || errno == ECONNREFUSED) {
 755         close(fd);
 756         return JNI_TRUE;
 757     } else {
 758         int optlen;
 759 
 760         switch (errno) {
 761         case ENETUNREACH: /* Network Unreachable */
 762         case EAFNOSUPPORT: /* Address Family not supported */
 763         case EADDRNOTAVAIL: /* address is not available on  the  remote machine */
 764 #ifdef __linux__
 765         case EINVAL:
 766         case EHOSTUNREACH:
 767           /*
 768            * On some Linux versions, when  a socket is bound to the
 769            * loopback interface, connect will fail and errno will
 770            * be set to EINVAL or EHOSTUNREACH.  When that happens,
 771            * don't throw an exception, just return false.
 772            */
 773 #endif /* __linux__ */
 774           close(fd);
 775           return JNI_FALSE;
 776         }
 777 
 778         if (errno != EINPROGRESS) {
 779             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
 780                                          "connect failed");
 781             close(fd);
 782             return JNI_FALSE;
 783         }
 784 
 785         timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
 786 
 787         if (timeout >= 0) {
 788           /* has connection been established */
 789           optlen = sizeof(connect_rv);
 790           if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
 791                              &optlen) <0) {
 792             connect_rv = errno;
 793           }
 794           if (connect_rv == 0 || ECONNREFUSED) {
 795             close(fd);
 796             return JNI_TRUE;
 797           }
 798         }
 799         close(fd);
 800         return JNI_FALSE;
 801     }
 802 #else /* AF_INET6 */
 803     return JNI_FALSE;
 804 #endif /* AF_INET6 */
 805 }


  53 #ifndef NI_MAXHOST
  54 #define NI_MAXHOST 1025
  55 #endif
  56 
  57 
  58 /************************************************************************
  59  * Inet6AddressImpl
  60  */
  61 
  62 /*
  63  * Class:     java_net_Inet6AddressImpl
  64  * Method:    getLocalHostName
  65  * Signature: ()Ljava/lang/String;
  66  */
  67 JNIEXPORT jstring JNICALL
  68 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
  69     int ret;
  70     char hostname[NI_MAXHOST+1];
  71 
  72     hostname[0] = '\0';
  73     ret = gethostname(hostname, NI_MAXHOST);
  74     if (ret == -1) {
  75         /* Something went wrong, maybe networking is not setup? */
  76         strcpy(hostname, "localhost");
  77     } else {
  78         // ensure null-terminated
  79         hostname[NI_MAXHOST] = '\0';
  80     }
  81 
  82 #if defined(__solaris__) && defined(AF_INET6)
  83     if (ret == 0) {
  84         /* Solaris doesn't want to give us a fully qualified domain name.
  85          * We do a reverse lookup to try and get one.  This works
  86          * if DNS occurs before NIS in /etc/resolv.conf, but fails
  87          * if NIS comes first (it still gets only a partial name).
  88          * We use thread-safe system calls.
  89          */
  90         struct addrinfo  hints, *res;
  91         int error;
  92 
  93         memset(&hints, 0, sizeof(hints));
  94         hints.ai_flags = AI_CANONNAME;


 123 lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
 124 {
 125     jobjectArray result = NULL;
 126     char myhostname[NI_MAXHOST+1];
 127     struct ifaddrs *ifa = NULL;
 128     int familyOrder = 0;
 129     int count = 0, i, j;
 130     int addrs4 = 0, addrs6 = 0, numV4Loopbacks = 0, numV6Loopbacks = 0;
 131     jboolean includeLoopback = JNI_FALSE;
 132     jobject name;
 133 
 134     initInetAddressIDs(env);
 135     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 136 
 137     /* If the requested name matches this host's hostname, return IP addresses
 138      * from all attached interfaces. (#2844683 et al) This prevents undesired
 139      * PPP dialup, but may return addresses that don't actually correspond to
 140      * the name (if the name actually matches something in DNS etc.
 141      */
 142     myhostname[0] = '\0';
 143     if (gethostname(myhostname, NI_MAXHOST) == -1) {
 144         /* Something went wrong, maybe networking is not setup? */
 145         return NULL;
 146     }
 147     myhostname[NI_MAXHOST] = '\0';
 148 
 149     if (strcmp(myhostname, hostname) != 0) {
 150         // Non-self lookup
 151         return NULL;
 152     }
 153 
 154     if (getifaddrs(&ifa) != 0) {
 155         NET_ThrowNew(env, errno, "Can't get local interface addresses");
 156         return NULL;
 157     }
 158 
 159     name = (*env)->NewStringUTF(env, hostname);
 160     CHECK_NULL_RETURN(name, NULL);
 161 
 162     /* Iterate over the interfaces, and total up the number of IPv4 and IPv6
 163      * addresses we have. Also keep a count of loopback addresses. We need to


 694     /*
 695      * If a network interface was specified, let's create the address
 696      * for it.
 697      */
 698     if (!(IS_NULL(ifArray))) {
 699       memset((void *) caddr, 0, 16);
 700       memset((void *) &inf6, 0, sizeof(inf6));
 701       (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
 702       memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
 703       inf6.sin6_family = AF_INET6;
 704       inf6.sin6_scope_id = if_scope;
 705       netif = &inf6;
 706     }
 707     /*
 708      * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
 709      * otherwise we'll try a tcp socket to the Echo port (7).
 710      * Note that this is empiric, and not connecting could mean it's blocked
 711      * or the echo service has been disabled.
 712      */
 713 
 714     fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
 715 
 716     if (fd != -1) { /* Good to go, let's do a ping */
 717         return ping6(env, fd, &him6, timeout, netif, ttl);
 718     }
 719 
 720     /* No good, let's fall back on TCP */
 721     fd = socket(AF_INET6, SOCK_STREAM, 0);
 722     if (fd == -1) {
 723         /* note: if you run out of fds, you may not be able to load
 724          * the exception class, and get a NoClassDefFoundError
 725          * instead.
 726          */
 727         NET_ThrowNew(env, errno, "Can't create socket");
 728         return JNI_FALSE;
 729     }
 730     if (ttl > 0) {
 731       setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
 732     }
 733 
 734     /*
 735      * A network interface was specified, so let's bind to it.
 736      */
 737     if (netif != NULL) {
 738       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
 739         NET_ThrowNew(env, errno, "Can't bind socket");
 740         close(fd);
 741         return JNI_FALSE;
 742       }
 743     }
 744     SET_NONBLOCKING(fd);
 745 

 746     him6.sin6_port = htons((short) 7); /* Echo port */
 747     connect_rv = NET_Connect(fd, (struct sockaddr *)&him6, len);
 748 
 749     /**
 750      * connection established or refused immediately, either way it means
 751      * we were able to reach the host!
 752      */
 753     if (connect_rv == 0 || errno == ECONNREFUSED) {
 754         close(fd);
 755         return JNI_TRUE;
 756     } else {
 757         socklen_t optlen = (socklen_t)sizeof(connect_rv);
 758 
 759         switch (errno) {
 760         case ENETUNREACH: /* Network Unreachable */
 761         case EAFNOSUPPORT: /* Address Family not supported */
 762         case EADDRNOTAVAIL: /* address is not available on  the  remote machine */
 763 #ifdef __linux__
 764         case EINVAL:
 765         case EHOSTUNREACH:
 766           /*
 767            * On some Linux versions, when  a socket is bound to the
 768            * loopback interface, connect will fail and errno will
 769            * be set to EINVAL or EHOSTUNREACH.  When that happens,
 770            * don't throw an exception, just return false.
 771            */
 772 #endif /* __linux__ */
 773           close(fd);
 774           return JNI_FALSE;
 775         }
 776 
 777         if (errno != EINPROGRESS) {
 778             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
 779                                          "connect failed");
 780             close(fd);
 781             return JNI_FALSE;
 782         }
 783 
 784         timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
 785 
 786         if (timeout >= 0) {
 787           /* has connection been established */
 788           if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,

 789                          &optlen) <0) {
 790             connect_rv = errno;
 791           }
 792           if (connect_rv == 0 || ECONNREFUSED) {
 793             close(fd);
 794             return JNI_TRUE;
 795           }
 796         }
 797         close(fd);
 798         return JNI_FALSE;
 799     }
 800 #else /* AF_INET6 */
 801     return JNI_FALSE;
 802 #endif /* AF_INET6 */
 803 }