Remove thread-local variable h_errno in gethostby{name, addr} 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: Ie9da1a6b18525967f0e8fe3d54b0df18e37d2b0e
diff --git a/gethnamaddr.cpp b/gethnamaddr.cpp
index 0ccc3d7..fd56f26 100644
--- a/gethnamaddr.cpp
+++ b/gethnamaddr.cpp
@@ -140,12 +140,11 @@
static int _dns_gethtbyname(const char* name, int af, getnamaddr* info);
static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
- size_t hbuflen, int* errorp,
- const android_net_context* netcontext);
+ size_t hbuflen, const android_net_context* netcontext);
static int gethostbyname_internal_real(const char* name, int af, res_state res, hostent* hp,
- char* buf, size_t buflen, int* he);
+ char* buf, size_t buflen);
static int android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t, int,
- struct hostent*, char*, size_t, int*,
+ struct hostent*, char*, size_t,
const struct android_net_context*);
static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
const struct android_net_context* netcontext,
@@ -471,9 +470,11 @@
}
static int gethostbyname_internal_real(const char* name, int af, res_state res, hostent* hp,
- char* buf, size_t buflen, int* he) {
+ char* buf, size_t buflen) {
getnamaddr info;
size_t size;
+ // TODO: Remove it once the data member "he" of struct getnamaddr is removed.
+ int he = NETDB_INTERNAL;
_DIAGASSERT(name != NULL);
@@ -485,7 +486,6 @@
size = NS_IN6ADDRSZ;
break;
default:
- *he = NETDB_INTERNAL;
errno = EAFNOSUPPORT;
return EAI_FAMILY;
}
@@ -527,24 +527,20 @@
}
}
- *he = NETDB_INTERNAL;
info.hp = hp;
info.buf = buf;
info.buflen = buflen;
- info.he = he;
- if (!_hf_gethtbyname2(name, af, &info)) {
+ info.he = &he; // TODO: Remove the data member "he" of struct getnamaddr.
+ if (_hf_gethtbyname2(name, af, &info)) {
int error = _dns_gethtbyname(name, af, &info);
if (error != 0) {
return error;
}
}
- *he = NETDB_SUCCESS;
return 0;
nospc:
- *he = NETDB_INTERNAL;
errno = ENOSPC;
- // Bad arguments
- return EAI_FAIL;
+ return EAI_MEMORY;
fake:
HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
@@ -553,7 +549,6 @@
if (size > buflen) goto nospc;
if (inet_pton(af, name, buf) <= 0) {
- *he = HOST_NOT_FOUND;
return EAI_NODATA;
}
hp->h_addr_list[0] = buf;
@@ -562,32 +557,30 @@
buflen -= size;
HENT_SCOPY(hp->h_name, name, buf, buflen);
if (res->options & RES_USE_INET6) map_v4v6_hostent(hp, &buf, buf + buflen);
- *he = NETDB_SUCCESS;
return 0;
}
// very similar in proxy-ness to android_getaddrinfo_proxy
static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
- size_t hbuflen, int* errorp,
- const android_net_context* netcontext) {
+ size_t hbuflen, const android_net_context* netcontext) {
res_setnetcontext(res, netcontext);
- return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
+ return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen);
}
static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t len, int af,
struct hostent* hp, char* buf, size_t buflen,
- int* he,
const struct android_net_context* netcontext) {
const u_char* uaddr = (const u_char*) addr;
socklen_t size;
struct getnamaddr info;
+ // TODO: Remove it once the data member "he" of struct getnamaddr is removed.
+ int he = NETDB_INTERNAL;
_DIAGASSERT(addr != NULL);
if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
(IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) ||
IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) {
- *he = HOST_NOT_FOUND;
return EAI_NODATA;
}
if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
@@ -608,35 +601,30 @@
break;
default:
errno = EAFNOSUPPORT;
- *he = NETDB_INTERNAL;
return EAI_FAMILY;
}
if (size != len) {
errno = EINVAL;
- *he = NETDB_INTERNAL;
// TODO: Consider to remap error code without relying on errno.
return EAI_SYSTEM;
}
info.hp = hp;
info.buf = buf;
info.buflen = buflen;
- info.he = he;
- *he = NETDB_INTERNAL;
- if (!_hf_gethtbyaddr(uaddr, len, af, &info)) {
+ info.he = &he; // TODO: Remove the data member "he" of struct getnamaddr.
+ if (_hf_gethtbyaddr(uaddr, len, af, &info)) {
int error = _dns_gethtbyaddr(uaddr, len, af, netcontext, &info);
if (error != 0) {
return error;
}
}
- *he = NETDB_SUCCESS;
return 0;
}
static int android_gethostbyaddrfornetcontext_proxy_internal(
const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
- int* he, const struct android_net_context* netcontext) {
- return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, he,
- netcontext);
+ const struct android_net_context* netcontext) {
+ return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, netcontext);
}
struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
@@ -878,7 +866,8 @@
}
int ai_error = EAI_NODATA;
- n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf), &ai_error);
+ int herrno = NETDB_INTERNAL;
+ n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf), &ai_error, &herrno);
if (n < 0) {
free(buf);
debugprintf("res_nsearch failed (%d)\n", res, n);
@@ -887,14 +876,14 @@
// get the nulltpr hp.
// TODO: Adjust the error closed to res_nsend instead of here after h_errno is removed.
if (ai_error == 0) {
- return herrnoToAiError(h_errno);
+ return herrnoToAiError(herrno);
}
return ai_error;
}
- hp = getanswer(buf, n, name, type, res, info->hp, info->buf, info->buflen, info->he);
+ hp = getanswer(buf, n, name, type, res, info->hp, info->buf, info->buflen, &herrno);
free(buf);
if (hp == NULL) {
- return herrnoToAiError(h_errno);
+ return herrnoToAiError(herrno);
}
return 0;
}
@@ -952,7 +941,8 @@
}
res_setnetcontext(res, netcontext);
int ai_error = 0;
- n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf), &ai_error);
+ int herrno = NETDB_INTERNAL;
+ n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf), &ai_error, &herrno);
if (n < 0) {
free(buf);
debugprintf("res_nquery failed (%d)\n", res, n);
@@ -963,12 +953,12 @@
// query progress. DNS server may respond a DNS packet without any answer for queried
// address. In this case, return error code from h_errno NO_DATA rather than rcode NOERROR
// (ai_error).
- return herrnoToAiError(h_errno);
+ return herrnoToAiError(herrno);
}
- hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, info->he);
+ hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, &herrno);
free(buf);
if (hp == NULL) {
- return herrnoToAiError(h_errno);
+ return herrnoToAiError(herrno);
}
char* bf = (char*) (hp->h_addr_list + 2);
@@ -1011,7 +1001,7 @@
if (res == NULL) return EAI_MEMORY;
res_static* rs = res_get_static(); // For thread-safety.
error = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
- &h_errno, netcontext);
+ netcontext);
if (error == 0) {
*hp = &rs->host;
}
@@ -1028,7 +1018,7 @@
hostent** hp) {
struct res_static* rs = res_get_static(); // For thread-safety.
int error = android_gethostbyaddrfornetcontext_proxy_internal(
- addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno, netcontext);
+ addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), netcontext);
if (error == 0) *hp = &rs->host;
return error;
}
diff --git a/hostent.h b/hostent.h
index 892ed88..6052489 100644
--- a/hostent.h
+++ b/hostent.h
@@ -42,8 +42,8 @@
};
// /etc/hosts lookup
-bool _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info);
-hostent* _hf_gethtbyname2(const char* name, int af, getnamaddr* info);
+int _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info);
+int _hf_gethtbyname2(const char* name, int af, getnamaddr* info);
hostent* netbsd_gethostent_r(FILE*, struct hostent*, char*, size_t, int*);
// Reserved padding for remapping IPv4 address to NAT64 synthesis IPv6 address
diff --git a/res_query.cpp b/res_query.cpp
index 6faa504..513c1db 100644
--- a/res_query.cpp
+++ b/res_query.cpp
@@ -103,7 +103,7 @@
* 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.
*/
@@ -111,7 +111,8 @@
int cl, int type, // class and type of query
u_char* answer, // buffer to put answer
int anslen, // size of answer buffer
- int* ai_error) // error will be set based on rcode
+ int* ai_error, // error will be set based on rcode
+ int* herrno) // legacy h_errno
{
u_char buf[MAXPACKET];
HEADER* hp = (HEADER*) (void*) answer;
@@ -136,7 +137,7 @@
#ifdef DEBUG
if (statp->options & RES_DEBUG) printf(";; res_query: mkquery failed\n");
#endif
- RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ *herrno = NO_RECOVERY;
return n;
}
n = res_nsend(statp, buf, n, answer, anslen, &rcode);
@@ -152,7 +153,7 @@
#ifdef DEBUG
if (statp->options & RES_DEBUG) printf(";; res_query: send error\n");
#endif
- RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ *herrno = TRY_AGAIN;
return n;
}
@@ -164,19 +165,19 @@
#endif
switch (hp->rcode) {
case NXDOMAIN:
- RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *herrno = HOST_NOT_FOUND;
break;
case SERVFAIL:
- RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ *herrno = TRY_AGAIN;
break;
case NOERROR:
- RES_SET_H_ERRNO(statp, NO_DATA);
+ *herrno = NO_DATA;
break;
case FORMERR:
case NOTIMP:
case REFUSED:
default:
- RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ *herrno = NO_RECOVERY;
break;
}
return -1;
@@ -188,13 +189,14 @@
* 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.
*/
int res_nsearch(res_state statp, const char* name, /* domain name */
int cl, int type, /* class and type of query */
u_char* answer, /* buffer to put answer */
int anslen, /* size of answer */
- int* ai_error) /* error will be set based on rcode*/
+ int* ai_error, /* error will be set based on rcode */
+ int* herrno) /* legacy h_errno */
{
const char *cp, *const *domain;
HEADER* hp = (HEADER*) (void*) answer;
@@ -205,7 +207,7 @@
int searched = 0;
errno = 0;
- RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
+ *herrno = HOST_NOT_FOUND; /* True if we never query. */
dots = 0;
for (cp = name; *cp != '\0'; cp++) dots += (*cp == '.');
@@ -219,9 +221,9 @@
*/
saved_herrno = -1;
if (dots >= statp->ndots || trailing_dot) {
- ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error);
+ ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error, herrno);
if (ret > 0 || trailing_dot) return ret;
- saved_herrno = statp->res_h_errno;
+ saved_herrno = *herrno;
tried_as_is++;
}
@@ -250,7 +252,8 @@
if (domain[0][0] == '\0' || (domain[0][0] == '.' && domain[0][1] == '\0'))
root_on_list++;
- ret = res_nquerydomain(statp, name, *domain, cl, type, answer, anslen, ai_error);
+ ret = res_nquerydomain(statp, name, *domain, cl, type, answer, anslen, ai_error,
+ herrno);
if (ret > 0) return ret;
/*
@@ -267,11 +270,11 @@
* fully-qualified.
*/
if (errno == ECONNREFUSED) {
- RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ *herrno = TRY_AGAIN;
return -1;
}
- switch (statp->res_h_errno) {
+ switch (*herrno) {
case NO_DATA:
got_nodata++;
break;
@@ -303,7 +306,7 @@
*/
if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) &&
!(tried_as_is || root_on_list)) {
- ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error);
+ ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error, herrno);
if (ret > 0) return ret;
}
@@ -315,11 +318,11 @@
* the last DNSRCH we did.
*/
if (saved_herrno != -1)
- RES_SET_H_ERRNO(statp, saved_herrno);
+ *herrno = saved_herrno;
else if (got_nodata)
- RES_SET_H_ERRNO(statp, NO_DATA);
+ *herrno = NO_DATA;
else if (got_servfail)
- RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ *herrno = TRY_AGAIN;
return -1;
}
@@ -331,7 +334,8 @@
int type, /* class and type of query */
u_char* answer, /* buffer to put answer */
int anslen, /* size of answer */
- int* ai_error) /* error will be set based on rcode*/
+ int* ai_error, /* error will be set based on rcode */
+ int* herrno) /* legacy h_errno */
{
char nbuf[MAXDNAME];
const char* longname = nbuf;
@@ -349,7 +353,7 @@
*/
n = strlen(name);
if (n >= MAXDNAME) {
- RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ *herrno = NO_RECOVERY;
return -1;
}
n--;
@@ -362,10 +366,10 @@
n = strlen(name);
d = strlen(domain);
if (n + d + 1 >= MAXDNAME) {
- RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ *herrno = NO_RECOVERY;
return -1;
}
snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
}
- return res_nquery(statp, longname, cl, type, answer, anslen, ai_error);
+ return res_nquery(statp, longname, cl, type, answer, anslen, ai_error, herrno);
}
diff --git a/resolv_private.h b/resolv_private.h
index bd48660..85907ac 100644
--- a/resolv_private.h
+++ b/resolv_private.h
@@ -258,9 +258,11 @@
/* Things involving a resolver context. */
int res_ninit(res_state);
void res_pquery(const res_state, const u_char*, int, FILE*);
-int res_nquery(res_state, const char*, int, int, u_char*, int, int*);
-int res_nsearch(res_state, const char*, int, int, u_char*, int, int*);
-int res_nquerydomain(res_state, const char*, const char*, int, int, u_char*, int, int*);
+// TODO: Consider that refactor res_nquery, res_nsearch and res_nquerydomain to return one error
+// code but two error codes.
+int res_nquery(res_state, const char*, int, int, u_char*, int, int*, int*);
+int res_nsearch(res_state, const char*, int, int, u_char*, int, int*, int*);
+int res_nquerydomain(res_state, const char*, const char*, int, int, u_char*, int, int*, int*);
int res_nmkquery(res_state, int, const char*, int, int, const u_char*, int, const u_char*, u_char*,
int);
int res_nsend(res_state, const u_char*, int, u_char*, int, int*);
diff --git a/sethostent.cpp b/sethostent.cpp
index 7c5b905..b0d2c75 100644
--- a/sethostent.cpp
+++ b/sethostent.cpp
@@ -61,7 +61,7 @@
}
}
-hostent* _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
+int _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
struct hostent *hp, hent;
char *buf, *ptr;
size_t len, num, i;
@@ -73,12 +73,13 @@
if (hf == NULL) {
errno = EINVAL;
*info->he = NETDB_INTERNAL;
- return NULL;
+ // TODO: Consider to remap error code without relying on errno.
+ return EAI_SYSTEM;
}
if ((ptr = buf = (char*) malloc(len = info->buflen)) == NULL) {
*info->he = NETDB_INTERNAL;
- return NULL;
+ return EAI_MEMORY;
}
hent.h_name = NULL;
@@ -129,7 +130,7 @@
if (num == 0) {
*info->he = HOST_NOT_FOUND;
free(buf);
- return NULL;
+ return EAI_NODATA;
}
hp = info->hp;
@@ -160,15 +161,15 @@
hp->h_aliases[anum] = NULL;
free(buf);
- return hp;
+ return 0;
nospc:
*info->he = NETDB_INTERNAL;
free(buf);
errno = ENOSPC;
- return NULL;
+ return EAI_MEMORY;
}
-bool _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info) {
+int _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info) {
info->hp->h_length = len;
info->hp->h_addrtype = af;
@@ -176,7 +177,8 @@
sethostent_r(&hf);
if (hf == NULL) {
*info->he = NETDB_INTERNAL;
- return false;
+ // TODO: Consider to remap error code without relying on errno.
+ return EAI_SYSTEM;
}
struct hostent* hp;
while ((hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, info->he)) != NULL)
@@ -184,9 +186,9 @@
endhostent_r(&hf);
if (hp == NULL) {
- if (errno == ENOSPC) return false; // glibc compatibility.
+ if (errno == ENOSPC) return EAI_MEMORY; // glibc compatibility.
*info->he = HOST_NOT_FOUND;
- return false;
+ return EAI_NODATA;
}
- return true;
+ return 0;
}