summaryrefslogtreecommitdiffstats
path: root/src/knot/dnssec/nsec-chain.h
blob: 362780e1bc1463fed3c3417d22e852cc8cda724f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#pragma once

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>

#include "knot/zone/contents.h"
#include "knot/updates/zone-update.h"
#include "libdnssec/nsec.h"

/*!
 * \brief Parameters to be used in connect_nsec_nodes callback.
 */
typedef struct {
	uint32_t ttl;          // TTL for NSEC(3) records
	zone_update_t *update; // The zone update for NSECs
	uint16_t nsec_type;    // NSEC or NSEC3
	const dnssec_nsec3_params_t *nsec3_params;
} nsec_chain_iterate_data_t;

/*!
 * \brief Used to control changeset iteration functions.
 */
enum {
	NSEC_NODE_SKIP = 1,
};

/*!
 * \brief Callback used when creating NSEC chains.
 */
typedef int (*chain_iterate_create_cb)(zone_node_t *, zone_node_t *,
                                       nsec_chain_iterate_data_t *);

/*!
 * \brief Add all RR types from a node into the bitmap.
 */
void bitmap_add_node_rrsets(dnssec_nsec_bitmap_t *bitmap, const zone_node_t *node,
                            bool exact);

/*!
 * \brief Check that the NSEC(3) record in node A points to B.
 *
 * \param a      Node A.
 * \param b      Node B.
 * \param data   Validation context.
 *
 * \retval NSEC_NODE_SKIP            Node B is not part of NSEC chain, call again with A and B->next.
 * \retval KNOT_DNSSEC_ENSEC_CHAIN   The NSEC(3) chain is broken.
 * \return KNOT_E*
 */
int nsec_check_connect_nodes(zone_node_t *a, zone_node_t *b,
                             nsec_chain_iterate_data_t *data);

/*!
 * \brief Check NSEC connections of updated nodes.
 *
 * \param tree   Trie with updated nodes.
 * \param data   Validation context.
 *
 * \return KNOT_DNSSEC_ENSEC_CHAIN, KNOT_E*
 */
int nsec_check_new_connects(zone_tree_t *tree, nsec_chain_iterate_data_t *data);

/*!
 * \brief Check NSEC(3) bitmaps for updated nodes.
 *
 * \param nsec_ptrs   Trie with nodes to be checked.
 * \param data        Validation context.
 *
 * \return KNOT_DNSSEC_ENSEC_BITMAP, KNOT_E*
 */
int nsec_check_bitmaps(zone_tree_t *nsec_ptrs, nsec_chain_iterate_data_t *data);

/*!
 * \brief Call a function for each piece of the chain formed by sorted nodes.
 *
 * \note If the callback function returns anything other than KNOT_EOK, the
 *       iteration is terminated and the error code is propagated.
 *
 * \param nodes     Zone nodes.
 * \param callback  Callback function.
 * \param data      Custom data supplied to the callback function.
 *
 * \return Error code, KNOT_EOK if successful.
 */
int knot_nsec_chain_iterate_create(zone_tree_t *nodes,
                                   chain_iterate_create_cb callback,
                                   nsec_chain_iterate_data_t *data);

/*!
 * \brief Call the chain-connecting function for modified records and their neighbours.
 *
 * \param node_ptrs  Tree of those nodes that have ben changed by the update.
 * \param callback   Callback function.
 * \param cb_reconn  Callback for re-connecting "next" link to another node.
 * \param data       Custom data supplied, incl. changeset to be updated.
 *
 * \retval KNOT_ENORECORD if the chain must be recreated from scratch.
 * \return KNOT_E*
 */
int knot_nsec_chain_iterate_fix(zone_tree_t *node_ptrs,
                                chain_iterate_create_cb callback,
                                chain_iterate_create_cb cb_reconn,
                                nsec_chain_iterate_data_t *data);

/*!
 * \brief Add entry for removed NSEC(3) and its RRSIG to the changeset.
 *
 * \param n          Node to extract NSEC(3) from.
 * \param update     Update to add the old RR removal into.
 *
 * \return Error code, KNOT_EOK if successful.
 */
int knot_nsec_changeset_remove(const zone_node_t *n, zone_update_t *update);

/*!
 * \brief Checks whether the node is empty or eventually contains only NSEC and
 *        RRSIGs.
 *
 * \param n Node to check.
 *
 * \retval true if the node is empty or contains only NSEC and RRSIGs.
 * \retval false otherwise.
 */
bool knot_nsec_empty_nsec_and_rrsigs_in_node(const zone_node_t *n);

/*!
 * \brief Create new NSEC chain.
 *
 * \param update     Zone update to create NSEC chain for.
 * \param ttl        TTL for created NSEC records.
 *
 * \return Error code, KNOT_EOK if successful.
 */
int knot_nsec_create_chain(zone_update_t *update, uint32_t ttl);

/*!
 * \brief Fix existing NSEC chain to cover the changes in zone contents.
 *
 * \param update     Zone update to update NSEC chain for.
 * \param ttl        TTL for created NSEC records.
 *
 * \retval KNOT_ENORECORD if the chain must be recreated from scratch.
 * \return KNOT_E*
 */
int knot_nsec_fix_chain(zone_update_t *update, uint32_t ttl);

/*!
 * \brief Validate NSEC chain in new_cont as whole.
 *
 * \note new_cont must have been adjusted already!
 */
int knot_nsec_check_chain(zone_update_t *update);

/*!
 * \brief Validate NSEC chain in new_cont incrementally.
 */
int knot_nsec_check_chain_fix(zone_update_t *update);