• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string.h>
22 
23 #include <android/log.h>
24 
25 #define LOG_TAG "NativeDns-JNI"
26 #define LOGD(fmt, ...) \
27         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__)
28 
29 const char *GoogleDNSIpV4Address="8.8.8.8";
30 const char *GoogleDNSIpV4Address2="8.8.4.4";
31 const char *GoogleDNSIpV6Address="2001:4860:4860::8888";
32 const char *GoogleDNSIpV6Address2="2001:4860:4860::8844";
33 
Java_android_net_cts_DnsTest_testNativeDns(JNIEnv * env,jclass class)34 JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclass class)
35 {
36     const char *node = "www.google.com";
37     char *service = NULL;
38     struct addrinfo *answer;
39 
40     int res = getaddrinfo(node, service, NULL, &answer);
41     LOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res));
42     if (res != 0) return JNI_FALSE;
43 
44     // check for v4 & v6
45     {
46         int foundv4 = 0;
47         int foundv6 = 0;
48         struct addrinfo *current = answer;
49         while (current != NULL) {
50             char buf[256];
51             if (current->ai_addr->sa_family == AF_INET) {
52                 inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
53                         buf, sizeof(buf));
54                 foundv4 = 1;
55                 LOGD("  %s", buf);
56             } else if (current->ai_addr->sa_family == AF_INET6) {
57                 inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
58                         buf, sizeof(buf));
59                 foundv6 = 1;
60                 LOGD("  %s", buf);
61             }
62             current = current->ai_next;
63         }
64 
65         freeaddrinfo(answer);
66         answer = NULL;
67         if (foundv4 != 1 && foundv6 != 1) {
68             LOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address");
69             return JNI_FALSE;
70         }
71     }
72 
73     node = "ipv6.google.com";
74     res = getaddrinfo(node, service, NULL, &answer);
75     LOGD("getaddrinfo(ipv6.google.com) gave res=%d", res);
76     if (res != 0) return JNI_FALSE;
77 
78     {
79         int foundv4 = 0;
80         int foundv6 = 0;
81         struct addrinfo *current = answer;
82         while (current != NULL) {
83             char buf[256];
84             if (current->ai_addr->sa_family == AF_INET) {
85                 inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
86                         buf, sizeof(buf));
87                 LOGD("  %s", buf);
88                 foundv4 = 1;
89             } else if (current->ai_addr->sa_family == AF_INET6) {
90                 inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
91                         buf, sizeof(buf));
92                 LOGD("  %s", buf);
93                 foundv6 = 1;
94             }
95             current = current->ai_next;
96         }
97 
98         freeaddrinfo(answer);
99         answer = NULL;
100         if (foundv4 == 1 || foundv6 != 1) {
101             LOGD("getaddrinfo(ipv6.google.com) didn't find only v6");
102             return JNI_FALSE;
103         }
104     }
105 
106     // getnameinfo
107     struct sockaddr_in sa4;
108     sa4.sin_family = AF_INET;
109     sa4.sin_port = 0;
110     inet_pton(AF_INET, GoogleDNSIpV4Address, &(sa4.sin_addr));
111 
112     struct sockaddr_in6 sa6;
113     sa6.sin6_family = AF_INET6;
114     sa6.sin6_port = 0;
115     sa6.sin6_flowinfo = 0;
116     sa6.sin6_scope_id = 0;
117     inet_pton(AF_INET6, GoogleDNSIpV6Address2, &(sa6.sin6_addr));
118 
119     char buf[NI_MAXHOST];
120     int flags = NI_NAMEREQD;
121 
122     res = getnameinfo((const struct sockaddr*)&sa4, sizeof(sa4), buf, sizeof(buf), NULL, 0, flags);
123     if (res != 0) {
124         LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res,
125             gai_strerror(res));
126         return JNI_FALSE;
127     }
128     if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) {
129         LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
130             GoogleDNSIpV4Address, buf);
131         return JNI_FALSE;
132     }
133 
134     memset(buf, 0, sizeof(buf));
135     res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf), NULL, 0, flags);
136     if (res != 0) {
137         LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2,
138             res, gai_strerror(res));
139         return JNI_FALSE;
140     }
141     if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) {
142         LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
143             GoogleDNSIpV6Address2, buf);
144         return JNI_FALSE;
145     }
146 
147     // gethostbyname
148     struct hostent *my_hostent = gethostbyname("www.youtube.com");
149     if (my_hostent == NULL) {
150         LOGD("gethostbyname(www.youtube.com) gave null response");
151         return JNI_FALSE;
152     }
153     if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) {
154         LOGD("gethostbyname(www.youtube.com) gave 0 addresses");
155         return JNI_FALSE;
156     }
157     {
158         char **current = my_hostent->h_addr_list;
159         while (*current != NULL) {
160             char buf[256];
161             inet_ntop(my_hostent->h_addrtype, *current, buf, sizeof(buf));
162             LOGD("gethostbyname(www.youtube.com) gave %s", buf);
163             current++;
164         }
165     }
166 
167     // gethostbyaddr
168     char addr6[16];
169     inet_pton(AF_INET6, GoogleDNSIpV6Address, addr6);
170     my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6);
171     if (my_hostent == NULL) {
172         LOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address);
173         return JNI_FALSE;
174     }
175 
176     LOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address,
177         my_hostent->h_name ? my_hostent->h_name : "null");
178 
179     if (my_hostent->h_name == NULL) return JNI_FALSE;
180     return JNI_TRUE;
181 }
182