about summary refs log tree commit diff
path: root/resolv/tst-resolv-edns.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-04-13 13:22:51 +0200
committerFlorian Weimer <fweimer@redhat.com>2017-04-13 13:22:51 +0200
commit44500cbb25bc6e76723304b9ff39f875c04309f9 (patch)
tree924aa24c754a523da4c0f381f9f269ddc5c327c9 /resolv/tst-resolv-edns.c
parente14a27723cc3a154d67f3f26e719d08c0ba9ad25 (diff)
downloadglibc-44500cbb25bc6e76723304b9ff39f875c04309f9.tar.gz
glibc-44500cbb25bc6e76723304b9ff39f875c04309f9.tar.xz
glibc-44500cbb25bc6e76723304b9ff39f875c04309f9.zip
resolv: Remove EDNS fallback [BZ #21369]
EDNS is disabled by default (so there is interoperability issue), and
the fallback code is problematic because it prevents an application
from obtaining DNSSEC data after a FORMERR response.
Diffstat (limited to 'resolv/tst-resolv-edns.c')
-rw-r--r--resolv/tst-resolv-edns.c88
1 files changed, 59 insertions, 29 deletions
diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c
index f17dbc3450..093a4f5f22 100644
--- a/resolv/tst-resolv-edns.c
+++ b/resolv/tst-resolv-edns.c
@@ -115,8 +115,23 @@ response (const struct resolv_response_context *ctx,
 {
   TEST_VERIFY_EXIT (qname != NULL);
 
-  /* The "tcp." prefix can be used to request TCP fallback.  */
   const char *qname_compare = qname;
+
+  /* The "formerr." prefix can be used to request a FORMERR response on the
+     first server.  */
+  bool send_formerr;
+  if (strncmp ("formerr.", qname, strlen ("formerr.")) == 0)
+    {
+      send_formerr = true;
+      qname_compare = qname + strlen ("formerr.");
+    }
+  else
+    {
+      send_formerr = false;
+      qname_compare = qname;
+    }
+
+  /* The "tcp." prefix can be used to request TCP fallback.  */
   bool force_tcp;
   if (strncmp ("tcp.", qname_compare, strlen ("tcp.")) == 0)
     {
@@ -132,14 +147,20 @@ response (const struct resolv_response_context *ctx,
   else
     {
       support_record_failure ();
-      printf ("error: unexpected QNAME: %s\n", qname);
+      printf ("error: unexpected QNAME: %s (reduced: %s)\n",
+              qname, qname_compare);
       return;
     }
   TEST_VERIFY_EXIT (qclass == C_IN);
-  struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp};
+  struct resolv_response_flags flags = { };
+  flags.tc = force_tcp && !ctx->tcp;
+  if (!flags.tc && send_formerr && ctx->server_index == 0)
+    /* Send a FORMERR for the first full response from the first
+       server.  */
+    flags.rcode = 1;          /* FORMERR */
   resolv_response_init (b, flags);
   resolv_response_add_question (b, qname, qclass, qtype);
-  if (flags.tc)
+  if (flags.tc || flags.rcode != 0)
     return;
 
   if (test_verbose)
@@ -466,33 +487,42 @@ do_test (void)
   for (int do_edns = 0; do_edns < 2; ++do_edns)
     for (int do_dnssec = 0; do_dnssec < 2; ++do_dnssec)
       for (int do_tcp = 0; do_tcp < 2; ++do_tcp)
-        {
-          struct resolv_test *aux = resolv_test_start
-            ((struct resolv_redirect_config)
-             {
-               .response_callback = response,
-                 });
-
-          use_edns = do_edns;
-          if (do_edns)
-            _res.options |= RES_USE_EDNS0;
-          use_dnssec = do_dnssec;
-          if (do_dnssec)
-            _res.options |= RES_USE_DNSSEC;
-
-          char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE);
-          if (do_tcp)
-            {
-              char *n = xasprintf ("tcp.%s", probe_name);
-              free (probe_name);
-              probe_name = n;
-            }
+        for (int do_formerr = 0; do_formerr < 2; ++do_formerr)
+          {
+            struct resolv_test *aux = resolv_test_start
+              ((struct resolv_redirect_config)
+               {
+                 .response_callback = response,
+               });
+
+            use_edns = do_edns;
+            if (do_edns)
+              _res.options |= RES_USE_EDNS0;
+            use_dnssec = do_dnssec;
+            if (do_dnssec)
+              _res.options |= RES_USE_DNSSEC;
+
+            char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE);
+            if (do_tcp)
+              {
+                char *n = xasprintf ("tcp.%s", probe_name);
+                free (probe_name);
+                probe_name = n;
+              }
+            if (do_formerr)
+              {
+                /* Send a garbage query in an attempt to trigger EDNS
+                   fallback.  */
+                char *n = xasprintf ("formerr.%s", probe_name);
+                gethostbyname (n);
+                free (n);
+              }
 
-          run_test (probe_name);
+            run_test (probe_name);
 
-          free (probe_name);
-          resolv_test_end (aux);
-        }
+            free (probe_name);
+            resolv_test_end (aux);
+          }
 
   free_response_data ();
   return 0;