blob: 92fc2771c472c3f454b4f97b26d54978cbbcee05 [file] [log] [blame]
Hungming Chenf9cd4eb2019-08-06 20:55:28 +09001/*
2 * Copyright (C) 2019 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
18#define LOG_TAG "resolv_gold_test"
19
Hungming Chenc6556622019-10-02 16:01:07 +080020#include <Fwmark.h>
21#include <android-base/chrono_utils.h>
Hungming Chen21c0f832019-09-20 18:38:47 +080022#include <android-base/file.h>
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090023#include <gmock/gmock-matchers.h>
Hungming Chen21c0f832019-09-20 18:38:47 +080024#include <google/protobuf/text_format.h>
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090025#include <gtest/gtest.h>
26
Hungming Chenc6556622019-10-02 16:01:07 +080027#include "PrivateDnsConfiguration.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090028#include "dns_responder/dns_responder.h"
Hungming Chenc6556622019-10-02 16:01:07 +080029#include "dns_responder_client.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090030#include "getaddrinfo.h"
Hungming Chen21c0f832019-09-20 18:38:47 +080031#include "golddata.pb.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090032#include "resolv_cache.h"
33#include "resolv_test_utils.h"
Hungming Chenc6556622019-10-02 16:01:07 +080034#include "tests/dns_responder/dns_tls_certificate.h"
35#include "tests/dns_responder/dns_tls_frontend.h"
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090036
37namespace android {
38namespace net {
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090039using android::netdutils::ScopedAddrinfo;
Hungming Chenc6556622019-10-02 16:01:07 +080040using std::chrono::milliseconds;
41
42const std::string kTestDataPath = android::base::GetExecutableDirectory() + "/testdata/";
Hungming Chen2a56a622019-09-24 17:01:01 +080043const std::vector<std::string> kGoldFilesGetAddrInfo = {
44 "getaddrinfo.topsite.google.pbtxt", "getaddrinfo.topsite.youtube.pbtxt",
45 "getaddrinfo.topsite.amazon.pbtxt", "getaddrinfo.topsite.yahoo.pbtxt",
46 "getaddrinfo.topsite.facebook.pbtxt", "getaddrinfo.topsite.reddit.pbtxt",
47 "getaddrinfo.topsite.wikipedia.pbtxt", "getaddrinfo.topsite.ebay.pbtxt",
48 "getaddrinfo.topsite.netflix.pbtxt", "getaddrinfo.topsite.bing.pbtxt"};
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090049
Hungming Chen21c0f832019-09-20 18:38:47 +080050// Fixture test class definition.
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090051class TestBase : public ::testing::Test {
52 protected:
53 void SetUp() override {
54 // Create cache for test
55 resolv_create_cache_for_net(TEST_NETID);
56 }
57
58 void TearDown() override {
Hungming Chenc6556622019-10-02 16:01:07 +080059 // Clear TLS configuration for test
60 gPrivateDnsConfiguration.clear(TEST_NETID);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090061 // Delete cache for test
62 resolv_delete_cache_for_net(TEST_NETID);
63 }
64
Hungming Chenc6556622019-10-02 16:01:07 +080065 void SetResolverConfiguration(const std::vector<std::string>& servers = {},
66 const std::vector<std::string>& domains = {},
67 const std::vector<std::string>& tlsServers = {},
68 const std::string& tlsHostname = "",
69 const std::string& caCert = "") {
70 // Determine the DNS configuration steps from setResolverConfiguration() in
71 // packages/modules/DnsResolver/ResolverController.cpp. The gold test just needs to setup
72 // simply DNS and DNS-over-TLS server configuration. Some implementation in
73 // setResolverConfiguration() are not required. For example, limiting TLS server amount is
74 // not necessary for gold test because gold test has only one TLS server for testing
75 // so far.
76 Fwmark fwmark;
77 fwmark.netId = TEST_NETID;
78 fwmark.explicitlySelected = true;
79 fwmark.protectedFromVpn = true;
80 fwmark.permission = PERMISSION_SYSTEM;
81 ASSERT_EQ(gPrivateDnsConfiguration.set(TEST_NETID, fwmark.intValue, tlsServers, tlsHostname,
82 caCert),
83 0);
84 ASSERT_EQ(resolv_set_nameservers(TEST_NETID, servers, domains, kParams), 0);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +090085 }
86
Hungming Chenc6556622019-10-02 16:01:07 +080087 void SetResolvers() { SetResolverConfiguration(kDefaultServers, kDefaultSearchDomains); }
88
89 void SetResolversWithTls() {
90 // Pass servers as both network-assigned and TLS servers. Tests can
91 // determine on which server and by which protocol queries arrived.
92 // See also DnsClient::SetResolversWithTls() in
93 // packages/modules/DnsResolver/tests/dns_responder/dns_responder_client.h.
94 SetResolverConfiguration(kDefaultServers, kDefaultSearchDomains, kDefaultServers,
95 kDefaultPrivateDnsHostName, kCaCert);
96 }
97
98 bool WaitForPrivateDnsValidation(const std::string& serverAddr) {
99 constexpr milliseconds retryIntervalMs{20};
100 constexpr milliseconds timeoutMs{3000};
101 android::base::Timer t;
102 while (t.duration() < timeoutMs) {
103 const auto& validatedServers =
104 gPrivateDnsConfiguration.getStatus(TEST_NETID).validatedServers();
105 for (const auto& server : validatedServers) {
106 if (serverAddr == ToString(&server.ss)) return true;
107 }
108 std::this_thread::sleep_for(retryIntervalMs);
109 }
110 return false;
111 }
112
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900113 static constexpr res_params kParams = {
114 .sample_validity = 300,
115 .success_threshold = 25,
116 .min_samples = 8,
117 .max_samples = 8,
118 .base_timeout_msec = 1000,
119 .retry_count = 2,
120 };
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900121 static constexpr android_net_context kNetcontext = {
122 .app_netid = TEST_NETID,
123 .app_mark = MARK_UNSET,
124 .dns_netid = TEST_NETID,
125 .dns_mark = MARK_UNSET,
126 .uid = NET_CONTEXT_INVALID_UID,
127 };
Hungming Chenc6556622019-10-02 16:01:07 +0800128 static constexpr android_net_context kNetcontextTls = {
129 .app_netid = TEST_NETID,
130 .app_mark = MARK_UNSET,
131 .dns_netid = TEST_NETID,
132 .dns_mark = MARK_UNSET,
133 .uid = NET_CONTEXT_INVALID_UID,
134 // Set TLS flags. See also maybeFixupNetContext() in
135 // packages/modules/DnsResolver/DnsProxyListener.cpp.
136 .flags = NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS,
137 };
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900138};
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900139class ResolvGetAddrInfo : public TestBase {};
140
Hungming Chen21c0f832019-09-20 18:38:47 +0800141// Parameterized test class definition.
142class ResolvGoldTest : public TestBase, public ::testing::WithParamInterface<std::string> {};
143
144// GetAddrInfo tests.
Hungming Chen2a56a622019-09-24 17:01:01 +0800145INSTANTIATE_TEST_SUITE_P(GetAddrInfo, ResolvGoldTest, ::testing::ValuesIn(kGoldFilesGetAddrInfo),
Hungming Chen21c0f832019-09-20 18:38:47 +0800146 [](const ::testing::TestParamInfo<std::string>& info) {
147 std::string name = info.param;
148 std::replace_if(
149 std::begin(name), std::end(name),
150 [](char ch) { return !std::isalnum(ch); }, '_');
151 return name;
152 });
153
154// Fixture tests.
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900155TEST_F(ResolvGetAddrInfo, RemovePacketMapping) {
156 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
157 ASSERT_TRUE(dns.startServer());
Hungming Chenc6556622019-10-02 16:01:07 +0800158 ASSERT_NO_FATAL_FAILURE(SetResolvers());
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900159
160 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, kHelloExampleComResponseV4);
161
162 addrinfo* res = nullptr;
163 const addrinfo hints = {.ai_family = AF_INET};
164 NetworkDnsEventReported event;
165 int rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
166 ScopedAddrinfo result(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800167 ASSERT_NE(result, nullptr);
168 ASSERT_EQ(rv, 0);
169 EXPECT_EQ(ToString(result), "1.2.3.4");
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900170
171 // Remove existing DNS record.
172 dns.removeMappingBinaryPacket(kHelloExampleComQueryV4);
173
174 // Expect to have no answer in DNS query result.
175 rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
176 result.reset(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800177 ASSERT_EQ(result, nullptr);
178 ASSERT_EQ(rv, EAI_NODATA);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900179}
180
181TEST_F(ResolvGetAddrInfo, ReplacePacketMapping) {
182 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
183 ASSERT_TRUE(dns.startServer());
Hungming Chenc6556622019-10-02 16:01:07 +0800184 ASSERT_NO_FATAL_FAILURE(SetResolvers());
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900185
186 // Register the record which uses IPv4 address 1.2.3.4.
187 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, kHelloExampleComResponseV4);
188
189 // Expect that the DNS query returns IPv4 address 1.2.3.4.
190 addrinfo* res = nullptr;
191 const addrinfo hints = {.ai_family = AF_INET};
192 NetworkDnsEventReported event;
193 int rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
194 ScopedAddrinfo result(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800195 ASSERT_NE(result, nullptr);
196 ASSERT_EQ(rv, 0);
197 EXPECT_EQ(ToString(result), "1.2.3.4");
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900198
199 // Replace the registered record with a record which uses new IPv4 address 5.6.7.8.
200 std::vector<uint8_t> newHelloExampleComResponseV4 = {
201 /* Header */
202 0x00, 0x00, /* Transaction ID: 0x0000 */
203 0x81, 0x80, /* Flags: qr rd ra */
204 0x00, 0x01, /* Questions: 1 */
205 0x00, 0x01, /* Answer RRs: 1 */
206 0x00, 0x00, /* Authority RRs: 0 */
207 0x00, 0x00, /* Additional RRs: 0 */
208 /* Queries */
209 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
210 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
211 0x00, 0x01, /* Type: A */
212 0x00, 0x01, /* Class: IN */
213 /* Answers */
214 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
215 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
216 0x00, 0x01, /* Type: A */
217 0x00, 0x01, /* Class: IN */
218 0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
219 0x00, 0x04, /* Data length: 4 */
220 0x05, 0x06, 0x07, 0x08 /* Address: 5.6.7.8 */
221 };
222 dns.addMappingBinaryPacket(kHelloExampleComQueryV4, newHelloExampleComResponseV4);
223
224 // Expect that DNS query returns new IPv4 address 5.6.7.8.
225 rv = resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontext, &res, &event);
226 result.reset(res);
Hungming Chenc6556622019-10-02 16:01:07 +0800227 ASSERT_NE(result, nullptr);
228 ASSERT_EQ(rv, 0);
229 EXPECT_EQ(ToString(result), "5.6.7.8");
230}
231
232TEST_F(ResolvGetAddrInfo, BasicTlsQuery) {
233 test::DNSResponder dns;
234 dns.addMapping(kHelloExampleCom, ns_type::ns_t_a, "1.2.3.4");
235 dns.addMapping(kHelloExampleCom, ns_type::ns_t_aaaa, "::1.2.3.4");
236 ASSERT_TRUE(dns.startServer());
237
238 test::DnsTlsFrontend tls;
239 ASSERT_TRUE(tls.startServer());
240 ASSERT_NO_FATAL_FAILURE(SetResolversWithTls());
241 EXPECT_TRUE(WaitForPrivateDnsValidation(tls.listen_address()));
242
243 dns.clearQueries();
244 addrinfo* res = nullptr;
245 // If the socket type is not specified, every address will appear twice, once for
246 // SOCK_STREAM and one for SOCK_DGRAM. Just pick one because the addresses for
247 // the second query of different socket type are responded by the cache.
248 const addrinfo hints = {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM};
249 NetworkDnsEventReported event;
250 const int rv =
251 resolv_getaddrinfo(kHelloExampleCom, nullptr, &hints, &kNetcontextTls, &res, &event);
252 ScopedAddrinfo result(res);
253 ASSERT_EQ(rv, 0);
254 EXPECT_EQ(GetNumQueries(dns, kHelloExampleCom), 2U);
255 const std::vector<std::string> result_strs = ToStrings(result);
256 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray({"1.2.3.4", "::1.2.3.4"}));
257 EXPECT_EQ(tls.queries(), 3);
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900258}
259
Hungming Chen21c0f832019-09-20 18:38:47 +0800260// Parameterized tests.
261TEST_P(ResolvGoldTest, GoldData) {
262 const auto& testFile = GetParam();
263
264 // Convert the testing configuration from .pbtxt file to proto.
265 std::string file_content;
266 ASSERT_TRUE(android::base::ReadFileToString(kTestDataPath + testFile, &file_content))
267 << strerror(errno);
268 android::net::GoldTest goldtest;
269 ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(file_content, &goldtest));
270 ASSERT_EQ(android::net::CallType::CALL_GETADDRINFO, goldtest.config().call());
271 ASSERT_TRUE(goldtest.config().has_addrinfo());
272
273 test::DNSResponder dns(test::DNSResponder::MappingType::BINARY_PACKET);
274 ASSERT_TRUE(dns.startServer());
Hungming Chenc6556622019-10-02 16:01:07 +0800275 ASSERT_NO_FATAL_FAILURE(SetResolvers());
Hungming Chen21c0f832019-09-20 18:38:47 +0800276
277 // Register packet mapping (query, response) from proto.
278 for (const auto& m : goldtest.packet_mapping()) {
279 // Convert string to bytes because .proto type "bytes" is "string" type in C++.
280 // See also the section "Scalar Value Types" in "Language Guide (proto3)".
281 dns.addMappingBinaryPacket(std::vector<uint8_t>(m.query().begin(), m.query().end()),
282 std::vector<uint8_t>(m.response().begin(), m.response().end()));
283 }
284
285 addrinfo* res = nullptr;
286 const auto& args = goldtest.config().addrinfo();
287 const addrinfo hints = {
Hungming Chen21c0f832019-09-20 18:38:47 +0800288 // Clear the flag AI_ADDRCONFIG to avoid flaky test because AI_ADDRCONFIG looks at
289 // whether connectivity is available. It makes that the resolver may send only A
290 // or AAAA DNS query per connectivity even AF_UNSPEC has been assigned. See also
291 // have_ipv6() and have_ipv4() in packages/modules/DnsResolver/getaddrinfo.cpp.
292 // TODO: Consider keeping the configuration flag AI_ADDRCONFIG once the unit
293 // test can treat the IPv4 and IPv6 connectivity.
294 .ai_flags = args.ai_flags() & ~AI_ADDRCONFIG,
Nick Desaulniersdffafb72019-11-11 16:17:57 -0800295 .ai_family = args.family(),
296 .ai_socktype = args.socktype(),
297 .ai_protocol = args.protocol(),
Hungming Chen21c0f832019-09-20 18:38:47 +0800298 };
299 NetworkDnsEventReported event;
Hungming Chenc6556622019-10-02 16:01:07 +0800300 const int rv =
301 resolv_getaddrinfo(args.host().c_str(), nullptr, &hints, &kNetcontext, &res, &event);
Hungming Chen21c0f832019-09-20 18:38:47 +0800302 ScopedAddrinfo result(res);
303 ASSERT_EQ(goldtest.result().return_code(), rv);
304
305 if (goldtest.result().return_code() != GT_EAI_NO_ERROR) {
Hungming Chenc6556622019-10-02 16:01:07 +0800306 ASSERT_EQ(result, nullptr);
Hungming Chen21c0f832019-09-20 18:38:47 +0800307 } else {
Hungming Chenc6556622019-10-02 16:01:07 +0800308 ASSERT_NE(result, nullptr);
Hungming Chen21c0f832019-09-20 18:38:47 +0800309 const auto& addresses = goldtest.result().addresses();
310 EXPECT_THAT(ToStrings(result),
311 ::testing::UnorderedElementsAreArray(
312 std::vector<std::string>(addresses.begin(), addresses.end())));
313 }
Hungming Chenc6556622019-10-02 16:01:07 +0800314 EXPECT_EQ(GetNumQueries(dns, args.host().c_str()), (hints.ai_family == AF_UNSPEC) ? 2U : 1U);
Hungming Chen21c0f832019-09-20 18:38:47 +0800315}
316
Hungming Chenf9cd4eb2019-08-06 20:55:28 +0900317} // end of namespace net
318} // end of namespace android