Move DnsProxyListener to libnetd_resolv
[1] Support APIs for netd to set callbacks and bring up
DnsProxyListener.
[2] Keep DnsProxyListener functioning as usual by function pointers,
including getNetworkContext(), checkCallingPermission(), and
getPrefix64().
[3] Use libbinder_ndk to report onDnsEvent().
Test: as follows
- built, flashed, booted
- system/netd/tests/runtests.sh passed
- netd_benchmark passed
- Browsing websites passed
Change-Id: Ib6575833c248579aa079e302795b6d6cddde1f2b
diff --git a/server/Android.bp b/server/Android.bp
index b375cfc..18d7c5f 100644
--- a/server/Android.bp
+++ b/server/Android.bp
@@ -124,7 +124,6 @@
"libpcap",
"libqtaguid",
"libselinux",
- "libstatslog",
"libsysutils",
"libutils",
"netd_aidl_interface-cpp",
@@ -139,7 +138,6 @@
srcs: [
"ClatdController.cpp",
"CommandListener.cpp",
- "DnsProxyListener.cpp",
"DummyNetwork.cpp",
"DumpWriter.cpp",
"EventReporter.cpp",
diff --git a/server/DnsProxyListener.cpp b/server/DnsProxyListener.cpp
deleted file mode 100644
index 822a840..0000000
--- a/server/DnsProxyListener.cpp
+++ /dev/null
@@ -1,1180 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#include <arpa/inet.h>
-#include <dirent.h>
-#include <errno.h>
-#include <linux/if.h>
-#include <math.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <string.h>
-#include <pthread.h>
-#include <net/if.h>
-
-#define LOG_TAG "DnsProxyListener"
-#define DBG 0
-#define VDBG 0
-
-#include <algorithm>
-#include <chrono>
-#include <list>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-#include <cutils/misc.h>
-#include <log/log.h>
-#include <netdutils/OperationLimiter.h>
-#include <netdutils/Slice.h>
-#include <resolv.h>
-#include <statslog.h>
-#include <sysutils/SocketClient.h>
-#include <utils/String16.h>
-
-#include <binder/IServiceManager.h>
-
-#include "Controllers.h"
-#include "DnsProxyListener.h"
-#include "Fwmark.h"
-#include "NetdClient.h"
-#include "NetdConstants.h"
-#include "NetworkController.h"
-#include "ResponseCode.h"
-#include "Stopwatch.h"
-#include "android/net/metrics/INetdEventListener.h"
-#include "thread_util.h"
-
-#include <netd_resolv/resolv_stub.h>
-
-using android::String16;
-using android::base::StringPrintf;
-using android::net::metrics::INetdEventListener;
-
-namespace android {
-namespace net {
-
-namespace {
-
-// TODO: move to a separate file (with other constants from FwmarkService and NetdNativeService)
-constexpr const char CONNECTIVITY_USE_RESTRICTED_NETWORKS[] =
- "android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS";
-constexpr const char NETWORK_BYPASS_PRIVATE_DNS[] =
- "android.permission.NETWORK_BYPASS_PRIVATE_DNS";
-
-// Limits the number of outstanding DNS queries by client UID.
-constexpr int MAX_QUERIES_PER_UID = 256;
-
-// Max packet size for answer, sync with getaddrinfo.c
-constexpr int MAXPACKET = 8 * 1024;
-
-android::netdutils::OperationLimiter<uid_t> queryLimiter(MAX_QUERIES_PER_UID);
-
-void logArguments(int argc, char** argv) {
- for (int i = 0; i < argc; i++) {
- ALOGD("argv[%i]=%s", i, argv[i]);
- }
-}
-
-template<typename T>
-void tryThreadOrError(SocketClient* cli, T* handler) {
- cli->incRef();
-
- const int rval = threadLaunch(handler);
- if (rval == 0) {
- // SocketClient decRef() happens in the handler's run() method.
- return;
- }
-
- char* msg = nullptr;
- asprintf(&msg, "%s (%d)", strerror(-rval), -rval);
- cli->sendMsg(ResponseCode::OperationFailed, msg, false);
- free(msg);
-
- delete handler;
- cli->decRef();
-}
-
-bool checkAndClearUseLocalNameserversFlag(unsigned* netid) {
- if (netid == nullptr || ((*netid) & NETID_USE_LOCAL_NAMESERVERS) == 0) {
- return false;
- }
- *netid = (*netid) & ~NETID_USE_LOCAL_NAMESERVERS;
- return true;
-}
-
-constexpr bool requestingUseLocalNameservers(unsigned flags) {
- return (flags & NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS) != 0;
-}
-
-inline bool queryingViaTls(unsigned dns_netid) {
- ExternalPrivateDnsStatus privateDnsStatus = {PrivateDnsMode::OFF, 0, {}};
- RESOLV_STUB.resolv_get_private_dns_status_for_net(dns_netid, &privateDnsStatus);
- switch (static_cast<PrivateDnsMode>(privateDnsStatus.mode)) {
- case PrivateDnsMode::OPPORTUNISTIC:
- for (int i = 0; i < privateDnsStatus.numServers; i++) {
- if (privateDnsStatus.serverStatus[i].validation == Validation::success) {
- return true;
- }
- }
- return false;
- case PrivateDnsMode::STRICT:
- return true;
- default:
- return false;
- }
-}
-
-bool hasPermissionToBypassPrivateDns(uid_t uid) {
- static_assert(AID_SYSTEM >= 0 && AID_SYSTEM < FIRST_APPLICATION_UID,
- "Calls from AID_SYSTEM must not result in a permission check to avoid deadlock.");
- if (uid >= 0 && uid < FIRST_APPLICATION_UID) {
- return true;
- }
-
- for (const char* const permission :
- {CONNECTIVITY_USE_RESTRICTED_NETWORKS, NETWORK_BYPASS_PRIVATE_DNS}) {
- if (checkCallingPermission(String16(permission))) {
- return true;
- }
- }
- return false;
-}
-
-void maybeFixupNetContext(android_net_context* ctx) {
- if (requestingUseLocalNameservers(ctx->flags) && !hasPermissionToBypassPrivateDns(ctx->uid)) {
- // Not permitted; clear the flag.
- ctx->flags &= ~NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS;
- }
-
- if (!requestingUseLocalNameservers(ctx->flags)) {
- // If we're not explicitly bypassing DNS-over-TLS servers, check whether
- // DNS-over-TLS is in use as an indicator for when to use more modern
- // DNS resolution mechanics.
- if (queryingViaTls(ctx->dns_netid)) {
- ctx->flags |= NET_CONTEXT_FLAG_USE_EDNS;
- }
- }
-}
-
-void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* addr,
- socklen_t addrlen);
-
-int extractResNsendAnswers(const uint8_t* answer, size_t anslen, int ipType,
- std::vector<std::string>* ip_addrs) {
- int total_ip_addr_count = 0;
- ns_msg handle;
- if (ns_initparse((const uint8_t*) answer, anslen, &handle) < 0) {
- return 0;
- }
- int ancount = ns_msg_count(handle, ns_s_an);
- ns_rr rr;
- for (int i = 0; i < ancount; i++) {
- if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) {
- continue;
- }
- const uint8_t* rdata = ns_rr_rdata(rr);
- if (ipType == ns_t_a) {
- sockaddr_in sin = {.sin_family = AF_INET};
- memcpy(&sin.sin_addr, rdata, sizeof(sin.sin_addr));
- addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin, sizeof(sin));
- total_ip_addr_count++;
- } else if (ipType == ns_t_aaaa) {
- sockaddr_in6 sin6 = {.sin6_family = AF_INET6};
- memcpy(&sin6.sin6_addr, rdata, sizeof(sin6.sin6_addr));
- addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin6, sizeof(sin6));
- total_ip_addr_count++;
- }
- }
-
- return total_ip_addr_count;
-}
-
-int extractGetAddrInfoAnswers(const addrinfo* result, std::vector<std::string>* ip_addrs) {
- int total_ip_addr_count = 0;
- if (result == nullptr) {
- return 0;
- }
- for (const addrinfo* ai = result; ai; ai = ai->ai_next) {
- sockaddr* ai_addr = ai->ai_addr;
- if (ai_addr) {
- addIpAddrWithinLimit(ip_addrs, ai_addr, ai->ai_addrlen);
- total_ip_addr_count++;
- }
- }
- return total_ip_addr_count;
-}
-
-int extractGetHostByNameAnswers(const hostent* hp, std::vector<std::string>* ip_addrs) {
- int total_ip_addr_count = 0;
- if (hp == nullptr) {
- return 0;
- }
- if (hp->h_addrtype == AF_INET) {
- in_addr** list = (in_addr**) hp->h_addr_list;
- for (int i = 0; list[i] != nullptr; i++) {
- sockaddr_in sin = {.sin_family = AF_INET, .sin_addr = *list[i]};
- addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin, sizeof(sin));
- total_ip_addr_count++;
- }
- } else if (hp->h_addrtype == AF_INET6) {
- in6_addr** list = (in6_addr**) hp->h_addr_list;
- for (int i = 0; list[i] != nullptr; i++) {
- sockaddr_in6 sin6 = {.sin6_family = AF_INET6, .sin6_addr = *list[i]};
- addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin6, sizeof(sin6));
- total_ip_addr_count++;
- }
- }
- return total_ip_addr_count;
-}
-
-int rcodeToAiError(int rcode) {
- switch (rcode) {
- case NOERROR:
- return 0;
- case RCODE_TIMEOUT:
- return NETD_RESOLV_TIMEOUT;
- default:
- return EAI_NODATA;
- }
-}
-
-int resNSendToAiError(int err, int rcode) {
- if (err > 0) {
- return rcodeToAiError(rcode);
- }
- if (err == -ETIMEDOUT) {
- return NETD_RESOLV_TIMEOUT;
- }
- return EAI_SYSTEM;
-}
-
-template <typename IntegralType>
-bool simpleStrtoul(const char* input, IntegralType* output, int base = 10) {
- char* endPtr;
- errno = 0;
- auto result = strtoul(input, &endPtr, base);
- // Check the length in order to ensure there is no "-" sign
- if (!*input || *endPtr || (endPtr - input) != static_cast<ptrdiff_t>(strlen(input)) ||
- (errno == ERANGE && (result == ULONG_MAX))) {
- return false;
- }
- *output = result;
- return true;
-}
-
-bool parseQuery(const uint8_t* msg, size_t msgLen, int* rr_type, std::string* rr_name) {
- ns_msg handle;
- ns_rr rr;
- if (ns_initparse((const uint8_t*) msg, msgLen, &handle) < 0 ||
- ns_parserr(&handle, ns_s_qd, 0, &rr) < 0) {
- return false;
- }
-
- *rr_name = ns_rr_name(rr);
- *rr_type = ns_rr_type(rr);
- return true;
-}
-
-void reportDnsEvent(int eventType, const android_net_context& netContext, int latencyUs,
- int returnCode, const std::string& query_name,
- const std::vector<std::string>& ip_addrs = {}, int total_ip_addr_count = 0) {
- android::util::stats_write(android::util::NETWORK_DNS_EVENT_REPORTED, eventType, returnCode,
- latencyUs);
-
- const auto listener = gCtls->eventReporter.getNetdEventListener();
- if (!listener) return;
- const int latencyMs = latencyUs / 1000;
- listener->onDnsEvent(netContext.dns_netid, eventType, returnCode, latencyMs, query_name,
- ip_addrs, total_ip_addr_count, netContext.uid);
-}
-
-bool onlyIPv4Answers(const addrinfo* res) {
- // Null addrinfo pointer isn't checked because the caller doesn't pass null pointer.
-
- for (const addrinfo* ai = res; ai; ai = ai->ai_next)
- if (ai->ai_family != AF_INET) return false;
-
- return true;
-}
-
-bool isSpecialUseIPv4Address(const struct in_addr& ia) {
- const uint32_t addr = ntohl(ia.s_addr);
-
- // Only check necessary IP ranges in RFC 5735 section 4
- return ((addr & 0xff000000) == 0x00000000) || // "This" Network
- ((addr & 0xff000000) == 0x7f000000) || // Loopback
- ((addr & 0xffff0000) == 0xa9fe0000) || // Link Local
- ((addr & 0xf0000000) == 0xe0000000) || // Multicast
- (addr == INADDR_BROADCAST); // Limited Broadcast
-}
-
-bool isSpecialUseIPv4Address(const struct sockaddr* sa) {
- if (sa->sa_family != AF_INET) return false;
-
- return isSpecialUseIPv4Address(((struct sockaddr_in*) sa)->sin_addr);
-}
-
-bool onlyNonSpecialUseIPv4Addresses(struct hostent* hp) {
- // Null hostent pointer isn't checked because the caller doesn't pass null pointer.
-
- if (hp->h_addrtype != AF_INET) return false;
-
- for (int i = 0; hp->h_addr_list[i] != nullptr; i++)
- if (isSpecialUseIPv4Address(*(struct in_addr*) hp->h_addr_list[i])) return false;
-
- return true;
-}
-
-bool onlyNonSpecialUseIPv4Addresses(const addrinfo* res) {
- // Null addrinfo pointer isn't checked because the caller doesn't pass null pointer.
-
- for (const addrinfo* ai = res; ai; ai = ai->ai_next) {
- if (ai->ai_family != AF_INET) return false;
- if (isSpecialUseIPv4Address(ai->ai_addr)) return false;
- }
-
- return true;
-}
-
-void logDnsQueryResult(const struct hostent* hp) {
- if (hp == nullptr) return;
-
- ALOGD("DNS records:");
- for (int i = 0; hp->h_addr_list[i] != nullptr; i++) {
- char ip_addr[INET6_ADDRSTRLEN];
- if (inet_ntop(hp->h_addrtype, hp->h_addr_list[i], ip_addr, sizeof(ip_addr)) != nullptr) {
- ALOGD("[%d] %s, %d, %d, %s (%p)", i, hp->h_name ? hp->h_name : "null", hp->h_addrtype,
- hp->h_length, ip_addr, hp->h_addr_list[i]);
- } else {
- ALOGD("[%d] numeric hostname translation fail (%d)", i, errno);
- }
- }
-}
-
-void logDnsQueryResult(const addrinfo* res) {
- if (res == nullptr) return;
-
- int i;
- const addrinfo* ai;
- ALOGD("DNS records:");
- for (ai = res, i = 0; ai; ai = ai->ai_next, i++) {
- if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6)) continue;
- char ip_addr[INET6_ADDRSTRLEN];
- int ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, ip_addr, sizeof(ip_addr), nullptr, 0,
- NI_NUMERICHOST);
- if (!ret) {
- ALOGD("[%d] 0x%x,%d,%d,%d,%d,%s,%s,%p", i, ai->ai_flags, ai->ai_family, ai->ai_socktype,
- ai->ai_protocol, ai->ai_addrlen, ai->ai_canonname ? ai->ai_canonname : "null",
- ip_addr, ai);
- } else {
- ALOGD("[%d] numeric hostname translation fail (%d)", i, ret);
- }
- }
-}
-
-bool isValidNat64Prefix(const netdutils::IPPrefix prefix) {
- if (prefix.family() != AF_INET6) {
- ALOGE("Only IPv6 NAT64 prefixes are supported (%u)", prefix.family());
- return false;
- }
- if (prefix.length() != 96) {
- ALOGE("Only /96 NAT64 prefixes are supported (%d)", prefix.length());
- return false;
- }
- return true;
-}
-
-bool synthesizeNat64PrefixWithARecord(const netdutils::IPPrefix& prefix, struct hostent* hp) {
- if (hp == nullptr) return false;
- if (!onlyNonSpecialUseIPv4Addresses(hp)) return false;
- if (!isValidNat64Prefix(prefix)) return false;
-
- struct sockaddr_storage ss = netdutils::IPSockAddr(prefix.ip());
- struct sockaddr_in6* v6prefix = (struct sockaddr_in6*) &ss;
- for (int i = 0; hp->h_addr_list[i] != nullptr; i++) {
- struct in_addr iaOriginal = *(struct in_addr*) hp->h_addr_list[i];
- struct in6_addr* ia6 = (struct in6_addr*) hp->h_addr_list[i];
- memset(ia6, 0, sizeof(struct in6_addr));
-
- // Synthesize /96 NAT64 prefix in place. The space has reserved by getanswer() and
- // _hf_gethtbyname2() in system/netd/resolv/gethnamaddr.cpp and
- // system/netd/resolv/sethostent.cpp.
- *ia6 = v6prefix->sin6_addr;
- ia6->s6_addr32[3] = iaOriginal.s_addr;
-
- if (DBG) {
- char buf[INET6_ADDRSTRLEN]; // big enough for either IPv4 or IPv6
- inet_ntop(AF_INET, &iaOriginal.s_addr, buf, sizeof(buf));
- ALOGD("DNS A record: %s", buf);
- inet_ntop(AF_INET6, &v6prefix->sin6_addr, buf, sizeof(buf));
- ALOGD("NAT64 prefix: %s", buf);
- inet_ntop(AF_INET6, ia6, buf, sizeof(buf));
- ALOGD("DNS64 Synthesized AAAA record: %s", buf);
- }
- }
- hp->h_addrtype = AF_INET6;
- hp->h_length = sizeof(in6_addr);
-
- if (DBG) logDnsQueryResult(hp);
- return true;
-}
-
-bool synthesizeNat64PrefixWithARecord(const netdutils::IPPrefix& prefix, addrinfo* result) {
- if (result == nullptr) return false;
- if (!onlyNonSpecialUseIPv4Addresses(result)) return false;
- if (!isValidNat64Prefix(prefix)) return false;
-
- struct sockaddr_storage ss = netdutils::IPSockAddr(prefix.ip());
- struct sockaddr_in6* v6prefix = (struct sockaddr_in6*) &ss;
- for (addrinfo* ai = result; ai; ai = ai->ai_next) {
- struct sockaddr_in sinOriginal = *(struct sockaddr_in*) ai->ai_addr;
- struct sockaddr_in6* sin6 = (struct sockaddr_in6*) ai->ai_addr;
- memset(sin6, 0, sizeof(sockaddr_in6));
-
- // Synthesize /96 NAT64 prefix in place. The space has reserved by get_ai() in
- // system/netd/resolv/getaddrinfo.cpp.
- sin6->sin6_addr = v6prefix->sin6_addr;
- sin6->sin6_addr.s6_addr32[3] = sinOriginal.sin_addr.s_addr;
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = sinOriginal.sin_port;
- ai->ai_addrlen = sizeof(struct sockaddr_in6);
- ai->ai_family = AF_INET6;
-
- if (DBG) {
- char buf[INET6_ADDRSTRLEN]; // big enough for either IPv4 or IPv6
- inet_ntop(AF_INET, &sinOriginal.sin_addr.s_addr, buf, sizeof(buf));
- ALOGD("DNS A record: %s", buf);
- inet_ntop(AF_INET6, &v6prefix->sin6_addr, buf, sizeof(buf));
- ALOGD("NAT64 prefix: %s", buf);
- inet_ntop(AF_INET6, &sin6->sin6_addr, buf, sizeof(buf));
- ALOGD("DNS64 Synthesized AAAA record: %s", buf);
- }
- }
- if (DBG) logDnsQueryResult(result);
- return true;
-}
-
-} // namespace
-
-DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl)
- : FrameworkListener(SOCKET_NAME), mNetCtrl(netCtrl) {
- registerCmd(new GetAddrInfoCmd(this));
- registerCmd(new GetHostByAddrCmd(this));
- registerCmd(new GetHostByNameCmd(this));
- registerCmd(new ResNSendCommand(this));
-}
-
-DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient* c, char* host, char* service,
- addrinfo* hints,
- const android_net_context& netcontext)
- : mClient(c), mHost(host), mService(service), mHints(hints), mNetContext(netcontext) {}
-
-DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
- free(mHost);
- free(mService);
- free(mHints);
-}
-
-static bool sendBE32(SocketClient* c, uint32_t data) {
- uint32_t be_data = htonl(data);
- return c->sendData(&be_data, sizeof(be_data)) == 0;
-}
-
-// Sends 4 bytes of big-endian length, followed by the data.
-// Returns true on success.
-static bool sendLenAndData(SocketClient* c, const int len, const void* data) {
- return sendBE32(c, len) && (len == 0 || c->sendData(data, len) == 0);
-}
-
-// Returns true on success
-static bool sendhostent(SocketClient* c, hostent* hp) {
- bool success = true;
- int i;
- if (hp->h_name != nullptr) {
- success &= sendLenAndData(c, strlen(hp->h_name)+1, hp->h_name);
- } else {
- success &= sendLenAndData(c, 0, "") == 0;
- }
-
- for (i=0; hp->h_aliases[i] != nullptr; i++) {
- success &= sendLenAndData(c, strlen(hp->h_aliases[i])+1, hp->h_aliases[i]);
- }
- success &= sendLenAndData(c, 0, ""); // null to indicate we're done
-
- uint32_t buf = htonl(hp->h_addrtype);
- success &= c->sendData(&buf, sizeof(buf)) == 0;
-
- buf = htonl(hp->h_length);
- success &= c->sendData(&buf, sizeof(buf)) == 0;
-
- for (i=0; hp->h_addr_list[i] != nullptr; i++) {
- success &= sendLenAndData(c, 16, hp->h_addr_list[i]);
- }
- success &= sendLenAndData(c, 0, ""); // null to indicate we're done
- return success;
-}
-
-static bool sendaddrinfo(SocketClient* c, addrinfo* ai) {
- // struct addrinfo {
- // int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
- // int ai_family; /* PF_xxx */
- // int ai_socktype; /* SOCK_xxx */
- // int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
- // socklen_t ai_addrlen; /* length of ai_addr */
- // char *ai_canonname; /* canonical name for hostname */
- // struct sockaddr *ai_addr; /* binary address */
- // struct addrinfo *ai_next; /* next structure in linked list */
- // };
-
- // Write the struct piece by piece because we might be a 64-bit netd
- // talking to a 32-bit process.
- bool success =
- sendBE32(c, ai->ai_flags) &&
- sendBE32(c, ai->ai_family) &&
- sendBE32(c, ai->ai_socktype) &&
- sendBE32(c, ai->ai_protocol);
- if (!success) {
- return false;
- }
-
- // ai_addrlen and ai_addr.
- if (!sendLenAndData(c, ai->ai_addrlen, ai->ai_addr)) {
- return false;
- }
-
- // strlen(ai_canonname) and ai_canonname.
- if (!sendLenAndData(c, ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0, ai->ai_canonname)) {
- return false;
- }
-
- return true;
-}
-
-void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinfo** res) {
- if (mHost == nullptr) return;
-
- const bool ipv6WantedButNoData = (mHints && mHints->ai_family == AF_INET6 && *rv == EAI_NODATA);
- const bool unspecWantedButNoIPv6 =
- ((!mHints || mHints->ai_family == AF_UNSPEC) && *rv == 0 && onlyIPv4Answers(*res));
-
- if (!ipv6WantedButNoData && !unspecWantedButNoIPv6) {
- return;
- }
-
- netdutils::IPPrefix prefix{};
- if (net::gCtls->resolverCtrl.getPrefix64(mNetContext.dns_netid, &prefix)) {
- return;
- }
-
- if (ipv6WantedButNoData) {
- // If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis
- const uid_t uid = mClient->getUid();
- if (queryLimiter.start(uid)) {
- 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_STUB.android_getaddrinfofornetcontext(mHost, mService, mHints,
- &mNetContext, res);
- queryLimiter.finish(uid);
- if (*rv) {
- *rv = EAI_NODATA; // return original error code
- return;
- }
- } else {
- ALOGE("getaddrinfo: from UID %d, max concurrent queries reached", uid);
- return;
- }
- }
-
- if (!synthesizeNat64PrefixWithARecord(prefix, *res)) {
- if (ipv6WantedButNoData) {
- // If caller wants IPv6 answers but no data and failed to synthesize IPv6 answers,
- // don't return the IPv4 answers.
- *rv = EAI_NODATA; // return original error code
- if (*res) {
- freeaddrinfo(*res);
- *res = nullptr;
- }
- }
- }
-}
-
-void DnsProxyListener::GetAddrInfoHandler::run() {
- if (DBG) {
- ALOGD("GetAddrInfoHandler, now for %s / %s / {%u,%u,%u,%u,%u,%u}", mHost, mService,
- mNetContext.app_netid, mNetContext.app_mark,
- mNetContext.dns_netid, mNetContext.dns_mark,
- mNetContext.uid, mNetContext.flags);
- }
-
- addrinfo* result = nullptr;
- Stopwatch s;
- maybeFixupNetContext(&mNetContext);
- const uid_t uid = mClient->getUid();
- int32_t rv = 0;
- if (queryLimiter.start(uid)) {
- rv = RESOLV_STUB.android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext,
- &result);
- queryLimiter.finish(uid);
- } else {
- // Note that this error code is currently not passed down to the client.
- // android_getaddrinfo_proxy() returns EAI_NODATA on any error.
- rv = EAI_MEMORY;
- ALOGE("getaddrinfo: from UID %d, max concurrent queries reached", uid);
- }
-
- doDns64Synthesis(&rv, &result);
- const int latencyUs = int(s.timeTakenUs());
-
- if (rv) {
- // getaddrinfo failed
- mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, &rv, sizeof(rv));
- } else {
- bool success = !mClient->sendCode(ResponseCode::DnsProxyQueryResult);
- addrinfo* ai = result;
- while (ai && success) {
- success = sendBE32(mClient, 1) && sendaddrinfo(mClient, ai);
- ai = ai->ai_next;
- }
- success = success && sendBE32(mClient, 0);
- if (!success) {
- ALOGW("Error writing DNS result to client");
- }
- }
- std::vector<std::string> ip_addrs;
- const int total_ip_addr_count = extractGetAddrInfoAnswers(result, &ip_addrs);
- reportDnsEvent(INetdEventListener::EVENT_GETADDRINFO, mNetContext, latencyUs, rv, mHost,
- ip_addrs, total_ip_addr_count);
- freeaddrinfo(result);
- mClient->decRef();
-}
-
-namespace {
-
-void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* addr,
- socklen_t addrlen) {
- // ipAddresses array is limited to first INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT
- // addresses for A and AAAA. Total count of addresses is provided, to be able to tell whether
- // some addresses didn't get logged.
- if (ip_addrs->size() < INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT) {
- char ip_addr[INET6_ADDRSTRLEN];
- if (getnameinfo(addr, addrlen, ip_addr, sizeof(ip_addr), nullptr, 0, NI_NUMERICHOST) == 0) {
- ip_addrs->push_back(std::string(ip_addr));
- }
- }
-}
-
-} // namespace
-
-DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd(DnsProxyListener* dnsProxyListener) :
- NetdCommand("getaddrinfo"),
- mDnsProxyListener(dnsProxyListener) {
-}
-
-int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
- if (DBG) logArguments(argc, argv);
-
- if (argc != 8) {
- char* msg = nullptr;
- asprintf( &msg, "Invalid number of arguments to getaddrinfo: %i", argc);
- ALOGW("%s", msg);
- cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
- free(msg);
- return -1;
- }
-
- char* name = argv[1];
- if (strcmp("^", name) == 0) {
- name = nullptr;
- } else {
- name = strdup(name);
- }
-
- char* service = argv[2];
- if (strcmp("^", service) == 0) {
- service = nullptr;
- } else {
- service = strdup(service);
- }
-
- addrinfo* hints = nullptr;
- int ai_flags = strtol(argv[3], nullptr, 10);
- int ai_family = strtol(argv[4], nullptr, 10);
- int ai_socktype = strtol(argv[5], nullptr, 10);
- int ai_protocol = strtol(argv[6], nullptr, 10);
- unsigned netId = strtoul(argv[7], nullptr, 10);
- const bool useLocalNameservers = checkAndClearUseLocalNameserversFlag(&netId);
- const uid_t uid = cli->getUid();
-
- android_net_context netcontext;
- mDnsProxyListener->mNetCtrl->getNetworkContext(netId, uid, &netcontext);
- if (useLocalNameservers) {
- netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS;
- }
-
- if (ai_flags != -1 || ai_family != -1 ||
- ai_socktype != -1 || ai_protocol != -1) {
- hints = (addrinfo*) calloc(1, sizeof(addrinfo));
- hints->ai_flags = ai_flags;
- hints->ai_family = ai_family;
- hints->ai_socktype = ai_socktype;
- hints->ai_protocol = ai_protocol;
- }
-
- if (DBG) {
- ALOGD("GetAddrInfoHandler for %s / %s / {%u,%u,%u,%u,%u}",
- name ? name : "[nullhost]",
- service ? service : "[nullservice]",
- netcontext.app_netid, netcontext.app_mark,
- netcontext.dns_netid, netcontext.dns_mark,
- netcontext.uid);
- }
-
- DnsProxyListener::GetAddrInfoHandler* handler =
- new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netcontext);
- tryThreadOrError(cli, handler);
- return 0;
-}
-
-/*******************************************************
- * ResNSendCommand *
- *******************************************************/
-DnsProxyListener::ResNSendCommand::ResNSendCommand(DnsProxyListener* dnsProxyListener)
- : NetdCommand("resnsend"), mDnsProxyListener(dnsProxyListener) {}
-
-int DnsProxyListener::ResNSendCommand::runCommand(SocketClient* cli, int argc, char** argv) {
- if (DBG) logArguments(argc, argv);
-
- const uid_t uid = cli->getUid();
- if (argc != 4) {
- ALOGW("resnsend: from UID %d, invalid number of arguments to resnsend: %d", uid, argc);
- sendBE32(cli, -EINVAL);
- return -1;
- }
-
- unsigned netId;
- if (!simpleStrtoul(argv[1], &netId)) {
- ALOGW("resnsend: from UID %d, invalid netId", uid);
- sendBE32(cli, -EINVAL);
- return -1;
- }
-
- uint32_t flags;
- if (!simpleStrtoul(argv[2], &flags)) {
- ALOGW("resnsend: from UID %d, invalid flags", uid);
- sendBE32(cli, -EINVAL);
- return -1;
- }
-
- android_net_context netcontext;
- mDnsProxyListener->mNetCtrl->getNetworkContext(netId, uid, &netcontext);
- if (checkAndClearUseLocalNameserversFlag(&netId)) {
- netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS;
- }
-
- DnsProxyListener::ResNSendHandler* handler =
- new DnsProxyListener::ResNSendHandler(cli, argv[3], flags, netcontext);
- tryThreadOrError(cli, handler);
- return 0;
-}
-
-DnsProxyListener::ResNSendHandler::ResNSendHandler(SocketClient* c, std::string msg, uint32_t flags,
- const android_net_context& netcontext)
- : mClient(c), mMsg(std::move(msg)), mFlags(flags), mNetContext(netcontext) {}
-
-DnsProxyListener::ResNSendHandler::~ResNSendHandler() {
- mClient->decRef();
-}
-
-void DnsProxyListener::ResNSendHandler::run() {
- if (DBG) {
- ALOGD("ResNSendHandler, now for %s %u/ {%u,%u,%u,%u,%u,%u}", mMsg.c_str(), mFlags,
- mNetContext.app_netid, mNetContext.app_mark, mNetContext.dns_netid,
- mNetContext.dns_mark, mNetContext.uid, mNetContext.flags);
- }
-
- Stopwatch s;
- maybeFixupNetContext(&mNetContext);
-
- // Decode
- std::vector<uint8_t> msg(MAXPACKET, 0);
-
- // Max length of mMsg is less than 1024 since the CMD_BUF_SIZE in FrameworkListener is 1024
- int msgLen = b64_pton(mMsg.c_str(), msg.data(), MAXPACKET);
- if (msgLen == -1) {
- // Decode fail
- sendBE32(mClient, -EILSEQ);
- return;
- }
-
- const uid_t uid = mClient->getUid();
- int rr_type = 0;
- std::string rr_name;
-
- // TODO: Handle the case which is msg contains more than one query
- // Parse and store query type/name
- if (!parseQuery(msg.data(), msgLen, &rr_type, &rr_name)) {
- // If the query couldn't be parsed, block the request.
- ALOGW("resnsend: from UID %d, invalid query", uid);
- sendBE32(mClient, -EINVAL);
- return;
- }
-
- // Send DNS query
- std::vector<uint8_t> ansBuf(MAXPACKET, 0);
- int arcode, nsendAns = -1;
- if (queryLimiter.start(uid)) {
- nsendAns = RESOLV_STUB.resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(),
- MAXPACKET, &arcode,
- static_cast<ResNsendFlags>(mFlags));
- queryLimiter.finish(uid);
- } else {
- ALOGW("resnsend: from UID %d, max concurrent queries reached", uid);
- nsendAns = -EBUSY;
- }
-
- const int latencyUs = int(s.timeTakenUs());
-
- // Fail, send -errno
- if (nsendAns < 0) {
- sendBE32(mClient, nsendAns);
- if (rr_type == ns_t_a || rr_type == ns_t_aaaa) {
- reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
- resNSendToAiError(nsendAns, arcode), rr_name);
- }
- return;
- }
-
- // Send rcode
- if (!sendBE32(mClient, arcode)) {
- ALOGW("resnsend: failed to send rcode to uid %d: %s", uid, strerror(errno));
- return;
- }
-
- // Send answer
- if (!sendLenAndData(mClient, nsendAns, ansBuf.data())) {
- ALOGW("resnsend: failed to send answer to uid %d: %s", uid, strerror(errno));
- return;
- }
-
- if (rr_type == ns_t_a || rr_type == ns_t_aaaa) {
- std::vector<std::string> ip_addrs;
- const int total_ip_addr_count =
- extractResNsendAnswers((uint8_t*) ansBuf.data(), nsendAns, rr_type, &ip_addrs);
- reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
- resNSendToAiError(nsendAns, arcode), rr_name, ip_addrs, total_ip_addr_count);
- }
-}
-
-/*******************************************************
- * GetHostByName *
- *******************************************************/
-DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd(DnsProxyListener* dnsProxyListener) :
- NetdCommand("gethostbyname"),
- mDnsProxyListener(dnsProxyListener) {
-}
-
-int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
- if (DBG) logArguments(argc, argv);
-
- if (argc != 4) {
- char* msg = nullptr;
- asprintf(&msg, "Invalid number of arguments to gethostbyname: %i", argc);
- ALOGW("%s", msg);
- cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
- free(msg);
- return -1;
- }
-
- uid_t uid = cli->getUid();
- unsigned netId = strtoul(argv[1], nullptr, 10);
- const bool useLocalNameservers = checkAndClearUseLocalNameserversFlag(&netId);
- char* name = argv[2];
- int af = strtol(argv[3], nullptr, 10);
-
- if (strcmp(name, "^") == 0) {
- name = nullptr;
- } else {
- name = strdup(name);
- }
-
- android_net_context netcontext;
- mDnsProxyListener->mNetCtrl->getNetworkContext(netId, uid, &netcontext);
- if (useLocalNameservers) {
- netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS;
- }
-
- DnsProxyListener::GetHostByNameHandler* handler =
- new DnsProxyListener::GetHostByNameHandler(cli, name, af, netcontext);
- tryThreadOrError(cli, handler);
- return 0;
-}
-
-DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c, char* name, int af,
- const android_net_context& netcontext)
- : mClient(c), mName(name), mAf(af), mNetContext(netcontext) {}
-
-DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
- free(mName);
-}
-
-void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, struct hostent** hpp) {
- netdutils::IPPrefix prefix{};
- // Don't have to consider family AF_UNSPEC case because gethostbyname{, 2} only supports
- // family AF_INET or AF_INET6.
- const bool ipv6WantedButNoData = (mAf == AF_INET6 && *rv == EAI_NODATA);
-
- if (!ipv6WantedButNoData) {
- return;
- }
-
- if (net::gCtls->resolverCtrl.getPrefix64(mNetContext.dns_netid, &prefix)) {
- return;
- }
-
- // If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis
- const uid_t uid = mClient->getUid();
- if (queryLimiter.start(uid)) {
- *rv = RESOLV_STUB.android_gethostbynamefornetcontext(mName, AF_INET, &mNetContext, hpp);
- queryLimiter.finish(uid);
- if (*rv) {
- *rv = EAI_NODATA; // return original error code
- return;
- }
- } else {
- ALOGE("gethostbyname: from UID %d, max concurrent queries reached", uid);
- return;
- }
-
- if (!synthesizeNat64PrefixWithARecord(prefix, *hpp)) {
- // If caller wants IPv6 answers but no data and failed to synthesize IPv4 answers,
- // don't return the IPv4 answers.
- *hpp = nullptr;
- }
-}
-
-void DnsProxyListener::GetHostByNameHandler::run() {
- if (DBG) {
- ALOGD("DnsProxyListener::GetHostByNameHandler::run");
- }
-
- Stopwatch s;
- maybeFixupNetContext(&mNetContext);
- const uid_t uid = mClient->getUid();
- hostent* hp = nullptr;
- int32_t rv = 0;
- if (queryLimiter.start(uid)) {
- rv = RESOLV_STUB.android_gethostbynamefornetcontext(mName, mAf, &mNetContext, &hp);
- queryLimiter.finish(uid);
- } else {
- rv = EAI_MEMORY;
- ALOGE("gethostbyname: from UID %d, max concurrent queries reached", uid);
- }
-
- doDns64Synthesis(&rv, &hp);
- const int latencyUs = lround(s.timeTakenUs());
-
- if (DBG) {
- ALOGD("GetHostByNameHandler::run gethostbyname errno: %s hp->h_name = %s, name_len = %zu",
- hp ? "success" : strerror(errno),
- (hp && hp->h_name) ? hp->h_name : "null",
- (hp && hp->h_name) ? strlen(hp->h_name) + 1 : 0);
- }
-
- bool success = true;
- if (hp) {
- // hp is not nullptr iff. rv is 0.
- success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
- success &= sendhostent(mClient, hp);
- } else {
- success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, nullptr, 0) == 0;
- }
-
- if (!success) {
- ALOGW("GetHostByNameHandler: Error writing DNS result to client");
- }
-
- std::vector<std::string> ip_addrs;
- const int total_ip_addr_count = extractGetHostByNameAnswers(hp, &ip_addrs);
- reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYNAME, mNetContext, latencyUs, rv, mName,
- ip_addrs, total_ip_addr_count);
- mClient->decRef();
-}
-
-
-/*******************************************************
- * GetHostByAddr *
- *******************************************************/
-DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd(const DnsProxyListener* dnsProxyListener) :
- NetdCommand("gethostbyaddr"),
- mDnsProxyListener(dnsProxyListener) {
-}
-
-int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
- if (DBG) logArguments(argc, argv);
-
- if (argc != 5) {
- char* msg = nullptr;
- asprintf(&msg, "Invalid number of arguments to gethostbyaddr: %i", argc);
- ALOGW("%s", msg);
- cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
- free(msg);
- return -1;
- }
-
- char* addrStr = argv[1];
- int addrLen = strtol(argv[2], nullptr, 10);
- int addrFamily = strtol(argv[3], nullptr, 10);
- uid_t uid = cli->getUid();
- unsigned netId = strtoul(argv[4], nullptr, 10);
- const bool useLocalNameservers = checkAndClearUseLocalNameserversFlag(&netId);
-
- void* addr = malloc(sizeof(in6_addr));
- errno = 0;
- int result = inet_pton(addrFamily, addrStr, addr);
- if (result <= 0) {
- char* msg = nullptr;
- asprintf(&msg, "inet_pton(\"%s\") failed %s", addrStr, strerror(errno));
- ALOGW("%s", msg);
- cli->sendMsg(ResponseCode::OperationFailed, msg, false);
- free(addr);
- free(msg);
- return -1;
- }
-
- android_net_context netcontext;
- mDnsProxyListener->mNetCtrl->getNetworkContext(netId, uid, &netcontext);
- if (useLocalNameservers) {
- netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS;
- }
-
- DnsProxyListener::GetHostByAddrHandler* handler = new DnsProxyListener::GetHostByAddrHandler(
- cli, addr, addrLen, addrFamily, netcontext);
- tryThreadOrError(cli, handler);
- return 0;
-}
-
-DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c, void* address,
- int addressLen, int addressFamily,
- const android_net_context& netcontext)
- : mClient(c),
- mAddress(address),
- mAddressLen(addressLen),
- mAddressFamily(addressFamily),
- mNetContext(netcontext) {}
-
-DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
- free(mAddress);
-}
-
-void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent** hpp) {
- if (*hpp != nullptr || mAddressFamily != AF_INET6 || !mAddress) {
- return;
- }
-
- netdutils::IPPrefix prefix{};
- if (net::gCtls->resolverCtrl.getPrefix64(mNetContext.dns_netid, &prefix)) {
- return;
- }
-
- if (!isValidNat64Prefix(prefix)) {
- return;
- }
-
- struct sockaddr_storage ss = netdutils::IPSockAddr(prefix.ip());
- struct sockaddr_in6* v6prefix = (struct sockaddr_in6*) &ss;
- struct in6_addr v6addr = *(in6_addr*) mAddress;
- // Check if address has NAT64 prefix. Only /96 IPv6 NAT64 prefixes are supported
- if ((v6addr.s6_addr32[0] != v6prefix->sin6_addr.s6_addr32[0]) ||
- (v6addr.s6_addr32[1] != v6prefix->sin6_addr.s6_addr32[1]) ||
- (v6addr.s6_addr32[2] != v6prefix->sin6_addr.s6_addr32[2])) {
- return;
- }
-
- const uid_t uid = mClient->getUid();
- if (queryLimiter.start(uid)) {
- // Remove NAT64 prefix and do reverse DNS query
- struct in_addr v4addr = {.s_addr = v6addr.s6_addr32[3]};
- RESOLV_STUB.android_gethostbyaddrfornetcontext(&v4addr, sizeof(v4addr), AF_INET,
- &mNetContext, hpp);
- queryLimiter.finish(uid);
- if (*hpp) {
- // Replace IPv4 address with original queried IPv6 address in place. The space has
- // reserved by _dns_gethtbyaddr() and netbsd_gethostent_r() in
- // system/netd/resolv/gethnamaddr.cpp.
- // Note that android_gethostbyaddrfornetcontext returns only one entry in result.
- memcpy((*hpp)->h_addr_list[0], &v6addr, sizeof(v6addr));
- (*hpp)->h_addrtype = AF_INET6;
- (*hpp)->h_length = sizeof(struct in6_addr);
- }
- } else {
- ALOGE("gethostbyaddr: from UID %d, max concurrent queries reached", uid);
- }
-}
-
-void DnsProxyListener::GetHostByAddrHandler::run() {
- if (DBG) {
- ALOGD("DnsProxyListener::GetHostByAddrHandler::run");
- }
-
- Stopwatch s;
- maybeFixupNetContext(&mNetContext);
- const uid_t uid = mClient->getUid();
- hostent* hp = nullptr;
- int32_t rv = 0;
- if (queryLimiter.start(uid)) {
- rv = RESOLV_STUB.android_gethostbyaddrfornetcontext(mAddress, mAddressLen, mAddressFamily,
- &mNetContext, &hp);
- queryLimiter.finish(uid);
- } else {
- rv = EAI_MEMORY;
- ALOGE("gethostbyaddr: from UID %d, max concurrent queries reached", uid);
- }
-
- doDns64ReverseLookup(&hp);
- const int latencyUs = int(s.timeTakenUs());
-
- if (DBG) {
- ALOGD("GetHostByAddrHandler::run gethostbyaddr result: %s hp->h_name = %s, name_len = %zu",
- hp ? "success" : gai_strerror(rv), (hp && hp->h_name) ? hp->h_name : "null",
- (hp && hp->h_name) ? strlen(hp->h_name) + 1 : 0);
- }
-
- bool success = true;
- if (hp) {
- success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
- success &= sendhostent(mClient, hp);
- } else {
- success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, nullptr, 0) == 0;
- }
-
- if (!success) {
- ALOGW("GetHostByAddrHandler: Error writing DNS result to client");
- }
-
- reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYADDR, mNetContext, latencyUs, rv,
- (hp && hp->h_name) ? hp->h_name : "null", {}, 0);
- mClient->decRef();
-}
-
-} // namespace net
-} // namespace android
diff --git a/server/DnsProxyListener.h b/server/DnsProxyListener.h
deleted file mode 100644
index e34f82e..0000000
--- a/server/DnsProxyListener.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2010 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 _DNSPROXYLISTENER_H__
-#define _DNSPROXYLISTENER_H__
-
-#include <binder/IServiceManager.h>
-#include <sysutils/FrameworkListener.h>
-
-#include "NetdCommand.h"
-#include "netd_resolv/resolv.h" // android_net_context
-
-namespace android {
-namespace net {
-
-class NetworkController;
-
-class DnsProxyListener : public FrameworkListener {
- public:
- explicit DnsProxyListener(const NetworkController* netCtrl);
- virtual ~DnsProxyListener() {}
-
- static constexpr const char* SOCKET_NAME = "dnsproxyd";
-
- private:
- const NetworkController *mNetCtrl;
-
- class GetAddrInfoCmd : public NetdCommand {
- public:
- explicit GetAddrInfoCmd(DnsProxyListener* dnsProxyListener);
- virtual ~GetAddrInfoCmd() {}
- int runCommand(SocketClient* c, int argc, char** argv) override;
-
- private:
- DnsProxyListener* mDnsProxyListener;
- };
-
- /* ------ getaddrinfo ------*/
- class GetAddrInfoHandler {
- public:
- // Note: All of host, service, and hints may be NULL
- GetAddrInfoHandler(SocketClient* c, char* host, char* service, addrinfo* hints,
- const android_net_context& netcontext);
- ~GetAddrInfoHandler();
-
- void run();
-
- private:
- void doDns64Synthesis(int32_t* rv, addrinfo** res);
-
- SocketClient* mClient; // ref counted
- char* mHost; // owned. TODO: convert to std::string.
- char* mService; // owned. TODO: convert to std::string.
- addrinfo* mHints; // owned
- android_net_context mNetContext;
- };
-
- /* ------ gethostbyname ------*/
- class GetHostByNameCmd : public NetdCommand {
- public:
- explicit GetHostByNameCmd(DnsProxyListener* dnsProxyListener);
- virtual ~GetHostByNameCmd() {}
- int runCommand(SocketClient* c, int argc, char** argv) override;
-
- private:
- DnsProxyListener* mDnsProxyListener;
- };
-
- class GetHostByNameHandler {
- public:
- GetHostByNameHandler(SocketClient* c, char* name, int af,
- const android_net_context& netcontext);
- ~GetHostByNameHandler();
-
- void run();
-
- private:
- void doDns64Synthesis(int32_t* rv, hostent** hpp);
-
- SocketClient* mClient; //ref counted
- char* mName; // owned. TODO: convert to std::string.
- int mAf;
- android_net_context mNetContext;
- };
-
- /* ------ gethostbyaddr ------*/
- class GetHostByAddrCmd : public NetdCommand {
- public:
- explicit GetHostByAddrCmd(const DnsProxyListener* dnsProxyListener);
- virtual ~GetHostByAddrCmd() {}
- int runCommand(SocketClient* c, int argc, char** argv) override;
-
- private:
- const DnsProxyListener* mDnsProxyListener;
- };
-
- class GetHostByAddrHandler {
- public:
- GetHostByAddrHandler(SocketClient* c, void* address, int addressLen, int addressFamily,
- const android_net_context& netcontext);
- ~GetHostByAddrHandler();
-
- void run();
-
- private:
- void doDns64ReverseLookup(hostent** hpp);
-
- SocketClient* mClient; // ref counted
- void* mAddress; // address to lookup; owned
- int mAddressLen; // length of address to look up
- int mAddressFamily; // address family
- android_net_context mNetContext;
- };
-
- /* ------ resnsend ------*/
- class ResNSendCommand : public NetdCommand {
- public:
- explicit ResNSendCommand(DnsProxyListener* dnsProxyListener);
- ~ResNSendCommand() override {}
- int runCommand(SocketClient* c, int argc, char** argv) override;
-
- private:
- DnsProxyListener* mDnsProxyListener;
- };
-
- class ResNSendHandler {
- public:
- ResNSendHandler(SocketClient* c, std::string msg, uint32_t flags,
- const android_net_context& netcontext);
- ~ResNSendHandler();
-
- void run();
-
- private:
- SocketClient* mClient; // ref counted
- std::string mMsg;
- uint32_t mFlags;
- android_net_context mNetContext;
- };
-};
-
-} // namespace net
-} // namespace android
-
-#endif
diff --git a/server/EventReporter.h b/server/EventReporter.h
index d4dc93d..7dfa659 100644
--- a/server/EventReporter.h
+++ b/server/EventReporter.h
@@ -37,7 +37,7 @@
// std::atomic<android::net::metrics::INetdEventListener> and deleting the mutex.
//
// Alternatively, if this locking causes a performance penalty, have each single-threaded
- // caller (DnsProxyListener, FwmarkServer) keep their own per-thread copy of NetdEventListener
+ // caller (FwmarkServer) keep their own per-thread copy of NetdEventListener
// and remove mNetdEventListener entirely.
android::sp<android::net::metrics::INetdEventListener> mNetdEventListener;
std::mutex mutex;
diff --git a/server/ResolvStub.cpp b/server/ResolvStub.cpp
index dafd58f..774b651 100644
--- a/server/ResolvStub.cpp
+++ b/server/ResolvStub.cpp
@@ -84,6 +84,7 @@
RESOLV_STUB_LOAD_SYMBOL(resolv_delete_private_dns_for_net);
RESOLV_STUB_LOAD_SYMBOL(resolv_get_private_dns_status_for_net);
RESOLV_STUB_LOAD_SYMBOL(resolv_has_nameservers);
+ RESOLV_STUB_LOAD_SYMBOL(resolv_init);
RESOLV_STUB_LOAD_SYMBOL(resolv_register_private_dns_callback);
RESOLV_STUB_LOAD_SYMBOL(resolv_res_nsend);
RESOLV_STUB_LOAD_SYMBOL(resolv_set_nameservers_for_net);
diff --git a/server/ResolverController.cpp b/server/ResolverController.cpp
index 39a0b83..c746f26 100644
--- a/server/ResolverController.cpp
+++ b/server/ResolverController.cpp
@@ -108,6 +108,24 @@
}
}
+void getNetworkContextCallback(uint32_t netId, uint32_t uid, android_net_context* netcontext) {
+ net::gCtls->netCtrl.getNetworkContext(netId, uid, netcontext);
+}
+
+bool getDns64PrefixCallback(unsigned netId, in6_addr* v6addr, uint8_t* prefix_len) {
+ netdutils::IPPrefix prefix{};
+ if (net::gCtls->resolverCtrl.getPrefix64(netId, &prefix) != 0) {
+ return false;
+ }
+ *v6addr = prefix.addr6();
+ *prefix_len = prefix.length();
+ return true;
+}
+
+bool checkCallingPermissionCallback(const char* permission) {
+ return checkCallingPermission(String16(permission));
+}
+
bool allIPv6Only(const std::vector<std::string>& servers) {
for (const auto& server : servers) {
if (server.find(':') == std::string::npos) return false;
@@ -356,6 +374,15 @@
args.prefixLength);
}
+bool ResolverController::initResolver() {
+ dnsproxylistener_callbacks callbacks = {
+ .get_network_context = &getNetworkContextCallback,
+ .get_dns64_prefix = &getDns64PrefixCallback,
+ .check_calling_permission = &checkCallingPermissionCallback,
+ };
+ return RESOLV_STUB.resolv_init(callbacks);
+}
+
void ResolverController::dump(DumpWriter& dw, unsigned netId) {
// No lock needed since Bionic's resolver locks all accessed data structures internally.
using android::net::ResolverStats;
diff --git a/server/ResolverController.h b/server/ResolverController.h
index bcb82db..4a104ed 100644
--- a/server/ResolverController.h
+++ b/server/ResolverController.h
@@ -64,6 +64,8 @@
void sendNat64PrefixEvent(const net::Dns64Configuration::Nat64PrefixInfo& args);
+ bool initResolver();
+
void dump(DumpWriter& dw, unsigned netId);
private:
diff --git a/server/main.cpp b/server/main.cpp
index 51ce7ea..fd0856e 100644
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -39,7 +39,6 @@
#include "CommandListener.h"
#include "Controllers.h"
-#include "DnsProxyListener.h"
#include "FwmarkServer.h"
#include "MDnsSdListener.h"
#include "NFLogListener.h"
@@ -58,7 +57,6 @@
using android::ProcessState;
using android::defaultServiceManager;
using android::net::CommandListener;
-using android::net::DnsProxyListener;
using android::net::FwmarkServer;
using android::net::NetdHwService;
using android::net::NetdNativeService;
@@ -67,6 +65,7 @@
using android::net::makeNFLogListener;
const char* const PID_FILE_PATH = "/data/misc/net/netd_pid";
+constexpr const char DNSPROXYLISTENER_SOCKET_NAME[] = "dnsproxyd";
std::mutex android::net::gBigNetdLock;
@@ -83,7 +82,7 @@
// FrameworkListener does this on initialization as well, but we only initialize these
// components after having initialized other subsystems that can fork.
for (const auto& sock : { CommandListener::SOCKET_NAME,
- DnsProxyListener::SOCKET_NAME,
+ DNSPROXYLISTENER_SOCKET_NAME,
FwmarkServer::SOCKET_NAME,
MDnsSdListener::SOCKET_NAME }) {
setCloseOnExec(sock);
@@ -132,10 +131,11 @@
// Set local DNS mode, to prevent bionic from proxying
// back to this service, recursively.
+ // TODO: Check if we could remove it since resolver cache no loger
+ // checks this environment variable after aosp/838050.
setenv("ANDROID_DNS_MODE", "local", 1);
- DnsProxyListener dpl(&gCtls->netCtrl);
- if (dpl.startListener()) {
- ALOGE("Unable to start DnsProxyListener (%s)", strerror(errno));
+ if (!gCtls->resolverCtrl.initResolver()) {
+ ALOGE("Unable to init resolver");
exit(1);
}