Merge "Make private DNS connect timeout configurable"
diff --git a/PrivateDnsConfiguration.cpp b/PrivateDnsConfiguration.cpp
index dbe0557..9242222 100644
--- a/PrivateDnsConfiguration.cpp
+++ b/PrivateDnsConfiguration.cpp
@@ -42,7 +42,10 @@
 }
 
 bool parseServer(const char* server, sockaddr_storage* parsed) {
-    addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV};
+    addrinfo hints = {
+            .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV,
+            .ai_family = AF_UNSPEC,
+    };
     addrinfo* res;
 
     int err = getaddrinfo(server, "853", &hints, &res);
diff --git a/gethnamaddr.cpp b/gethnamaddr.cpp
index c9a6b2a..a2e88b4 100644
--- a/gethnamaddr.cpp
+++ b/gethnamaddr.cpp
@@ -76,6 +76,7 @@
 #include "netd_resolv/resolv.h"
 #include "resolv_cache.h"
 #include "resolv_private.h"
+#include "resolv_static.h"
 #include "stats.pb.h"
 
 using android::net::NetworkDnsEventReported;
diff --git a/res_cache.cpp b/res_cache.cpp
index b9737fe..4b5ba28 100644
--- a/res_cache.cpp
+++ b/res_cache.cpp
@@ -59,7 +59,6 @@
 #include <server_configurable_flags/get_flags.h>
 
 #include "res_debug.h"
-#include "res_state_ext.h"
 #include "resolv_private.h"
 
 using android::base::StringAppendF;
@@ -1488,7 +1487,10 @@
     for (int i = 0; i < numservers; i++) {
         // The addrinfo structures allocated here are freed in free_nameservers_locked().
         const addrinfo hints = {
-                .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, .ai_flags = AI_NUMERICHOST};
+                .ai_flags = AI_NUMERICHOST,
+                .ai_family = AF_UNSPEC,
+                .ai_socktype = SOCK_DGRAM,
+        };
         const int rt = getaddrinfo_numeric(nameservers[i].c_str(), "53", hints, &nsaddrinfo[i]);
         if (rt != 0) {
             for (int j = 0; j < i; j++) {
@@ -1582,8 +1584,8 @@
                 break;
             }
 
-            if ((size_t) ai->ai_addrlen <= sizeof(statp->_u._ext.ext->nsaddrs[0])) {
-                memcpy(&statp->_u._ext.ext->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen);
+            if ((size_t)ai->ai_addrlen <= sizeof(statp->nsaddrs[0])) {
+                memcpy(&statp->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen);
             } else {
                 LOG(INFO) << __func__ << ": found too long addrlen";
             }
diff --git a/res_init.cpp b/res_init.cpp
index 502f9ea..12f4124 100644
--- a/res_init.cpp
+++ b/res_init.cpp
@@ -90,7 +90,6 @@
 #include <unistd.h>
 
 #include "netd_resolv/resolv.h"
-#include "res_state_ext.h"
 #include "resolv_private.h"
 
 // Set up Resolver state default settings.
@@ -100,15 +99,13 @@
     statp->id = arc4random_uniform(65536);
     statp->_mark = MARK_UNSET;
 
-    statp->nscount = 0;
     statp->ndots = 1;
     statp->_vcsock = -1;
     statp->_flags = 0;
-    statp->_u._ext.nscount = 0;
-    statp->_u._ext.ext = (res_state_ext*) malloc(sizeof(*statp->_u._ext.ext));
     statp->netcontext_flags = 0;
-    if (statp->_u._ext.ext != NULL) {
-        memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
+
+    for (int ns = 0; ns < MAXNS; ns++) {
+        statp->nssocks[ns] = -1;
     }
 
     // The following dummy initialization is probably useless because
@@ -119,7 +116,7 @@
             .sin.sin_family = AF_INET,
             .sin.sin_port = htons(NAMESERVER_PORT),
     };
-    memcpy(&statp->_u._ext.ext->nsaddrs[0], &u, sizeof(u));
+    memcpy(&statp->nsaddrs, &u, sizeof(u));
     statp->nscount = 1;
 }
 
@@ -138,20 +135,14 @@
         statp->_vcsock = -1;
         statp->_flags &= ~RES_F_VC;
     }
-    for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
-        if (statp->_u._ext.nssocks[ns] != -1) {
-            (void) close(statp->_u._ext.nssocks[ns]);
-            statp->_u._ext.nssocks[ns] = -1;
+    for (ns = 0; ns < MAXNS; ns++) {
+        if (statp->nssocks[ns] != -1) {
+            close(statp->nssocks[ns]);
+            statp->nssocks[ns] = -1;
         }
     }
 }
 
-void res_ndestroy(res_state statp) {
-    res_nclose(statp);
-    if (statp->_u._ext.ext != NULL) free(statp->_u._ext.ext);
-    statp->_u._ext.ext = NULL;
-}
-
 void res_setnetcontext(res_state statp, const struct android_net_context* netcontext,
                        android::net::NetworkDnsEventReported* _Nonnull event) {
     if (statp != nullptr) {
diff --git a/res_send.cpp b/res_send.cpp
index af60376..6616ca3 100644
--- a/res_send.cpp
+++ b/res_send.cpp
@@ -107,7 +107,6 @@
 #include "netd_resolv/stats.h"
 #include "private/android_filesystem_config.h"
 #include "res_debug.h"
-#include "res_state_ext.h"
 #include "resolv_cache.h"
 #include "stats.pb.h"
 
@@ -291,16 +290,8 @@
     }
 }
 
-/* int
- * res_isourserver(ina)
- *	looks up "ina" in _res.ns_addr_list[]
- * returns:
- *	0  : not found
- *	>0 : found
- * author:
- *	paul vixie, 29may94
- */
-static int res_ourserver_p(res_state statp, const sockaddr* sa) {
+// Looks up the nameserver address in res.nsaddrs[], returns true if found, otherwise false.
+static bool res_ourserver_p(res_state statp, const sockaddr* sa) {
     const sockaddr_in *inp, *srv;
     const sockaddr_in6 *in6p, *srv6;
     int ns;
@@ -313,11 +304,10 @@
                 if (srv->sin_family == inp->sin_family && srv->sin_port == inp->sin_port &&
                     (srv->sin_addr.s_addr == INADDR_ANY ||
                      srv->sin_addr.s_addr == inp->sin_addr.s_addr))
-                    return 1;
+                    return true;
             }
             break;
         case AF_INET6:
-            if (statp->_u._ext.ext == NULL) break;
             in6p = (const struct sockaddr_in6*) (const void*) sa;
             for (ns = 0; ns < statp->nscount; ns++) {
                 srv6 = (struct sockaddr_in6*) (void*) get_nsaddr(statp, (size_t) ns);
@@ -327,13 +317,13 @@
 #endif
                     (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
                      IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
-                    return 1;
+                    return true;
             }
             break;
         default:
             break;
     }
-    return 0;
+    return false;
 }
 
 /* int
@@ -457,49 +447,6 @@
         return -ESRCH;
     }
 
-    /*
-     * If the ns_addr_list in the resolver context has changed, then
-     * invalidate our cached copy and the associated timing data.
-     */
-    if (statp->_u._ext.nscount != 0) {
-        int needclose = 0;
-        struct sockaddr_storage peer;
-        socklen_t peerlen;
-
-        if (statp->_u._ext.nscount != statp->nscount) {
-            needclose++;
-        } else {
-            for (int ns = 0; ns < statp->nscount; ns++) {
-                if (statp->_u._ext.nssocks[ns] == -1) continue;
-                peerlen = sizeof(peer);
-                if (getpeername(statp->_u._ext.nssocks[ns], (struct sockaddr*) (void*) &peer,
-                                &peerlen) < 0) {
-                    needclose++;
-                    break;
-                }
-                if (!sock_eq((struct sockaddr*) (void*) &peer, get_nsaddr(statp, (size_t) ns))) {
-                    needclose++;
-                    break;
-                }
-            }
-        }
-        if (needclose) {
-            res_nclose(statp);
-            statp->_u._ext.nscount = 0;
-        }
-    }
-
-    /*
-     * Maybe initialize our private copy of the ns_addr_list.
-     */
-    if (statp->_u._ext.nscount == 0) {
-        for (int ns = 0; ns < statp->nscount; ns++) {
-            statp->_u._ext.nstimes[ns] = RES_MAXTIME;
-            statp->_u._ext.nssocks[ns] = -1;
-        }
-        statp->_u._ext.nscount = statp->nscount;
-    }
-
     res_stats stats[MAXNS];
     res_params params;
     int revision_id = resolv_cache_get_resolver_stats(statp->netid, &params, stats);
@@ -684,7 +631,7 @@
 }
 
 static struct sockaddr* get_nsaddr(res_state statp, size_t n) {
-    return (struct sockaddr*)(void*)&statp->_u._ext.ext->nsaddrs[n];
+    return (struct sockaddr*)(void*)&statp->nsaddrs[n];
 }
 
 static struct timespec get_timeout(res_state statp, const res_params* params, const int ns) {
@@ -991,9 +938,9 @@
 
     nsap = get_nsaddr(statp, (size_t) ns);
     nsaplen = get_salen(nsap);
-    if (statp->_u._ext.nssocks[ns] == -1) {
-        statp->_u._ext.nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-        if (statp->_u._ext.nssocks[ns] < 0) {
+    if (statp->nssocks[ns] == -1) {
+        statp->nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+        if (statp->nssocks[ns] < 0) {
             switch (errno) {
                 case EPROTONOSUPPORT:
                 case EPFNOSUPPORT:
@@ -1007,9 +954,9 @@
             }
         }
 
-        resolv_tag_socket(statp->_u._ext.nssocks[ns], statp->uid);
+        resolv_tag_socket(statp->nssocks[ns], statp->uid);
         if (statp->_mark != MARK_UNSET) {
-            if (setsockopt(statp->_u._ext.nssocks[ns], SOL_SOCKET, SO_MARK, &(statp->_mark),
+            if (setsockopt(statp->nssocks[ns], SOL_SOCKET, SO_MARK, &(statp->_mark),
                            sizeof(statp->_mark)) < 0) {
                 res_nclose(statp);
                 return -1;
@@ -1019,19 +966,19 @@
         // on the next socket operation when the server responds with an
         // ICMP port-unreachable error. This way we can detect the absence of
         // a nameserver without timing out.
-        if (random_bind(statp->_u._ext.nssocks[ns], nsap->sa_family) < 0) {
+        if (random_bind(statp->nssocks[ns], nsap->sa_family) < 0) {
             dump_error("bind(dg)", nsap, nsaplen);
             res_nclose(statp);
             return (0);
         }
-        if (connect(statp->_u._ext.nssocks[ns], nsap, (socklen_t) nsaplen) < 0) {
+        if (connect(statp->nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
             dump_error("connect(dg)", nsap, nsaplen);
             res_nclose(statp);
             return (0);
         }
         LOG(DEBUG) << __func__ << ": new DG socket";
     }
-    s = statp->_u._ext.nssocks[ns];
+    s = statp->nssocks[ns];
     if (send(s, (const char*) buf, (size_t) buflen, 0) != buflen) {
         PLOG(DEBUG) << __func__ << ": send: ";
         res_nclose(statp);
diff --git a/res_state.cpp b/res_state.cpp
index 372c37a..316a4f9 100644
--- a/res_state.cpp
+++ b/res_state.cpp
@@ -41,6 +41,7 @@
 #include "res_init.h"
 #include "resolv_cache.h"
 #include "resolv_private.h"
+#include "resolv_static.h"
 
 typedef struct {
     // TODO: Have one __res_state per network so we don't have to repopulate frequently.
@@ -75,7 +76,7 @@
     LOG(VERBOSE) << __func__ << ": rt=" << rt << " for thread=" << gettid();
 
     res_static_done(rt->_rstatic);
-    res_ndestroy(rt->_nres);
+    res_nclose(rt->_nres);
     free(rt);
 }
 
diff --git a/res_state_ext.h b/res_state_ext.h
deleted file mode 100644
index d0dbc1a..0000000
--- a/res_state_ext.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*	$NetBSD: res_private.h,v 1.1.1.1 2004/05/20 17:18:54 christos Exp $	*/
-
-#ifndef NETD_RES_STATE_EXT_H
-#define NETD_RES_STATE_EXT_H
-
-#include "resolv_private.h"
-
-// TODO: consider inlining into res_state
-struct res_state_ext {
-    sockaddr_union nsaddrs[MAXNS];
-};
-
-#endif  // NETD_RES_STATE_EXT_H
diff --git a/resolv_integration_test.cpp b/resolv_integration_test.cpp
index 0705676..27e21d2 100644
--- a/resolv_integration_test.cpp
+++ b/resolv_integration_test.cpp
@@ -558,8 +558,8 @@
     // TODO: Test other invalid socket types.
     const addrinfo hints = {
             .ai_family = AF_UNSPEC,
-            .ai_protocol = ANY,
             .ai_socktype = SOCK_PACKET,
+            .ai_protocol = ANY,
     };
     addrinfo* result = nullptr;
     // This is a valid hint, but the query won't be sent because the socket type is
@@ -2640,10 +2640,10 @@
         SCOPED_TRACE(config.asParameters());
 
         addrinfo hints = {
+                .ai_flags = config.flag,
                 .ai_family = AF_UNSPEC,  // any address family
                 .ai_socktype = 0,        // any type
                 .ai_protocol = 0,        // any protocol
-                .ai_flags = config.flag,
         };
 
         // Assign hostname as null and service as port name.
diff --git a/resolv_private.h b/resolv_private.h
index 0029254..4c881c2 100644
--- a/resolv_private.h
+++ b/resolv_private.h
@@ -65,7 +65,6 @@
 #include "netd_resolv/params.h"
 #include "netd_resolv/resolv.h"
 #include "netd_resolv/stats.h"
-#include "resolv_static.h"
 #include "stats.pb.h"
 
 // Linux defines MAXHOSTNAMELEN as 64, while the domain name limit in
@@ -79,11 +78,14 @@
  * Global defines and variables for resolver stub.
  */
 #define RES_TIMEOUT 5000 /* min. milliseconds between retries */
-#define RES_MAXNDOTS 15   /* should reflect bit field size */
 #define RES_DFLRETRY 2    /* Default #/tries. */
-#define RES_MAXTIME 65535 /* Infinity, in milliseconds. */
 
-struct res_state_ext;
+// Holds either a sockaddr_in or a sockaddr_in6.
+union sockaddr_union {
+    struct sockaddr sa;
+    struct sockaddr_in sin;
+    struct sockaddr_in6 sin6;
+};
 
 struct __res_state {
     unsigned netid;                           // NetId: cache key and socket mark
@@ -91,32 +93,18 @@
     int nscount;                              // number of name srvers
     uint16_t id;                              // current message id
     std::vector<std::string> search_domains;  // domains to search
+    sockaddr_union nsaddrs[MAXNS];
+    int nssocks[MAXNS];                       // UDP sockets to nameservers
     unsigned ndots : 4;                       // threshold for initial abs. query
-    unsigned _mark;       /* If non-0 SET_MARK to _mark on all request sockets */
-    int _vcsock;          /* PRIVATE: for res_send VC i/o */
-    uint32_t _flags;      /* PRIVATE: see below */
-    union {
-        struct {
-            uint16_t nscount;
-            uint16_t nstimes[MAXNS]; /* ms. */
-            int nssocks[MAXNS];
-            struct res_state_ext* ext; /* extention for IPv6 */
-        } _ext;
-    } _u;
-    struct res_static rstatic[1];
+    unsigned _mark;                           // If non-0 SET_MARK to _mark on all request sockets
+    int _vcsock;                              // TCP socket (but why not one per nameserver?)
+    uint32_t _flags;                          // See RES_F_* defines below
     android::net::NetworkDnsEventReported* event;
     uint32_t netcontext_flags;
 };
 
 typedef struct __res_state* res_state;
 
-// Holds either a sockaddr_in or a sockaddr_in6.
-typedef union sockaddr_union {
-    struct sockaddr sa;
-    struct sockaddr_in sin;
-    struct sockaddr_in6 sin6;
-} sockaddr_union;
-
 /* Retrieve a local copy of the stats for the given netid. The buffer must have space for
  * MAXNS __resolver_stats. Returns the revision id of the resolvers used.
  */
@@ -174,11 +162,8 @@
 int res_nsend(res_state, const uint8_t*, int, uint8_t*, int, int*, uint32_t);
 void res_nclose(res_state);
 int res_nopt(res_state, int, uint8_t*, int, int);
-void res_ndestroy(res_state);
-void res_setservers(res_state, const sockaddr_union*, int);
-int res_getservers(res_state, sockaddr_union*, int);
 
-struct android_net_context; /* forward */
+struct android_net_context;
 void res_setnetcontext(res_state, const struct android_net_context*,
                        android::net::NetworkDnsEventReported* event);
 
diff --git a/resolv_unit_test.cpp b/resolv_unit_test.cpp
index f9accd0..fa59571 100644
--- a/resolv_unit_test.cpp
+++ b/resolv_unit_test.cpp
@@ -236,8 +236,8 @@
             for (const auto& socktype : {SOCK_RDM, SOCK_SEQPACKET, SOCK_DCCP, SOCK_PACKET}) {
                 const addrinfo hints = {
                         .ai_family = family,
-                        .ai_protocol = protocol,
                         .ai_socktype = socktype,
+                        .ai_protocol = protocol,
                 };
                 for (const char* service : {static_cast<const char*>(nullptr),  // service is null
                                             "80",
@@ -295,8 +295,8 @@
                 addrinfo* result = nullptr;
                 const addrinfo hints = {
                         .ai_family = family,
-                        .ai_protocol = protocol,
                         .ai_socktype = socktype,
+                        .ai_protocol = protocol,
                 };
                 NetworkDnsEventReported event;
                 int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
diff --git a/sethostent.cpp b/sethostent.cpp
index 6423bee..acd7151 100644
--- a/sethostent.cpp
+++ b/sethostent.cpp
@@ -42,6 +42,7 @@
 
 #include "hostent.h"
 #include "resolv_private.h"
+#include "resolv_static.h"
 
 #define ALIGNBYTES (sizeof(uintptr_t) - 1)
 #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
diff --git a/tests/dns_responder/dns_responder.cpp b/tests/dns_responder/dns_responder.cpp
index 4bac4b0..072c2dd 100644
--- a/tests/dns_responder/dns_responder.cpp
+++ b/tests/dns_responder/dns_responder.cpp
@@ -515,7 +515,11 @@
     }
 
     // Set up UDP socket.
-    addrinfo ai_hints{.ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, .ai_flags = AI_PASSIVE};
+    addrinfo ai_hints{
+            .ai_flags = AI_PASSIVE,
+            .ai_family = AF_UNSPEC,
+            .ai_socktype = SOCK_DGRAM,
+    };
     addrinfo* ai_res = nullptr;
     int rv = getaddrinfo(listen_address_.c_str(), listen_service_.c_str(), &ai_hints, &ai_res);
     ScopedAddrinfo ai_res_cleanup(ai_res);
diff --git a/tests/dns_responder/dns_tls_frontend.cpp b/tests/dns_responder/dns_tls_frontend.cpp
index 059527d..6399842 100644
--- a/tests/dns_responder/dns_tls_frontend.cpp
+++ b/tests/dns_responder/dns_tls_frontend.cpp
@@ -164,7 +164,10 @@
 
     // Set up TCP server socket for clients.
     addrinfo frontend_ai_hints{
-            .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE};
+            .ai_flags = AI_PASSIVE,
+            .ai_family = AF_UNSPEC,
+            .ai_socktype = SOCK_STREAM,
+    };
     addrinfo* frontend_ai_res = nullptr;
     int rv = getaddrinfo(listen_address_.c_str(), listen_service_.c_str(), &frontend_ai_hints,
                          &frontend_ai_res);