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