Expose DNS timeout error to netd
For resolver stats, RCODE_TIMEOUT has been used for catching DNS timeout
error. This change adds the Support for reporting NETD_RESOLV_TIMEOUT to
frameworks.
Also clean up res_data.cpp as these functions are not used.
- res_init
- res_mkquery
- res_query
- res_send
- res_search
Bug: 113916551
Test: as follows
- built and flash netd
- system/netd/tests/runtests.sh passed
- silently drop packets by iptables, the return error is correct
Change-Id: I62ba6759b519d42aef62ae5b756a3c1ae3cb00d8
diff --git a/resolv/getaddrinfo.cpp b/resolv/getaddrinfo.cpp
index c229588..fc311ba 100644
--- a/resolv/getaddrinfo.cpp
+++ b/resolv/getaddrinfo.cpp
@@ -187,9 +187,10 @@
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*, struct res_target*, res_state);
-static int res_searchN(const char*, struct res_target*, res_state);
-static int res_querydomainN(const char*, const char*, struct res_target*, res_state);
+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);
+static int res_querydomainN(const char* name, const char* domain, res_target* target, res_state res,
+ int* ai_error);
static const char* const ai_errlist[] = {
"Success",
@@ -1517,10 +1518,13 @@
* and have a cache hit that would be wasted, so we do the rest there on miss
*/
res_setnetcontext(res, netcontext);
- if (res_searchN(name, &q, res) < 0) {
+
+ // 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) {
free(buf);
free(buf2);
- return EAI_NODATA; // TODO: Decode error from h_errno like we do below
+ return ai_error; // TODO: Decode error from h_errno like we do below
}
ai = getanswer(buf, q.n, q.name, q.qtype, pai);
if (ai) {
@@ -1534,14 +1538,7 @@
free(buf);
free(buf2);
if (sentinel.ai_next == NULL) {
- switch (h_errno) {
- case HOST_NOT_FOUND:
- return EAI_NODATA;
- case TRY_AGAIN:
- return EAI_AGAIN;
- default:
- return EAI_FAIL;
- }
+ return herrnoToAiError(h_errno);
}
_rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
@@ -1646,8 +1643,7 @@
*
* Caller must parse answer and determine whether it answers the question.
*/
-static int res_queryN(const char* name, /* domain name */ struct res_target* target,
- res_state res) {
+static int res_queryN(const char* name, res_target* target, res_state res, int* ai_error) {
u_char buf[MAXPACKET];
HEADER* hp;
int n;
@@ -1692,7 +1688,9 @@
h_errno = NO_RECOVERY;
return n;
}
- n = res_nsend(res, buf, n, answer, anslen);
+
+ n = res_nsend(res, buf, n, answer, anslen, &rcode);
+ *ai_error = rcodeToAiError(rcode);
if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
rcode = hp->rcode; /* record most recent error */
@@ -1746,7 +1744,7 @@
* If enabled, implement search rules until answer or unrecoverable failure
* is detected. Error code, if any, is left in h_errno.
*/
-static int res_searchN(const char* name, struct res_target* target, res_state res) {
+static int res_searchN(const char* name, res_target* target, res_state res, int* ai_error) {
const char *cp, *const *domain;
HEADER* hp;
u_int dots;
@@ -1771,7 +1769,7 @@
*/
saved_herrno = -1;
if (dots >= res->ndots) {
- ret = res_querydomainN(name, NULL, target, res);
+ ret = res_querydomainN(name, NULL, target, res, ai_error);
if (ret > 0) return (ret);
saved_herrno = h_errno;
tried_as_is++;
@@ -1794,7 +1792,7 @@
_resolv_populate_res_for_net(res);
for (domain = (const char* const*) res->dnsrch; *domain && !done; domain++) {
- ret = res_querydomainN(name, *domain, target, res);
+ ret = res_querydomainN(name, *domain, target, res, ai_error);
if (ret > 0) return ret;
/*
@@ -1847,7 +1845,7 @@
* name or whether it ends with a dot.
*/
if (!tried_as_is) {
- ret = res_querydomainN(name, NULL, target, res);
+ ret = res_querydomainN(name, NULL, target, res, ai_error);
if (ret > 0) return ret;
}
@@ -1872,8 +1870,8 @@
* Perform a call on res_query on the concatenation of name and domain,
* removing a trailing dot from name if domain is NULL.
*/
-static int res_querydomainN(const char* name, const char* domain, struct res_target* target,
- res_state res) {
+static int res_querydomainN(const char* name, const char* domain, res_target* target, res_state res,
+ int* ai_error) {
char nbuf[MAXDNAME];
const char* longname = nbuf;
size_t n, d;
@@ -1909,5 +1907,5 @@
}
snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
}
- return res_queryN(longname, target, res);
+ return res_queryN(longname, target, res, ai_error);
}