• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #pragma once
19 
20 #include <arpa/nameser.h>
21 #include <netdb.h>
22 
23 #include <filesystem>
24 #include <functional>
25 #include <string>
26 #include <vector>
27 
28 #include <aidl/android/net/INetd.h>
29 #include <aidl/android/net/ResolverParamsParcel.h>
30 #include <android-base/properties.h>
31 #include <android-modules-utils/sdk_level.h>
32 #include <firewall.h>
33 #include <gtest/gtest.h>
34 #include <netdutils/InternetAddresses.h>
35 
36 #include "dns_responder/dns_responder.h"
37 #include "params.h"
38 #include "util.h"
39 
40 class ScopeBlockedUIDRule {
41     using INetd = aidl::android::net::INetd;
42 
43   public:
ScopeBlockedUIDRule(INetd * netSrv,uid_t testUid)44     ScopeBlockedUIDRule(INetd* netSrv, uid_t testUid)
45         : mNetSrv(netSrv), mTestUid(testUid), mSavedUid(getuid()) {
46         // Add drop rule for testUid. Also enable the standby chain because it might not be
47         // enabled. Unfortunately we cannot use FIREWALL_CHAIN_NONE, or custom iptables rules, for
48         // this purpose because netd calls fchown() on the DNS query sockets, and "iptables -m
49         // owner" matches the UID of the socket creator, not the UID set by fchown().
50         // TODO: migrate FIREWALL_CHAIN_NONE to eBPF as well.
51         if (android::modules::sdklevel::IsAtLeastT()) {
52             mFw = Firewall::getInstance();
53             EXPECT_RESULT_OK(mFw->toggleStandbyMatch(true));
54             EXPECT_RESULT_OK(mFw->addRule(mTestUid, STANDBY_MATCH));
55         } else {
56             EXPECT_TRUE(
57                     mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, true).isOk());
58             EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid,
59                                                     INetd::FIREWALL_RULE_DENY)
60                                 .isOk());
61         }
62         EXPECT_TRUE(seteuid(mTestUid) == 0);
63     };
~ScopeBlockedUIDRule()64     ~ScopeBlockedUIDRule() {
65         // Restore uid
66         EXPECT_TRUE(seteuid(mSavedUid) == 0);
67         // Remove drop rule for testUid, and disable the standby chain.
68         if (android::modules::sdklevel::IsAtLeastT()) {
69             EXPECT_RESULT_OK(mFw->removeRule(mTestUid, STANDBY_MATCH));
70             EXPECT_RESULT_OK(mFw->toggleStandbyMatch(false));
71         } else {
72             EXPECT_TRUE(mNetSrv->firewallSetUidRule(INetd::FIREWALL_CHAIN_STANDBY, mTestUid,
73                                                     INetd::FIREWALL_RULE_ALLOW)
74                                 .isOk());
75             EXPECT_TRUE(
76                     mNetSrv->firewallEnableChildChain(INetd::FIREWALL_CHAIN_STANDBY, false).isOk());
77         }
78     }
79 
80   private:
81     INetd* mNetSrv;
82     Firewall* mFw;
83     const uid_t mTestUid;
84     const uid_t mSavedUid;
85 };
86 
87 // Supported from T+ only.
88 class ScopedSetDataSaverByBPF {
89   public:
ScopedSetDataSaverByBPF(bool wanted)90     ScopedSetDataSaverByBPF(bool wanted) {
91         if (android::modules::sdklevel::IsAtLeastT()) {
92             mFw = Firewall::getInstance();
93             // Backup current setting.
94             const Result<bool> current = mFw->getDataSaverSetting();
95             EXPECT_RESULT_OK(current);
96             if (wanted != current.value()) {
97                 mSavedDataSaverSetting = current;
98                 EXPECT_RESULT_OK(mFw->setDataSaver(wanted));
99             }
100         }
101     };
~ScopedSetDataSaverByBPF()102     ~ScopedSetDataSaverByBPF() {
103         // Restore the setting.
104         if (mSavedDataSaverSetting.has_value()) {
105             EXPECT_RESULT_OK(mFw->setDataSaver(mSavedDataSaverSetting.value()));
106         }
107     }
108 
109   private:
110     Firewall* mFw;
111     Result<bool> mSavedDataSaverSetting;
112 };
113 
114 class ScopedChangeUID {
115   public:
ScopedChangeUID(uid_t testUid)116     ScopedChangeUID(uid_t testUid) : mTestUid(testUid), mSavedUid(getuid()) {
117         EXPECT_TRUE(seteuid(mTestUid) == 0);
118     };
~ScopedChangeUID()119     ~ScopedChangeUID() { EXPECT_TRUE(seteuid(mSavedUid) == 0); }
120 
121   private:
122     const uid_t mTestUid;
123     const uid_t mSavedUid;
124 };
125 
126 class ScopedSystemProperties {
127   public:
ScopedSystemProperties(const std::string & key,const std::string & value)128     ScopedSystemProperties(const std::string& key, const std::string& value) : mStoredKey(key) {
129         mStoredValue = android::base::GetProperty(key, "");
130         android::base::SetProperty(key, value);
131     }
~ScopedSystemProperties()132     ~ScopedSystemProperties() { android::base::SetProperty(mStoredKey, mStoredValue); }
133 
134   private:
135     std::string mStoredKey;
136     std::string mStoredValue;
137 };
138 
139 class ScopedDefaultNetwork {
140     using INetd = aidl::android::net::INetd;
141 
142   public:
ScopedDefaultNetwork(INetd * netSrv,uid_t testDefaultNetwork)143     ScopedDefaultNetwork(INetd* netSrv, uid_t testDefaultNetwork) : mNetSrv(netSrv) {
144         EXPECT_TRUE(mNetSrv->networkGetDefault(&mStoredDefaultNetwork).isOk());
145         EXPECT_TRUE(mNetSrv->networkSetDefault(testDefaultNetwork).isOk());
146     };
~ScopedDefaultNetwork()147     ~ScopedDefaultNetwork() {
148         EXPECT_TRUE(mNetSrv->networkSetDefault(mStoredDefaultNetwork).isOk());
149     }
150 
151   private:
152     INetd* mNetSrv;
153     int mStoredDefaultNetwork;
154 };
155 
156 struct DnsRecord {
157     std::string host_name;  // host name
158     ns_type type;           // record type
159     std::string addr;       // ipv4/v6 address
160 };
161 
162 // TODO: make this dynamic and stop depending on implementation details.
163 constexpr int TEST_NETID = 30;
164 // Use the biggest two reserved appId for applications to avoid conflict with existing uids.
165 constexpr int TEST_UID = 99999;
166 constexpr int TEST_UID2 = 99998;
167 
168 constexpr char kDnsPortString[] = "53";
169 constexpr char kDohPortString[] = "443";
170 constexpr char kDotPortString[] = "853";
171 
172 const std::string kFlagPrefix("persist.device_config.netd_native.");
173 
174 const std::string kDohEarlyDataFlag(kFlagPrefix + "doh_early_data");
175 const std::string kDohIdleTimeoutFlag(kFlagPrefix + "doh_idle_timeout_ms");
176 const std::string kDohProbeTimeoutFlag(kFlagPrefix + "doh_probe_timeout_ms");
177 const std::string kDohQueryTimeoutFlag(kFlagPrefix + "doh_query_timeout_ms");
178 const std::string kDohSessionResumptionFlag(kFlagPrefix + "doh_session_resumption");
179 const std::string kDotAsyncHandshakeFlag(kFlagPrefix + "dot_async_handshake");
180 const std::string kDotConnectTimeoutMsFlag(kFlagPrefix + "dot_connect_timeout_ms");
181 const std::string kDotMaxretriesFlag(kFlagPrefix + "dot_maxtries");
182 const std::string kDotQueryTimeoutMsFlag(kFlagPrefix + "dot_query_timeout_ms");
183 const std::string kDotQuickFallbackFlag(kFlagPrefix + "dot_quick_fallback");
184 const std::string kDotRevalidationThresholdFlag(kFlagPrefix + "dot_revalidation_threshold");
185 const std::string kDotXportUnusableThresholdFlag(kFlagPrefix + "dot_xport_unusable_threshold");
186 const std::string kDotValidationLatencyFactorFlag(kFlagPrefix + "dot_validation_latency_factor");
187 const std::string kDotValidationLatencyOffsetMsFlag(kFlagPrefix +
188                                                     "dot_validation_latency_offset_ms");
189 const std::string kFailFastOnUidNetworkBlockingFlag(kFlagPrefix +
190                                                     "fail_fast_on_uid_network_blocking");
191 const std::string kKeepListeningUdpFlag(kFlagPrefix + "keep_listening_udp");
192 const std::string kNoRetryAfterCancelFlag(kFlagPrefix + "no_retry_after_cancel");
193 const std::string kParallelLookupSleepTimeFlag(kFlagPrefix + "parallel_lookup_sleep_time");
194 const std::string kRetransIntervalFlag(kFlagPrefix + "retransmission_time_interval");
195 const std::string kRetryCountFlag(kFlagPrefix + "retry_count");
196 const std::string kSortNameserversFlag(kFlagPrefix + "sort_nameservers");
197 
198 const std::string kPersistNetPrefix("persist.net.");
199 
200 const std::string kQueryLogSize(kPersistNetPrefix + "dns_query_log_size");
201 
202 static constexpr char kLocalHost[] = "localhost";
203 static constexpr char kLocalHostAddr[] = "127.0.0.1";
204 static constexpr char kIp6LocalHost[] = "ip6-localhost";
205 static constexpr char kIp6LocalHostAddr[] = "::1";
206 static constexpr char kHelloExampleCom[] = "hello.example.com.";
207 static constexpr char kHelloExampleComAddrV4[] = "1.2.3.4";
208 static constexpr char kHelloExampleComAddrV4_2[] = "8.8.8.8";
209 static constexpr char kHelloExampleComAddrV4_3[] = "81.117.21.202";
210 static constexpr char kHelloExampleComAddrV6[] = "::1.2.3.4";
211 static constexpr char kHelloExampleComAddrV6_IPV4COMPAT[] = "::1.2.3.4";
212 static constexpr char kHelloExampleComAddrV6_TEREDO[] = "2001::47c1";
213 static constexpr char kHelloExampleComAddrV6_GUA[] = "2404:6800::5175:15ca";
214 static constexpr char kExampleComDomain[] = ".example.com";
215 
216 static const std::string kNat64Prefix = "64:ff9b::/96";
217 static const std::string kNat64Prefix2 = "2001:db8:6464::/96";
218 
219 constexpr size_t kMaxmiumLabelSize = 63;  // see RFC 1035 section 2.3.4.
220 
221 static const std::vector<uint8_t> kHelloExampleComQueryV4 = {
222         /* Header */
223         0x00, 0x00, /* Transaction ID: 0x0000 */
224         0x01, 0x00, /* Flags: rd */
225         0x00, 0x01, /* Questions: 1 */
226         0x00, 0x00, /* Answer RRs: 0 */
227         0x00, 0x00, /* Authority RRs: 0 */
228         0x00, 0x00, /* Additional RRs: 0 */
229         /* Queries */
230         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
231         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
232         0x00, 0x01,             /* Type: A */
233         0x00, 0x01              /* Class: IN */
234 };
235 
236 static const std::vector<uint8_t> kHelloExampleComResponseV4 = {
237         /* Header */
238         0x00, 0x00, /* Transaction ID: 0x0000 */
239         0x81, 0x80, /* Flags: qr rd ra */
240         0x00, 0x01, /* Questions: 1 */
241         0x00, 0x01, /* Answer RRs: 1 */
242         0x00, 0x00, /* Authority RRs: 0 */
243         0x00, 0x00, /* Additional RRs: 0 */
244         /* Queries */
245         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
246         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
247         0x00, 0x01,             /* Type: A */
248         0x00, 0x01,             /* Class: IN */
249         /* Answers */
250         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
251         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
252         0x00, 0x01,             /* Type: A */
253         0x00, 0x01,             /* Class: IN */
254         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
255         0x00, 0x04,             /* Data length: 4 */
256         0x01, 0x02, 0x03, 0x04  /* Address: 1.2.3.4 */
257 };
258 
259 const std::vector<uint8_t> kHelloExampleComResponsesV4 = {
260         // scapy.DNS(
261         //   id=0,
262         //   qr=1,
263         //   ra=1,
264         //   qd=scapy.DNSQR(qname="hello.example.com",qtype="A"),
265         //   an=scapy.DNSRR(rrname="hello.example.com",type="A",ttl=0,rdata='1.2.3.4') /
266         //      scapy.DNSRR(rrname="hello.example.com",type="A",ttl=0,rdata='8.8.8.8') /
267         //      scapy.DNSRR(rrname="hello.example.com",type="A",ttl=0,rdata='81.117.21.202'))
268         /* Header */
269         0x00, 0x00, /* Transaction ID: 0x0000 */
270         0x81, 0x80, /* Flags: qr rd ra */
271         0x00, 0x01, /* Questions: 1 */
272         0x00, 0x03, /* Answer RRs: 3 */
273         0x00, 0x00, /* Authority RRs: 0 */
274         0x00, 0x00, /* Additional RRs: 0 */
275         /* Queries */
276         0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x03,
277         0x63, 0x6F, 0x6D, 0x00, /* Name: hello.example.com */
278         0x00, 0x01,             /* Type: A */
279         0x00, 0x01,             /* Class: IN */
280         /* Answers */
281         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
282         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
283         0x00, 0x01,             /* Type: A */
284         0x00, 0x01,             /* Class: IN */
285         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
286         0x00, 0x04,             /* Data length: 4 */
287         0x01, 0x02, 0x03, 0x04, /* Address: 1.2.3.4 */
288         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
289         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
290         0x00, 0x01,             /* Type: A */
291         0x00, 0x01,             /* Class: IN */
292         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
293         0x00, 0x04,             /* Data length: 4 */
294         0x08, 0x08, 0x08, 0x08, /* Address: 8.8.8.8 */
295         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
296         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
297         0x00, 0x01,             /* Type: A */
298         0x00, 0x01,             /* Class: IN */
299         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
300         0x00, 0x04,             /* Data length: 4 */
301         0x51, 0x75, 0x15, 0xca  /* Address: 81.117.21.202 */
302 };
303 
304 static const std::vector<uint8_t> kHelloExampleComQueryV6 = {
305         /* Header */
306         0x00, 0x00, /* Transaction ID: 0x0000 */
307         0x01, 0x00, /* Flags: rd */
308         0x00, 0x01, /* Questions: 1 */
309         0x00, 0x00, /* Answer RRs: 0 */
310         0x00, 0x00, /* Authority RRs: 0 */
311         0x00, 0x00, /* Additional RRs: 0 */
312         /* Queries */
313         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
314         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
315         0x00, 0x1c,             /* Type: AAAA */
316         0x00, 0x01              /* Class: IN */
317 };
318 
319 const std::vector<uint8_t> kHelloExampleComResponsesV6 = {
320         // The addresses are IPv4-compatible address, teredo tunneling address and global unicast
321         // address.
322         //
323         // scapy.DNS(
324         // id=0,
325         // qr=1,
326         // ra=1,
327         // qd=scapy.DNSQR(qname="hello.example.com",qtype="AAAA"),
328         // an=scapy.DNSRR(rrname="hello.example.com",type="AAAA",rdata='::1.2.3.4') /
329         //    scapy.DNSRR(rrname="hello.example.com",type="AAAA",rdata='2001::47c1') /
330         //    scapy.DNSRR(rrname="hello.example.com",type="AAAA",rdata='2404:6800::5175:15ca'))
331         /* Header */
332         0x00, 0x00, /* Transaction ID: 0x0000 */
333         0x81, 0x80, /* Flags: qr rd ra */
334         0x00, 0x01, /* Questions: 1 */
335         0x00, 0x03, /* Answer RRs: 3 */
336         0x00, 0x00, /* Authority RRs: 0 */
337         0x00, 0x00, /* Additional RRs: 0 */
338         /* Queries */
339         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
340         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
341         0x00, 0x1c,             /* Type: AAAA */
342         0x00, 0x01,             /* Class: IN */
343         /* Answers */
344         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
345         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
346         0x00, 0x1c,             /* Type: AAAA */
347         0x00, 0x01,             /* Class: IN */
348         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
349         0x00, 0x10,             /* Data length: 4 */
350         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
351         0x04, /* Address: ::1.2.3.4 */
352         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
353         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
354         0x00, 0x1c,             /* Type: AAAA */
355         0x00, 0x01,             /* Class: IN */
356         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
357         0x00, 0x10,             /* Data length: 4 */
358         0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
359         0xc1, /* Address: 2001::47c1 */
360         0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
361         0x63, 0x6f, 0x6d, 0x00, /* Name: hello.example.com */
362         0x00, 0x1c,             /* Type: AAAA */
363         0x00, 0x01,             /* Class: IN */
364         0x00, 0x00, 0x00, 0x00, /* Time to live: 0 */
365         0x00, 0x10,             /* Data length: 4 */
366         0x24, 0x04, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x75, 0x15,
367         0xCA /* Address: 2404:6800::5175:15ca */
368 };
369 
370 // Illegal hostnames
371 static constexpr char kBadCharAfterPeriodHost[] = "hello.example.^com.";
372 static constexpr char kBadCharBeforePeriodHost[] = "hello.example^.com.";
373 static constexpr char kBadCharAtTheEndHost[] = "hello.example.com^.";
374 static constexpr char kBadCharInTheMiddleOfLabelHost[] = "hello.ex^ample.com.";
375 
376 static const test::DNSHeader kDefaultDnsHeader = {
377         // Don't need to initialize the flag "id" and "rd" because DNS responder assigns them from
378         // query to response. See RFC 1035 section 4.1.1.
379         .id = 0,                // unused. should be assigned from query to response
380         .ra = false,            // recursive query support is not available
381         .rcode = ns_r_noerror,  // no error
382         .qr = true,             // message is a response
383         .opcode = QUERY,        // a standard query
384         .aa = false,            // answer/authority portion was not authenticated by the server
385         .tr = false,            // message is not truncated
386         .rd = false,            // unused. should be assigned from query to response
387         .ad = false,            // non-authenticated data is unacceptable
388 };
389 
390 // The CNAME chain records for building a response message which exceeds 512 bytes.
391 //
392 // Ignoring the other fields of the message, the response message has 8 CNAMEs in 5 answer RRs
393 // and each CNAME has 77 bytes as the follows. The response message at least has 616 bytes in
394 // answer section and has already exceeded 512 bytes totally.
395 //
396 // The CNAME is presented as:
397 //   0   1            64  65                          72  73          76  77
398 //   +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+
399 //   | 63| {x, .., x} | 7 | e | x | a | m | p | l | e | 3 | c | o | m | 0 |
400 //   +---+--........--+---+---+---+---+---+---+---+---+---+---+---+---+---+
401 //          ^-- x = {a, b, c, d}
402 //
403 const std::string kCnameA = std::string(kMaxmiumLabelSize, 'a') + kExampleComDomain + ".";
404 const std::string kCnameB = std::string(kMaxmiumLabelSize, 'b') + kExampleComDomain + ".";
405 const std::string kCnameC = std::string(kMaxmiumLabelSize, 'c') + kExampleComDomain + ".";
406 const std::string kCnameD = std::string(kMaxmiumLabelSize, 'd') + kExampleComDomain + ".";
407 const std::vector<DnsRecord> kLargeCnameChainRecords = {
408         {kHelloExampleCom, ns_type::ns_t_cname, kCnameA},
409         {kCnameA, ns_type::ns_t_cname, kCnameB},
410         {kCnameB, ns_type::ns_t_cname, kCnameC},
411         {kCnameC, ns_type::ns_t_cname, kCnameD},
412         {kCnameD, ns_type::ns_t_a, kHelloExampleComAddrV4},
413 };
414 
415 // TODO: Integrate GetNumQueries relevent functions
416 size_t GetNumQueries(const test::DNSResponder& dns, const char* name);
417 size_t GetNumQueriesForProtocol(const test::DNSResponder& dns, const int protocol,
418                                 const char* name);
419 size_t GetNumQueriesForType(const test::DNSResponder& dns, ns_type type, const char* name);
420 std::string ToString(const hostent* he);
421 std::string ToString(const addrinfo* ai);
422 std::string ToString(const android::netdutils::ScopedAddrinfo& ai);
423 std::string ToString(const sockaddr_storage* addr);
424 std::vector<std::string> ToStrings(const hostent* he);
425 std::vector<std::string> ToStrings(const addrinfo* ai);
426 std::vector<std::string> ToStrings(const android::netdutils::ScopedAddrinfo& ai);
427 
428 // Wait for |condition| to be met until |timeout|.
429 bool PollForCondition(const std::function<bool()>& condition,
430                       std::chrono::milliseconds timeout = std::chrono::milliseconds(1000));
431 
432 android::netdutils::ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service,
433                                                     const struct addrinfo* hints);
434 
435 void SetMdnsRoute();
436 void RemoveMdnsRoute();
437 void AllowNetworkInBackground(int uid, bool allow);
438 
439 // Local definition to avoid including resolv_cache.h.
440 int resolv_set_nameservers(const aidl::android::net::ResolverParamsParcel& params);
441 
442 // For testing only. Production code passes the parcel down directly.
443 inline int resolv_set_nameservers(
444         unsigned netid, const std::vector<std::string>& servers,
445         const std::vector<std::string>& domains, const res_params& res_params,
446         std::optional<aidl::android::net::ResolverOptionsParcel> resolverOptions,
447         const std::vector<int32_t>& transportTypes = {}, bool metered = false) {
448     aidl::android::net::ResolverParamsParcel params;
449     params.netId = netid;
450     params.servers = servers;
451     params.domains = domains;
452     params.resolverOptions = resolverOptions;
453     params.transportTypes = transportTypes;
454     params.meteredNetwork = metered;
455 
456     params.sampleValiditySeconds = res_params.sample_validity;
457     params.successThreshold = res_params.success_threshold;
458     params.minSamples = res_params.min_samples;
459     params.maxSamples = res_params.max_samples;
460     params.baseTimeoutMsec = res_params.base_timeout_msec;
461     params.retryCount = res_params.retry_count;
462     // This is currently not configurable. Tests relying on DnsResponderClient, are currently
463     // creating a network with no interfaces. They then end up relying on local communication to
464     // receive and send DNS queries. Adding "lo" as an interface for |TEST_NETID| makes that
465     // dependency explicit, allowing mDNS multicast queries to be sent via
466     // IP_MULTICAST_IF/IPV6_MULTICAST_IF.
467     params.interfaceNames = {"lo"};
468 
469     return resolv_set_nameservers(params);
470 }
471 
472 #define SKIP_IF_BEFORE_T                                                         \
473     do {                                                                         \
474         if (!isAtLeastT()) {                                                     \
475             GTEST_SKIP() << "Skipping test because SDK version is less than T."; \
476         }                                                                        \
477     } while (0)
478 
479 bool is64bitAbi();
480 
481 static const std::string DNS_HELPER =
482         is64bitAbi() ? "/apex/com.android.tethering/lib64/libcom.android.tethering.dns_helper.so"
483                      : "/apex/com.android.tethering/lib/libcom.android.tethering.dns_helper.so";
484 
485 #define SKIP_IF_DEPENDENT_LIB_DOES_NOT_EXIST(libPath)                  \
486     do {                                                               \
487         if (!std::filesystem::exists(libPath))                         \
488             GTEST_SKIP() << "Required " << (libPath) << " not found."; \
489     } while (0)
490