| /* |
| * 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 <utils/Log.h> |
| |
| 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 both v4 and v6"); |
| 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, "173.252.110.27", &(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, "2001:4860:4001:802::1008", &(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(173.252.110.27 (facebook) ) gave error %d (%s)", res, gai_strerror(res)); |
| return JNI_FALSE; |
| } |
| if (strstr(buf, "facebook.com") == NULL) { |
| ALOGD("getnameinfo(173.252.110.27 (facebook) ) didn't return facebook.com: %s", 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(2a03:2880:2110:df01:face:b00c::8 (facebook) ) gave error %d (%s)", |
| res, gai_strerror(res)); |
| return JNI_FALSE; |
| } |
| if (strstr(buf, "1e100.net") == NULL) { |
| ALOGD("getnameinfo(2a03:2880:2110:df01:face:b00c::8) didn't return facebook.com: %s", buf); |
| return JNI_FALSE; |
| } |
| |
| // gethostbyname |
| struct hostent *my_hostent = gethostbyname("www.mit.edu"); |
| if (my_hostent == NULL) { |
| ALOGD("gethostbyname(www.mit.edu) gave null response"); |
| return JNI_FALSE; |
| } |
| if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) { |
| ALOGD("gethostbyname(www.mit.edu) 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.mit.edu) gave %s", buf); |
| current++; |
| } |
| } |
| |
| // gethostbyaddr |
| char addr6[16]; |
| inet_pton(AF_INET6, "2001:4b10:bbc::2", addr6); |
| my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6); |
| if (my_hostent == NULL) { |
| ALOGD("gethostbyaddr(2001:4b10:bbc::2 (bbc) ) gave null response"); |
| return JNI_FALSE; |
| } |
| ALOGD("gethostbyaddr(2001:4b10:bbc::2 (bbc) ) gave %s for name", |
| my_hostent->h_name ? my_hostent->h_name : "null"); |
| if (my_hostent->h_name == NULL) return JNI_FALSE; |
| return JNI_TRUE; |
| } |