#define VDBG 0
#include <chrono>
+#include <vector>
#include <cutils/log.h>
+#include <utils/String16.h>
#include <sysutils/SocketClient.h>
#include "Fwmark.h"
#include "Stopwatch.h"
#include "android/net/metrics/INetdEventListener.h"
+using android::String16;
using android::net::metrics::INetdEventListener;
DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl, EventReporter* eventReporter) :
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();
// 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 {
}
}
+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) {
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;
}
}
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);
}