/*! * \brief Connect two nodes by adding a NSEC RR into the first node. * * Callback function, signature chain_iterate_cb. * * \param a First node. * \param b Second node (immediate follower of a). * \param data Pointer to nsec_chain_iterate_data_t holding parameters * including changeset. * * \return Error code, KNOT_EOK if successful. */ static int connect_nsec_nodes(zone_node_t *a, zone_node_t *b, nsec_chain_iterate_data_t *data) { assert(a); assert(b); assert(data); if (b->rrset_count == 0 || b->flags & NODE_FLAGS_NONAUTH) { return NSEC_NODE_SKIP; } int ret = 0; /*! * If the node has no other RRSets than NSEC (and possibly RRSIGs), * just remove the NSEC and its RRSIG, they are redundant */ if (node_rrtype_exists(b, KNOT_RRTYPE_NSEC) && knot_nsec_empty_nsec_and_rrsigs_in_node(b)) { ret = knot_nsec_changeset_remove(b, data->changeset); if (ret != KNOT_EOK) { return ret; } // Skip the 'b' node return NSEC_NODE_SKIP; } // create new NSEC knot_rrset_t *new_nsec = create_nsec_rrset(a, b, data->ttl); if (!new_nsec) { dbg_dnssec_detail("Failed to create new NSEC.\n"); return KNOT_ENOMEM; } knot_rrset_t old_nsec = node_rrset(a, KNOT_RRTYPE_NSEC); if (!knot_rrset_empty(&old_nsec)) { if (knot_rrset_equal(new_nsec, &old_nsec, KNOT_RRSET_COMPARE_WHOLE)) { // current NSEC is valid, do nothing dbg_dnssec_detail("NSECs equal.\n"); knot_rrset_free(&new_nsec, NULL); return KNOT_EOK; } dbg_dnssec_detail("NSECs not equal, replacing.\n"); // Mark the node so that we do not sign this NSEC a->flags |= NODE_FLAGS_REMOVED_NSEC; ret = knot_nsec_changeset_remove(a, data->changeset); if (ret != KNOT_EOK) { knot_rrset_free(&new_nsec, NULL); return ret; } } dbg_dnssec_detail("Adding new NSEC to changeset.\n"); // Add new NSEC to the changeset (no matter if old was removed) return knot_changeset_add_rrset(data->changeset, new_nsec, KNOT_CHANGESET_ADD); }
/* @note Packet equivalence test, 5 checks. */ static void packet_match(knot_pkt_t *in, knot_pkt_t *out) { /* Check counts */ is_int(knot_wire_get_qdcount(out->wire), knot_wire_get_qdcount(in->wire), "pkt: QD match"); is_int(knot_wire_get_ancount(out->wire), knot_wire_get_ancount(in->wire), "pkt: AN match"); is_int(knot_wire_get_nscount(out->wire), knot_wire_get_nscount(in->wire), "pkt: NS match"); is_int(knot_wire_get_arcount(out->wire), knot_wire_get_arcount(in->wire), "pkt: AR match"); /* Check RRs */ int rr_matched = 0; for (unsigned i = 0; i < NAMECOUNT; ++i) { if (knot_rrset_equal(&out->rr[i], &in->rr[i], KNOT_RRSET_COMPARE_WHOLE) > 0) { ++rr_matched; } } is_int(NAMECOUNT, rr_matched, "pkt: RR content match"); }
int main(int argc, char *argv[]) { plan(23); // Test with NULL changeset ok(changeset_size(NULL) == 0, "changeset: NULL size"); ok(changeset_empty(NULL), "changeset: NULL empty"); // Test creation. knot_dname_t *d = knot_dname_from_str_alloc("test."); assert(d); changeset_t *ch = changeset_new(d); knot_dname_free(&d, NULL); ok(ch != NULL, "changeset: new"); ok(changeset_empty(ch), "changeset: empty"); ch->soa_to = (knot_rrset_t *)0xdeadbeef; ok(!changeset_empty(ch), "changseset: empty SOA"); ch->soa_to = NULL; ok(changeset_size(ch) == 0, "changeset: empty size"); // Test additions. d = knot_dname_from_str_alloc("non.terminals.test."); assert(d); knot_rrset_t *apex_txt_rr = knot_rrset_new(d, KNOT_RRTYPE_TXT, KNOT_CLASS_IN, NULL); assert(apex_txt_rr); uint8_t data[8] = "\7teststr"; knot_rrset_add_rdata(apex_txt_rr, data, sizeof(data), 3600, NULL); int ret = changeset_add_rrset(ch, apex_txt_rr); ok(ret == KNOT_EOK, "changeset: add RRSet"); ok(changeset_size(ch) == 1, "changeset: size add"); ret = changeset_rem_rrset(ch, apex_txt_rr); ok(ret == KNOT_EOK, "changeset: rem RRSet"); ok(changeset_size(ch) == 2, "changeset: size remove"); ok(!changeset_empty(ch), "changeset: not empty"); // Add another RR to node. knot_rrset_t *apex_spf_rr = knot_rrset_new(d, KNOT_RRTYPE_SPF, KNOT_CLASS_IN, NULL); assert(apex_spf_rr); knot_rrset_add_rdata(apex_spf_rr, data, sizeof(data), 3600, NULL); ret = changeset_add_rrset(ch, apex_spf_rr); ok(ret == KNOT_EOK, "changeset: add multiple"); // Add another node. knot_dname_free(&d, NULL); d = knot_dname_from_str_alloc("here.come.more.non.terminals.test"); assert(d); knot_rrset_t *other_rr = knot_rrset_new(d, KNOT_RRTYPE_TXT, KNOT_CLASS_IN, NULL); assert(other_rr); knot_rrset_add_rdata(other_rr, data, sizeof(data), 3600, NULL); ret = changeset_add_rrset(ch, other_rr); ok(ret == KNOT_EOK, "changeset: remove multiple"); // Test add traversal. changeset_iter_t it; ret = changeset_iter_add(&it, ch, true); ok(ret == KNOT_EOK, "changeset: create iter add"); // Order: non.terminals.test. TXT, SPF, here.come.more.non.terminals.test. TXT. knot_rrset_t iter = changeset_iter_next(&it); bool trav_ok = knot_rrset_equal(&iter, apex_txt_rr, KNOT_RRSET_COMPARE_WHOLE); iter = changeset_iter_next(&it); trav_ok = trav_ok && knot_rrset_equal(&iter, apex_spf_rr, KNOT_RRSET_COMPARE_WHOLE); iter = changeset_iter_next(&it); trav_ok = trav_ok && knot_rrset_equal(&iter, other_rr, KNOT_RRSET_COMPARE_WHOLE); ok(trav_ok, "changeset: add traversal"); iter = changeset_iter_next(&it); changeset_iter_clear(&it); ok(knot_rrset_empty(&iter), "changeset: traversal: skip non-terminals"); // Test remove traversal. ret = changeset_iter_rem(&it, ch, false); ok(ret == KNOT_EOK, "changeset: create iter rem"); iter = changeset_iter_next(&it); ok(knot_rrset_equal(&iter, apex_txt_rr, KNOT_RRSET_COMPARE_WHOLE), "changeset: rem traversal"); changeset_iter_clear(&it); // Test all traversal - just count. ret = changeset_iter_all(&it, ch, false); ok(ret == KNOT_EOK, "changest: create iter all"); size_t size = 0; iter = changeset_iter_next(&it); while (!knot_rrset_empty(&iter)) { ++size; iter = changeset_iter_next(&it); } changeset_iter_clear(&it); ok(size == 4, "changeset: iter all"); // Create new changeset. knot_dname_free(&d, NULL); d = knot_dname_from_str_alloc("test."); assert(d); changeset_t *ch2 = changeset_new(d); knot_dname_free(&d, NULL); assert(ch2); // Add something to add section. knot_dname_free(&apex_txt_rr->owner, NULL); apex_txt_rr->owner = knot_dname_from_str_alloc("something.test."); assert(apex_txt_rr->owner); ret = changeset_add_rrset(ch2, apex_txt_rr); assert(ret == KNOT_EOK); // Add something to remove section. knot_dname_free(&apex_txt_rr->owner, NULL); apex_txt_rr->owner = knot_dname_from_str_alloc("and.now.for.something.completely.different.test."); assert(apex_txt_rr->owner); ret = changeset_rem_rrset(ch2, apex_txt_rr); assert(ret == KNOT_EOK); // Test merge. ret = changeset_merge(ch, ch2); ok(ret == KNOT_EOK && changeset_size(ch) == 6, "changeset: merge"); // Test cleanup. changeset_clear(ch); ok(changeset_empty(ch), "changeset: clear"); free(ch); list_t chgs; init_list(&chgs); add_head(&chgs, &ch2->n); changesets_clear(&chgs); ok(changeset_empty(ch2), "changeset: clear list"); free(ch2); knot_rrset_free(&apex_txt_rr, NULL); knot_rrset_free(&apex_spf_rr, NULL); knot_rrset_free(&other_rr, NULL); return 0; }