1 /*
2  * Copyright (C) 2011 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 "ResolverController"
18 #define DBG 0
19 
20 #include <algorithm>
21 #include <cstdlib>
22 #include <string>
23 #include <vector>
24 #include <cutils/log.h>
25 #include <net/if.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
28 
29 // NOTE: <resolv_netid.h> is a private C library header that provides
30 //       declarations for _resolv_set_nameservers_for_net and
31 //       _resolv_flush_cache_for_net
32 #include <resolv_netid.h>
33 #include <resolv_params.h>
34 #include <resolv_stats.h>
35 
36 #include <android-base/strings.h>
37 #include <android/net/INetd.h>
38 
39 #include "DumpWriter.h"
40 #include "ResolverController.h"
41 #include "ResolverStats.h"
42 
43 namespace android {
44 namespace net {
45 
setDnsServers(unsigned netId,const char * searchDomains,const char ** servers,int numservers,const __res_params * params)46 int ResolverController::setDnsServers(unsigned netId, const char* searchDomains,
47         const char** servers, int numservers, const __res_params* params) {
48     if (DBG) {
49         ALOGD("setDnsServers netId = %u\n", netId);
50     }
51     return -_resolv_set_nameservers_for_net(netId, servers, numservers, searchDomains, params);
52 }
53 
clearDnsServers(unsigned netId)54 int ResolverController::clearDnsServers(unsigned netId) {
55     _resolv_set_nameservers_for_net(netId, NULL, 0, "", NULL);
56     if (DBG) {
57         ALOGD("clearDnsServers netId = %u\n", netId);
58     }
59     return 0;
60 }
61 
flushDnsCache(unsigned netId)62 int ResolverController::flushDnsCache(unsigned netId) {
63     if (DBG) {
64         ALOGD("flushDnsCache netId = %u\n", netId);
65     }
66 
67     _resolv_flush_cache_for_net(netId);
68 
69     return 0;
70 }
71 
getDnsInfo(unsigned netId,std::vector<std::string> * servers,std::vector<std::string> * domains,__res_params * params,std::vector<android::net::ResolverStats> * stats)72 int ResolverController::getDnsInfo(unsigned netId, std::vector<std::string>* servers,
73         std::vector<std::string>* domains, __res_params* params,
74         std::vector<android::net::ResolverStats>* stats) {
75     using android::net::ResolverStats;
76     using android::net::INetd;
77     static_assert(ResolverStats::STATS_SUCCESSES == INetd::RESOLVER_STATS_SUCCESSES &&
78             ResolverStats::STATS_ERRORS == INetd::RESOLVER_STATS_ERRORS &&
79             ResolverStats::STATS_TIMEOUTS == INetd::RESOLVER_STATS_TIMEOUTS &&
80             ResolverStats::STATS_INTERNAL_ERRORS == INetd::RESOLVER_STATS_INTERNAL_ERRORS &&
81             ResolverStats::STATS_RTT_AVG == INetd::RESOLVER_STATS_RTT_AVG &&
82             ResolverStats::STATS_LAST_SAMPLE_TIME == INetd::RESOLVER_STATS_LAST_SAMPLE_TIME &&
83             ResolverStats::STATS_USABLE == INetd::RESOLVER_STATS_USABLE &&
84             ResolverStats::STATS_COUNT == INetd::RESOLVER_STATS_COUNT,
85             "AIDL and ResolverStats.h out of sync");
86     int nscount = -1;
87     sockaddr_storage res_servers[MAXNS];
88     int dcount = -1;
89     char res_domains[MAXDNSRCH][MAXDNSRCHPATH];
90     __res_stats res_stats[MAXNS];
91     servers->clear();
92     domains->clear();
93     *params = __res_params{};
94     stats->clear();
95     int revision_id = android_net_res_stats_get_info_for_net(netId, &nscount, res_servers, &dcount,
96             res_domains, params, res_stats);
97 
98     // If the netId is unknown (which can happen for valid net IDs for which no DNS servers have
99     // yet been configured), there is no revision ID. In this case there is no data to return.
100     if (revision_id < 0) {
101         return 0;
102     }
103 
104     // Verify that the returned data is sane.
105     if (nscount < 0 || nscount > MAXNS || dcount < 0 || dcount > MAXDNSRCH) {
106         ALOGE("%s: nscount=%d, dcount=%d", __FUNCTION__, nscount, dcount);
107         return -ENOTRECOVERABLE;
108     }
109 
110     // Determine which servers are considered usable by the resolver.
111     bool valid_servers[MAXNS];
112     std::fill_n(valid_servers, MAXNS, false);
113     android_net_res_stats_get_usable_servers(params, res_stats, nscount, valid_servers);
114 
115     // Convert the server sockaddr structures to std::string.
116     stats->resize(nscount);
117     for (int i = 0 ; i < nscount ; ++i) {
118         char hbuf[NI_MAXHOST];
119         int rv = getnameinfo(reinterpret_cast<const sockaddr*>(&res_servers[i]),
120                 sizeof(res_servers[i]), hbuf, sizeof(hbuf), nullptr, 0, NI_NUMERICHOST);
121         std::string server_str;
122         if (rv == 0) {
123             server_str.assign(hbuf);
124         } else {
125             ALOGE("getnameinfo() failed for server #%d: %s", i, gai_strerror(rv));
126             server_str.assign("<invalid>");
127         }
128         servers->push_back(std::move(server_str));
129         android::net::ResolverStats& cur_stats = (*stats)[i];
130         android_net_res_stats_aggregate(&res_stats[i], &cur_stats.successes, &cur_stats.errors,
131                 &cur_stats.timeouts, &cur_stats.internal_errors, &cur_stats.rtt_avg,
132                 &cur_stats.last_sample_time);
133         cur_stats.usable = valid_servers[i];
134     }
135 
136     // Convert the stack-allocated search domain strings to std::string.
137     for (int i = 0 ; i < dcount ; ++i) {
138         domains->push_back(res_domains[i]);
139     }
140     return 0;
141 }
142 
setResolverConfiguration(int32_t netId,const std::vector<std::string> & servers,const std::vector<std::string> & domains,const std::vector<int32_t> & params)143 int ResolverController::setResolverConfiguration(int32_t netId,
144         const std::vector<std::string>& servers, const std::vector<std::string>& domains,
145         const std::vector<int32_t>& params) {
146     using android::net::INetd;
147     if (params.size() != INetd::RESOLVER_PARAMS_COUNT) {
148         ALOGE("%s: params.size()=%zu", __FUNCTION__, params.size());
149         return -EINVAL;
150     }
151 
152     auto server_count = std::min<size_t>(MAXNS, servers.size());
153     std::vector<const char*> server_ptrs;
154     for (size_t i = 0 ; i < server_count ; ++i) {
155         server_ptrs.push_back(servers[i].c_str());
156     }
157 
158     std::string domains_str;
159     if (!domains.empty()) {
160         domains_str = domains[0];
161         for (size_t i = 1 ; i < domains.size() ; ++i) {
162             domains_str += " " + domains[i];
163         }
164     }
165 
166     __res_params res_params;
167     res_params.sample_validity = params[INetd::RESOLVER_PARAMS_SAMPLE_VALIDITY];
168     res_params.success_threshold = params[INetd::RESOLVER_PARAMS_SUCCESS_THRESHOLD];
169     res_params.min_samples = params[INetd::RESOLVER_PARAMS_MIN_SAMPLES];
170     res_params.max_samples = params[INetd::RESOLVER_PARAMS_MAX_SAMPLES];
171 
172     return setDnsServers(netId, domains_str.c_str(), server_ptrs.data(), server_ptrs.size(),
173             &res_params);
174 }
175 
getResolverInfo(int32_t netId,std::vector<std::string> * servers,std::vector<std::string> * domains,std::vector<int32_t> * params,std::vector<int32_t> * stats)176 int ResolverController::getResolverInfo(int32_t netId, std::vector<std::string>* servers,
177         std::vector<std::string>* domains, std::vector<int32_t>* params,
178         std::vector<int32_t>* stats) {
179     using android::net::ResolverStats;
180     using android::net::INetd;
181     __res_params res_params;
182     std::vector<ResolverStats> res_stats;
183     int ret = getDnsInfo(netId, servers, domains, &res_params, &res_stats);
184     if (ret != 0) {
185         return ret;
186     }
187 
188     // Serialize the information for binder.
189     ResolverStats::encodeAll(res_stats, stats);
190 
191     params->resize(INetd::RESOLVER_PARAMS_COUNT);
192     (*params)[INetd::RESOLVER_PARAMS_SAMPLE_VALIDITY] = res_params.sample_validity;
193     (*params)[INetd::RESOLVER_PARAMS_SUCCESS_THRESHOLD] = res_params.success_threshold;
194     (*params)[INetd::RESOLVER_PARAMS_MIN_SAMPLES] = res_params.min_samples;
195     (*params)[INetd::RESOLVER_PARAMS_MAX_SAMPLES] = res_params.max_samples;
196     return 0;
197 }
198 
dump(DumpWriter & dw,unsigned netId)199 void ResolverController::dump(DumpWriter& dw, unsigned netId) {
200     // No lock needed since Bionic's resolver locks all accessed data structures internally.
201     using android::net::ResolverStats;
202     std::vector<std::string> servers;
203     std::vector<std::string> domains;
204     __res_params params;
205     std::vector<ResolverStats> stats;
206     time_t now = time(nullptr);
207     int rv = getDnsInfo(netId, &servers, &domains, &params, &stats);
208     dw.incIndent();
209     if (rv != 0) {
210         dw.println("getDnsInfo() failed for netid %u", netId);
211     } else {
212         if (servers.empty()) {
213             dw.println("No DNS servers defined");
214         } else {
215             dw.println("DNS servers: # IP (total, successes, errors, timeouts, internal errors, "
216                     "RTT avg, last sample)");
217             dw.incIndent();
218             for (size_t i = 0 ; i < servers.size() ; ++i) {
219                 if (i < stats.size()) {
220                     const ResolverStats& s = stats[i];
221                     int total = s.successes + s.errors + s.timeouts + s.internal_errors;
222                     if (total > 0) {
223                         int time_delta = (s.last_sample_time > 0) ? now - s.last_sample_time : -1;
224                         dw.println("%s (%d, %d, %d, %d, %d, %dms, %ds)%s", servers[i].c_str(),
225                                 total, s.successes, s.errors, s.timeouts, s.internal_errors,
226                                 s.rtt_avg, time_delta, s.usable ? "" : " BROKEN");
227                     } else {
228                         dw.println("%s <no data>", servers[i].c_str());
229                     }
230                 } else {
231                     dw.println("%s <no stats>", servers[i].c_str());
232                 }
233             }
234             dw.decIndent();
235         }
236         if (domains.empty()) {
237             dw.println("No search domains defined");
238         } else {
239             std::string domains_str = android::base::Join(domains, ", ");
240             dw.println("search domains: %s", domains_str.c_str());
241         }
242         if (params.sample_validity != 0) {
243             dw.println("DNS parameters: sample validity = %us, success threshold = %u%%, "
244                     "samples (min, max) = (%u, %u)", params.sample_validity,
245                     static_cast<unsigned>(params.success_threshold),
246                     static_cast<unsigned>(params.min_samples),
247                     static_cast<unsigned>(params.max_samples));
248         }
249     }
250     dw.decIndent();
251 }
252 
253 }  // namespace net
254 }  // namespace android
255