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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
|
/*!
* \file rdata.h
*
* \author Lubos Slovak <lubos.slovak@nic.cz>
*
* \brief Structures representing RDATA and its items and API for manipulating
* both.
*
* \addtogroup libknot
* @{
*/
/* Copyright (C) 2011 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _KNOT_RDATA_H_
#define _KNOT_RDATA_H_
#include <stdint.h>
#include <string.h>
#include "dname.h"
#include "util/descriptor.h"
/*----------------------------------------------------------------------------*/
/*!
* \brief RDATA item structure.
*
* Each RDATA may be logically divided into items, each of possible different
* type. This structure distinguishes between general data (\a raw_data)
* represented as an array of octets, and domain name (\a dname) as domain names
* require special treatment within some RDATA (e.g. compressing in packets).
*/
union knot_rdata_item {
knot_dname_t *dname; /*!< RDATA item represented as a domain name. */
/*!
* \brief RDATA item represented as raw array of octets.
*
* The first two bytes hold the length of the item in bytes. The length
* is stored in little endian.
*
* In some cases the stored length is also used in the wire format of
* RDATA (e.g. character-data as defined in RFC1035). In such case,
* the length should be less than 256, so that it fits into one byte
* in the wireformat.
*
* \todo Store the length in system byte order.
*/
uint16_t *raw_data;
};
typedef union knot_rdata_item knot_rdata_item_t;
/*----------------------------------------------------------------------------*/
/*!
* \brief RDATA structure.
*
* Each RDATA may be logically divided into items, each of possible different
* type (see knot_rdata_item). This structure stores an array of such items.
* It is not dynamic, so any RDATA structure may hold either 0 or one specified
* number of items which cannot be changed later. However, the number of items
* may be different for each RDATA structure. The number of items should be
* given by descriptors for each RR type. Some types may have variable number
* of items. In such cases, the last item in the array will be set tu NULL
* to distinguish the actual count of items.
*
* This structure does not hold information about the RDATA items, such as
* what type is which item or how long are they. This information should be
* stored elsewhere (in descriptors) as it is RR-specific and given for each
* RR type.
*
* \todo Find out whether NULL is appropriate value. If it is a possible
* value for some of the items, we must find some other way to deal with
* this.
* \todo Add some function for freeing particular item? Or a non-const getter?
*/
struct knot_rdata {
knot_rdata_item_t *items; /*!< RDATA items comprising this RDATA. */
unsigned int count; /*! < Count of RDATA items in this RDATA. */
struct knot_rdata *next; /*!< Next RDATA item in a linked list. */
};
typedef struct knot_rdata knot_rdata_t;
/*----------------------------------------------------------------------------*/
/*!
* \brief Creates an empty RDATA structure.
*
* \return Pointer to the new RDATA structure or NULL if an error occured.
*/
knot_rdata_t *knot_rdata_new();
/*!
* \brief Parses RDATA from the given data in wire format.
*
* \param rdata RDATA to fill.
* \param wire Wire format of the whole data in which the RDATA are present.
* \param pos Position in \a wire where to start parsing.
* \param total_size Size of the whole data.
* \param rdlength Size of the RDATA to parse in bytes.
* \param desc RR type descriptor for the RDATA type.
*
* \retval KNOT_ENOMEM
* \retval KNOT_EFEWDATA
* \retval KNOT_EMALF
* \retval KNOT_ERROR
* \retval KNOT_EOK
*/
int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
size_t *pos, size_t total_size, size_t rdlength,
const knot_rrtype_descriptor_t *desc);
/*!
* \brief Sets the RDATA item on position \a pos.
*
* \param rdata RDATA structure in which the item should be set.
* \param pos Position of the RDATA item to be set.
* \param item RDATA item value to be set.
*
* \retval KNOT_EOK if successful.
* \retval KNOT_EBADARG if \a pos is not a valid position.
*
* \todo Use the union or a pointer to it as parameter? IMHO there is always
* only one pointer that is copied, so it doesn't matter.
*/
int knot_rdata_set_item(knot_rdata_t *rdata, unsigned int pos,
knot_rdata_item_t item);
/*!
* \brief Sets all RDATA items within the given RDATA structure.
*
* \a rdata must be empty so far (\a rdata->count == 0). The necessary space
* is allocated.
*
* This function copies the array of RDATA items from \a items to \a rdata.
*
* \param rdata RDATA structure to store the items in.
* \param items An array of RDATA items to be stored in this RDATA structure.
* \param count Count of RDATA items to be stored.
*
* \retval 0 if successful.
* \retval KNOT_EBADARG
* \retval KNOT_ENOMEM
*/
int knot_rdata_set_items(knot_rdata_t *rdata,
const knot_rdata_item_t *items,
unsigned int count);
unsigned int knot_rdata_item_count(const knot_rdata_t *rdata);
/*!
* \brief Returns the RDATA item on position \a pos.
*
* \note Although returning union would be OK (no overhead), we need to be able
* to distinguish errors (in this case by returning NULL).
*
* \param rdata RDATA structure to get the item from.
* \param pos Position of the item to retrieve.
*
* \return The RDATA item on position \a pos, or NULL if such position does not
* exist within the given RDATA structure.
*/
knot_rdata_item_t *knot_rdata_get_item(const knot_rdata_t *rdata,
unsigned int pos);
/*!
* \brief Returns the RDATA item on position \a pos.
*
* \note Although returning union would be OK (no overhead), we need to be able
* to distinguish errors (in this case by returning NULL).
* \note This function is identical to knot_rdata_get_item(), only it returns
* constant data.
*
* \param rdata RDATA structure to get the item from.
* \param pos Position of the item to retrieve.
*
* \return The RDATA item on position \a pos, or NULL if such position does not
* exist within the given RDATA structure.
*/
const knot_rdata_item_t *knot_rdata_item(const knot_rdata_t *rdata,
unsigned int pos);
/*!
* \brief Sets the given domain name as a value of RDATA item on position
* \a pos.
*
* \param rdata RDATA structure to set the item in.
* \param pos Position of the RDATA item to set.
* \param dname Domain name to set to the item.
*
* \retval KNOT_EOK if successful.
* \retval KNOT_EBADARG
*/
int knot_rdata_item_set_dname(knot_rdata_t *rdata, unsigned int pos,
knot_dname_t *dname);
/*!
* \brief Sets the given raw data as a value of RDATA item on position \a pos.
*
* \param rdata RDATA structure to set the item in.
* \param pos Position of the RDATA item to set.
* \param raw_data Raw data to set to the item.
*
* \retval KNOT_EOK if successful.
* \retval KNOT_EBADARG
*/
int knot_rdata_item_set_raw_data(knot_rdata_t *rdata, unsigned int pos,
uint16_t *raw_data);
/*!
* \brief Copies the given RDATA.
*
* \param rdata RDATA to copy.
* \param type RR type of the RDATA.
*
* \return Copy of \a rdata.
*/
knot_rdata_t *knot_rdata_deep_copy(const knot_rdata_t *rdata,
uint16_t type);
/*!
* \brief Destroys the RDATA structure without deleting RDATA items.
*
* Also sets the given pointer to NULL.
*
* \param rdata RDATA structure to be destroyed.
*/
void knot_rdata_free(knot_rdata_t **rdata);
/*!
* \brief Destroys the RDATA structure and all its RDATA items.
*
* RDATA items are deleted according to the given RR Type. In case of domain
* name, it is deallocated only if either the free_all_dnames parameter is set
* to <> 0 or the name does not contain reference to a node (i.e. it is not an
* owner of some node) or if it does contain a reference to a node, but is
* not equal to its owner. (If free_all_dnames is set to <> 0, no other
* condition is evaluated.)
*
* Also sets the given pointer to NULL.
*
* \param rdata RDATA structure to be destroyed.
* \param type RR Type of the RDATA.
* \param free_all_dnames Set to <> 0 if you want to delete ALL domain names
* from the RDATA. Set to 0 otherwise.
*/
void knot_rdata_deep_free(knot_rdata_t **rdata, unsigned int type,
int free_all_dnames);
/*!
* \brief Compares two RDATAs of the same type.
*
* \note Compares domain names normally (dname_compare()), i.e.
* case-insensitive.
*
* \param r1 First RDATA.
* \param r2 Second RDATA.
* \param format Descriptor of the RDATA format.
*
* \retval 0 if RDATAs are equal.
* \retval < 0 if \a r1 goes before \a r2 in canonical order.
* \retval > 0 if \a r1 goes after \a r2 in canonical order.
*/
int knot_rdata_compare(const knot_rdata_t *r1, const knot_rdata_t *r2,
const uint8_t *format);
/*!
* \brief Retrieves the domain name from CNAME RDATA.
*
* \note This is only convenience function. It does not (and cannot) check if
* the given RDATA is of the right type, so it always returns the first
* RDATA item, even if it is not a domain name.
*
* \param rdata RDATA to get the CNAME domain name from.
*
* \return Canonical name stored in \a rdata or NULL if \a rdata has no items.
*/
const knot_dname_t *knot_rdata_cname_name(const knot_rdata_t *rdata);
/*!
* \brief Retrieves the domain name from DNAME RDATA.
*
* \note This is only convenience function. It does not (and cannot) check if
* the given RDATA is of the right type, so it always returns the first
* RDATA item, even if it is not a domain name.
*
* \param rdata RDATA to get the DNAME domain name from.
*
* \return Target domain name stored in \a rdata or NULL if \a rdata has no
* items.
*/
const knot_dname_t *knot_rdata_dname_target(const knot_rdata_t *rdata);
/*!
* \brief Retrieves the domain name from RDATA of given type.
*
* Supported types:
* - KNOT_RRTYPE_NS
* - KNOT_RRTYPE_MX
* - KNOT_RRTYPE_SRV
* - KNOT_RRTYPE_CNAME
*
* \note This is only convenience function. It does not (and cannot) check if
* the given RDATA is of the right type, so it always returns the RDATA
* item according to the given type, even if it is not a domain name.
*
* \param rdata RDATA to get the domain name from.
* \param type RR type of the RDATA.
*
* \return Domain name stored in \a rdata or NULL if \a rdata has not enough
* items.
*/
const knot_dname_t *knot_rdata_get_name(const knot_rdata_t *rdata,
uint16_t type);
int64_t knot_rdata_soa_serial(const knot_rdata_t *rdata);
uint32_t knot_rdata_soa_refresh(const knot_rdata_t *rdata);
uint32_t knot_rdata_soa_retry(const knot_rdata_t *rdata);
uint32_t knot_rdata_soa_expire(const knot_rdata_t *rdata);
uint32_t knot_rdata_soa_minimum(const knot_rdata_t *rdata);
uint16_t knot_rdata_rrsig_type_covered(const knot_rdata_t *rdata);
#endif /* _KNOT_RDATA_H */
/*! @} */
|