Merge "Remap existing EAI_SYSTEM to avoid relying on global errno variable"
diff --git a/resolv/getaddrinfo.cpp b/resolv/getaddrinfo.cpp
index 7f7683b..4795d38 100644
--- a/resolv/getaddrinfo.cpp
+++ b/resolv/getaddrinfo.cpp
@@ -1441,25 +1441,29 @@
*/
res_setnetcontext(res, netcontext);
- int herrno = NETDB_INTERNAL;
- if (res_searchN(name, &q, res, &herrno) < 0) {
- // Pass herrno to catch more detailed errors rather than EAI_NODATA.
- return herrnoToAiErrno(herrno);
+ int he;
+ if (res_searchN(name, &q, res, &he) < 0) {
+ // Return h_errno (he) to catch more detailed errors rather than EAI_NODATA.
+ // Note that res_searchN() doesn't set the pair NETDB_INTERNAL and errno.
+ // See also herrnoToAiErrno().
+ return herrnoToAiErrno(he);
}
addrinfo sentinel = {};
addrinfo* cur = &sentinel;
- addrinfo* ai = getanswer(buf.get(), q.n, q.name, q.qtype, pai, &herrno);
+ addrinfo* ai = getanswer(buf.get(), 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, &herrno);
+ ai = getanswer(buf2.get(), q2.n, q2.name, q2.qtype, pai, &he);
if (ai) cur->ai_next = ai;
}
if (sentinel.ai_next == NULL) {
- return herrnoToAiErrno(herrno);
+ // Note that getanswer() doesn't set the pair NETDB_INTERNAL and errno.
+ // See also herrnoToAiErrno().
+ return herrnoToAiErrno(he);
}
_rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
diff --git a/resolv/gethnamaddr.cpp b/resolv/gethnamaddr.cpp
index 0c0a865..b3ae91a 100644
--- a/resolv/gethnamaddr.cpp
+++ b/resolv/gethnamaddr.cpp
@@ -421,7 +421,6 @@
size = NS_IN6ADDRSZ;
break;
default:
- errno = EAFNOSUPPORT;
return EAI_FAMILY;
}
if (buflen < size) goto nospc;
@@ -467,13 +466,10 @@
info.buflen = buflen;
if (_hf_gethtbyname2(name, af, &info)) {
int error = dns_gethtbyname(name, af, &info);
- if (error != 0) {
- return error;
- }
+ if (error != 0) return error;
}
return 0;
nospc:
- errno = ENOSPC;
return EAI_MEMORY;
fake:
HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
@@ -532,22 +528,21 @@
size = NS_IN6ADDRSZ;
break;
default:
- errno = EAFNOSUPPORT;
return EAI_FAMILY;
}
if (size != len) {
- errno = EINVAL;
- // TODO: Consider to remap error code without relying on errno.
- return EAI_SYSTEM;
+ // TODO: Consider converting to a private extended EAI_* error code.
+ // Currently, the EAI_* value has no corresponding error code for invalid argument socket
+ // length. In order to not rely on errno, convert the original error code pair, EAI_SYSTEM
+ // and EINVAL, to EAI_FAIL.
+ return EAI_FAIL;
}
info.hp = hp;
info.buf = buf;
info.buflen = buflen;
if (_hf_gethtbyaddr(uaddr, len, af, &info)) {
int error = dns_gethtbyaddr(uaddr, len, af, netcontext, &info);
- if (error != 0) {
- return error;
- }
+ if (error != 0) return error;
}
return 0;
}
@@ -558,6 +553,8 @@
return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, netcontext);
}
+// TODO: Consider leaving function without returning error code as _gethtent() does because
+// the error code of the caller does not currently return to netd.
struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
int* he) {
const size_t line_buf_size = sizeof(res_get_static()->hostbuf);
@@ -780,18 +777,18 @@
res_state res = res_get_state();
if (!res) return EAI_MEMORY;
- int herrno = NETDB_INTERNAL;
- n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf), &herrno);
+ int he;
+ n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf), &he);
if (n < 0) {
LOG(DEBUG) << __func__ << ": res_nsearch failed (" << n << ")";
- // Pass herrno to catch more detailed errors rather than EAI_NODATA.
- return herrnoToAiErrno(herrno);
+ // Return h_errno (he) to catch more detailed errors rather than EAI_NODATA.
+ // Note that res_nsearch() doesn't set the pair NETDB_INTERNAL and errno.
+ // See also herrnoToAiErrno().
+ return herrnoToAiErrno(he);
}
- hostent* hp =
- getanswer(buf.get(), n, name, type, res, info->hp, info->buf, info->buflen, &herrno);
- if (hp == NULL) {
- return herrnoToAiErrno(herrno);
- }
+ hostent* hp = getanswer(buf.get(), n, name, type, res, info->hp, info->buf, info->buflen, &he);
+ if (hp == NULL) return herrnoToAiErrno(he);
+
return 0;
}
@@ -819,13 +816,19 @@
if (advance > 0 && qp + advance < ep)
qp += advance;
else {
- // TODO: Consider to remap error code without relying on errno.
- return EAI_SYSTEM;
+ // TODO: Consider converting to a private extended EAI_* error code.
+ // Currently, the EAI_* value has no corresponding error code for an internal
+ // out of buffer space. In order to not rely on errno, convert the original
+ // error code EAI_SYSTEM to EAI_MEMORY.
+ return EAI_MEMORY;
}
}
if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
- // TODO: Consider to remap error code without relying on errno.
- return EAI_SYSTEM;
+ // TODO: Consider converting to a private extended EAI_* error code.
+ // Currently, the EAI_* value has no corresponding error code for an internal
+ // out of buffer space. In order to not rely on errno, convert the original
+ // error code EAI_SYSTEM to EAI_MEMORY.
+ return EAI_MEMORY;
}
break;
default:
@@ -838,17 +841,17 @@
if (!res) return EAI_MEMORY;
res_setnetcontext(res, netcontext);
- int herrno = NETDB_INTERNAL;
- n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf), &herrno);
+ int he;
+ n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf), &he);
if (n < 0) {
LOG(DEBUG) << __func__ << ": res_nquery failed (" << n << ")";
- return herrnoToAiErrno(herrno);
+ // Note that res_nquery() doesn't set the pair NETDB_INTERNAL and errno.
+ // Return h_errno (he) to catch more detailed errors rather than EAI_NODATA.
+ // See also herrnoToAiErrno().
+ return herrnoToAiErrno(he);
}
- hostent* hp =
- getanswer(buf.get(), n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, &herrno);
- if (hp == NULL) {
- return herrnoToAiErrno(herrno);
- }
+ hostent* hp = getanswer(buf.get(), n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, &he);
+ if (hp == NULL) return herrnoToAiErrno(he);
char* bf = (char*) (hp->h_addr_list + 2);
size_t blen = (size_t)(bf - info->buf);
@@ -873,7 +876,6 @@
return 0;
nospc:
- errno = ENOSPC;
return EAI_MEMORY;
}
@@ -910,8 +912,8 @@
return error;
}
-int herrnoToAiErrno(int herrno) {
- switch (herrno) {
+int herrnoToAiErrno(int he) {
+ switch (he) {
// extended h_errno
case NETD_RESOLV_H_ERRNO_EXT_TIMEOUT:
return NETD_RESOLV_TIMEOUT;
@@ -924,9 +926,17 @@
case TRY_AGAIN:
return EAI_AGAIN;
case NETDB_INTERNAL:
+ // TODO: Remove ENOSPC and call abort() immediately whenever any allocation fails.
+ if (errno == ENOSPC) return EAI_MEMORY;
+ // Theoretically, this should not happen. Leave this here just in case.
+ // Currently, getanswer() of {gethnamaddr, getaddrinfo}.cpp, res_nsearch() and
+ // res_searchN() use this function to convert error code. Only getanswer()
+ // of gethnamaddr.cpp may return the error code pair, herrno NETDB_INTERNAL and
+ // errno ENOSPC, which has already converted to EAI_MEMORY. The remaining functions
+ // don't set the pair herrno and errno.
return EAI_SYSTEM; // see errno for detail
case NO_RECOVERY:
default:
- return EAI_FAIL;
+ return EAI_FAIL; // TODO: Perhaps convert default to EAI_MAX (unknown error) instead
}
-}
+}
\ No newline at end of file
diff --git a/resolv/sethostent.cpp b/resolv/sethostent.cpp
index 49cc236..2885fbc 100644
--- a/resolv/sethostent.cpp
+++ b/resolv/sethostent.cpp
@@ -61,6 +61,8 @@
}
}
+// TODO: Consider returning a boolean result as files_getaddrinfo() does because the error code
+// does not currently return to netd.
int _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
struct hostent *hp, hent;
char *buf, *ptr;
@@ -71,9 +73,11 @@
FILE* hf = NULL;
sethostent_r(&hf);
if (hf == NULL) {
- errno = EINVAL;
- // TODO: Consider to remap error code without relying on errno.
- return EAI_SYSTEM;
+ // TODO: Consider converting to a private extended EAI_* error code.
+ // Currently, the EAI_* value has no corresponding error code for invalid argument socket
+ // length. In order to not rely on errno, convert the original error code pair, EAI_SYSTEM
+ // and EINVAL, to EAI_FAIL.
+ return EAI_FAIL;
}
if ((ptr = buf = (char*) malloc(len = info->buflen)) == NULL) {
@@ -89,10 +93,10 @@
info->hp->h_addrtype = af;
info->hp->h_length = 0;
- int herrno;
- hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, &herrno);
+ int he;
+ hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, &he);
if (hp == NULL) {
- if (herrno == NETDB_INTERNAL && errno == ENOSPC) {
+ if (he == NETDB_INTERNAL && errno == ENOSPC) {
goto nospc; // glibc compatibility.
}
break;
@@ -165,10 +169,11 @@
return 0;
nospc:
free(buf);
- errno = ENOSPC;
return EAI_MEMORY;
}
+// TODO: Consider returning a boolean result as files_getaddrinfo() does because the error code
+// does not currently return to netd.
int _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info) {
info->hp->h_length = len;
info->hp->h_addrtype = af;
@@ -176,12 +181,15 @@
FILE* hf = NULL;
sethostent_r(&hf);
if (hf == NULL) {
- // TODO: Consider to remap error code without relying on errno.
- return EAI_SYSTEM;
+ // TODO: Consider converting to a private extended EAI_* error code.
+ // Currently, the EAI_* value has no corresponding error code for invalid argument socket
+ // length. In order to not rely on errno, convert the original error code pair, EAI_SYSTEM
+ // and EINVAL, to EAI_FAIL.
+ return EAI_FAIL;
}
struct hostent* hp;
- int herrno;
- while ((hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, &herrno)) != NULL)
+ int he;
+ while ((hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, &he)) != NULL)
if (!memcmp(hp->h_addr_list[0], uaddr, (size_t) hp->h_length)) break;
endhostent_r(&hf);