Remove thread-local variable h_errno in getaddrinfo related APIs

Using a thread-local variable to return an int to the caller is a hack and
adds a lot of complexity. Return error code with an int pointer instead.

Test: built, flashed, booted
      system/netd/tests/runtests.sh pass

Change-Id: Idd11da334f78ba04be72566764351d328866385a
diff --git a/resolv/getaddrinfo.cpp b/resolv/getaddrinfo.cpp
index 45c3792..84aa278 100644
--- a/resolv/getaddrinfo.cpp
+++ b/resolv/getaddrinfo.cpp
@@ -134,7 +134,8 @@
 static const struct afd* find_afd(int);
 static int ip6_str2scopeid(const char*, struct sockaddr_in6*, u_int32_t*);
 
-static struct addrinfo* getanswer(const querybuf*, int, const char*, int, const struct addrinfo*);
+static struct addrinfo* getanswer(const querybuf*, 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);
 static void _sethtent(FILE**);
@@ -143,10 +144,14 @@
 static bool files_getaddrinfo(const char* name, const addrinfo* pai, addrinfo** res);
 static int _find_src_addr(const struct sockaddr*, struct sockaddr*, unsigned, uid_t);
 
-static int res_queryN(const char* name, res_target* target, res_state res, int* ai_error);
-static int res_searchN(const char* name, res_target* target, res_state res, int* ai_error);
+// TODO: Consider that refactor res_queryN, res_searchN and res_querydomainN to return one error
+// code but two error codes.
+static int res_queryN(const char* name, res_target* target, res_state res, int* ai_error,
+                      int* herrno);
+static int res_searchN(const char* name, res_target* target, res_state res, int* ai_error,
+                       int* herrno);
 static int res_querydomainN(const char* name, const char* domain, res_target* target, res_state res,
-                            int* ai_error);
+                            int* ai_error, int* herrno);
 
 const char* const ai_errlist[] = {
         "Success",
@@ -820,13 +825,13 @@
 #define BOUNDS_CHECK(ptr, count)     \
     do {                             \
         if (eom - (ptr) < (count)) { \
-            h_errno = NO_RECOVERY;   \
+            *herrno = NO_RECOVERY;   \
             return NULL;             \
         }                            \
     } while (0)
 
 static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
-                                  const struct addrinfo* pai) {
+                                  const struct addrinfo* pai, int* herrno) {
     struct addrinfo sentinel = {};
     struct addrinfo *cur;
     struct addrinfo ai;
@@ -871,12 +876,12 @@
     cp = answer->buf;
     BOUNDED_INCR(HFIXEDSZ);
     if (qdcount != 1) {
-        h_errno = NO_RECOVERY;
+        *herrno = NO_RECOVERY;
         return (NULL);
     }
     n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
     if ((n < 0) || !(*name_ok)(bp)) {
-        h_errno = NO_RECOVERY;
+        *herrno = NO_RECOVERY;
         return (NULL);
     }
     BOUNDED_INCR(n + QFIXEDSZ);
@@ -887,7 +892,7 @@
          */
         n = strlen(bp) + 1; /* for the \0 */
         if (n >= MAXHOSTNAMELEN) {
-            h_errno = NO_RECOVERY;
+            *herrno = NO_RECOVERY;
             return (NULL);
         }
         canonname = bp;
@@ -1003,11 +1008,11 @@
             (void) get_canonname(pai, sentinel.ai_next, qname);
         else
             (void) get_canonname(pai, sentinel.ai_next, canonname);
-        h_errno = NETDB_SUCCESS;
+        *herrno = NETDB_SUCCESS;
         return sentinel.ai_next;
     }
 
-    h_errno = NO_RECOVERY;
+    *herrno = NO_RECOVERY;
     return NULL;
 }
 
@@ -1391,13 +1396,11 @@
 
     querybuf* buf = (querybuf*) malloc(sizeof(*buf));
     if (buf == NULL) {
-        h_errno = NETDB_INTERNAL;
         return EAI_MEMORY;
     }
     querybuf* buf2 = (querybuf*) malloc(sizeof(*buf2));
     if (buf2 == NULL) {
         free(buf);
-        h_errno = NETDB_INTERNAL;
         return EAI_MEMORY;
     }
 
@@ -1468,24 +1471,25 @@
 
     // Pass ai_error to catch more detailed errors rather than EAI_NODATA.
     int ai_error = EAI_NODATA;
-    if (res_searchN(name, &q, res, &ai_error) < 0) {
+    int herrno = NETDB_INTERNAL;
+    if (res_searchN(name, &q, res, &ai_error, &herrno) < 0) {
         free(buf);
         free(buf2);
         return ai_error;  // TODO: Decode error from h_errno like we do below
     }
-    ai = getanswer(buf, q.n, q.name, q.qtype, pai);
+    ai = getanswer(buf, q.n, q.name, q.qtype, pai, &herrno);
     if (ai) {
         cur->ai_next = ai;
         while (cur && cur->ai_next) cur = cur->ai_next;
     }
     if (q.next) {
-        ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
+        ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, &herrno);
         if (ai) cur->ai_next = ai;
     }
     free(buf);
     free(buf2);
     if (sentinel.ai_next == NULL) {
-        return herrnoToAiError(h_errno);
+        return herrnoToAiError(herrno);
     }
 
     _rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
@@ -1586,11 +1590,12 @@
  * Perform preliminary check of answer, returning success only
  * if no error is indicated and the answer count is nonzero.
  * Return the size of the response on success, -1 on error.
- * Error number is left in h_errno.
+ * Error number is left in *herrno.
  *
  * Caller must parse answer and determine whether it answers the question.
  */
-static int res_queryN(const char* name, res_target* target, res_state res, int* ai_error) {
+static int res_queryN(const char* name, res_target* target, res_state res, int* ai_error,
+                      int* herrno) {
     u_char buf[MAXPACKET];
     HEADER* hp;
     int n;
@@ -1632,7 +1637,7 @@
 #ifdef DEBUG
             if (res->options & RES_DEBUG) printf(";; res_nquery: mkquery failed\n");
 #endif
-            h_errno = NO_RECOVERY;
+            *herrno = NO_RECOVERY;
             return n;
         }
 
@@ -1665,19 +1670,19 @@
     if (ancount == 0) {
         switch (rcode) {
             case NXDOMAIN:
-                h_errno = HOST_NOT_FOUND;
+                *herrno = HOST_NOT_FOUND;
                 break;
             case SERVFAIL:
-                h_errno = TRY_AGAIN;
+                *herrno = TRY_AGAIN;
                 break;
             case NOERROR:
-                h_errno = NO_DATA;
+                *herrno = NO_DATA;
                 break;
             case FORMERR:
             case NOTIMP:
             case REFUSED:
             default:
-                h_errno = NO_RECOVERY;
+                *herrno = NO_RECOVERY;
                 break;
         }
         return -1;
@@ -1689,9 +1694,10 @@
  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  * Return the size of the response on success, -1 on error.
  * If enabled, implement search rules until answer or unrecoverable failure
- * is detected.  Error code, if any, is left in h_errno.
+ * is detected.  Error code, if any, is left in *herrno.
  */
-static int res_searchN(const char* name, res_target* target, res_state res, int* ai_error) {
+static int res_searchN(const char* name, res_target* target, res_state res, int* ai_error,
+                       int* herrno) {
     const char *cp, *const *domain;
     HEADER* hp;
     u_int dots;
@@ -1704,7 +1710,7 @@
     hp = (HEADER*) (void*) target->answer; /*XXX*/
 
     errno = 0;
-    h_errno = HOST_NOT_FOUND; /* default, if we never query */
+    *herrno = HOST_NOT_FOUND; /* default, if we never query */
     dots = 0;
     for (cp = name; *cp; cp++) dots += (*cp == '.');
     trailing_dot = 0;
@@ -1716,9 +1722,9 @@
      */
     saved_herrno = -1;
     if (dots >= res->ndots) {
-        ret = res_querydomainN(name, NULL, target, res, ai_error);
+        ret = res_querydomainN(name, NULL, target, res, ai_error, herrno);
         if (ret > 0) return (ret);
-        saved_herrno = h_errno;
+        saved_herrno = *herrno;
         tried_as_is++;
     }
 
@@ -1739,7 +1745,7 @@
         _resolv_populate_res_for_net(res);
 
         for (domain = (const char* const*) res->dnsrch; *domain && !done; domain++) {
-            ret = res_querydomainN(name, *domain, target, res, ai_error);
+            ret = res_querydomainN(name, *domain, target, res, ai_error, herrno);
             if (ret > 0) return ret;
 
             /*
@@ -1756,11 +1762,11 @@
              * fully-qualified.
              */
             if (errno == ECONNREFUSED) {
-                h_errno = TRY_AGAIN;
+                *herrno = TRY_AGAIN;
                 return -1;
             }
 
-            switch (h_errno) {
+            switch (*herrno) {
                 case NO_DATA:
                     got_nodata++;
                     [[fallthrough]];
@@ -1792,7 +1798,7 @@
      * name or whether it ends with a dot.
      */
     if (!tried_as_is) {
-        ret = res_querydomainN(name, NULL, target, res, ai_error);
+        ret = res_querydomainN(name, NULL, target, res, ai_error, herrno);
         if (ret > 0) return ret;
     }
 
@@ -1805,11 +1811,11 @@
      * the last DNSRCH we did.
      */
     if (saved_herrno != -1)
-        h_errno = saved_herrno;
+        *herrno = saved_herrno;
     else if (got_nodata)
-        h_errno = NO_DATA;
+        *herrno = NO_DATA;
     else if (got_servfail)
-        h_errno = TRY_AGAIN;
+        *herrno = TRY_AGAIN;
     return -1;
 }
 
@@ -1818,7 +1824,7 @@
  * removing a trailing dot from name if domain is NULL.
  */
 static int res_querydomainN(const char* name, const char* domain, res_target* target, res_state res,
-                            int* ai_error) {
+                            int* ai_error, int* herrno) {
     char nbuf[MAXDNAME];
     const char* longname = nbuf;
     size_t n, d;
@@ -1837,7 +1843,7 @@
          */
         n = strlen(name);
         if (n + 1 > sizeof(nbuf)) {
-            h_errno = NO_RECOVERY;
+            *herrno = NO_RECOVERY;
             return -1;
         }
         if (n > 0 && name[--n] == '.') {
@@ -1849,10 +1855,10 @@
         n = strlen(name);
         d = strlen(domain);
         if (n + 1 + d + 1 > sizeof(nbuf)) {
-            h_errno = NO_RECOVERY;
+            *herrno = NO_RECOVERY;
             return -1;
         }
         snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
     }
-    return res_queryN(longname, target, res, ai_error);
+    return res_queryN(longname, target, res, ai_error, herrno);
 }