diff --git a/bin/named/config.c b/bin/named/config.c index 405197363e..f3c7b39a16 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -432,6 +432,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) { diff --git a/bin/named/server.c b/bin/named/server.c index 1fc81d8991..26019992aa 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -10162,7 +10162,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 +10195,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 +10288,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 +10306,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 +13500,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; @@ -14093,6 +14099,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 79d66d8e01..bd8d1c58ce 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 85e5421fd2..57ace8a0da 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); } @@ -982,7 +987,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 +1081,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, @@ -1537,7 +1542,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, @@ -1696,6 +1701,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, */ switch (ztype) { case dns_zone_slave: + case dns_zone_mirror: case dns_zone_stub: case dns_zone_redirect: count = 0; diff --git a/doc/design/zone b/doc/design/zone index 227576d856..55c3484bba 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/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 484e82806f..aaa4a1e435 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, diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 60545141c7..27dda5ab9f 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)) diff --git a/lib/ns/notify.c b/lib/ns/notify.c index 1b3b420144..a01c4ce552 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 60b3310ab6..ba45b6667e 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -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); diff --git a/lib/ns/update.c b/lib/ns/update.c index d39eec7522..c1d3e70b7b 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 d2851063f6..4573d52248 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);