Extending DNS event reporting
This adds hostname, array of addresses, total count of IP addresses
and uid to the existing pipeline.
Currently ignores the new data it receives, further work will be
done in the subsequent CLs.
Test: for now just the benchmarking, in the future CTS
Bug: 29748723
Change-Id: I3f76746b4afe3287803ace6b6657240ab2e1c02e
diff --git a/server/DnsProxyListener.cpp b/server/DnsProxyListener.cpp
index 0e4058f..dc31b1a 100644
--- a/server/DnsProxyListener.cpp
+++ b/server/DnsProxyListener.cpp
@@ -34,8 +34,10 @@
#define VDBG 0
#include <chrono>
+#include <vector>
#include <cutils/log.h>
+#include <utils/String16.h>
#include <sysutils/SocketClient.h>
#include "Fwmark.h"
@@ -46,6 +48,7 @@
#include "Stopwatch.h"
#include "android/net/metrics/INetdEventListener.h"
+using android::String16;
using android::net::metrics::INetdEventListener;
DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl, EventReporter* eventReporter) :
@@ -192,7 +195,19 @@
ALOGW("Error writing DNS result to client");
}
}
+ std::vector<String16> ip_addrs;
+ int total_ip_addr_count = 0;
if (result) {
+ if (mNetdEventListener != nullptr
+ && mReportingLevel == INetdEventListener::REPORTING_LEVEL_FULL) {
+ for (addrinfo* ai = result; ai; ai = ai->ai_next) {
+ sockaddr* ai_addr = ai->ai_addr;
+ if (ai_addr) {
+ addIpAddrWithinLimit(ip_addrs, ai_addr, ai->ai_addrlen);
+ total_ip_addr_count++;
+ }
+ }
+ }
freeaddrinfo(result);
}
mClient->decRef();
@@ -202,13 +217,17 @@
// Skip reporting.
break;
case INetdEventListener::REPORTING_LEVEL_METRICS:
- // Reporting is on. Send metrics.
+ // Metrics reporting is on. Send metrics.
mNetdEventListener->onDnsEvent(mNetContext.dns_netid,
- INetdEventListener::EVENT_GETADDRINFO, (int32_t) rv,
- latencyMs);
+ INetdEventListener::EVENT_GETADDRINFO, (int32_t) rv,
+ latencyMs, String16(""), {}, -1, -1);
break;
case INetdEventListener::REPORTING_LEVEL_FULL:
- // TODO add full info reporting
+ // Full event info reporting is on. Send full info.
+ mNetdEventListener->onDnsEvent(mNetContext.dns_netid,
+ INetdEventListener::EVENT_GETADDRINFO, (int32_t) rv,
+ latencyMs, String16(mHost), ip_addrs,
+ total_ip_addr_count, mNetContext.uid);
break;
}
} else {
@@ -216,6 +235,19 @@
}
}
+void DnsProxyListener::addIpAddrWithinLimit(std::vector<android::String16>& ip_addrs,
+ const sockaddr* addr, socklen_t addrlen) {
+ // ipAddresses array is limited to first INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT
+ // addresses for A and AAAA. Total count of addresses is provided, to be able to tell whether
+ // some addresses didn't get logged.
+ if (ip_addrs.size() < INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT) {
+ char ip_addr[INET6_ADDRSTRLEN];
+ if (getnameinfo(addr, addrlen, ip_addr, sizeof(ip_addr), nullptr, 0, NI_NUMERICHOST) == 0) {
+ ip_addrs.push_back(String16(ip_addr));
+ }
+ }
+}
+
DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd(DnsProxyListener* dnsProxyListener) :
NetdCommand("getaddrinfo"),
mDnsProxyListener(dnsProxyListener) {
@@ -399,17 +431,39 @@
mClient->decRef();
if (mNetdEventListener != nullptr) {
+ std::vector<String16> ip_addrs;
+ int total_ip_addr_count = 0;
+ if (mReportingLevel == INetdEventListener::REPORTING_LEVEL_FULL) {
+ if (hp->h_addrtype == AF_INET) {
+ in_addr** list = (in_addr**) hp->h_addr_list;
+ for (int i = 0; list[i] != NULL; i++) {
+ sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = *list[i] };
+ addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin, sizeof(sin));
+ total_ip_addr_count++;
+ }
+ } else if (hp->h_addrtype == AF_INET6) {
+ in6_addr** list = (in6_addr**) hp->h_addr_list;
+ for (int i = 0; list[i] != NULL; i++) {
+ sockaddr_in6 sin6 = { .sin6_family = AF_INET6, .sin6_addr = *list[i] };
+ addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin6, sizeof(sin6));
+ total_ip_addr_count++;
+ }
+ }
+ }
switch (mReportingLevel) {
case INetdEventListener::REPORTING_LEVEL_NONE:
// Reporting is off.
break;
case INetdEventListener::REPORTING_LEVEL_METRICS:
- // Reporting is on. Send metrics.
+ // Metrics reporting is on. Send metrics.
mNetdEventListener->onDnsEvent(mNetId, INetdEventListener::EVENT_GETHOSTBYNAME,
- h_errno, latencyMs);
+ h_errno, latencyMs, String16(""), {}, -1, -1);
break;
case INetdEventListener::REPORTING_LEVEL_FULL:
- // TODO add full info reporting
+ // Full event info reporting is on. Send full info.
+ mNetdEventListener->onDnsEvent(mNetId, INetdEventListener::EVENT_GETHOSTBYNAME,
+ h_errno, latencyMs, String16(mName), ip_addrs,
+ total_ip_addr_count, mClient->getUid());
break;
}
}
diff --git a/server/DnsProxyListener.h b/server/DnsProxyListener.h
index 3b51f52..8807488 100644
--- a/server/DnsProxyListener.h
+++ b/server/DnsProxyListener.h
@@ -35,6 +35,8 @@
private:
const NetworkController *mNetCtrl;
EventReporter *mEventReporter;
+ static void addIpAddrWithinLimit(std::vector<android::String16>& ip_addrs, const sockaddr* addr,
+ socklen_t addrlen);
class GetAddrInfoCmd : public NetdCommand {
public:
diff --git a/server/EventReporter.h b/server/EventReporter.h
index 1152812..cc0e912 100644
--- a/server/EventReporter.h
+++ b/server/EventReporter.h
@@ -39,7 +39,7 @@
private:
std::atomic_int mReportingLevel{
- android::net::metrics::INetdEventListener::REPORTING_LEVEL_METRICS};
+ android::net::metrics::INetdEventListener::REPORTING_LEVEL_FULL};
android::sp<android::net::metrics::INetdEventListener> mNetdEventListener;
};
diff --git a/server/binder/android/net/metrics/INetdEventListener.aidl b/server/binder/android/net/metrics/INetdEventListener.aidl
index c3ca317..3d3774b 100644
--- a/server/binder/android/net/metrics/INetdEventListener.aidl
+++ b/server/binder/android/net/metrics/INetdEventListener.aidl
@@ -29,6 +29,23 @@
const int REPORTING_LEVEL_METRICS = 4;
const int REPORTING_LEVEL_FULL = 5;
- // Logs a single DNS lookup.
- void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs);
+ // Maximum number of IP addresses logged for DNS lookups before we truncate the full list.
+ const int DNS_REPORTED_IP_ADDRESSES_LIMIT = 10;
+
+ /**
+ * Logs a DNS lookup function call (getaddrinfo and gethostbyname).
+ *
+ * @param netId the ID of the network the lookup was performed on.
+ * @param eventType one of the EVENT_* constants in this interface.
+ * @param returnCode the return value of the function call.
+ * @param latencyMs the latency of the function call.
+ * @param hostname the name that was looked up.
+ * @param ipAddresses (possibly a subset of) the IP addresses returned.
+ * At most {@link #DNS_REPORTED_IP_ADDRESSES_LIMIT} addresses are logged.
+ * @param ipAddressesCount the number of IP addresses returned. May be different from the length
+ * of ipAddresses if there were too many addresses to log.
+ * @param uid the UID of the application that performed the query.
+ */
+ void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs, String hostname,
+ in String[] ipAddresses, int ipAddressesCount, int uid);
}