Fix potential bugs that may cause resolver to retry endlessly
[1] If DNS-over-TLS validation success, but server does not
respond to DNS-over-TLS query after a while (the server can still
respond to DNS-over-UDP). Then, query a non-exist domain.
[2] If DNS-over-TLS validation success, but server does not
respond to DNS-over-TLS query after a while. Also, the server always
responds RCODE=RES_F_EDNS0ERR on DNS-over-UDP.
These strange network behaviors should not happen. However, once they
happen (maybe by bogus servers), the resolver should be able to handle
it gracefully.
Bug: 120910570
Test: runtests.sh pass
Change-Id: I7e3044e012303a7991b04e7d38e55340e2a5db1a
diff --git a/resolv/res_query.cpp b/resolv/res_query.cpp
index 4ae13bf..acf6160 100644
--- a/resolv/res_query.cpp
+++ b/resolv/res_query.cpp
@@ -117,10 +117,8 @@
u_char buf[MAXPACKET];
HEADER* hp = (HEADER*) (void*) answer;
int n;
- u_int oflags;
int rcode = NOERROR;
-
- oflags = statp->_flags;
+ bool retried = false;
again:
hp->rcode = NOERROR; /* default */
@@ -130,8 +128,7 @@
#endif
n = res_nmkquery(statp, QUERY, name, cl, type, NULL, 0, NULL, buf, sizeof(buf));
- if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
- (statp->options & (RES_USE_EDNS0 | RES_USE_DNSSEC)) != 0U)
+ if (n > 0 && (statp->options & (RES_USE_EDNS0 | RES_USE_DNSSEC)) != 0U && !retried)
n = res_nopt(statp, n, buf, sizeof(buf), anslen);
if (n <= 0) {
#ifdef DEBUG
@@ -144,9 +141,9 @@
if (n < 0) {
/* if the query choked with EDNS0, retry without EDNS0 */
if ((statp->options & (RES_USE_EDNS0 | RES_USE_DNSSEC)) != 0U &&
- ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
- statp->_flags |= RES_F_EDNS0ERR;
+ (statp->_flags & RES_F_EDNS0ERR) && !retried) {
if (statp->options & RES_DEBUG) printf(";; res_nquery: retry without EDNS0\n");
+ retried = true;
goto again;
}
#ifdef DEBUG