diff --git a/src/knot/dnssec/nsec3-chain.c b/src/knot/dnssec/nsec3-chain.c index 41a4cff6de6a64a4982c9c7bde91952b9f560ad3..c3e8f52bcce42c17f4c191ccd3cdcc175a995d25 100644 --- a/src/knot/dnssec/nsec3-chain.c +++ b/src/knot/dnssec/nsec3-chain.c @@ -121,7 +121,7 @@ static int shallow_copy_signature(const zone_node_t *from, zone_node_t *to) if (knot_rrset_empty(&from_sig)) { return KNOT_EOK; } - return node_add_rrset(to, &from_sig, NULL); + return node_add_rrset(to, &from_sig); } /*! @@ -298,7 +298,7 @@ static zone_node_t *create_nsec3_node(knot_dname_t *owner, return NULL; } - ret = node_add_rrset(new_node, &nsec3_rrset, NULL); + ret = node_add_rrset(new_node, &nsec3_rrset); knot_rrset_clear(&nsec3_rrset, NULL); if (ret != KNOT_EOK) { node_free(&new_node); diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c index 3c034c43e57659affce83570e2361761b258a029..d676d29757f213d1baf4d5dab2fe17cd4d981c77 100644 --- a/src/knot/nameserver/update.c +++ b/src/knot/nameserver/update.c @@ -281,7 +281,11 @@ static int zones_process_update_auth(struct query_data *qdata) ret = xfrin_apply_changesets(zone, chgsets, &new_contents); if (ret != KNOT_EOK) { log_zone_notice("%s: Failed to process: %s.\n", msg, knot_strerror(ret)); - qdata->rcode = KNOT_RCODE_SERVFAIL; + if (ret == KNOT_ETTL) { + qdata->rcode = KNOT_RCODE_REFUSED; + } else { + qdata->rcode = KNOT_RCODE_SERVFAIL; + } knot_changesets_free(&chgsets); free(msg); return ret; diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c index 0c9ade64d8322c779904315dab4fb1bb1d5188f3..059f4a72524bb69702c6bb4e1e1863f004c33ea6 100644 --- a/src/knot/updates/ddns.c +++ b/src/knot/updates/ddns.c @@ -667,18 +667,6 @@ static int process_add_normal(const zone_node_t *node, return KNOT_EOK; } - /* First check if the TTL of the new RR is equal to that of the first - * RR in the node's RRSet. If not, refuse the UPDATE. - */ - knot_rrset_t rr_in_zone = node_rrset(node, rr->type); - if (node_rrtype_exists(node, rr->type)) { - const knot_rdata_t *add_data = knot_rdataset_at(&rr->rrs, 0); - const knot_rdata_t *zone_data = knot_rdataset_at(&rr_in_zone.rrs, 0); - if (knot_rdata_ttl(add_data) != knot_rdata_ttl(zone_data)) { - return KNOT_ETTL; - } - } - const bool apex_ns = node_rrtype_exists(node, KNOT_RRTYPE_SOA) && rr->type == KNOT_RRTYPE_NS; return add_rr_to_chgset(rr, changeset, apex_ns ? apex_ns_rem : NULL); @@ -931,7 +919,7 @@ static uint16_t ret_to_rcode(int ret) { if (ret == KNOT_EMALF) { return KNOT_RCODE_FORMERR; - } else if (ret == KNOT_EDENIED || ret == KNOT_ETTL) { + } else if (ret == KNOT_EDENIED) { return KNOT_RCODE_REFUSED; } else { return KNOT_RCODE_SERVFAIL; diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c index 41d8d63d5f0f67ee9df710f1767d111ee23b87f8..5e5e493c6430a43165496808f0a98007f9626169 100644 --- a/src/knot/updates/xfr-in.c +++ b/src/knot/updates/xfr-in.c @@ -826,7 +826,7 @@ static int xfrin_apply_remove(knot_zone_contents_t *contents, } static int add_rr(zone_node_t *node, const knot_rrset_t *rr, - knot_changeset_t *chset) + knot_changeset_t *chset, bool master) { knot_rrset_t changed_rrset = node_rrset(node, rr->type); if (!knot_rrset_empty(&changed_rrset)) { @@ -843,37 +843,24 @@ static int add_rr(zone_node_t *node, const knot_rrset_t *rr, clear_new_rrs(node, rr->type); return ret; } - - // Extract copy, merge into it - knot_rdataset_t *changed_rrs = node_rdataset(node, rr->type); - ret = knot_rdataset_merge(changed_rrs, &rr->rrs, NULL); - if (ret != KNOT_EOK) { - clear_new_rrs(node, rr->type); - return ret; - } - } else { - // Inserting new RRSet, data will be copied. - bool ttl_err = false; - int ret = node_add_rrset(node, rr, &ttl_err); - if (ret != KNOT_EOK) { + } + // Insert new RR to RRSet, data will be copied. + int ret = node_add_rrset(node, rr); + if (ret != KNOT_EOK) { + if (ret == KNOT_ETTL) { + log_ttl_error(node, rr); + if (master) { + // TTL errors fatal on master. + return KNOT_ETTL; + } + } else { return ret; } - - if (ttl_err) { - char type_str[16] = { '\0' }; - knot_rrtype_to_string(rr->type, type_str, sizeof(type_str)); - char *name = knot_dname_to_str(rr->owner); - char *zname = knot_dname_to_str(chset->soa_from->owner); - log_zone_warning("Changes application to zone %s: TTL mismatch" - " in %s, type %s\n", zname, name, type_str); - free(name); - free(zname); - } } // Get changed RRS and store for possible rollback. knot_rdataset_t *rrs = node_rdataset(node, rr->type); - int ret = add_new_data(chset, rrs->data); + ret = add_new_data(chset, rrs->data); if (ret != KNOT_EOK) { knot_rdataset_clear(rrs, NULL); return ret; @@ -883,7 +870,7 @@ static int add_rr(zone_node_t *node, const knot_rrset_t *rr, } static int xfrin_apply_add(knot_zone_contents_t *contents, - knot_changeset_t *chset) + knot_changeset_t *chset, bool master) { knot_rr_ln_t *rr_node = NULL; WALK_LIST(rr_node, chset->add) { @@ -895,7 +882,7 @@ static int xfrin_apply_add(knot_zone_contents_t *contents, return KNOT_ENOMEM; } - int ret = add_rr(node, rr, chset); + int ret = add_rr(node, rr, chset, master); if (ret != KNOT_EOK) { return ret; } @@ -917,14 +904,13 @@ static int xfrin_apply_replace_soa(knot_zone_contents_t *contents, assert(!node_rrtype_exists(contents->apex, KNOT_RRTYPE_SOA)); - return add_rr(contents->apex, chset->soa_to, chset); + return add_rr(contents->apex, chset->soa_to, chset, false); } /*----------------------------------------------------------------------------*/ -static int xfrin_apply_changeset(list_t *old_rrs, list_t *new_rrs, - knot_zone_contents_t *contents, - knot_changeset_t *chset) +static int xfrin_apply_changeset(knot_zone_contents_t *contents, + knot_changeset_t *chset, bool master) { /* * Applies one changeset to the zone. Checks if the changeset may be @@ -948,7 +934,7 @@ static int xfrin_apply_changeset(list_t *old_rrs, list_t *new_rrs, return ret; } - ret = xfrin_apply_add(contents, chset); + ret = xfrin_apply_add(contents, chset, master); if (ret != KNOT_EOK) { return ret; } @@ -1160,9 +1146,8 @@ int xfrin_apply_changesets_directly(knot_zone_contents_t *contents, knot_changeset_t *set = NULL; WALK_LIST(set, chsets->sets) { - int ret = xfrin_apply_changeset(&set->old_data, - &set->new_data, - contents, set); + const bool master = true; // Only DNSSEC changesets are applied directly. + int ret = xfrin_apply_changeset(contents, set, master); if (ret != KNOT_EOK) { return ret; } @@ -1234,10 +1219,9 @@ int xfrin_apply_changesets(zone_t *zone, dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n", old_contents->apex, contents_copy->apex); knot_changeset_t *set = NULL; + const bool master = (zone_master(zone) == NULL); WALK_LIST(set, chsets->sets) { - ret = xfrin_apply_changeset(&set->old_data, - &set->new_data, - contents_copy, set); + ret = xfrin_apply_changeset(contents_copy, set, master); if (ret != KNOT_EOK) { xfrin_rollback_update(chsets, &contents_copy); dbg_xfrin("Failed to apply changesets to zone: " diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c index 5c0b3c256cb1b51894bc704d64f41fc79cd37dc9..c7a8db120cde0f5ec6e4a844aae9406cadedf210 100644 --- a/src/knot/zone/node.c +++ b/src/knot/zone/node.c @@ -164,7 +164,7 @@ zone_node_t *node_shallow_copy(const zone_node_t *src) return dst; } -int node_add_rrset(zone_node_t *node, const knot_rrset_t *rrset, bool *ttl_err) +int node_add_rrset(zone_node_t *node, const knot_rrset_t *rrset) { if (node == NULL || rrset == NULL) { return KNOT_EINVAL; @@ -173,13 +173,14 @@ int node_add_rrset(zone_node_t *node, const knot_rrset_t *rrset, bool *ttl_err) for (uint16_t i = 0; i < node->rrset_count; ++i) { if (node->rrs[i].type == rrset->type) { struct rr_data *node_data = &node->rrs[i]; - if (ttl_err) { - // Do TTL check. - *ttl_err = ttl_error(node_data, rrset); + const bool ttl_err = ttl_error(node_data, rrset); + int ret = knot_rdataset_merge(&node_data->rrs, + &rrset->rrs, NULL); + if (ret != KNOT_EOK) { + return ret; + } else { + return ttl_err ? KNOT_ETTL : KNOT_EOK; } - - return knot_rdataset_merge(&node_data->rrs, - &rrset->rrs, NULL); } } diff --git a/src/knot/zone/node.h b/src/knot/zone/node.h index 65e4ff22629cf80e782d8a76cb20ca23c70de857..e49f88048935e4a6f6ad59bf6aee1a945f670b95 100644 --- a/src/knot/zone/node.h +++ b/src/knot/zone/node.h @@ -126,12 +126,10 @@ zone_node_t *node_shallow_copy(const zone_node_t *src); * * \param node Node to add the RRSet to. * \param rrset RRSet to add. - * \param ttl_err Set to true if TTL error occured when inserting. New zone API - * will obsolete this parameter. * * \return KNOT_E* */ -int node_add_rrset(zone_node_t *node, const knot_rrset_t *rrset, bool *ttl_err); +int node_add_rrset(zone_node_t *node, const knot_rrset_t *rrset); /*! * \brief Removes data for given RR type from node. diff --git a/src/knot/zone/zone-contents.c b/src/knot/zone/zone-contents.c index 7129c1ea9adb10e067d2ba03342738b8fdd69c62..c6bf11249ceb0284ea3e28cf7acc5d911b7117f2 100644 --- a/src/knot/zone/zone-contents.c +++ b/src/knot/zone/zone-contents.c @@ -644,7 +644,7 @@ static zone_node_t *knot_zone_contents_get_nsec3_node( static int insert_rr(knot_zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n, - bool nsec3, bool *ttl_err) + bool nsec3) { if (z == NULL || knot_rrset_empty(rr) || n == NULL) { return KNOT_EINVAL; @@ -674,7 +674,7 @@ static int insert_rr(knot_zone_contents_t *z, } } - return node_add_rrset(*n, rr, ttl_err); + return node_add_rrset(*n, rr); } static int recreate_normal_tree(const knot_zone_contents_t *z, @@ -779,9 +779,9 @@ static bool rrset_is_nsec3rel(const knot_rrset_t *rr) } int knot_zone_contents_add_rr(knot_zone_contents_t *z, - const knot_rrset_t *rr, zone_node_t **n, bool *ttl_err) + const knot_rrset_t *rr, zone_node_t **n) { - return insert_rr(z, rr, n, rrset_is_nsec3rel(rr), ttl_err); + return insert_rr(z, rr, n, rrset_is_nsec3rel(rr)); } /*----------------------------------------------------------------------------*/ diff --git a/src/knot/zone/zone-contents.h b/src/knot/zone/zone-contents.h index d8b1716bf5aef6841e0aa6b01514153a3380f44a..9eeac9a6b3cbf769308b985a4f3eab9a675fe715 100644 --- a/src/knot/zone/zone-contents.h +++ b/src/knot/zone/zone-contents.h @@ -93,7 +93,7 @@ void knot_zone_contents_set_gen_old(knot_zone_contents_t *contents); void knot_zone_contents_set_gen_new(knot_zone_contents_t *contents); int knot_zone_contents_add_rr(knot_zone_contents_t *z, - const knot_rrset_t *rr, zone_node_t **n, bool *ttl_err); + const knot_rrset_t *rr, zone_node_t **n); int knot_zone_contents_remove_node(knot_zone_contents_t *contents, const knot_dname_t *owner); diff --git a/src/knot/zone/zone-create.c b/src/knot/zone/zone-create.c index 70f7d076e1a3dc4493bc613da56b0860d50c6163..0f928860179c382358366b0db6e259acb09c8eff 100644 --- a/src/knot/zone/zone-create.c +++ b/src/knot/zone/zone-create.c @@ -55,9 +55,8 @@ static int add_rdata_to_rr(knot_rrset_t *rrset, const zs_scanner_t *scanner) scanner->r_ttl, NULL); } -static bool handle_err(zcreator_t *zc, - const knot_rrset_t *rr, - int ret) +static bool handle_err(zcreator_t *zc, const zone_node_t *node, + const knot_rrset_t *rr, int ret, bool master) { char *zname = zc->z ? knot_dname_to_str(zc->z->apex->owner) : NULL; char *rrname = rr ? knot_dname_to_str(rr->owner) : NULL; @@ -67,6 +66,13 @@ static bool handle_err(zcreator_t *zc, free(zname); free(rrname); return true; + } else if (ret == KNOT_ETTL) { + free(zname); + free(rrname); + assert(node); + log_ttl_error(node, rr); + // Fail if we're the master for this zone. + return !master; } else { log_zone_error("Zone %s: Cannot process record %s, stopping.\n", zname ? zname : "unknown", rrname ? rrname : "unknown"); @@ -76,8 +82,7 @@ static bool handle_err(zcreator_t *zc, } } -static int log_ttl(const zcreator_t *zc, const zone_node_t *node, - const knot_rrset_t *rr) +void log_ttl_error(const zone_node_t *node, const knot_rrset_t *rr) { err_handler_t err_handler; err_handler_init(&err_handler); @@ -91,16 +96,9 @@ static int log_ttl(const zcreator_t *zc, const zone_node_t *node, *info_str = '\0'; } - if (zc->master) { - /*!< \todo REPLACE WITH FATAL ERROR */ - err_handler_handle_error(&err_handler, node, - ZC_ERR_TTL_MISMATCH, info_str); - return KNOT_EMALF; - } else { - err_handler_handle_error(&err_handler, node, - ZC_ERR_TTL_MISMATCH, info_str); - return KNOT_EOK; - } + /*!< \todo REPLACE WITH FATAL ERROR for master. */ + err_handler_handle_error(&err_handler, node, + ZC_ERR_TTL_MISMATCH, info_str); } int zcreator_step(zcreator_t *zc, const knot_rrset_t *rr) @@ -115,25 +113,19 @@ int zcreator_step(zcreator_t *zc, const knot_rrset_t *rr) return KNOT_EOK; } - bool ttl_err = false; zone_node_t *node = NULL; - int ret = knot_zone_contents_add_rr(zc->z, rr, &node, &ttl_err); - if (ret < 0) { - if (!handle_err(zc, rr, ret)) { + int ret = knot_zone_contents_add_rr(zc->z, rr, &node); + if (ret != KNOT_EOK) { + if (!handle_err(zc, node, rr, ret, zc->master)) { // Fatal error return ret; } - // Recoverable error, skip record - return KNOT_EOK; - } - assert(node); - - if (ttl_err) { - ret = log_ttl(zc, node, rr); - if (ret != KNOT_EOK) { - return ret; + if (ret == KNOT_EOUTOFZONE) { + // Skip out-of-zone record + return KNOT_EOK; } } + assert(node); // Do node semantic checks err_handler_t err_handler; diff --git a/src/knot/zone/zone-create.h b/src/knot/zone/zone-create.h index 8cb15d4ed69271c88a4007587e4fa547e1e8fd6e..92e26c3de113be409df4350904af295d7a539887 100644 --- a/src/knot/zone/zone-create.h +++ b/src/knot/zone/zone-create.h @@ -82,10 +82,30 @@ knot_zone_contents_t *zonefile_load(zloader_t *loader); */ void zonefile_close(zloader_t *loader); +/*! + * \brief Adds one RR into zone. + * + * \param zl Zone loader. + * \param rr RR to add. + * + * \return KNOT_E* + */ int zcreator_step(zcreator_t *zl, const knot_rrset_t *rr); +/*! + * \brief Scanner error processing function. + * \param scanner Scanner to use. + */ void process_error(zs_scanner_t *scanner); +/*! + * \brief Logs TTL mismatch error. + * + * \param node Node with TTL mismatch. + * \param rr RR that caused the mismatch. + */ +void log_ttl_error(const zone_node_t *node, const knot_rrset_t *rr); + #endif /* _KNOTD_ZONELOAD_H_ */ /*! @} */ diff --git a/tests/process_query.c b/tests/process_query.c index e94abd07d138298d59a187839f3e7c00046020ec..f0b4d76e968ea642fa679ef8208c1533783bc456 100644 --- a/tests/process_query.c +++ b/tests/process_query.c @@ -52,7 +52,7 @@ void create_root_zone(server_t *server, mm_ctx_t *mm) KNOT_RRTYPE_SOA, KNOT_CLASS_IN, NULL); knot_rrset_add_rdata(soa_rrset, SOA_RDATA, SOA_RDLEN, 7200, NULL); - node_add_rrset(root->contents->apex, soa_rrset, NULL); + node_add_rrset(root->contents->apex, soa_rrset); /* Bake the zone. */ zone_node_t *first_nsec3 = NULL, *last_nsec3 = NULL;