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

Commit 5f01f311 authored by Ken Chen's avatar Ken Chen
Browse files

Read DNS query log settings from system property

Currently, we need to provide a special build of the image for carrier
testing, so that we can find out which apps are using DNS queries
when the device idle. In fact, DnsQueryLog already can dump the required
information, but lacks the interface to set the number of records. The
default number of records 200 may not be enough for a 24 hours idle
test. This commit enables DNS resolver to read the record setting from
system properties, which is limited to 0 ~ 10000.

Dumping DnsQueryLog requires root permission. There is no privacy
concern in production builds.

Bug: 279596912
Bug: 231264474
Bug: 200748696
Test: Run script like this to trigger 400 DNS queries
      #!/bin/bash
      for ((i=1; i<=400; i++))
      do
          hostname="http://example${i}.com"
          adb shell am start -a android.intent.action.VIEW -d "$hostname"
          sleep 1
      done

      $adb root; chmod +x run_dns_queries.sh; ./run_dns_queries.sh
      $adb shell dumpsys dnsresolver querylog | grep time | wc -l
      200

      $adb shell setprop persist.net.dns_query_log_size 3
      $adb reboot
      $adb root; chmod +x run_dns_queries.sh; ./run_dns_queries.sh
      $adb shell dumpsys dnsresolver querylog | grep time | wc -l
      3

      $adb shell setprop persist.net.dns_query_log_size 300
      $adb reboot
      $adb root; chmod +x run_dns_queries.sh; ./run_dns_queries.sh
      $adb shell dumpsys dnsresolver querylog | grep time | wc -l
      300

Change-Id: Ic8fbe7e3ec52e1901fea9962d1c7564152693fc3
parent 9c71c8b5
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -51,6 +51,12 @@ void DnsQueryLog::push(Record&& record) {
    mQueue.push(std::move(record));
}

uint64_t DnsQueryLog::getLogSizeFromSysProp() {
    const uint64_t logSize = android::base::GetUintProperty<uint64_t>(
            "persist.net.dns_query_log_size", kDefaultLogSize);
    return logSize <= kMaxLogSize ? logSize : kDefaultLogSize;
}

void DnsQueryLog::dump(netdutils::DumpWriter& dw) const {
    dw.println("DNS query log (last %lld minutes):", (mValidityTimeMs / 60000).count());
    netdutils::ScopedIndent indentStats(dw);
+7 −2
Original line number Diff line number Diff line
@@ -49,9 +49,10 @@ class DnsQueryLog {
        const int timeTaken;
    };

    DnsQueryLog() : DnsQueryLog(getLogSizeFromSysProp()) {}

    // Allow the tests to set the capacity and the validaty time in milliseconds.
    DnsQueryLog(size_t size = kDefaultLogSize,
                std::chrono::milliseconds time = kDefaultValidityMinutes)
    DnsQueryLog(size_t size, std::chrono::milliseconds time = kDefaultValidityMinutes)
        : mQueue(size), mValidityTimeMs(time) {}

    void push(Record&& record);
@@ -63,9 +64,13 @@ class DnsQueryLog {

    // The capacity of the circular buffer.
    static constexpr size_t kDefaultLogSize = 200;
    // The upper bound of the circular buffer.
    static constexpr size_t kMaxLogSize = 10000;

    // Limit to dump the queries within last |kDefaultValidityMinutes| minutes.
    static constexpr std::chrono::minutes kDefaultValidityMinutes{60};

    uint64_t getLogSizeFromSysProp();
};

}  // namespace android::net
+34 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <netdutils/NetNativeTestBase.h>

#include "DnsQueryLog.h"
#include "tests/resolv_test_utils.h"

using namespace std::chrono_literals;

@@ -162,4 +163,37 @@ TEST_F(DnsQueryLogTest, ValidityTime) {
    verifyDumpOutput(output, {31});
}

TEST_F(DnsQueryLogTest, SizeCustomization) {
    const size_t logSize = 3;
    const ScopedSystemProperties sp(kQueryLogSize, std::to_string(logSize));
    DnsQueryLog queryLog;

    for (int i = 0; i < 200; i++) {
        DnsQueryLog::Record record(30, 1000, 1000, "www.example.com", serversV4, 10);
        queryLog.push(std::move(record));
    }

    // Verify that there are exact customized number of records in queryLog.
    const std::string output = captureDumpOutput(queryLog);
    verifyDumpOutput(output, std::vector(logSize, 30));
}

TEST_F(DnsQueryLogTest, InvalidSizeCustomization) {
    // The max log size defined in DnsQueryLog.h is 10000.
    for (const auto& logSize : {"-1", "10001", "non-digit"}) {
        const ScopedSystemProperties sp(kQueryLogSize, logSize);
        DnsQueryLog queryLog;

        for (int i = 0; i < 300; i++) {
            DnsQueryLog::Record record(30, 1000, 1000, "www.example.com", serversV4, 10);
            queryLog.push(std::move(record));
        }

        // Verify that queryLog has the default number of records. The default size defined in
        // DnsQueryLog.h is 200.
        const std::string output = captureDumpOutput(queryLog);
        verifyDumpOutput(output, std::vector(200, 30));
    }
}

}  // namespace android::net
+4 −0
Original line number Diff line number Diff line
@@ -162,6 +162,10 @@ const std::string kSkip4aQueryOnV6LinklocalAddrFlag(kFlagPrefix +
                                                    "skip_4a_query_on_v6_linklocal_addr");
const std::string kSortNameserversFlag(kFlagPrefix + "sort_nameservers");

const std::string kPersistNetPrefix("persist.net.");

const std::string kQueryLogSize(kPersistNetPrefix + "dns_query_log_size");

static constexpr char kLocalHost[] = "localhost";
static constexpr char kLocalHostAddr[] = "127.0.0.1";
static constexpr char kIp6LocalHost[] = "ip6-localhost";