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

Commit e8f970cd authored by Hungming Chen's avatar Hungming Chen
Browse files

resolv_integration_test: Retrieve NAT64 prefix through DNS event listener

Currently, the unit test could retrieve NAT64 prefix through registering a
DNS event listener. It doesn't need to query the prefix through the binder
interface method getPrefix64() anymore.

Test: built, flashed, booted
      system/netd/tests/runtests.sh passes

Change-Id: I54386f7d8c03f7009c12fe3fc39da85985d8d3ad
parent 41b82c41
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -25,23 +25,6 @@ aidl_interface {
    ],
}

cc_test_library {
    name: "libnetd_test_metrics_listener",
    defaults: ["netd_defaults"],
    srcs: [
        "tests/BaseTestMetricsListener.cpp",
        "tests/TestMetrics.cpp",
    ],
    include_dirs: [
        "system/netd/include",
    ],
    shared_libs: [
        "libbinder",
        "libutils",
        "netd_event_listener_interface-V1-cpp",
    ],
}

cc_library {
    name: "libnetd_resolv",
    version_script: "libnetd_resolv.map.txt",
+4 −5
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@
#include <gtest/gtest.h>
#include <netdutils/Stopwatch.h>
#include <openssl/base64.h>
#include "tests/BaseTestMetricsListener.h"
#include "tests/TestMetrics.h"

#include "tests/dns_metrics_listener/base_metrics_listener.h"
#include "tests/dns_metrics_listener/test_metrics.h"

#include "NetdConstants.h"  // SHA256_SIZE
#include "ResolverStats.h"
@@ -153,9 +154,7 @@ TEST_F(DnsResolverBinderTest, RegisterEventListener_NullListener) {
}

TEST_F(DnsResolverBinderTest, RegisterEventListener_DuplicateSubscription) {
    class DummyListener : public android::net::metrics::BaseTestMetricsListener {
        bool isVerified() override { return true; }  // unused
    };
    class DummyListener : public android::net::metrics::BaseMetricsListener {};

    // Expect to subscribe successfully.
    android::sp<DummyListener> dummyListener = new DummyListener();
+54 −35
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <android/multinetwork.h>  // ResNsendFlags
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <binder/ProcessState.h>
#include <cutils/sockets.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
@@ -57,6 +58,7 @@
#include "netdutils/ResponseCode.h"
#include "netdutils/SocketOption.h"
#include "netid_client.h"  // NETID_UNSET
#include "tests/dns_metrics_listener/dns_metrics_listener.h"
#include "tests/resolv_test_utils.h"

// Valid VPN netId range is 100 ~ 65535
@@ -73,6 +75,7 @@ using android::base::ParseInt;
using android::base::StringPrintf;
using android::base::unique_fd;
using android::net::ResolverStats;
using android::net::metrics::DnsMetricsListener;
using android::netdutils::enableSockopt;
using android::netdutils::ResponseCode;

@@ -91,6 +94,20 @@ ScopedAddrinfo safe_getaddrinfo(const char* node, const char* service,
}  // namespace

class ResolverTest : public ::testing::Test {
  public:
    ResolverTest() {
        // Use a shared static DNS listener for all tests to avoid registering lots of listeners
        // which may be released late until process terminated. Currently, registered DNS listener
        // is removed by binder death notification which is fired when the process hosting an
        // IBinder has gone away. If every test in ResolverTest registers its DNS listener, Netd
        // may temporarily hold lots of dead listeners until the unit test process terminates.
        // TODO: Perhaps add an unregistering listener binder call or fork a listener process which
        // could be terminated earlier.
        static android::sp<DnsMetricsListener> listener =
                new DnsMetricsListener(TEST_NETID /*monitor specific network*/);
        mDnsMetricsListener = listener;
    }

  protected:
    struct DnsRecord {
        std::string host_name;  // host name
@@ -98,25 +115,21 @@ class ResolverTest : public ::testing::Test {
        std::string addr;       // ipv4/v6 address
    };

    void SetUp() { mDnsClient.SetUp(); }
    void TearDown() {
        mDnsClient.TearDown();
    }
    void SetUp() {
        mDnsClient.SetUp();

    bool WaitForPrefix64Detected(int netId, int timeoutMs) {
        constexpr int intervalMs = 2;
        const int limit = timeoutMs / intervalMs;
        for (int count = 0; count <= limit; ++count) {
            std::string prefix;
            auto rv = mDnsClient.resolvService()->getPrefix64(netId, &prefix);
            if (rv.isOk()) {
                return true;
            }
            usleep(intervalMs * 1000);
        }
        return false;
        // Register the shared static DNS listener which may have been registered in previous test
        // ResolverTest.
        // TODO: Move the registration to SetUpTestCase which is called once before the first test.
        auto status = mDnsClient.resolvService()->registerEventListener(mDnsMetricsListener);
        ASSERT_TRUE(status.isOk() || status.serviceSpecificErrorCode() == EEXIST /*ignore*/);

        // Start the binder thread pool for listening DNS metrics events.
        android::ProcessState::self()->startThreadPool();
    }

    void TearDown() { mDnsClient.TearDown(); }

    void StartDns(test::DNSResponder& dns, const std::vector<DnsRecord>& records) {
        for (const auto& r : records) {
            dns.addMapping(r.host_name, r.type, r.addr);
@@ -126,7 +139,13 @@ class ResolverTest : public ::testing::Test {
        dns.clearQueries();
    }

    bool WaitForNat64Prefix(ExpectNat64PrefixStatus status,
                            std::chrono::milliseconds timeout = std::chrono::milliseconds(1000)) {
        return mDnsMetricsListener->waitForNat64Prefix(status, timeout);
    }

    DnsResponderClient mDnsClient;
    android::sp<DnsMetricsListener> mDnsMetricsListener;  // Initialized in constructor.

    static constexpr char kLocalHost[] = "localhost";
    static constexpr char kLocalHostAddr[] = "127.0.0.1";
@@ -2368,7 +2387,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64Synthesize) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // hints are necessary in order to let netd know which type of addresses the caller is
    // interested in.
@@ -2384,7 +2403,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64Synthesize) {

    // Stopping NAT64 prefix discovery disables synthesis.
    EXPECT_TRUE(mDnsClient.resolvService()->stopPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_FALSE(WaitForPrefix64Detected(TEST_NETID, 300));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_NOT_FOUND));

    dns.clearQueries();

@@ -2414,7 +2433,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64QuerySpecified) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Ensure to synthesize AAAA if AF_INET6 is specified, and not to synthesize AAAA
    // in AF_INET case.
@@ -2451,7 +2470,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64QueryUnspecifiedV6) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    const addrinfo hints = {.ai_family = AF_UNSPEC};
    ScopedAddrinfo result = safe_getaddrinfo("v4v6", nullptr, &hints);
@@ -2482,7 +2501,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64QueryUnspecifiedNoV6) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    const addrinfo hints = {.ai_family = AF_UNSPEC};
    ScopedAddrinfo result = safe_getaddrinfo("v4v6", nullptr, &hints);
@@ -2517,7 +2536,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64QuerySpecialUseIPv4Addresses) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    static const struct TestConfig {
        std::string name;
@@ -2580,7 +2599,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64QueryWithNullArgumentHints) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Assign argument hints of getaddrinfo() as null is equivalent to set ai_family AF_UNSPEC.
    // In AF_UNSPEC case, synthesize AAAA if there has A answer only.
@@ -2621,7 +2640,7 @@ TEST_F(ResolverTest, GetAddrInfo_Dns64QueryNullArgumentNode) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // If node is null, return address is listed by libc/getaddrinfo.c as follows.
    // - passive socket -> anyaddr (0.0.0.0 or ::)
@@ -2701,7 +2720,7 @@ TEST_F(ResolverTest, GetHostByAddr_ReverseDnsQueryWithHavingNat64Prefix) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Reverse IPv4 DNS query. Prefix should have no effect on it.
    inet_pton(AF_INET, "1.2.3.4", &v4addr);
@@ -2745,7 +2764,7 @@ TEST_F(ResolverTest, GetHostByAddr_ReverseDns64Query) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Synthesized PTR record doesn't exist on DNS server
    // Reverse IPv6 DNS64 query while DNS server doesn't have an answer for synthesized address.
@@ -2791,7 +2810,7 @@ TEST_F(ResolverTest, GetHostByAddr_ReverseDns64QueryFromHostFile) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Using synthesized "localhost" address to be a trick for resolving host name
    // from host file /etc/hosts and "localhost" is the only name in /etc/hosts. Note that this is
@@ -2833,7 +2852,7 @@ TEST_F(ResolverTest, GetNameInfo_ReverseDnsQueryWithHavingNat64Prefix) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    static const struct TestConfig {
        int flag;
@@ -2912,7 +2931,7 @@ TEST_F(ResolverTest, GetNameInfo_ReverseDns64Query) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    static const struct TestConfig {
        bool hasSynthesizedPtrRecord;
@@ -2982,7 +3001,7 @@ TEST_F(ResolverTest, GetNameInfo_ReverseDns64QueryFromHostFile) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Using synthesized "localhost" address to be a trick for resolving host name
    // from host file /etc/hosts and "localhost" is the only name in /etc/hosts. Note that this is
@@ -3016,7 +3035,7 @@ TEST_F(ResolverTest, GetHostByName2_Dns64Synthesize) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Query an IPv4-only hostname. Expect that gets a synthesized address.
    struct hostent* result = gethostbyname2("ipv4only", AF_INET6);
@@ -3043,7 +3062,7 @@ TEST_F(ResolverTest, GetHostByName2_DnsQueryWithHavingNat64Prefix) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // IPv4 DNS query. Prefix should have no effect on it.
    struct hostent* result = gethostbyname2("v4v6", AF_INET);
@@ -3084,7 +3103,7 @@ TEST_F(ResolverTest, GetHostByName2_Dns64QuerySpecialUseIPv4Addresses) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    static const struct TestConfig {
        std::string name;
@@ -3140,7 +3159,7 @@ TEST_F(ResolverTest, PrefixDiscoveryBypassTls) {

    // Start NAT64 prefix discovery and wait for it complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Verify it bypassed TLS even though there's a TLS server available.
    EXPECT_EQ(0, tls.queries());
@@ -3159,7 +3178,7 @@ TEST_F(ResolverTest, PrefixDiscoveryBypassTls) {

    // Start NAT64 prefix discovery and wait for it to complete.
    EXPECT_TRUE(mDnsClient.resolvService()->startPrefix64Discovery(TEST_NETID).isOk());
    EXPECT_TRUE(WaitForPrefix64Detected(TEST_NETID, 1000));
    EXPECT_TRUE(WaitForNat64Prefix(EXPECT_FOUND));

    // Verify it bypassed TLS despite STRICT mode.
    EXPECT_EQ(0, tls.queries());

tests/BaseTestMetricsListener.h

deleted100644 → 0
+0 −104
Original line number Diff line number Diff line
/**
 * Copyright (c) 2019, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _BASE_TEST_METRICS_LISTENER_H_
#define _BASE_TEST_METRICS_LISTENER_H_

#include <string>
#include <vector>

#include <binder/BinderService.h>

#include "android/net/metrics/BnNetdEventListener.h"

enum EventFlag : uint32_t {
    onDnsEvent = 1 << 0,
    onPrivateDnsValidationEvent = 1 << 1,
    onConnectEvent = 1 << 2,
    onWakeupEvent = 1 << 3,
    onTcpSocketStatsEvent = 1 << 4,
    onNat64PrefixEvent = 1 << 5,
};

namespace android {
namespace net {
namespace metrics {

class BaseTestMetricsListener : public BnNetdEventListener {
  public:
    BaseTestMetricsListener() = default;
    ~BaseTestMetricsListener() = default;

    // Returns TRUE if the verification was successful. Otherwise, returns FALSE.
    virtual bool isVerified() = 0;

    std::condition_variable& getCv() { return mCv; }
    std::mutex& getCvMutex() { return mCvMutex; }

    android::binder::Status onDnsEvent(int32_t /*netId*/, int32_t /*eventType*/,
                                       int32_t /*returnCode*/, int32_t /*latencyMs*/,
                                       const std::string& /*hostname*/,
                                       const ::std::vector<std::string>& /*ipAddresses*/,
                                       int32_t /*ipAddressesCount*/, int32_t /*uid*/) override;
    android::binder::Status onPrivateDnsValidationEvent(int32_t /*netId*/,
                                                        const ::android::String16& /*ipAddress*/,
                                                        const ::android::String16& /*hostname*/,
                                                        bool /*validated*/) override;
    android::binder::Status onConnectEvent(int32_t /*netId*/, int32_t /*error*/,
                                           int32_t /*latencyMs*/,
                                           const ::android::String16& /*ipAddr*/, int32_t /*port*/,
                                           int32_t /*uid*/) override;
    android::binder::Status onWakeupEvent(const ::android::String16& /*prefix*/, int32_t /*uid*/,
                                          int32_t /*ethertype*/, int32_t /*ipNextHeader*/,
                                          const ::std::vector<uint8_t>& /*dstHw*/,
                                          const ::android::String16& /*srcIp*/,
                                          const ::android::String16& /*dstIp*/, int32_t /*srcPort*/,
                                          int32_t /*dstPort*/, int64_t /*timestampNs*/) override;
    android::binder::Status onTcpSocketStatsEvent(
            const ::std::vector<int32_t>& /*networkIds*/,
            const ::std::vector<int32_t>& /*sentPackets*/,
            const ::std::vector<int32_t>& /*lostPackets*/, const ::std::vector<int32_t>& /*rttUs*/,
            const ::std::vector<int32_t>& /*sentAckDiffMs*/) override;
    android::binder::Status onNat64PrefixEvent(int32_t /*netId*/, bool /*added*/,
                                               const ::std::string& /*prefixString*/,
                                               int32_t /*prefixLength*/) override;

  private:
    // The verified event(s) as a bitwise-OR combination of enum EventFlag flags.
    uint32_t mVerified{};

    // This lock prevents racing condition between signaling thread(s) and waiting thread(s).
    std::mutex mCvMutex;

    // Condition variable signaled when notify() is called.
    std::condition_variable mCv;

  protected:
    // Notify who is waiting for test results. See also mCvMutex and mCv.
    void notify();

    // Get current verified event(s).
    uint32_t getVerified() const { return mVerified; }

    // Set the specific event as verified if its verification was successful.
    void setVerified(EventFlag event);
};

}  // namespace metrics
}  // namespace net
}  // namespace android

#endif  // _BASE_TEST_METRICS_LISTENER_H_
+17 −0
Original line number Diff line number Diff line
cc_test_library {
    name: "libnetd_test_metrics_listener",
    defaults: ["netd_defaults"],
    srcs: [
        "base_metrics_listener.cpp",
        "dns_metrics_listener.cpp",
        "test_metrics.cpp",
    ],
    shared_libs: [
        "libbase",
        "libbinder",
        "libutils",
    ],
    static_libs: [
        "netd_event_listener_interface-V1-cpp",
    ],
}
 No newline at end of file
Loading