| /* |
| * 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. |
| */ |
| |
| #define LOG_TAG "resolv_callback_unit_test" |
| |
| #include <android-base/properties.h> |
| #include <gtest/gtest.h> |
| |
| #include "DnsResolver.h" |
| #include "getaddrinfo.h" |
| #include "resolv_cache.h" |
| #include "tests/resolv_test_utils.h" |
| |
| namespace android::net { |
| |
| using android::net::NetworkDnsEventReported; |
| using android::netdutils::ScopedAddrinfo; |
| |
| // Use maximum reserved appId for applications to avoid conflict with existing uids. |
| const int TEST_UID = 99999; |
| // Use testUid to make sure TagSocketCallback is called. |
| static int testUid = 0; |
| |
| bool isApiLevelSupported(size_t requiredVersion) { |
| if (android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0) >= requiredVersion) |
| return true; |
| else |
| return false; |
| } |
| |
| #define SKIP_IF_APILEVEL_LESS_THAN(version) \ |
| do { \ |
| if (!isApiLevelSupported(version)) { \ |
| GTEST_LOG_(INFO) << "Skip. Required API version: " << (version) << "\n"; \ |
| return; \ |
| } \ |
| } while (0) |
| |
| void getNetworkContextCallback(uint32_t, uint32_t, android_net_context*) { |
| // No-op |
| } |
| |
| bool checkCallingPermissionCallback(const char*) { |
| // No-op |
| return true; |
| } |
| |
| void logCallback(const char*) { |
| // No-op |
| } |
| |
| int tagSocketCallback(int, uint32_t, uid_t uid, pid_t) { |
| testUid = uid; |
| return true; |
| } |
| |
| bool evaluateDomainNameCallback(const android_net_context&, const char*) { |
| // No-op |
| return true; |
| } |
| |
| void initDnsResolverCallbacks() { |
| ResolverNetdCallbacks callbacks = { |
| .check_calling_permission = &checkCallingPermissionCallback, |
| .get_network_context = &getNetworkContextCallback, |
| .log = &logCallback, |
| .tagSocket = &tagSocketCallback, |
| .evaluate_domain_name = &evaluateDomainNameCallback, |
| }; |
| // It returns fail since socket 'dnsproxyd' has been occupied. |
| // But the callback funtions is configured successfully and can |
| // be tested when running unit test cases. |
| resolv_init(&callbacks); |
| } |
| |
| void resetDnsResolverCallbacks() { |
| ResolverNetdCallbacks callbacks = { |
| .check_calling_permission = nullptr, |
| .get_network_context = nullptr, |
| .log = nullptr, |
| .tagSocket = nullptr, |
| .evaluate_domain_name = nullptr, |
| }; |
| resolv_init(&callbacks); |
| } |
| |
| void resetCallbackParams() { |
| testUid = 0; |
| } |
| |
| class CallbackTest : public ::testing::Test { |
| protected: |
| void SetUp() override { |
| initDnsResolverCallbacks(); |
| // Create cache for test |
| android::net::gDnsResolv->resolverCtrl.createNetworkCache(TEST_NETID); |
| } |
| |
| void TearDown() override { |
| // Reset related parameters and callback functions. |
| resetCallbackParams(); |
| resetDnsResolverCallbacks(); |
| // Delete cache for test |
| android::net::gDnsResolv->resolverCtrl.destroyNetworkCache(TEST_NETID); |
| } |
| |
| int SetResolvers() { |
| const std::vector<std::string> servers = {test::kDefaultListenAddr}; |
| const std::vector<std::string> domains = {"example.com"}; |
| const res_params params = { |
| .sample_validity = 300, |
| .success_threshold = 25, |
| .min_samples = 8, |
| .max_samples = 8, |
| .base_timeout_msec = 1000, |
| .retry_count = 2, |
| }; |
| return resolv_set_nameservers(TEST_NETID, servers, domains, params); |
| } |
| |
| const android_net_context mNetcontext = { |
| .app_netid = TEST_NETID, |
| .app_mark = MARK_UNSET, |
| .dns_netid = TEST_NETID, |
| .dns_mark = MARK_UNSET, |
| .uid = TEST_UID, |
| }; |
| }; |
| |
| TEST_F(CallbackTest, tagSocketCallback) { |
| // tagSocketCallback is used when ro.build.version.sdk >=30. |
| // If ro.build.version.sdk < 30, don't run this test case. |
| SKIP_IF_APILEVEL_LESS_THAN(30); |
| test::DNSResponder dns; |
| dns.addMapping(kHelloExampleCom, ns_type::ns_t_a, kHelloExampleComAddrV4); |
| ASSERT_TRUE(dns.startServer()); |
| EXPECT_EQ(SetResolvers(), 0); |
| |
| addrinfo* result = nullptr; |
| const addrinfo hints = {.ai_family = AF_INET}; |
| NetworkDnsEventReported event; |
| // tagSocketCallback will be called. |
| const int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event); |
| ScopedAddrinfo result_cleanup(result); |
| EXPECT_EQ(testUid, TEST_UID); |
| EXPECT_EQ(rv, 0); |
| } |
| } // end of namespace android::net |