• 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 #define LOG_TAG "dns_responder_client"
18 
19 #include "dns_responder_client_ndk.h"
20 
21 #include <android/binder_manager.h>
22 #include "NetdClient.h"
23 
24 #define TEST_NETID 30
25 
26 // TODO: move this somewhere shared.
27 static const char* ANDROID_DNS_MODE = "ANDROID_DNS_MODE";
28 
29 using aidl::android::net::IDnsResolver;
30 using aidl::android::net::INetd;
31 using aidl::android::net::ResolverOptionsParcel;
32 using aidl::android::net::ResolverParamsParcel;
33 using android::base::Error;
34 using android::base::Result;
35 using android::net::ResolverStats;
36 
Builder()37 ResolverParams::Builder::Builder() {
38     // Default resolver configuration for opportunistic mode.
39     mParcel.netId = TEST_NETID;
40 
41     // Default Resolver params.
42     mParcel.sampleValiditySeconds = 300;
43     mParcel.successThreshold = 25;
44     mParcel.minSamples = 8;
45     mParcel.maxSamples = 8;
46     mParcel.baseTimeoutMsec = 1000;
47     mParcel.retryCount = 2;
48 
49     mParcel.servers = {kDefaultServer};
50     mParcel.domains = {kDefaultSearchDomain};
51     mParcel.tlsServers = {kDefaultServer};
52     mParcel.caCertificate = kCaCert;
53     mParcel.resolverOptions = ResolverOptionsParcel{};  // optional, must be explicitly set.
54 }
55 
SetupMappings(unsigned numHosts,const std::vector<std::string> & domains,std::vector<Mapping> * mappings)56 void DnsResponderClient::SetupMappings(unsigned numHosts, const std::vector<std::string>& domains,
57                                        std::vector<Mapping>* mappings) {
58     mappings->resize(numHosts * domains.size());
59     auto mappingsIt = mappings->begin();
60     for (unsigned i = 0; i < numHosts; ++i) {
61         for (const auto& domain : domains) {
62             mappingsIt->host = fmt::format("host{}", i);
63             mappingsIt->entry = fmt::format("{}.{}.", mappingsIt->host, domain);
64             mappingsIt->ip4 = fmt::format("192.0.2.{}", i % 253 + 1);
65             mappingsIt->ip6 = fmt::format("2001:db8::{:x}", i % 65534 + 1);
66             ++mappingsIt;
67         }
68     }
69 }
70 
getResolverInfo()71 Result<ResolverInfo> DnsResponderClient::getResolverInfo() {
72     std::vector<std::string> dnsServers;
73     std::vector<std::string> domains;
74     std::vector<std::string> dotServers;
75     std::vector<int32_t> params;
76     std::vector<int32_t> stats;
77     std::vector<int32_t> waitForPendingReqTimeoutCount{0};
78     auto rv = mDnsResolvSrv->getResolverInfo(TEST_NETID, &dnsServers, &domains, &dotServers,
79                                              &params, &stats, &waitForPendingReqTimeoutCount);
80     if (!rv.isOk()) {
81         return Error() << "getResolverInfo failed: " << rv.getMessage();
82     }
83     if (stats.size() % IDnsResolver::RESOLVER_STATS_COUNT != 0) {
84         return Error() << "Unexpected stats size: " << stats.size();
85     }
86     if (params.size() != IDnsResolver::RESOLVER_PARAMS_COUNT) {
87         return Error() << "Unexpected params size: " << params.size();
88     }
89     if (waitForPendingReqTimeoutCount.size() != 1) {
90         return Error() << "Unexpected waitForPendingReqTimeoutCount size: "
91                        << waitForPendingReqTimeoutCount.size();
92     }
93 
94     ResolverInfo out = {
95             .dnsServers = std::move(dnsServers),
96             .domains = std::move(domains),
97             .dotServers = std::move(dotServers),
98             .params{
99                     .sample_validity = static_cast<uint16_t>(
100                             params[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]),
101                     .success_threshold = static_cast<uint8_t>(
102                             params[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]),
103                     .min_samples =
104                             static_cast<uint8_t>(params[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]),
105                     .max_samples =
106                             static_cast<uint8_t>(params[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]),
107                     .base_timeout_msec = params[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC],
108                     .retry_count = params[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT],
109             },
110             .stats = {},
111             .waitForPendingReqTimeoutCount = waitForPendingReqTimeoutCount[0],
112     };
113     ResolverStats::decodeAll(stats, &out.stats);
114 
115     return std::move(out);
116 }
117 
SetResolversForNetwork(const std::vector<std::string> & servers,const std::vector<std::string> & domains,std::vector<int> params)118 bool DnsResponderClient::SetResolversForNetwork(const std::vector<std::string>& servers,
119                                                 const std::vector<std::string>& domains,
120                                                 std::vector<int> params) {
121     params.resize(IDnsResolver::RESOLVER_PARAMS_COUNT);
122     std::array<int, IDnsResolver::RESOLVER_PARAMS_COUNT> arr;
123     std::copy_n(params.begin(), arr.size(), arr.begin());
124     const auto resolverParams = ResolverParams::Builder()
125                                         .setDomains(domains)
126                                         .setDnsServers(servers)
127                                         .setDotServers({})
128                                         .setParams(arr)
129                                         .build();
130     const auto rv = mDnsResolvSrv->setResolverConfiguration(resolverParams);
131     return rv.isOk();
132 }
133 
SetResolversForNetwork(const std::vector<std::string> & servers,const std::vector<std::string> & domains)134 bool DnsResponderClient::SetResolversForNetwork(const std::vector<std::string>& servers,
135                                                 const std::vector<std::string>& domains) {
136     const auto resolverParams = ResolverParams::Builder()
137                                         .setDomains(domains)
138                                         .setDnsServers(servers)
139                                         .setDotServers({})
140                                         .build();
141     const auto rv = mDnsResolvSrv->setResolverConfiguration(resolverParams);
142     return rv.isOk();
143 }
144 
SetResolversFromParcel(const ResolverParamsParcel & resolverParams)145 bool DnsResponderClient::SetResolversFromParcel(const ResolverParamsParcel& resolverParams) {
146     const auto rv = mDnsResolvSrv->setResolverConfiguration(resolverParams);
147     if (!rv.isOk()) LOG(ERROR) << "SetResolversFromParcel() -> " << rv.getMessage();
148     return rv.isOk();
149 }
150 
GetDefaultResolverParamsParcel()151 ResolverParamsParcel DnsResponderClient::GetDefaultResolverParamsParcel() {
152     return ResolverParams::Builder().build();
153 }
154 
SetupDNSServers(unsigned numServers,const std::vector<Mapping> & mappings,std::vector<std::unique_ptr<test::DNSResponder>> * dns,std::vector<std::string> * servers)155 void DnsResponderClient::SetupDNSServers(unsigned numServers, const std::vector<Mapping>& mappings,
156                                          std::vector<std::unique_ptr<test::DNSResponder>>* dns,
157                                          std::vector<std::string>* servers) {
158     const char* listenSrv = "53";
159     dns->resize(numServers);
160     servers->resize(numServers);
161     for (unsigned i = 0; i < numServers; ++i) {
162         auto& server = (*servers)[i];
163         auto& d = (*dns)[i];
164         server = fmt::format("127.0.0.{}", i + 100);
165         d = std::make_unique<test::DNSResponder>(server, listenSrv, ns_rcode::ns_r_servfail);
166         for (const auto& mapping : mappings) {
167             d->addMapping(mapping.entry.c_str(), ns_type::ns_t_a, mapping.ip4.c_str());
168             d->addMapping(mapping.entry.c_str(), ns_type::ns_t_aaaa, mapping.ip6.c_str());
169         }
170         d->startServer();
171     }
172 }
173 
SetupOemNetwork(int oemNetId)174 int DnsResponderClient::SetupOemNetwork(int oemNetId) {
175     mNetdSrv->networkDestroy(oemNetId);
176     mDnsResolvSrv->destroyNetworkCache(oemNetId);
177 
178     ::ndk::ScopedAStatus ret;
179     if (DnsResponderClient::isRemoteVersionSupported(mNetdSrv, 6)) {
180         const auto& config = DnsResponderClient::makeNativeNetworkConfig(
181                 oemNetId, NativeNetworkType::PHYSICAL, INetd::PERMISSION_NONE, /*secure=*/false);
182         ret = mNetdSrv->networkCreate(config);
183     } else {
184         // Only for presubmit tests that run mainline module (and its tests) on R or earlier images.
185 #pragma clang diagnostic push
186 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
187         ret = mNetdSrv->networkCreatePhysical(oemNetId, INetd::PERMISSION_NONE);
188 #pragma clang diagnostic pop
189     }
190     if (!ret.isOk()) {
191         fprintf(stderr, "Creating physical network %d failed, %s\n", oemNetId, ret.getMessage());
192         return -1;
193     }
194     ret = mDnsResolvSrv->createNetworkCache(oemNetId);
195     if (!ret.isOk()) {
196         fprintf(stderr, "Creating network cache %d failed, %s\n", oemNetId, ret.getMessage());
197         return -1;
198     }
199     setNetworkForProcess(oemNetId);
200     if ((unsigned)oemNetId != getNetworkForProcess()) {
201         return -1;
202     }
203     return 0;
204 }
205 
TearDownOemNetwork(int oemNetId)206 int DnsResponderClient::TearDownOemNetwork(int oemNetId) {
207     if (auto status = mNetdSrv->networkDestroy(oemNetId); !status.isOk()) {
208         fprintf(stderr, "Removing network %d failed, %s\n", oemNetId, status.getMessage());
209         return -1;
210     }
211     if (auto status = mDnsResolvSrv->destroyNetworkCache(oemNetId); !status.isOk()) {
212         fprintf(stderr, "Removing network cache %d failed, %s\n", oemNetId, status.getMessage());
213         return -1;
214     }
215     return 0;
216 }
217 
SetUp()218 void DnsResponderClient::SetUp() {
219     // binder setup
220     ndk::SpAIBinder netdBinder = ndk::SpAIBinder(AServiceManager_getService("netd"));
221     mNetdSrv = INetd::fromBinder(netdBinder);
222     if (mNetdSrv.get() == nullptr) {
223         LOG(FATAL) << "Can't connect to service 'netd'. Missing root privileges? uid=" << getuid();
224     }
225 
226     ndk::SpAIBinder resolvBinder = ndk::SpAIBinder(AServiceManager_getService("dnsresolver"));
227     mDnsResolvSrv = IDnsResolver::fromBinder(resolvBinder);
228     if (mDnsResolvSrv.get() == nullptr) {
229         LOG(FATAL) << "Can't connect to service 'dnsresolver'. Missing root privileges? uid="
230                    << getuid();
231     }
232 
233     // Ensure resolutions go via proxy.
234     setenv(ANDROID_DNS_MODE, "", 1);
235     SetupOemNetwork(TEST_NETID);
236 }
237 
TearDown()238 void DnsResponderClient::TearDown() {
239     TearDownOemNetwork(TEST_NETID);
240 }
241 
makeNativeNetworkConfig(int netId,NativeNetworkType networkType,int permission,bool secure)242 NativeNetworkConfig DnsResponderClient::makeNativeNetworkConfig(int netId,
243                                                                 NativeNetworkType networkType,
244                                                                 int permission, bool secure) {
245     NativeNetworkConfig config = {};
246     config.netId = netId;
247     config.networkType = networkType;
248     config.permission = permission;
249     config.secure = secure;
250     // The vpnType doesn't matter in AOSP. Just pick a well defined one from INetd.
251     config.vpnType = NativeVpnType::PLATFORM;
252     return config;
253 }
254