Add two Netd binder calls to set/get resolver config.
setResolverConfiguration() sets the name servers, search domains,
and resolver parameters.
getResolverInfo() returns the configured information and also the
statistics for each server.
Also includes tests for the new functionality.
BUG: 25731675
Change-Id: Idde486f36bb731f9edd240d62dc1795f8e621fe6
diff --git a/server/ResolverStats.h b/server/ResolverStats.h
new file mode 100644
index 0000000..be63d88
--- /dev/null
+++ b/server/ResolverStats.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _RESOLVER_STATS_H_
+#define _RESOLVER_STATS_H_
+
+#include <time.h>
+
+namespace android {
+namespace net {
+
+struct ResolverStats {
+ // Offsets into the per-server resolver stats as encoded in vector<int32_t> stats of
+ // getResolverInfo() of Netd's binder interface. The stats are based on data reported by
+ // android_net_res_stats_get_info_for_net(), the usability is calculated by applying
+ // android_net_res_stats_get_usable_servers() to this data.
+ enum ResolverStatsOffsets {
+ STATS_SUCCESSES = 0, // # successes counted for this server
+ STATS_ERRORS, // # errors
+ STATS_TIMEOUTS, // # timeouts
+ STATS_INTERNAL_ERRORS, // # internal errors
+ STATS_RTT_AVG, // average round-trip-time
+ STATS_LAST_SAMPLE_TIME, // time in s when the last sample was recorded
+ STATS_USABLE, // whether the server is considered usable
+ STATS_COUNT // total count of integers in the per-server data
+ };
+
+ int successes {-1};
+ int errors {-1};
+ int timeouts {-1};
+ int internal_errors {-1};
+ int rtt_avg {-1};
+ time_t last_sample_time {0};
+ bool usable {false};
+
+ // Serialize the resolver stats to the end of |out|.
+ void encode(std::vector<int32_t>* out) const;
+
+ // Read the serialized resolverstats starting at |in[ofs]|.
+ ssize_t decode(const std::vector<int32_t>& in, ssize_t ofs);
+
+ // Serialize the contents of |stats| and append them to the end of |out|. Multiple arrays
+ // can be written to the same output vector in sequence, however, the corresponding call
+ // to decodeAll() will return the combined contents in one vector.
+ static void encodeAll(const std::vector<ResolverStats>& stats, std::vector<int32_t>* out);
+
+ // Decodes the serialized ResolverStats from |in| and appends them to stats.
+ static bool decodeAll(const std::vector<int32_t>& in, std::vector<ResolverStats>* stats);
+};
+
+
+inline void ResolverStats::encode(std::vector<int32_t>* out) const {
+ size_t ofs = out->size();
+ out->resize(ofs + STATS_COUNT);
+ int32_t* cur = &(*out)[ofs];
+ cur[STATS_SUCCESSES] = successes;
+ cur[STATS_ERRORS] = errors;
+ cur[STATS_TIMEOUTS] = timeouts;
+ cur[STATS_INTERNAL_ERRORS] = internal_errors;
+ cur[STATS_RTT_AVG] = rtt_avg;
+ cur[STATS_LAST_SAMPLE_TIME] = last_sample_time;
+ cur[STATS_USABLE] = usable;
+}
+
+ // Read the serialized resolverstats starting at |in[ofs]|.
+inline ssize_t ResolverStats::decode(const std::vector<int32_t>& in, ssize_t ofs) {
+ if (ofs < 0 || static_cast<size_t>(ofs) + STATS_COUNT > in.size()) {
+ return -1;
+ }
+ const int32_t* cur = &in[ofs];
+ successes = cur[STATS_SUCCESSES];
+ errors = cur[STATS_ERRORS];
+ timeouts = cur[STATS_TIMEOUTS];
+ internal_errors = cur[STATS_INTERNAL_ERRORS];
+ rtt_avg = cur[STATS_RTT_AVG];
+ last_sample_time = cur[STATS_LAST_SAMPLE_TIME];
+ usable = cur[STATS_USABLE];
+ return ofs + STATS_COUNT;
+}
+
+inline void ResolverStats::encodeAll(const std::vector<ResolverStats>& stats,
+ std::vector<int32_t>* out) {
+ for (const auto& s : stats) {
+ s.encode(out);
+ }
+}
+
+// TODO: Replace with a better representation, e.g. a Parcelable.
+inline bool ResolverStats::decodeAll(const std::vector<int32_t>& in,
+ std::vector<ResolverStats>* stats) {
+ ssize_t size = in.size();
+ if (size % STATS_COUNT) {
+ return false;
+ }
+ stats->resize(size / STATS_COUNT);
+ ssize_t ofs = 0;
+ for (auto& s : *stats) {
+ ofs = s.decode(in, ofs);
+ if (ofs < 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace net
+} // namespace android
+
+#endif /* _RESOLVER_STATS_H_ */