Loading Android.bp +10 −2 Original line number Diff line number Diff line Loading @@ -13,6 +13,10 @@ cc_library_headers { cc_library_headers { name: "dnsproxyd_protocol_headers", export_include_dirs: ["include/dnsproxyd_protocol"], apex_available: [ "//apex_available:platform", "com.android.tethering", ], } aidl_interface { Loading @@ -23,6 +27,8 @@ aidl_interface { "binder/android/net/ResolverHostsParcel.aidl", "binder/android/net/ResolverOptionsParcel.aidl", "binder/android/net/ResolverParamsParcel.aidl", // New AIDL classes should go into android.net.resolv.aidl so they can be clearly identified "binder/android/net/resolv/aidl/**/*.aidl", ], imports: [ "netd_event_listener_interface", Loading Loading @@ -50,6 +56,7 @@ aidl_interface { "4", "5", "6", "7", ], } Loading Loading @@ -101,7 +108,6 @@ cc_library { "res_cache.cpp", "res_comp.cpp", "res_debug.cpp", "res_init.cpp", "res_mkquery.cpp", "res_query.cpp", "res_send.cpp", Loading Loading @@ -259,6 +265,8 @@ cc_test { "DnsQueryLogTest.cpp", "DnsStatsTest.cpp", "ExperimentsTest.cpp", "OperationLimiterTest.cpp", "PrivateDnsConfigurationTest.cpp", ], shared_libs: [ "libcrypto", Loading @@ -268,7 +276,7 @@ cc_test { static_libs: [ "dnsresolver_aidl_interface-unstable-ndk_platform", "netd_aidl_interface-ndk_platform", "netd_event_listener_interface-ndk_platform", "netd_event_listener_interface-unstable-ndk_platform", "libcutils", "libgmock", "libnetd_resolv", Loading DnsProxyListener.cpp +86 −140 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ #include <cutils/misc.h> // FIRST_APPLICATION_UID #include <cutils/multiuser.h> #include <netdutils/InternetAddresses.h> #include <netdutils/OperationLimiter.h> #include <netdutils/ResponseCode.h> #include <netdutils/Slice.h> #include <netdutils/Stopwatch.h> Loading @@ -50,6 +49,7 @@ #include "DnsResolver.h" #include "NetdPermissions.h" #include "OperationLimiter.h" #include "PrivateDnsConfiguration.h" #include "ResolverEventReporter.h" #include "dnsproxyd_protocol/DnsProxydProtocol.h" // NETID_USE_LOCAL_NAMESERVERS Loading Loading @@ -84,25 +84,6 @@ void logArguments(int argc, char** argv) { } } template<typename T> void tryThreadOrError(SocketClient* cli, T* handler) { cli->incRef(); const int rval = netdutils::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; Loading Loading @@ -563,21 +544,31 @@ DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { registerCmd(new GetDnsNetIdCommand()); } 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) {} void DnsProxyListener::Handler::spawn() { const int rval = netdutils::threadLaunch(this); if (rval == 0) { return; } DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() { free(mHost); free(mService); free(mHints); char* msg = nullptr; asprintf(&msg, "%s (%d)", strerror(-rval), -rval); mClient->sendMsg(ResponseCode::OperationFailed, msg, false); free(msg); delete this; } static bool evaluate_domain_name(const android_net_context &netcontext, const char *host) { if (!gResNetdCallbacks.evaluate_domain_name) return true; DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient* c, std::string host, std::string service, std::unique_ptr<addrinfo> hints, const android_net_context& netcontext) : Handler(c), mHost(move(host)), mService(move(service)), mHints(move(hints)), mNetContext(netcontext) {} static bool evaluate_domain_name(const android_net_context& netcontext, const char* host) { if (!gResNetdCallbacks.evaluate_domain_name) return true; return gResNetdCallbacks.evaluate_domain_name(netcontext, host); } Loading Loading @@ -634,11 +625,8 @@ static bool sendaddrinfo(SocketClient* c, addrinfo* ai) { // 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); 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; } Loading @@ -658,8 +646,6 @@ static bool sendaddrinfo(SocketClient* c, addrinfo* ai) { void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinfo** res, NetworkDnsEventReported* event) { 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)); Loading @@ -677,10 +663,12 @@ void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinf // 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)) { 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(mHost, mService, mHints, &mNetContext, res, event); *rv = resolv_getaddrinfo(host, service, mHints.get(), &mNetContext, res, event); queryLimiter.finish(uid); if (*rv) { *rv = EAI_NODATA; // return original error code Loading Loading @@ -718,9 +706,10 @@ void DnsProxyListener::GetAddrInfoHandler::run() { NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { if (evaluate_domain_name(mNetContext, mHost)) { rv = resolv_getaddrinfo(mHost, mService, mHints, &mNetContext, &result, &event); const char* host = mHost.starts_with('^') ? nullptr : mHost.c_str(); 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); } else { rv = EAI_SYSTEM; } Loading Loading @@ -763,7 +752,6 @@ void DnsProxyListener::GetAddrInfoHandler::run() { reportDnsEvent(INetdEventListener::EVENT_GETADDRINFO, mNetContext, latencyUs, rv, event, mHost, ip_addrs, total_ip_addr_count); freeaddrinfo(result); mClient->decRef(); } std::string DnsProxyListener::GetAddrInfoHandler::threadName() { Loading @@ -789,8 +777,7 @@ void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* ad DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() : FrameworkCommand("getaddrinfo") {} int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, int argc, char **argv) { int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient* cli, int argc, char** argv) { logArguments(argc, argv); if (argc != 8) { Loading @@ -802,21 +789,8 @@ int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, 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; const std::string name = argv[1]; const std::string service = argv[2]; int ai_flags = strtol(argv[3], nullptr, 10); int ai_family = strtol(argv[4], nullptr, 10); int ai_socktype = strtol(argv[5], nullptr, 10); Loading @@ -832,18 +806,16 @@ int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, 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)); std::unique_ptr<addrinfo> hints; if (ai_flags != -1 || ai_family != -1 || ai_socktype != -1 || ai_protocol != -1) { hints.reset((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; } DnsProxyListener::GetAddrInfoHandler* handler = new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netcontext); tryThreadOrError(cli, handler); (new GetAddrInfoHandler(cli, name, service, move(hints), netcontext))->spawn(); return 0; } Loading Loading @@ -888,19 +860,13 @@ int DnsProxyListener::ResNSendCommand::runCommand(SocketClient* cli, int argc, c netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS; } DnsProxyListener::ResNSendHandler* handler = new DnsProxyListener::ResNSendHandler(cli, argv[3], flags, netcontext); tryThreadOrError(cli, handler); (new ResNSendHandler(cli, argv[3], flags, netcontext))->spawn(); 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(); } : Handler(c), mMsg(std::move(msg)), mFlags(flags), mNetContext(netcontext) {} void DnsProxyListener::ResNSendHandler::run() { LOG(DEBUG) << "ResNSendHandler::run: " << mFlags << " / {" << mNetContext.app_netid << " " Loading Loading @@ -1058,8 +1024,7 @@ int DnsProxyListener::GetDnsNetIdCommand::runCommand(SocketClient* cli, int argc *******************************************************/ DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd() : FrameworkCommand("gethostbyname") {} int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, int argc, char **argv) { int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient* cli, int argc, char** argv) { logArguments(argc, argv); if (argc != 4) { Loading @@ -1074,15 +1039,9 @@ int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, uid_t uid = cli->getUid(); unsigned netId = strtoul(argv[1], nullptr, 10); const bool useLocalNameservers = checkAndClearUseLocalNameserversFlag(&netId); char* name = argv[2]; std::string name = argv[2]; int af = strtol(argv[3], nullptr, 10); if (strcmp(name, "^") == 0) { name = nullptr; } else { name = strdup(name); } android_net_context netcontext; gResNetdCallbacks.get_network_context(netId, uid, &netcontext); Loading @@ -1090,19 +1049,14 @@ int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS; } DnsProxyListener::GetHostByNameHandler* handler = new DnsProxyListener::GetHostByNameHandler(cli, name, af, netcontext); tryThreadOrError(cli, handler); (new GetHostByNameHandler(cli, name, af, netcontext))->spawn(); return 0; } DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c, char* name, int af, DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c, std::string name, int af, const android_net_context& netcontext) : mClient(c), mName(name), mAf(af), mNetContext(netcontext) {} DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() { free(mName); } : Handler(c), mName(move(name)), mAf(af), mNetContext(netcontext) {} void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, hostent* hbuf, char* buf, size_t buflen, struct hostent** hpp, Loading @@ -1123,7 +1077,8 @@ 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 (queryLimiter.start(uid)) { *rv = resolv_gethostbyname(mName, AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); *rv = resolv_gethostbyname(name, AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); queryLimiter.finish(uid); if (*rv) { *rv = EAI_NODATA; // return original error code Loading Loading @@ -1152,8 +1107,9 @@ void DnsProxyListener::GetHostByNameHandler::run() { NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { if (evaluate_domain_name(mNetContext, mName)) { rv = resolv_gethostbyname(mName, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); if (evaluate_domain_name(mNetContext, name)) { rv = resolv_gethostbyname(name, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); } else { rv = EAI_SYSTEM; Loading Loading @@ -1190,7 +1146,6 @@ void DnsProxyListener::GetHostByNameHandler::run() { const int total_ip_addr_count = extractGetHostByNameAnswers(hp, &ip_addrs); reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYNAME, mNetContext, latencyUs, rv, event, mName, ip_addrs, total_ip_addr_count); mClient->decRef(); } std::string DnsProxyListener::GetHostByNameHandler::threadName() { Loading @@ -1202,8 +1157,7 @@ std::string DnsProxyListener::GetHostByNameHandler::threadName() { *******************************************************/ DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd() : FrameworkCommand("gethostbyaddr") {} int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, int argc, char **argv) { int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient* cli, int argc, char** argv) { logArguments(argc, argv); if (argc != 5) { Loading @@ -1222,15 +1176,14 @@ int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, unsigned netId = strtoul(argv[4], nullptr, 10); const bool useLocalNameservers = checkAndClearUseLocalNameserversFlag(&netId); void* addr = malloc(sizeof(in6_addr)); in6_addr addr; errno = 0; int result = inet_pton(addrFamily, addrStr, addr); int result = inet_pton(addrFamily, addrStr, &addr); if (result <= 0) { char* msg = nullptr; asprintf(&msg, "inet_pton(\"%s\") failed %s", addrStr, strerror(errno)); LOG(WARNING) << "GetHostByAddrCmd::runCommand: " << (msg ? msg : "null"); cli->sendMsg(ResponseCode::OperationFailed, msg, false); free(addr); free(msg); return -1; } Loading @@ -1242,30 +1195,24 @@ int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS; } DnsProxyListener::GetHostByAddrHandler* handler = new DnsProxyListener::GetHostByAddrHandler( cli, addr, addrLen, addrFamily, netcontext); tryThreadOrError(cli, handler); (new GetHostByAddrHandler(cli, addr, addrLen, addrFamily, netcontext))->spawn(); return 0; } DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c, void* address, DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c, in6_addr address, int addressLen, int addressFamily, const android_net_context& netcontext) : mClient(c), : Handler(c), mAddress(address), mAddressLen(addressLen), mAddressFamily(addressFamily), mNetContext(netcontext) {} DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() { free(mAddress); } void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, char* buf, size_t buflen, struct hostent** hpp, NetworkDnsEventReported* event) { if (*hpp != nullptr || mAddressFamily != AF_INET6 || !mAddress) { if (*hpp != nullptr || mAddressFamily != AF_INET6) { return; } Loading @@ -1280,7 +1227,7 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, struct sockaddr_storage ss = netdutils::IPSockAddr(prefix.ip()); struct sockaddr_in6* v6prefix = (struct sockaddr_in6*)&ss; struct in6_addr v6addr = *(in6_addr*) mAddress; struct in6_addr v6addr = 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]) || Loading Loading @@ -1320,7 +1267,7 @@ void DnsProxyListener::GetHostByAddrHandler::run() { NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { rv = resolv_gethostbyaddr(mAddress, mAddressLen, mAddressFamily, &hbuf, tmpbuf, rv = resolv_gethostbyaddr(&mAddress, mAddressLen, mAddressFamily, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); queryLimiter.finish(uid); } else { Loading Loading @@ -1351,7 +1298,6 @@ void DnsProxyListener::GetHostByAddrHandler::run() { reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYADDR, mNetContext, latencyUs, rv, event, (hp && hp->h_name) ? hp->h_name : "null", {}, 0); mClient->decRef(); } std::string DnsProxyListener::GetHostByAddrHandler::threadName() { Loading DnsProxyListener.h +42 −30 Original line number Diff line number Diff line Loading @@ -38,6 +38,23 @@ class DnsProxyListener : public FrameworkListener { static constexpr const char* SOCKET_NAME = "dnsproxyd"; private: class Handler { public: Handler(SocketClient* c) : mClient(c) { mClient->incRef(); } virtual ~Handler() { mClient->decRef(); } void operator=(const Handler&) = delete; // Attept to spawn the worker thread, or return an error to the client. // The Handler instance will self-delete in either case. void spawn(); virtual void run() = 0; virtual std::string threadName() = 0; SocketClient* mClient; // ref-counted }; /* ------ getaddrinfo ------*/ class GetAddrInfoCmd : public FrameworkCommand { public: GetAddrInfoCmd(); Loading @@ -45,24 +62,22 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; /* ------ getaddrinfo ------*/ class GetAddrInfoHandler { class GetAddrInfoHandler : public Handler { 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(); GetAddrInfoHandler(SocketClient* c, std::string host, std::string service, std::unique_ptr<addrinfo> hints, const android_net_context& netcontext); ~GetAddrInfoHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: void doDns64Synthesis(int32_t* rv, addrinfo** res, NetworkDnsEventReported* event); SocketClient* mClient; // ref counted char* mHost; // owned. TODO: convert to std::string. char* mService; // owned. TODO: convert to std::string. addrinfo* mHints; // owned std::string mHost; std::string mService; std::unique_ptr<addrinfo> mHints; android_net_context mNetContext; }; Loading @@ -74,21 +89,20 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; class GetHostByNameHandler { class GetHostByNameHandler : public Handler { public: GetHostByNameHandler(SocketClient* c, char* name, int af, GetHostByNameHandler(SocketClient* c, std::string name, int af, const android_net_context& netcontext); ~GetHostByNameHandler(); ~GetHostByNameHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: void doDns64Synthesis(int32_t* rv, hostent* hbuf, char* buf, size_t buflen, hostent** hpp, NetworkDnsEventReported* event); SocketClient* mClient; // ref counted char* mName; // owned. TODO: convert to std::string. std::string mName; int mAf; android_net_context mNetContext; }; Loading @@ -101,21 +115,20 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; class GetHostByAddrHandler { class GetHostByAddrHandler : public Handler { public: GetHostByAddrHandler(SocketClient* c, void* address, int addressLen, int addressFamily, GetHostByAddrHandler(SocketClient* c, in6_addr address, int addressLen, int addressFamily, const android_net_context& netcontext); ~GetHostByAddrHandler(); ~GetHostByAddrHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: void doDns64ReverseLookup(hostent* hbuf, char* buf, size_t buflen, hostent** hpp, NetworkDnsEventReported* event); SocketClient* mClient; // ref counted void* mAddress; // address to lookup; owned in6_addr mAddress; int mAddressLen; // length of address to look up int mAddressFamily; // address family android_net_context mNetContext; Loading @@ -129,17 +142,16 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; class ResNSendHandler { class ResNSendHandler : public Handler { public: ResNSendHandler(SocketClient* c, std::string msg, uint32_t flags, const android_net_context& netcontext); ~ResNSendHandler(); ~ResNSendHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: SocketClient* mClient; // ref counted std::string mMsg; uint32_t mFlags; android_net_context mNetContext; Loading DnsQueryLog.cpp +3 −19 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include "DnsQueryLog.h" #include <android-base/stringprintf.h> #include "util.h" namespace android::net { Loading Loading @@ -45,25 +45,10 @@ std::string maskIps(const std::vector<std::string>& ips) { return ret.empty() ? "" : ret.substr(0, ret.length() - 2); } // Return the readable string format "hr:min:sec.ms". std::string timestampToString(const std::chrono::system_clock::time_point& ts) { using std::chrono::duration_cast; using std::chrono::milliseconds; const auto time_sec = std::chrono::system_clock::to_time_t(ts); char buf[32]; std::strftime(buf, sizeof(buf), "%H:%M:%S", std::localtime(&time_sec)); int ms = duration_cast<milliseconds>(ts.time_since_epoch()).count() % 1000; return android::base::StringPrintf("%s.%03d", buf, ms); } } // namespace void DnsQueryLog::push(Record&& record) { std::lock_guard guard(mLock); mQueue.push_back(std::move(record)); if (mQueue.size() > mCapacity) { mQueue.pop_front(); } mQueue.push(std::move(record)); } void DnsQueryLog::dump(netdutils::DumpWriter& dw) const { Loading @@ -71,8 +56,7 @@ void DnsQueryLog::dump(netdutils::DumpWriter& dw) const { netdutils::ScopedIndent indentStats(dw); const auto now = std::chrono::system_clock::now(); std::lock_guard guard(mLock); for (const auto& record : mQueue) { for (const auto& record : mQueue.copy()) { if (now - record.timestamp > mValidityTimeMs) continue; const std::string maskedHostname = maskHostname(record.hostname); Loading DnsQueryLog.h +7 −9 Original line number Diff line number Diff line Loading @@ -17,16 +17,16 @@ #pragma once #include <deque> #include <string> #include <vector> #include <android-base/thread_annotations.h> #include <netdutils/DumpWriter.h> #include "LockedQueue.h" namespace android::net { // A circular buffer based class used for query logging. It's thread-safe for concurrent access. // This class stores query records in a locked ring buffer. It's thread-safe for concurrent access. class DnsQueryLog { public: static constexpr std::string_view DUMP_KEYWORD = "querylog"; Loading @@ -52,15 +52,13 @@ class DnsQueryLog { // Allow the tests to set the capacity and the validaty time in milliseconds. DnsQueryLog(size_t size = kDefaultLogSize, std::chrono::milliseconds time = kDefaultValidityMinutes) : mCapacity(size), mValidityTimeMs(time) {} : mQueue(size), mValidityTimeMs(time) {} void push(Record&& record) EXCLUDES(mLock); void dump(netdutils::DumpWriter& dw) const EXCLUDES(mLock); void push(Record&& record); void dump(netdutils::DumpWriter& dw) const; private: mutable std::mutex mLock; std::deque<Record> mQueue GUARDED_BY(mLock); const size_t mCapacity; LockedRingBuffer<Record> mQueue; const std::chrono::milliseconds mValidityTimeMs; // The capacity of the circular buffer. Loading Loading
Android.bp +10 −2 Original line number Diff line number Diff line Loading @@ -13,6 +13,10 @@ cc_library_headers { cc_library_headers { name: "dnsproxyd_protocol_headers", export_include_dirs: ["include/dnsproxyd_protocol"], apex_available: [ "//apex_available:platform", "com.android.tethering", ], } aidl_interface { Loading @@ -23,6 +27,8 @@ aidl_interface { "binder/android/net/ResolverHostsParcel.aidl", "binder/android/net/ResolverOptionsParcel.aidl", "binder/android/net/ResolverParamsParcel.aidl", // New AIDL classes should go into android.net.resolv.aidl so they can be clearly identified "binder/android/net/resolv/aidl/**/*.aidl", ], imports: [ "netd_event_listener_interface", Loading Loading @@ -50,6 +56,7 @@ aidl_interface { "4", "5", "6", "7", ], } Loading Loading @@ -101,7 +108,6 @@ cc_library { "res_cache.cpp", "res_comp.cpp", "res_debug.cpp", "res_init.cpp", "res_mkquery.cpp", "res_query.cpp", "res_send.cpp", Loading Loading @@ -259,6 +265,8 @@ cc_test { "DnsQueryLogTest.cpp", "DnsStatsTest.cpp", "ExperimentsTest.cpp", "OperationLimiterTest.cpp", "PrivateDnsConfigurationTest.cpp", ], shared_libs: [ "libcrypto", Loading @@ -268,7 +276,7 @@ cc_test { static_libs: [ "dnsresolver_aidl_interface-unstable-ndk_platform", "netd_aidl_interface-ndk_platform", "netd_event_listener_interface-ndk_platform", "netd_event_listener_interface-unstable-ndk_platform", "libcutils", "libgmock", "libnetd_resolv", Loading
DnsProxyListener.cpp +86 −140 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ #include <cutils/misc.h> // FIRST_APPLICATION_UID #include <cutils/multiuser.h> #include <netdutils/InternetAddresses.h> #include <netdutils/OperationLimiter.h> #include <netdutils/ResponseCode.h> #include <netdutils/Slice.h> #include <netdutils/Stopwatch.h> Loading @@ -50,6 +49,7 @@ #include "DnsResolver.h" #include "NetdPermissions.h" #include "OperationLimiter.h" #include "PrivateDnsConfiguration.h" #include "ResolverEventReporter.h" #include "dnsproxyd_protocol/DnsProxydProtocol.h" // NETID_USE_LOCAL_NAMESERVERS Loading Loading @@ -84,25 +84,6 @@ void logArguments(int argc, char** argv) { } } template<typename T> void tryThreadOrError(SocketClient* cli, T* handler) { cli->incRef(); const int rval = netdutils::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; Loading Loading @@ -563,21 +544,31 @@ DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { registerCmd(new GetDnsNetIdCommand()); } 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) {} void DnsProxyListener::Handler::spawn() { const int rval = netdutils::threadLaunch(this); if (rval == 0) { return; } DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() { free(mHost); free(mService); free(mHints); char* msg = nullptr; asprintf(&msg, "%s (%d)", strerror(-rval), -rval); mClient->sendMsg(ResponseCode::OperationFailed, msg, false); free(msg); delete this; } static bool evaluate_domain_name(const android_net_context &netcontext, const char *host) { if (!gResNetdCallbacks.evaluate_domain_name) return true; DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient* c, std::string host, std::string service, std::unique_ptr<addrinfo> hints, const android_net_context& netcontext) : Handler(c), mHost(move(host)), mService(move(service)), mHints(move(hints)), mNetContext(netcontext) {} static bool evaluate_domain_name(const android_net_context& netcontext, const char* host) { if (!gResNetdCallbacks.evaluate_domain_name) return true; return gResNetdCallbacks.evaluate_domain_name(netcontext, host); } Loading Loading @@ -634,11 +625,8 @@ static bool sendaddrinfo(SocketClient* c, addrinfo* ai) { // 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); 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; } Loading @@ -658,8 +646,6 @@ static bool sendaddrinfo(SocketClient* c, addrinfo* ai) { void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinfo** res, NetworkDnsEventReported* event) { 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)); Loading @@ -677,10 +663,12 @@ void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinf // 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)) { 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(mHost, mService, mHints, &mNetContext, res, event); *rv = resolv_getaddrinfo(host, service, mHints.get(), &mNetContext, res, event); queryLimiter.finish(uid); if (*rv) { *rv = EAI_NODATA; // return original error code Loading Loading @@ -718,9 +706,10 @@ void DnsProxyListener::GetAddrInfoHandler::run() { NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { if (evaluate_domain_name(mNetContext, mHost)) { rv = resolv_getaddrinfo(mHost, mService, mHints, &mNetContext, &result, &event); const char* host = mHost.starts_with('^') ? nullptr : mHost.c_str(); 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); } else { rv = EAI_SYSTEM; } Loading Loading @@ -763,7 +752,6 @@ void DnsProxyListener::GetAddrInfoHandler::run() { reportDnsEvent(INetdEventListener::EVENT_GETADDRINFO, mNetContext, latencyUs, rv, event, mHost, ip_addrs, total_ip_addr_count); freeaddrinfo(result); mClient->decRef(); } std::string DnsProxyListener::GetAddrInfoHandler::threadName() { Loading @@ -789,8 +777,7 @@ void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* ad DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() : FrameworkCommand("getaddrinfo") {} int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, int argc, char **argv) { int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient* cli, int argc, char** argv) { logArguments(argc, argv); if (argc != 8) { Loading @@ -802,21 +789,8 @@ int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, 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; const std::string name = argv[1]; const std::string service = argv[2]; int ai_flags = strtol(argv[3], nullptr, 10); int ai_family = strtol(argv[4], nullptr, 10); int ai_socktype = strtol(argv[5], nullptr, 10); Loading @@ -832,18 +806,16 @@ int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, 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)); std::unique_ptr<addrinfo> hints; if (ai_flags != -1 || ai_family != -1 || ai_socktype != -1 || ai_protocol != -1) { hints.reset((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; } DnsProxyListener::GetAddrInfoHandler* handler = new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netcontext); tryThreadOrError(cli, handler); (new GetAddrInfoHandler(cli, name, service, move(hints), netcontext))->spawn(); return 0; } Loading Loading @@ -888,19 +860,13 @@ int DnsProxyListener::ResNSendCommand::runCommand(SocketClient* cli, int argc, c netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS; } DnsProxyListener::ResNSendHandler* handler = new DnsProxyListener::ResNSendHandler(cli, argv[3], flags, netcontext); tryThreadOrError(cli, handler); (new ResNSendHandler(cli, argv[3], flags, netcontext))->spawn(); 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(); } : Handler(c), mMsg(std::move(msg)), mFlags(flags), mNetContext(netcontext) {} void DnsProxyListener::ResNSendHandler::run() { LOG(DEBUG) << "ResNSendHandler::run: " << mFlags << " / {" << mNetContext.app_netid << " " Loading Loading @@ -1058,8 +1024,7 @@ int DnsProxyListener::GetDnsNetIdCommand::runCommand(SocketClient* cli, int argc *******************************************************/ DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd() : FrameworkCommand("gethostbyname") {} int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, int argc, char **argv) { int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient* cli, int argc, char** argv) { logArguments(argc, argv); if (argc != 4) { Loading @@ -1074,15 +1039,9 @@ int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, uid_t uid = cli->getUid(); unsigned netId = strtoul(argv[1], nullptr, 10); const bool useLocalNameservers = checkAndClearUseLocalNameserversFlag(&netId); char* name = argv[2]; std::string name = argv[2]; int af = strtol(argv[3], nullptr, 10); if (strcmp(name, "^") == 0) { name = nullptr; } else { name = strdup(name); } android_net_context netcontext; gResNetdCallbacks.get_network_context(netId, uid, &netcontext); Loading @@ -1090,19 +1049,14 @@ int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS; } DnsProxyListener::GetHostByNameHandler* handler = new DnsProxyListener::GetHostByNameHandler(cli, name, af, netcontext); tryThreadOrError(cli, handler); (new GetHostByNameHandler(cli, name, af, netcontext))->spawn(); return 0; } DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c, char* name, int af, DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c, std::string name, int af, const android_net_context& netcontext) : mClient(c), mName(name), mAf(af), mNetContext(netcontext) {} DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() { free(mName); } : Handler(c), mName(move(name)), mAf(af), mNetContext(netcontext) {} void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, hostent* hbuf, char* buf, size_t buflen, struct hostent** hpp, Loading @@ -1123,7 +1077,8 @@ 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 (queryLimiter.start(uid)) { *rv = resolv_gethostbyname(mName, AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); *rv = resolv_gethostbyname(name, AF_INET, hbuf, buf, buflen, &mNetContext, hpp, event); queryLimiter.finish(uid); if (*rv) { *rv = EAI_NODATA; // return original error code Loading Loading @@ -1152,8 +1107,9 @@ void DnsProxyListener::GetHostByNameHandler::run() { NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { if (evaluate_domain_name(mNetContext, mName)) { rv = resolv_gethostbyname(mName, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, const char* name = mName.starts_with('^') ? nullptr : mName.c_str(); if (evaluate_domain_name(mNetContext, name)) { rv = resolv_gethostbyname(name, mAf, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); } else { rv = EAI_SYSTEM; Loading Loading @@ -1190,7 +1146,6 @@ void DnsProxyListener::GetHostByNameHandler::run() { const int total_ip_addr_count = extractGetHostByNameAnswers(hp, &ip_addrs); reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYNAME, mNetContext, latencyUs, rv, event, mName, ip_addrs, total_ip_addr_count); mClient->decRef(); } std::string DnsProxyListener::GetHostByNameHandler::threadName() { Loading @@ -1202,8 +1157,7 @@ std::string DnsProxyListener::GetHostByNameHandler::threadName() { *******************************************************/ DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd() : FrameworkCommand("gethostbyaddr") {} int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, int argc, char **argv) { int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient* cli, int argc, char** argv) { logArguments(argc, argv); if (argc != 5) { Loading @@ -1222,15 +1176,14 @@ int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, unsigned netId = strtoul(argv[4], nullptr, 10); const bool useLocalNameservers = checkAndClearUseLocalNameserversFlag(&netId); void* addr = malloc(sizeof(in6_addr)); in6_addr addr; errno = 0; int result = inet_pton(addrFamily, addrStr, addr); int result = inet_pton(addrFamily, addrStr, &addr); if (result <= 0) { char* msg = nullptr; asprintf(&msg, "inet_pton(\"%s\") failed %s", addrStr, strerror(errno)); LOG(WARNING) << "GetHostByAddrCmd::runCommand: " << (msg ? msg : "null"); cli->sendMsg(ResponseCode::OperationFailed, msg, false); free(addr); free(msg); return -1; } Loading @@ -1242,30 +1195,24 @@ int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS; } DnsProxyListener::GetHostByAddrHandler* handler = new DnsProxyListener::GetHostByAddrHandler( cli, addr, addrLen, addrFamily, netcontext); tryThreadOrError(cli, handler); (new GetHostByAddrHandler(cli, addr, addrLen, addrFamily, netcontext))->spawn(); return 0; } DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c, void* address, DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c, in6_addr address, int addressLen, int addressFamily, const android_net_context& netcontext) : mClient(c), : Handler(c), mAddress(address), mAddressLen(addressLen), mAddressFamily(addressFamily), mNetContext(netcontext) {} DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() { free(mAddress); } void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, char* buf, size_t buflen, struct hostent** hpp, NetworkDnsEventReported* event) { if (*hpp != nullptr || mAddressFamily != AF_INET6 || !mAddress) { if (*hpp != nullptr || mAddressFamily != AF_INET6) { return; } Loading @@ -1280,7 +1227,7 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, struct sockaddr_storage ss = netdutils::IPSockAddr(prefix.ip()); struct sockaddr_in6* v6prefix = (struct sockaddr_in6*)&ss; struct in6_addr v6addr = *(in6_addr*) mAddress; struct in6_addr v6addr = 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]) || Loading Loading @@ -1320,7 +1267,7 @@ void DnsProxyListener::GetHostByAddrHandler::run() { NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { rv = resolv_gethostbyaddr(mAddress, mAddressLen, mAddressFamily, &hbuf, tmpbuf, rv = resolv_gethostbyaddr(&mAddress, mAddressLen, mAddressFamily, &hbuf, tmpbuf, sizeof tmpbuf, &mNetContext, &hp, &event); queryLimiter.finish(uid); } else { Loading Loading @@ -1351,7 +1298,6 @@ void DnsProxyListener::GetHostByAddrHandler::run() { reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYADDR, mNetContext, latencyUs, rv, event, (hp && hp->h_name) ? hp->h_name : "null", {}, 0); mClient->decRef(); } std::string DnsProxyListener::GetHostByAddrHandler::threadName() { Loading
DnsProxyListener.h +42 −30 Original line number Diff line number Diff line Loading @@ -38,6 +38,23 @@ class DnsProxyListener : public FrameworkListener { static constexpr const char* SOCKET_NAME = "dnsproxyd"; private: class Handler { public: Handler(SocketClient* c) : mClient(c) { mClient->incRef(); } virtual ~Handler() { mClient->decRef(); } void operator=(const Handler&) = delete; // Attept to spawn the worker thread, or return an error to the client. // The Handler instance will self-delete in either case. void spawn(); virtual void run() = 0; virtual std::string threadName() = 0; SocketClient* mClient; // ref-counted }; /* ------ getaddrinfo ------*/ class GetAddrInfoCmd : public FrameworkCommand { public: GetAddrInfoCmd(); Loading @@ -45,24 +62,22 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; /* ------ getaddrinfo ------*/ class GetAddrInfoHandler { class GetAddrInfoHandler : public Handler { 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(); GetAddrInfoHandler(SocketClient* c, std::string host, std::string service, std::unique_ptr<addrinfo> hints, const android_net_context& netcontext); ~GetAddrInfoHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: void doDns64Synthesis(int32_t* rv, addrinfo** res, NetworkDnsEventReported* event); SocketClient* mClient; // ref counted char* mHost; // owned. TODO: convert to std::string. char* mService; // owned. TODO: convert to std::string. addrinfo* mHints; // owned std::string mHost; std::string mService; std::unique_ptr<addrinfo> mHints; android_net_context mNetContext; }; Loading @@ -74,21 +89,20 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; class GetHostByNameHandler { class GetHostByNameHandler : public Handler { public: GetHostByNameHandler(SocketClient* c, char* name, int af, GetHostByNameHandler(SocketClient* c, std::string name, int af, const android_net_context& netcontext); ~GetHostByNameHandler(); ~GetHostByNameHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: void doDns64Synthesis(int32_t* rv, hostent* hbuf, char* buf, size_t buflen, hostent** hpp, NetworkDnsEventReported* event); SocketClient* mClient; // ref counted char* mName; // owned. TODO: convert to std::string. std::string mName; int mAf; android_net_context mNetContext; }; Loading @@ -101,21 +115,20 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; class GetHostByAddrHandler { class GetHostByAddrHandler : public Handler { public: GetHostByAddrHandler(SocketClient* c, void* address, int addressLen, int addressFamily, GetHostByAddrHandler(SocketClient* c, in6_addr address, int addressLen, int addressFamily, const android_net_context& netcontext); ~GetHostByAddrHandler(); ~GetHostByAddrHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: void doDns64ReverseLookup(hostent* hbuf, char* buf, size_t buflen, hostent** hpp, NetworkDnsEventReported* event); SocketClient* mClient; // ref counted void* mAddress; // address to lookup; owned in6_addr mAddress; int mAddressLen; // length of address to look up int mAddressFamily; // address family android_net_context mNetContext; Loading @@ -129,17 +142,16 @@ class DnsProxyListener : public FrameworkListener { int runCommand(SocketClient* c, int argc, char** argv) override; }; class ResNSendHandler { class ResNSendHandler : public Handler { public: ResNSendHandler(SocketClient* c, std::string msg, uint32_t flags, const android_net_context& netcontext); ~ResNSendHandler(); ~ResNSendHandler() override = default; void run(); std::string threadName(); void run() override; std::string threadName() override; private: SocketClient* mClient; // ref counted std::string mMsg; uint32_t mFlags; android_net_context mNetContext; Loading
DnsQueryLog.cpp +3 −19 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include "DnsQueryLog.h" #include <android-base/stringprintf.h> #include "util.h" namespace android::net { Loading Loading @@ -45,25 +45,10 @@ std::string maskIps(const std::vector<std::string>& ips) { return ret.empty() ? "" : ret.substr(0, ret.length() - 2); } // Return the readable string format "hr:min:sec.ms". std::string timestampToString(const std::chrono::system_clock::time_point& ts) { using std::chrono::duration_cast; using std::chrono::milliseconds; const auto time_sec = std::chrono::system_clock::to_time_t(ts); char buf[32]; std::strftime(buf, sizeof(buf), "%H:%M:%S", std::localtime(&time_sec)); int ms = duration_cast<milliseconds>(ts.time_since_epoch()).count() % 1000; return android::base::StringPrintf("%s.%03d", buf, ms); } } // namespace void DnsQueryLog::push(Record&& record) { std::lock_guard guard(mLock); mQueue.push_back(std::move(record)); if (mQueue.size() > mCapacity) { mQueue.pop_front(); } mQueue.push(std::move(record)); } void DnsQueryLog::dump(netdutils::DumpWriter& dw) const { Loading @@ -71,8 +56,7 @@ void DnsQueryLog::dump(netdutils::DumpWriter& dw) const { netdutils::ScopedIndent indentStats(dw); const auto now = std::chrono::system_clock::now(); std::lock_guard guard(mLock); for (const auto& record : mQueue) { for (const auto& record : mQueue.copy()) { if (now - record.timestamp > mValidityTimeMs) continue; const std::string maskedHostname = maskHostname(record.hostname); Loading
DnsQueryLog.h +7 −9 Original line number Diff line number Diff line Loading @@ -17,16 +17,16 @@ #pragma once #include <deque> #include <string> #include <vector> #include <android-base/thread_annotations.h> #include <netdutils/DumpWriter.h> #include "LockedQueue.h" namespace android::net { // A circular buffer based class used for query logging. It's thread-safe for concurrent access. // This class stores query records in a locked ring buffer. It's thread-safe for concurrent access. class DnsQueryLog { public: static constexpr std::string_view DUMP_KEYWORD = "querylog"; Loading @@ -52,15 +52,13 @@ class DnsQueryLog { // Allow the tests to set the capacity and the validaty time in milliseconds. DnsQueryLog(size_t size = kDefaultLogSize, std::chrono::milliseconds time = kDefaultValidityMinutes) : mCapacity(size), mValidityTimeMs(time) {} : mQueue(size), mValidityTimeMs(time) {} void push(Record&& record) EXCLUDES(mLock); void dump(netdutils::DumpWriter& dw) const EXCLUDES(mLock); void push(Record&& record); void dump(netdutils::DumpWriter& dw) const; private: mutable std::mutex mLock; std::deque<Record> mQueue GUARDED_BY(mLock); const size_t mCapacity; LockedRingBuffer<Record> mQueue; const std::chrono::milliseconds mValidityTimeMs; // The capacity of the circular buffer. Loading