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

Commit 128183a5 authored by lifr's avatar lifr Committed by Frank Li
Browse files

Fix retry time value in dnsQueryEvent when perform DNS query over TCP

DNS queries over TCP can only be made once per server.
The retry time value of dnsQueryEvent on TCP should always be "0".
(Currently, it will populate the wrong value from the variable
"retryTimes".)

Bug: 147343838
Test: atest
Change-Id: I67b9602fcf9882e8035765e1598c16cf36bfb5e4
parent 731dc404
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -506,6 +506,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            const bool shouldRecordStats = (attempt == 0);
            int resplen;
            Stopwatch queryStopwatch;
            int retry_count_for_event = 0;
            if (useTcp) {
                // TCP; at most one attempt per server.
                attempt = retryTimes;
@@ -524,6 +525,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
                resplen = send_dg(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &useTcp,
                                  &gotsomewhere, &now, rcode, &delay);
                fallbackTCP = useTcp ? true : false;
                retry_count_for_event = attempt;
                LOG(INFO) << __func__ << ": used send_dg " << resplen;
            }

@@ -532,7 +534,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            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_retry_times(attempt);
            dnsQueryEvent->set_retry_times(retry_count_for_event);
            dnsQueryEvent->set_rcode(static_cast<NsRcode>(*rcode));
            dnsQueryEvent->set_protocol(query_proto);
            dnsQueryEvent->set_type(getQueryType(buf, buflen));
+296 −0
Original line number Diff line number Diff line
@@ -641,6 +641,179 @@ TEST_F(ResolvGetAddrInfoTest, ServerResponseError) {
// TODO: Add private DNS server timeout test.
TEST_F(ResolvGetAddrInfoTest, ServerTimeout) {
    constexpr char host_name[] = "hello.example.com.";
    // Following fields will not be verified during the test in proto NetworkDnsEventReported.
    // So don't need to config those values: event_type, return_code, latency_micros,
    // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
    // Expected_event is 16 DNS queries and only "type" and "retry_times" fields are changed.
    // 2(T_AAAA + T_A) * 2(w/ retry) * 2(query w/ and w/o domain) * 2(SOCK_DGRAM and SOCK_STREAM)
    constexpr char expected_event[] = R"Event(
             NetworkDnsEventReported {
             dns_query_events:
             {
               dns_query_event:[
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                }
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                }
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                }
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                }
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 255,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 1,
                 dns_server_index: 0,
                 connected: 0,
                },
               ]
             }
        })Event";
    test::DNSResponder dns(static_cast<ns_rcode>(-1) /*no response*/);
    dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
    dns.setResponseProbability(0.0);  // always ignore requests and don't response
@@ -651,6 +824,7 @@ TEST_F(ResolvGetAddrInfoTest, ServerTimeout) {
    const addrinfo hints = {.ai_family = AF_UNSPEC};
    NetworkDnsEventReported event;
    int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
    EXPECT_THAT(event, NetworkDnsEventEq(fromNetworkDnsEventReportedStr(expected_event)));
    EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
}

@@ -810,6 +984,128 @@ TEST_F(ResolvGetAddrInfoTest, MultiAnswerSections) {
    }
}

TEST_F(ResolvGetAddrInfoTest, TruncatedResponse) {
    // Following fields will not be verified during the test in proto NetworkDnsEventReported.
    // So don't need to config those values: event_type, return_code, latency_micros,
    // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
    constexpr char event_ipv4[] = R"Event(
             NetworkDnsEventReported {
             dns_query_events:
             {
               dns_query_event:[
                {
                 rcode: 254,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 0,
                 type: 1,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 2,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 0,
                 type: 1,
                 cache_hit: 2,
                 ip_version: 0,
                 protocol: 0,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                }
               ]
             }
        })Event";

    constexpr char event_ipv6[] = R"Event(
             NetworkDnsEventReported {
             dns_query_events:
             {
               dns_query_event:[
                {
                 rcode: 254,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 1,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 0,
                 type: 28,
                 cache_hit: 1,
                 ip_version: 1,
                 protocol: 2,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                },
                {
                 rcode: 0,
                 type: 28,
                 cache_hit: 2,
                 ip_version: 0,
                 protocol: 0,
                 retry_times: 0,
                 dns_server_index: 0,
                 connected: 0,
                }
               ]
             }
        })Event";

    test::DNSResponder dns;
    dns.addMapping(kHelloExampleCom, ns_type::ns_t_cname, kCnameA);
    dns.addMapping(kCnameA, ns_type::ns_t_cname, kCnameB);
    dns.addMapping(kCnameB, ns_type::ns_t_cname, kCnameC);
    dns.addMapping(kCnameC, ns_type::ns_t_cname, kCnameD);
    dns.addMapping(kCnameD, ns_type::ns_t_a, kHelloExampleComAddrV4);
    dns.addMapping(kCnameD, ns_type::ns_t_aaaa, kHelloExampleComAddrV6);
    ASSERT_TRUE(dns.startServer());
    ASSERT_EQ(0, SetResolvers());

    static const struct TestConfig {
        int ai_family;
        const std::string expected_addr;
        const std::string expected_event;
    } testConfigs[]{
            {AF_INET, kHelloExampleComAddrV4, event_ipv4},
            {AF_INET6, kHelloExampleComAddrV6, event_ipv6},
    };

    for (const auto& config : testConfigs) {
        SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
        dns.clearQueries();

        addrinfo* result = nullptr;
        const addrinfo hints = {.ai_family = config.ai_family};
        NetworkDnsEventReported event;
        int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
        EXPECT_THAT(event,
                    NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
        ScopedAddrinfo result_cleanup(result);
        EXPECT_EQ(rv, 0);
        EXPECT_TRUE(result != nullptr);
        // Expect UDP response is truncated. The resolver retries over TCP. See RFC 1035
        // section 4.2.1.
        EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_UDP, kHelloExampleCom), 1U);
        EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_TCP, kHelloExampleCom), 1U);
        EXPECT_EQ(ToString(result), config.expected_addr);
    }
}

TEST_F(GetHostByNameForNetContextTest, AlphabeticalHostname) {
    constexpr char host_name[] = "jiababuei.example.com.";
    constexpr char v4addr[] = "1.2.3.4";