1 /*  Copyright (C) 2019 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 /*!
18  * \file
19  *
20  * \brief RRSet structure and API for manipulating it.
21  *
22  * \addtogroup rr
23  * @{
24  */
25 
26 #pragma once
27 
28 #include <stdint.h>
29 #include <stdbool.h>
30 
31 #include "libknot/dname.h"
32 #include "libknot/descriptor.h"
33 #include "libknot/mm_ctx.h"
34 #include "libknot/rdataset.h"
35 
36 /*!
37  * \brief Structure for representing RRSet.
38  *
39  * For RRSet definition see RFC2181, Section 5.
40  */
41 typedef struct {
42 	knot_dname_t *owner;  /*!< Domain name being the owner of the RRSet. */
43 	uint32_t ttl;         /*!< TTL of the RRset. */
44 	uint16_t type;        /*!< TYPE of the RRset. */
45 	uint16_t rclass;      /*!< CLASS of the RRSet. */
46 	knot_rdataset_t rrs;  /*!< RRSet's RRs */
47 	/* Optional fields. */
48 	void *additional;     /*!< Additional records. */
49 } knot_rrset_t;
50 
51 /*!
52  * \brief Creates a new RRSet with the given properties.
53  *
54  * The created RRSet contains no RDATAs (i.e. is actually empty).
55  *
56  * \param owner   OWNER of the RRSet.
57  * \param type    TYPE of the RRSet.
58  * \param rclass  CLASS of the RRSet.
59  * \param ttl     TTL of the RRSet.
60  * \param mm      Memory context.
61  *
62  * \return New RRSet structure or NULL if an error occurred.
63  */
64 knot_rrset_t *knot_rrset_new(const knot_dname_t *owner, uint16_t type,
65                              uint16_t rclass, uint32_t ttl, knot_mm_t *mm);
66 
67 /*!
68  * \brief Initializes RRSet structure with given data.
69  *
70  * \param rrset   RRSet to init.
71  * \param owner   RRSet owner to use.
72  * \param type    RR type to use.
73  * \param rclass  Class to use.
74  * \param ttl     TTL to use.
75  */
knot_rrset_init(knot_rrset_t * rrset,knot_dname_t * owner,uint16_t type,uint16_t rclass,uint32_t ttl)76 inline static void knot_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
77                                    uint16_t type, uint16_t rclass, uint32_t ttl)
78 {
79 	if (rrset != NULL) {
80 		rrset->owner = owner;
81 		rrset->type = type;
82 		rrset->rclass = rclass;
83 		rrset->ttl = ttl;
84 		knot_rdataset_init(&rrset->rrs);
85 		rrset->additional = NULL;
86 	}
87 }
88 
89 /*!
90  * \brief Initializes given RRSet structure.
91  *
92  * \param rrset  RRSet to init.
93  */
knot_rrset_init_empty(knot_rrset_t * rrset)94 inline static void knot_rrset_init_empty(knot_rrset_t *rrset)
95 {
96 	knot_rrset_init(rrset, NULL, 0, KNOT_CLASS_IN, 0);
97 }
98 
99 /*!
100  * \brief Creates new RRSet from \a src RRSet.
101  *
102  * \param src  Source RRSet.
103  * \param mm   Memory context.
104  *
105  * \retval Pointer to new RRSet if all went OK.
106  * \retval NULL on error.
107  */
108 knot_rrset_t *knot_rrset_copy(const knot_rrset_t *src, knot_mm_t *mm);
109 
110 /*!
111  * \brief Destroys the RRSet structure and all its substructures.
112  *
113  * \param rrset  RRset to be destroyed.
114  * \param mm     Memory context.
115  */
116 void knot_rrset_free(knot_rrset_t *rrset, knot_mm_t *mm);
117 
118 /*!
119  * \brief Frees structures inside RRSet, but not the RRSet itself.
120  *
121  * \param rrset  RRSet to be cleared.
122  * \param mm     Memory context used for allocations.
123  */
124 void knot_rrset_clear(knot_rrset_t *rrset, knot_mm_t *mm);
125 
126 /*!
127  * \brief Adds the given RDATA to the RRSet.
128  *
129  * \param rrset  RRSet to add the RDATA to.
130  * \param data   RDATA to add to the RRSet.
131  * \param len    Length of RDATA.
132  * \param mm     Memory context.
133  *
134  * \return KNOT_E*
135  */
136 int knot_rrset_add_rdata(knot_rrset_t *rrset, const uint8_t *data, uint16_t len,
137                          knot_mm_t *mm);
138 
139 /*!
140  * \brief Compares two RRSets for equality.
141  *
142  * \param r1   First RRSet.
143  * \param r2   Second RRSet.
144  * \param incl_ttl  Compare also TTLs for equality.
145  *
146  * \retval True   if RRSets are equal.
147  * \retval False  if RRSets are not equal.
148  */
149 bool knot_rrset_equal(const knot_rrset_t *r1, const knot_rrset_t *r2,
150                       bool incl_ttl);
151 
152 /*!
153  * \brief Checks whether RRSet is empty.
154  *
155  * \param rrset  RRSet to check.
156  *
157  * \retval True if RRSet is empty.
158  * \retval False if RRSet is not empty.
159  */
knot_rrset_empty(const knot_rrset_t * rrset)160 inline static bool knot_rrset_empty(const knot_rrset_t *rrset)
161 {
162 	return rrset == NULL || rrset->rrs.count == 0;
163 }
164 
165 /*!
166  * \brief Return whether the RR type is NSEC3 related (NSEC3 or RRSIG).
167  */
168 bool knot_rrset_is_nsec3rel(const knot_rrset_t *rr);
169 
170 /*!
171  * \brief Convert one RR into canonical format.
172  *
173  * Owner is always converted to lowercase. RDATA domain names are converted only
174  * for types listed in RFC 4034, Section 6.2, except for NSEC (updated by
175  * RFC 6840, Section 5.1) and A6 (not supported).
176  *
177  * \note If RRSet with more RRs is given to this function, only the first RR
178  *       will be converted.
179  * \warning This function expects either empty RDATA or full, not malformed
180  *          RDATA. If malformed RRSet is passed to this function, memory errors
181  *          may occur.
182  *
183  * \param rrset  RR to convert.
184  */
185 int knot_rrset_rr_to_canonical(knot_rrset_t *rrset);
186 
187 /*!
188  * \brief Size of rrset in wire format.
189  *
190  * \retval size in bytes
191  */
192 size_t knot_rrset_size(const knot_rrset_t *rrset);
193 
194 /*! @} */
195