Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da66be08 authored by Frank Li's avatar Frank Li Committed by android-build-merger
Browse files

Merge "Fill in each dns stats value in message NetworkDnsEventReported" am: a20c3cee3f

am: 3559090746

Change-Id: I5a8cd382c09925fdfee8f0a19a429de83cac0b1e
parents f194011a 9498178e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -199,6 +199,8 @@ cc_test {
        "libnetd_resolv",
        "libnetd_test_dnsresponder",
        "libnetdutils",
        "libprotobuf-cpp-lite",
        "server_configurable_flags",
        "stats_proto",
    ],
}
+5 −1
Original line number Diff line number Diff line
@@ -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 @@ bool Dns64Configuration::doRfc7050PrefixDiscovery(const android_net_context& net
    // 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("
+64 −38
Original line number Diff line number Diff line
@@ -299,17 +299,23 @@ bool parseQuery(const uint8_t* msg, size_t msgLen, uint16_t* query_id, int* rr_t
    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 @@ static bool sendaddrinfo(SocketClient* c, addrinfo* ai) {
    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 @@ void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinf
            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 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
    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 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
                   << ", 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 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
    }
    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 @@ void DnsProxyListener::ResNSendHandler::run() {
    // 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 @@ void DnsProxyListener::ResNSendHandler::run() {
        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 @@ void DnsProxyListener::ResNSendHandler::run() {
        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 @@ DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
    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 @@ void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, struc
    // 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 @@ void DnsProxyListener::GetHostByNameHandler::run() {
    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 @@ void DnsProxyListener::GetHostByNameHandler::run() {
                   << ", 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 @@ void DnsProxyListener::GetHostByNameHandler::run() {

    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 @@ DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
    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 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent
    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 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
    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 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
                   << ", 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 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
        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();
}
+5 −3
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ struct hostent;
namespace android {
namespace net {

class NetworkDnsEventReported;

class DnsProxyListener : public FrameworkListener {
  public:
    DnsProxyListener();
@@ -54,7 +56,7 @@ class DnsProxyListener : public FrameworkListener {
        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 @@ class DnsProxyListener : public FrameworkListener {
        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 @@ class DnsProxyListener : public FrameworkListener {
        void run();

      private:
        void doDns64ReverseLookup(hostent** hpp);
        void doDns64ReverseLookup(hostent** hpp, NetworkDnsEventReported* event);

        SocketClient* mClient;  // ref counted
        void* mAddress;         // address to lookup; owned
+27 −7
Original line number Diff line number Diff line
@@ -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 @@ std::list<DnsTlsServer> DnsTlsDispatcher::getOrderedServerList(
    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.
        }
    }
Loading