summaryrefslogtreecommitdiff
path: root/backport-resolv-fix-non-existing-second-DNS-response-error.patch
diff options
context:
space:
mode:
Diffstat (limited to 'backport-resolv-fix-non-existing-second-DNS-response-error.patch')
-rw-r--r--backport-resolv-fix-non-existing-second-DNS-response-error.patch197
1 files changed, 197 insertions, 0 deletions
diff --git a/backport-resolv-fix-non-existing-second-DNS-response-error.patch b/backport-resolv-fix-non-existing-second-DNS-response-error.patch
new file mode 100644
index 0000000..9e914c3
--- /dev/null
+++ b/backport-resolv-fix-non-existing-second-DNS-response-error.patch
@@ -0,0 +1,197 @@
+From 09ce1e84db1b175195584dd20aa7241f3e95061f Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 14 Jun 2024 08:20:48 +0200
+Subject: [PATCH 2/4] resolv: Do not wait for non-existing second DNS response after error (bug 30081)
+Message-ID: <09ce1e84db1b175195584dd20aa7241f3e95061f.1718345824.git.fweimer@redhat.com> (raw)
+In-Reply-To: <cover.1718345824.git.fweimer@redhat.com>
+
+In single-request mode, there is no second response after an error
+because the second query has not been sent yet. Waiting for it
+introduces an unnecessary timeout.
+
+Conflict:The tst-resolv-short-response test case does not exist. Therefore, the modification of this test case is not incorporated.
+Reference:https://inbox.sourceware.org/libc-alpha/09ce1e84db1b175195584dd20aa7241f3e95061f.1718345824.git.fweimer@redhat.com/
+
+---
+ resolv/Makefile | 3 +
+ resolv/res_send.c | 2 +-
+ resolv/tst-resolv-semi-failure.c | 133 +++++++++++++++++++++++++++++++
+ 3 files changed, 137 insertions(+), 1 deletion(-)
+ create mode 100644 resolv/tst-resolv-semi-failure.c
+
+diff --git a/resolv/Makefile b/resolv/Makefile
+index 59e59953..9e12d364 100644
+--- a/resolv/Makefile
++++ b/resolv/Makefile
+@@ -96,6 +96,7 @@ tests += \
+ tst-resolv-nondecimal \
+ tst-resolv-res_init-multi \
+ tst-resolv-search \
++ tst-resolv-semi-failure \
+ tst-resolv-trailing \
+
+ # This test calls __res_context_send directly, which is not exported
+@@ -260,6 +261,8 @@ $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
++$(objpfx)tst-resolv-semi-failure: $(objpfx)libresolv.so \
++ $(shared-thread-library)
+ $(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-threads: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-txnid-collision: $(objpfx)libresolv.a \
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index 9f86f5fe..54226a2e 100644
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -1222,7 +1222,7 @@ send_dg(res_state statp,
+ *resplen2 = 0;
+ return resplen;
+ }
+- if (buf2 != NULL)
++ if (buf2 != NULL && !single_request)
+ {
+ /* No data from the first reply. */
+ resplen = 0;
+diff --git a/resolv/tst-resolv-semi-failure.c b/resolv/tst-resolv-semi-failure.c
+new file mode 100644
+index 00000000..aa9798b5
+--- /dev/null
++++ b/resolv/tst-resolv-semi-failure.c
+@@ -0,0 +1,133 @@
++/* Test parallel failure/success responses (bug 30081).
++ Copyright (C) 2024 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <resolv.h>
++#include <support/check.h>
++#include <support/resolv_test.h>
++#include <support/check_nss.h>
++
++/* The rcode in the initial response. */
++static volatile int rcode;
++
++/* Whether to fail the initial A query (!fail_aaaa) or the initial
++ AAAA query (fail_aaaa). */
++static volatile bool fail_aaaa;
++
++static void
++response (const struct resolv_response_context *ctx,
++ struct resolv_response_builder *b,
++ const char *qname, uint16_t qclass, uint16_t qtype)
++{
++ /* Handle the failing query. */
++ if ((fail_aaaa && qtype == T_AAAA) && ctx->server_index == 0)
++ {
++ struct resolv_response_flags flags = {.rcode = rcode};
++ resolv_response_init (b, flags);
++ return;
++ }
++
++ /* Otherwise produce a response. */
++ resolv_response_init (b, (struct resolv_response_flags) {});
++ resolv_response_add_question (b, qname, qclass, qtype);
++ resolv_response_section (b, ns_s_an);
++ resolv_response_open_record (b, qname, qclass, qtype, 0);
++ switch (qtype)
++ {
++ case T_A:
++ {
++ char ipv4[4] = {192, 0, 2, 17};
++ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
++ }
++ break;
++ case T_AAAA:
++ {
++ char ipv6[16]
++ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
++ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
++ }
++ break;
++ default:
++ FAIL_EXIT1 ("unexpected TYPE%d query", qtype);
++ }
++ resolv_response_close_record (b);
++}
++
++static void
++check_one (void)
++{
++
++ /* The buggy 1-second query timeout results in 30 seconds of delay,
++ which triggers are test timeout failure. */
++ for (int i = 0; i < 30; ++i)
++ {
++ static const struct addrinfo hints =
++ {
++ .ai_family = AF_UNSPEC,
++ .ai_socktype = SOCK_STREAM,
++ };
++ struct addrinfo *ai;
++ int ret = getaddrinfo ("www.example", "80", &hints, &ai);
++ const char *expected;
++ if (ret == 0 && ai->ai_next != NULL)
++ expected = ("address: STREAM/TCP 192.0.2.17 80\n"
++ "address: STREAM/TCP 2001:db8::1 80\n");
++ else
++ /* Only one response because the AAAA lookup failure is
++ treated as an ignoreable error. */
++ expected = "address: STREAM/TCP 192.0.2.17 80\n";
++ check_addrinfo ("www.example", ai, ret, expected);
++ if (ret == 0)
++ freeaddrinfo (ai);
++ }
++}
++
++static int
++do_test (void)
++{
++ for (int do_single_lookup = 0; do_single_lookup < 2; ++do_single_lookup)
++ {
++ struct resolv_test *aux = resolv_test_start
++ ((struct resolv_redirect_config)
++ {
++ .response_callback = response,
++ });
++
++ if (do_single_lookup)
++ _res.options |= RES_SNGLKUP;
++
++ for (int do_fail_aaaa = 0; do_fail_aaaa < 2; ++do_fail_aaaa)
++ {
++ fail_aaaa = do_fail_aaaa;
++
++ rcode = 2; /* SERVFAIL. */
++ check_one ();
++
++ rcode = 4; /* NOTIMP. */
++ check_one ();
++
++ rcode = 5; /* REFUSED. */
++ check_one ();
++ }
++
++ resolv_test_end (aux);
++ }
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.33.0
+