diff options
Diffstat (limited to 'resolv/res_send.cpp')
| -rw-r--r-- | resolv/res_send.cpp | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/resolv/res_send.cpp b/resolv/res_send.cpp index d89ad7ee..1ccfc741 100644 --- a/resolv/res_send.cpp +++ b/resolv/res_send.cpp @@ -101,6 +101,7 @@ #include <android/multinetwork.h> // ResNsendFlags #include <netdutils/Slice.h> +#include <netdutils/Stopwatch.h> #include "DnsTlsDispatcher.h" #include "DnsTlsTransport.h" #include "PrivateDnsConfiguration.h" @@ -110,10 +111,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; @@ -133,11 +137,29 @@ static int retrying_poll(const int sock, short events, const struct timespec* fi 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) { @@ -201,6 +223,7 @@ static struct iovec evConsIovec(void* buf, size_t cnt) { // 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; @@ -373,6 +396,10 @@ int res_queriesmatch(const u_char* buf1, const u_char* eom1, const u_char* buf2, 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; @@ -391,11 +418,15 @@ int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int a 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 @@ -522,12 +553,11 @@ int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int a 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: @@ -551,13 +581,16 @@ int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int a } } - [[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); @@ -566,6 +599,15 @@ int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int a 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 @@ -594,6 +636,15 @@ int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int a 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; @@ -1211,13 +1262,25 @@ static int sock_eq(struct sockaddr* a, struct sockaddr* b) { } } +PrivateDnsModes convertEnumType(PrivateDnsMode privateDnsmode) { + switch (privateDnsmode) { + case PrivateDnsMode::OFF: + return PrivateDnsModes::PDM_OFF; + case PrivateDnsMode::OPPORTUNISTIC: + return PrivateDnsModes::PDM_OPPORTUNISTIC; + case PrivateDnsMode::STRICT: + return PrivateDnsModes::PDM_STRICT; + } + return PrivateDnsModes::PDM_UNKNOWN; +} + static int res_tls_send(res_state statp, const Slice query, const Slice answer, int* rcode, 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(convertEnumType(privateDnsStatus.mode)); if (privateDnsStatus.mode == PrivateDnsMode::OFF) { *fallback = true; @@ -1256,7 +1319,7 @@ static int res_tls_send(res_state statp, const Slice query, const Slice answer, 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); @@ -1298,9 +1361,11 @@ static int res_tls_send(res_state statp, const Slice query, const Slice answer, } 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); |
