Merge "Replace addrinfo with IPSockAddr to store dns addresses"
diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp
index ce6081d..bb8251c 100644
--- a/DnsProxyListener.cpp
+++ b/DnsProxyListener.cpp
@@ -74,10 +74,6 @@
 // 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
-// TODO: switch to dynamically allocated buffers with std::vector
-constexpr int MAXPACKET = 8 * 1024;
-
 android::netdutils::OperationLimiter<uid_t> queryLimiter(MAX_QUERIES_PER_UID);
 
 void logArguments(int argc, char** argv) {
@@ -147,7 +143,7 @@
     return false;
 }
 
-void maybeFixupNetContext(android_net_context* ctx) {
+void maybeFixupNetContext(android_net_context* ctx, pid_t pid) {
     if (requestingUseLocalNameservers(ctx->flags) && !hasPermissionToBypassPrivateDns(ctx->uid)) {
         // Not permitted; clear the flag.
         ctx->flags &= ~NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS;
@@ -161,6 +157,7 @@
             ctx->flags |= NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS;
         }
     }
+    ctx->pid = pid;
 }
 
 void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* addr,
@@ -669,7 +666,7 @@
 
     addrinfo* result = nullptr;
     Stopwatch s;
-    maybeFixupNetContext(&mNetContext);
+    maybeFixupNetContext(&mNetContext, mClient->getPid());
     const uid_t uid = mClient->getUid();
     int32_t rv = 0;
     NetworkDnsEventReported event;
@@ -856,7 +853,7 @@
                << mNetContext.dns_mark << " " << mNetContext.uid << " " << mNetContext.flags << "}";
 
     Stopwatch s;
-    maybeFixupNetContext(&mNetContext);
+    maybeFixupNetContext(&mNetContext, mClient->getPid());
 
     // Decode
     std::vector<uint8_t> msg(MAXPACKET, 0);
@@ -885,12 +882,13 @@
 
     // Send DNS query
     std::vector<uint8_t> ansBuf(MAXPACKET, 0);
-    int arcode, nsendAns = -1;
+    int rcode = ns_r_noerror;
+    int nsendAns = -1;
     NetworkDnsEventReported event;
     initDnsEvent(&event);
     if (queryLimiter.start(uid)) {
         nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET,
-                                    &arcode, static_cast<ResNsendFlags>(mFlags), &event);
+                                    &rcode, static_cast<ResNsendFlags>(mFlags), &event);
         queryLimiter.finish(uid);
     } else {
         LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid
@@ -908,13 +906,13 @@
         sendBE32(mClient, nsendAns);
         if (rr_type == ns_t_a || rr_type == ns_t_aaaa) {
             reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
-                           resNSendToAiError(nsendAns, arcode), event, rr_name);
+                           resNSendToAiError(nsendAns, rcode), event, rr_name);
         }
         return;
     }
 
     // Send rcode
-    if (!sendBE32(mClient, arcode)) {
+    if (!sendBE32(mClient, rcode)) {
         PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send rcode to uid " << uid;
         return;
     }
@@ -931,7 +929,7 @@
         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), event, rr_name, ip_addrs,
+                       resNSendToAiError(nsendAns, rcode), event, rr_name, ip_addrs,
                        total_ip_addr_count);
     }
 }
@@ -1073,7 +1071,7 @@
 
 void DnsProxyListener::GetHostByNameHandler::run() {
     Stopwatch s;
-    maybeFixupNetContext(&mNetContext);
+    maybeFixupNetContext(&mNetContext, mClient->getPid());
     const uid_t uid = mClient->getUid();
     hostent* hp = nullptr;
     hostent hbuf;
@@ -1236,7 +1234,7 @@
 
 void DnsProxyListener::GetHostByAddrHandler::run() {
     Stopwatch s;
-    maybeFixupNetContext(&mNetContext);
+    maybeFixupNetContext(&mNetContext, mClient->getPid());
     const uid_t uid = mClient->getUid();
     hostent* hp = nullptr;
     hostent hbuf;
diff --git a/DnsTlsSocket.cpp b/DnsTlsSocket.cpp
index bb43ed9..6a221fe 100644
--- a/DnsTlsSocket.cpp
+++ b/DnsTlsSocket.cpp
@@ -38,6 +38,7 @@
 #include <netdutils/SocketOption.h>
 #include <netdutils/ThreadUtil.h>
 
+#include "netd_resolv/resolv.h"
 #include "private/android_filesystem_config.h"  // AID_DNS
 #include "resolv_private.h"
 
@@ -95,7 +96,7 @@
         return Status(errno);
     }
 
-    resolv_tag_socket(mSslFd.get(), AID_DNS);
+    resolv_tag_socket(mSslFd.get(), AID_DNS, NET_CONTEXT_INVALID_PID);
 
     const socklen_t len = sizeof(mMark);
     if (setsockopt(mSslFd.get(), SOL_SOCKET, SO_MARK, &mMark, len) == -1) {
diff --git a/getaddrinfo.cpp b/getaddrinfo.cpp
index 087deda..6e2376b 100644
--- a/getaddrinfo.cpp
+++ b/getaddrinfo.cpp
@@ -108,20 +108,13 @@
 };
 
 #define PTON_MAX 16
-#define MAXPACKET (8 * 1024)
-
-typedef union {
-    HEADER hdr;
-    uint8_t buf[MAXPACKET];
-} querybuf;
 
 struct res_target {
     struct res_target* next;
-    const char* name;  /* domain name */
-    int qclass, qtype; /* class and type of query */
-    uint8_t* answer;   /* buffer to put answer */
-    int anslen;        /* size of answer buffer */
-    int n;             /* result length */
+    const char* name;                                                  // domain name
+    int qclass, qtype;                                                 // class and type of query
+    std::vector<uint8_t> answer = std::vector<uint8_t>(MAXPACKET, 0);  // buffer to put answer
+    int n = 0;                                                         // result length
 };
 
 static int str2number(const char*);
@@ -139,8 +132,8 @@
 static const struct afd* find_afd(int);
 static int ip6_str2scopeid(const char*, struct sockaddr_in6*, uint32_t*);
 
-static struct addrinfo* getanswer(const querybuf*, int, const char*, int, const struct addrinfo*,
-                                  int* herrno);
+static struct addrinfo* getanswer(const std::vector<uint8_t>&, int, const char*, int,
+                                  const struct addrinfo*, int* herrno);
 static int dns_getaddrinfo(const char* name, const addrinfo* pai,
                            const android_net_context* netcontext, addrinfo** rv,
                            NetworkDnsEventReported* event);
@@ -266,6 +259,7 @@
             .dns_netid = NETID_UNSET,
             .dns_mark = MARK_UNSET,
             .uid = NET_CONTEXT_INVALID_UID,
+            .pid = NET_CONTEXT_INVALID_PID,
     };
     NetworkDnsEventReported event;
     return android_getaddrinfofornetcontext(hostname, servname, &hints, &netcontext, result,
@@ -837,8 +831,8 @@
         }                            \
     } while (0)
 
-static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
-                                  const struct addrinfo* pai, int* herrno) {
+static struct addrinfo* getanswer(const std::vector<uint8_t>& answer, int anslen, const char* qname,
+                                  int qtype, const struct addrinfo* pai, int* herrno) {
     struct addrinfo sentinel = {};
     struct addrinfo *cur;
     struct addrinfo ai;
@@ -855,14 +849,13 @@
     int (*name_ok)(const char*);
     char hostbuf[8 * 1024];
 
-    assert(answer != NULL);
     assert(qname != NULL);
     assert(pai != NULL);
 
     cur = &sentinel;
 
     canonname = NULL;
-    eom = answer->buf + anslen;
+    eom = answer.data() + anslen;
     switch (qtype) {
         case T_A:
         case T_AAAA:
@@ -875,18 +868,18 @@
     /*
      * find first satisfactory answer
      */
-    hp = &answer->hdr;
+    hp = reinterpret_cast<const HEADER*>(answer.data());
     ancount = ntohs(hp->ancount);
     qdcount = ntohs(hp->qdcount);
     bp = hostbuf;
     ep = hostbuf + sizeof hostbuf;
-    cp = answer->buf;
+    cp = answer.data();
     BOUNDED_INCR(HFIXEDSZ);
     if (qdcount != 1) {
         *herrno = NO_RECOVERY;
         return (NULL);
     }
-    n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+    n = dn_expand(answer.data(), eom, cp, bp, ep - bp);
     if ((n < 0) || !(*name_ok)(bp)) {
         *herrno = NO_RECOVERY;
         return (NULL);
@@ -910,7 +903,7 @@
     haveanswer = 0;
     had_error = 0;
     while (ancount-- > 0 && cp < eom && !had_error) {
-        n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+        n = dn_expand(answer.data(), eom, cp, bp, ep - bp);
         if ((n < 0) || !(*name_ok)(bp)) {
             had_error++;
             continue;
@@ -930,7 +923,7 @@
             continue; /* XXX - had_error++ ? */
         }
         if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) {
-            n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+            n = dn_expand(answer.data(), eom, cp, tbuf, sizeof tbuf);
             if ((n < 0) || !(*name_ok)(tbuf)) {
                 had_error++;
                 continue;
@@ -1396,16 +1389,11 @@
     res_target q = {};
     res_target q2 = {};
 
-    auto buf = std::make_unique<querybuf>();
-    auto buf2 = std::make_unique<querybuf>();
-
     switch (pai->ai_family) {
         case AF_UNSPEC: {
             /* prefer IPv6 */
             q.name = name;
             q.qclass = C_IN;
-            q.answer = buf->buf;
-            q.anslen = sizeof(buf->buf);
             int query_ipv6 = 1, query_ipv4 = 1;
             if (pai->ai_flags & AI_ADDRCONFIG) {
                 query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid);
@@ -1418,8 +1406,6 @@
                     q2.name = name;
                     q2.qclass = C_IN;
                     q2.qtype = T_A;
-                    q2.answer = buf2->buf;
-                    q2.anslen = sizeof(buf2->buf);
                 }
             } else if (query_ipv4) {
                 q.qtype = T_A;
@@ -1432,15 +1418,11 @@
             q.name = name;
             q.qclass = C_IN;
             q.qtype = T_A;
-            q.answer = buf->buf;
-            q.anslen = sizeof(buf->buf);
             break;
         case AF_INET6:
             q.name = name;
             q.qclass = C_IN;
             q.qtype = T_AAAA;
-            q.answer = buf->buf;
-            q.anslen = sizeof(buf->buf);
             break;
         default:
             return EAI_FAMILY;
@@ -1459,13 +1441,13 @@
 
     addrinfo sentinel = {};
     addrinfo* cur = &sentinel;
-    addrinfo* ai = getanswer(buf.get(), q.n, q.name, q.qtype, pai, &he);
+    addrinfo* ai = getanswer(q.answer, q.n, q.name, q.qtype, pai, &he);
     if (ai) {
         cur->ai_next = ai;
         while (cur && cur->ai_next) cur = cur->ai_next;
     }
     if (q.next) {
-        ai = getanswer(buf2.get(), q2.n, q2.name, q2.qtype, pai, &he);
+        ai = getanswer(q2.answer, q2.n, q2.name, q2.qtype, pai, &he);
         if (ai) cur->ai_next = ai;
     }
     if (sentinel.ai_next == NULL) {
@@ -1577,7 +1559,6 @@
  */
 static int res_queryN(const char* name, res_target* target, res_state res, int* herrno) {
     uint8_t buf[MAXPACKET];
-    HEADER* hp;
     int n;
     struct res_target* t;
     int rcode;
@@ -1590,10 +1571,7 @@
     ancount = 0;
 
     for (t = target; t; t = t->next) {
-        uint8_t* answer;
-        int anslen;
-
-        hp = (HEADER*) (void*) t->answer;
+        HEADER* hp = (HEADER*)(void*)t->answer.data();
         bool retried = false;
     again:
         hp->rcode = NOERROR; /* default */
@@ -1601,8 +1579,7 @@
         /* make it easier... */
         int cl = t->qclass;
         int type = t->qtype;
-        answer = t->answer;
-        anslen = t->anslen;
+        const int anslen = t->answer.size();
 
         LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")";
 
@@ -1619,7 +1596,7 @@
             return n;
         }
 
-        n = res_nsend(res, buf, n, answer, anslen, &rcode, 0);
+        n = res_nsend(res, buf, n, t->answer.data(), anslen, &rcode, 0);
         if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
             // Record rcode from DNS response header only if no timeout.
             // Keep rcode timeout for reporting later if any.
@@ -1688,7 +1665,7 @@
     assert(name != NULL);
     assert(target != NULL);
 
-    hp = (HEADER*) (void*) target->answer; /*XXX*/
+    hp = (HEADER*)(void*)target->answer.data();
 
     errno = 0;
     *herrno = HOST_NOT_FOUND; /* default, if we never query */
diff --git a/gethnamaddr.cpp b/gethnamaddr.cpp
index 2a8c92b..6dcd358 100644
--- a/gethnamaddr.cpp
+++ b/gethnamaddr.cpp
@@ -95,8 +95,6 @@
 #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
 #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
 
-#define MAXPACKET (8 * 1024)
-
 constexpr int MAXADDRS = 35;
 
 typedef union {
diff --git a/include/netd_resolv/resolv.h b/include/netd_resolv/resolv.h
index afd63f5..22eadeb 100644
--- a/include/netd_resolv/resolv.h
+++ b/include/netd_resolv/resolv.h
@@ -30,6 +30,7 @@
 
 #include "params.h"
 
+#include <arpa/nameser.h>
 #include <netinet/in.h>
 
 /*
@@ -43,6 +44,9 @@
  */
 #define MARK_UNSET 0u
 
+#define NET_CONTEXT_INVALID_UID ((uid_t)-1)
+#define NET_CONTEXT_INVALID_PID ((pid_t)-1)
+
 /*
  * A struct to capture context relevant to network operations.
  *
@@ -59,11 +63,12 @@
     unsigned app_mark;
     unsigned dns_netid;
     unsigned dns_mark;
-    uid_t uid;
+    uid_t uid = NET_CONTEXT_INVALID_UID;
     unsigned flags;
+    // Variable to store the pid of the application sending DNS query.
+    pid_t pid = NET_CONTEXT_INVALID_PID;
 };
 
-#define NET_CONTEXT_INVALID_UID ((uid_t) -1)
 #define NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS 0x00000001
 #define NET_CONTEXT_FLAG_USE_EDNS 0x00000002
 #define NET_CONTEXT_FLAG_USE_DNS_OVER_TLS 0x00000004
@@ -74,7 +79,7 @@
 typedef void (*get_network_context_callback)(unsigned netid, uid_t uid,
                                              android_net_context* netcontext);
 typedef void (*log_callback)(const char* msg);
-typedef int (*tagSocketCallback)(int sockFd, uint32_t tag, uid_t uid);
+typedef int (*tagSocketCallback)(int sockFd, uint32_t tag, uid_t uid, pid_t pid);
 
 /*
  * Some functions needed by the resolver (e.g. checkCallingPermission()) live in
@@ -95,3 +100,10 @@
 
 // Set callbacks and bring DnsResolver up.
 LIBNETD_RESOLV_PUBLIC bool resolv_init(const ResolverNetdCallbacks* callbacks);
+
+// Function that performs RDNS in local cache. The |domain_name_size| is the size of domain_name
+// buffer, which is recommended to NS_MAXDNAME. Function return false if hostname not found or
+// domain_name_size > NS_MAXDNAME.
+LIBNETD_RESOLV_PUBLIC bool resolv_gethostbyaddr_from_local_cache(unsigned netId, char domain_name[],
+                                                                 unsigned domain_name_size,
+                                                                 char* ip_address);
diff --git a/include/netd_resolv/resolv_stub.h b/include/netd_resolv/resolv_stub.h
index 41f56fa..d1939d1 100644
--- a/include/netd_resolv/resolv_stub.h
+++ b/include/netd_resolv/resolv_stub.h
@@ -37,6 +37,9 @@
     bool (*resolv_has_nameservers)(unsigned netid);
 
     bool (*resolv_init)(const ResolverNetdCallbacks& callbacks);
+
+    bool (*resolv_gethostbyaddr_from_local_cache)(unsigned netId, char domain_name[],
+                                                  unsigned domain_name_size, char* ip_address);
 } RESOLV_STUB;
 
 int resolv_stub_init();
diff --git a/libnetd_resolv.map.txt b/libnetd_resolv.map.txt
index be193db..4b0fb95 100644
--- a/libnetd_resolv.map.txt
+++ b/libnetd_resolv.map.txt
@@ -22,6 +22,7 @@
   global:
     resolv_has_nameservers;
     resolv_init;
+    resolv_gethostbyaddr_from_local_cache;
   local:
     *;
 };
diff --git a/res_cache.cpp b/res_cache.cpp
index bfeab35..de11363 100644
--- a/res_cache.cpp
+++ b/res_cache.cpp
@@ -1293,6 +1293,85 @@
     return 0;
 }
 
+bool resolv_gethostbyaddr_from_local_cache(unsigned netid, char domain_name[],
+                                           unsigned domain_name_size, char* ip_address) {
+    if (domain_name_size > NS_MAXDNAME) {
+        LOG(ERROR) << __func__ << ": invalid domain_name_size " << domain_name_size;
+        return false;
+    }
+
+    Cache* cache = nullptr;
+    Entry* node = nullptr;
+
+    ns_rr rr;
+    ns_msg handle;
+
+    int query_count;
+    ns_rr rr_query;
+
+    // For ntop.
+    char* resolved_ip = nullptr;
+    char buf4[INET_ADDRSTRLEN];
+    char buf6[INET6_ADDRSTRLEN];
+
+    std::lock_guard guard(cache_mutex);
+
+    cache = find_named_cache_locked(netid);
+    if (cache == nullptr) {
+        return false;
+    }
+
+    for (node = cache->mru_list.mru_next; node != nullptr && node != &cache->mru_list;
+         node = node->mru_next) {
+        if (node->answer == nullptr) {
+            continue;
+        }
+
+        memset(&handle, 0, sizeof(handle));
+
+        if (ns_initparse(node->answer, node->answerlen, &handle) < 0) {
+            continue;
+        }
+
+        for (int n = 0; n < ns_msg_count(handle, ns_s_an); n++) {
+            memset(&rr, 0, sizeof(rr));
+
+            if (ns_parserr(&handle, ns_s_an, n, &rr)) {
+                continue;
+            }
+
+            resolved_ip = nullptr;
+            if (ns_rr_type(rr) == ns_t_a) {
+                inet_ntop(AF_INET, ns_rr_rdata(rr), buf4, sizeof(buf4));
+                resolved_ip = buf4;
+            } else if (ns_rr_type(rr) == ns_t_aaaa) {
+                inet_ntop(AF_INET6, ns_rr_rdata(rr), buf6, sizeof(buf6));
+                resolved_ip = buf6;
+            } else {
+                continue;
+            }
+
+            if ((resolved_ip != nullptr) && (resolved_ip[0] != '\0')) {
+                if (strcmp(resolved_ip, ip_address) == 0) {
+                    query_count = ns_msg_count(handle, ns_s_qd);
+                    for (int i = 0; i < query_count; i++) {
+                        memset(&rr_query, 0, sizeof(rr_query));
+                        if (ns_parserr(&handle, ns_s_qd, i, &rr_query)) {
+                            continue;
+                        }
+                        strlcpy(domain_name, ns_rr_name(rr_query), domain_name_size);
+                        if (domain_name[0] != '\0') {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
 // Head of the list of caches.
 static struct resolv_cache_info res_cache_list GUARDED_BY(cache_mutex);
 
diff --git a/res_init.cpp b/res_init.cpp
index 181a778..16fd98c 100644
--- a/res_init.cpp
+++ b/res_init.cpp
@@ -98,6 +98,7 @@
 
     statp->netid = netcontext->dns_netid;
     statp->uid = netcontext->uid;
+    statp->pid = netcontext->pid;
     statp->id = arc4random_uniform(65536);
     statp->_mark = netcontext->dns_mark;
     statp->netcontext_flags = netcontext->flags;
diff --git a/res_query.cpp b/res_query.cpp
index c39515e..7702b44 100644
--- a/res_query.cpp
+++ b/res_query.cpp
@@ -89,12 +89,6 @@
 #include "resolv_cache.h"
 #include "resolv_private.h"
 
-#if PACKETSZ > 1024
-#define MAXPACKET PACKETSZ
-#else
-#define MAXPACKET 1024
-#endif
-
 /*
  * Formulate a normal query, send, and await answer.
  * Returned answer is placed in supplied buffer "answer".
diff --git a/res_send.cpp b/res_send.cpp
index 1c98c7c..ef86d0c 100644
--- a/res_send.cpp
+++ b/res_send.cpp
@@ -225,15 +225,6 @@
     return tsnow;
 }
 
-static struct iovec evConsIovec(void* buf, size_t cnt) {
-    struct iovec ret;
-
-    memset(&ret, 0xf5, sizeof ret);
-    ret.iov_base = buf;
-    ret.iov_len = cnt;
-    return ret;
-}
-
 // END: Code copied from ISC eventlib
 
 /* BIONIC-BEGIN: implement source port randomization */
@@ -448,6 +439,25 @@
         return -ESRCH;
     }
 
+    // DoT
+    if (!(statp->netcontext_flags & NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS)) {
+        bool fallback = false;
+        resplen = res_tls_send(statp, Slice(const_cast<uint8_t*>(buf), buflen), Slice(ans, anssiz),
+                               rcode, &fallback);
+        if (resplen > 0) {
+            LOG(DEBUG) << __func__ << ": got answer from DoT";
+            res_pquery(ans, resplen);
+            if (cache_status == RESOLV_CACHE_NOTFOUND) {
+                resolv_cache_add(statp->netid, buf, buflen, ans, resplen);
+            }
+            return resplen;
+        }
+        if (!fallback) {
+            _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
+            return -terrno;
+        }
+    }
+
     res_stats stats[MAXNS];
     res_params params;
     int revision_id = resolv_cache_get_resolver_stats(statp->netid, &params, stats);
@@ -485,28 +495,6 @@
             nsaplen = sockaddrSize(nsap);
 
         same_ns:
-            // TODO: Since we expect there is only one DNS server being queried here while this
-            // function tries to query all of private DNS servers. Consider moving it to other
-            // reasonable place. In addition, maybe add stats for private DNS.
-            if (!(statp->netcontext_flags & NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS)) {
-                bool fallback = false;
-                resplen = res_tls_send(statp, Slice(const_cast<uint8_t*>(buf), buflen),
-                                       Slice(ans, anssiz), rcode, &fallback);
-                if (resplen > 0) {
-                    LOG(DEBUG) << __func__ << ": got answer from DoT";
-                    res_pquery(ans, resplen);
-                    if (cache_status == RESOLV_CACHE_NOTFOUND) {
-                        resolv_cache_add(statp->netid, buf, buflen, ans, resplen);
-                    }
-                    return resplen;
-                }
-                if (!fallback) {
-                    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
-                    res_nclose(statp);
-                    return -terrno;
-                }
-            }
-
             static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
             char abuf[NI_MAXHOST];
             DnsQueryEvent* dnsQueryEvent = addDnsQueryEvent(statp->event);
@@ -659,7 +647,6 @@
     struct sockaddr* nsap;
     int nsaplen;
     int truncating, connreset, n;
-    struct iovec iov[2];
     uint8_t* cp;
 
     LOG(INFO) << __func__ << ": using send_vc";
@@ -705,7 +692,7 @@
                     return -1;
             }
         }
-        resolv_tag_socket(statp->_vcsock, statp->uid);
+        resolv_tag_socket(statp->_vcsock, statp->uid, statp->pid);
         if (statp->_mark != MARK_UNSET) {
             if (setsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &statp->_mark,
                            sizeof(statp->_mark)) < 0) {
@@ -744,8 +731,10 @@
      * Send length & message
      */
     uint16_t len = htons(static_cast<uint16_t>(buflen));
-    iov[0] = evConsIovec(&len, INT16SZ);
-    iov[1] = evConsIovec((void*) buf, (size_t) buflen);
+    const iovec iov[] = {
+            {.iov_base = &len, .iov_len = INT16SZ},
+            {.iov_base = const_cast<uint8_t*>(buf), .iov_len = static_cast<size_t>(buflen)},
+    };
     if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
         *terrno = errno;
         PLOG(DEBUG) << __func__ << ": write failed: ";
@@ -853,8 +842,8 @@
 }
 
 /* return -1 on error (errno set), 0 on success */
-static int connect_with_timeout(int sock, const struct sockaddr* nsap, socklen_t salen,
-                                const struct timespec timeout) {
+static int connect_with_timeout(int sock, const sockaddr* nsap, socklen_t salen,
+                                const timespec timeout) {
     int res, origflags;
 
     origflags = fcntl(sock, F_GETFL, 0);
@@ -866,8 +855,8 @@
         goto done;
     }
     if (res != 0) {
-        struct timespec now = evNowTime();
-        struct timespec finish = evAddTime(now, timeout);
+        timespec now = evNowTime();
+        timespec finish = evAddTime(now, timeout);
         LOG(INFO) << __func__ << ": " << sock << " send_vc";
         res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
         if (res <= 0) {
@@ -948,7 +937,7 @@
             }
         }
 
-        resolv_tag_socket(statp->nssocks[ns], statp->uid);
+        resolv_tag_socket(statp->nssocks[ns], statp->uid, statp->pid);
         if (statp->_mark != MARK_UNSET) {
             if (setsockopt(statp->nssocks[ns], SOL_SOCKET, SO_MARK, &(statp->_mark),
                            sizeof(statp->_mark)) < 0) {
@@ -1092,6 +1081,7 @@
     char hbuf[NI_MAXHOST];
     char sbuf[NI_MAXSERV];
     constexpr int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+    const int err = errno;
 
     if (!WOULD_LOG(DEBUG)) return;
 
@@ -1101,6 +1091,7 @@
         strncpy(sbuf, "?", sizeof(sbuf) - 1);
         sbuf[sizeof(sbuf) - 1] = '\0';
     }
+    errno = err;
     PLOG(DEBUG) << __func__ << ": " << str << " ([" << hbuf << "]." << sbuf << "): ";
 }
 
diff --git a/resolv_cache_unit_test.cpp b/resolv_cache_unit_test.cpp
index 1db209f..4235480 100644
--- a/resolv_cache_unit_test.cpp
+++ b/resolv_cache_unit_test.cpp
@@ -43,7 +43,6 @@
 // Constant values sync'd from res_cache.cpp
 constexpr int DNS_HEADER_SIZE = 12;
 constexpr int MAX_ENTRIES = 64 * 2 * 5;
-constexpr int MAXPACKET = 8 * 1024;
 
 namespace {
 
@@ -99,13 +98,6 @@
     return std::time(nullptr);
 }
 
-std::string addrToString(const sockaddr_storage* addr) {
-    char out[INET6_ADDRSTRLEN] = {0};
-    getnameinfo((const sockaddr*)addr, sizeof(sockaddr_storage), out, INET6_ADDRSTRLEN, nullptr, 0,
-                NI_NUMERICHOST);
-    return std::string(out);
-}
-
 // Comparison for res_stats. Simply check the count in the cache test.
 bool operator==(const res_stats& a, const res_stats& b) {
     return std::tie(a.sample_count, a.sample_next) == std::tie(b.sample_count, b.sample_next);
diff --git a/resolv_private.h b/resolv_private.h
index ea7cdc2..e5efc64 100644
--- a/resolv_private.h
+++ b/resolv_private.h
@@ -86,10 +86,12 @@
     struct sockaddr_in sin;
     struct sockaddr_in6 sin6;
 };
+constexpr int MAXPACKET = 8 * 1024;
 
 struct ResState {
     unsigned netid;                           // NetId: cache key and socket mark
     uid_t uid;                                // uid of the app that sent the DNS lookup
+    pid_t pid;                                // pid of the app that sent the DNS lookup
     int nscount;                              // number of name srvers
     uint16_t id;                              // current message id
     std::vector<std::string> search_domains;  // domains to search
@@ -182,9 +184,9 @@
 
 android::net::IpVersion ipFamilyToIPVersion(int ipFamily);
 
-inline void resolv_tag_socket(int sock, uid_t uid) {
+inline void resolv_tag_socket(int sock, uid_t uid, pid_t pid) {
     if (android::net::gResNetdCallbacks.tagSocket != nullptr) {
-        if (int err = android::net::gResNetdCallbacks.tagSocket(sock, TAG_SYSTEM_DNS, uid)) {
+        if (int err = android::net::gResNetdCallbacks.tagSocket(sock, TAG_SYSTEM_DNS, uid, pid)) {
             LOG(WARNING) << "Failed to tag socket: " << strerror(-err);
         }
     }
@@ -194,4 +196,11 @@
     }
 }
 
+inline std::string addrToString(const sockaddr_storage* addr) {
+    char out[INET6_ADDRSTRLEN] = {0};
+    getnameinfo((const sockaddr*)addr, sizeof(sockaddr_storage), out, INET6_ADDRSTRLEN, nullptr, 0,
+                NI_NUMERICHOST);
+    return std::string(out);
+}
+
 #endif  // NETD_RESOLV_PRIVATE_H