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

Commit 01c7787a authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6224475 from a64455b6 to rvc-release

Change-Id: I52f27f1a40cacca9f5f693056adcc8b4ceadc913
parents af0eb5ec a64455b6
Loading
Loading
Loading
Loading
+51 −59
Original line number Diff line number Diff line
@@ -984,9 +984,10 @@ struct NetConfig {
        dns_event_subsampling_map = resolv_get_dns_event_subsampling_map();
    }

    int nameserverCount() { return nameserverSockAddrs.size(); }

    const unsigned netid;
    std::unique_ptr<Cache> cache;
    int nscount = 0;
    std::vector<std::string> nameservers;
    std::vector<IPSockAddr> nameserverSockAddrs;
    int revision_id = 0;  // # times the nameservers have been replaced
@@ -1442,7 +1443,7 @@ static void res_cache_clear_stats_locked(NetConfig* netconfig);
bool resolv_has_nameservers(unsigned netid) {
    std::lock_guard guard(cache_mutex);
    NetConfig* info = find_netconfig_locked(netid);
    return (info != nullptr) && (info->nscount > 0);
    return (info != nullptr) && (info->nameserverCount() > 0);
}

int resolv_create_cache_for_net(unsigned netid) {
@@ -1603,7 +1604,6 @@ int resolv_set_nameservers(
                      << ", addr = " << netconfig->nameservers[i];
        }
        netconfig->nameserverSockAddrs = std::move(ipSockAddrs);
        netconfig->nscount = numservers;
    } else {
        if (netconfig->params.max_samples != old_max_samples) {
            // If the maximum number of samples changes, the overhead of keeping the most recent
@@ -1655,7 +1655,6 @@ static bool resolv_is_nameservers_equal(const std::vector<std::string>& oldServe
}

static void free_nameservers_locked(NetConfig* netconfig) {
    netconfig->nscount = 0;
    netconfig->nameservers.clear();
    netconfig->nameserverSockAddrs.clear();
    res_cache_clear_stats_locked(netconfig);
@@ -1671,21 +1670,7 @@ void resolv_populate_res_for_net(ResState* statp) {
    NetConfig* info = find_netconfig_locked(statp->netid);
    if (info == nullptr) return;

    // TODO: Convert nsaddrs[] to c++ container and remove the size-checking.
    const int serverNum = std::min(MAXNS, static_cast<int>(info->nameserverSockAddrs.size()));

    for (int nserv = 0; nserv < serverNum; nserv++) {
        sockaddr_storage ss = info->nameserverSockAddrs.at(nserv);

        if (auto sockaddr_len = sockaddrSize(ss); sockaddr_len != 0) {
            memcpy(&statp->nsaddrs[nserv], &ss, sockaddr_len);
        } else {
            LOG(WARNING) << __func__ << ": can't get sa_len from "
                         << info->nameserverSockAddrs.at(nserv);
        }
    }

    statp->nscount = serverNum;
    statp->nsaddrs = info->nameserverSockAddrs;
    statp->search_domains = info->search_domains;
    statp->tc_mode = info->tc_mode;
}
@@ -1725,42 +1710,32 @@ int android_net_res_stats_get_info_for_net(unsigned netid, int* nscount,
                                           char domains[MAXDNSRCH][MAXDNSRCHPATH],
                                           res_params* params, struct res_stats stats[MAXNS],
                                           int* wait_for_pending_req_timeout_count) {
    int revision_id = -1;
    std::lock_guard guard(cache_mutex);

    NetConfig* info = find_netconfig_locked(netid);
    if (info) {
        if (info->nscount > MAXNS) {
            LOG(INFO) << __func__ << ": nscount " << info->nscount << " > MAXNS " << MAXNS;
            errno = EFAULT;
            return -1;
        }
        int i;
        *nscount = info->nscount;
    if (!info) return -1;

        // It shouldn't happen, but just in case of buffer overflow.
        if (info->nscount != static_cast<int>(info->nameserverSockAddrs.size())) {
            LOG(INFO) << __func__ << ": nscount " << info->nscount
                      << " != " << info->nameserverSockAddrs.size();
    const int num = info->nameserverCount();
    if (num > MAXNS) {
        LOG(INFO) << __func__ << ": nscount " << num << " > MAXNS " << MAXNS;
        errno = EFAULT;
        return -1;
    }

        for (i = 0; i < info->nscount; i++) {
            servers[i] = info->nameserverSockAddrs.at(i);
    for (int i = 0; i < num; i++) {
        servers[i] = info->nameserverSockAddrs[i];
        stats[i] = info->nsstats[i];
    }

        for (i = 0; i < static_cast<int>(info->search_domains.size()); i++) {
    for (size_t i = 0; i < info->search_domains.size(); i++) {
        strlcpy(domains[i], info->search_domains[i].c_str(), MAXDNSRCHPATH);
    }
        *dcount = i;

    *nscount = num;
    *dcount = static_cast<int>(info->search_domains.size());
    *params = info->params;
        revision_id = info->revision_id;
    *wait_for_pending_req_timeout_count = info->wait_for_pending_req_timeout_count;
    }

    return revision_id;
    return info->revision_id;
}

std::vector<std::string> resolv_cache_dump_subsampling_map(unsigned netid) {
@@ -1799,30 +1774,47 @@ uint32_t resolv_cache_get_subsampling_denom(unsigned netid, int return_code) {
    return denom;
}

int resolv_cache_get_resolver_stats(unsigned netid, res_params* params, res_stats stats[MAXNS]) {
int resolv_cache_get_resolver_stats(unsigned netid, res_params* params, res_stats stats[MAXNS],
                                    const std::vector<IPSockAddr>& serverSockAddrs) {
    std::lock_guard guard(cache_mutex);
    NetConfig* info = find_netconfig_locked(netid);
    if (info) {
        memcpy(stats, info->nsstats, sizeof(info->nsstats));
        *params = info->params;
        return info->revision_id;
    }
    if (!info) return -1;

    for (size_t i = 0; i < serverSockAddrs.size(); i++) {
        for (size_t j = 0; j < info->nameserverSockAddrs.size(); j++) {
            // Should never happen. Just in case because of the fix-sized array |stats|.
            if (j >= MAXNS) {
                LOG(WARNING) << __func__ << ": unexpected size " << j;
                return -1;
            }

void resolv_cache_add_resolver_stats_sample(unsigned netid, int revision_id, const sockaddr* sa,
            // It's possible that the server is not found, e.g. when a new list of nameservers
            // is updated to the NetConfig just after this look up thread being populated.
            // Keep the server valid as-is (by means of keeping stats[i] unset), but we should
            // think about if there's a better way.
            if (info->nameserverSockAddrs[j] == serverSockAddrs[i]) {
                stats[i] = info->nsstats[j];
                break;
            }
        }
    }

    *params = info->params;
    return info->revision_id;
}

void resolv_cache_add_resolver_stats_sample(unsigned netid, int revision_id,
                                            const IPSockAddr& serverSockAddr,
                                            const res_sample& sample, int max_samples) {
    if (max_samples <= 0 || sa == nullptr) return;
    if (max_samples <= 0) return;

    std::lock_guard guard(cache_mutex);
    NetConfig* info = find_netconfig_locked(netid);

    if (info && info->revision_id == revision_id) {
        const int serverNum = std::min(MAXNS, static_cast<int>(info->nameserverSockAddrs.size()));
        const IPSockAddr ipsa = IPSockAddr::toIPSockAddr(*sa);
        for (int ns = 0; ns < serverNum; ns++) {
            if (ipsa == info->nameserverSockAddrs.at(ns)) {
            if (serverSockAddr == info->nameserverSockAddrs[ns]) {
                res_cache_add_stats_sample_locked(&info->nsstats[ns], sample, max_samples);
                return;
            }
+0 −10
Original line number Diff line number Diff line
@@ -97,17 +97,7 @@ void res_init(ResState* statp, const struct android_net_context* _Nonnull netcon
    statp->netid = netcontext->dns_netid;
    statp->uid = netcontext->uid;
    statp->pid = netcontext->pid;
    statp->nscount = 1;
    statp->id = arc4random_uniform(65536);
    // The following dummy initialization is probably useless because
    // it's overwritten later by resolv_populate_res_for_net().
    // TODO: check if it's safe to remove.
    const sockaddr_union u{
            .sin.sin_addr.s_addr = INADDR_ANY,
            .sin.sin_family = AF_INET,
            .sin.sin_port = htons(NAMESERVER_PORT),
    };
    memcpy(&statp->nsaddrs, &u, sizeof(u));

    for (auto& sock : statp->nssocks) {
        sock.reset();
+49 −44
Original line number Diff line number Diff line
@@ -138,11 +138,13 @@ using android::netdutils::Stopwatch;

static DnsTlsDispatcher sDnsTlsDispatcher;

static struct sockaddr* get_nsaddr(res_state, size_t);
static int send_vc(res_state, res_params* params, const uint8_t*, int, uint8_t*, int, int*, int,
                   time_t*, int*, int*);
static int send_dg(res_state, res_params* params, const uint8_t*, int, uint8_t*, int, int*, int,
                   int*, int*, time_t*, int*, int*);
static int send_vc(res_state statp, res_params* params, const uint8_t* buf, int buflen,
                   uint8_t* ans, int anssiz, int* terrno, size_t ns, time_t* at, int* rcode,
                   int* delay);
static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int buflen,
                   uint8_t* ans, int anssiz, int* terrno, size_t ns, int* v_circuit,
                   int* gotsomewhere, time_t* at, int* rcode, int* delay);

static void dump_error(const char*, const struct sockaddr*, int);

static int sock_eq(struct sockaddr*, struct sockaddr*);
@@ -288,13 +290,13 @@ static void res_set_usable_server(int selectedServer, int nscount, bool usable_s
static bool res_ourserver_p(res_state statp, const sockaddr* sa) {
    const sockaddr_in *inp, *srv;
    const sockaddr_in6 *in6p, *srv6;
    int ns;

    switch (sa->sa_family) {
        case AF_INET:
            inp = (const struct sockaddr_in*) (const void*) sa;
            for (ns = 0; ns < statp->nscount; ns++) {
                srv = (struct sockaddr_in*) (void*) get_nsaddr(statp, (size_t) ns);
            for (const IPSockAddr& ipsa : statp->nsaddrs) {
                sockaddr_storage ss = ipsa;
                srv = reinterpret_cast<sockaddr_in*>(&ss);
                if (srv->sin_family == inp->sin_family && srv->sin_port == inp->sin_port &&
                    (srv->sin_addr.s_addr == INADDR_ANY ||
                     srv->sin_addr.s_addr == inp->sin_addr.s_addr))
@@ -303,8 +305,9 @@ static bool res_ourserver_p(res_state statp, const sockaddr* sa) {
            break;
        case AF_INET6:
            in6p = (const struct sockaddr_in6*) (const void*) sa;
            for (ns = 0; ns < statp->nscount; ns++) {
                srv6 = (struct sockaddr_in6*) (void*) get_nsaddr(statp, (size_t) ns);
            for (const IPSockAddr& ipsa : statp->nsaddrs) {
                sockaddr_storage ss = ipsa;
                srv6 = reinterpret_cast<sockaddr_in6*>(&ss);
                if (srv6->sin6_family == in6p->sin6_family && srv6->sin6_port == in6p->sin6_port &&
#ifdef HAVE_SIN6_SCOPE_ID
                    (srv6->sin6_scope_id == 0 || srv6->sin6_scope_id == in6p->sin6_scope_id) &&
@@ -427,7 +430,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
        // data so the normal resolve path can do its thing
        resolv_populate_res_for_net(statp);
    }
    if (statp->nscount == 0) {
    if (statp->nameserverCount() == 0) {
        // We have no nameservers configured, so there's no point trying.
        // Tell the cache the query failed, or any retries and anyone else asking the same
        // question will block for PENDING_REQUEST_TIMEOUT seconds instead of failing fast.
@@ -457,9 +460,9 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
        }
    }

    res_stats stats[MAXNS];
    res_stats stats[MAXNS]{};
    res_params params;
    int revision_id = resolv_cache_get_resolver_stats(statp->netid, &params, stats);
    int revision_id = resolv_cache_get_resolver_stats(statp->netid, &params, stats, statp->nsaddrs);
    if (revision_id < 0) {
        // TODO: Remove errno once callers stop using it
        errno = ESRCH;
@@ -467,14 +470,14 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
    }
    bool usable_servers[MAXNS];
    int usableServersCount = android_net_res_stats_get_usable_servers(
            &params, stats, statp->nscount, usable_servers);
            &params, stats, statp->nameserverCount(), usable_servers);

    if ((flags & ANDROID_RESOLV_NO_RETRY) && usableServersCount > 1) {
        auto hp = reinterpret_cast<const HEADER*>(buf);

        // Select a random server based on the query id
        int selectedServer = (hp->id % usableServersCount) + 1;
        res_set_usable_server(selectedServer, statp->nscount, usable_servers);
        res_set_usable_server(selectedServer, statp->nameserverCount(), usable_servers);
    }

    // Send request, RETRY times, or until successful.
@@ -484,20 +487,15 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
    int terrno = ETIMEDOUT;

    for (int attempt = 0; attempt < retryTimes; ++attempt) {
        for (int ns = 0; ns < statp->nscount; ++ns) {
        for (size_t ns = 0; ns < statp->nsaddrs.size(); ++ns) {
            if (!usable_servers[ns]) continue;

            *rcode = RCODE_INTERNAL_ERROR;

            // Get server addr
            const sockaddr* nsap = get_nsaddr(statp, ns);
            const int nsaplen = sockaddrSize(nsap);

            static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
            char abuf[NI_MAXHOST];
            if (getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), NULL, 0, niflags) == 0)
            const IPSockAddr& serverSockAddr = statp->nsaddrs[ns];
            LOG(DEBUG) << __func__ << ": Querying server (# " << ns + 1
                           << ") address = " << abuf;
                       << ") address = " << serverSockAddr.toString();

            ::android::net::Protocol query_proto = useTcp ? PROTO_TCP : PROTO_UDP;
            time_t now = 0;
@@ -533,7 +531,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            dnsQueryEvent->set_cache_hit(static_cast<CacheStatus>(cache_status));
            dnsQueryEvent->set_latency_micros(saturate_cast<int32_t>(queryStopwatch.timeTakenUs()));
            dnsQueryEvent->set_dns_server_index(ns);
            dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(nsap->sa_family));
            dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(serverSockAddr.family()));
            dnsQueryEvent->set_retry_times(retry_count_for_event);
            dnsQueryEvent->set_rcode(static_cast<NsRcode>(*rcode));
            dnsQueryEvent->set_protocol(query_proto);
@@ -544,10 +542,10 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            // SERVFAIL or times out) do not unduly affect the stats.
            if (shouldRecordStats) {
                res_sample sample;
                _res_stats_set_sample(&sample, now, *rcode, delay);
                resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample,
                                                       params.max_samples);
                resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent);
                res_stats_set_sample(&sample, now, *rcode, delay);
                resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, serverSockAddr,
                                                       sample, params.max_samples);
                resolv_stats_add(statp->netid, serverSockAddr, dnsQueryEvent);
            }

            if (resplen == 0) continue;
@@ -582,12 +580,6 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
    return -terrno;
}

/* Private */

static struct sockaddr* get_nsaddr(res_state statp, size_t n) {
    return (struct sockaddr*)(void*)&statp->nsaddrs[n];
}

static struct timespec get_timeout(res_state statp, const res_params* params, const int ns) {
    int msec;
    // Legacy algorithm which scales the timeout by nameserver number.
@@ -595,7 +587,7 @@ static struct timespec get_timeout(res_state statp, const res_params* params, co
    // This has no effect with 1 or 2 nameservers
    msec = params->base_timeout_msec << ns;
    if (ns > 0) {
        msec /= statp->nscount;
        msec /= statp->nameserverCount();
    }
    // For safety, don't allow OEMs and experiments to configure a timeout shorter than 1s.
    if (msec < 1000) {
@@ -610,7 +602,7 @@ static struct timespec get_timeout(res_state statp, const res_params* params, co
}

static int send_vc(res_state statp, res_params* params, const uint8_t* buf, int buflen,
                   uint8_t* ans, int anssiz, int* terrno, int ns, time_t* at, int* rcode,
                   uint8_t* ans, int anssiz, int* terrno, size_t ns, time_t* at, int* rcode,
                   int* delay) {
    *at = time(NULL);
    *delay = 0;
@@ -623,7 +615,14 @@ static int send_vc(res_state statp, res_params* params, const uint8_t* buf, int

    LOG(INFO) << __func__ << ": using send_vc";

    nsap = get_nsaddr(statp, (size_t) ns);
    // It should never happen, but just in case.
    if (ns >= statp->nsaddrs.size()) {
        LOG(ERROR) << __func__ << ": Out-of-bound indexing: " << ns;
        return -1;
    }

    sockaddr_storage ss = statp->nsaddrs[ns];
    nsap = reinterpret_cast<sockaddr*>(&ss);
    nsaplen = sockaddrSize(nsap);

    connreset = 0;
@@ -804,7 +803,7 @@ read_len:
     */
    if (resplen > 0) {
        struct timespec done = evNowTime();
        *delay = _res_stats_calculate_rtt(&done, &now);
        *delay = res_stats_calculate_rtt(&done, &now);
        *rcode = anhp->rcode;
    }
    return (resplen);
@@ -897,12 +896,18 @@ bool ignoreInvalidAnswer(res_state statp, const sockaddr_storage& from, const ui
}

static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int buflen,
                   uint8_t* ans, int anssiz, int* terrno, int ns, int* v_circuit, int* gotsomewhere,
                   time_t* at, int* rcode, int* delay) {
                   uint8_t* ans, int anssiz, int* terrno, size_t ns, int* v_circuit,
                   int* gotsomewhere, time_t* at, int* rcode, int* delay) {
    // It should never happen, but just in case.
    if (ns >= statp->nsaddrs.size()) {
        LOG(ERROR) << __func__ << ": Out-of-bound indexing: " << ns;
        return -1;
    }

    *at = time(nullptr);
    *delay = 0;

    const sockaddr* nsap = get_nsaddr(statp, (size_t)ns);
    const sockaddr_storage ss = statp->nsaddrs[ns];
    const sockaddr* nsap = reinterpret_cast<const sockaddr*>(&ss);
    const int nsaplen = sockaddrSize(nsap);

    if (statp->nssocks[ns] == -1) {
@@ -1007,7 +1012,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
        }

        timespec done = evNowTime();
        *delay = _res_stats_calculate_rtt(&done, &now);
        *delay = res_stats_calculate_rtt(&done, &now);
        if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || anhp->rcode == REFUSED) {
            LOG(DEBUG) << __func__ << ": server rejected query:";
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
+2 −2
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@
#include "stats.h"

// Calculate the round-trip-time from start time t0 and end time t1.
int _res_stats_calculate_rtt(const timespec* t1, const timespec* t0) {
int res_stats_calculate_rtt(const timespec* t1, const timespec* t0) {
    // Divide ns by one million to get ms, multiply s by thousand to get ms (obvious)
    long ms0 = t0->tv_sec * 1000 + t0->tv_nsec / 1000000;
    long ms1 = t1->tv_sec * 1000 + t1->tv_nsec / 1000000;
@@ -32,7 +32,7 @@ int _res_stats_calculate_rtt(const timespec* t1, const timespec* t0) {
}

// Create a sample for calculating server reachability statistics.
void _res_stats_set_sample(res_sample* sample, time_t now, int rcode, int rtt) {
void res_stats_set_sample(res_sample* sample, time_t now, int rcode, int rtt) {
    LOG(INFO) << __func__ << ": rcode = " << rcode << ", sec = " << rtt;
    sample->at = now;
    sample->rcode = rcode;
+15 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@

#include "ResolverStats.h"
#include "params.h"
#include "stats.h"

// Sets the name server addresses to the provided ResState.
// The name servers are retrieved from the cache which is associated
@@ -115,3 +116,17 @@ void resolv_stats_dump(android::netdutils::DumpWriter& dw, unsigned netid);
void resolv_oem_options_dump(android::netdutils::DumpWriter& dw, unsigned netid);

const char* tc_mode_to_str(const int mode);

/* Retrieve a local copy of the stats for the given netid. The buffer must have space for
 * MAXNS __resolver_stats. Returns the revision id of the resolvers used.
 */
int resolv_cache_get_resolver_stats(
        unsigned netid, res_params* params, res_stats stats[MAXNS],
        const std::vector<android::netdutils::IPSockAddr>& serverSockAddrs);

/* Add a sample to the shared struct for the given netid and server, provided that the
 * revision_id of the stored servers has not changed.
 */
void resolv_cache_add_resolver_stats_sample(unsigned netid, int revision_id,
                                            const android::netdutils::IPSockAddr& serverSockAddr,
                                            const res_sample& sample, int max_samples);
Loading