]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add 'tls' configuration support for the 'forwarders' option
authorAram Sargsyan <aram@isc.org>
Thu, 8 Dec 2022 10:57:37 +0000 (10:57 +0000)
committerAram Sargsyan <aram@isc.org>
Fri, 20 Jan 2023 14:45:30 +0000 (14:45 +0000)
A 'tls' statement can be specified both for individual addresses
and for the whole list (as a default value when an individual
address doesn't have its own 'tls' set), just as it was done
before for the 'port' value.

Create a new function 'print_rawqstring()' to print a string residing
in a 'isc_textregion_t' type parameter.

Create a new function 'copy_string()' to copy a string from a
'cfg_obj_t' object into a 'isc_textregion_t'.

18 files changed:
bin/tests/system/checkconf/bad-forwarders-dot-badtls-1.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-forwarders-dot-badtls-2.conf [new file with mode: 0644]
bin/tests/system/checkconf/good-forwarders-dot.conf [new file with mode: 0644]
bin/tests/system/checkconf/good.conf.in
doc/man/named.conf.5in
doc/misc/forward.zoneopt
doc/misc/mirror.zoneopt
doc/misc/options
doc/misc/primary.zoneopt
doc/misc/redirect.zoneopt
doc/misc/secondary.zoneopt
doc/misc/static-stub.zoneopt
doc/misc/stub.zoneopt
lib/bind9/check.c
lib/isccfg/include/isccfg/cfg.h
lib/isccfg/include/isccfg/grammar.h
lib/isccfg/namedconf.c
lib/isccfg/parser.c

diff --git a/bin/tests/system/checkconf/bad-forwarders-dot-badtls-1.conf b/bin/tests/system/checkconf/bad-forwarders-dot-badtls-1.conf
new file mode 100644 (file)
index 0000000..68c1f14
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+tls test-tls {
+       protocols { TLSv1.2; };
+       ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+       prefer-server-ciphers yes;
+};
+
+# Bad: trying to use a TLS profile that has not been specified (another-tls).
+zone "example" {
+       type forward;
+       forward only;
+       forwarders port 5300 tls test-tls { 10.53.0.1; 10.53.0.2 port 5301 tls another-tls; };
+};
diff --git a/bin/tests/system/checkconf/bad-forwarders-dot-badtls-2.conf b/bin/tests/system/checkconf/bad-forwarders-dot-badtls-2.conf
new file mode 100644 (file)
index 0000000..d95af2d
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+tls test-tls {
+       protocols { TLSv1.2; };
+       ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+       prefer-server-ciphers yes;
+};
+
+# Bad: trying to use a TLS profile that has not been specified (another-tls).
+zone "example" {
+       type forward;
+       forward only;
+       forwarders port 5300 tls another-tls { 10.53.0.1; 10.53.0.2 port 5301 tls test-tls; };
+};
diff --git a/bin/tests/system/checkconf/good-forwarders-dot.conf b/bin/tests/system/checkconf/good-forwarders-dot.conf
new file mode 100644 (file)
index 0000000..0d9bfa3
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+tls test-tls {
+       protocols { TLSv1.2; };
+       ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384";
+       prefer-server-ciphers yes;
+};
+
+tls another-tls {
+       protocols { TLSv1.2; };
+       session-tickets no;
+};
+
+zone "example" {
+       type forward;
+       forward only;
+       forwarders port 5300 tls test-tls { 10.53.0.1; 10.53.0.2 port 5301 tls another-tls; };
+};
index f67d7172a33780abd1be3d313d8f4fc75ae54b06..84a08eefe1e55917fa6bb53314ba5c8a7f16a78d 100644 (file)
@@ -118,8 +118,8 @@ view "second" {
        zone "example2" {
                type static-stub;
                forward only;
-               forwarders {
-                       10.53.0.4;
+               forwarders tls "ephemeral" {
+                       10.53.0.4 port 8053 tls "ephemeral";
                };
                zone-statistics no;
        };
index ce1d817a1bd895e58e717531d17d88505036ee8d..ea9e2b86c4c2d6a625ed7231ae84e9d9a2ffa540 100644 (file)
@@ -126,7 +126,7 @@ options {
        allow\-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow\-update { <address_match_element>; ... };
        allow\-update\-forwarding { <address_match_element>; ... };
-       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        answer\-cookie <boolean>;
        attach\-cache <string>;
        auth\-nxdomain <boolean>;
@@ -136,7 +136,7 @@ options {
        avoid\-v6\-udp\-ports { <portrange>; ... }; // deprecated
        bindkeys\-file <quoted_string>;
        blackhole { <address_match_element>; ... };
-       catalog\-zones { zone <string> [ default\-primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone\-directory <quoted_string> ] [ in\-memory <boolean> ] [ min\-update\-interval <duration> ]; ... };
+       catalog\-zones { zone <string> [ default\-primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone\-directory <quoted_string> ] [ in\-memory <boolean> ] [ min\-update\-interval <duration> ]; ... };
        check\-dup\-records ( fail | warn | ignore );
        check\-integrity <boolean>;
        check\-mx ( fail | warn | ignore );
@@ -193,7 +193,7 @@ options {
        fetches\-per\-zone <integer> [ ( drop | fail ) ];
        flush\-zones\-on\-shutdown <boolean>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        fstrm\-set\-buffer\-hint <integer>; // not configured
        fstrm\-set\-flush\-timeout <integer>; // not configured
        fstrm\-set\-input\-queue\-size <integer>; // not configured
@@ -259,15 +259,15 @@ options {
        notify ( explicit | master\-only | primary\-only | <boolean> );
        notify\-delay <integer>;
        notify\-rate <integer>;
-       notify\-source ( <ipv4_address> | * ) ;
-       notify\-source\-v6 ( <ipv6_address> | * ) ;
+       notify\-source ( <ipv4_address> | * );
+       notify\-source\-v6 ( <ipv6_address> | * );
        notify\-to\-soa <boolean>;
        nsec3\-test\-zone <boolean>; // test only
        nta\-lifetime <duration>;
        nta\-recheck <duration>;
        nxdomain\-redirect <string>;
-       parental\-source ( <ipv4_address> | * ) ;
-       parental\-source\-v6 ( <ipv6_address> | * ) ;
+       parental\-source ( <ipv4_address> | * );
+       parental\-source\-v6 ( <ipv6_address> | * );
        pid\-file ( <quoted_string> | none );
        port <integer>;
        preferred\-glue <string>;
@@ -349,8 +349,8 @@ options {
        tls\-port <integer>;
        transfer\-format ( many\-answers | one\-answer );
        transfer\-message\-size <integer>;
-       transfer\-source ( <ipv4_address> | * ) ;
-       transfer\-source\-v6 ( <ipv6_address> | * ) ;
+       transfer\-source ( <ipv4_address> | * );
+       transfer\-source\-v6 ( <ipv6_address> | * );
        transfers\-in <integer>;
        transfers\-out <integer>;
        transfers\-per\-ns <integer>;
@@ -369,11 +369,11 @@ options {
        zone\-statistics ( full | terse | none | <boolean> );
 };
 
-parental\-agents <string> [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
+parental\-agents <string> [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
 
 plugin ( query ) <string> [ { <unspecified\-text> } ]; // may occur multiple times
 
-primaries <string> [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
+primaries <string> [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
 
 server <netprefix> {
        bogus <boolean>;
@@ -382,8 +382,8 @@ server <netprefix> {
        edns\-version <integer>;
        keys <server_key>;
        max\-udp\-size <integer>;
-       notify\-source ( <ipv4_address> | * ) ;
-       notify\-source\-v6 ( <ipv6_address> | * ) ;
+       notify\-source ( <ipv4_address> | * );
+       notify\-source\-v6 ( <ipv6_address> | * );
        padding <integer>;
        provide\-ixfr <boolean>;
        query\-source [ address ] ( <ipv4_address> | * );
@@ -396,8 +396,8 @@ server <netprefix> {
        tcp\-keepalive <boolean>;
        tcp\-only <boolean>;
        transfer\-format ( many\-answers | one\-answer );
-       transfer\-source ( <ipv4_address> | * ) ;
-       transfer\-source\-v6 ( <ipv6_address> | * ) ;
+       transfer\-source ( <ipv4_address> | * );
+       transfer\-source\-v6 ( <ipv6_address> | * );
        transfers <integer>;
 }; // may occur multiple times
 
@@ -433,11 +433,11 @@ view <string> [ <class> ] {
        allow\-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow\-update { <address_match_element>; ... };
        allow\-update\-forwarding { <address_match_element>; ... };
-       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        attach\-cache <string>;
        auth\-nxdomain <boolean>;
        auto\-dnssec ( allow | maintain | off ); // deprecated
-       catalog\-zones { zone <string> [ default\-primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone\-directory <quoted_string> ] [ in\-memory <boolean> ] [ min\-update\-interval <duration> ]; ... };
+       catalog\-zones { zone <string> [ default\-primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone\-directory <quoted_string> ] [ in\-memory <boolean> ] [ min\-update\-interval <duration> ]; ... };
        check\-dup\-records ( fail | warn | ignore );
        check\-integrity <boolean>;
        check\-mx ( fail | warn | ignore );
@@ -491,7 +491,7 @@ view <string> [ <class> ] {
        fetches\-per\-server <integer> [ ( drop | fail ) ];
        fetches\-per\-zone <integer> [ ( drop | fail ) ];
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        ipv4only\-contact <string>;
        ipv4only\-enable <boolean>;
        ipv4only\-server <string>;
@@ -540,15 +540,15 @@ view <string> [ <class> ] {
        nocookie\-udp\-size <integer>;
        notify ( explicit | master\-only | primary\-only | <boolean> );
        notify\-delay <integer>;
-       notify\-source ( <ipv4_address> | * ) ;
-       notify\-source\-v6 ( <ipv6_address> | * ) ;
+       notify\-source ( <ipv4_address> | * );
+       notify\-source\-v6 ( <ipv6_address> | * );
        notify\-to\-soa <boolean>;
        nsec3\-test\-zone <boolean>; // test only
        nta\-lifetime <duration>;
        nta\-recheck <duration>;
        nxdomain\-redirect <string>;
-       parental\-source ( <ipv4_address> | * ) ;
-       parental\-source\-v6 ( <ipv6_address> | * ) ;
+       parental\-source ( <ipv4_address> | * );
+       parental\-source\-v6 ( <ipv6_address> | * );
        plugin ( query ) <string> [ { <unspecified\-text> } ]; // may occur multiple times
        preferred\-glue <string>;
        prefetch <integer> [ <integer> ];
@@ -595,8 +595,8 @@ view <string> [ <class> ] {
                edns\-version <integer>;
                keys <server_key>;
                max\-udp\-size <integer>;
-               notify\-source ( <ipv4_address> | * ) ;
-               notify\-source\-v6 ( <ipv6_address> | * ) ;
+               notify\-source ( <ipv4_address> | * );
+               notify\-source\-v6 ( <ipv6_address> | * );
                padding <integer>;
                provide\-ixfr <boolean>;
                query\-source [ address ] ( <ipv4_address> | * );
@@ -609,8 +609,8 @@ view <string> [ <class> ] {
                tcp\-keepalive <boolean>;
                tcp\-only <boolean>;
                transfer\-format ( many\-answers | one\-answer );
-               transfer\-source ( <ipv4_address> | * ) ;
-               transfer\-source\-v6 ( <ipv6_address> | * ) ;
+               transfer\-source ( <ipv4_address> | * );
+               transfer\-source\-v6 ( <ipv6_address> | * );
                transfers <integer>;
        }; // may occur multiple times
        servfail\-ttl <duration>;
@@ -627,8 +627,8 @@ view <string> [ <class> ] {
        suppress\-initial\-notify <boolean>; // obsolete
        synth\-from\-dnssec <boolean>;
        transfer\-format ( many\-answers | one\-answer );
-       transfer\-source ( <ipv4_address> | * ) ;
-       transfer\-source\-v6 ( <ipv6_address> | * ) ;
+       transfer\-source ( <ipv4_address> | * );
+       transfer\-source\-v6 ( <ipv6_address> | * );
        trust\-anchor\-telemetry <boolean>; // experimental
        trust\-anchors { <string> ( static\-key | initial\-key | static\-ds | initial\-ds ) <integer> <integer> <integer> <quoted_string>; ... }; // may occur multiple times
        trusted\-keys { <string> <integer> <integer> <integer> <quoted_string>; ... }; // may occur multiple times, deprecated
@@ -659,7 +659,7 @@ zone <string> [ <class> ] {
        allow\-query\-on { <address_match_element>; ... };
        allow\-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow\-update { <address_match_element>; ... };
-       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        auto\-dnssec ( allow | maintain | off ); // deprecated
        check\-dup\-records ( fail | warn | ignore );
        check\-integrity <boolean>;
@@ -682,7 +682,7 @@ zone <string> [ <class> ] {
        dnssec\-update\-mode ( maintain | no\-resign );
        file <quoted_string>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        inline\-signing <boolean>;
        ixfr\-from\-differences <boolean>;
        journal <quoted_string>;
@@ -697,13 +697,13 @@ zone <string> [ <class> ] {
        max\-zone\-ttl ( unlimited | <duration> ); // deprecated
        notify ( explicit | master\-only | primary\-only | <boolean> );
        notify\-delay <integer>;
-       notify\-source ( <ipv4_address> | * ) ;
-       notify\-source\-v6 ( <ipv6_address> | * ) ;
+       notify\-source ( <ipv4_address> | * );
+       notify\-source\-v6 ( <ipv6_address> | * );
        notify\-to\-soa <boolean>;
        nsec3\-test\-zone <boolean>; // test only
-       parental\-agents [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
-       parental\-source ( <ipv4_address> | * ) ;
-       parental\-source\-v6 ( <ipv6_address> | * ) ;
+       parental\-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       parental\-source ( <ipv4_address> | * );
+       parental\-source\-v6 ( <ipv6_address> | * );
        serial\-update\-method ( date | increment | unixtime );
        sig\-signing\-nodes <integer>;
        sig\-signing\-signatures <integer>;
@@ -731,7 +731,7 @@ zone <string> [ <class> ] {
        allow\-query\-on { <address_match_element>; ... };
        allow\-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow\-update\-forwarding { <address_match_element>; ... };
-       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        auto\-dnssec ( allow | maintain | off ); // deprecated
        check\-names ( fail | warn | ignore );
        database <string>;
@@ -744,7 +744,7 @@ zone <string> [ <class> ] {
        dnssec\-update\-mode ( maintain | no\-resign );
        file <quoted_string>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        inline\-signing <boolean>;
        ixfr\-from\-differences <boolean>;
        journal <quoted_string>;
@@ -765,22 +765,22 @@ zone <string> [ <class> ] {
        multi\-master <boolean>;
        notify ( explicit | master\-only | primary\-only | <boolean> );
        notify\-delay <integer>;
-       notify\-source ( <ipv4_address> | * ) ;
-       notify\-source\-v6 ( <ipv6_address> | * ) ;
+       notify\-source ( <ipv4_address> | * );
+       notify\-source\-v6 ( <ipv6_address> | * );
        notify\-to\-soa <boolean>;
        nsec3\-test\-zone <boolean>; // test only
-       parental\-agents [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
-       parental\-source ( <ipv4_address> | * ) ;
-       parental\-source\-v6 ( <ipv6_address> | * ) ;
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       parental\-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       parental\-source ( <ipv4_address> | * );
+       parental\-source\-v6 ( <ipv6_address> | * );
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        request\-expire <boolean>;
        request\-ixfr <boolean>;
        sig\-signing\-nodes <integer>;
        sig\-signing\-signatures <integer>;
        sig\-signing\-type <integer>;
        sig\-validity\-interval <integer> [ <integer> ];
-       transfer\-source ( <ipv4_address> | * ) ;
-       transfer\-source\-v6 ( <ipv6_address> | * ) ;
+       transfer\-source ( <ipv4_address> | * );
+       transfer\-source\-v6 ( <ipv6_address> | * );
        try\-tcp\-refresh <boolean>;
        update\-check\-ksk <boolean>;
        zero\-no\-soa\-ttl <boolean>;
@@ -803,7 +803,7 @@ zone <string> [ <class> ] {
        allow\-query\-on { <address_match_element>; ... };
        allow\-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow\-update\-forwarding { <address_match_element>; ... };
-       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also\-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        check\-names ( fail | warn | ignore );
        database <string>;
        file <quoted_string>;
@@ -825,13 +825,13 @@ zone <string> [ <class> ] {
        multi\-master <boolean>;
        notify ( explicit | master\-only | primary\-only | <boolean> );
        notify\-delay <integer>;
-       notify\-source ( <ipv4_address> | * ) ;
-       notify\-source\-v6 ( <ipv6_address> | * ) ;
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       notify\-source ( <ipv4_address> | * );
+       notify\-source\-v6 ( <ipv6_address> | * );
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        request\-expire <boolean>;
        request\-ixfr <boolean>;
-       transfer\-source ( <ipv4_address> | * ) ;
-       transfer\-source\-v6 ( <ipv6_address> | * ) ;
+       transfer\-source ( <ipv4_address> | * );
+       transfer\-source\-v6 ( <ipv6_address> | * );
        try\-tcp\-refresh <boolean>;
        zero\-no\-soa\-ttl <boolean>;
        zone\-statistics ( full | terse | none | <boolean> );
@@ -850,7 +850,7 @@ zone <string> [ <class> ] {
        type forward;
        delegation\-only <boolean>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
 };
 
 .ft P
@@ -888,7 +888,7 @@ zone <string> [ <class> ] {
        masterfile\-style ( full | relative );
        max\-records <integer>;
        max\-zone\-ttl ( unlimited | <duration> ); // deprecated
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        zone\-statistics ( full | terse | none | <boolean> );
 };
 
@@ -906,7 +906,7 @@ zone <string> [ <class> ] {
        allow\-query { <address_match_element>; ... };
        allow\-query\-on { <address_match_element>; ... };
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        max\-records <integer>;
        server\-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
        server\-names { <string>; ... };
@@ -932,7 +932,7 @@ zone <string> [ <class> ] {
        dialup ( notify | notify\-passive | passive | refresh | <boolean> );
        file <quoted_string>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        masterfile\-format ( raw | text );
        masterfile\-style ( full | relative );
        max\-records <integer>;
@@ -943,9 +943,9 @@ zone <string> [ <class> ] {
        min\-refresh\-time <integer>;
        min\-retry\-time <integer>;
        multi\-master <boolean>;
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source\-v6 ( <ipv6_address> | * )  ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
-       transfer\-source ( <ipv4_address> | * ) ;
-       transfer\-source\-v6 ( <ipv6_address> | * ) ;
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source\-v6 ( <ipv6_address> | * ) ] { ( <remote\-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       transfer\-source ( <ipv4_address> | * );
+       transfer\-source\-v6 ( <ipv6_address> | * );
        zone\-statistics ( full | terse | none | <boolean> );
 };
 
index 211a0901b926bffbf4f58f92d8f58f083b645f52..6c5f38b013c534860bb65b9eeb1de8dbab963783 100644 (file)
@@ -2,5 +2,5 @@ zone <string> [ <class> ] {
        type forward;
        delegation-only <boolean>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
 };
index 467a78dc1e1908975b354def557ad8f2865aba75..cc9dbaa446badbba3749a468450729f6f368a65f 100644 (file)
@@ -5,7 +5,7 @@ zone <string> [ <class> ] {
        allow-query-on { <address_match_element>; ... };
        allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow-update-forwarding { <address_match_element>; ... };
-       also-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        check-names ( fail | warn | ignore );
        database <string>;
        file <quoted_string>;
@@ -27,13 +27,13 @@ zone <string> [ <class> ] {
        multi-master <boolean>;
        notify ( explicit | master-only | primary-only | <boolean> );
        notify-delay <integer>;
-       notify-source ( <ipv4_address> | * ) ;
-       notify-source-v6 ( <ipv6_address> | * ) ;
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       notify-source ( <ipv4_address> | * );
+       notify-source-v6 ( <ipv6_address> | * );
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        request-expire <boolean>;
        request-ixfr <boolean>;
-       transfer-source ( <ipv4_address> | * ) ;
-       transfer-source-v6 ( <ipv6_address> | * ) ;
+       transfer-source ( <ipv4_address> | * );
+       transfer-source-v6 ( <ipv6_address> | * );
        try-tcp-refresh <boolean>;
        zero-no-soa-ttl <boolean>;
        zone-statistics ( full | terse | none | <boolean> );
index 9064b2b598c5b21eadf1238d28d0572d7ae8f6d0..e6e8d67816e7424b6ac33baf7ef58b824e8a4211 100644 (file)
@@ -69,7 +69,7 @@ options {
        allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow-update { <address_match_element>; ... };
        allow-update-forwarding { <address_match_element>; ... };
-       also-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        answer-cookie <boolean>;
        attach-cache <string>;
        auth-nxdomain <boolean>;
@@ -79,7 +79,7 @@ options {
        avoid-v6-udp-ports { <portrange>; ... }; // deprecated
        bindkeys-file <quoted_string>;
        blackhole { <address_match_element>; ... };
-       catalog-zones { zone <string> [ default-primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone-directory <quoted_string> ] [ in-memory <boolean> ] [ min-update-interval <duration> ]; ... };
+       catalog-zones { zone <string> [ default-primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone-directory <quoted_string> ] [ in-memory <boolean> ] [ min-update-interval <duration> ]; ... };
        check-dup-records ( fail | warn | ignore );
        check-integrity <boolean>;
        check-mx ( fail | warn | ignore );
@@ -136,7 +136,7 @@ options {
        fetches-per-zone <integer> [ ( drop | fail ) ];
        flush-zones-on-shutdown <boolean>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        fstrm-set-buffer-hint <integer>; // not configured
        fstrm-set-flush-timeout <integer>; // not configured
        fstrm-set-input-queue-size <integer>; // not configured
@@ -202,15 +202,15 @@ options {
        notify ( explicit | master-only | primary-only | <boolean> );
        notify-delay <integer>;
        notify-rate <integer>;
-       notify-source ( <ipv4_address> | * ) ;
-       notify-source-v6 ( <ipv6_address> | * ) ;
+       notify-source ( <ipv4_address> | * );
+       notify-source-v6 ( <ipv6_address> | * );
        notify-to-soa <boolean>;
        nsec3-test-zone <boolean>; // test only
        nta-lifetime <duration>;
        nta-recheck <duration>;
        nxdomain-redirect <string>;
-       parental-source ( <ipv4_address> | * ) ;
-       parental-source-v6 ( <ipv6_address> | * ) ;
+       parental-source ( <ipv4_address> | * );
+       parental-source-v6 ( <ipv6_address> | * );
        pid-file ( <quoted_string> | none );
        port <integer>;
        preferred-glue <string>;
@@ -292,8 +292,8 @@ options {
        tls-port <integer>;
        transfer-format ( many-answers | one-answer );
        transfer-message-size <integer>;
-       transfer-source ( <ipv4_address> | * ) ;
-       transfer-source-v6 ( <ipv6_address> | * ) ;
+       transfer-source ( <ipv4_address> | * );
+       transfer-source-v6 ( <ipv6_address> | * );
        transfers-in <integer>;
        transfers-out <integer>;
        transfers-per-ns <integer>;
@@ -312,11 +312,11 @@ options {
        zone-statistics ( full | terse | none | <boolean> );
 };
 
-parental-agents <string> [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
+parental-agents <string> [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
 
 plugin ( query ) <string> [ { <unspecified-text> } ]; // may occur multiple times
 
-primaries <string> [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
+primaries <string> [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... }; // may occur multiple times
 
 server <netprefix> {
        bogus <boolean>;
@@ -325,8 +325,8 @@ server <netprefix> {
        edns-version <integer>;
        keys <server_key>;
        max-udp-size <integer>;
-       notify-source ( <ipv4_address> | * ) ;
-       notify-source-v6 ( <ipv6_address> | * ) ;
+       notify-source ( <ipv4_address> | * );
+       notify-source-v6 ( <ipv6_address> | * );
        padding <integer>;
        provide-ixfr <boolean>;
        query-source [ address ] ( <ipv4_address> | * );
@@ -339,8 +339,8 @@ server <netprefix> {
        tcp-keepalive <boolean>;
        tcp-only <boolean>;
        transfer-format ( many-answers | one-answer );
-       transfer-source ( <ipv4_address> | * ) ;
-       transfer-source-v6 ( <ipv6_address> | * ) ;
+       transfer-source ( <ipv4_address> | * );
+       transfer-source-v6 ( <ipv6_address> | * );
        transfers <integer>;
 }; // may occur multiple times
 
@@ -376,11 +376,11 @@ view <string> [ <class> ] {
        allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow-update { <address_match_element>; ... };
        allow-update-forwarding { <address_match_element>; ... };
-       also-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        attach-cache <string>;
        auth-nxdomain <boolean>;
        auto-dnssec ( allow | maintain | off ); // deprecated
-       catalog-zones { zone <string> [ default-primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone-directory <quoted_string> ] [ in-memory <boolean> ] [ min-update-interval <duration> ]; ... };
+       catalog-zones { zone <string> [ default-primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... } ] [ zone-directory <quoted_string> ] [ in-memory <boolean> ] [ min-update-interval <duration> ]; ... };
        check-dup-records ( fail | warn | ignore );
        check-integrity <boolean>;
        check-mx ( fail | warn | ignore );
@@ -434,7 +434,7 @@ view <string> [ <class> ] {
        fetches-per-server <integer> [ ( drop | fail ) ];
        fetches-per-zone <integer> [ ( drop | fail ) ];
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        ipv4only-contact <string>;
        ipv4only-enable <boolean>;
        ipv4only-server <string>;
@@ -483,15 +483,15 @@ view <string> [ <class> ] {
        nocookie-udp-size <integer>;
        notify ( explicit | master-only | primary-only | <boolean> );
        notify-delay <integer>;
-       notify-source ( <ipv4_address> | * ) ;
-       notify-source-v6 ( <ipv6_address> | * ) ;
+       notify-source ( <ipv4_address> | * );
+       notify-source-v6 ( <ipv6_address> | * );
        notify-to-soa <boolean>;
        nsec3-test-zone <boolean>; // test only
        nta-lifetime <duration>;
        nta-recheck <duration>;
        nxdomain-redirect <string>;
-       parental-source ( <ipv4_address> | * ) ;
-       parental-source-v6 ( <ipv6_address> | * ) ;
+       parental-source ( <ipv4_address> | * );
+       parental-source-v6 ( <ipv6_address> | * );
        plugin ( query ) <string> [ { <unspecified-text> } ]; // may occur multiple times
        preferred-glue <string>;
        prefetch <integer> [ <integer> ];
@@ -538,8 +538,8 @@ view <string> [ <class> ] {
                edns-version <integer>;
                keys <server_key>;
                max-udp-size <integer>;
-               notify-source ( <ipv4_address> | * ) ;
-               notify-source-v6 ( <ipv6_address> | * ) ;
+               notify-source ( <ipv4_address> | * );
+               notify-source-v6 ( <ipv6_address> | * );
                padding <integer>;
                provide-ixfr <boolean>;
                query-source [ address ] ( <ipv4_address> | * );
@@ -552,8 +552,8 @@ view <string> [ <class> ] {
                tcp-keepalive <boolean>;
                tcp-only <boolean>;
                transfer-format ( many-answers | one-answer );
-               transfer-source ( <ipv4_address> | * ) ;
-               transfer-source-v6 ( <ipv6_address> | * ) ;
+               transfer-source ( <ipv4_address> | * );
+               transfer-source-v6 ( <ipv6_address> | * );
                transfers <integer>;
        }; // may occur multiple times
        servfail-ttl <duration>;
@@ -570,8 +570,8 @@ view <string> [ <class> ] {
        suppress-initial-notify <boolean>; // obsolete
        synth-from-dnssec <boolean>;
        transfer-format ( many-answers | one-answer );
-       transfer-source ( <ipv4_address> | * ) ;
-       transfer-source-v6 ( <ipv6_address> | * ) ;
+       transfer-source ( <ipv4_address> | * );
+       transfer-source-v6 ( <ipv6_address> | * );
        trust-anchor-telemetry <boolean>; // experimental
        trust-anchors { <string> ( static-key | initial-key | static-ds | initial-ds ) <integer> <integer> <integer> <quoted_string>; ... }; // may occur multiple times
        trusted-keys { <string> <integer> <integer> <integer> <quoted_string>; ... }; // may occur multiple times, deprecated
index 85fc3a36ed4435b60a28ca22cc85a23130362731..f0d3a93b7526537804d601e4716111d21afa2bb5 100644 (file)
@@ -4,7 +4,7 @@ zone <string> [ <class> ] {
        allow-query-on { <address_match_element>; ... };
        allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow-update { <address_match_element>; ... };
-       also-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        auto-dnssec ( allow | maintain | off ); // deprecated
        check-dup-records ( fail | warn | ignore );
        check-integrity <boolean>;
@@ -27,7 +27,7 @@ zone <string> [ <class> ] {
        dnssec-update-mode ( maintain | no-resign );
        file <quoted_string>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        inline-signing <boolean>;
        ixfr-from-differences <boolean>;
        journal <quoted_string>;
@@ -42,13 +42,13 @@ zone <string> [ <class> ] {
        max-zone-ttl ( unlimited | <duration> ); // deprecated
        notify ( explicit | master-only | primary-only | <boolean> );
        notify-delay <integer>;
-       notify-source ( <ipv4_address> | * ) ;
-       notify-source-v6 ( <ipv6_address> | * ) ;
+       notify-source ( <ipv4_address> | * );
+       notify-source-v6 ( <ipv6_address> | * );
        notify-to-soa <boolean>;
        nsec3-test-zone <boolean>; // test only
-       parental-agents [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
-       parental-source ( <ipv4_address> | * ) ;
-       parental-source-v6 ( <ipv6_address> | * ) ;
+       parental-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       parental-source ( <ipv4_address> | * );
+       parental-source-v6 ( <ipv6_address> | * );
        serial-update-method ( date | increment | unixtime );
        sig-signing-nodes <integer>;
        sig-signing-signatures <integer>;
index 94e104d444e23ccae1722a2e6a7c0a3d2fd1c428..c0bee863fb5fb932efc952620ce8444528d1270d 100644 (file)
@@ -8,6 +8,6 @@ zone <string> [ <class> ] {
        masterfile-style ( full | relative );
        max-records <integer>;
        max-zone-ttl ( unlimited | <duration> ); // deprecated
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        zone-statistics ( full | terse | none | <boolean> );
 };
index cbddd65be880069b0f53c43555a1db160b40d9c2..c4de3866a7d3605b59f326e14eabc50f724e85ea 100644 (file)
@@ -5,7 +5,7 @@ zone <string> [ <class> ] {
        allow-query-on { <address_match_element>; ... };
        allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
        allow-update-forwarding { <address_match_element>; ... };
-       also-notify [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        auto-dnssec ( allow | maintain | off ); // deprecated
        check-names ( fail | warn | ignore );
        database <string>;
@@ -18,7 +18,7 @@ zone <string> [ <class> ] {
        dnssec-update-mode ( maintain | no-resign );
        file <quoted_string>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        inline-signing <boolean>;
        ixfr-from-differences <boolean>;
        journal <quoted_string>;
@@ -39,22 +39,22 @@ zone <string> [ <class> ] {
        multi-master <boolean>;
        notify ( explicit | master-only | primary-only | <boolean> );
        notify-delay <integer>;
-       notify-source ( <ipv4_address> | * ) ;
-       notify-source-v6 ( <ipv6_address> | * ) ;
+       notify-source ( <ipv4_address> | * );
+       notify-source-v6 ( <ipv6_address> | * );
        notify-to-soa <boolean>;
        nsec3-test-zone <boolean>; // test only
-       parental-agents [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
-       parental-source ( <ipv4_address> | * ) ;
-       parental-source-v6 ( <ipv6_address> | * ) ;
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       parental-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       parental-source ( <ipv4_address> | * );
+       parental-source-v6 ( <ipv6_address> | * );
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        request-expire <boolean>;
        request-ixfr <boolean>;
        sig-signing-nodes <integer>;
        sig-signing-signatures <integer>;
        sig-signing-type <integer>;
        sig-validity-interval <integer> [ <integer> ];
-       transfer-source ( <ipv4_address> | * ) ;
-       transfer-source-v6 ( <ipv6_address> | * ) ;
+       transfer-source ( <ipv4_address> | * );
+       transfer-source-v6 ( <ipv6_address> | * );
        try-tcp-refresh <boolean>;
        update-check-ksk <boolean>;
        zero-no-soa-ttl <boolean>;
index 58fd0ce9eb595bf59177b5c9ea7457bc8e99234f..85c158fbcbd33c562c22847bc2b42b0fbc2a39ed 100644 (file)
@@ -3,7 +3,7 @@ zone <string> [ <class> ] {
        allow-query { <address_match_element>; ... };
        allow-query-on { <address_match_element>; ... };
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        max-records <integer>;
        server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
        server-names { <string>; ... };
index 0c37eefef8ce705ce9ee57c09d0d324d22698252..ab1e49e1897ae90e8d40dbcba426d75e49584781 100644 (file)
@@ -8,7 +8,7 @@ zone <string> [ <class> ] {
        dialup ( notify | notify-passive | passive | refresh | <boolean> );
        file <quoted_string>;
        forward ( first | only );
-       forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
+       forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
        masterfile-format ( raw | text );
        masterfile-style ( full | relative );
        max-records <integer>;
@@ -19,8 +19,8 @@ zone <string> [ <class> ] {
        min-refresh-time <integer>;
        min-retry-time <integer>;
        multi-master <boolean>;
-       primaries [ port <integer> ] [ source ( <ipv4_address> | * )  ] [ source-v6 ( <ipv6_address> | * )  ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
-       transfer-source ( <ipv4_address> | * ) ;
-       transfer-source-v6 ( <ipv6_address> | * ) ;
+       primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
+       transfer-source ( <ipv4_address> | * );
+       transfer-source-v6 ( <ipv6_address> | * );
        zone-statistics ( full | terse | none | <boolean> );
 };
index ec18d66f4e839ec93a0f3f033b007e432d2bf477..48cb90c6e2790c227437bfda4979160790838aad 100644 (file)
@@ -80,6 +80,10 @@ fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable,
 static isc_result_t
 keydirexist(const cfg_obj_t *zcgf, const char *dir, const char *kaspnamestr,
            isc_symtab_t *symtab, isc_log_t *logctx, isc_mem_t *mctx);
+
+static const cfg_obj_t *
+find_maplist(const cfg_obj_t *config, const char *listname, const char *name);
+
 static void
 freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
        UNUSED(type);
@@ -272,10 +276,38 @@ check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
 }
 
 static isc_result_t
-check_forward(const cfg_obj_t *options, const cfg_obj_t *global,
-             isc_log_t *logctx) {
+validate_tls(const cfg_obj_t *config, const cfg_obj_t *obj, isc_log_t *logctx,
+            const char *str) {
+       dns_fixedname_t fname;
+       dns_name_t *nm = dns_fixedname_initname(&fname);
+       isc_result_t result = dns_name_fromstring(nm, str, 0, NULL);
+
+       if (result != ISC_R_SUCCESS) {
+               cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                           "'%s' is not a valid name", str);
+               return (result);
+       }
+
+       if (strcasecmp(str, "ephemeral") != 0) {
+               const cfg_obj_t *tlsmap = find_maplist(config, "tls", str);
+
+               if (tlsmap == NULL) {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "tls '%s' is not defined", str);
+                       return (ISC_R_FAILURE);
+               }
+       }
+
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+check_forward(const cfg_obj_t *config, const cfg_obj_t *options,
+             const cfg_obj_t *global, isc_log_t *logctx) {
        const cfg_obj_t *forward = NULL;
        const cfg_obj_t *forwarders = NULL;
+       const cfg_obj_t *faddresses = NULL;
+       const cfg_listelt_t *element;
 
        (void)cfg_map_get(options, "forward", &forward);
        (void)cfg_map_get(options, "forwarders", &forwarders);
@@ -294,6 +326,37 @@ check_forward(const cfg_obj_t *options, const cfg_obj_t *global,
                            "no matching 'forwarders' statement");
                return (ISC_R_FAILURE);
        }
+       if (forwarders != NULL) {
+               isc_result_t result = ISC_R_SUCCESS;
+               const cfg_obj_t *tlspobj = cfg_tuple_get(forwarders, "tls");
+
+               if (tlspobj != NULL && cfg_obj_isstring(tlspobj)) {
+                       const char *tls = cfg_obj_asstring(tlspobj);
+                       if (tls != NULL) {
+                               result = validate_tls(config, tlspobj, logctx,
+                                                     tls);
+                               if (result != ISC_R_SUCCESS) {
+                                       return (result);
+                               }
+                       }
+               }
+
+               faddresses = cfg_tuple_get(forwarders, "addresses");
+               for (element = cfg_list_first(faddresses); element != NULL;
+                    element = cfg_list_next(element))
+               {
+                       const cfg_obj_t *forwarder = cfg_listelt_value(element);
+                       const char *tls = cfg_obj_getsockaddrtls(forwarder);
+                       if (tls != NULL) {
+                               result = validate_tls(config, faddresses,
+                                                     logctx, tls);
+                               if (result != ISC_R_SUCCESS) {
+                                       return (result);
+                               }
+                       }
+               }
+       }
+
        return (ISC_R_SUCCESS);
 }
 
@@ -3601,7 +3664,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
                        (void)cfg_map_get(goptions, "forwarders", &obj);
                }
        }
-       if (check_forward(zoptions, obj, logctx) != ISC_R_SUCCESS) {
+       if (check_forward(config, zoptions, obj, logctx) != ISC_R_SUCCESS) {
                result = ISC_R_FAILURE;
        }
 
@@ -5293,7 +5356,8 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
        /*
         * Check that forwarding is reasonable.
         */
-       if (opts != NULL && check_forward(opts, NULL, logctx) != ISC_R_SUCCESS)
+       if (opts != NULL &&
+           check_forward(config, opts, NULL, logctx) != ISC_R_SUCCESS)
        {
                result = ISC_R_FAILURE;
        }
index c4f2d86362889538b9a290482024ff753275b394..f790cd4377f2865f3f069c1edccf4bd8e39a3e76 100644 (file)
@@ -392,6 +392,12 @@ cfg_obj_issockaddr(const cfg_obj_t *obj);
  * Return true iff 'obj' is a socket address.
  */
 
+bool
+cfg_obj_issockaddrtls(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is a socket address with an optional tls configuration.
+ */
+
 const isc_sockaddr_t *
 cfg_obj_assockaddr(const cfg_obj_t *obj);
 /*%<
@@ -399,13 +405,27 @@ cfg_obj_assockaddr(const cfg_obj_t *obj);
  *
  * Requires:
  * \li     'obj' points to a valid configuration object of a socket address
- * type.
+ * type, or of a socket address type with an optional tls configuration.
  *
  * Returns:
  * \li     A pointer to a sockaddr.  The sockaddr must be copied by the caller
  *      if necessary.
  */
 
+const char *
+cfg_obj_getsockaddrtls(const cfg_obj_t *obj);
+/*%<
+ * Returns the TLS value of a configuration object representing a
+ * socket address.
+ *
+ * Requires:
+ * \li     'obj' points to a valid configuration object of a
+ *         socket address type.
+ *
+ * Returns:
+ * \li     TLS value associated with a sockaddr, or NULL.
+ */
+
 bool
 cfg_obj_isnetprefix(const cfg_obj_t *obj);
 /*%<
index 3b19a5f4effea93a5df8aff131fcbc1e9919766b..7cbcf7f47068bde93f6a84199f0365d9e20703f3 100644 (file)
@@ -169,14 +169,18 @@ struct cfg_rep {
 struct cfg_obj {
        const cfg_type_t *type;
        union {
-               uint32_t          uint32;
-               uint64_t          uint64;
-               isc_textregion_t  string; /*%< null terminated, too */
-               bool              boolean;
-               cfg_map_t         map;
-               cfg_list_t        list;
-               cfg_obj_t       **tuple;
-               isc_sockaddr_t    sockaddr;
+               uint32_t         uint32;
+               uint64_t         uint64;
+               isc_textregion_t string; /*%< null terminated, too */
+               bool             boolean;
+               cfg_map_t        map;
+               cfg_list_t       list;
+               cfg_obj_t      **tuple;
+               isc_sockaddr_t   sockaddr;
+               struct {
+                       isc_sockaddr_t   sockaddr;
+                       isc_textregion_t tls;
+               } sockaddrtls;
                cfg_netprefix_t   netprefix;
                isccfg_duration_t duration;
        } value;
@@ -266,6 +270,7 @@ struct cfg_parser {
 #define CFG_ADDR_V6OK      0x00000004
 #define CFG_ADDR_WILDOK            0x00000008
 #define CFG_ADDR_PORTOK            0x00000010
+#define CFG_ADDR_TLSOK     0x00000020
 #define CFG_ADDR_MASK      (CFG_ADDR_V6OK | CFG_ADDR_V4OK)
 /*@}*/
 
@@ -281,6 +286,7 @@ extern cfg_rep_t cfg_rep_map;
 extern cfg_rep_t cfg_rep_list;
 extern cfg_rep_t cfg_rep_tuple;
 extern cfg_rep_t cfg_rep_sockaddr;
+extern cfg_rep_t cfg_rep_sockaddrtls;
 extern cfg_rep_t cfg_rep_netprefix;
 extern cfg_rep_t cfg_rep_void;
 extern cfg_rep_t cfg_rep_fixedpoint;
@@ -304,6 +310,7 @@ extern cfg_type_t cfg_type_bracketed_text;
 extern cfg_type_t cfg_type_optional_bracketed_text;
 extern cfg_type_t cfg_type_keyref;
 extern cfg_type_t cfg_type_sockaddr;
+extern cfg_type_t cfg_type_sockaddrtls;
 extern cfg_type_t cfg_type_netaddr;
 extern cfg_type_t cfg_type_netaddr4;
 extern cfg_type_t cfg_type_netaddr4wild;
@@ -372,6 +379,10 @@ cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port);
 isc_result_t
 cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
 
+isc_result_t
+cfg_parse_sockaddrtls(cfg_parser_t *pctx, const cfg_type_t *type,
+                     cfg_obj_t **ret);
+
 isc_result_t
 cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
 
index 898b03a6f5f104693087e4c273822ca89ffd25ef..2e92d2d48750c59542d0b4ad14921581a4d2407b 100644 (file)
@@ -89,8 +89,8 @@ cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type);
 static cfg_type_t cfg_type_acl;
 static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
 static cfg_type_t cfg_type_bracketed_netaddrlist;
-static cfg_type_t cfg_type_bracketed_sockaddrlist;
 static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
+static cfg_type_t cfg_type_bracketed_sockaddrtlslist;
 static cfg_type_t cfg_type_bracketed_http_endpoint_list;
 static cfg_type_t cfg_type_controls;
 static cfg_type_t cfg_type_controls_sockaddr;
@@ -285,11 +285,12 @@ static cfg_type_t cfg_type_namesockaddrkeylist = {
 
 /*%
  * A list of socket addresses with an optional default port, as used
- * in the 'listen-on' option.  E.g., "{ 10.0.0.1; 1::2 port 69; }"
+ * in the 'forwarders' option.  E.g., "{ 10.0.0.1; 1::2 port 69; }"
  */
 static cfg_tuplefielddef_t portiplist_fields[] = {
        { "port", &cfg_type_optional_port, 0 },
-       { "addresses", &cfg_type_bracketed_sockaddrlist, 0 },
+       { "tls", &cfg_type_optional_tls, 0 },
+       { "addresses", &cfg_type_bracketed_sockaddrtlslist, 0 },
        { NULL, NULL, 0 }
 };
 static cfg_type_t cfg_type_portiplist = { "portiplist",           cfg_parse_tuple,
@@ -732,12 +733,14 @@ static cfg_type_t cfg_type_bracketed_netaddrlist = { "bracketed_netaddrlist",
                                                     &cfg_rep_list,
                                                     &cfg_type_netaddr };
 
-static cfg_type_t cfg_type_bracketed_sockaddrlist = { "bracketed_sockaddrlist",
-                                                     cfg_parse_bracketed_list,
-                                                     cfg_print_bracketed_list,
-                                                     cfg_doc_bracketed_list,
-                                                     &cfg_rep_list,
-                                                     &cfg_type_sockaddr };
+static cfg_type_t cfg_type_bracketed_sockaddrtlslist = {
+       "bracketed_sockaddrtlslist",
+       cfg_parse_bracketed_list,
+       cfg_print_bracketed_list,
+       cfg_doc_bracketed_list,
+       &cfg_rep_list,
+       &cfg_type_sockaddrtls
+};
 
 static const char *autodnssec_enums[] = { "allow", "maintain", "off", NULL };
 static cfg_type_t cfg_type_autodnssec = {
@@ -1085,7 +1088,7 @@ static cfg_type_t cfg_type_portrange = { "portrange", parse_portrange,
                                         NULL,        cfg_doc_terminal,
                                         NULL,        NULL };
 
-static cfg_type_t cfg_type_bracketed_portlist = { "bracketed_sockaddrlist",
+static cfg_type_t cfg_type_bracketed_portlist = { "bracketed_portlist",
                                                  cfg_parse_bracketed_list,
                                                  cfg_print_bracketed_list,
                                                  cfg_doc_bracketed_list,
@@ -3169,6 +3172,7 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        in_port_t port = 0;
        unsigned int have_address = 0;
        unsigned int have_port = 0;
+       unsigned int have_tls = 0;
        const unsigned int *flagp = type->of;
 
        if ((*flagp & CFG_ADDR_V4OK) != 0) {
@@ -3201,7 +3205,12 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                                CHECK(cfg_parse_rawport(pctx, CFG_ADDR_WILDOK,
                                                        &port));
                                have_port++;
-                       } else if (have_port == 0 && have_address == 0) {
+                       } else if (strcasecmp(TOKEN_STRING(pctx), "tls") == 0) {
+                               /* We do not expect TLS here, not parsing. */
+                               ++have_tls;
+                       } else if (have_port == 0 && have_tls == 0 &&
+                                  have_address == 0)
+                       {
                                return (cfg_parse_sockaddr(pctx, type, ret));
                        } else {
                                cfg_parser_error(pctx, CFG_LOG_NEAR,
@@ -3213,12 +3222,18 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                        break;
                }
        }
+
        if (have_address > 1 || have_port > 1 || have_address + have_port == 0)
        {
                cfg_parser_error(pctx, 0, "expected one address and/or port");
                return (ISC_R_UNEXPECTEDTOKEN);
        }
 
+       if (have_tls > 0) {
+               cfg_parser_error(pctx, 0, "unexpected tls");
+               return (ISC_R_UNEXPECTEDTOKEN);
+       }
+
        CHECK(cfg_create_obj(pctx, &cfg_type_querysource, &obj));
        isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
        *ret = obj;
index 6fc3e8094720515b9e7e6a26e6ac1b3403672f18..f70665675edfda4c6661bf25c6e1bb198fa533dd 100644 (file)
@@ -119,6 +119,12 @@ create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
 static void
 free_string(cfg_parser_t *pctx, cfg_obj_t *obj);
 
+static void
+copy_string(cfg_parser_t *pctx, const cfg_obj_t *obj, isc_textregion_t *dst);
+
+static void
+free_sockaddrtls(cfg_parser_t *pctx, cfg_obj_t *obj);
+
 static isc_result_t
 create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
 
@@ -164,6 +170,7 @@ cfg_rep_t cfg_rep_map = { "map", free_map };
 cfg_rep_t cfg_rep_list = { "list", free_list };
 cfg_rep_t cfg_rep_tuple = { "tuple", free_tuple };
 cfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };
+cfg_rep_t cfg_rep_sockaddrtls = { "sockaddrtls", free_sockaddrtls };
 cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };
 cfg_rep_t cfg_rep_void = { "void", free_noop };
 cfg_rep_t cfg_rep_fixedpoint = { "fixedpoint", free_noop };
@@ -1511,17 +1518,22 @@ cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
 }
 
 static void
-print_qstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+print_rawqstring(cfg_printer_t *pctx, const isc_textregion_t string) {
        cfg_print_cstr(pctx, "\"");
-       for (size_t i = 0; i < obj->value.string.length; i++) {
-               if (obj->value.string.base[i] == '"') {
+       for (size_t i = 0; i < string.length; i++) {
+               if (string.base[i] == '"') {
                        cfg_print_cstr(pctx, "\\");
                }
-               cfg_print_chars(pctx, &obj->value.string.base[i], 1);
+               cfg_print_chars(pctx, (const char *)&string.base[i], 1);
        }
        cfg_print_cstr(pctx, "\"");
 }
 
+static void
+print_qstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+       print_rawqstring(pctx, obj->value.string);
+}
+
 static void
 print_sstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        cfg_print_cstr(pctx, "\"");
@@ -1542,6 +1554,27 @@ free_string(cfg_parser_t *pctx, cfg_obj_t *obj) {
                    obj->value.string.length + 1);
 }
 
+static void
+copy_string(cfg_parser_t *pctx, const cfg_obj_t *obj, isc_textregion_t *dst) {
+       if (dst->base != NULL) {
+               INSIST(dst->length != 0);
+               isc_mem_put(pctx->mctx, dst->base, dst->length + 1);
+       }
+       dst->length = obj->value.string.length;
+       dst->base = isc_mem_get(pctx->mctx, dst->length + 1);
+       memmove(dst->base, obj->value.string.base, dst->length);
+       dst->base[dst->length] = '\0';
+}
+
+static void
+free_sockaddrtls(cfg_parser_t *pctx, cfg_obj_t *obj) {
+       if (obj->value.sockaddrtls.tls.base != NULL) {
+               INSIST(obj->value.sockaddrtls.tls.length != 0);
+               isc_mem_put(pctx->mctx, obj->value.sockaddrtls.tls.base,
+                           obj->value.sockaddrtls.tls.length + 1);
+       }
+}
+
 bool
 cfg_obj_isstring(const cfg_obj_t *obj) {
        REQUIRE(obj != NULL);
@@ -3211,9 +3244,11 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
        in_port_t port = 0;
        cfg_obj_t *obj = NULL;
        int have_port = 0;
+       int have_tls = 0;
 
        CHECK(cfg_create_obj(pctx, type, &obj));
        CHECK(cfg_parse_rawaddr(pctx, flags, &netaddr));
+
        for (;;) {
                CHECK(cfg_peektoken(pctx, 0));
                if (pctx->token.type == isc_tokentype_string) {
@@ -3229,6 +3264,17 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
                                CHECK(cfg_gettoken(pctx, 0)); /* read "port" */
                                CHECK(cfg_parse_rawport(pctx, flags, &port));
                                ++have_port;
+                       } else if ((flags & CFG_ADDR_TLSOK) != 0 &&
+                                  strcasecmp(TOKEN_STRING(pctx), "tls") == 0)
+                       {
+                               cfg_obj_t *tls = NULL;
+
+                               CHECK(cfg_gettoken(pctx, 0)); /* read "tls" */
+                               CHECK(cfg_parse_astring(pctx, NULL, &tls));
+                               copy_string(pctx, tls,
+                                           &obj->value.sockaddrtls.tls);
+                               CLEANUP_OBJ(tls);
+                               ++have_tls;
                        } else {
                                break;
                        }
@@ -3236,11 +3282,17 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
                        break;
                }
        }
+
        if (have_port > 1) {
                cfg_parser_error(pctx, 0, "expected at most one port");
                result = ISC_R_UNEXPECTEDTOKEN;
                goto cleanup;
        }
+       if (have_tls > 1) {
+               cfg_parser_error(pctx, 0, "expected at most one tls");
+               result = ISC_R_UNEXPECTEDTOKEN;
+               goto cleanup;
+       }
 
        isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
        *ret = obj;
@@ -3257,6 +3309,12 @@ cfg_type_t cfg_type_sockaddr = { "sockaddr",          cfg_parse_sockaddr,
                                 cfg_print_sockaddr, cfg_doc_sockaddr,
                                 &cfg_rep_sockaddr,  &sockaddr_flags };
 
+static unsigned int sockaddrtls_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK |
+                                       CFG_ADDR_PORTOK | CFG_ADDR_TLSOK;
+cfg_type_t cfg_type_sockaddrtls = { "sockaddrtls",       cfg_parse_sockaddrtls,
+                                   cfg_print_sockaddr,   cfg_doc_sockaddr,
+                                   &cfg_rep_sockaddrtls, &sockaddrtls_flags };
+
 isc_result_t
 cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type,
                   cfg_obj_t **ret) {
@@ -3271,6 +3329,20 @@ cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type,
        return (parse_sockaddrsub(pctx, &cfg_type_sockaddr, *flagp, ret));
 }
 
+isc_result_t
+cfg_parse_sockaddrtls(cfg_parser_t *pctx, const cfg_type_t *type,
+                     cfg_obj_t **ret) {
+       const unsigned int *flagp;
+
+       REQUIRE(pctx != NULL);
+       REQUIRE(type != NULL);
+       REQUIRE(ret != NULL && *ret == NULL);
+
+       flagp = type->of;
+
+       return (parse_sockaddrsub(pctx, &cfg_type_sockaddrtls, *flagp, ret));
+}
+
 void
 cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        isc_netaddr_t netaddr;
@@ -3288,6 +3360,10 @@ cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj) {
                cfg_print_cstr(pctx, " port ");
                cfg_print_rawuint(pctx, port);
        }
+       if (obj->value.sockaddrtls.tls.base != NULL) {
+               cfg_print_cstr(pctx, " tls ");
+               print_rawqstring(pctx, obj->value.sockaddrtls.tls);
+       }
 }
 
 void
@@ -3320,14 +3396,17 @@ cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
                n++;
                POST(n);
        }
-       cfg_print_cstr(pctx, " ) ");
+       cfg_print_cstr(pctx, " )");
        if ((*flagp & CFG_ADDR_PORTOK) != 0) {
                if ((*flagp & CFG_ADDR_WILDOK) != 0) {
-                       cfg_print_cstr(pctx, "[ port ( <integer> | * ) ]");
+                       cfg_print_cstr(pctx, " [ port ( <integer> | * ) ]");
                } else {
-                       cfg_print_cstr(pctx, "[ port <integer> ]");
+                       cfg_print_cstr(pctx, " [ port <integer> ]");
                }
        }
+       if ((*flagp & CFG_ADDR_TLSOK) != 0) {
+               cfg_print_cstr(pctx, " [ tls <string> ]");
+       }
 }
 
 bool
@@ -3336,12 +3415,26 @@ cfg_obj_issockaddr(const cfg_obj_t *obj) {
        return (obj->type->rep == &cfg_rep_sockaddr);
 }
 
+bool
+cfg_obj_issockaddrtls(const cfg_obj_t *obj) {
+       REQUIRE(obj != NULL);
+       return (obj->type->rep == &cfg_rep_sockaddrtls);
+}
+
 const isc_sockaddr_t *
 cfg_obj_assockaddr(const cfg_obj_t *obj) {
-       REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddr);
+       REQUIRE(obj != NULL);
+       REQUIRE(obj->type->rep == &cfg_rep_sockaddr ||
+               obj->type->rep == &cfg_rep_sockaddrtls);
        return (&obj->value.sockaddr);
 }
 
+const char *
+cfg_obj_getsockaddrtls(const cfg_obj_t *obj) {
+       REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddrtls);
+       return (obj->value.sockaddrtls.tls.base);
+}
+
 isc_result_t
 cfg_gettoken(cfg_parser_t *pctx, int options) {
        isc_result_t result;
@@ -3626,12 +3719,10 @@ cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        REQUIRE(ret != NULL && *ret == NULL);
 
        obj = isc_mem_get(pctx->mctx, sizeof(cfg_obj_t));
-
-       obj->type = type;
-       obj->file = current_file(pctx);
-       obj->line = pctx->line;
-       obj->pctx = pctx;
-
+       *obj = (cfg_obj_t){ .type = type,
+                           .file = current_file(pctx),
+                           .line = pctx->line,
+                           .pctx = pctx };
        isc_refcount_init(&obj->references, 1);
 
        *ret = obj;