diff --git a/src/knot/server/zone-load.c b/src/knot/server/zone-load.c index 9b1a29bf53de42221e00a814e3e8e0002ab05a51..524b07e0a25b90722b1e5c4789dfe5a08a36436c 100644 --- a/src/knot/server/zone-load.c +++ b/src/knot/server/zone-load.c @@ -118,12 +118,25 @@ zone_t *load_zone_file(conf_zone_t *conf) return NULL; } + /* Create the new zone. */ + zone_t *zone = zone_new((conf_zone_t *)conf); + if (zone == NULL) { + log_zone_error("Failed to create zone '%s': %s\n", + conf->name, knot_strerror(KNOT_ENOMEM)); + return NULL; + } + struct stat st; if (stat(conf->file, &st) < 0) { /* Go silently and reset mtime to 0. */ memset(&st, 0, sizeof(struct stat)); } + /* Set the zone type (master/slave). If zone has no master set, we + * are the primary master for this zone (i.e. zone type = master). + */ + zl.creator->master = (zone_master(zone) == NULL); + /* Load the zone contents. */ knot_zone_contents_t *zone_contents = zonefile_load(&zl); zonefile_close(&zl); @@ -134,15 +147,6 @@ zone_t *load_zone_file(conf_zone_t *conf) return NULL; } - /* Create the new zone. */ - zone_t *zone = zone_new((conf_zone_t *)conf); - if (zone == NULL) { - log_zone_error("Failed to create zone '%s': %s\n", - conf->name, knot_strerror(KNOT_ENOMEM)); - knot_zone_contents_deep_free(&zone_contents); - return NULL; - } - /* Link zone contents to zone. */ zone->contents = zone_contents; diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c index c94f2719e72cb07f10e45983e504ef5aa6db9784..d47468ba08236926894ef1f446332815fa2ca6dd 100644 --- a/src/knot/updates/xfr-in.c +++ b/src/knot/updates/xfr-in.c @@ -312,8 +312,8 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr, knot_zone_contents_t **zone) } // Init zone creator - zcreator_t zc = {.z = *zone, - .last_node = NULL, .ret = KNOT_EOK }; + zcreator_t zc = {.z = *zone, .last_node = NULL, + .master = false, .ret = KNOT_EOK }; while (ret == KNOT_EOK && rr) { diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index a72ca9b5a7a4394a3e89432656ceb3e2dc9ecab4..cb3a5c64db77365c586f04bc8b37ea3ff7b3995c 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -277,16 +277,12 @@ static bool rrset_ttls_equal(const knot_rrset_t *rrset) * \param rr RRSet we're adding into. * \param zname Zone name for logging. */ -static void rrset_ttl_check(err_handler_t *handler, - const knot_rrset_t *rr, const knot_node_t *n) +static int rrset_ttl_check(const knot_rrset_t *rr) { if (rr->type != KNOT_RRTYPE_RRSIG && !rrset_ttls_equal(rr)) { - /* Prepare additional info string. */ - char info_str[64] = { '\0' }; - char type_str[16] = { '\0' }; - knot_rrtype_to_string(rr->type, type_str, sizeof(type_str)); - snprintf(info_str, sizeof(info_str), "Record type: %s.", type_str); - err_handler_handle_error(handler, n, ZC_ERR_TTL_MISMATCH, info_str); + return KNOT_EMALF; + } else { + return KNOT_EOK; } } @@ -946,15 +942,35 @@ int sem_check_node_plain(const knot_zone_contents_t *zone, } } -int sem_check_rrset(const knot_node_t *node, - const knot_rrset_t *rrset, - err_handler_t *handler) +int sem_check_rrset(const knot_node_t *node, const knot_rrset_t *rrset, + bool master, err_handler_t *handler) { if (node == NULL || rrset == NULL || handler == NULL) { return KNOT_EINVAL; } - rrset_ttl_check(handler, rrset, node); + int ret = rrset_ttl_check(rrset); + + /* Do the check both on master and slave because of the warning, + * but fail only on master. */ + if (ret != KNOT_EOK) { + /* Prepare additional info string. */ + char info_str[64] = { '\0' }; + char type_str[16] = { '\0' }; + knot_rrtype_to_string(rr->type, type_str, sizeof(type_str)); + snprintf(info_str, sizeof(info_str), "Record type: %s.", type_str); + + if (master) { + /*! \todo REPLACE WITH FATAL ERROR */ + err_handler_handle_error(handler, n, ZC_ERR_TTL_MISMATCH, + info_str); + return KNOT_EMALF; + } else { + err_handler_handle_error(handler, n, ZC_ERR_TTL_MISMATCH, + info_str); + } + } + return KNOT_EOK; } diff --git a/src/knot/zone/semantic-check.h b/src/knot/zone/semantic-check.h index 649db7600a3d0d574bc634e5c8565e154287d088..7eeeabda859b15167d59d6294764a1fdbcc22cb7 100644 --- a/src/knot/zone/semantic-check.h +++ b/src/knot/zone/semantic-check.h @@ -229,13 +229,17 @@ int sem_check_node_plain(const knot_zone_contents_t *zone, * * \param node Node containg the RRSet. * \param rrset RRSet to be tested. + * \param master Set to true if server is primary master for this zone. * \param handler Error handler. * + * If \a master is true, additional check is performed which results in error + * of the RR has different TTL than the rest of the RRSet. + * * \return KNOT_E* */ int sem_check_rrset(const knot_node_t *node, const knot_rrset_t *rrset, - err_handler_t *handler); + bool master, err_handler_t *handler); #endif // _KNOT_SEMANTIC_CHECK_H_ diff --git a/src/knot/zone/zone-create.c b/src/knot/zone/zone-create.c index b83ffd59d87ad65befb011718e140acac28eb8a6..b654c243241a366843a31b1d31735bac446f6e2b 100644 --- a/src/knot/zone/zone-create.c +++ b/src/knot/zone/zone-create.c @@ -119,7 +119,8 @@ int zcreator_step(zcreator_t *zc, knot_rrset_t *rr) bool sem_fatal_error = false; err_handler_t err_handler; err_handler_init(&err_handler); - ret = sem_check_rrset(n, zone_rrset, &err_handler); + + ret = sem_check_rrset(n, zone_rrset, zc->master, &err_handler); if (ret != KNOT_EOK) { return ret; } diff --git a/src/knot/zone/zone-create.h b/src/knot/zone/zone-create.h index 65d6436586166fe78380ed26628a3ba6d0591399..a8aed1150894d88a6e9f720e91e733ff9ac9f8f9 100644 --- a/src/knot/zone/zone-create.h +++ b/src/knot/zone/zone-create.h @@ -38,6 +38,8 @@ typedef struct zcreator { knot_zone_contents_t *z; /*!< Created zone. */ knot_node_t *last_node; /*!< Last used node, use to save zone lookup. */ + bool master; /*!< Master flag. True if server is a primary + master for the zone. */ int ret; /*!< Return value. */ } zcreator_t;