1 /* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> 2 3 This program is free software: you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation, either version 3 of the License, or 6 (at your option) any later version. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <https://www.gnu.org/licenses/>. 15 */ 16 17 #pragma once 18 19 #include <assert.h> 20 #include <stdbool.h> 21 #include <stdint.h> 22 23 #include "knot/zone/contents.h" 24 #include "knot/updates/zone-update.h" 25 #include "libdnssec/nsec.h" 26 27 /*! 28 * \brief Parameters to be used in connect_nsec_nodes callback. 29 */ 30 typedef struct { 31 uint32_t ttl; // TTL for NSEC(3) records 32 zone_update_t *update; // The zone update for NSECs 33 uint16_t nsec_type; // NSEC or NSEC3 34 const dnssec_nsec3_params_t *nsec3_params; 35 } nsec_chain_iterate_data_t; 36 37 /*! 38 * \brief Used to control changeset iteration functions. 39 */ 40 enum { 41 NSEC_NODE_SKIP = 1, 42 }; 43 44 /*! 45 * \brief Callback used when creating NSEC chains. 46 */ 47 typedef int (*chain_iterate_create_cb)(zone_node_t *, zone_node_t *, 48 nsec_chain_iterate_data_t *); 49 50 /*! 51 * \brief Add all RR types from a node into the bitmap. 52 */ 53 void bitmap_add_node_rrsets(dnssec_nsec_bitmap_t *bitmap, const zone_node_t *node, 54 bool exact); 55 56 /*! 57 * \brief Check that the NSEC(3) record in node A points to B. 58 * 59 * \param a Node A. 60 * \param b Node B. 61 * \param data Validation context. 62 * 63 * \retval NSEC_NODE_SKIP Node B is not part of NSEC chain, call again with A and B->next. 64 * \retval KNOT_DNSSEC_ENSEC_CHAIN The NSEC(3) chain is broken. 65 * \return KNOT_E* 66 */ 67 int nsec_check_connect_nodes(zone_node_t *a, zone_node_t *b, 68 nsec_chain_iterate_data_t *data); 69 70 /*! 71 * \brief Check NSEC connections of updated nodes. 72 * 73 * \param tree Trie with updated nodes. 74 * \param data Validation context. 75 * 76 * \return KNOT_DNSSEC_ENSEC_CHAIN, KNOT_E* 77 */ 78 int nsec_check_new_connects(zone_tree_t *tree, nsec_chain_iterate_data_t *data); 79 80 /*! 81 * \brief Check NSEC(3) bitmaps for updated nodes. 82 * 83 * \param nsec_ptrs Trie with nodes to be checked. 84 * \param data Validation context. 85 * 86 * \return KNOT_DNSSEC_ENSEC_BITMAP, KNOT_E* 87 */ 88 int nsec_check_bitmaps(zone_tree_t *nsec_ptrs, nsec_chain_iterate_data_t *data); 89 90 /*! 91 * \brief Call a function for each piece of the chain formed by sorted nodes. 92 * 93 * \note If the callback function returns anything other than KNOT_EOK, the 94 * iteration is terminated and the error code is propagated. 95 * 96 * \param nodes Zone nodes. 97 * \param callback Callback function. 98 * \param data Custom data supplied to the callback function. 99 * 100 * \return Error code, KNOT_EOK if successful. 101 */ 102 int knot_nsec_chain_iterate_create(zone_tree_t *nodes, 103 chain_iterate_create_cb callback, 104 nsec_chain_iterate_data_t *data); 105 106 /*! 107 * \brief Call the chain-connecting function for modified records and their neighbours. 108 * 109 * \param node_ptrs Tree of those nodes that have ben changed by the update. 110 * \param callback Callback function. 111 * \param cb_reconn Callback for re-connecting "next" link to another node. 112 * \param data Custom data supplied, incl. changeset to be updated. 113 * 114 * \retval KNOT_ENORECORD if the chain must be recreated from scratch. 115 * \return KNOT_E* 116 */ 117 int knot_nsec_chain_iterate_fix(zone_tree_t *node_ptrs, 118 chain_iterate_create_cb callback, 119 chain_iterate_create_cb cb_reconn, 120 nsec_chain_iterate_data_t *data); 121 122 /*! 123 * \brief Add entry for removed NSEC(3) and its RRSIG to the changeset. 124 * 125 * \param n Node to extract NSEC(3) from. 126 * \param update Update to add the old RR removal into. 127 * 128 * \return Error code, KNOT_EOK if successful. 129 */ 130 int knot_nsec_changeset_remove(const zone_node_t *n, zone_update_t *update); 131 132 /*! 133 * \brief Checks whether the node is empty or eventually contains only NSEC and 134 * RRSIGs. 135 * 136 * \param n Node to check. 137 * 138 * \retval true if the node is empty or contains only NSEC and RRSIGs. 139 * \retval false otherwise. 140 */ 141 bool knot_nsec_empty_nsec_and_rrsigs_in_node(const zone_node_t *n); 142 143 /*! 144 * \brief Create new NSEC chain. 145 * 146 * \param update Zone update to create NSEC chain for. 147 * \param ttl TTL for created NSEC records. 148 * 149 * \return Error code, KNOT_EOK if successful. 150 */ 151 int knot_nsec_create_chain(zone_update_t *update, uint32_t ttl); 152 153 /*! 154 * \brief Fix existing NSEC chain to cover the changes in zone contents. 155 * 156 * \param update Zone update to update NSEC chain for. 157 * \param ttl TTL for created NSEC records. 158 * 159 * \retval KNOT_ENORECORD if the chain must be recreated from scratch. 160 * \return KNOT_E* 161 */ 162 int knot_nsec_fix_chain(zone_update_t *update, uint32_t ttl); 163 164 /*! 165 * \brief Validate NSEC chain in new_cont as whole. 166 * 167 * \note new_cont must have been adjusted already! 168 */ 169 int knot_nsec_check_chain(zone_update_t *update); 170 171 /*! 172 * \brief Validate NSEC chain in new_cont incrementally. 173 */ 174 int knot_nsec_check_chain_fix(zone_update_t *update); 175