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

Commit 6bd1af11 authored by Luke Huang's avatar Luke Huang Committed by Automerger Merge Worker
Browse files

Merge "Refactor DoH implementation" am: 5d811e85

Original change: https://android-review.googlesource.com/c/platform/packages/modules/DnsResolver/+/1745461

Change-Id: Ic6b5a96230dd5e87885ae8f9da6a091aea777ccf
parents 2f0bc27e 5d811e85
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -328,7 +328,8 @@ rust_ffi_static {
    rlibs: [
        "libandroid_logger",
        "libanyhow",
        "liblazy_static",
        "libbase64_rust",
        "libfutures",
        "liblibc",
        "liblog_rust",
        "libquiche",
@@ -363,7 +364,8 @@ rust_test {
    rustlibs: [
        "libandroid_logger",
        "libanyhow",
        "liblazy_static",
        "libbase64_rust",
        "libfutures",
        "liblibc",
        "liblog_rust",
        "libquiche_static",
@@ -384,7 +386,8 @@ rust_ffi_static {
    rlibs: [
        "libandroid_logger",
        "libanyhow",
        "liblazy_static",
        "libbase64_rust",
        "libfutures",
        "liblibc",
        "liblog_rust",
        "libquiche_static",
+48 −13
Original line number Diff line number Diff line
@@ -20,28 +20,63 @@

#pragma once

/* Generated with cbindgen:0.15.0 */
/* Generated with cbindgen:0.17.0 */

#include <stdint.h>
#include <sys/types.h>

/// Context for a running DoH engine and associated thread.
struct DohServer;
/// The return code of doh_query means that there is no answer.
static const ssize_t RESULT_INTERNAL_ERROR = -1;

extern "C" {
/// The return code of doh_query means that query can't be sent.
static const ssize_t RESULT_CAN_NOT_SEND = -2;

/// The return code of doh_query to indicate that the query timed out.
static const ssize_t RESULT_TIMEOUT = -255;

/// Performs static initialization fo the DoH engine.
const char* doh_init();
/// Context for a running DoH engine.
struct DohDispatcher;

using ValidationCallback = void (*)(uint32_t net_id, bool success, const char* ip_addr,
                                    const char* host);

extern "C" {

/// Performs static initialization for the DoH engine.
/// Creates and returns a DoH engine instance.
/// The returned object must be freed with doh_delete().
DohServer* doh_new(const char* url, const char* ip_addr, uint32_t mark, const char* cert_path);
DohDispatcher* doh_dispatcher_new(ValidationCallback ptr);

/// Deletes a DoH engine created by doh_dispatcher_new().
/// # Safety
/// `doh` must be a non-null pointer previously created by `doh_dispatcher_new()`
/// and not yet deleted by `doh_dispatcher_delete()`.
void doh_dispatcher_delete(DohDispatcher* doh);

/// Probes and stores the DoH server with the given configurations.
/// Use the negative errno-style codes as the return value to represent the result.
/// # Safety
/// `doh` must be a non-null pointer previously created by `doh_dispatcher_new()`
/// and not yet deleted by `doh_dispatcher_delete()`.
/// `url`, `domain`, `ip_addr`, `cert_path` are null terminated strings.
int32_t doh_net_new(DohDispatcher* doh, uint32_t net_id, const char* url, const char* domain,
                    const char* ip_addr, uint32_t sk_mark, const char* cert_path,
                    uint64_t timeout_ms);

/// Deletes a DoH engine created by doh_new().
void doh_delete(DohServer* doh);
/// Sends a DNS query via the network associated to the given |net_id| and waits for the response.
/// The return code should be either one of the public constant RESULT_* to indicate the error or
/// the size of the answer.
/// # Safety
/// `doh` must be a non-null pointer previously created by `doh_dispatcher_new()`
/// and not yet deleted by `doh_dispatcher_delete()`.
/// `dns_query` must point to a buffer at least `dns_query_len` in size.
/// `response` must point to a buffer at least `response_len` in size.
ssize_t doh_query(DohDispatcher* doh, uint32_t net_id, uint8_t* dns_query, size_t dns_query_len,
                  uint8_t* response, size_t response_len, uint64_t timeout_ms);

/// Sends a DNS query and waits for the response.
ssize_t doh_query(DohServer* doh, uint8_t* query, size_t query_len, uint8_t* response,
                  size_t response_len);
/// Clears the DoH servers associated with the given |netid|.
/// # Safety
/// `doh` must be a non-null pointer previously created by `doh_dispatcher_new()`
/// and not yet deleted by `doh_dispatcher_delete()`.
void doh_net_delete(DohDispatcher* doh, uint32_t net_id);

}  // extern "C"
+752 −406

File changed.

Preview size limit exceeded, changes collapsed.

+3 −0
Original line number Diff line number Diff line
@@ -298,5 +298,8 @@ cc_test {
        "libring-core",
        "libssl",
    ],
    shared_libs: [
        "libnetd_client",
    ],
    min_sdk_version: "29",
}
+48 −6
Original line number Diff line number Diff line
@@ -16,18 +16,60 @@

#include "doh.h"

#include <chrono>
#include <condition_variable>
#include <mutex>

#include <resolv.h>

#include <NetdClient.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>

static const char* GOOGLE_SERVER_IP = "8.8.8.8";
static const int TIMEOUT_MS = 3000;
constexpr int MAXPACKET = (8 * 1024);
constexpr unsigned int MINIMAL_NET_ID = 100;

std::mutex m;
std::condition_variable cv;
unsigned int dnsNetId;

TEST(DoHFFITest, SmokeTest) {
    EXPECT_STREQ(doh_init(), "1.0");
    DohServer* doh = doh_new("https://dns.google/dns-query", "8.8.8.8", 0, "");
    getNetworkForDns(&dnsNetId);
    // To ensure that we have a real network.
    ASSERT_GE(dnsNetId, MINIMAL_NET_ID) << "No available networks";

    auto callback = [](uint32_t netId, bool success, const char* ip_addr, const char* host) {
        EXPECT_EQ(netId, dnsNetId);
        EXPECT_TRUE(success);
        EXPECT_STREQ(ip_addr, GOOGLE_SERVER_IP);
        EXPECT_STREQ(host, "");
        cv.notify_one();
    };
    DohDispatcher* doh = doh_dispatcher_new(callback);
    EXPECT_TRUE(doh != nullptr);

    // www.example.com
    uint8_t query[] = "q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB";
    // TODO: Use a local server instead of dns.google.
    // sk_mark doesn't matter here because this test doesn't have permission to set sk_mark.
    // The DNS packet would be sent via default network.
    EXPECT_EQ(doh_net_new(doh, dnsNetId, "https://dns.google/dns-query", /* domain */ "",
                          GOOGLE_SERVER_IP,
                          /* sk_mark */ 0, /* cert_path */ "", TIMEOUT_MS),
              0);
    {
        std::unique_lock<std::mutex> lk(m);
        EXPECT_EQ(cv.wait_for(lk, std::chrono::milliseconds(TIMEOUT_MS)),
                  std::cv_status::no_timeout);
    }

    std::vector<uint8_t> buf(MAXPACKET, 0);
    ssize_t len = res_mkquery(ns_o_query, "www.example.com", ns_c_in, ns_t_aaaa, nullptr, 0,
                              nullptr, buf.data(), MAXPACKET);
    uint8_t answer[8192];
    ssize_t len = doh_query(doh, query, sizeof query, answer, sizeof answer);

    len = doh_query(doh, dnsNetId, buf.data(), len, answer, sizeof answer, TIMEOUT_MS);
    EXPECT_GT(len, 0);
    doh_delete(doh);
    doh_net_delete(doh, dnsNetId);
    doh_dispatcher_delete(doh);
}