Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <arpa/inet.h>
     18 #include <jni.h>
     19 #include <netdb.h>
     20 #include <stdio.h>
     21 #include <utils/Log.h>
     22 
     23 const char *GoogleDNSIpV4Address="8.8.8.8";
     24 const char *GoogleDNSIpV4Address2="8.8.4.4";
     25 const char *GoogleDNSIpV6Address="2001:4860:4860::8888";
     26 const char *GoogleDNSIpV6Address2="2001:4860:4860::8844";
     27 
     28 JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclass class)
     29 {
     30     const char *node = "www.google.com";
     31     char *service = NULL;
     32     struct addrinfo *answer;
     33 
     34     int res = getaddrinfo(node, service, NULL, &answer);
     35     ALOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res));
     36     if (res != 0) return JNI_FALSE;
     37 
     38     // check for v4 & v6
     39     {
     40         int foundv4 = 0;
     41         int foundv6 = 0;
     42         struct addrinfo *current = answer;
     43         while (current != NULL) {
     44             char buf[256];
     45             if (current->ai_addr->sa_family == AF_INET) {
     46                 inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
     47                         buf, sizeof(buf));
     48                 foundv4 = 1;
     49                 ALOGD("  %s", buf);
     50             } else if (current->ai_addr->sa_family == AF_INET6) {
     51                 inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
     52                         buf, sizeof(buf));
     53                 foundv6 = 1;
     54                 ALOGD("  %s", buf);
     55             }
     56             current = current->ai_next;
     57         }
     58 
     59         freeaddrinfo(answer);
     60         answer = NULL;
     61         if (foundv4 != 1 && foundv6 != 1) {
     62             ALOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address");
     63             return JNI_FALSE;
     64         }
     65     }
     66 
     67     node = "ipv6.google.com";
     68     res = getaddrinfo(node, service, NULL, &answer);
     69     ALOGD("getaddrinfo(ipv6.google.com) gave res=%d", res);
     70     if (res != 0) return JNI_FALSE;
     71 
     72     {
     73         int foundv4 = 0;
     74         int foundv6 = 0;
     75         struct addrinfo *current = answer;
     76         while (current != NULL) {
     77             char buf[256];
     78             if (current->ai_addr->sa_family == AF_INET) {
     79                 inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
     80                         buf, sizeof(buf));
     81                 ALOGD("  %s", buf);
     82                 foundv4 = 1;
     83             } else if (current->ai_addr->sa_family == AF_INET6) {
     84                 inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
     85                         buf, sizeof(buf));
     86                 ALOGD("  %s", buf);
     87                 foundv6 = 1;
     88             }
     89             current = current->ai_next;
     90         }
     91 
     92         freeaddrinfo(answer);
     93         answer = NULL;
     94         if (foundv4 == 1 || foundv6 != 1) {
     95             ALOGD("getaddrinfo(ipv6.google.com) didn't find only v6");
     96             return JNI_FALSE;
     97         }
     98     }
     99 
    100     // getnameinfo
    101     struct sockaddr_in sa4;
    102     sa4.sin_family = AF_INET;
    103     sa4.sin_port = 0;
    104     inet_pton(AF_INET, GoogleDNSIpV4Address, &(sa4.sin_addr));
    105 
    106     struct sockaddr_in6 sa6;
    107     sa6.sin6_family = AF_INET6;
    108     sa6.sin6_port = 0;
    109     sa6.sin6_flowinfo = 0;
    110     sa6.sin6_scope_id = 0;
    111     inet_pton(AF_INET6, GoogleDNSIpV6Address2, &(sa6.sin6_addr));
    112 
    113     char buf[NI_MAXHOST];
    114     int flags = NI_NAMEREQD;
    115 
    116     res = getnameinfo((const struct sockaddr*)&sa4, sizeof(sa4), buf, sizeof(buf), NULL, 0, flags);
    117     if (res != 0) {
    118         ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res,
    119             gai_strerror(res));
    120         return JNI_FALSE;
    121     }
    122     if (strstr(buf, "google.com") == NULL) {
    123         ALOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com: %s",
    124             GoogleDNSIpV4Address, buf);
    125         return JNI_FALSE;
    126     }
    127 
    128     memset(buf, sizeof(buf), 0);
    129     res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf), NULL, 0, flags);
    130     if (res != 0) {
    131         ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2,
    132             res, gai_strerror(res));
    133         return JNI_FALSE;
    134     }
    135     if (strstr(buf, "google.com") == NULL) {
    136         ALOGD("getnameinfo(%s) didn't return google.com: %s", GoogleDNSIpV6Address2, buf);
    137         return JNI_FALSE;
    138     }
    139 
    140     // gethostbyname
    141     struct hostent *my_hostent = gethostbyname("www.youtube.com");
    142     if (my_hostent == NULL) {
    143         ALOGD("gethostbyname(www.youtube.com) gave null response");
    144         return JNI_FALSE;
    145     }
    146     if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) {
    147         ALOGD("gethostbyname(www.youtube.com) gave 0 addresses");
    148         return JNI_FALSE;
    149     }
    150     {
    151         char **current = my_hostent->h_addr_list;
    152         while (*current != NULL) {
    153             char buf[256];
    154             inet_ntop(my_hostent->h_addrtype, *current, buf, sizeof(buf));
    155             ALOGD("gethostbyname(www.youtube.com) gave %s", buf);
    156             current++;
    157         }
    158     }
    159 
    160     // gethostbyaddr
    161     char addr6[16];
    162     inet_pton(AF_INET6, GoogleDNSIpV6Address, addr6);
    163     my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6);
    164     if (my_hostent == NULL) {
    165         ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address);
    166         return JNI_FALSE;
    167     }
    168 
    169     ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address,
    170         my_hostent->h_name ? my_hostent->h_name : "null");
    171 
    172     if (my_hostent->h_name == NULL) return JNI_FALSE;
    173     return JNI_TRUE;
    174 }
    175