| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <arpa/inet.h> |
| #include <jni.h> |
| #include <netdb.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <utils/Log.h> |
| |
| const char *GoogleDNSIpV4Address="8.8.8.8"; |
| const char *GoogleDNSIpV4Address2="8.8.4.4"; |
| const char *GoogleDNSIpV6Address="2001:4860:4860::8888"; |
| const char *GoogleDNSIpV6Address2="2001:4860:4860::8844"; |
| |
| JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclass class) |
| { |
| const char *node = "www.google.com"; |
| char *service = NULL; |
| struct addrinfo *answer; |
| |
| int res = getaddrinfo(node, service, NULL, &answer); |
| ALOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res)); |
| if (res != 0) return JNI_FALSE; |
| |
| // check for v4 & v6 |
| { |
| int foundv4 = 0; |
| int foundv6 = 0; |
| struct addrinfo *current = answer; |
| while (current != NULL) { |
| char buf[256]; |
| if (current->ai_addr->sa_family == AF_INET) { |
| inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr, |
| buf, sizeof(buf)); |
| foundv4 = 1; |
| ALOGD(" %s", buf); |
| } else if (current->ai_addr->sa_family == AF_INET6) { |
| inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr, |
| buf, sizeof(buf)); |
| foundv6 = 1; |
| ALOGD(" %s", buf); |
| } |
| current = current->ai_next; |
| } |
| |
| freeaddrinfo(answer); |
| answer = NULL; |
| if (foundv4 != 1 && foundv6 != 1) { |
| ALOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address"); |
| return JNI_FALSE; |
| } |
| } |
| |
| node = "ipv6.google.com"; |
| res = getaddrinfo(node, service, NULL, &answer); |
| ALOGD("getaddrinfo(ipv6.google.com) gave res=%d", res); |
| if (res != 0) return JNI_FALSE; |
| |
| { |
| int foundv4 = 0; |
| int foundv6 = 0; |
| struct addrinfo *current = answer; |
| while (current != NULL) { |
| char buf[256]; |
| if (current->ai_addr->sa_family == AF_INET) { |
| inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr, |
| buf, sizeof(buf)); |
| ALOGD(" %s", buf); |
| foundv4 = 1; |
| } else if (current->ai_addr->sa_family == AF_INET6) { |
| inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr, |
| buf, sizeof(buf)); |
| ALOGD(" %s", buf); |
| foundv6 = 1; |
| } |
| current = current->ai_next; |
| } |
| |
| freeaddrinfo(answer); |
| answer = NULL; |
| if (foundv4 == 1 || foundv6 != 1) { |
| ALOGD("getaddrinfo(ipv6.google.com) didn't find only v6"); |
| return JNI_FALSE; |
| } |
| } |
| |
| // getnameinfo |
| struct sockaddr_in sa4; |
| sa4.sin_family = AF_INET; |
| sa4.sin_port = 0; |
| inet_pton(AF_INET, GoogleDNSIpV4Address, &(sa4.sin_addr)); |
| |
| struct sockaddr_in6 sa6; |
| sa6.sin6_family = AF_INET6; |
| sa6.sin6_port = 0; |
| sa6.sin6_flowinfo = 0; |
| sa6.sin6_scope_id = 0; |
| inet_pton(AF_INET6, GoogleDNSIpV6Address2, &(sa6.sin6_addr)); |
| |
| char buf[NI_MAXHOST]; |
| int flags = NI_NAMEREQD; |
| |
| res = getnameinfo((const struct sockaddr*)&sa4, sizeof(sa4), buf, sizeof(buf), NULL, 0, flags); |
| if (res != 0) { |
| ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res, |
| gai_strerror(res)); |
| return JNI_FALSE; |
| } |
| if (strstr(buf, "google.com") == NULL) { |
| ALOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com: %s", |
| GoogleDNSIpV4Address, buf); |
| return JNI_FALSE; |
| } |
| |
| memset(buf, sizeof(buf), 0); |
| res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf), NULL, 0, flags); |
| if (res != 0) { |
| ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2, |
| res, gai_strerror(res)); |
| return JNI_FALSE; |
| } |
| if (strstr(buf, "google.com") == NULL) { |
| ALOGD("getnameinfo(%s) didn't return google.com: %s", GoogleDNSIpV6Address2, buf); |
| return JNI_FALSE; |
| } |
| |
| // gethostbyname |
| struct hostent *my_hostent = gethostbyname("www.youtube.com"); |
| if (my_hostent == NULL) { |
| ALOGD("gethostbyname(www.youtube.com) gave null response"); |
| return JNI_FALSE; |
| } |
| if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) { |
| ALOGD("gethostbyname(www.youtube.com) gave 0 addresses"); |
| return JNI_FALSE; |
| } |
| { |
| char **current = my_hostent->h_addr_list; |
| while (*current != NULL) { |
| char buf[256]; |
| inet_ntop(my_hostent->h_addrtype, *current, buf, sizeof(buf)); |
| ALOGD("gethostbyname(www.youtube.com) gave %s", buf); |
| current++; |
| } |
| } |
| |
| // gethostbyaddr |
| char addr6[16]; |
| inet_pton(AF_INET6, GoogleDNSIpV6Address, addr6); |
| my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6); |
| if (my_hostent == NULL) { |
| ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address); |
| return JNI_FALSE; |
| } |
| |
| ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address, |
| my_hostent->h_name ? my_hostent->h_name : "null"); |
| |
| if (my_hostent->h_name == NULL) return JNI_FALSE; |
| return JNI_TRUE; |
| } |