diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-04-13 13:22:51 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-04-13 13:22:51 +0200 |
commit | 44500cbb25bc6e76723304b9ff39f875c04309f9 (patch) | |
tree | 924aa24c754a523da4c0f381f9f269ddc5c327c9 /resolv/tst-resolv-edns.c | |
parent | e14a27723cc3a154d67f3f26e719d08c0ba9ad25 (diff) | |
download | glibc-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.c | 88 |
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; |