blob: 0d1fb158ab24bc49037b1f09a9f7e268e2972ac5 [file] [log] [blame]
Luke Huang3c5f35a2018-11-21 14:38:40 +08001/*
2 * Copyright (C) 2018 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 <arpa/nameser.h>
19#include <netinet/in.h>
20#include <sys/socket.h>
21#include <error.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <inttypes.h>
25#include <poll.h> /* poll */
26#include <resolv.h>
27#include <string.h>
28
29#include <android/multinetwork.h>
30#include <gtest/gtest.h>
31
32namespace {
33constexpr int MAXPACKET = 8 * 1024;
34constexpr int PTON_MAX = 16;
35
36int getAsyncResponse(int fd, int timeoutMs, int* rcode, u_char* buf, int bufLen) {
37 struct pollfd wait_fd[1];
38 wait_fd[0].fd = fd;
39 wait_fd[0].events = POLLIN;
40 short revents;
41 int ret;
42 ret = poll(wait_fd, 1, timeoutMs);
43 revents = wait_fd[0].revents;
44 if (revents & POLLIN) {
45 int n = android_res_nresult(fd, rcode, buf, bufLen);
46 return n;
47 }
48
49 return -1;
50}
51
52std::vector<std::string> extractIpAddressAnswers(u_char* buf, int bufLen, int ipType) {
53 ns_msg handle;
54 if (ns_initparse((const uint8_t*) buf, bufLen, &handle) < 0) {
55 return {};
56 }
57 int ancount = ns_msg_count(handle, ns_s_an);
58 ns_rr rr;
59 std::vector<std::string> answers;
60 for (int i = 0; i < ancount; i++) {
61 if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) {
62 continue;
63 }
64 const u_char* rdata = ns_rr_rdata(rr);
65 char buffer[INET6_ADDRSTRLEN];
66 if (inet_ntop(ipType, (const char*) rdata, buffer, sizeof(buffer))) {
67 answers.push_back(buffer);
68 }
69 }
70 return answers;
71}
72
73void expectAnswersValid(int fd, int ipType, int expectedRcode) {
74 int rcode = -1;
75 u_char buf[MAXPACKET] = {};
76 int res = getAsyncResponse(fd, 10000, &rcode, buf, MAXPACKET);
77 EXPECT_GT(res, 0);
78 EXPECT_EQ(rcode, expectedRcode);
79
80
81 if (expectedRcode == NOERROR) {
82 auto answers = extractIpAddressAnswers(buf, res, ipType);
83 EXPECT_GT(answers.size(), 0U);
84 for (auto &answer : answers) {
85 char pton[PTON_MAX];
86 EXPECT_EQ(1, inet_pton(ipType, answer.c_str(), pton));
87 }
88 }
89}
90
91} // namespace
92
93TEST (NativeDnsAsyncTest, Async_Query) {
94 // V4
Luke Huang84d8e362018-12-21 18:50:41 +080095 int fd = android_res_nquery(NETWORK_UNSPECIFIED ,"www.google.com", ns_c_in, ns_t_a, 0);
Luke Huang3c5f35a2018-11-21 14:38:40 +080096 EXPECT_GT(fd, 0);
97 expectAnswersValid(fd, AF_INET, NOERROR);
98
99 // V6
Luke Huang84d8e362018-12-21 18:50:41 +0800100 fd = android_res_nquery(NETWORK_UNSPECIFIED ,"www.google.com", ns_c_in, ns_t_aaaa, 0);
Luke Huang3c5f35a2018-11-21 14:38:40 +0800101 EXPECT_GT(fd, 0);
102 expectAnswersValid(fd, AF_INET6, NOERROR);
103}
104
105TEST (NativeDnsAsyncTest, Async_Send) {
106 // V4
107 u_char buf[MAXPACKET] = {};
108 int len = res_mkquery(QUERY, "www.youtube.com",
109 ns_c_in, ns_t_a, nullptr, 0, nullptr, buf, sizeof(buf));
110 EXPECT_GT(len, 0);
Luke Huang84d8e362018-12-21 18:50:41 +0800111 int fd = android_res_nsend(NETWORK_UNSPECIFIED , buf, len, 0);
Luke Huang3c5f35a2018-11-21 14:38:40 +0800112 EXPECT_GT(fd, 0);
113 expectAnswersValid(fd, AF_INET, NOERROR);
114
115 // V6
116 memset(buf, 0, MAXPACKET);
117 len = res_mkquery(QUERY, "www.youtube.com",
118 ns_c_in, ns_t_aaaa, nullptr, 0, nullptr, buf, sizeof(buf));
119 EXPECT_GT(len, 0);
Luke Huang84d8e362018-12-21 18:50:41 +0800120 fd = android_res_nsend(NETWORK_UNSPECIFIED , buf, len, 0);
Luke Huang3c5f35a2018-11-21 14:38:40 +0800121 EXPECT_GT(fd, 0);
122 expectAnswersValid(fd, AF_INET6, NOERROR);
123}
124
125TEST (NativeDnsAsyncTest, Async_NXDOMAIN) {
126 u_char buf[MAXPACKET] = {};
127 int len = res_mkquery(QUERY, "test-nx.metric.gstatic.com",
128 ns_c_in, ns_t_a, nullptr, 0, nullptr, buf, sizeof(buf));
129 EXPECT_GT(len, 0);
Luke Huang84d8e362018-12-21 18:50:41 +0800130 int fd = android_res_nsend(NETWORK_UNSPECIFIED , buf, len, 0);
Luke Huang3c5f35a2018-11-21 14:38:40 +0800131 EXPECT_GT(fd, 0);
132 expectAnswersValid(fd, AF_INET, NXDOMAIN);
133}
134
135TEST (NativeDnsAsyncTest, Async_Cancel) {
Luke Huang84d8e362018-12-21 18:50:41 +0800136 int fd = android_res_nquery(NETWORK_UNSPECIFIED ,"www.google.com", ns_c_in, ns_t_a, 0);
Luke Huang3c5f35a2018-11-21 14:38:40 +0800137 int rcode = -1;
138 u_char buf[MAXPACKET] = {};
139 android_res_cancel(fd);
140
141 int res = android_res_nresult(fd, &rcode, buf, MAXPACKET);
142 EXPECT_EQ(res, -EBADF);
143}
144
145int main(int argc, char **argv) {
146 testing::InitGoogleTest(&argc, argv);
147 return RUN_ALL_TESTS();
148}