about summary refs log tree commit diff
path: root/resolv/res_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/res_query.c')
-rw-r--r--resolv/res_query.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 85bad97d2d..4371af5b05 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -120,10 +120,13 @@ __libc_res_nquery(res_state statp,
 	u_char *buf;
 	HEADER *hp = (HEADER *) answer;
 	int n, use_malloc = 0;
+        u_int oflags = statp->_flags;
 
-	hp->rcode = NOERROR;	/* default */
+	size_t bufsize = QUERYSIZE;
+	buf = alloca (bufsize);
 
-	buf = alloca (QUERYSIZE);
+ again:
+	hp->rcode = NOERROR;	/* default */
 
 #ifdef DEBUG
 	if (statp->options & RES_DEBUG)
@@ -131,18 +134,30 @@ __libc_res_nquery(res_state statp,
 #endif
 
 	n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
-			 buf, QUERYSIZE);
-	if (__builtin_expect (n <= 0, 0)) {
+			 buf, bufsize);
+	if (n > 0
+	    && (oflags & RES_F_EDNS0ERR) == 0
+	    && (statp->options & RES_USE_EDNS0) != 0)
+		n = __res_nopt(statp, n, buf, bufsize, anslen);
+	if (__builtin_expect (n <= 0, 0) && !use_malloc) {
 		/* Retry just in case res_nmkquery failed because of too
 		   short buffer.  Shouldn't happen.  */
-		buf = malloc (MAXPACKET);
+		bufsize = MAXPACKET;
+		buf = malloc (bufsize);
 		if (buf != NULL) {
 			use_malloc = 1;
-			n = res_nmkquery(statp, QUERY, name, class, type, NULL,
-					 0, NULL, buf, MAXPACKET);
+			goto again;
 		}
 	}
 	if (__builtin_expect (n <= 0, 0)) {
+		/* If the query choked with EDNS0, retry without EDNS0.  */
+		if ((statp->options & RES_USE_EDNS0) != 0
+		    && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
+			statp->_flags |= RES_F_EDNS0ERR;
+			if (statp->options & RES_DEBUG)
+				printf(";; res_nquery: retry without EDNS0\n");
+                        goto again;
+		}
 #ifdef DEBUG
 		if (statp->options & RES_DEBUG)
 			printf(";; res_query: mkquery failed\n");