Merge "Fix typo in a few license files."
diff --git a/Android.bp b/Android.bp
index 908c389..1f634f2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -199,6 +199,8 @@
"libnetd_resolv",
"libnetd_test_dnsresponder",
"libnetdutils",
+ "libprotobuf-cpp-lite",
"server_configurable_flags",
+ "stats_proto",
],
}
diff --git a/Dns64Configuration.cpp b/Dns64Configuration.cpp
index 12fb61f..7f43d34 100644
--- a/Dns64Configuration.cpp
+++ b/Dns64Configuration.cpp
@@ -33,9 +33,11 @@
#include "DnsResolver.h"
#include "getaddrinfo.h"
#include "netd_resolv/resolv.h"
+#include "stats.pb.h"
namespace android {
+using android::net::NetworkDnsEventReported;
using netdutils::DumpWriter;
using netdutils::IPAddress;
using netdutils::IPPrefix;
@@ -154,7 +156,9 @@
// ourselves, which means we also bypass all the special netcontext flag
// handling and the resolver event logging.
struct addrinfo* res = nullptr;
- const int status = resolv_getaddrinfo(kIPv4OnlyHost, nullptr, &hints, &netcontext, &res);
+ NetworkDnsEventReported event;
+ const int status =
+ resolv_getaddrinfo(kIPv4OnlyHost, nullptr, &hints, &netcontext, &res, &event);
ScopedAddrinfo result(res);
if (status != 0) {
LOG(WARNING) << "(" << cfg->netId << ", " << cfg->discoveryId << ") plat_prefix/dns("
diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp
index 14a1566..2c6e7b6 100644
--- a/DnsProxyListener.cpp
+++ b/DnsProxyListener.cpp
@@ -299,17 +299,23 @@
return true;
}
+void initDnsEvent(NetworkDnsEventReported* event) {
+ // The value 0 has the special meaning of unset/unknown in Westworld atoms.
+ event->set_hints_ai_flags(-1);
+ event->set_res_nsend_flags(-1);
+}
+
void reportDnsEvent(int eventType, const android_net_context& netContext, int latencyUs,
- int returnCode, const NetworkDnsEventReported& dnsEvent,
- const std::string& query_name, const std::vector<std::string>& ip_addrs = {},
- int total_ip_addr_count = 0) {
- std::string dnsQueryStats = dnsEvent.dns_query_events().SerializeAsString();
- char const* dnsQueryStatsBytes = dnsQueryStats.c_str();
- stats::BytesField dnsQueryBytesField{dnsQueryStatsBytes, dnsQueryStats.size()};
- android::net::stats::stats_write(android::net::stats::NETWORK_DNS_EVENT_REPORTED, eventType,
- returnCode, latencyUs, dnsEvent.hints_ai_flags(),
- dnsEvent.res_nsend_flags(), dnsEvent.network_type(),
- dnsEvent.private_dns_modes(), dnsQueryBytesField);
+ int returnCode, NetworkDnsEventReported& event, const std::string& query_name,
+ const std::vector<std::string>& ip_addrs = {}, int total_ip_addr_count = 0) {
+ const std::string& dnsQueryStats = event.dns_query_events().SerializeAsString();
+ stats::BytesField dnsQueryBytesField{dnsQueryStats.c_str(), dnsQueryStats.size()};
+ event.set_return_code(static_cast<ReturnCode>(returnCode));
+ android::net::stats::stats_write(android::net::stats::NETWORK_DNS_EVENT_REPORTED,
+ event.event_type(), event.return_code(),
+ event.latency_micros(), event.hints_ai_flags(),
+ event.res_nsend_flags(), event.network_type(),
+ event.private_dns_modes(), dnsQueryBytesField);
const auto& listeners = ResolverEventReporter::getInstance().getListeners();
if (listeners.size() == 0) {
@@ -590,7 +596,8 @@
return true;
}
-void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinfo** res) {
+void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinfo** res,
+ NetworkDnsEventReported* event) {
if (mHost == nullptr) return;
const bool ipv6WantedButNoData = (mHints && mHints->ai_family == AF_INET6 && *rv == EAI_NODATA);
@@ -613,7 +620,8 @@
mHints->ai_family = AF_INET;
// Don't need to do freeaddrinfo(res) before starting new DNS lookup because previous
// DNS lookup is failed with error EAI_NODATA.
- *rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, res);
+ *rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, res,
+ event);
queryLimiter.finish(uid);
if (*rv) {
*rv = EAI_NODATA; // return original error code
@@ -648,9 +656,10 @@
maybeFixupNetContext(&mNetContext);
const uid_t uid = mClient->getUid();
int32_t rv = 0;
- NetworkDnsEventReported dnsEvent;
+ NetworkDnsEventReported event;
+ initDnsEvent(&event);
if (queryLimiter.start(uid)) {
- rv = resolv_getaddrinfo(mHost, mService, mHints, &mNetContext, &result);
+ rv = resolv_getaddrinfo(mHost, mService, mHints, &mNetContext, &result, &event);
queryLimiter.finish(uid);
} else {
// Note that this error code is currently not passed down to the client.
@@ -660,8 +669,11 @@
<< ", max concurrent queries reached";
}
- doDns64Synthesis(&rv, &result);
- const int latencyUs = int(s.timeTakenUs());
+ doDns64Synthesis(&rv, &result, &event);
+ const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
+ event.set_latency_micros(latencyUs);
+ event.set_event_type(EVENT_GETADDRINFO);
+ event.set_hints_ai_flags((mHints ? mHints->ai_flags : 0));
if (rv) {
// getaddrinfo failed
@@ -680,8 +692,8 @@
}
std::vector<std::string> ip_addrs;
const int total_ip_addr_count = extractGetAddrInfoAnswers(result, &ip_addrs);
- reportDnsEvent(INetdEventListener::EVENT_GETADDRINFO, mNetContext, latencyUs, rv, dnsEvent,
- mHost, ip_addrs, total_ip_addr_count);
+ reportDnsEvent(INetdEventListener::EVENT_GETADDRINFO, mNetContext, latencyUs, rv, event, mHost,
+ ip_addrs, total_ip_addr_count);
freeaddrinfo(result);
mClient->decRef();
}
@@ -854,10 +866,11 @@
// Send DNS query
std::vector<uint8_t> ansBuf(MAXPACKET, 0);
int arcode, nsendAns = -1;
- NetworkDnsEventReported dnsEvent;
+ NetworkDnsEventReported event;
+ initDnsEvent(&event);
if (queryLimiter.start(uid)) {
nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET,
- &arcode, static_cast<ResNsendFlags>(mFlags));
+ &arcode, static_cast<ResNsendFlags>(mFlags), &event);
queryLimiter.finish(uid);
} else {
LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid
@@ -865,14 +878,17 @@
nsendAns = -EBUSY;
}
- const int latencyUs = int(s.timeTakenUs());
+ const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
+ event.set_latency_micros(latencyUs);
+ event.set_event_type(EVENT_RES_NSEND);
+ event.set_res_nsend_flags(static_cast<ResNsendFlags>(mFlags));
// Fail, send -errno
if (nsendAns < 0) {
sendBE32(mClient, nsendAns);
if (rr_type == ns_t_a || rr_type == ns_t_aaaa) {
reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
- resNSendToAiError(nsendAns, arcode), dnsEvent, rr_name);
+ resNSendToAiError(nsendAns, arcode), event, rr_name);
}
return;
}
@@ -895,7 +911,7 @@
const int total_ip_addr_count =
extractResNsendAnswers((uint8_t*) ansBuf.data(), nsendAns, rr_type, &ip_addrs);
reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
- resNSendToAiError(nsendAns, arcode), dnsEvent, rr_name, ip_addrs,
+ resNSendToAiError(nsendAns, arcode), event, rr_name, ip_addrs,
total_ip_addr_count);
}
}
@@ -994,7 +1010,8 @@
free(mName);
}
-void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, struct hostent** hpp) {
+void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, struct hostent** hpp,
+ NetworkDnsEventReported* event) {
// Don't have to consider family AF_UNSPEC case because gethostbyname{, 2} only supports
// family AF_INET or AF_INET6.
const bool ipv6WantedButNoData = (mAf == AF_INET6 && *rv == EAI_NODATA);
@@ -1011,7 +1028,7 @@
// If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis
const uid_t uid = mClient->getUid();
if (queryLimiter.start(uid)) {
- *rv = android_gethostbynamefornetcontext(mName, AF_INET, &mNetContext, hpp);
+ *rv = android_gethostbynamefornetcontext(mName, AF_INET, &mNetContext, hpp, event);
queryLimiter.finish(uid);
if (*rv) {
*rv = EAI_NODATA; // return original error code
@@ -1035,9 +1052,10 @@
const uid_t uid = mClient->getUid();
hostent* hp = nullptr;
int32_t rv = 0;
- NetworkDnsEventReported dnsEvent;
+ NetworkDnsEventReported event;
+ initDnsEvent(&event);
if (queryLimiter.start(uid)) {
- rv = android_gethostbynamefornetcontext(mName, mAf, &mNetContext, &hp);
+ rv = android_gethostbynamefornetcontext(mName, mAf, &mNetContext, &hp, &event);
queryLimiter.finish(uid);
} else {
rv = EAI_MEMORY;
@@ -1045,8 +1063,11 @@
<< ", max concurrent queries reached";
}
- doDns64Synthesis(&rv, &hp);
- const int latencyUs = lround(s.timeTakenUs());
+ doDns64Synthesis(&rv, &hp, &event);
+ const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
+ event.set_latency_micros(latencyUs);
+ event.set_event_type(EVENT_GETHOSTBYNAME);
+
LOG(DEBUG) << "GetHostByNameHandler::run: errno: " << (hp ? "success" : strerror(errno));
bool success = true;
@@ -1064,7 +1085,7 @@
std::vector<std::string> ip_addrs;
const int total_ip_addr_count = extractGetHostByNameAnswers(hp, &ip_addrs);
- reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYNAME, mNetContext, latencyUs, rv, dnsEvent,
+ reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYNAME, mNetContext, latencyUs, rv, event,
mName, ip_addrs, total_ip_addr_count);
mClient->decRef();
}
@@ -1134,7 +1155,8 @@
free(mAddress);
}
-void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent** hpp) {
+void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent** hpp,
+ NetworkDnsEventReported* event) {
if (*hpp != nullptr || mAddressFamily != AF_INET6 || !mAddress) {
return;
}
@@ -1162,7 +1184,8 @@
if (queryLimiter.start(uid)) {
// Remove NAT64 prefix and do reverse DNS query
struct in_addr v4addr = {.s_addr = v6addr.s6_addr32[3]};
- android_gethostbyaddrfornetcontext(&v4addr, sizeof(v4addr), AF_INET, &mNetContext, hpp);
+ android_gethostbyaddrfornetcontext(&v4addr, sizeof(v4addr), AF_INET, &mNetContext, hpp,
+ event);
queryLimiter.finish(uid);
if (*hpp) {
// Replace IPv4 address with original queried IPv6 address in place. The space has
@@ -1184,10 +1207,11 @@
const uid_t uid = mClient->getUid();
hostent* hp = nullptr;
int32_t rv = 0;
- NetworkDnsEventReported dnsEvent;
+ NetworkDnsEventReported event;
+ initDnsEvent(&event);
if (queryLimiter.start(uid)) {
- rv = android_gethostbyaddrfornetcontext(mAddress, mAddressLen, mAddressFamily,
- &mNetContext, &hp);
+ rv = android_gethostbyaddrfornetcontext(mAddress, mAddressLen, mAddressFamily, &mNetContext,
+ &hp, &event);
queryLimiter.finish(uid);
} else {
rv = EAI_MEMORY;
@@ -1195,8 +1219,10 @@
<< ", max concurrent queries reached";
}
- doDns64ReverseLookup(&hp);
- const int latencyUs = int(s.timeTakenUs());
+ doDns64ReverseLookup(&hp, &event);
+ const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
+ event.set_latency_micros(latencyUs);
+ event.set_event_type(EVENT_GETHOSTBYADDR);
LOG(DEBUG) << "GetHostByAddrHandler::run: result: " << (hp ? "success" : gai_strerror(rv));
@@ -1212,7 +1238,7 @@
LOG(WARNING) << "GetHostByAddrHandler::run: Error writing DNS result to client";
}
- reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYADDR, mNetContext, latencyUs, rv, dnsEvent,
+ reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYADDR, mNetContext, latencyUs, rv, event,
(hp && hp->h_name) ? hp->h_name : "null", {}, 0);
mClient->decRef();
}
diff --git a/DnsProxyListener.h b/DnsProxyListener.h
index 423e77f..9b71bc5 100644
--- a/DnsProxyListener.h
+++ b/DnsProxyListener.h
@@ -28,6 +28,8 @@
namespace android {
namespace net {
+class NetworkDnsEventReported;
+
class DnsProxyListener : public FrameworkListener {
public:
DnsProxyListener();
@@ -54,7 +56,7 @@
void run();
private:
- void doDns64Synthesis(int32_t* rv, addrinfo** res);
+ void doDns64Synthesis(int32_t* rv, addrinfo** res, NetworkDnsEventReported* event);
SocketClient* mClient; // ref counted
char* mHost; // owned. TODO: convert to std::string.
@@ -80,7 +82,7 @@
void run();
private:
- void doDns64Synthesis(int32_t* rv, hostent** hpp);
+ void doDns64Synthesis(int32_t* rv, hostent** hpp, NetworkDnsEventReported* event);
SocketClient* mClient; // ref counted
char* mName; // owned. TODO: convert to std::string.
@@ -105,7 +107,7 @@
void run();
private:
- void doDns64ReverseLookup(hostent** hpp);
+ void doDns64ReverseLookup(hostent** hpp, NetworkDnsEventReported* event);
SocketClient* mClient; // ref counted
void* mAddress; // address to lookup; owned
diff --git a/DnsTlsDispatcher.cpp b/DnsTlsDispatcher.cpp
index 957bd4f..d1c4022 100644
--- a/DnsTlsDispatcher.cpp
+++ b/DnsTlsDispatcher.cpp
@@ -17,13 +17,17 @@
#define LOG_TAG "resolv"
#include "DnsTlsDispatcher.h"
+#include <netdutils/Stopwatch.h>
#include "DnsTlsSocketFactory.h"
+#include "resolv_private.h"
+#include "stats.pb.h"
#include <android-base/logging.h>
namespace android {
namespace net {
+using android::netdutils::Stopwatch;
using netdutils::Slice;
// static
@@ -81,29 +85,45 @@
return out;
}
-DnsTlsTransport::Response DnsTlsDispatcher::query(
- const std::list<DnsTlsServer> &tlsServers, unsigned mark,
- const Slice query, const Slice ans, int *resplen) {
- const std::list<DnsTlsServer> orderedServers(getOrderedServerList(tlsServers, mark));
+DnsTlsTransport::Response DnsTlsDispatcher::query(const std::list<DnsTlsServer>& tlsServers,
+ res_state statp, const Slice query,
+ const Slice ans, int* resplen) {
+ const std::list<DnsTlsServer> orderedServers(getOrderedServerList(tlsServers, statp->_mark));
if (orderedServers.empty()) LOG(WARNING) << "Empty DnsTlsServer list";
DnsTlsTransport::Response code = DnsTlsTransport::Response::internal_error;
+ int serverCount = 0;
for (const auto& server : orderedServers) {
- code = this->query(server, mark, query, ans, resplen);
+ DnsQueryEvent* dnsQueryEvent =
+ statp->event->mutable_dns_query_events()->add_dns_query_event();
+ dnsQueryEvent->set_rcode(NS_R_INTERNAL_ERROR);
+ Stopwatch query_stopwatch;
+ code = this->query(server, statp->_mark, query, ans, resplen);
+
+ dnsQueryEvent->set_latency_micros(saturate_cast<int32_t>(query_stopwatch.timeTakenUs()));
+ dnsQueryEvent->set_dns_server_index(serverCount++);
+ dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(server.ss.ss_family));
+ dnsQueryEvent->set_protocol(PROTO_DOT);
+ dnsQueryEvent->set_type(getQueryType(query.base(), query.size()));
+
switch (code) {
// These response codes are valid responses and not expected to
// change if another server is queried.
case DnsTlsTransport::Response::success:
+ dnsQueryEvent->set_rcode(
+ static_cast<NsRcode>(reinterpret_cast<HEADER*>(ans.base())->rcode));
+ [[fallthrough]];
case DnsTlsTransport::Response::limit_error:
return code;
- break;
// These response codes might differ when trying other servers, so
// keep iterating to see if we can get a different (better) result.
case DnsTlsTransport::Response::network_error:
+ // Sync from res_tls_send in res_send.cpp
+ dnsQueryEvent->set_rcode(NS_R_TIMEOUT);
+ [[fallthrough]];
case DnsTlsTransport::Response::internal_error:
continue;
- break;
// No "default" statement.
}
}
diff --git a/DnsTlsDispatcher.h b/DnsTlsDispatcher.h
index 7a48089..b8e9968 100644
--- a/DnsTlsDispatcher.h
+++ b/DnsTlsDispatcher.h
@@ -28,6 +28,7 @@
#include "DnsTlsServer.h"
#include "DnsTlsTransport.h"
#include "IDnsTlsSocketFactory.h"
+#include "resolv_private.h"
namespace android {
namespace net {
@@ -48,9 +49,9 @@
// the count of bytes written in |resplen|. Returns a success or error code.
// The order in which servers from |tlsServers| are queried may not be the
// order passed in by the caller.
- DnsTlsTransport::Response query(const std::list<DnsTlsServer>& tlsServers, unsigned mark,
- const netdutils::Slice query, const netdutils::Slice ans,
- int* _Nonnull resplen);
+ DnsTlsTransport::Response query(const std::list<DnsTlsServer>& tlsServers,
+ res_state _Nonnull statp, const netdutils::Slice query,
+ const netdutils::Slice ans, int* _Nonnull resplen);
// Given a |query|, sends it to the server on the network indicated by |mark|,
// and writes the response into |ans|, and indicates
diff --git a/PrivateDnsConfiguration.h b/PrivateDnsConfiguration.h
index 50fb54d..775cff1 100644
--- a/PrivateDnsConfiguration.h
+++ b/PrivateDnsConfiguration.h
@@ -30,7 +30,7 @@
namespace net {
// The DNS over TLS mode on a specific netId.
-enum class PrivateDnsMode : uint8_t { OFF, OPPORTUNISTIC, STRICT };
+enum class PrivateDnsMode : uint8_t { UNKNOWN, OFF, OPPORTUNISTIC, STRICT };
// Validation status of a DNS over TLS server (on a specific netId).
enum class Validation : uint8_t { in_process, success, fail, unknown_server, unknown_netid };
diff --git a/ResolverController.cpp b/ResolverController.cpp
index 2ceeba7..ceb7639 100644
--- a/ResolverController.cpp
+++ b/ResolverController.cpp
@@ -57,6 +57,8 @@
const char* getPrivateDnsModeString(PrivateDnsMode mode) {
switch (mode) {
+ case PrivateDnsMode::UNKNOWN:
+ return "UNKNOWN";
case PrivateDnsMode::OFF:
return "OFF";
case PrivateDnsMode::OPPORTUNISTIC:
@@ -357,8 +359,7 @@
mDns64Configuration.dump(dw, netId);
ExternalPrivateDnsStatus privateDnsStatus = {PrivateDnsMode::OFF, 0, {}};
gPrivateDnsConfiguration.getStatus(netId, &privateDnsStatus);
- dw.println("Private DNS mode: %s",
- getPrivateDnsModeString(static_cast<PrivateDnsMode>(privateDnsStatus.mode)));
+ dw.println("Private DNS mode: %s", getPrivateDnsModeString(privateDnsStatus.mode));
if (!privateDnsStatus.numServers) {
dw.println("No Private DNS servers configured");
} else {
diff --git a/getaddrinfo.cpp b/getaddrinfo.cpp
index 1758de5..e560ca5 100644
--- a/getaddrinfo.cpp
+++ b/getaddrinfo.cpp
@@ -62,6 +62,8 @@
#define ANY 0
+using android::net::NetworkDnsEventReported;
+
const char in_addrany[] = {0, 0, 0, 0};
const char in_loopback[] = {127, 0, 0, 1};
const char in6_addrany[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@@ -124,7 +126,7 @@
static int str2number(const char*);
static int explore_fqdn(const struct addrinfo*, const char*, const char*, struct addrinfo**,
- const struct android_net_context*);
+ const struct android_net_context*, NetworkDnsEventReported* event);
static int explore_null(const struct addrinfo*, const char*, struct addrinfo**);
static int explore_numeric(const struct addrinfo*, const char*, const char*, struct addrinfo**,
const char*);
@@ -140,7 +142,8 @@
static struct addrinfo* getanswer(const querybuf*, int, const char*, int, const struct addrinfo*,
int* herrno);
static int dns_getaddrinfo(const char* name, const addrinfo* pai,
- const android_net_context* netcontext, addrinfo** rv);
+ const android_net_context* netcontext, addrinfo** rv,
+ NetworkDnsEventReported* event);
static void _sethtent(FILE**);
static void _endhtent(FILE**);
static struct addrinfo* _gethtent(FILE**, const char*, const struct addrinfo*);
@@ -264,7 +267,9 @@
.dns_mark = MARK_UNSET,
.uid = NET_CONTEXT_INVALID_UID,
};
- return android_getaddrinfofornetcontext(hostname, servname, &hints, &netcontext, result);
+ NetworkDnsEventReported event;
+ return android_getaddrinfofornetcontext(hostname, servname, &hints, &netcontext, result,
+ &event);
}
namespace {
@@ -303,12 +308,13 @@
int android_getaddrinfofornetcontext(const char* hostname, const char* servname,
const addrinfo* hints, const android_net_context* netcontext,
- addrinfo** res) {
+ addrinfo** res, NetworkDnsEventReported* event) {
// hostname is allowed to be nullptr
// servname is allowed to be nullptr
// hints is allowed to be nullptr
assert(res != nullptr);
assert(netcontext != nullptr);
+ assert(event != nullptr);
addrinfo sentinel = {};
addrinfo* cur = &sentinel;
@@ -375,7 +381,7 @@
break;
}
- return resolv_getaddrinfo(hostname, servname, hints, netcontext, res);
+ return resolv_getaddrinfo(hostname, servname, hints, netcontext, res, event);
} while (0);
if (error) {
@@ -388,7 +394,8 @@
}
int resolv_getaddrinfo(const char* _Nonnull hostname, const char* servname, const addrinfo* hints,
- const android_net_context* _Nonnull netcontext, addrinfo** _Nonnull res) {
+ const android_net_context* _Nonnull netcontext, addrinfo** _Nonnull res,
+ NetworkDnsEventReported* _Nonnull event) {
if (hostname == nullptr && servname == nullptr) return EAI_NONAME;
if (hostname == nullptr) return EAI_NODATA;
@@ -397,6 +404,7 @@
// hints is allowed to be nullptr
assert(res != nullptr);
assert(netcontext != nullptr);
+ assert(event != nullptr);
int error = EAI_FAIL;
if (hints && (error = validateHints(hints))) {
@@ -423,7 +431,7 @@
LOG(DEBUG) << __func__ << ": explore_fqdn(): ai_family=" << tmp.ai_family
<< " ai_socktype=" << tmp.ai_socktype << " ai_protocol=" << tmp.ai_protocol;
- error = explore_fqdn(&tmp, hostname, servname, &cur->ai_next, netcontext);
+ error = explore_fqdn(&tmp, hostname, servname, &cur->ai_next, netcontext, event);
while (cur->ai_next) cur = cur->ai_next;
}
@@ -437,7 +445,8 @@
// FQDN hostname, DNS lookup
static int explore_fqdn(const addrinfo* pai, const char* hostname, const char* servname,
- addrinfo** res, const android_net_context* netcontext) {
+ addrinfo** res, const android_net_context* netcontext,
+ NetworkDnsEventReported* event) {
assert(pai != nullptr);
// hostname may be nullptr
// servname may be nullptr
@@ -450,7 +459,7 @@
if ((error = get_portmatch(pai, servname))) return error;
if (!files_getaddrinfo(hostname, pai, &result)) {
- error = dns_getaddrinfo(hostname, pai, netcontext, &result);
+ error = dns_getaddrinfo(hostname, pai, netcontext, &result, event);
}
if (error) {
freeaddrinfo(result);
@@ -1370,7 +1379,8 @@
}
static int dns_getaddrinfo(const char* name, const addrinfo* pai,
- const android_net_context* netcontext, addrinfo** rv) {
+ const android_net_context* netcontext, addrinfo** rv,
+ NetworkDnsEventReported* event) {
res_target q = {};
res_target q2 = {};
@@ -1432,7 +1442,7 @@
* fully populate the thread private data here, but if we get down there
* and have a cache hit that would be wasted, so we do the rest there on miss
*/
- res_setnetcontext(res, netcontext);
+ res_setnetcontext(res, netcontext, event);
int he;
if (res_searchN(name, &q, res, &he) < 0) {
diff --git a/getaddrinfo.h b/getaddrinfo.h
index a601314..7f1c877 100644
--- a/getaddrinfo.h
+++ b/getaddrinfo.h
@@ -17,13 +17,15 @@
#pragma once
#include "netd_resolv/resolv.h" // struct android_net_context
+#include "stats.pb.h"
struct addrinfo;
int android_getaddrinfofornetcontext(const char* hostname, const char* servname,
const addrinfo* hints, const android_net_context* netcontext,
- addrinfo** res);
+ addrinfo** res, android::net::NetworkDnsEventReported*);
// This is the DNS proxy entry point for getaddrinfo().
int resolv_getaddrinfo(const char* hostname, const char* servname, const addrinfo* hints,
- const android_net_context* netcontext, addrinfo** res);
+ const android_net_context* netcontext, addrinfo** res,
+ android::net::NetworkDnsEventReported*);
diff --git a/gethnamaddr.cpp b/gethnamaddr.cpp
index 9be5949..97236f9 100644
--- a/gethnamaddr.cpp
+++ b/gethnamaddr.cpp
@@ -77,6 +77,9 @@
#include "netd_resolv/resolv.h"
#include "resolv_cache.h"
#include "resolv_private.h"
+#include "stats.pb.h"
+
+using android::net::NetworkDnsEventReported;
// NetBSD uses _DIAGASSERT to null-check arguments and the like,
// but it's clear from the number of mistakes in their assertions
@@ -113,19 +116,23 @@
static void addrsort(char**, int, res_state);
static int dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
- const android_net_context* netcontext, getnamaddr* info);
+ const android_net_context* netcontext, getnamaddr* info,
+ NetworkDnsEventReported* event);
static int dns_gethtbyname(const char* name, int af, getnamaddr* info);
static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
- size_t hbuflen, const android_net_context* netcontext);
+ size_t hbuflen, const android_net_context* netcontext,
+ NetworkDnsEventReported* event);
static int gethostbyname_internal_real(const char* name, int af, hostent* hp, char* buf,
size_t buflen);
+
static int android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t, int,
struct hostent*, char*, size_t,
- const struct android_net_context*);
+ const struct android_net_context*,
+ NetworkDnsEventReported* event);
static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
const struct android_net_context* netcontext,
- hostent** hp);
+ hostent** hp, NetworkDnsEventReported* event);
#define BOUNDED_INCR(x) \
do { \
@@ -489,14 +496,16 @@
// very similar in proxy-ness to android_getaddrinfo_proxy
static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
- size_t hbuflen, const android_net_context* netcontext) {
- res_setnetcontext(res, netcontext);
+ size_t hbuflen, const android_net_context* netcontext,
+ NetworkDnsEventReported* event) {
+ res_setnetcontext(res, netcontext, event);
return gethostbyname_internal_real(name, af, hp, hbuf, hbuflen);
}
static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t len, int af,
struct hostent* hp, char* buf, size_t buflen,
- const struct android_net_context* netcontext) {
+ const struct android_net_context* netcontext,
+ NetworkDnsEventReported* event) {
const u_char* uaddr = (const u_char*) addr;
socklen_t size;
struct getnamaddr info;
@@ -538,7 +547,7 @@
info.buf = buf;
info.buflen = buflen;
if (_hf_gethtbyaddr(uaddr, len, af, &info)) {
- int error = dns_gethtbyaddr(uaddr, len, af, netcontext, &info);
+ int error = dns_gethtbyaddr(uaddr, len, af, netcontext, &info, event);
if (error != 0) return error;
}
return 0;
@@ -546,8 +555,9 @@
static int android_gethostbyaddrfornetcontext_proxy_internal(
const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
- const struct android_net_context* netcontext) {
- return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, netcontext);
+ const struct android_net_context* netcontext, NetworkDnsEventReported* event) {
+ return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, netcontext,
+ event);
}
// TODO: Consider leaving function without returning error code as _gethtent() does because
@@ -758,7 +768,8 @@
}
static int dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
- const android_net_context* netcontext, getnamaddr* info) {
+ const android_net_context* netcontext, getnamaddr* info,
+ NetworkDnsEventReported* event) {
char qbuf[MAXDNAME + 1], *qp, *ep;
int n;
int advance;
@@ -805,7 +816,7 @@
res_state res = res_get_state();
if (!res) return EAI_MEMORY;
- res_setnetcontext(res, netcontext);
+ res_setnetcontext(res, netcontext, event);
int he;
n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf), &he);
if (n < 0) {
@@ -843,13 +854,16 @@
*/
int android_gethostbynamefornetcontext(const char* name, int af,
- const struct android_net_context* netcontext, hostent** hp) {
- int error;
+ const struct android_net_context* netcontext, hostent** hp,
+ NetworkDnsEventReported* event) {
+ assert(event != nullptr);
+
res_state res = res_get_state();
if (res == NULL) return EAI_MEMORY;
res_static* rs = res_get_static(); // For thread-safety.
+ int error;
error = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
- netcontext);
+ netcontext, event);
if (error == 0) {
*hp = &rs->host;
}
@@ -857,16 +871,19 @@
}
int android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
- const struct android_net_context* netcontext, hostent** hp) {
- return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext, hp);
+ const struct android_net_context* netcontext, hostent** hp,
+ NetworkDnsEventReported* event) {
+ return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext, hp, event);
}
static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
const struct android_net_context* netcontext,
- hostent** hp) {
+ hostent** hp, NetworkDnsEventReported* event) {
+ assert(event != nullptr);
+
struct res_static* rs = res_get_static(); // For thread-safety.
int error = android_gethostbyaddrfornetcontext_proxy_internal(
- addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), netcontext);
+ addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), netcontext, event);
if (error == 0) *hp = &rs->host;
return error;
}
diff --git a/gethnamaddr.h b/gethnamaddr.h
index 27cc1c2..bfdb14e 100644
--- a/gethnamaddr.h
+++ b/gethnamaddr.h
@@ -18,10 +18,12 @@
#include <netdb.h> // struct hostent
#include "netd_resolv/resolv.h" // struct android_net_context
+#include "stats.pb.h"
// This is the entry point for the gethostbyname() family of legacy calls.
-int android_gethostbynamefornetcontext(const char*, int, const android_net_context*, hostent**);
+int android_gethostbynamefornetcontext(const char*, int, const android_net_context*, hostent**,
+ android::net::NetworkDnsEventReported*);
// This is the entry point for the gethostbyaddr() family of legacy calls.
int android_gethostbyaddrfornetcontext(const void*, socklen_t, int, const android_net_context*,
- hostent**);
+ hostent**, android::net::NetworkDnsEventReported*);
diff --git a/libnetd_resolv_test.cpp b/libnetd_resolv_test.cpp
index 6485e0d..4769b1f 100644
--- a/libnetd_resolv_test.cpp
+++ b/libnetd_resolv_test.cpp
@@ -27,6 +27,7 @@
#include "getaddrinfo.h"
#include "gethnamaddr.h"
#include "resolv_cache.h"
+#include "stats.pb.h"
#define NAME(variable) #variable
@@ -41,6 +42,7 @@
namespace net {
using android::base::StringPrintf;
+using android::net::NetworkDnsEventReported;
using android::netdutils::ScopedAddrinfo;
// Minimize class ResolverTest to be class TestBase because class TestBase doesn't need all member
@@ -122,8 +124,9 @@
// Invalid hostname and servname.
// Both hostname and servname are null pointers. Expect error number EAI_NONAME.
struct addrinfo* result = nullptr;
+ NetworkDnsEventReported event;
int rv = resolv_getaddrinfo(nullptr /*hostname*/, nullptr /*servname*/, nullptr /*hints*/,
- &mNetcontext, &result);
+ &mNetcontext, &result, &event);
EXPECT_EQ(EAI_NONAME, rv);
if (result) {
freeaddrinfo(result);
@@ -177,8 +180,9 @@
.ai_addr = config.ai_addr,
.ai_next = config.ai_next,
};
-
- rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext, &result);
+ NetworkDnsEventReported event;
+ rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext, &result,
+ &event);
EXPECT_EQ(config.expected_eai_error, rv);
if (result) {
@@ -199,9 +203,9 @@
const struct addrinfo hints = {
.ai_family = family, // unsupported family
};
-
+ NetworkDnsEventReported event;
int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
- &result);
+ &result, &event);
EXPECT_EQ(EAI_FAMILY, rv);
if (result) freeaddrinfo(result);
@@ -246,9 +250,9 @@
.ai_protocol = protocol,
.ai_socktype = socktype,
};
-
+ NetworkDnsEventReported event;
int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
- &result);
+ &result, &event);
EXPECT_EQ(EAI_BADHINTS, rv);
if (result) freeaddrinfo(result);
@@ -319,7 +323,9 @@
};
struct addrinfo* result = nullptr;
- int rv = resolv_getaddrinfo("localhost", config.servname, &hints, &mNetcontext, &result);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo("localhost", config.servname, &hints, &mNetcontext, &result,
+ &event);
EXPECT_EQ(config.expected_eai_error, rv);
if (result) freeaddrinfo(result);
@@ -342,7 +348,8 @@
// Want AAAA answer but DNS server has A answer only.
struct addrinfo* result = nullptr;
const addrinfo hints = {.ai_family = AF_INET6};
- int rv = resolv_getaddrinfo("v4only", nullptr, &hints, &mNetcontext, &result);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo("v4only", nullptr, &hints, &mNetcontext, &result, &event);
EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
EXPECT_EQ(nullptr, result);
EXPECT_EQ(EAI_NODATA, rv);
@@ -380,7 +387,8 @@
struct addrinfo* result = nullptr;
const struct addrinfo hints = {.ai_family = config.ai_family};
- int rv = resolv_getaddrinfo("sawadee", nullptr, &hints, &mNetcontext, &result);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo("sawadee", nullptr, &hints, &mNetcontext, &result, &event);
EXPECT_EQ(0, rv);
EXPECT_TRUE(result != nullptr);
EXPECT_EQ(1U, GetNumQueries(dns, host_name));
@@ -427,7 +435,8 @@
addrinfo* res = nullptr;
const addrinfo hints = {.ai_family = family};
- int rv = resolv_getaddrinfo(hostname, nullptr, &hints, &mNetcontext, &res);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo(hostname, nullptr, &hints, &mNetcontext, &res, &event);
ScopedAddrinfo result(res);
EXPECT_EQ(nullptr, result);
EXPECT_EQ(EAI_FAIL, rv);
@@ -470,7 +479,8 @@
struct addrinfo* result = nullptr;
const struct addrinfo hints = {.ai_family = AF_UNSPEC};
- int rv = resolv_getaddrinfo(host_name, nullptr, &hints, &mNetcontext, &result);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo(host_name, nullptr, &hints, &mNetcontext, &result, &event);
EXPECT_EQ(config.expected_eai_error, rv);
if (result) freeaddrinfo(result);
@@ -493,7 +503,8 @@
struct addrinfo* result = nullptr;
const struct addrinfo hints = {.ai_family = AF_UNSPEC};
- int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
if (result) freeaddrinfo(result);
@@ -535,8 +546,8 @@
addrinfo* res = nullptr;
const addrinfo hints = {.ai_family = config.family};
-
- int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res, &event);
ScopedAddrinfo result(res);
EXPECT_EQ(nullptr, result);
EXPECT_EQ(EAI_FAIL, rv);
@@ -592,7 +603,8 @@
addrinfo* res = nullptr;
const addrinfo hints = {.ai_family = family};
- int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res, &event);
ScopedAddrinfo result(res);
EXPECT_EQ(nullptr, result);
EXPECT_EQ(EAI_FAIL, rv);
@@ -618,8 +630,8 @@
addrinfo* res = nullptr;
const addrinfo hints = {.ai_family = family};
-
- int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &res);
+ NetworkDnsEventReported event;
+ int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &res, &event);
ScopedAddrinfo result(res);
EXPECT_EQ(nullptr, result);
EXPECT_EQ(EAI_FAIL, rv);
@@ -655,8 +667,9 @@
dns.clearQueries();
struct hostent* hp = nullptr;
+ NetworkDnsEventReported event;
int rv = android_gethostbynamefornetcontext("jiababuei", config.ai_family, &mNetcontext,
- &hp);
+ &hp, &event);
EXPECT_EQ(0, rv);
EXPECT_TRUE(hp != nullptr);
EXPECT_EQ(1U, GetNumQueries(dns, host_name));
@@ -700,7 +713,9 @@
SCOPED_TRACE(StringPrintf("family: %d, config.name: %s", family, hostname));
struct hostent* hp = nullptr;
- int rv = android_gethostbynamefornetcontext(hostname, family, &mNetcontext, &hp);
+ NetworkDnsEventReported event;
+ int rv =
+ android_gethostbynamefornetcontext(hostname, family, &mNetcontext, &hp, &event);
EXPECT_EQ(nullptr, hp);
EXPECT_EQ(EAI_FAIL, rv);
}
@@ -722,7 +737,8 @@
// Want AAAA answer but DNS server has A answer only.
struct hostent* hp = nullptr;
- int rv = android_gethostbynamefornetcontext("v4only", AF_INET6, &mNetcontext, &hp);
+ NetworkDnsEventReported event;
+ int rv = android_gethostbynamefornetcontext("v4only", AF_INET6, &mNetcontext, &hp, &event);
EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
EXPECT_EQ(nullptr, hp);
EXPECT_EQ(EAI_NODATA, rv);
@@ -764,7 +780,8 @@
mDefaultSearchDomains, &mDefaultParams_Binder));
struct hostent* hp = nullptr;
- int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp);
+ NetworkDnsEventReported event;
+ int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp, &event);
EXPECT_EQ(nullptr, hp);
EXPECT_EQ(config.expected_eai_error, rv);
}
@@ -785,7 +802,8 @@
mDefaultSearchDomains, &mDefaultParams_Binder));
struct hostent* hp = nullptr;
- int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp);
+ NetworkDnsEventReported event;
+ int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp, &event);
EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
}
@@ -820,7 +838,9 @@
StringPrintf("config.family: %d, config.name: %s", config.family, config.name));
struct hostent* hp = nullptr;
- int rv = android_gethostbynamefornetcontext(config.name, config.family, &mNetcontext, &hp);
+ NetworkDnsEventReported event;
+ int rv = android_gethostbynamefornetcontext(config.name, config.family, &mNetcontext, &hp,
+ &event);
EXPECT_EQ(nullptr, hp);
EXPECT_EQ(EAI_FAIL, rv);
}
@@ -874,7 +894,9 @@
StringPrintf("family: %d, testHostName: %s", family, testHostName.c_str()));
struct hostent* hp = nullptr;
- int rv = android_gethostbynamefornetcontext(config.name, family, &mNetcontext, &hp);
+ NetworkDnsEventReported event;
+ int rv = android_gethostbynamefornetcontext(config.name, family, &mNetcontext, &hp,
+ &event);
EXPECT_EQ(nullptr, hp);
EXPECT_EQ(EAI_FAIL, rv);
}
@@ -898,7 +920,8 @@
SCOPED_TRACE(StringPrintf("family: %d", family));
struct hostent* hp = nullptr;
- int rv = android_gethostbynamefornetcontext("hello", family, &mNetcontext, &hp);
+ NetworkDnsEventReported event;
+ int rv = android_gethostbynamefornetcontext("hello", family, &mNetcontext, &hp, &event);
EXPECT_EQ(nullptr, hp);
EXPECT_EQ(EAI_FAIL, rv);
}
diff --git a/res_init.cpp b/res_init.cpp
index 5be0188..bb86723 100644
--- a/res_init.cpp
+++ b/res_init.cpp
@@ -309,7 +309,8 @@
return (statp->nscount);
}
-void res_setnetcontext(res_state statp, const struct android_net_context* netcontext) {
+void res_setnetcontext(res_state statp, const struct android_net_context* netcontext,
+ android::net::NetworkDnsEventReported* _Nonnull event) {
if (statp != NULL) {
statp->netid = netcontext->dns_netid;
statp->_mark = netcontext->dns_mark;
@@ -319,5 +320,6 @@
if (netcontext->flags & NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS) {
statp->use_local_nameserver = true;
}
+ statp->event = event;
}
}
diff --git a/res_send.cpp b/res_send.cpp
index 3289378..ce6f36f 100644
--- a/res_send.cpp
+++ b/res_send.cpp
@@ -100,6 +100,7 @@
#include <android/multinetwork.h> // ResNsendFlags
#include <netdutils/Slice.h>
+#include <netdutils/Stopwatch.h>
#include "DnsTlsDispatcher.h"
#include "DnsTlsTransport.h"
#include "PrivateDnsConfiguration.h"
@@ -109,10 +110,13 @@
#include "res_state_ext.h"
#include "resolv_cache.h"
#include "resolv_private.h"
+#include "stats.pb.h"
// TODO: use the namespace something like android::netd_resolv for libnetd_resolv
using namespace android::net;
+using android::net::NetworkDnsEventReported;
using android::netdutils::Slice;
+using android::netdutils::Stopwatch;
static DnsTlsDispatcher sDnsTlsDispatcher;
@@ -131,11 +135,29 @@
static int res_tls_send(res_state, const Slice query, const Slice answer, int* rcode,
bool* fallback);
-/* BIONIC-BEGIN: implement source port randomization */
+NsType getQueryType(const uint8_t* msg, size_t msgLen) {
+ ns_msg handle;
+ ns_rr rr;
+ if (ns_initparse((const uint8_t*)msg, msgLen, &handle) < 0 ||
+ ns_parserr(&handle, ns_s_qd, 0, &rr) < 0) {
+ return NS_T_INVALID;
+ }
+ return static_cast<NsType>(ns_rr_type(rr));
+}
+
+IpVersion ipFamilyToIPVersion(const int ipFamily) {
+ switch (ipFamily) {
+ case AF_INET:
+ return IV_IPV4;
+ case AF_INET6:
+ return IV_IPV6;
+ default:
+ return IV_UNKNOWN;
+ }
+}
// BEGIN: Code copied from ISC eventlib
// TODO: move away from this code
-
#define BILLION 1000000000
static struct timespec evConsTime(time_t sec, long nsec) {
@@ -199,6 +221,7 @@
// END: Code copied from ISC eventlib
+/* BIONIC-BEGIN: implement source port randomization */
static int random_bind(int s, int family) {
sockaddr_union u;
int j;
@@ -371,6 +394,10 @@
return (1);
}
+static DnsQueryEvent* addDnsQueryEvent(NetworkDnsEventReported* event) {
+ return event->mutable_dns_query_events()->add_dns_query_event();
+}
+
int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int anssiz, int* rcode,
uint32_t flags) {
int gotsomewhere, terrno, v_circuit, resplen, n;
@@ -389,11 +416,15 @@
terrno = ETIMEDOUT;
int anslen = 0;
+ Stopwatch cache_stopwatch;
cache_status = resolv_cache_lookup(statp->netid, buf, buflen, ans, anssiz, &anslen, flags);
-
+ const int32_t cacheLatencyUs = saturate_cast<int32_t>(cache_stopwatch.timeTakenUs());
if (cache_status == RESOLV_CACHE_FOUND) {
HEADER* hp = (HEADER*)(void*)ans;
*rcode = hp->rcode;
+ DnsQueryEvent* dnsQueryEvent = addDnsQueryEvent(statp->event);
+ dnsQueryEvent->set_latency_micros(cacheLatencyUs);
+ dnsQueryEvent->set_cache_hit(static_cast<CacheStatus>(cache_status));
return anslen;
} else if (cache_status != RESOLV_CACHE_UNSUPPORTED) {
// had a cache miss for a known network, so populate the thread private
@@ -492,12 +523,11 @@
for (int ns = 0; ns < statp->nscount; ns++) {
if (!usable_servers[ns]) continue;
- struct sockaddr* nsap;
int nsaplen;
time_t now = 0;
int delay = 0;
*rcode = RCODE_INTERNAL_ERROR;
- nsap = get_nsaddr(statp, (size_t) ns);
+ const sockaddr* nsap = get_nsaddr(statp, ns);
nsaplen = get_salen(nsap);
same_ns:
@@ -521,13 +551,16 @@
}
}
- [[maybe_unused]] static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
- [[maybe_unused]] char abuf[NI_MAXHOST];
+ static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+ char abuf[NI_MAXHOST];
+ DnsQueryEvent* dnsQueryEvent = addDnsQueryEvent(statp->event);
+ dnsQueryEvent->set_cache_hit(static_cast<CacheStatus>(cache_status));
if (getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), NULL, 0, niflags) == 0)
LOG(DEBUG) << __func__ << ": Querying server (# " << ns + 1
<< ") address = " << abuf;
+ Stopwatch query_stopwatch;
if (v_circuit) {
/* Use VC; at most one attempt per server. */
bool shouldRecordStats = (attempt == 0);
@@ -536,6 +569,15 @@
n = send_vc(statp, ¶ms, buf, buflen, ans, anssiz, &terrno, ns, &now, rcode,
&delay);
+ dnsQueryEvent->set_latency_micros(
+ saturate_cast<int32_t>(query_stopwatch.timeTakenUs()));
+ dnsQueryEvent->set_dns_server_index(ns);
+ dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(nsap->sa_family));
+ dnsQueryEvent->set_retry_times(attempt);
+ dnsQueryEvent->set_rcode(static_cast<NsRcode>(*rcode));
+ dnsQueryEvent->set_protocol(PROTO_TCP);
+ dnsQueryEvent->set_type(getQueryType(buf, buflen));
+
/*
* Only record stats the first time we try a query. This ensures that
* queries that deterministically fail (e.g., a name that always returns
@@ -564,6 +606,15 @@
n = send_dg(statp, ¶ms, buf, buflen, ans, anssiz, &terrno, ns, &v_circuit,
&gotsomewhere, &now, rcode, &delay);
+ dnsQueryEvent->set_latency_micros(
+ saturate_cast<int32_t>(query_stopwatch.timeTakenUs()));
+ dnsQueryEvent->set_dns_server_index(ns);
+ dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(nsap->sa_family));
+ dnsQueryEvent->set_retry_times(attempt);
+ dnsQueryEvent->set_rcode(static_cast<NsRcode>(*rcode));
+ dnsQueryEvent->set_protocol(PROTO_UDP);
+ dnsQueryEvent->set_type(getQueryType(buf, buflen));
+
/* Only record stats the first time we try a query. See above. */
if (attempt == 0) {
res_sample sample;
@@ -1164,9 +1215,9 @@
bool* fallback) {
int resplen = 0;
const unsigned netId = statp->netid;
- const unsigned mark = statp->_mark;
PrivateDnsStatus privateDnsStatus = gPrivateDnsConfiguration.getStatus(netId);
+ statp->event->set_private_dns_modes(static_cast<PrivateDnsModes>(privateDnsStatus.mode));
if (privateDnsStatus.mode == PrivateDnsMode::OFF) {
*fallback = true;
@@ -1205,7 +1256,7 @@
LOG(INFO) << __func__ << ": performing query over TLS";
- const auto response = sDnsTlsDispatcher.query(privateDnsStatus.validatedServers, mark, query,
+ const auto response = sDnsTlsDispatcher.query(privateDnsStatus.validatedServers, statp, query,
answer, &resplen);
LOG(INFO) << __func__ << ": TLS query result: " << static_cast<int>(response);
@@ -1247,9 +1298,11 @@
}
int resolv_res_nsend(const android_net_context* netContext, const uint8_t* msg, int msgLen,
- uint8_t* ans, int ansLen, int* rcode, uint32_t flags) {
+ uint8_t* ans, int ansLen, int* rcode, uint32_t flags,
+ NetworkDnsEventReported* event) {
+ assert(event != nullptr);
res_state res = res_get_state();
- res_setnetcontext(res, netContext);
+ res_setnetcontext(res, netContext, event);
_resolv_populate_res_for_net(res);
*rcode = NOERROR;
return res_nsend(res, msg, msgLen, ans, ansLen, rcode, flags);
diff --git a/res_send.h b/res_send.h
index 7fc77cb..fb80160 100644
--- a/res_send.h
+++ b/res_send.h
@@ -17,7 +17,9 @@
#pragma once
#include "netd_resolv/resolv.h" // struct android_net_context
+#include "stats.pb.h"
// Query dns with raw msg
int resolv_res_nsend(const android_net_context* netContext, const uint8_t* msg, int msgLen,
- uint8_t* ans, int ansLen, int* rcode, uint32_t flags);
+ uint8_t* ans, int ansLen, int* rcode, uint32_t flags,
+ android::net::NetworkDnsEventReported* event);
diff --git a/resolv_private.h b/resolv_private.h
index 41fc5de..6d58d15 100644
--- a/resolv_private.h
+++ b/resolv_private.h
@@ -64,6 +64,7 @@
#include "netd_resolv/resolv.h"
#include "netd_resolv/stats.h"
#include "resolv_static.h"
+#include "stats.pb.h"
// Linux defines MAXHOSTNAMELEN as 64, while the domain name limit in
// RFC 1034 and RFC 1035 is 255 octets.
@@ -118,6 +119,7 @@
} _u;
struct res_static rstatic[1];
bool use_local_nameserver; /* DNS-over-TLS bypass */
+ android::net::NetworkDnsEventReported* event;
};
typedef struct __res_state* res_state;
@@ -211,7 +213,8 @@
int res_getservers(res_state, sockaddr_union*, int);
struct android_net_context; /* forward */
-void res_setnetcontext(res_state, const struct android_net_context*);
+void res_setnetcontext(res_state, const struct android_net_context*,
+ android::net::NetworkDnsEventReported* event);
int getaddrinfo_numeric(const char* hostname, const char* servname, addrinfo hints,
addrinfo** result);
@@ -222,4 +225,16 @@
// switch resolver log severity
android::base::LogSeverity logSeverityStrToEnum(const std::string& logSeverityStr);
+template <typename Dest>
+Dest saturate_cast(int64_t x) {
+ using DestLimits = std::numeric_limits<Dest>;
+ if (x > DestLimits::max()) return DestLimits::max();
+ if (x < DestLimits::min()) return DestLimits::min();
+ return static_cast<Dest>(x);
+}
+
+android::net::NsType getQueryType(const uint8_t* msg, size_t msgLen);
+
+android::net::IpVersion ipFamilyToIPVersion(int ipFamily);
+
#endif // NETD_RESOLV_PRIVATE_H
diff --git a/stats.proto b/stats.proto
index d6fc577..7b48e92 100644
--- a/stats.proto
+++ b/stats.proto
@@ -68,6 +68,7 @@
// NS_R_BADSIG = 16,
NS_R_BADKEY = 17;
NS_R_BADTIME = 18;
+ NS_R_INTERNAL_ERROR = 254;
NS_R_TIMEOUT = 255;
}