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