From bcf24ca07e289ead00a407136cbaed6b88e59231 Mon Sep 17 00:00:00 2001 From: Colin Vidal Date: Tue, 5 Nov 2024 13:40:55 +0100 Subject: [PATCH] Add a none parameter to query-source[-v6] This change adds a "none" parameter to the query-source[-v6] options in named.conf, which forbid the usage of IPv4 or IPv6 addresses when doing upstream queries. --- bin/named/server.c | 20 +- bin/tests/system/Makefile.am | 1 + ...ad-options-query-source-address-v4-v6.conf | 17 ++ .../bad-query-source-address-v4-none.conf | 16 ++ .../bad-query-source-address-v6-none.conf | 16 ++ ...-options-query-source-address-v4-none.conf | 16 ++ ...-options-query-source-address-v6-none.conf | 16 ++ .../good-query-source-address-v4-1.conf | 2 +- .../good-query-source-address-v6-1.conf | 2 +- .../system/query-source/ns1/named.conf.in | 37 ++++ bin/tests/system/query-source/ns1/root.db | 16 ++ .../system/query-source/ns2/named.conf.in | 37 ++++ bin/tests/system/query-source/ns2/root.hint | 14 ++ .../system/query-source/ns3/named.conf.in | 37 ++++ bin/tests/system/query-source/ns3/root.hint | 14 ++ .../system/query-source/ns4/named.conf.in | 37 ++++ bin/tests/system/query-source/ns4/root.hint | 14 ++ .../system/query-source/ns5/named.conf.in | 37 ++++ bin/tests/system/query-source/ns5/root.hint | 14 ++ bin/tests/system/query-source/setup.sh | 20 ++ .../query-source/tests_querysource_none.py | 58 ++++++ doc/arm/reference.rst | 8 +- doc/misc/options | 8 +- lib/isccfg/check.c | 49 +++-- lib/isccfg/namedconf.c | 64 +++++- tests/isccfg/Makefile.am | 3 +- tests/isccfg/grammar_test.c | 185 ++++++++++++++++++ 27 files changed, 717 insertions(+), 41 deletions(-) create mode 100644 bin/tests/system/checkconf/bad-options-query-source-address-v4-v6.conf create mode 100644 bin/tests/system/checkconf/bad-query-source-address-v4-none.conf create mode 100644 bin/tests/system/checkconf/bad-query-source-address-v6-none.conf create mode 100644 bin/tests/system/checkconf/good-options-query-source-address-v4-none.conf create mode 100644 bin/tests/system/checkconf/good-options-query-source-address-v6-none.conf create mode 100644 bin/tests/system/query-source/ns1/named.conf.in create mode 100644 bin/tests/system/query-source/ns1/root.db create mode 100644 bin/tests/system/query-source/ns2/named.conf.in create mode 100644 bin/tests/system/query-source/ns2/root.hint create mode 100644 bin/tests/system/query-source/ns3/named.conf.in create mode 100644 bin/tests/system/query-source/ns3/root.hint create mode 100644 bin/tests/system/query-source/ns4/named.conf.in create mode 100644 bin/tests/system/query-source/ns4/root.hint create mode 100644 bin/tests/system/query-source/ns5/named.conf.in create mode 100644 bin/tests/system/query-source/ns5/root.hint create mode 100644 bin/tests/system/query-source/setup.sh create mode 100644 bin/tests/system/query-source/tests_querysource_none.py create mode 100644 tests/isccfg/grammar_test.c diff --git a/bin/named/server.c b/bin/named/server.c index 08b3f62735..722e4d8de2 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1288,9 +1288,22 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, UNREACHABLE(); } - sa = *(cfg_obj_assockaddr(obj)); - INSIST(isc_sockaddr_pf(&sa) == af); - INSIST(isc_sockaddr_getport(&sa) == 0); + if (cfg_obj_isvoid(obj)) { + /* + * We don't want to use this address family, let's + * bail now. The dispatch object for this family will + * be null then not used to run queries. + */ + return ISC_R_SUCCESS; + } else { + /* + * obj _has_ to be sockaddr here, cfg_obj_assockaddr() + * asserts this internally. + */ + sa = *(cfg_obj_assockaddr(obj)); + INSIST(isc_sockaddr_pf(&sa) == af); + INSIST(isc_sockaddr_getport(&sa) == 0); + } /* * If we don't support this address family, we're done! @@ -1614,6 +1627,7 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { (void)cfg_map_get(cpeer, "query-source-v6", &obj); } if (obj != NULL) { + INSIST(cfg_obj_issockaddr(obj)); result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj)); if (result != ISC_R_SUCCESS) { goto cleanup; diff --git a/bin/tests/system/Makefile.am b/bin/tests/system/Makefile.am index 58cfdfe0a4..530ca50053 100644 --- a/bin/tests/system/Makefile.am +++ b/bin/tests/system/Makefile.am @@ -134,6 +134,7 @@ TESTS = \ proxy \ pipelined \ qmin \ + query-source \ reclimit \ redirect \ resolver \ diff --git a/bin/tests/system/checkconf/bad-options-query-source-address-v4-v6.conf b/bin/tests/system/checkconf/bad-options-query-source-address-v4-v6.conf new file mode 100644 index 0000000000..a10cf04c26 --- /dev/null +++ b/bin/tests/system/checkconf/bad-options-query-source-address-v4-v6.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source none; + query-source-v6 none; +}; diff --git a/bin/tests/system/checkconf/bad-query-source-address-v4-none.conf b/bin/tests/system/checkconf/bad-query-source-address-v4-none.conf new file mode 100644 index 0000000000..497c2f07da --- /dev/null +++ b/bin/tests/system/checkconf/bad-query-source-address-v4-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +server 1.2.3.4 { + query-source none; +}; diff --git a/bin/tests/system/checkconf/bad-query-source-address-v6-none.conf b/bin/tests/system/checkconf/bad-query-source-address-v6-none.conf new file mode 100644 index 0000000000..4ea1ba7a01 --- /dev/null +++ b/bin/tests/system/checkconf/bad-query-source-address-v6-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +server fd92:7065:b8e:ffff::1 { + query-source-v6 none; +}; diff --git a/bin/tests/system/checkconf/good-options-query-source-address-v4-none.conf b/bin/tests/system/checkconf/good-options-query-source-address-v4-none.conf new file mode 100644 index 0000000000..5e0159d85a --- /dev/null +++ b/bin/tests/system/checkconf/good-options-query-source-address-v4-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source none; +}; diff --git a/bin/tests/system/checkconf/good-options-query-source-address-v6-none.conf b/bin/tests/system/checkconf/good-options-query-source-address-v6-none.conf new file mode 100644 index 0000000000..42988810a3 --- /dev/null +++ b/bin/tests/system/checkconf/good-options-query-source-address-v6-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source-v6 none; +}; diff --git a/bin/tests/system/checkconf/good-query-source-address-v4-1.conf b/bin/tests/system/checkconf/good-query-source-address-v4-1.conf index d787448334..9f8b340cd8 100644 --- a/bin/tests/system/checkconf/good-query-source-address-v4-1.conf +++ b/bin/tests/system/checkconf/good-query-source-address-v4-1.conf @@ -12,5 +12,5 @@ */ server 1.2.3.4 { - query-source address 10.10.10.10; + query-source 10.10.10.10; }; diff --git a/bin/tests/system/checkconf/good-query-source-address-v6-1.conf b/bin/tests/system/checkconf/good-query-source-address-v6-1.conf index 9ced5a5fe0..ea3e76cee7 100644 --- a/bin/tests/system/checkconf/good-query-source-address-v6-1.conf +++ b/bin/tests/system/checkconf/good-query-source-address-v6-1.conf @@ -12,5 +12,5 @@ */ server fd92:7065:b8e:ffff::1 { - query-source-v6 address fd92:7065:b8e:ffff::2; + query-source-v6 fd92:7065:b8e:ffff::2; }; diff --git a/bin/tests/system/query-source/ns1/named.conf.in b/bin/tests/system/query-source/ns1/named.conf.in new file mode 100644 index 0000000000..58ca68366e --- /dev/null +++ b/bin/tests/system/query-source/ns1/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + listen-on { 10.53.0.1; }; + recursion no; + dnssec-validation no; + query-source 10.53.0.1; + query-source-v6 fd92:7065:b8e:ffff::1; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/query-source/ns1/root.db b/bin/tests/system/query-source/ns1/root.db new file mode 100644 index 0000000000..e635a623eb --- /dev/null +++ b/bin/tests/system/query-source/ns1/root.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 300 SOA . . 0 0 0 0 0 +. 300 NS a.root-servers.nil. +a.root-servers.nil. 300 A 10.53.0.1 +example. 300 A 10.53.0.10 +exampletwo. 300 A 10.53.0.11 \ No newline at end of file diff --git a/bin/tests/system/query-source/ns2/named.conf.in b/bin/tests/system/query-source/ns2/named.conf.in new file mode 100644 index 0000000000..de69fe3e6f --- /dev/null +++ b/bin/tests/system/query-source/ns2/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion yes; + dnssec-validation no; + query-source none; + query-source-v6 fd92:7065:b8e:ffff::2; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns2/root.hint b/bin/tests/system/query-source/ns2/root.hint new file mode 100644 index 0000000000..315a233fe8 --- /dev/null +++ b/bin/tests/system/query-source/ns2/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/query-source/ns3/named.conf.in b/bin/tests/system/query-source/ns3/named.conf.in new file mode 100644 index 0000000000..408edb3ace --- /dev/null +++ b/bin/tests/system/query-source/ns3/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + recursion yes; + dnssec-validation no; + query-source-v6 none; + query-source 10.53.0.3; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns3/root.hint b/bin/tests/system/query-source/ns3/root.hint new file mode 100644 index 0000000000..e0f186c2f8 --- /dev/null +++ b/bin/tests/system/query-source/ns3/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/query-source/ns4/named.conf.in b/bin/tests/system/query-source/ns4/named.conf.in new file mode 100644 index 0000000000..7fc4dabd50 --- /dev/null +++ b/bin/tests/system/query-source/ns4/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { fd92:7065:b8e:ffff::4; }; + recursion yes; + dnssec-validation no; + query-source none; + query-source-v6 fd92:7065:b8e:ffff::4; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns4/root.hint b/bin/tests/system/query-source/ns4/root.hint new file mode 100644 index 0000000000..49dcae0722 --- /dev/null +++ b/bin/tests/system/query-source/ns4/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/query-source/ns5/named.conf.in b/bin/tests/system/query-source/ns5/named.conf.in new file mode 100644 index 0000000000..df8975f471 --- /dev/null +++ b/bin/tests/system/query-source/ns5/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { fd92:7065:b8e:ffff::5; }; + recursion yes; + dnssec-validation no; + query-source 10.53.0.5; + query-source-v6 none; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns5/root.hint b/bin/tests/system/query-source/ns5/root.hint new file mode 100644 index 0000000000..315a233fe8 --- /dev/null +++ b/bin/tests/system/query-source/ns5/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/query-source/setup.sh b/bin/tests/system/query-source/setup.sh new file mode 100644 index 0000000000..5d12d6ac95 --- /dev/null +++ b/bin/tests/system/query-source/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf diff --git a/bin/tests/system/query-source/tests_querysource_none.py b/bin/tests/system/query-source/tests_querysource_none.py new file mode 100644 index 0000000000..0f19d05115 --- /dev/null +++ b/bin/tests/system/query-source/tests_querysource_none.py @@ -0,0 +1,58 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest +import isctest + +pytest.importorskip("dns") +import dns.message + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns*/named.pid", + "ns*/managed-keys.bind*", + ] +) + + +def test_querysource_none(): + msg = dns.message.make_query("example.", "A", want_dnssec=False) + + res = isctest.query.udp(msg, "10.53.0.2") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "10.53.0.3") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "10.53.0.4") + isctest.check.servfail(res) + + res = isctest.query.udp(msg, "10.53.0.5") + isctest.check.servfail(res) + + # using a different name below to make sure we don't use the + # resolver cache + + msg = dns.message.make_query("exampletwo.", "A", want_dnssec=False) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::2") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::3") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::4") + isctest.check.servfail(res) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::5") + isctest.check.servfail(res) diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 83f5a222ed..8851c842c0 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -3304,11 +3304,15 @@ Query Address .. namedconf:statement:: query-source :tags: query - :short: Controls the IPv4 address from which queries are issued. + :short: Controls the IPv4 address from which queries are issued. If + `none`, then no IPv4 address would be used to issue the + query and therefore only IPv6 servers are queried. .. namedconf:statement:: query-source-v6 :tags: query - :short: Controls the IPv6 address from which queries are issued. + :short: Controls the IPv6 address from which queries are issued. If + `none`, then no IPv6 address would be used to issue the + query and therefore only IPv4 servers are quried. If the server does not know the answer to a question, it queries other name servers. :any:`query-source` specifies the address used for diff --git a/doc/misc/options b/doc/misc/options index 44186cd37b..eacf693634 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -228,8 +228,8 @@ options { prefetch [ ]; provide-ixfr ; qname-minimization ( strict | relaxed | disabled | off ); - query-source [ address ] ( | * ); - query-source-v6 [ address ] ( | * ); + query-source [ address ] ( | * | none ); + query-source-v6 [ address ] ( | * | none ); querylog ; rate-limit { all-per-second ; @@ -514,8 +514,8 @@ view [ ] { prefetch [ ]; provide-ixfr ; qname-minimization ( strict | relaxed | disabled | off ); - query-source [ address ] ( | * ); - query-source-v6 [ address ] ( | * ); + query-source [ address ] ( | * | none ); + query-source-v6 [ address ] ( | * | none ); rate-limit { all-per-second ; errors-per-second ; diff --git a/lib/isccfg/check.c b/lib/isccfg/check.c index ea465cb494..4609734779 100644 --- a/lib/isccfg/check.c +++ b/lib/isccfg/check.c @@ -1315,24 +1315,21 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config, * Warn if query-source or query-source-v6 options specify * a port, and fail if they specify the DNS port. */ + unsigned int none_found = false; + for (i = 0; i < ARRAY_SIZE(sources); i++) { obj = NULL; (void)cfg_map_get(options, sources[i], &obj); - if (obj != NULL) { - const isc_sockaddr_t *sa = - cfg_obj_assockaddr(obj); - in_port_t port = isc_sockaddr_getport(sa); - if (port == dnsport) { + if (obj != NULL && cfg_obj_isvoid(obj)) { + none_found++; + + if (none_found > 1) { cfg_obj_log(obj, ISC_LOG_ERROR, - "'%s' cannot specify the " - "DNS listener port (%d)", - sources[i], port); + "query-source and " + "query-source-v6 can't be " + "none at the same time."); result = ISC_R_FAILURE; - } else if (port != 0) { - cfg_obj_log(obj, ISC_LOG_WARNING, - "'%s': specifying a port " - "is not recommended", - sources[i]); + break; } } } @@ -4419,14 +4416,26 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions, } (void)cfg_map_get(v1, xfr, &obj); if (obj != NULL) { - const isc_sockaddr_t *sa = - cfg_obj_assockaddr(obj); - in_port_t port = isc_sockaddr_getport(sa); - if (port == dnsport) { + if (cfg_obj_issockaddr(obj)) { + const isc_sockaddr_t *sa = + cfg_obj_assockaddr(obj); + in_port_t port = + isc_sockaddr_getport(sa); + if (port == dnsport) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "'%s' cannot " + "specify the " + "DNS listener port " + "(%d)", + xfr, port); + result = ISC_R_FAILURE; + } + } else { cfg_obj_log(obj, ISC_LOG_ERROR, - "'%s' cannot specify the " - "DNS listener port (%d)", - xfr, port); + "'none' is not a legal " + "'%s' parameter in a " + "server block", + xfr); result = ISC_R_FAILURE; } } diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 8eb846b9a1..02057b2cf7 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -131,6 +131,8 @@ static cfg_type_t cfg_type_printtime; static cfg_type_t cfg_type_qminmethod; static cfg_type_t cfg_type_querysource4; static cfg_type_t cfg_type_querysource6; +static cfg_type_t cfg_type_server_querysource4; +static cfg_type_t cfg_type_server_querysource6; static cfg_type_t cfg_type_querysource; static cfg_type_t cfg_type_server; static cfg_type_t cfg_type_server_key_kludge; @@ -2603,8 +2605,8 @@ static cfg_clausedef_t server_clauses[] = { { "notify-source-v6", &cfg_type_sockaddr6wild, 0 }, { "padding", &cfg_type_uint32, 0 }, { "provide-ixfr", &cfg_type_boolean, 0 }, - { "query-source", &cfg_type_querysource4, 0 }, - { "query-source-v6", &cfg_type_querysource6, 0 }, + { "query-source", &cfg_type_server_querysource4, 0 }, + { "query-source-v6", &cfg_type_server_querysource6, 0 }, { "request-expire", &cfg_type_boolean, 0 }, { "request-ixfr", &cfg_type_boolean, 0 }, { "request-ixfr-max-diffs", &cfg_type_uint32, 0 }, @@ -3218,14 +3220,33 @@ static cfg_type_t cfg_type_optional_class = { "optional_class", static isc_result_t parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { - REQUIRE(type != NULL); + isc_result_t result; - isc_result_t result = cfg_parse_sockaddr_generic( - pctx, &cfg_type_querysource, type, ret); - /* Preserve legacy query-source logging. */ + REQUIRE(type != NULL); + CHECK(cfg_peektoken(pctx, 0)); + + if (pctx->token.type == isc_tokentype_string && + strcasecmp(TOKEN_STRING(pctx), "address") == 0) + { + CHECK(cfg_gettoken(pctx, 0)); + CHECK(cfg_peektoken(pctx, 0)); + } + + if (pctx->token.type == isc_tokentype_string && + strcasecmp(TOKEN_STRING(pctx), "none") == 0) + { + CHECK(cfg_gettoken(pctx, 0)); + CHECK(cfg_create_obj(pctx, &cfg_type_none, ret)); + } else { + CHECK(cfg_parse_sockaddr_generic(pctx, &cfg_type_querysource, + type, ret)); + } + +cleanup: if (result != ISC_R_SUCCESS) { cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid query source"); } + return result; } @@ -3233,15 +3254,15 @@ static void print_querysource(cfg_printer_t *pctx, const cfg_obj_t *obj) { isc_netaddr_t na; isc_netaddr_fromsockaddr(&na, &obj->value.sockaddr); - cfg_print_cstr(pctx, "address "); cfg_print_rawaddr(pctx, &na); } static void -doc_querysource(cfg_printer_t *pctx, const cfg_type_t *type) { +doc__querysource(cfg_printer_t *pctx, const cfg_type_t *type, bool has_none) { const unsigned int *flagp = type->of; cfg_print_cstr(pctx, "[ address ] ( "); + if ((*flagp & CFG_ADDR_V4OK) != 0) { cfg_print_cstr(pctx, ""); } else if ((*flagp & CFG_ADDR_V6OK) != 0) { @@ -3249,7 +3270,22 @@ doc_querysource(cfg_printer_t *pctx, const cfg_type_t *type) { } else { UNREACHABLE(); } - cfg_print_cstr(pctx, " | * )"); + + cfg_print_cstr(pctx, " | *"); + if (has_none) { + cfg_print_cstr(pctx, " | none"); + } + cfg_print_cstr(pctx, " )"); +} + +static void +doc_querysource(cfg_printer_t *pctx, const cfg_type_t *type) { + doc__querysource(pctx, type, true); +} + +static void +doc_serverquerysource(cfg_printer_t *pctx, const cfg_type_t *type) { + doc__querysource(pctx, type, false); } static unsigned int sockaddr4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK; @@ -3270,6 +3306,16 @@ static cfg_type_t cfg_type_querysource6 = { NULL, &querysource6wild_flags }; +static cfg_type_t cfg_type_server_querysource4 = { + "querysource4", parse_querysource, NULL, doc_serverquerysource, + NULL, &querysource4wild_flags +}; + +static cfg_type_t cfg_type_server_querysource6 = { + "querysource6", parse_querysource, NULL, doc_serverquerysource, + NULL, &querysource6wild_flags +}; + static cfg_type_t cfg_type_querysource = { "querysource", NULL, print_querysource, NULL, &cfg_rep_sockaddr, NULL }; diff --git a/tests/isccfg/Makefile.am b/tests/isccfg/Makefile.am index 5a6fb03ac4..1a1887d917 100644 --- a/tests/isccfg/Makefile.am +++ b/tests/isccfg/Makefile.am @@ -15,6 +15,7 @@ LDADD += \ check_PROGRAMS = \ duration_test \ - parser_test + parser_test \ + grammar_test include $(top_srcdir)/Makefile.tests diff --git a/tests/isccfg/grammar_test.c b/tests/isccfg/grammar_test.c new file mode 100644 index 0000000000..e276287b59 --- /dev/null +++ b/tests/isccfg/grammar_test.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +static void +write_to_buffer(void *closure, const char *text, int textlen); + +static isc_buffer_t gbuffer; +static char gtext[512]; +static cfg_printer_t gprinter = { + .f = write_to_buffer, .closure = &gbuffer, .indent = 0, .flags = 0 +}; + +ISC_SETUP_TEST_IMPL(group) { + isc_buffer_init(&gbuffer, gtext, sizeof(gtext)); + isc_logconfig_t *logconfig = isc_logconfig_get(); + isc_log_createandusechannel( + logconfig, "default_stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, ISC_LOGDESTINATION_STDERR, 0, + ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_DEFAULT); + + return 0; +} + +static void +write_to_buffer(void *closure, const char *text, int textlen) { + isc_buffer_putmem((isc_buffer_t *)closure, (const unsigned char *)text, + textlen); +} + +static void +assert_text(const char *text) { + assert_int_equal(strcasecmp(text, isc_buffer_base(&gbuffer)), 0); + isc_buffer_clear(&gbuffer); + memset(gtext, 0, sizeof(gtext)); +} + +static const cfg_clausedef_t * +find_clause(const cfg_type_t *map, const char *name) { + const char *found_name = NULL; + const void *clauses = NULL; + unsigned int idx; + + found_name = cfg_map_firstclause(map, &clauses, &idx); + while (name != NULL && strcasecmp(name, found_name)) { + found_name = cfg_map_nextclause(map, &clauses, &idx); + } + + return ((cfg_clausedef_t *)clauses) + idx; +} + +static void +test__querysource(const char *clause_name, const char *name, + const char *expected) { + const cfg_clausedef_t *options_clause = NULL; + options_clause = find_clause(&cfg_type_namedconf, clause_name); + assert_non_null(options_clause); + + const cfg_clausedef_t *querysource_clause = NULL; + querysource_clause = find_clause(options_clause->type, name); + assert_non_null(querysource_clause); + querysource_clause->type->doc(&gprinter, querysource_clause->type); + assert_text(expected); +} + +ISC_RUN_TEST_IMPL(query_source) { + test__querysource("options", "query-source", + "[ address ] ( | * | none )"); +} + +ISC_RUN_TEST_IMPL(query_source_v6) { + test__querysource("options", "query-source-v6", + "[ address ] ( | * | none )"); +} + +ISC_RUN_TEST_IMPL(server_query_source) { + test__querysource("server", "query-source", + "[ address ] ( | * )"); +} + +ISC_RUN_TEST_IMPL(server_query_source_v6) { + test__querysource("server", "query-source-v6", + "[ address ] ( | * )"); +} + +static void +test__query_source_print(const char *config, const char *expected) { + isc_result_t result; + isc_buffer_t buffer; + cfg_parser_t *parser = NULL; + cfg_obj_t *output_conf = NULL; + + result = cfg_parser_create(mctx, &parser); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buffer, config, strlen(config)); + isc_buffer_add(&buffer, strlen(config)); + + result = cfg_parse_buffer(parser, &buffer, "text1", 0, + &cfg_type_namedconf, 0, &output_conf); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(output_conf); + + cfg_printer_t pctx = gprinter; + pctx.flags = CFG_PRINTER_ONELINE; + + output_conf->type->print(&pctx, output_conf); + assert_text(expected); + + cfg_obj_destroy(parser, &output_conf); + cfg_parser_reset(parser); + cfg_parser_destroy(&parser); +} + +ISC_RUN_TEST_IMPL(query_source_print_none) { + test__query_source_print(" options { query-source none; };", + "options { query-source none; }; "); + test__query_source_print( + " options { query-source address none; };", + "options { query-source none; }; "); + test__query_source_print(" options {query-source-v6 none; };", + "options { query-source-v6 none; }; "); + test__query_source_print(" options {query-source-v6 address none; };", + "options { query-source-v6 none; }; "); +} + +ISC_RUN_TEST_IMPL(query_source_print_addr) { + test__query_source_print(" options{query-source address 127.0.0.1;};", + "options { query-source 127.0.0.1; }; "); + test__query_source_print(" options{query-source 127.0.0.1;};", + "options { query-source 127.0.0.1; }; "); + test__query_source_print(" options{query-source-v6 address ::1; };", + "options { query-source-v6 ::1; }; "); + test__query_source_print(" options{query-source-v6 ::1; };", + "options { query-source-v6 ::1; }; "); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(query_source) +ISC_TEST_ENTRY(query_source_v6) +ISC_TEST_ENTRY(server_query_source) +ISC_TEST_ENTRY(server_query_source_v6) +ISC_TEST_ENTRY(query_source_print_none) +ISC_TEST_ENTRY(query_source_print_addr) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN_CUSTOM(setup_test_group, NULL)