diff options
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.patch | 197 |
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 + |