From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id C3E9E388265E for ; Fri, 14 Jun 2024 06:21:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C3E9E388265E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C3E9E388265E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1718346081; cv=none; b=fMCLB8sNDKGwjdwzZdOixAq8CIfKYr4gne3FYZCQbZrmg4sh/e7syBJ7lRxzFsJtBBtr391oFHrxSriPE8AWDzgMRrkkwyVE4RvRlZWCe4lxiT4jikiikEITMOr+3JsE9m2Xk1zVPyvU/445XxTKZ5HSELSLzNXkbDGcL/pM1to= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1718346081; c=relaxed/simple; bh=sCzIbj2xASu+597422BC2ekst88vfY2CObsPrzLpzc8=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=KoDTIvZVyx36xQCYj/laLl4xzZQ/rguI+1uKSaHniUdvZkJ3/Z2IgQPkyoRF+AdSEx8qkoqCfJ/G7IsPf3y32d6j6XIwbByg/8LXiHwltGUdJfzIVgWCs6S5MuhLERVvrsAor8/QTK6oshitTqcDKaFFoLV3SbP++e/yKf8i3yo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1718346077; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=/ungLbTWRQ6gXuyEP1H//dwVqx+bMqhNseouIlPVlLE=; b=OOOb8mWk4c8Us5KBGP19bRkzLc4JQ2cOK20fMMHGtBC8T8xtdyGQFs/pmsZmKg1lnTm5KG 30AfXP5YbzZrPcPNpso1xL9HDdoj2txm+4XBFB20nu21aSRm4B+jfZXR4l/Xu6SvW/hA7Q Smee38HPm3/gP5AXozceVAJ9OltUx1k= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-623-oRQS1INuNo2DXcnj-gn1GQ-1; Fri, 14 Jun 2024 02:21:15 -0400 X-MC-Unique: oRQS1INuNo2DXcnj-gn1GQ-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 103C41956088 for ; Fri, 14 Jun 2024 06:21:15 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.96]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 254391955F2D for ; Fri, 14 Jun 2024 06:21:13 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 4/4] resolv: Implement strict-error stub resolver option (bug 27929) In-Reply-To: Message-ID: References: X-From-Line: acc0609d6242a34436f4bea2fa499b3428d9f635 Mon Sep 17 00:00:00 2001 Date: Fri, 14 Jun 2024 08:21:11 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: For now, do not enable this mode by default due to the potential impact on compatibility with existing deployments. --- NEWS | 10 +++++ resolv/res_init.c | 1 + resolv/res_send.c | 45 ++++++++++++++++------- resolv/resolv.h | 1 + resolv/tst-resolv-res_init-skeleton.c | 10 +++++ resolv/tst-resolv-semi-failure.c | 53 ++++++++++++++++----------- 6 files changed, 84 insertions(+), 36 deletions(-) diff --git a/NEWS b/NEWS index 495bbd5cbc..2149da63c4 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,16 @@ Major new features: the RES_OPTIONS=-no-aaaa environment variable performs AAAA DNS queries when the glibc DNS stub resolver is used. +* The DNS stub resolver now supports the strict-error option. If + activated, getaddrinfo for the AF_UNSPEC address family (with dual + A/AAAA DNS lookups) attemps to obtain a A/AAAA response pair from + another DNS server if one of the responses indicates failure. Without + the strict-error option, getaddrinfo returns the A record data it has + obtained even if the AAAA query failed. The new strict error mode is + incompatible with some DNS environments which do not follow the RFCs, + which is why this mode is not enabled by default. A future version + of the library may turn it on by default, however. + Deprecated and removed features, and other changes affecting compatibility: * Architectures which use a 32-bit seconds-since-epoch field in struct diff --git a/resolv/res_init.c b/resolv/res_init.c index 243532b3ad..b838dc7064 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -695,6 +695,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options) { STRnLEN ("use-vc"), RES_USEVC }, { STRnLEN ("trust-ad"), RES_TRUSTAD }, { STRnLEN ("no-aaaa"), RES_NOAAAA }, + { STRnLEN ("strict-error"), RES_STRICTERR }, }; #define noptions (sizeof (options) / sizeof (options[0])) bool negate_option = *cp == '-'; diff --git a/resolv/res_send.c b/resolv/res_send.c index 9c77613f37..9a284ed44a 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -1234,21 +1234,38 @@ send_dg(res_state statp, if (thisansp_error) { next_ns: - if (recvresp1 || (buf2 != NULL && recvresp2)) { - *resplen2 = 0; - return resplen; - } - if (buf2 != NULL && !single_request) + /* Outside of strict-error mode, use the first + response even if the second response is an + error. This allows parallel resolution to + succeed even if the recursive resolver + always answers with SERVFAIL for AAAA + queries (which still happens in practice + unfortunately). + + In strict-error mode, always switch to the + next server and try to get a response from + there. */ + if ((statp->options & RES_STRICTERR) == 0) { - /* No data from the first reply. */ - resplen = 0; - /* We are waiting for a possible second reply. */ - if (matching_query == 1) - recvresp1 = 1; - else - recvresp2 = 1; - - goto wait; + if (recvresp1 || (buf2 != NULL && recvresp2)) + { + *resplen2 = 0; + return resplen; + } + + if (buf2 != NULL && !single_request) + { + /* No data from the first reply. */ + resplen = 0; + /* We are waiting for a possible + second reply. */ + if (matching_query == 1) + recvresp1 = 1; + else + recvresp2 = 1; + + goto wait; + } } /* don't retry if called from dig */ diff --git a/resolv/resolv.h b/resolv/resolv.h index f40d6c58ce..b8a0f66a5f 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -133,6 +133,7 @@ struct res_sym { #define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */ #define RES_TRUSTAD 0x04000000 /* Request AD bit, keep it in responses. */ #define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */ +#define RES_STRICTERR 0x10000000 /* Report more DNS errors as errors. */ #define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c index d3a19eb305..e41bcebd9d 100644 --- a/resolv/tst-resolv-res_init-skeleton.c +++ b/resolv/tst-resolv-res_init-skeleton.c @@ -129,6 +129,7 @@ print_resp (FILE *fp, res_state resp) print_option_flag (fp, &options, RES_NORELOAD, "no-reload"); print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad"); print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa"); + print_option_flag (fp, &options, RES_STRICTERR, "strict-error"); fputc ('\n', fp); if (options != 0) fprintf (fp, "; error: unresolved option bits: 0x%x\n", options); @@ -741,6 +742,15 @@ struct test_case test_cases[] = "nameserver 192.0.2.1\n" "; nameserver[0]: [192.0.2.1]:53\n" }, + {.name = "strict-error flag", + .conf = "options strict-error\n" + "nameserver 192.0.2.1\n", + .expected = "options strict-error\n" + "search example.com\n" + "; search[0]: example.com\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, { NULL } }; diff --git a/resolv/tst-resolv-semi-failure.c b/resolv/tst-resolv-semi-failure.c index aa9798b5a7..b7681210f4 100644 --- a/resolv/tst-resolv-semi-failure.c +++ b/resolv/tst-resolv-semi-failure.c @@ -67,6 +67,9 @@ response (const struct resolv_response_context *ctx, resolv_response_close_record (b); } +/* Set to 1 if strict error checking is enabled. */ +static int do_strict_error; + static void check_one (void) { @@ -83,7 +86,10 @@ check_one (void) struct addrinfo *ai; int ret = getaddrinfo ("www.example", "80", &hints, &ai); const char *expected; - if (ret == 0 && ai->ai_next != NULL) + /* In strict-error mode, a switch to the second name server + happens, and both responses are received, so a single + response is a bug. */ + if (do_strict_error || (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 @@ -99,33 +105,36 @@ check_one (void) 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, - }); + for (do_strict_error = 0; do_strict_error < 2; ++do_strict_error) + 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; + if (do_strict_error) + _res.options |= RES_STRICTERR; + 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; + for (int do_fail_aaaa = 0; do_fail_aaaa < 2; ++do_fail_aaaa) + { + fail_aaaa = do_fail_aaaa; - rcode = 2; /* SERVFAIL. */ - check_one (); + rcode = 2; /* SERVFAIL. */ + check_one (); - rcode = 4; /* NOTIMP. */ - check_one (); + rcode = 4; /* NOTIMP. */ + check_one (); - rcode = 5; /* REFUSED. */ - check_one (); - } + rcode = 5; /* REFUSED. */ + check_one (); + } - resolv_test_end (aux); - } + resolv_test_end (aux); + } return 0; } -- 2.45.2