Loading DnsProxyListener.cpp +29 −49 Original line number Diff line number Diff line Loading @@ -818,23 +818,16 @@ void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinf if (ipv6WantedButNoData) { // If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis const uid_t uid = mClient->getUid(); if (startQueryLimiter(uid)) { const char* host = mHost.starts_with('^') ? nullptr : mHost.c_str(); const char* service = mService.starts_with('^') ? nullptr : mService.c_str(); mHints->ai_family = AF_INET; // Don't need to do freeaddrinfo(res) before starting new DNS lookup because previous // DNS lookup is failed with error EAI_NODATA. *rv = resolv_getaddrinfo(host, service, mHints.get(), &mNetContext, res, event); endQueryLimiter(uid); if (*rv) { *rv = EAI_NODATA; // return original error code return; } } else { LOG(ERROR) << __func__ << ": from UID " << uid << ", max concurrent queries reached"; return; } } if (!synthesizeNat64PrefixWithARecord(prefix, res, unspecWantedButNoIPv6, &mNetContext)) { Loading Loading @@ -865,6 +858,7 @@ void DnsProxyListener::GetAddrInfoHandler::run() { const char* service = mService.starts_with('^') ? nullptr : mService.c_str(); if (evaluate_domain_name(mNetContext, host)) { rv = resolv_getaddrinfo(host, service, mHints.get(), &mNetContext, &result, &event); doDns64Synthesis(&rv, &result, &event); } else { rv = EAI_SYSTEM; } Loading @@ -877,7 +871,6 @@ void DnsProxyListener::GetAddrInfoHandler::run() { << ", max concurrent queries reached"; } doDns64Synthesis(&rv, &result, &event); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETADDRINFO); Loading Loading @@ -1244,19 +1237,12 @@ void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, hoste } // If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis const uid_t uid = mClient->getUid(); if (startQueryLimiter(uid)) { const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); *rv = resolv_gethostbyname(name, AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); endQueryLimiter(uid); if (*rv) { *rv = EAI_NODATA; // return original error code return; } } else { LOG(ERROR) << __func__ << ": from UID " << uid << ", max concurrent queries reached"; return; } if (!synthesizeNat64PrefixWithARecord(prefix, *hpp)) { // If caller wants IPv6 answers but no data and failed to synthesize IPv4 answers, Loading @@ -1281,6 +1267,7 @@ void DnsProxyListener::GetHostByNameHandler::run() { if (evaluate_domain_name(mNetContext, name)) { rv = resolv_gethostbyname(name, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); doDns64Synthesis(&rv, &hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); } else { rv = EAI_SYSTEM; } Loading @@ -1291,7 +1278,6 @@ void DnsProxyListener::GetHostByNameHandler::run() { << ", max concurrent queries reached"; } doDns64Synthesis(&rv, &hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYNAME); Loading Loading @@ -1406,13 +1392,10 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, return; } const uid_t uid = mClient->getUid(); if (startQueryLimiter(uid)) { // Remove NAT64 prefix and do reverse DNS query struct in_addr v4addr = {.s_addr = v6addr.s6_addr32[3]}; resolv_gethostbyaddr(&v4addr, sizeof(v4addr), AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); endQueryLimiter(uid); if (*hpp && (*hpp)->h_addr_list[0]) { // Replace IPv4 address with original queried IPv6 address in place. The space has // reserved by dns_gethtbyaddr() and netbsd_gethostent_r() in Loading @@ -1425,9 +1408,6 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, } else { LOG(ERROR) << __func__ << ": hpp or (*hpp)->h_addr_list[0] is null"; } } else { LOG(ERROR) << __func__ << ": from UID " << uid << ", max concurrent queries reached"; } } void DnsProxyListener::GetHostByAddrHandler::run() { Loading @@ -1453,6 +1433,7 @@ void DnsProxyListener::GetHostByAddrHandler::run() { } else { rv = resolv_gethostbyaddr(&mAddress, mAddressLen, mAddressFamily, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); doDns64ReverseLookup(&hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); } endQueryLimiter(uid); } else { Loading @@ -1461,7 +1442,6 @@ void DnsProxyListener::GetHostByAddrHandler::run() { << ", max concurrent queries reached"; } doDns64ReverseLookup(&hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYADDR); Loading res_cache.cpp +9 −1 Original line number Diff line number Diff line Loading @@ -2102,3 +2102,11 @@ int resolv_get_max_cache_entries(unsigned netid) { } return info->cache->get_max_cache_entries(); } bool resolv_is_enforceDnsUid_enabled_network(unsigned netid) { std::lock_guard guard(cache_mutex); if (const auto info = find_netconfig_locked(netid); info != nullptr) { return info->enforceDnsUid; } return false; } resolv_cache.h +3 −0 Original line number Diff line number Diff line Loading @@ -143,3 +143,6 @@ void resolv_netconfig_dump(android::netdutils::DumpWriter& dw, unsigned netid); // Get the maximum cache size of a network. // Return positive value on success, -1 on failure. int resolv_get_max_cache_entries(unsigned netid); // Return true if the enforceDnsUid is enabled on the network. bool resolv_is_enforceDnsUid_enabled_network(unsigned netid); tests/resolv_cache_unit_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -928,6 +928,38 @@ TEST_F(ResolvCacheTest, GetResolverStats) { } } TEST_F(ResolvCacheTest, IsEnforceDnsUidEnabled) { const SetupParams unenforcedDnsUidCfg = { .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"}, .domains = {"domain1.com", "domain2.com"}, .params = kParams, }; // Network #1 EXPECT_EQ(0, cacheCreate(TEST_NETID)); EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, unenforcedDnsUidCfg)); EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID)); // Network #2 EXPECT_EQ(0, cacheCreate(TEST_NETID + 1)); EXPECT_EQ(0, cacheSetupResolver(TEST_NETID + 1, unenforcedDnsUidCfg)); EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID + 1)); // Change the enforceDnsUid setting on network #1 const SetupParams enforcedDnsUidCfg = { .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"}, .domains = {"domain1.com", "domain2.com"}, .params = kParams, .resolverOptions = {.enforceDnsUid = true}, }; EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, enforcedDnsUidCfg)); EXPECT_TRUE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID)); // Network #2 is unaffected EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID + 1)); // Returns false on non-existent network EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID + 2)); } namespace { constexpr int EAI_OK = 0; Loading Loading
DnsProxyListener.cpp +29 −49 Original line number Diff line number Diff line Loading @@ -818,23 +818,16 @@ void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinf if (ipv6WantedButNoData) { // If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis const uid_t uid = mClient->getUid(); if (startQueryLimiter(uid)) { const char* host = mHost.starts_with('^') ? nullptr : mHost.c_str(); const char* service = mService.starts_with('^') ? nullptr : mService.c_str(); mHints->ai_family = AF_INET; // Don't need to do freeaddrinfo(res) before starting new DNS lookup because previous // DNS lookup is failed with error EAI_NODATA. *rv = resolv_getaddrinfo(host, service, mHints.get(), &mNetContext, res, event); endQueryLimiter(uid); if (*rv) { *rv = EAI_NODATA; // return original error code return; } } else { LOG(ERROR) << __func__ << ": from UID " << uid << ", max concurrent queries reached"; return; } } if (!synthesizeNat64PrefixWithARecord(prefix, res, unspecWantedButNoIPv6, &mNetContext)) { Loading Loading @@ -865,6 +858,7 @@ void DnsProxyListener::GetAddrInfoHandler::run() { const char* service = mService.starts_with('^') ? nullptr : mService.c_str(); if (evaluate_domain_name(mNetContext, host)) { rv = resolv_getaddrinfo(host, service, mHints.get(), &mNetContext, &result, &event); doDns64Synthesis(&rv, &result, &event); } else { rv = EAI_SYSTEM; } Loading @@ -877,7 +871,6 @@ void DnsProxyListener::GetAddrInfoHandler::run() { << ", max concurrent queries reached"; } doDns64Synthesis(&rv, &result, &event); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETADDRINFO); Loading Loading @@ -1244,19 +1237,12 @@ void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, hoste } // If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis const uid_t uid = mClient->getUid(); if (startQueryLimiter(uid)) { const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); *rv = resolv_gethostbyname(name, AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); endQueryLimiter(uid); if (*rv) { *rv = EAI_NODATA; // return original error code return; } } else { LOG(ERROR) << __func__ << ": from UID " << uid << ", max concurrent queries reached"; return; } if (!synthesizeNat64PrefixWithARecord(prefix, *hpp)) { // If caller wants IPv6 answers but no data and failed to synthesize IPv4 answers, Loading @@ -1281,6 +1267,7 @@ void DnsProxyListener::GetHostByNameHandler::run() { if (evaluate_domain_name(mNetContext, name)) { rv = resolv_gethostbyname(name, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); doDns64Synthesis(&rv, &hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); } else { rv = EAI_SYSTEM; } Loading @@ -1291,7 +1278,6 @@ void DnsProxyListener::GetHostByNameHandler::run() { << ", max concurrent queries reached"; } doDns64Synthesis(&rv, &hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYNAME); Loading Loading @@ -1406,13 +1392,10 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, return; } const uid_t uid = mClient->getUid(); if (startQueryLimiter(uid)) { // Remove NAT64 prefix and do reverse DNS query struct in_addr v4addr = {.s_addr = v6addr.s6_addr32[3]}; resolv_gethostbyaddr(&v4addr, sizeof(v4addr), AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); endQueryLimiter(uid); if (*hpp && (*hpp)->h_addr_list[0]) { // Replace IPv4 address with original queried IPv6 address in place. The space has // reserved by dns_gethtbyaddr() and netbsd_gethostent_r() in Loading @@ -1425,9 +1408,6 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, } else { LOG(ERROR) << __func__ << ": hpp or (*hpp)->h_addr_list[0] is null"; } } else { LOG(ERROR) << __func__ << ": from UID " << uid << ", max concurrent queries reached"; } } void DnsProxyListener::GetHostByAddrHandler::run() { Loading @@ -1453,6 +1433,7 @@ void DnsProxyListener::GetHostByAddrHandler::run() { } else { rv = resolv_gethostbyaddr(&mAddress, mAddressLen, mAddressFamily, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); doDns64ReverseLookup(&hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); } endQueryLimiter(uid); } else { Loading @@ -1461,7 +1442,6 @@ void DnsProxyListener::GetHostByAddrHandler::run() { << ", max concurrent queries reached"; } doDns64ReverseLookup(&hbuf, tmpbuf, sizeof tmpbuf, &hp, &event); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYADDR); Loading
res_cache.cpp +9 −1 Original line number Diff line number Diff line Loading @@ -2102,3 +2102,11 @@ int resolv_get_max_cache_entries(unsigned netid) { } return info->cache->get_max_cache_entries(); } bool resolv_is_enforceDnsUid_enabled_network(unsigned netid) { std::lock_guard guard(cache_mutex); if (const auto info = find_netconfig_locked(netid); info != nullptr) { return info->enforceDnsUid; } return false; }
resolv_cache.h +3 −0 Original line number Diff line number Diff line Loading @@ -143,3 +143,6 @@ void resolv_netconfig_dump(android::netdutils::DumpWriter& dw, unsigned netid); // Get the maximum cache size of a network. // Return positive value on success, -1 on failure. int resolv_get_max_cache_entries(unsigned netid); // Return true if the enforceDnsUid is enabled on the network. bool resolv_is_enforceDnsUid_enabled_network(unsigned netid);
tests/resolv_cache_unit_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -928,6 +928,38 @@ TEST_F(ResolvCacheTest, GetResolverStats) { } } TEST_F(ResolvCacheTest, IsEnforceDnsUidEnabled) { const SetupParams unenforcedDnsUidCfg = { .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"}, .domains = {"domain1.com", "domain2.com"}, .params = kParams, }; // Network #1 EXPECT_EQ(0, cacheCreate(TEST_NETID)); EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, unenforcedDnsUidCfg)); EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID)); // Network #2 EXPECT_EQ(0, cacheCreate(TEST_NETID + 1)); EXPECT_EQ(0, cacheSetupResolver(TEST_NETID + 1, unenforcedDnsUidCfg)); EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID + 1)); // Change the enforceDnsUid setting on network #1 const SetupParams enforcedDnsUidCfg = { .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"}, .domains = {"domain1.com", "domain2.com"}, .params = kParams, .resolverOptions = {.enforceDnsUid = true}, }; EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, enforcedDnsUidCfg)); EXPECT_TRUE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID)); // Network #2 is unaffected EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID + 1)); // Returns false on non-existent network EXPECT_FALSE(resolv_is_enforceDnsUid_enabled_network(TEST_NETID + 2)); } namespace { constexpr int EAI_OK = 0; Loading