diff --git a/CHANGES b/CHANGES index d82373c4bc02c1a673419630c116b24c2154e940..34c100c6702f9fec532ff6a0da11632689bbae9f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,18 @@ +5055. [func] A default list of primary servers for the root zone is + now built into named, allowing the "masters" statement + to be omitted when configuring an IANA root zone + mirror. [GL #564] + +5054. [func] Attempts to use mirror zones with recursion disabled + are now considered a configuration error. [GL #564] + +5053. [func] The only valid zone-level NOTIFY settings for mirror + zones are now "notify no;" and "notify explicit;". + [GL #564] + +5052. [func] Mirror zones are now configured using "type mirror;" + rather than "mirror yes;". [GL #564] + 5051. [doc] Documentation incorrectly stated that the "server-addresses" static-stub zone option accepts custom port numbers. [GL #582] diff --git a/bin/named/config.c b/bin/named/config.c index 405197363e59c1db6846c488c3c12e3964660ac9..9ce79bfd57484fba852b3302e1fd81d2864d1a75 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -301,6 +301,21 @@ view \"_bind\" chaos {\n\ MANAGED_KEYS "# END MANAGED KEYS\n\ +\n\ +masters " DEFAULT_IANA_ROOT_ZONE_MASTERS " {\n\ + 2001:500:84::b; # b.root-servers.net\n\ + 2001:500:2f::f; # f.root-servers.net\n\ + 2001:7fd::1; # k.root-servers.net\n\ + 2620:0:2830:202::132; # xfr.cjr.dns.icann.org\n\ + 2620:0:2d0:202::132; # xfr.lax.dns.icann.org\n\ + 192.228.79.201; # b.root-servers.net\n\ + 192.33.4.12; # c.root-servers.net\n\ + 192.5.5.241; # f.root-servers.net\n\ + 192.112.36.4; # g.root-servers.net\n\ + 193.0.14.129; # k.root-servers.net\n\ + 192.0.47.132; # xfr.cjr.dns.icann.org\n\ + 192.0.32.132; # xfr.lax.dns.icann.org\n\ +};\n\ "; isc_result_t @@ -432,6 +447,8 @@ named_config_getzonetype(const cfg_obj_t *zonetypeobj) { strcasecmp(str, "slave") == 0) { ztype = dns_zone_slave; + } else if (strcasecmp(str, "mirror") == 0) { + ztype = dns_zone_mirror; } else if (strcasecmp(str, "stub") == 0) { ztype = dns_zone_stub; } else if (strcasecmp(str, "static-stub") == 0) { @@ -553,9 +570,9 @@ named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, } } -static isc_result_t -get_masters_def(const cfg_obj_t *cctx, const char *name, - const cfg_obj_t **ret) +isc_result_t +named_config_getmastersdef(const cfg_obj_t *cctx, const char *name, + const cfg_obj_t **ret) { isc_result_t result; const cfg_obj_t *masters = NULL; @@ -697,7 +714,8 @@ named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, break; if (j < l) continue; - tresult = get_masters_def(config, listname, &list); + tresult = named_config_getmastersdef(config, listname, + &list); if (tresult == ISC_R_NOTFOUND) { cfg_obj_log(addr, named_g_lctx, ISC_LOG_ERROR, "masters \"%s\" not found", listname); diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h index ad69a1624819f26df9961daab7c1773e0cc3f075..a3e3ae241da2a50aa9965f5f4f5a4ba6be159529 100644 --- a/bin/named/include/named/config.h +++ b/bin/named/include/named/config.h @@ -22,6 +22,8 @@ #include #include +#define DEFAULT_IANA_ROOT_ZONE_MASTERS "_default_iana_root_zone_masters" + isc_result_t named_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf); @@ -57,6 +59,10 @@ void named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, uint32_t count); +isc_result_t +named_config_getmastersdef(const cfg_obj_t *cctx, const char *name, + const cfg_obj_t **ret); + isc_result_t named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_mem_t *mctx, dns_ipkeylist_t *ipkl); diff --git a/bin/named/named.conf.5 b/bin/named/named.conf.5 index 61048326819a005e505f732a10c1a02b5f86577f..8d109a00b9fe1bb96d2c6d4b49f44d951119fb3f 100644 --- a/bin/named/named.conf.5 +++ b/bin/named/named.conf.5 @@ -884,7 +884,6 @@ view \fIstring\fR [ \fIclass\fR ] { max\-zone\-ttl ( unlimited | \fIttlval\fR ); min\-refresh\-time \fIinteger\fR; min\-retry\-time \fIinteger\fR; - mirror \fIboolean\fR; multi\-master \fIboolean\fR; notify ( explicit | master\-only | \fIboolean\fR ); notify\-delay \fIinteger\fR; @@ -910,7 +909,7 @@ view \fIstring\fR [ \fIclass\fR ] { transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; try\-tcp\-refresh \fIboolean\fR; - type ( primary | master | secondary | slave | + type ( primary | master | secondary | slave | mirror | delegation\-only | forward | hint | redirect | static\-stub | stub ); update\-check\-ksk \fIboolean\fR; @@ -993,7 +992,6 @@ zone \fIstring\fR [ \fIclass\fR ] { max\-zone\-ttl ( unlimited | \fIttlval\fR ); min\-refresh\-time \fIinteger\fR; min\-retry\-time \fIinteger\fR; - mirror \fIboolean\fR; multi\-master \fIboolean\fR; notify ( explicit | master\-only | \fIboolean\fR ); notify\-delay \fIinteger\fR; @@ -1017,8 +1015,9 @@ zone \fIstring\fR [ \fIclass\fR ] { transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; try\-tcp\-refresh \fIboolean\fR; - type ( primary | master | secondary | slave | delegation\-only | - forward | hint | redirect | static\-stub | stub ); + type ( primary | master | secondary | slave | mirror | + delegation\-only | forward | hint | redirect | static\-stub | + stub ); update\-check\-ksk \fIboolean\fR; update\-policy ( local | { ( deny | grant ) \fIstring\fR ( 6to4\-self | external | krb5\-self | krb5\-subdomain | ms\-self | ms\-subdomain diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index 49aa2104f9b61dc3dd698e7410952e99461c1c96..01dc81be6c9aa2ea168cb77dfffbce443fb5983d 100644 --- a/bin/named/named.conf.docbook +++ b/bin/named/named.conf.docbook @@ -341,7 +341,6 @@ options { min-retry-time integer; minimal-any boolean; minimal-responses ( no-auth | no-auth-recursive | boolean ); - mirror boolean; multi-master boolean; new-zones-directory quoted_string; no-case-compress { address_match_element; ... }; @@ -673,7 +672,6 @@ view string [ class ] { min-retry-time integer; minimal-any boolean; minimal-responses ( no-auth | no-auth-recursive | boolean ); - mirror boolean; multi-master boolean; new-zones-directory quoted_string; no-case-compress { address_match_element; ... }; @@ -864,7 +862,6 @@ view string [ class ] { max-zone-ttl ( unlimited | ttlval ); min-refresh-time integer; min-retry-time integer; - mirror boolean; multi-master boolean; notify ( explicit | master-only | boolean ); notify-delay integer; @@ -890,7 +887,7 @@ view string [ class ] { transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; try-tcp-refresh boolean; - type ( primary | master | secondary | slave | + type ( primary | master | secondary | slave | mirror | delegation-only | forward | hint | redirect | static-stub | stub ); update-check-ksk boolean; @@ -969,7 +966,6 @@ zone string [ class ] { max-zone-ttl ( unlimited | ttlval ); min-refresh-time integer; min-retry-time integer; - mirror boolean; multi-master boolean; notify ( explicit | master-only | boolean ); notify-delay integer; @@ -993,8 +989,9 @@ zone string [ class ] { transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; try-tcp-refresh boolean; - type ( primary | master | secondary | slave | delegation-only | - forward | hint | redirect | static-stub | stub ); + type ( primary | master | secondary | slave | mirror | + delegation-only | forward | hint | redirect | static-stub | + stub ); update-check-ksk boolean; update-policy ( local | { ( deny | grant ) string ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self diff --git a/bin/named/named.conf.html b/bin/named/named.conf.html index 7169f14cebdcb62297a0b17b571380d567cd8e11..a5b2ccd7022b9e97fd01a96e534bc55dda8d638a 100644 --- a/bin/named/named.conf.html +++ b/bin/named/named.conf.html @@ -853,7 +853,6 @@ view max-zone-ttl ( unlimited | ttlval );
min-refresh-time integer;
min-retry-time integer;
- mirror boolean;
multi-master boolean;
notify ( explicit | master-only | boolean );
notify-delay integer;
@@ -879,7 +878,7 @@ view transfer-source-v6 ( ipv6_address | * ) [ port (
    integer | * ) ] [ dscp integer ];
try-tcp-refresh boolean;
- type ( primary | master | secondary | slave |
+ type ( primary | master | secondary | slave | mirror |
    delegation-only | forward | hint | redirect |
    static-stub | stub );
update-check-ksk boolean;
@@ -959,7 +958,6 @@ zone max-zone-ttl ( unlimited | ttlval );
min-refresh-time integer;
min-retry-time integer;
- mirror boolean;
multi-master boolean;
notify ( explicit | master-only | boolean );
notify-delay integer;
@@ -983,8 +981,9 @@ zone transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
try-tcp-refresh boolean;
- type ( primary | master | secondary | slave | delegation-only |
-     forward | hint | redirect | static-stub | stub );
+ type ( primary | master | secondary | slave | mirror |
+     delegation-only | forward | hint | redirect | static-stub |
+     stub );
update-check-ksk boolean;
update-policy ( local | { ( deny | grant ) string ( 6to4-self |
    external | krb5-self | krb5-subdomain | ms-self | ms-subdomain
diff --git a/bin/named/server.c b/bin/named/server.c index 1fc81d8991e2c4df8a21ac897b612e83295fc8cf..0c6224fd845ca97af93027d8f792f288b0cb5b4b 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -6978,6 +6978,9 @@ removed(dns_zone_t *zone, void *uap) { case dns_zone_slave: type = "slave"; break; + case dns_zone_mirror: + type = "mirror"; + break; case dns_zone_stub: type = "stub"; break; @@ -10162,7 +10165,8 @@ named_server_retransfercommand(named_server_t *server, isc_lex_t *lex, dns_zone_detach(&raw); } type = dns_zone_gettype(zone); - if (type == dns_zone_slave || type == dns_zone_stub || + if (type == dns_zone_slave || type == dns_zone_mirror || + type == dns_zone_stub || (type == dns_zone_redirect && dns_zone_getredirecttype(zone) == dns_zone_slave)) dns_zone_forcereload(zone); @@ -10194,7 +10198,9 @@ named_server_reloadcommand(named_server_t *server, isc_lex_t *lex, msg = "server reload successful"; } else { type = dns_zone_gettype(zone); - if (type == dns_zone_slave || type == dns_zone_stub) { + if (type == dns_zone_slave || type == dns_zone_mirror || + type == dns_zone_stub) + { dns_zone_refresh(zone); dns_zone_detach(&zone); msg = "zone refresh queued"; @@ -10285,7 +10291,7 @@ named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, isc_result_t result; dns_zone_t *zone = NULL, *raw = NULL; const char msg1[] = "zone refresh queued"; - const char msg2[] = "not a slave or stub zone"; + const char msg2[] = "not a slave, mirror, or stub zone"; dns_zonetype_t type; result = zone_from_args(server, lex, NULL, &zone, NULL, @@ -10303,7 +10309,9 @@ named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, } type = dns_zone_gettype(zone); - if (type == dns_zone_slave || type == dns_zone_stub) { + if (type == dns_zone_slave || type == dns_zone_mirror || + type == dns_zone_stub) + { dns_zone_refresh(zone); dns_zone_detach(&zone); (void) putstr(text, msg1); @@ -13495,6 +13503,7 @@ named_server_delzone(named_server_t *server, isc_lex_t *lex, TCHECK(putstr(text, zonename)); TCHECK(putstr(text, "' and associated files will be deleted.")); } else if (dns_zone_gettype(mayberaw) == dns_zone_slave || + dns_zone_gettype(mayberaw) == dns_zone_mirror || dns_zone_gettype(mayberaw) == dns_zone_stub) { bool first; @@ -14037,7 +14046,10 @@ named_server_zonestatus(named_server_t *server, isc_lex_t *lex, type = "master"; break; case dns_zone_slave: - type = dns_zone_ismirror(zone) ? "mirror" : "slave"; + type = "slave"; + break; + case dns_zone_mirror: + type = "mirror"; break; case dns_zone_stub: type = "stub"; @@ -14093,6 +14105,7 @@ named_server_zonestatus(named_server_t *server, isc_lex_t *lex, /* Refresh/expire times */ if (zonetype == dns_zone_slave || + zonetype == dns_zone_mirror || zonetype == dns_zone_stub || zonetype == dns_zone_redirect) { diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index 79d66d8e01234515a43c3c25d0a04706f16af281..bd8d1c58ce33fcc93d0edd91cdbc61aefd9ca2f2 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -94,6 +94,7 @@ user_zonetype( dns_zone_t *zone ) { { dns_zone_none, "none" }, { dns_zone_master, "master" }, { dns_zone_slave, "slave" }, + { dns_zone_mirror, "mirror" }, { dns_zone_stub, "stub" }, { dns_zone_staticstub, "static-stub" }, { dns_zone_key, "key" }, diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 85e5421fd27bd1761ab898907f3db48c20809fd3..52264239e09a8b4884d22853a815bd0c4343041e 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -755,8 +755,13 @@ checknames(dns_zonetype_t ztype, const cfg_obj_t **maps, isc_result_t result; switch (ztype) { - case dns_zone_slave: zone = "slave"; break; - case dns_zone_master: zone = "master"; break; + case dns_zone_slave: + case dns_zone_mirror: + zone = "slave"; + break; + case dns_zone_master: + zone = "master"; + break; default: INSIST(0); } @@ -828,6 +833,37 @@ isself(dns_view_t *myview, dns_tsigkey_t *mykey, return (view == myview); } +/*% + * For mirror zones, change "notify yes;" to "notify explicit;", informing the + * user only if "notify" was explicitly configured rather than inherited from + * default configuration. + */ +static dns_notifytype_t +process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype, + const char *zname, const cfg_obj_t **maps) +{ + const cfg_obj_t *obj = NULL; + + /* + * Return the original setting if this is not a mirror zone or if the + * zone is configured with something else than "notify yes;". + */ + if (ztype != dns_zone_mirror || ntype != dns_notifytype_yes) { + return (ntype); + } + + /* + * Only log a message if "notify" was set in the configuration + * hierarchy supplied in 'maps'. + */ + if (named_config_get(maps, "notify", &obj) == ISC_R_SUCCESS) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, + "'notify explicit;' will be used for mirror zone " + "'%s'", zname); + } + + return (dns_notifytype_explicit); +} isc_result_t named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, @@ -982,7 +1018,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, return (ISC_R_FAILURE); } - if (ztype == dns_zone_slave) + if (ztype == dns_zone_slave || ztype == dns_zone_mirror) masterformat = dns_masterformat_raw; else masterformat = dns_masterformat_text; @@ -1076,7 +1112,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, /* * Notify messages are processed by the raw zone if it exists. */ - if (ztype == dns_zone_slave) + if (ztype == dns_zone_slave || ztype == dns_zone_mirror) RETERR(configure_zone_acl(zconfig, vconfig, config, allow_notify, ac, mayberaw, dns_zone_setnotifyacl, @@ -1182,6 +1218,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, else INSIST(0); } + notifytype = process_notifytype(notifytype, ztype, zname, + nodefault); if (raw != NULL) dns_zone_setnotifytype(raw, dns_notifytype_no); dns_zone_setnotifytype(zone, notifytype); @@ -1537,7 +1575,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, } } - if (ztype == dns_zone_slave) { + if (ztype == dns_zone_slave || ztype == dns_zone_mirror) { RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update_forwarding, ac, mayberaw, dns_zone_setforwardacl, @@ -1695,12 +1733,38 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, * Configure slave functionality. */ switch (ztype) { + case dns_zone_mirror: + /* + * Disable outgoing zone transfers for mirror zones unless they + * are explicitly enabled by zone configuration. + */ + obj = NULL; + (void)cfg_map_get(zoptions, "allow-transfer", &obj); + if (obj == NULL) { + dns_acl_t *none; + RETERR(dns_acl_none(mctx, &none)); + dns_zone_setxfracl(zone, none); + dns_acl_detach(&none); + } + /* FALLTHROUGH */ case dns_zone_slave: case dns_zone_stub: case dns_zone_redirect: count = 0; obj = NULL; (void)cfg_map_get(zoptions, "masters", &obj); + /* + * Use the built-in master server list if one was not + * explicitly specified and this is a root zone mirror. + */ + if (obj == NULL && ztype == dns_zone_mirror && + dns_name_equal(dns_zone_getorigin(zone), dns_rootname)) + { + result = named_config_getmastersdef(named_g_config, + DEFAULT_IANA_ROOT_ZONE_MASTERS, + &obj); + RETERR(result); + } if (obj != NULL) { dns_ipkeylist_t ipkl; dns_ipkeylist_init(&ipkl); @@ -1727,35 +1791,6 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, } dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi); - obj = NULL; - (void)cfg_map_get(zoptions, "mirror", &obj); - if (obj != NULL) { - bool mirror = cfg_obj_asboolean(obj); - dns_zone_setoption(mayberaw, DNS_ZONEOPT_MIRROR, - mirror); - if (mirror) { - /* - * Disable outgoing zone transfers unless they - * are explicitly enabled by zone - * configuration. - */ - obj = NULL; - (void)cfg_map_get(zoptions, "allow-transfer", - &obj); - if (obj == NULL) { - dns_acl_t *none; - RETERR(dns_acl_none(mctx, &none)); - dns_zone_setxfracl(zone, none); - dns_acl_detach(&none); - } - /* - * Only allow "also-notify". - */ - notifytype = dns_notifytype_explicit; - dns_zone_setnotifytype(zone, notifytype); - } - } - obj = NULL; result = named_config_get(maps, "max-transfer-time-in", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); @@ -1895,7 +1930,7 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { const char *cfilename; const char *zfilename; dns_zone_t *raw = NULL; - bool has_raw, mirror; + bool has_raw; dns_zonetype_t ztype; zoptions = cfg_tuple_get(zconfig, "options"); @@ -1935,21 +1970,6 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { return (false); } - /* - * Do not reuse a zone whose "mirror" setting was changed. - */ - obj = NULL; - mirror = false; - (void)cfg_map_get(zoptions, "mirror", &obj); - if (obj != NULL) { - mirror = cfg_obj_asboolean(obj); - } - if (dns_zone_ismirror(zone) != mirror) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "not reusable: mirror setting changed"); - return (false); - } - if (zonetype_fromconfig(zoptions) != ztype) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "not reusable: type mismatch"); diff --git a/bin/tests/cfg_test.c b/bin/tests/cfg_test.c index 4d01e410560486254050c9769b695731798f56b6..0c8e1a7940d358b7a4aa389377e7100a07775624 100644 --- a/bin/tests/cfg_test.c +++ b/bin/tests/cfg_test.c @@ -115,6 +115,8 @@ main(int argc, char **argv) { strcmp(argv[1], "seconary") == 0) { zonetype = CFG_ZONE_SLAVE; + } else if (strcmp(argv[1], "mirror") == 0) { + zonetype = CFG_ZONE_MIRROR; } else if (strcmp(argv[1], "stub") == 0) { zonetype = CFG_ZONE_STUB; } else if (strcmp(argv[1], "static-stub") == 0) { diff --git a/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf b/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf new file mode 100644 index 0000000000000000000000000000000000000000..9dabf8897ee4062b74e58d1ba57eb2539fc2b0ab --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + recursion yes; + allow-recursion { none; }; +}; + +zone "." { + type mirror; + masters { 127.0.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf b/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf new file mode 100644 index 0000000000000000000000000000000000000000..8d5b28a792f6310fd140cae7d455e6d5a0873896 --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf @@ -0,0 +1,15 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type mirror; + notify yes; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf b/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf new file mode 100644 index 0000000000000000000000000000000000000000..e212bed6ac367c7125e41e6d6c883b18731d19b5 --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "foo." { + type mirror; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-recursion-no.conf b/bin/tests/system/checkconf/bad-mirror-recursion-no.conf new file mode 100644 index 0000000000000000000000000000000000000000..9b02f0dcb764a21a72d9597a39444db30b123ecc --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-recursion-no.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + recursion no; +}; + +zone "." { + type mirror; +}; diff --git a/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf b/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf new file mode 100644 index 0000000000000000000000000000000000000000..241a77ca0cfcdf054ad33fc48d55ab0237d83601 --- /dev/null +++ b/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + notify yes; +}; + +zone "." { + type mirror; +}; diff --git a/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf b/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf new file mode 100644 index 0000000000000000000000000000000000000000..1b7a1cdd6f3994b2325eea8ec43d41152e9e921d --- /dev/null +++ b/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type mirror; +}; diff --git a/bin/tests/system/mirror/README b/bin/tests/system/mirror/README new file mode 100644 index 0000000000000000000000000000000000000000..1cb7bdd422c37af341d5131ee4922d676d7fca56 --- /dev/null +++ b/bin/tests/system/mirror/README @@ -0,0 +1,17 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +See COPYRIGHT in the source root or http://isc.org/copyright.html for terms. + +This test checks whether zones configured with "type mirror;" behave as +expected. + +ns1 is an authoritative-only server. It only serves the root zone, which is +mirrored by ns3. + +ns2 is an authoritative-only server. It serves a number of zones, some of which +are delegated to it by ns1 and used in recursive resolution tests aimed at ns3 +while others are only served so that ns3 has a primary server to mirror zones +from during various tests of the mirror zone implementation. + +ns3 is a recursive resolver. It has a number of mirror zones configured. This +is the only server whose behavior is being examined by this system test. diff --git a/bin/tests/system/mirror/clean.sh b/bin/tests/system/mirror/clean.sh index fc189a86044ff83d369757342c668baa0cdfb88a..99ee2ae020cffddb7ec48770b84f40599c2e6234 100644 --- a/bin/tests/system/mirror/clean.sh +++ b/bin/tests/system/mirror/clean.sh @@ -11,6 +11,7 @@ rm -f */*.conf rm -f */*.db rm -f */*.jnl rm -f */*.mirror +rm -f */*.nzd* rm -f */*.prev rm -f */*.signed rm -f */K* diff --git a/bin/tests/system/mirror/ns2/named.conf.in b/bin/tests/system/mirror/ns2/named.conf.in index ebcce5729aabb2b0e6d5864561d131c04c186ce9..2979ea9980540c2cea276a0f85f5914a24bd504e 100644 --- a/bin/tests/system/mirror/ns2/named.conf.in +++ b/bin/tests/system/mirror/ns2/named.conf.in @@ -45,6 +45,11 @@ zone "initially-unavailable" { allow-transfer { 10.53.0.254; }; }; +zone "verify-addzone" { + type master; + file "verify-addzone.db.original.signed"; +}; + zone "verify-axfr" { type master; file "verify-axfr.db.signed"; diff --git a/bin/tests/system/mirror/ns2/sign.sh b/bin/tests/system/mirror/ns2/sign.sh index e8239b14e034bfc2fe7a8642e288d7a9a3f347a4..57df68db1b405599da1f2005bde48fe9167f5fa1 100644 --- a/bin/tests/system/mirror/ns2/sign.sh +++ b/bin/tests/system/mirror/ns2/sign.sh @@ -36,7 +36,7 @@ ORIGINAL_SERIAL=`awk '$2 == "SOA" {print $5}' verify.db.in` UPDATED_SERIAL_BAD=`expr ${ORIGINAL_SERIAL} + 1` UPDATED_SERIAL_GOOD=`expr ${ORIGINAL_SERIAL} + 2` -for variant in axfr ixfr load reconfig untrusted; do +for variant in addzone axfr ixfr load reconfig untrusted; do zone=verify-$variant infile=verify.db.in zonefile=verify-$variant.db diff --git a/bin/tests/system/mirror/ns3/named.conf.in b/bin/tests/system/mirror/ns3/named.conf.in index 9eec0acf8931d2b77ed67eb2c8167f806faab6c2..edf6a21702933a186f22859b144bc7b977d8ff23 100644 --- a/bin/tests/system/mirror/ns3/named.conf.in +++ b/bin/tests/system/mirror/ns3/named.conf.in @@ -29,6 +29,7 @@ options { recursion yes; allow-query-cache { 10.53.0.1; }; trust-anchor-telemetry yes; + allow-new-zones yes; }; zone "." { @@ -37,62 +38,54 @@ zone "." { }; zone "." { - type slave; + type mirror; masters { 10.53.0.1; }; - mirror yes; file "root.db.mirror"; }; zone "initially-unavailable" { - type slave; + type mirror; masters { 10.53.0.2; }; - mirror yes; file "initially-unavailable.db.mirror"; use-alt-transfer-source no; }; zone "verify-axfr" { - type slave; + type mirror; masters { 10.53.0.2; }; - mirror yes; file "verify-axfr.db.mirror"; }; zone "verify-ixfr" { - type slave; + type mirror; masters { 10.53.0.2; }; - mirror yes; file "verify-ixfr.db.mirror"; masterfile-format text; }; zone "verify-load" { - type slave; + type mirror; masters { 10.53.0.2; }; - mirror yes; file "verify-load.db.mirror"; masterfile-format text; }; zone "verify-reconfig" { - type slave; + type mirror; masters { 10.53.0.2; }; - mirror yes; file "verify-reconfig.db.mirror"; masterfile-format text; }; zone "verify-unsigned" { - type slave; + type mirror; masters { 10.53.0.2; }; - mirror yes; file "verify-unsigned.db.mirror"; }; zone "verify-untrusted" { - type slave; + type mirror; masters { 10.53.0.2; }; - mirror yes; file "verify-untrusted.db.mirror"; }; diff --git a/bin/tests/system/mirror/setup.sh b/bin/tests/system/mirror/setup.sh index 4a1413dfa19ca0640ada193ecf0f9426275e4ea6..da8161767595ed64ee27c9cbc8c21308c5bc9bb8 100644 --- a/bin/tests/system/mirror/setup.sh +++ b/bin/tests/system/mirror/setup.sh @@ -21,6 +21,4 @@ copy_setports ns3/named.conf.in ns3/named.conf ( cd ns1 && $SHELL -e sign.sh ) cat ns2/verify-axfr.db.bad.signed > ns2/verify-axfr.db.signed -cat ns2/verify-ixfr.db.original.signed > ns2/verify-ixfr.db.signed cat ns2/verify-load.db.bad.signed > ns3/verify-load.db.mirror -cat ns2/verify-untrusted.db.original.signed > ns2/verify-untrusted.db.signed diff --git a/bin/tests/system/mirror/tests.sh b/bin/tests/system/mirror/tests.sh index 73b01f7ae4011b986c0507a42851f016087f9621..8411857d0d569ba5f2ebb1dd93aa254e1a7c3526 100644 --- a/bin/tests/system/mirror/tests.sh +++ b/bin/tests/system/mirror/tests.sh @@ -380,7 +380,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo_i "checking that \"rndc reconfig\" properly handles a yes -> no \"mirror\" setting change ($n)" +echo_i "checking that \"rndc reconfig\" properly handles a mirror -> slave zone type change ($n)" ret=0 # Sanity check before we start. $DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n.1 2>&1 || ret=1 @@ -390,13 +390,13 @@ grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1 # Reconfigure the zone so that it is no longer a mirror zone. # (NOTE: Keep the embedded newline in the sed function list below.) sed '/^zone "verify-reconfig" {$/,/^};$/ { - s/mirror yes;/mirror no;/ + s/type mirror;/type slave;/ }' ns3/named.conf > ns3/named.conf.modified mv ns3/named.conf.modified ns3/named.conf nextpart ns3/named.run > /dev/null $RNDCCMD 10.53.0.3 reconfig > /dev/null 2>&1 -# Zones whose "mirror" setting was changed should not be reusable, which means -# the tested zone should have been reloaded from disk. +# Zones whose type was changed should not be reusable, which means the tested +# zone should have been reloaded from disk. wait_for_load verify-reconfig ${ORIGINAL_SERIAL} ns3/named.run # Ensure responses sourced from the reconfigured zone have AA=1 and AD=0. $DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n.2 2>&1 || ret=1 @@ -407,7 +407,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo_i "checking that \"rndc reconfig\" properly handles a no -> yes \"mirror\" setting change ($n)" +echo_i "checking that \"rndc reconfig\" properly handles a slave -> mirror zone type change ($n)" ret=0 # Put an incorrectly signed version of the zone in the zone file used by ns3. nextpart ns3/named.run > /dev/null @@ -415,7 +415,7 @@ cat ns2/verify-reconfig.db.bad.signed > ns3/verify-reconfig.db.mirror # Reconfigure the zone so that it is a mirror zone again. # (NOTE: Keep the embedded newline in the sed function list below.) sed '/^zone "verify-reconfig" {$/,/^};$/ { - s/mirror no;/mirror yes;/ + s/type slave;/type mirror;/ }' ns3/named.conf > ns3/named.conf.modified mv ns3/named.conf.modified ns3/named.conf $RNDCCMD 10.53.0.3 reconfig > /dev/null 2>&1 @@ -427,6 +427,39 @@ nextpart ns3/named.run | grep "No correct RSASHA256 signature for verify-reconfi if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` +n=`expr $n + 1` +echo_i "checking that a mirror zone can be added using rndc ($n)" +ret=0 +# Sanity check: the zone should not exist in the root zone. +$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n.1 2>&1 || ret=1 +grep "NXDOMAIN" dig.out.ns3.test$n.1 > /dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n.1 > /dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1 +# Mirror a zone which does not exist in the root zone. +nextpart ns3/named.run > /dev/null +$RNDCCMD 10.53.0.3 addzone verify-addzone '{ type mirror; masters { 10.53.0.2; }; };' > rndc.out.ns3.test$n 2>&1 || ret=1 +wait_for_transfer verify-addzone +# Check whether the mirror zone was added and whether it behaves as expected. +$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n.2 2>&1 || ret=1 +grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n.2 > /dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.2 > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "checking that a mirror zone can be deleted using rndc ($n)" +ret=0 +# Remove the mirror zone added in the previous test. +$RNDCCMD 10.53.0.3 delzone verify-addzone > rndc.out.ns3.test$n 2>&1 || ret=1 +# Check whether the mirror zone was removed. +$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n 2>&1 || ret=1 +grep "NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n > /dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + n=`expr $n + 1` echo_i "ensuring trust anchor telemetry queries are sent upstream for a mirror zone ($n)" ret=0 diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 02d933c7f616ce3a45c18bc4c554fb07a4b949f5..c2c5e4f43fbceebb12492c365900c1fc78a35038 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -7317,8 +7317,8 @@ options { - - allow-transfer + + allow-transfer Specifies which hosts are allowed to @@ -11410,6 +11410,7 @@ view "external" { + @@ -11429,6 +11430,7 @@ view "external" { acceptable values include: master (or primary), slave (or secondary), + mirror, delegation-only, forward, hint, @@ -11565,6 +11567,97 @@ view "external" { + + + + mirror + + + + + + + A mirror zone acts like a zone of type + secondary whose data is + subject to DNSSEC validation before being used + in answers. Validation is performed during the + zone transfer process, and again when the zone + file is loaded from disk when + named is restarted. If + validation fails, a retransfer of the zone is + scheduled; if the mirror zone had not previously + been loaded or if the previous version has + expired, traditional DNS recursion will be used + to look up the answers instead. + + + For validation to succeed, a key-signing key + (KSK) for the zone must be configured as a trust + anchor in named.conf: that + is, a key for the zone must either be specified + in managed-keys or + trusted-keys, or in the case + of the root zone, + dnssec-validation must be set + to auto. Answers coming + from a mirror zone look almost exactly like + answers from a zone of type + secondary, with the + notable exceptions that the AA bit + ("authoritative answer") is not set, and the AD + bit ("authenticated data") is. + + + Since mirror zones are intended to be used by + recursive resolvers, adding one to a view with + recursion disabled is considered to be a + configuration error. + + + When configuring NOTIFY for a mirror zone, only + notify no; and + notify explicit; can be + used. Using any other + notify setting at the + zone level is a configuration error. Using any + other notify setting at + the options or + view level will cause + that setting to be overridden with + notify explicit; for the + mirror zone in question. + + + Outgoing transfers of mirror zones are disabled + by default but may be enabled using + . + + + While any zone may be configured with this type, + it is intended to be used to set up a fast local + copy of the root zone, similar to the one + described in RFC 7706. Note, however, that + mirror zones are not supposed to augment the + example configuration provided by RFC 7706 but + rather to replace it altogether. + + + A default list of primary servers for the root + zone is built into named and + thus IANA root zone mirroring can be enabled + using the following configuration: + +zone "." { + type mirror; +}; + + To make mirror zone contents persist between + named restarts, use the + + option. + + + @@ -12067,19 +12160,20 @@ view "external" { - - file + + file Set the zone's filename. In master, hint, and redirect zones which do not have masters defined, zone data is loaded from this file. In - slave, stub, and - redirect zones which do have - masters defined, zone data is - retrieved from another server and saved in this file. - This option is not applicable to other zone types. + slave, mirror, + stub, and redirect + zones which do have masters + defined, zone data is retrieved from another server + and saved in this file. This option is not + applicable to other zone types. @@ -12524,68 +12618,6 @@ example.com. NS ns2.example.net. - - mirror - - - If set to yes, this causes the - zone to become a mirror zone. A mirror zone is a - secondary zone whose data - is subject to DNSSEC validation before being - used in answers. The default is - no. - - - A mirror zone's contents are validated during the transfer - process, and again when the zone file is loaded from disk - when named is restarted. If validation - fails, a retransfer of the zone is scheduled; if the mirror - zone had not previously been loaded or if the previous - version has expired, traditional DNS recursion will be used - to look up the answers instead. - - - For validation to succeed, a key-signing key (KSK) for - the zone must be configured as a trust anchor in - named.conf: - that is, a key for the zone must either be specified in - managed-keys or - trusted-keys, or in the case of - the root zone, dnssec-validation - must be set to auto. - Answers coming from a mirror zone look almost exactly like - answers from a normal slave zone, with the notable - exceptions that the AA bit ("authoritative answer") is - not set, and the AD bit ("authenticated data") is. - - - Though this option can be used for other zones, it - is intended to be used to set up a fast local copy of - the root zone, as described in RFC 7706. - This can be done by using the following configuration: - -zone "." { - type slave; - mirror yes; - file "root.mirror"; - masters { - 192.228.79.201; # b.root-servers.net - 192.33.4.12; # c.root-servers.net - 192.5.5.241; # f.root-servers.net - 192.112.36.4; # g.root-servers.net - 193.0.14.129; # k.root-servers.net - 192.0.47.132; # xfr.cjr.dns.icann.org - 192.0.32.132; # xfr.lax.dns.icann.org - 2001:500:84::b; # b.root-servers.net - 2001:500:2f::f; # f.root-servers.net - 2001:7fd::1; # k.root-servers.net - 2620:0:2830:202::132; # xfr.cjr.dns.icann.org - 2620:0:2d0:202::132; # xfr.lax.dns.icann.org - }; -}; - - - multi-master diff --git a/doc/arm/Bv9ARM.ch05.html b/doc/arm/Bv9ARM.ch05.html index 36939a6ea3c40c5fee7a67b92d75460eea71f978..401f9f204c7e699cc6d89471e5e2450c9981ac88 100644 --- a/doc/arm/Bv9ARM.ch05.html +++ b/doc/arm/Bv9ARM.ch05.html @@ -2531,7 +2531,6 @@ badresp:1,adberr:0,findfail:0,valfail:0] min-retry-time integer; minimal-any boolean; minimal-responses ( no-auth | no-auth-recursive | boolean ); - mirror boolean; multi-master boolean; new-zones-directory quoted_string; no-case-compress { address_match_element; ... }; @@ -5369,7 +5368,9 @@ options { It is now ignored with some warning messages.

-
allow-transfer
+
+allow-transfer +

Specifies which hosts are allowed to @@ -9398,7 +9399,6 @@ view "external" { max-transfer-time-out integer; min-refresh-time integer; min-retry-time integer; - mirror boolean; multi-master boolean; notify ( explicit | master-only | boolean ); notify-delay integer; @@ -9421,6 +9421,50 @@ view "external" { };

+zone string [ class ] {
+	type mirror;
+	allow-notify { address_match_element; ... };
+	allow-query { address_match_element; ... };
+	allow-query-on { address_match_element; ... };
+	allow-transfer { address_match_element; ... };
+	allow-update-forwarding { address_match_element; ... };
+	also-notify [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... };
+	alt-transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ];
+	alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ];
+	check-names ( fail | warn | ignore );
+	database string;
+	file quoted_string;
+	ixfr-from-differences boolean;
+	journal quoted_string;
+	masterfile-format ( map | raw | text );
+	masterfile-style ( full | relative );
+	masters [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... };
+	max-journal-size ( default | unlimited | sizeval );
+	max-records integer;
+	max-refresh-time integer;
+	max-retry-time integer;
+	max-transfer-idle-in integer;
+	max-transfer-idle-out integer;
+	max-transfer-time-in integer;
+	max-transfer-time-out integer;
+	min-refresh-time integer;
+	min-retry-time integer;
+	multi-master boolean;
+	notify ( explicit | master-only | boolean );
+	notify-delay integer;
+	notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ];
+	notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ];
+	request-expire boolean;
+	request-ixfr boolean;
+	transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ];
+	transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ];
+	try-tcp-refresh boolean;
+	use-alt-transfer-source boolean;
+	zero-no-soa-ttl boolean;
+	zone-statistics ( full | terse | none | boolean );
+};
+
+
 zone string [ class ] {
 	type hint;
 	check-names ( fail | warn | ignore );
@@ -9519,6 +9563,7 @@ view "external" {
               acceptable values include:
               master (or primary),
               slave (or secondary),
+              mirror,
               delegation-only,
               forward,
               hint,
@@ -9656,6 +9701,97 @@ view "external" {
                     
 
 
+
+                      

+ mirror +

+ + +

+

+

+ A mirror zone acts like a zone of type + secondary whose data is + subject to DNSSEC validation before being used + in answers. Validation is performed during the + zone transfer process, and again when the zone + file is loaded from disk when + named is restarted. If + validation fails, a retransfer of the zone is + scheduled; if the mirror zone had not previously + been loaded or if the previous version has + expired, traditional DNS recursion will be used + to look up the answers instead. +

+

+ For validation to succeed, a key-signing key + (KSK) for the zone must be configured as a trust + anchor in named.conf: that + is, a key for the zone must either be specified + in managed-keys or + trusted-keys, or in the case + of the root zone, + dnssec-validation must be set + to auto. Answers coming + from a mirror zone look almost exactly like + answers from a zone of type + secondary, with the + notable exceptions that the AA bit + ("authoritative answer") is not set, and the AD + bit ("authenticated data") is. +

+

+ Since mirror zones are intended to be used by + recursive resolvers, adding one to a view with + recursion disabled is considered to be a + configuration error. +

+

+ When configuring NOTIFY for a mirror zone, only + notify no; and + notify explicit; can be + used. Using any other + notify setting at the + zone level is a configuration error. Using any + other notify setting at + the options or + view level will cause + that setting to be overridden with + notify explicit; for the + mirror zone in question. +

+

+ Outgoing transfers of mirror zones are disabled + by default but may be enabled using + allow-transfer. +

+

+ While any zone may be configured with this type, + it is intended to be used to set up a fast local + copy of the root zone, similar to the one + described in RFC 7706. Note, however, that + mirror zones are not supposed to augment the + example configuration provided by RFC 7706 but + rather to replace it altogether. +

+

+ A default list of primary servers for the root + zone is built into named and + thus IANA root zone mirroring can be enabled + using the following configuration: +

+
zone "." {
+        type mirror;
+};
+

+ To make mirror zone contents persist between + named restarts, use the + file + option. +

+ + +

static-stub @@ -10093,18 +10229,21 @@ view "external" { See caveats in root-delegation-only.

-
file
+
+file +

Set the zone's filename. In master, hint, and redirect zones which do not have masters defined, zone data is loaded from this file. In - slave, stub, and - redirect zones which do have - masters defined, zone data is - retrieved from another server and saved in this file. - This option is not applicable to other zone types. + slave, mirror, + stub, and redirect + zones which do have masters + defined, zone data is retrieved from another server + and saved in this file. This option is not + applicable to other zone types.

forward
@@ -10444,65 +10583,6 @@ example.com. NS ns2.example.net. behavior is disabled by default.

-
mirror
-
-

- If set to yes, this causes the - zone to become a mirror zone. A mirror zone is a - secondary zone whose data - is subject to DNSSEC validation before being - used in answers. The default is - no. -

-

- A mirror zone's contents are validated during the transfer - process, and again when the zone file is loaded from disk - when named is restarted. If validation - fails, a retransfer of the zone is scheduled; if the mirror - zone had not previously been loaded or if the previous - version has expired, traditional DNS recursion will be used - to look up the answers instead. -

-

- For validation to succeed, a key-signing key (KSK) for - the zone must be configured as a trust anchor in - named.conf: - that is, a key for the zone must either be specified in - managed-keys or - trusted-keys, or in the case of - the root zone, dnssec-validation - must be set to auto. - Answers coming from a mirror zone look almost exactly like - answers from a normal slave zone, with the notable - exceptions that the AA bit ("authoritative answer") is - not set, and the AD bit ("authenticated data") is. -

-

- Though this option can be used for other zones, it - is intended to be used to set up a fast local copy of - the root zone, as described in RFC 7706. - This can be done by using the following configuration: -

-
zone "." {
-        type slave;
-        mirror yes;
-        file "root.mirror";
-        masters {
-                192.228.79.201;       # b.root-servers.net
-                192.33.4.12;          # c.root-servers.net
-                192.5.5.241;          # f.root-servers.net
-                192.112.36.4;         # g.root-servers.net
-                193.0.14.129;         # k.root-servers.net
-                192.0.47.132;         # xfr.cjr.dns.icann.org
-                192.0.32.132;         # xfr.lax.dns.icann.org
-                2001:500:84::b;       # b.root-servers.net
-                2001:500:2f::f;       # f.root-servers.net
-                2001:7fd::1;          # k.root-servers.net
-                2620:0:2830:202::132; # xfr.cjr.dns.icann.org
-                2620:0:2d0:202::132;  # xfr.lax.dns.icann.org
-        };
-};
-
multi-master

diff --git a/doc/arm/man.named.conf.html b/doc/arm/man.named.conf.html index 3c91638ea3b31171ef1711bf4d512bbd12202a25..4a9411be55b10a2a41bb3dd8e7182f11affcf104 100644 --- a/doc/arm/man.named.conf.html +++ b/doc/arm/man.named.conf.html @@ -871,7 +871,6 @@ view max-zone-ttl ( unlimited | ttlval );
min-refresh-time integer;
min-retry-time integer;
- mirror boolean;
multi-master boolean;
notify ( explicit | master-only | boolean );
notify-delay integer;
@@ -897,7 +896,7 @@ view transfer-source-v6 ( ipv6_address | * ) [ port (
    integer | * ) ] [ dscp integer ];
try-tcp-refresh boolean;
- type ( primary | master | secondary | slave |
+ type ( primary | master | secondary | slave | mirror |
    delegation-only | forward | hint | redirect |
    static-stub | stub );
update-check-ksk boolean;
@@ -977,7 +976,6 @@ zone max-zone-ttl ( unlimited | ttlval );
min-refresh-time integer;
min-retry-time integer;
- mirror boolean;
multi-master boolean;
notify ( explicit | master-only | boolean );
notify-delay integer;
@@ -1001,8 +999,9 @@ zone transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
try-tcp-refresh boolean;
- type ( primary | master | secondary | slave | delegation-only |
-     forward | hint | redirect | static-stub | stub );
+ type ( primary | master | secondary | slave | mirror |
+     delegation-only | forward | hint | redirect | static-stub |
+     stub );
update-check-ksk boolean;
update-policy ( local | { ( deny | grant ) string ( 6to4-self |
    external | krb5-self | krb5-subdomain | ms-self | ms-subdomain
diff --git a/doc/arm/mirror.zoneopt.xml b/doc/arm/mirror.zoneopt.xml new file mode 100644 index 0000000000000000000000000000000000000000..694fd80d78576ea41c8d2089aa4801562b4d6729 --- /dev/null +++ b/doc/arm/mirror.zoneopt.xml @@ -0,0 +1,56 @@ + + + + +zone string [ class ] { + type mirror; + allow-notify { address_match_element; ... }; + allow-query { address_match_element; ... }; + allow-query-on { address_match_element; ... }; + allow-transfer { address_match_element; ... }; + allow-update-forwarding { address_match_element; ... }; + also-notify [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; + alt-transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; + alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; + check-names ( fail | warn | ignore ); + database string; + file quoted_string; + ixfr-from-differences boolean; + journal quoted_string; + masterfile-format ( map | raw | text ); + masterfile-style ( full | relative ); + masters [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; + max-journal-size ( default | unlimited | sizeval ); + max-records integer; + max-refresh-time integer; + max-retry-time integer; + max-transfer-idle-in integer; + max-transfer-idle-out integer; + max-transfer-time-in integer; + max-transfer-time-out integer; + min-refresh-time integer; + min-retry-time integer; + multi-master boolean; + notify ( explicit | master-only | boolean ); + notify-delay integer; + notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; + notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; + request-expire boolean; + request-ixfr boolean; + transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; + transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; + try-tcp-refresh boolean; + use-alt-transfer-source boolean; + zero-no-soa-ttl boolean; + zone-statistics ( full | terse | none | boolean ); +}; + diff --git a/doc/arm/options.grammar.xml b/doc/arm/options.grammar.xml index 3eae56c229202c618adc47ad0f169f0e8a9ec355..d8c9243ae5e06d30922b35da096bd9be10e971d4 100644 --- a/doc/arm/options.grammar.xml +++ b/doc/arm/options.grammar.xml @@ -180,7 +180,6 @@ min-retry-time integer; minimal-any boolean; minimal-responses ( no-auth | no-auth-recursive | boolean ); - mirror boolean; multi-master boolean; new-zones-directory quoted_string; no-case-compress { address_match_element; ... }; diff --git a/doc/arm/slave.zoneopt.xml b/doc/arm/slave.zoneopt.xml index 0c4ee36a70cc85d5c195e91b128ef520a8726392..63c0a4acf182ffc6ac7e41a386284085d0d7cbf4 100644 --- a/doc/arm/slave.zoneopt.xml +++ b/doc/arm/slave.zoneopt.xml @@ -50,7 +50,6 @@ max-transfer-time-out integer; min-refresh-time integer; min-retry-time integer; - mirror boolean; multi-master boolean; notify ( explicit | master-only | boolean ); notify-delay integer; diff --git a/doc/design/zone b/doc/design/zone index 227576d8565774124e1a703043f92d6c4c96663b..55c3484bbacc942f2f920f41e77c1388be7eef2d 100644 --- a/doc/design/zone +++ b/doc/design/zone @@ -111,6 +111,7 @@ Types: dns_zone_none = 0, dns_zone_master, dns_zone_slave, + dns_zone_mirror, dns_zone_stub, dns_zone_hint, dns_zone_cache, diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in index c4967ff519bcf19a7e8ec63cd8d579cec27e93ab..21084d5591775114565a9b712f8b434645dea5fe 100644 --- a/doc/misc/Makefile.in +++ b/doc/misc/Makefile.in @@ -35,6 +35,7 @@ options: FORCE ${CFG_TEST} --named --grammar > $@.raw ; \ ${CFG_TEST} --zonegrammar master > master.zoneopt ; \ ${CFG_TEST} --zonegrammar slave > slave.zoneopt ; \ + ${CFG_TEST} --zonegrammar mirror > mirror.zoneopt ; \ ${CFG_TEST} --zonegrammar forward > forward.zoneopt ; \ ${CFG_TEST} --zonegrammar hint > hint.zoneopt ; \ ${CFG_TEST} --zonegrammar stub > stub.zoneopt ; \ @@ -54,6 +55,7 @@ docbook: options ${PERL} docbook-options.pl options > ${top_srcdir}/bin/named/named.conf.docbook ${PERL} docbook-zoneopt.pl master.zoneopt > ${top_srcdir}/doc/arm/master.zoneopt.xml ${PERL} docbook-zoneopt.pl slave.zoneopt > ${top_srcdir}/doc/arm/slave.zoneopt.xml + ${PERL} docbook-zoneopt.pl mirror.zoneopt > ${top_srcdir}/doc/arm/mirror.zoneopt.xml ${PERL} docbook-zoneopt.pl forward.zoneopt > ${top_srcdir}/doc/arm/forward.zoneopt.xml ${PERL} docbook-zoneopt.pl hint.zoneopt > ${top_srcdir}/doc/arm/hint.zoneopt.xml ${PERL} docbook-zoneopt.pl stub.zoneopt > ${top_srcdir}/doc/arm/stub.zoneopt.xml diff --git a/doc/misc/mirror.zoneopt b/doc/misc/mirror.zoneopt new file mode 100644 index 0000000000000000000000000000000000000000..6184d371d5adfed23b863e13e78861107a41a275 --- /dev/null +++ b/doc/misc/mirror.zoneopt @@ -0,0 +1,42 @@ +zone [ ] { + type mirror; + allow-notify { ; ... }; + allow-query { ; ... }; + allow-query-on { ; ... }; + allow-transfer { ; ... }; + allow-update-forwarding { ; ... }; + also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ]; ... }; + alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; + alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; + check-names ( fail | warn | ignore ); + database ; + file ; + ixfr-from-differences ; + journal ; + masterfile-format ( map | raw | text ); + masterfile-style ( full | relative ); + masters [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ]; ... }; + max-journal-size ( default | unlimited | ); + max-records ; + max-refresh-time ; + max-retry-time ; + max-transfer-idle-in ; + max-transfer-idle-out ; + max-transfer-time-in ; + max-transfer-time-out ; + min-refresh-time ; + min-retry-time ; + multi-master ; + notify ( explicit | master-only | ); + notify-delay ; + notify-source ( | * ) [ port ( | * ) ] [ dscp ]; + notify-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; + request-expire ; + request-ixfr ; + transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; + transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; + try-tcp-refresh ; + use-alt-transfer-source ; + zero-no-soa-ttl ; + zone-statistics ( full | terse | none | ); +}; diff --git a/doc/misc/options b/doc/misc/options index e845e3e52f104ff0785380da9b97d95cb889dea3..441cda28df017781609f994980fd01b6db554e89 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -239,7 +239,6 @@ options { min-roots ; // not implemented minimal-any ; minimal-responses ( no-auth | no-auth-recursive | ); - mirror ; multi-master ; multiple-cnames ; // obsolete named-xfer ; // obsolete @@ -580,7 +579,6 @@ view [ ] { min-roots ; // not implemented minimal-any ; minimal-responses ( no-auth | no-auth-recursive | ); - mirror ; multi-master ; new-zones-directory ; no-case-compress { ; ... }; @@ -786,7 +784,6 @@ view [ ] { max-zone-ttl ( unlimited | ); min-refresh-time ; min-retry-time ; - mirror ; multi-master ; notify ( explicit | master-only | ); notify-delay ; @@ -814,7 +811,7 @@ view [ ] { transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; try-tcp-refresh ; - type ( primary | master | secondary | slave | + type ( primary | master | secondary | slave | mirror | delegation-only | forward | hint | redirect | static-stub | stub ); update-check-ksk ; @@ -892,7 +889,6 @@ zone [ ] { max-zone-ttl ( unlimited | ); min-refresh-time ; min-retry-time ; - mirror ; multi-master ; notify ( explicit | master-only | ); notify-delay ; @@ -918,8 +914,9 @@ zone [ ] { transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; try-tcp-refresh ; - type ( primary | master | secondary | slave | delegation-only | - forward | hint | redirect | static-stub | stub ); + type ( primary | master | secondary | slave | mirror | + delegation-only | forward | hint | redirect | static-stub | + stub ); update-check-ksk ; update-policy ( local | { ( deny | grant ) ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self diff --git a/doc/misc/slave.zoneopt b/doc/misc/slave.zoneopt index 42c87f46780a1307e087e8d82e783b9f28741eab..248823a88bd5a7f6617da4d9dd0cdfdcd8badeb8 100644 --- a/doc/misc/slave.zoneopt +++ b/doc/misc/slave.zoneopt @@ -37,7 +37,6 @@ zone [ ] { max-transfer-time-out ; min-refresh-time ; min-retry-time ; - mirror ; multi-master ; notify ( explicit | master-only | ); notify-delay ; diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 40608518881eb4b272362f08c93a4bb6baabd7d2..ab944ebd7848eb8f28f76b5e8b75d9885735f80a 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -1915,6 +1915,114 @@ check_nonzero(const cfg_obj_t *options, isc_log_t *logctx) { return (result); } +/*% + * Check whether NOTIFY configuration at the zone level is acceptable for a + * mirror zone. Return true if it is; return false otherwise. + */ +static bool +check_mirror_zone_notify(const cfg_obj_t *zoptions, const char *znamestr, + isc_log_t *logctx) +{ + bool notify_configuration_ok = true; + const cfg_obj_t *obj = NULL; + + (void)cfg_map_get(zoptions, "notify", &obj); + if (obj == NULL) { + /* + * "notify" not set at zone level. This is fine. + */ + return (true); + } + + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + /* + * "notify yes;" set at zone level. This is an error. + */ + notify_configuration_ok = false; + } + } else { + const char *notifystr = cfg_obj_asstring(obj); + if (strcasecmp(notifystr, "explicit") != 0) { + /* + * Something else than "notify explicit;" set at zone + * level. This is an error. + */ + notify_configuration_ok = false; + } + } + + if (!notify_configuration_ok) { + cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, + "zone '%s': mirror zones can only be used with " + "'notify no;' or 'notify explicit;'", znamestr); + } + + return (notify_configuration_ok); +} + +/*% + * Try to determine whether recursion is available in a view without resorting + * to extraordinary measures: just check the "recursion" and "allow-recursion" + * settings. The point is to prevent accidental mirror zone misuse rather than + * to enforce some sort of policy. Recursion is assumed to be allowed by + * default if it is not explicitly disabled. + */ +static bool +check_recursion(const cfg_obj_t *config, const cfg_obj_t *voptions, + const cfg_obj_t *goptions, isc_log_t *logctx, + cfg_aclconfctx_t *actx, isc_mem_t *mctx) +{ + dns_acl_t *acl = NULL; + const cfg_obj_t *obj; + isc_result_t result; + bool retval = true; + + /* + * Check the "recursion" option first. + */ + obj = NULL; + result = ISC_R_NOTFOUND; + if (voptions != NULL) { + result = cfg_map_get(voptions, "recursion", &obj); + } + if (result != ISC_R_SUCCESS && goptions != NULL) { + result = cfg_map_get(goptions, "recursion", &obj); + } + if (result == ISC_R_SUCCESS && !cfg_obj_asboolean(obj)) { + retval = false; + goto cleanup; + } + + /* + * If recursion is not disabled by the "recursion" option, check + * whether it is disabled by the "allow-recursion" ACL. + */ + obj = NULL; + result = ISC_R_NOTFOUND; + if (voptions != NULL) { + result = cfg_map_get(voptions, "allow-recursion", &obj); + } + if (result != ISC_R_SUCCESS && goptions != NULL) { + result = cfg_map_get(goptions, "allow-recursion", &obj); + } + if (result == ISC_R_SUCCESS) { + result = cfg_acl_fromconfig(obj, config, logctx, actx, mctx, 0, + &acl); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + retval = !dns_acl_isnone(acl); + } + + cleanup: + if (acl != NULL) { + dns_acl_detach(&acl); + } + + return (retval); +} + static isc_result_t check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, const cfg_obj_t *config, isc_symtab_t *symtab, @@ -1989,6 +2097,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, strcasecmp(typestr, "secondary") == 0) { ztype = CFG_ZONE_SLAVE; + } else if (strcasecmp(typestr, "mirror") == 0) { + ztype = CFG_ZONE_MIRROR; } else if (strcasecmp(typestr, "stub") == 0) { ztype = CFG_ZONE_STUB; } else if (strcasecmp(typestr, "static-stub") == 0) { @@ -2100,6 +2210,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, case CFG_ZONE_MASTER: case CFG_ZONE_SLAVE: + case CFG_ZONE_MIRROR: case CFG_ZONE_HINT: case CFG_ZONE_STUB: case CFG_ZONE_STATICSTUB: @@ -2184,10 +2295,22 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, } /* - * Master & slave zones may have an "also-notify" field, but + * Only a limited subset of all possible "notify" settings can be used + * at the zone level for mirror zones. + */ + if (ztype == CFG_ZONE_MIRROR && + !check_mirror_zone_notify(zoptions, znamestr, logctx)) + { + result = ISC_R_FAILURE; + } + + /* + * Master, slave, and mirror zones may have an "also-notify" field, but * shouldn't if notify is disabled. */ - if (ztype == CFG_ZONE_MASTER || ztype == CFG_ZONE_SLAVE) { + if (ztype == CFG_ZONE_MASTER || ztype == CFG_ZONE_SLAVE || + ztype == CFG_ZONE_MIRROR) + { bool donotify = true; obj = NULL; @@ -2228,9 +2351,13 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, } /* - * Slave & stub zones must have a "masters" field. + * Slave, mirror, and stub zones must have a "masters" field, with one + * exception: when mirroring the root zone, a default, built-in master + * server list is used in the absence of one explicitly specified. */ - if (ztype == CFG_ZONE_SLAVE || ztype == CFG_ZONE_STUB) { + if (ztype == CFG_ZONE_SLAVE || ztype == CFG_ZONE_STUB || + (ztype == CFG_ZONE_MIRROR && !dns_name_equal(zname, dns_rootname))) + { obj = NULL; if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) { cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, @@ -2252,6 +2379,19 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, } } + /* + * Configuring a mirror zone and disabling recursion at the same time + * contradicts the purpose of the former. + */ + if (ztype == CFG_ZONE_MIRROR && + !check_recursion(config, voptions, goptions, logctx, actx, mctx)) + { + cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, + "zone '%s': mirror zones cannot be used if " + "recursion is disabled", znamestr); + result = ISC_R_FAILURE; + } + /* * Master zones can't have both "allow-update" and "update-policy". */ @@ -2621,7 +2761,9 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, znamestr); result = tresult; } else if (tresult == ISC_R_SUCCESS && - (ztype == CFG_ZONE_SLAVE || ddns)) { + (ztype == CFG_ZONE_SLAVE || + ztype == CFG_ZONE_MIRROR || ddns)) + { tresult = fileexist(fileobj, files, true, logctx); if (tresult != ISC_R_SUCCESS) result = tresult; diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 484e82806f672945d212742c9aeafd728216688c..e2ad6314a5bbf8562307121c9c2d685554610f91 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -38,6 +38,7 @@ typedef enum { dns_zone_none, dns_zone_master, dns_zone_slave, + dns_zone_mirror, dns_zone_stub, dns_zone_staticstub, dns_zone_key, @@ -82,7 +83,6 @@ typedef enum { DNS_ZONEOPT_CHECKSPF = 1<<27, /*%< check SPF records */ DNS_ZONEOPT_CHECKTTL = 1<<28, /*%< check max-zone-ttl */ DNS_ZONEOPT_AUTOEMPTY = 1<<29, /*%< automatic empty zone */ - DNS_ZONEOPT_MIRROR = 1<<30, /*%< mirror zone */ } dns_zoneopt_t; /* @@ -2485,12 +2485,6 @@ dns_zone_isloaded(const dns_zone_t *zone); * false otherwise. */ -bool -dns_zone_ismirror(const dns_zone_t *zone); -/*%< - * Return true if 'zone' is a mirror zone, return false otherwise. - */ - isc_result_t dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver); /*%< diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index e8ac6af323f734e8b9a94a3a745b7300c4748577..83a77856bc61722c62ef798350523e3f79ac9807 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -1201,7 +1201,6 @@ dns_zone_idetach dns_zone_isdynamic dns_zone_isforced dns_zone_isloaded -dns_zone_ismirror dns_zone_keydone dns_zone_link dns_zone_load diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 60545141c7534272700bcd8dd7db6774de2278e7..e4f1d3f4e3cb09df1056c9081822cbe76adf1f41 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1709,16 +1709,17 @@ dns_zone_getjournal(dns_zone_t *zone) { * master file (if any) is written by the server, rather than being * updated manually and read by the server. * - * This is true for slave zones, stub zones, key zones, and zones that - * allow dynamic updates either by having an update policy ("ssutable") - * or an "allow-update" ACL with a value other than exactly "{ none; }". + * This is true for slave zones, mirror zones, stub zones, key zones, + * and zones that allow dynamic updates either by having an update + * policy ("ssutable") or an "allow-update" ACL with a value other than + * exactly "{ none; }". */ bool dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) { REQUIRE(DNS_ZONE_VALID(zone)); - if (zone->type == dns_zone_slave || zone->type == dns_zone_stub || - zone->type == dns_zone_key || + if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror || + zone->type == dns_zone_stub || zone->type == dns_zone_key || (zone->type == dns_zone_redirect && zone->masters != NULL)) return (true); @@ -2072,7 +2073,8 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) { goto cleanup; } - if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub || + if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror || + zone->type == dns_zone_stub || (zone->type == dns_zone_redirect && zone->masters != NULL)) && rbt) { if (zone->masterfile == NULL || @@ -2108,7 +2110,9 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) { } dns_db_settask(db, zone->task); - if (zone->type == dns_zone_master || zone->type == dns_zone_slave) { + if (zone->type == dns_zone_master || zone->type == dns_zone_slave || + zone->type == dns_zone_mirror) + { result = dns_db_setgluecachestats(db, zone->gluecachestats); if (result == ISC_R_NOTIMPLEMENTED) { result = ISC_R_SUCCESS; @@ -2280,27 +2284,39 @@ get_master_options(dns_zone_t *zone) { unsigned int options; options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN; - if (zone->type == dns_zone_slave || + if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror || (zone->type == dns_zone_redirect && zone->masters == NULL)) + { options |= DNS_MASTER_SLAVE; - if (zone->type == dns_zone_key) + } + if (zone->type == dns_zone_key) { options |= DNS_MASTER_KEY; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) { options |= DNS_MASTER_CHECKNS; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) { options |= DNS_MASTER_FATALNS; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) { options |= DNS_MASTER_CHECKNAMES; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) { options |= DNS_MASTER_CHECKNAMESFAIL; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) { options |= DNS_MASTER_CHECKMX; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) { options |= DNS_MASTER_CHECKMXFAIL; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) { options |= DNS_MASTER_CHECKWILDCARD; - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) + } + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) { options |= DNS_MASTER_CHECKTTL; + } + return (options); } @@ -4433,6 +4449,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, */ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { if (zone->type == dns_zone_slave || + zone->type == dns_zone_mirror || zone->type == dns_zone_stub || (zone->type == dns_zone_redirect && zone->masters == NULL)) { @@ -4592,14 +4609,15 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, "loaded; checking validity"); /* - * Master / Slave / Stub zones require both NS and SOA records at - * the top of the zone. + * Master / Slave / Mirror / Stub zones require both NS and SOA records + * at the top of the zone. */ switch (zone->type) { case dns_zone_dlz: case dns_zone_master: case dns_zone_slave: + case dns_zone_mirror: case dns_zone_stub: case dns_zone_redirect: if (soacount != 1) { @@ -4723,6 +4741,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); if (zone->type == dns_zone_slave || + zone->type == dns_zone_mirror || zone->type == dns_zone_stub || (zone->type == dns_zone_redirect && zone->masters != NULL)) { @@ -4909,6 +4928,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, isc_mem_put(zone->mctx, inc, sizeof(*inc)); } if (zone->type == dns_zone_slave || + zone->type == dns_zone_mirror || zone->type == dns_zone_stub || zone->type == dns_zone_key || (zone->type == dns_zone_redirect && zone->masters != NULL)) { @@ -5063,7 +5083,9 @@ zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node, while (result == ISC_R_SUCCESS) { if (errors != NULL && zone->rdclass == dns_rdataclass_in && (zone->type == dns_zone_master || - zone->type == dns_zone_slave)) { + zone->type == dns_zone_slave || + zone->type == dns_zone_mirror)) + { dns_rdata_init(&rdata); dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &ns, NULL); @@ -10043,6 +10065,7 @@ zone_maintenance(dns_zone_t *zone) { break; /* FALLTHROUGH */ case dns_zone_slave: + case dns_zone_mirror: case dns_zone_stub: LOCK_ZONE(zone); if (isc_time_compare(&now, &zone->expiretime) >= 0 && @@ -10065,6 +10088,7 @@ zone_maintenance(dns_zone_t *zone) { break; /* FALLTHROUGH */ case dns_zone_slave: + case dns_zone_mirror: case dns_zone_stub: if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) && isc_time_compare(&now, &zone->refreshtime) >= 0) @@ -10077,7 +10101,7 @@ zone_maintenance(dns_zone_t *zone) { /* * Slaves send notifies before backing up to disk, masters after. */ - if (zone->type == dns_zone_slave && + if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror) && (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) && isc_time_compare(&now, &zone->notifytime) >= 0) @@ -10089,6 +10113,7 @@ zone_maintenance(dns_zone_t *zone) { switch (zone->type) { case dns_zone_master: case dns_zone_slave: + case dns_zone_mirror: case dns_zone_key: case dns_zone_redirect: case dns_zone_stub: @@ -11950,8 +11975,10 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { master, source); /* Try with slave with TCP. */ if ((zone->type == dns_zone_slave || + zone->type == dns_zone_mirror || zone->type == dns_zone_redirect) && - DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) { + DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) + { if (!dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr, &zone->sourceaddr, @@ -12026,8 +12053,11 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { */ if (msg->rcode == dns_rcode_refused && (zone->type == dns_zone_slave || + zone->type == dns_zone_mirror || zone->type == dns_zone_redirect)) + { goto tcp_transfer; + } goto next_master; } @@ -12036,7 +12066,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { */ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { if (zone->type == dns_zone_slave || - zone->type == dns_zone_redirect) { + zone->type == dns_zone_mirror || + zone->type == dns_zone_redirect) + { dns_zone_log(zone, ISC_LOG_INFO, "refresh: truncated UDP answer, " "initiating TCP zone xfer " @@ -12164,6 +12196,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { "refresh: skipping %s as master %s " "(source %s) is unreachable (cached)", (zone->type == dns_zone_slave || + zone->type == dns_zone_mirror || zone->type == dns_zone_redirect) ? "zone transfer" : "NS query", master, source); @@ -12173,7 +12206,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); dns_request_destroy(&zone->request); if (zone->type == dns_zone_slave || - zone->type == dns_zone_redirect) { + zone->type == dns_zone_mirror || + zone->type == dns_zone_redirect) + { do_queue_xfrin = true; } else { INSIST(zone->type == dns_zone_stub); @@ -13028,6 +13063,7 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) { break; case dns_zone_slave: + case dns_zone_mirror: treat_as_slave: if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) @@ -19410,13 +19446,6 @@ dns_zone_isloaded(const dns_zone_t *zone) { return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)); } -bool -dns_zone_ismirror(const dns_zone_t *zone) { - REQUIRE(DNS_ZONE_VALID(zone)); - - return (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MIRROR)); -} - isc_result_t dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) { dns_dbversion_t *version = NULL; @@ -19430,7 +19459,7 @@ dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) { REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(db != NULL); - if (!dns_zone_ismirror(zone)) { + if (dns_zone_gettype(zone) != dns_zone_mirror) { return (ISC_R_SUCCESS); } diff --git a/lib/dns/zt.c b/lib/dns/zt.c index 6b9e7d327764e75bb6909c6f5142bd36a69954e5..62b0e4a053ac99e8477f8bf07d8fa9b95f529fda 100644 --- a/lib/dns/zt.c +++ b/lib/dns/zt.c @@ -181,7 +181,8 @@ dns_zt_find(dns_zt_t *zt, const dns_name_t *name, unsigned int options, * instead of returning a SERVFAIL. */ if ((options & DNS_ZTFIND_MIRROR) != 0 && - dns_zone_ismirror(dummy) && !dns_zone_isloaded(dummy)) + dns_zone_gettype(dummy) == dns_zone_mirror && + !dns_zone_isloaded(dummy)) { result = ISC_R_NOTFOUND; } else { diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h index a066cd13e966539ce5f86e23e820dd302629d765..93ff3df15677914740e77995f10ee0bdab24f644 100644 --- a/lib/isccfg/include/isccfg/grammar.h +++ b/lib/isccfg/include/isccfg/grammar.h @@ -72,6 +72,7 @@ #define CFG_ZONE_REDIRECT 0x02000000 #define CFG_ZONE_DELEGATION 0x01000000 #define CFG_ZONE_INVIEW 0x00800000 +#define CFG_ZONE_MIRROR 0x00400000 typedef struct cfg_clausedef cfg_clausedef_t; typedef struct cfg_tuplefielddef cfg_tuplefielddef_t; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 3b51a080bab5b9a7933950e774fd16ea609531c0..3e537a3a60c6c17093c264e1014c0a8276dcbf76 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -668,7 +668,7 @@ static cfg_type_t cfg_type_forwardtype = { }; static const char *zonetype_enums[] = { - "primary", "master", "secondary", "slave", + "primary", "master", "secondary", "slave", "mirror", "delegation-only", "forward", "hint", "redirect", "static-stub", "stub", NULL }; @@ -2020,33 +2020,33 @@ static cfg_type_t cfg_type_validityinterval = { static cfg_clausedef_t zone_clauses[] = { { "allow-notify", &cfg_type_bracketed_aml, - CFG_ZONE_SLAVE + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "allow-query", &cfg_type_bracketed_aml, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB | - CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | + CFG_ZONE_STUB | CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB }, { "allow-query-on", &cfg_type_bracketed_aml, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB | - CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | + CFG_ZONE_STUB | CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB }, { "allow-transfer", &cfg_type_bracketed_aml, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "allow-update", &cfg_type_bracketed_aml, CFG_ZONE_MASTER }, { "allow-update-forwarding", &cfg_type_bracketed_aml, - CFG_ZONE_SLAVE + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "also-notify", &cfg_type_namesockaddrkeylist, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "alt-transfer-source", &cfg_type_sockaddr4wild, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "alt-transfer-source-v6", &cfg_type_sockaddr6wild, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "auto-dnssec", &cfg_type_autodnssec, CFG_ZONE_MASTER | CFG_ZONE_SLAVE @@ -2108,67 +2108,64 @@ zone_clauses[] = { CFG_CLAUSEFLAG_OBSOLETE }, { "masterfile-format", &cfg_type_masterformat, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB | CFG_ZONE_REDIRECT }, { "masterfile-style", &cfg_type_masterstyle, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB | CFG_ZONE_REDIRECT }, { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_OBSOLETE }, { "max-journal-size", &cfg_type_size, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "max-records", &cfg_type_uint32, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB | - CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | + CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT }, { "max-refresh-time", &cfg_type_uint32, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "max-retry-time", &cfg_type_uint32, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "max-transfer-idle-in", &cfg_type_uint32, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "max-transfer-idle-out", &cfg_type_uint32, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_MIRROR | CFG_ZONE_SLAVE }, { "max-transfer-time-in", &cfg_type_uint32, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "max-transfer-time-out", &cfg_type_uint32, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_MIRROR | CFG_ZONE_SLAVE }, { "max-zone-ttl", &cfg_type_maxttl, CFG_ZONE_MASTER | CFG_ZONE_REDIRECT }, { "min-refresh-time", &cfg_type_uint32, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "min-retry-time", &cfg_type_uint32, - CFG_ZONE_SLAVE | CFG_ZONE_STUB - }, - { "mirror", &cfg_type_boolean, - CFG_ZONE_SLAVE + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "multi-master", &cfg_type_boolean, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "notify", &cfg_type_notifytype, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "notify-delay", &cfg_type_uint32, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "notify-source", &cfg_type_sockaddr4wild, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "notify-source-v6", &cfg_type_sockaddr6wild, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "notify-to-soa", &cfg_type_boolean, CFG_ZONE_MASTER | CFG_ZONE_SLAVE @@ -2178,10 +2175,10 @@ zone_clauses[] = { CFG_ZONE_MASTER | CFG_ZONE_SLAVE }, { "request-expire", &cfg_type_boolean, - CFG_ZONE_SLAVE + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "request-ixfr", &cfg_type_boolean, - CFG_ZONE_SLAVE + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "serial-update-method", &cfg_type_updatemethod, CFG_ZONE_MASTER @@ -2202,26 +2199,26 @@ zone_clauses[] = { CFG_ZONE_MASTER | CFG_ZONE_SLAVE }, { "transfer-source", &cfg_type_sockaddr4wild, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "transfer-source-v6", &cfg_type_sockaddr6wild, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "try-tcp-refresh", &cfg_type_boolean, - CFG_ZONE_SLAVE + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "update-check-ksk", &cfg_type_boolean, CFG_ZONE_MASTER | CFG_ZONE_SLAVE }, { "use-alt-transfer-source", &cfg_type_boolean, - CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB }, { "zero-no-soa-ttl", &cfg_type_boolean, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "zone-statistics", &cfg_type_zonestat, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB | - CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | + CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT }, { NULL, NULL, 0 } }; @@ -2239,16 +2236,17 @@ zone_only_clauses[] = { * the zone options and the global/view options. Ugh. */ { "type", &cfg_type_zonetype, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB | - CFG_ZONE_STATICSTUB | CFG_ZONE_DELEGATION | CFG_ZONE_HINT | - CFG_ZONE_REDIRECT | CFG_ZONE_FORWARD + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | + CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_DELEGATION | + CFG_ZONE_HINT | CFG_ZONE_REDIRECT | CFG_ZONE_FORWARD }, { "check-names", &cfg_type_checkmode, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_HINT | CFG_ZONE_STUB }, { "database", &cfg_type_astring, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | + CFG_ZONE_STUB }, { "delegation-only", &cfg_type_boolean, CFG_ZONE_HINT | CFG_ZONE_STUB | CFG_ZONE_FORWARD @@ -2257,8 +2255,8 @@ zone_only_clauses[] = { CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_REDIRECT }, { "file", &cfg_type_qstring, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_STUB | - CFG_ZONE_HINT | CFG_ZONE_REDIRECT + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | + CFG_ZONE_STUB | CFG_ZONE_HINT | CFG_ZONE_REDIRECT }, { "in-view", &cfg_type_astring, CFG_ZONE_INVIEW @@ -2267,16 +2265,17 @@ zone_only_clauses[] = { CFG_CLAUSEFLAG_OBSOLETE }, { "ixfr-from-differences", &cfg_type_boolean, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "ixfr-tmp-file", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE }, { "journal", &cfg_type_qstring, - CFG_ZONE_MASTER | CFG_ZONE_SLAVE + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "masters", &cfg_type_namesockaddrkeylist, - CFG_ZONE_SLAVE | CFG_ZONE_STUB | CFG_ZONE_REDIRECT + CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB | + CFG_ZONE_REDIRECT }, { "pubkey", &cfg_type_pubkey, CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE @@ -4121,6 +4120,10 @@ cfg_print_zonegrammar(const unsigned int zonetype, cfg_print_indent(&pctx); cfg_print_cstr(&pctx, "type ( slave | secondary );\n"); break; + case CFG_ZONE_MIRROR: + cfg_print_indent(&pctx); + cfg_print_cstr(&pctx, "type mirror;\n"); + break; case CFG_ZONE_STUB: cfg_print_indent(&pctx); cfg_print_cstr(&pctx, "type stub;\n"); diff --git a/lib/ns/notify.c b/lib/ns/notify.c index 1b3b4201448896a7571ebdcc2eda4d56dc31f8de..a01c4ce55202d947a602c924845eabd8a4311ec5 100644 --- a/lib/ns/notify.c +++ b/lib/ns/notify.c @@ -141,6 +141,7 @@ ns_notify_start(ns_client_t *client) { if ((zonetype == dns_zone_master) || (zonetype == dns_zone_slave) || + (zonetype == dns_zone_mirror) || (zonetype == dns_zone_stub)) { isc_sockaddr_t *from = ns_client_getsockaddr(client); diff --git a/lib/ns/query.c b/lib/ns/query.c index 60b3310ab60bb57227c60c46f0e73e2f860490d7..20ed367495793c6f1470a3d14308d9412872729d 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -1095,7 +1095,7 @@ query_validatezonedb(ns_client_t *client, const dns_name_t *name, /* * Mirror zone data is treated as cache data. */ - if (dns_zone_ismirror(zone)) { + if (dns_zone_gettype(zone) == dns_zone_mirror) { return (query_checkcacheaccess(client, name, qtype, options)); } @@ -5382,7 +5382,7 @@ ns__query_start(query_ctx_t *qctx) { if (qctx->is_zone) { qctx->authoritative = true; if (qctx->zone != NULL) { - if (dns_zone_ismirror(qctx->zone)) { + if (dns_zone_gettype(qctx->zone) == dns_zone_mirror) { qctx->authoritative = false; } if (dns_zone_gettype(qctx->zone) == @@ -7099,8 +7099,8 @@ query_respond_any(query_ctx_t *qctx) { } /* - * Set the expire time, if requested, when answering from a - * slave or master zone. + * Set the expire time, if requested, when answering from a slave, mirror, or + * master zone. */ static void query_getexpire(query_ctx_t *qctx) { @@ -7117,7 +7117,9 @@ query_getexpire(query_ctx_t *qctx) { dns_zone_getraw(qctx->zone, &raw); mayberaw = (raw != NULL) ? raw : qctx->zone; - if (dns_zone_gettype(mayberaw) == dns_zone_slave) { + if (dns_zone_gettype(mayberaw) == dns_zone_slave || + dns_zone_gettype(mayberaw) == dns_zone_mirror) + { isc_time_t expiretime; uint32_t secs; dns_zone_getexpiretime(qctx->zone, &expiretime); @@ -7918,7 +7920,8 @@ query_zone_delegation(query_ctx_t *qctx) { if (USECACHE(qctx->client) && (RECURSIONOK(qctx->client) || - (qctx->zone != NULL && dns_zone_ismirror(qctx->zone)))) + (qctx->zone != NULL && + dns_zone_gettype(qctx->zone) == dns_zone_mirror))) { /* * We might have a better answer or delegation in the diff --git a/lib/ns/update.c b/lib/ns/update.c index d39eec752283403c59dc10f891eb9191a7683c30..c1d3e70b7b5aaf1d9dd89f4d6ba17677261fb927 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -1637,6 +1637,7 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { CHECK(send_update_event(client, zone)); break; case dns_zone_slave: + case dns_zone_mirror: CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone), "update forwarding", zonename, true, false)); @@ -1649,7 +1650,8 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { failure: if (result == DNS_R_REFUSED) { - INSIST(dns_zone_gettype(zone) == dns_zone_slave); + INSIST(dns_zone_gettype(zone) == dns_zone_slave || + dns_zone_gettype(zone) == dns_zone_mirror); inc_stats(client, zone, ns_statscounter_updaterej); } /* diff --git a/lib/ns/xfrout.c b/lib/ns/xfrout.c index d2851063f6092842f12bcd0a1589253c3837a069..4573d52248fb51b37e4c85604bb1eb498a4cb6b0 100644 --- a/lib/ns/xfrout.c +++ b/lib/ns/xfrout.c @@ -848,9 +848,12 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { } else { /* zone table has a match */ switch(dns_zone_gettype(zone)) { - /* Master and slave zones are OK for transfer. */ + /* + * Master, slave, and mirror zones are OK for transfer. + */ case dns_zone_master: case dns_zone_slave: + case dns_zone_mirror: case dns_zone_dlz: break; default: @@ -1087,7 +1090,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { dns_zone_getraw(zone, &raw); mayberaw = (raw != NULL) ? raw : zone; if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 && - dns_zone_gettype(mayberaw) == dns_zone_slave) { + (dns_zone_gettype(mayberaw) == dns_zone_slave || + dns_zone_gettype(mayberaw) == dns_zone_mirror)) + { isc_time_t expiretime; uint32_t secs; dns_zone_getexpiretime(zone, &expiretime); diff --git a/util/copyrights b/util/copyrights index 0a2cc0e0f7dfe78fd8f1622e37f18016a7f2ff13..0b1c9238212eb2bf8428a998d430b002e7d3cebf 100644 --- a/util/copyrights +++ b/util/copyrights @@ -597,6 +597,10 @@ ./bin/tests/system/checkconf/bad-maxcachettl.conf CONF-C 2018 ./bin/tests/system/checkconf/bad-maxncachettl.conf CONF-C 2018 ./bin/tests/system/checkconf/bad-maxttlmap.conf CONF-C 2014,2016,2018 +./bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf CONF-C 2018 +./bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf CONF-C 2018 +./bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf CONF-C 2018 +./bin/tests/system/checkconf/bad-mirror-recursion-no.conf CONF-C 2018 ./bin/tests/system/checkconf/bad-noddns.conf CONF-C 2014,2016,2018 ./bin/tests/system/checkconf/bad-options-also-notify.conf CONF-C 2016,2018 ./bin/tests/system/checkconf/bad-printtime.conf CONF-C 2016,2018 @@ -668,6 +672,8 @@ ./bin/tests/system/checkconf/good-lmdb-mapsize-smallest.conf CONF-C 2017,2018 ./bin/tests/system/checkconf/good-maxcachettl.conf CONF-C 2018 ./bin/tests/system/checkconf/good-maxncachettl.conf CONF-C 2018 +./bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf CONF-C 2018 +./bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf CONF-C 2018 ./bin/tests/system/checkconf/good-nested.conf CONF-C 2015,2016,2018 ./bin/tests/system/checkconf/good-options-also-notify.conf CONF-C 2016,2018 ./bin/tests/system/checkconf/good-printtime.conf CONF-C 2016,2018 @@ -1537,6 +1543,7 @@ ./bin/tests/system/metadata/parent.db ZONE 2009,2016,2018 ./bin/tests/system/metadata/setup.sh SH 2009,2011,2012,2014,2016,2017,2018 ./bin/tests/system/metadata/tests.sh SH 2009,2011,2012,2013,2014,2016,2017,2018 +./bin/tests/system/mirror/README TXT.BRIEF 2018 ./bin/tests/system/mirror/clean.sh SH 2018 ./bin/tests/system/mirror/ns1/named.conf.in CONF-C 2018 ./bin/tests/system/mirror/ns1/root.db.in ZONE 2018 @@ -2675,6 +2682,7 @@ ./doc/arm/managed-keys.xml SGML 2010,2014,2015,2016,2017,2018 ./doc/arm/master.zoneopt.xml SGML 2018 ./doc/arm/masters.grammar.xml SGML 2018 +./doc/arm/mirror.zoneopt.xml SGML 2018 ./doc/arm/notes-wrapper.xml SGML 2014,2015,2016,2018 ./doc/arm/notes.conf X 2015,2018 ./doc/arm/notes.html X 2014,2015,2016,2017,2018 @@ -2741,6 +2749,7 @@ ./doc/misc/master.zoneopt X 2018 ./doc/misc/migration TXT.BRIEF 2000,2001,2003,2004,2007,2008,2016,2018 ./doc/misc/migration-4to9 TXT.BRIEF 2001,2004,2016,2018 +./doc/misc/mirror.zoneopt X 2018 ./doc/misc/options X 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018 ./doc/misc/redirect.zoneopt X 2018 ./doc/misc/rfc-compliance TXT.BRIEF 2001,2004,2015,2016,2018