Lay the groundwork for enabling EDNS0 in queries.
This change does not enable EDNS0, so it should not
result in any behavior change. However, enabling EDNS0
should now be possible with only a small additional change
to "flip the switch".
This change has also landed in NetBSD upstream
(http://gnats.netbsd.org/52578) so this change reduces
divergence from upstream.
Most of the code in this change is for caching of queries that contain
an additional section.
Bug: 15132200
Bug: 64133961
Test: Added integration tests for fallback to the netd suite.
Merged-In: I9b0abc6e4f3ff7f9c23a5cb921d392d2d3065d99
Merged-In: I9c06bbaf1883de4bdebd822f9a052901bf3efc04
Merged-In: Ie438b77bc1aeea0b0c700a90998cec31ac9a0015
Change-Id: Ic64bed0754e1d529dc0c0ab6a5e2f1ea201ff0d5
(cherry picked from commit 6eed8e1bb6f7faac2accb85fe1ebafb4fd33dee7)
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index db683bb..47b3308 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -2171,8 +2171,12 @@
int class, type;
u_char *answer;
int anslen;
+ u_int oflags;
hp = (HEADER *)(void *)t->answer;
+ oflags = res->_flags;
+
+again:
hp->rcode = NOERROR; /* default */
/* make it easier... */
@@ -2188,7 +2192,8 @@
n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
buf, sizeof(buf));
#ifdef RES_USE_EDNS0
- if (n > 0 && (res->options & RES_USE_EDNS0) != 0)
+ if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 &&
+ (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
n = res_nopt(res, n, buf, sizeof(buf), anslen);
#endif
if (n <= 0) {
@@ -2213,6 +2218,18 @@
if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
rcode = hp->rcode; /* record most recent error */
+#ifdef RES_USE_EDNS0
+ /* if the query choked with EDNS0, retry without EDNS0 */
+ if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 &&
+ ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) {
+ res->_flags |= RES_F_EDNS0ERR;
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_nquery: retry without EDNS0\n");
+#endif
+ goto again;
+ }
+#endif
#ifdef DEBUG
if (res->options & RES_DEBUG)
printf(";; rcode = %u, ancount=%u\n", hp->rcode,