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 #include <stdio.h>
18 #include <stdlib.h>
19 #include <strings.h>
20
21 #include "libknot/attribute.h"
22 #include "libknot/descriptor.h"
23
24 /*!
25 * \brief Table with DNS classes.
26 */
27 static const char* dns_classes[] = {
28 [KNOT_CLASS_IN] = "IN",
29 [KNOT_CLASS_CH] = "CH",
30 [KNOT_CLASS_NONE] = "NONE",
31 [KNOT_CLASS_ANY] = "ANY"
32 };
33
34 /*!
35 * \brief RR type descriptors.
36 */
37 static const knot_rdata_descriptor_t rdata_descriptors[] = {
38 [0] = { { KNOT_RDATA_WF_REMAINDER,
39 KNOT_RDATA_WF_END }, NULL },
40 [KNOT_RRTYPE_A] = { { 4, KNOT_RDATA_WF_END }, "A" },
41 [KNOT_RRTYPE_NS] = { { KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
42 KNOT_RDATA_WF_END }, "NS" },
43 [KNOT_RRTYPE_CNAME] = { { KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
44 KNOT_RDATA_WF_END }, "CNAME" },
45 [KNOT_RRTYPE_SOA] = { { KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
46 KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
47 20, KNOT_RDATA_WF_END }, "SOA" },
48 [KNOT_RRTYPE_NULL] = { { KNOT_RDATA_WF_REMAINDER,
49 KNOT_RDATA_WF_END }, "NULL" },
50 [KNOT_RRTYPE_PTR] = { { KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
51 KNOT_RDATA_WF_END }, "PTR" },
52 [KNOT_RRTYPE_HINFO] = { { KNOT_RDATA_WF_REMAINDER,
53 KNOT_RDATA_WF_END }, "HINFO" },
54 [KNOT_RRTYPE_MINFO] = { { KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
55 KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
56 KNOT_RDATA_WF_END }, "MINFO" },
57 [KNOT_RRTYPE_MX] = { { 2, KNOT_RDATA_WF_COMPRESSIBLE_DNAME,
58 KNOT_RDATA_WF_END }, "MX" },
59 [KNOT_RRTYPE_TXT] = { { KNOT_RDATA_WF_REMAINDER,
60 KNOT_RDATA_WF_END }, "TXT" },
61 [KNOT_RRTYPE_RP] = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
62 KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
63 KNOT_RDATA_WF_END }, "RP" },
64 [KNOT_RRTYPE_AFSDB] = { { 2, KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
65 KNOT_RDATA_WF_END }, "AFSDB" },
66 [KNOT_RRTYPE_RT] = { { 2, KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
67 KNOT_RDATA_WF_END }, "RT" },
68 [KNOT_RRTYPE_SIG] = { { 18, KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
69 KNOT_RDATA_WF_REMAINDER,
70 KNOT_RDATA_WF_END }, "SIG" },
71 [KNOT_RRTYPE_KEY] = { { KNOT_RDATA_WF_REMAINDER,
72 KNOT_RDATA_WF_END }, "KEY" },
73 [KNOT_RRTYPE_AAAA] = { { 16, KNOT_RDATA_WF_END }, "AAAA" },
74 [KNOT_RRTYPE_LOC] = { { 16, KNOT_RDATA_WF_END }, "LOC" },
75 [KNOT_RRTYPE_SRV] = { { 6, KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
76 KNOT_RDATA_WF_END }, "SRV" },
77 [KNOT_RRTYPE_NAPTR] = { { KNOT_RDATA_WF_NAPTR_HEADER,
78 KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
79 KNOT_RDATA_WF_END }, "NAPTR" },
80 [KNOT_RRTYPE_KX] = { { 2, KNOT_RDATA_WF_FIXED_DNAME,
81 KNOT_RDATA_WF_END }, "KX" },
82 [KNOT_RRTYPE_CERT] = { { KNOT_RDATA_WF_REMAINDER,
83 KNOT_RDATA_WF_END }, "CERT" },
84 [KNOT_RRTYPE_DNAME] = { { KNOT_RDATA_WF_FIXED_DNAME,
85 KNOT_RDATA_WF_END }, "DNAME" },
86 [KNOT_RRTYPE_OPT] = { { KNOT_RDATA_WF_REMAINDER,
87 KNOT_RDATA_WF_END }, "OPT" },
88 [KNOT_RRTYPE_APL] = { { KNOT_RDATA_WF_REMAINDER,
89 KNOT_RDATA_WF_END }, "APL" },
90 [KNOT_RRTYPE_DS] = { { KNOT_RDATA_WF_REMAINDER,
91 KNOT_RDATA_WF_END }, "DS" },
92 [KNOT_RRTYPE_SSHFP] = { { KNOT_RDATA_WF_REMAINDER,
93 KNOT_RDATA_WF_END }, "SSHFP" },
94 [KNOT_RRTYPE_IPSECKEY] = { { KNOT_RDATA_WF_REMAINDER,
95 KNOT_RDATA_WF_END }, "IPSECKEY" },
96 [KNOT_RRTYPE_RRSIG] = { { 18, KNOT_RDATA_WF_FIXED_DNAME,
97 KNOT_RDATA_WF_REMAINDER,
98 KNOT_RDATA_WF_END }, "RRSIG" },
99 [KNOT_RRTYPE_NSEC] = { { KNOT_RDATA_WF_FIXED_DNAME,
100 KNOT_RDATA_WF_REMAINDER,
101 KNOT_RDATA_WF_END }, "NSEC" },
102 [KNOT_RRTYPE_DNSKEY] = { { KNOT_RDATA_WF_REMAINDER,
103 KNOT_RDATA_WF_END }, "DNSKEY" },
104 [KNOT_RRTYPE_DHCID] = { { KNOT_RDATA_WF_REMAINDER,
105 KNOT_RDATA_WF_END }, "DHCID" },
106 [KNOT_RRTYPE_NSEC3] = { { KNOT_RDATA_WF_REMAINDER,
107 KNOT_RDATA_WF_END }, "NSEC3" },
108 [KNOT_RRTYPE_NSEC3PARAM] = { { KNOT_RDATA_WF_REMAINDER,
109 KNOT_RDATA_WF_END }, "NSEC3PARAM" },
110 [KNOT_RRTYPE_TLSA] = { { KNOT_RDATA_WF_REMAINDER,
111 KNOT_RDATA_WF_END }, "TLSA" },
112 [KNOT_RRTYPE_SMIMEA] = { { KNOT_RDATA_WF_REMAINDER,
113 KNOT_RDATA_WF_END }, "SMIMEA" },
114 [KNOT_RRTYPE_CDS] = { { KNOT_RDATA_WF_REMAINDER,
115 KNOT_RDATA_WF_END }, "CDS" },
116 [KNOT_RRTYPE_CDNSKEY] = { { KNOT_RDATA_WF_REMAINDER,
117 KNOT_RDATA_WF_END }, "CDNSKEY" },
118 [KNOT_RRTYPE_OPENPGPKEY] = { { KNOT_RDATA_WF_REMAINDER,
119 KNOT_RDATA_WF_END }, "OPENPGPKEY" },
120 [KNOT_RRTYPE_CSYNC] = { { KNOT_RDATA_WF_REMAINDER,
121 KNOT_RDATA_WF_END }, "CSYNC" },
122 [KNOT_RRTYPE_ZONEMD] = { { KNOT_RDATA_WF_REMAINDER,
123 KNOT_RDATA_WF_END }, "ZONEMD" },
124 [KNOT_RRTYPE_SVCB] = { { KNOT_RDATA_WF_REMAINDER,
125 KNOT_RDATA_WF_END }, "SVCB" },
126 [KNOT_RRTYPE_HTTPS] = { { KNOT_RDATA_WF_REMAINDER,
127 KNOT_RDATA_WF_END }, "HTTPS" },
128 [KNOT_RRTYPE_SPF] = { { KNOT_RDATA_WF_REMAINDER,
129 KNOT_RDATA_WF_END }, "SPF" },
130 [KNOT_RRTYPE_NID] = { { 10, KNOT_RDATA_WF_END }, "NID" },
131 [KNOT_RRTYPE_L32] = { { 6, KNOT_RDATA_WF_END }, "L32" },
132 [KNOT_RRTYPE_L64] = { { 10, KNOT_RDATA_WF_END }, "L64" },
133 [KNOT_RRTYPE_LP] = { { 2, KNOT_RDATA_WF_FIXED_DNAME,
134 KNOT_RDATA_WF_END }, "LP" },
135 [KNOT_RRTYPE_EUI48] = { { 6, KNOT_RDATA_WF_END }, "EUI48" },
136 [KNOT_RRTYPE_EUI64] = { { 8, KNOT_RDATA_WF_END }, "EUI64" },
137 [KNOT_RRTYPE_TKEY] = { { KNOT_RDATA_WF_FIXED_DNAME,
138 KNOT_RDATA_WF_REMAINDER,
139 KNOT_RDATA_WF_END }, "TKEY" },
140 [KNOT_RRTYPE_TSIG] = { { KNOT_RDATA_WF_FIXED_DNAME,
141 KNOT_RDATA_WF_REMAINDER,
142 KNOT_RDATA_WF_END }, "TSIG" },
143 [KNOT_RRTYPE_IXFR] = { { KNOT_RDATA_WF_REMAINDER,
144 KNOT_RDATA_WF_END }, "IXFR" },
145 [KNOT_RRTYPE_AXFR] = { { KNOT_RDATA_WF_REMAINDER,
146 KNOT_RDATA_WF_END }, "AXFR" },
147 [KNOT_RRTYPE_ANY] = { { KNOT_RDATA_WF_REMAINDER,
148 KNOT_RDATA_WF_END }, "ANY" },
149 [KNOT_RRTYPE_URI] = { { KNOT_RDATA_WF_REMAINDER,
150 KNOT_RDATA_WF_END }, "URI" },
151 [KNOT_RRTYPE_CAA] = { { KNOT_RDATA_WF_REMAINDER,
152 KNOT_RDATA_WF_END }, "CAA" },
153 };
154
155 #define MAX_RRTYPE sizeof(rdata_descriptors) / sizeof(knot_rdata_descriptor_t) - 1
156
157 /*!
158 * \brief Some (OBSOLETE) RR type descriptors.
159 */
160 static const knot_rdata_descriptor_t obsolete_rdata_descriptors[] = {
161 [0] = { { KNOT_RDATA_WF_REMAINDER,
162 KNOT_RDATA_WF_END }, NULL },
163 [KNOT_RRTYPE_MD] = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
164 KNOT_RDATA_WF_END }, "MD" },
165 [KNOT_RRTYPE_MF] = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
166 KNOT_RDATA_WF_END }, "MF" },
167 [KNOT_RRTYPE_MB] = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
168 KNOT_RDATA_WF_END }, "MB" },
169 [KNOT_RRTYPE_MG] = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
170 KNOT_RDATA_WF_END }, "MG" },
171 [KNOT_RRTYPE_MR] = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
172 KNOT_RDATA_WF_END }, "MR" },
173 [KNOT_RRTYPE_PX] = { { 2, KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
174 KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
175 KNOT_RDATA_WF_END }, "PX" },
176 [KNOT_RRTYPE_NXT] = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
177 KNOT_RDATA_WF_REMAINDER,
178 KNOT_RDATA_WF_END }, "NXT" },
179 };
180
181 _public_
knot_get_rdata_descriptor(const uint16_t type)182 const knot_rdata_descriptor_t *knot_get_rdata_descriptor(const uint16_t type)
183 {
184 if (type <= MAX_RRTYPE && rdata_descriptors[type].type_name != NULL) {
185 return &rdata_descriptors[type];
186 } else {
187 return &rdata_descriptors[0];
188 }
189 }
190
191 _public_
knot_get_obsolete_rdata_descriptor(const uint16_t type)192 const knot_rdata_descriptor_t *knot_get_obsolete_rdata_descriptor(const uint16_t type)
193 {
194 if (type <= KNOT_RRTYPE_NXT &&
195 obsolete_rdata_descriptors[type].type_name != NULL) {
196 return &obsolete_rdata_descriptors[type];
197 } else {
198 return &obsolete_rdata_descriptors[0];
199 }
200 }
201
202 _public_
knot_rrtype_to_string(const uint16_t rrtype,char * out,const size_t out_len)203 int knot_rrtype_to_string(const uint16_t rrtype,
204 char *out,
205 const size_t out_len)
206 {
207 if (out == NULL) {
208 return -1;
209 }
210
211 int ret;
212
213 const knot_rdata_descriptor_t *descr = knot_get_rdata_descriptor(rrtype);
214
215 if (descr->type_name != NULL) {
216 ret = snprintf(out, out_len, "%s", descr->type_name);
217 } else {
218 ret = snprintf(out, out_len, "TYPE%u", rrtype);
219 }
220
221 if (ret <= 0 || (size_t)ret >= out_len) {
222 return -1;
223 } else {
224 return ret;
225 }
226 }
227
228 _public_
knot_rrtype_from_string(const char * name,uint16_t * num)229 int knot_rrtype_from_string(const char *name, uint16_t *num)
230 {
231 if (name == NULL || num == NULL) {
232 return -1;
233 }
234
235 int i;
236 char *end;
237 unsigned long n;
238
239 // Try to find name in descriptors table.
240 for (i = 0; i <= MAX_RRTYPE; i++) {
241 if (rdata_descriptors[i].type_name != NULL &&
242 strcasecmp(rdata_descriptors[i].type_name, name) == 0) {
243 *num = i;
244 return 0;
245 }
246 }
247
248 // Type name must begin with TYPE.
249 if (strncasecmp(name, "TYPE", 4) != 0) {
250 return -1;
251 } else {
252 name += 4;
253 }
254
255 // The rest must be a number.
256 n = strtoul(name, &end, 10);
257 if (end == name || *end != '\0' || n > UINT16_MAX) {
258 return -1;
259 }
260
261 *num = n;
262 return 0;
263 }
264
265 _public_
knot_rrclass_to_string(const uint16_t rrclass,char * out,const size_t out_len)266 int knot_rrclass_to_string(const uint16_t rrclass,
267 char *out,
268 const size_t out_len)
269 {
270 if (out == NULL) {
271 return -1;
272 }
273
274 int ret;
275
276 if (rrclass <= KNOT_CLASS_ANY && dns_classes[rrclass] != NULL) {
277 ret = snprintf(out, out_len, "%s", dns_classes[rrclass]);
278 } else {
279 ret = snprintf(out, out_len, "CLASS%u", rrclass);
280 }
281
282 if (ret <= 0 || (size_t)ret >= out_len) {
283 return -1;
284 } else {
285 return ret;
286 }
287 }
288
289 _public_
knot_rrclass_from_string(const char * name,uint16_t * num)290 int knot_rrclass_from_string(const char *name, uint16_t *num)
291 {
292 if (name == NULL || num == NULL) {
293 return -1;
294 }
295
296 int i;
297 char *end;
298 unsigned long n;
299
300 // Try to find the name in classes table.
301 for (i = 0; i <= KNOT_CLASS_ANY; i++) {
302 if (dns_classes[i] != NULL &&
303 strcasecmp(dns_classes[i], name) == 0) {
304 *num = i;
305 return 0;
306 }
307 }
308
309 // Class name must begin with CLASS.
310 if (strncasecmp(name, "CLASS", 5) != 0) {
311 return -1;
312 } else {
313 name += 5;
314 }
315
316 // The rest must be a number.
317 n = strtoul(name, &end, 10);
318 if (end == name || *end != '\0' || n > UINT16_MAX) {
319 return -1;
320 }
321
322 *num = n;
323 return 0;
324 }
325
326 _public_
knot_rrtype_is_metatype(const uint16_t type)327 int knot_rrtype_is_metatype(const uint16_t type)
328 {
329 return type == KNOT_RRTYPE_SIG ||
330 type == KNOT_RRTYPE_OPT ||
331 type == KNOT_RRTYPE_TKEY ||
332 type == KNOT_RRTYPE_TSIG ||
333 type == KNOT_RRTYPE_IXFR ||
334 type == KNOT_RRTYPE_AXFR ||
335 type == KNOT_RRTYPE_ANY;
336 }
337
338 _public_
knot_rrtype_is_dnssec(const uint16_t type)339 int knot_rrtype_is_dnssec(const uint16_t type)
340 {
341 return type == KNOT_RRTYPE_DNSKEY ||
342 type == KNOT_RRTYPE_RRSIG ||
343 type == KNOT_RRTYPE_NSEC ||
344 type == KNOT_RRTYPE_NSEC3 ||
345 type == KNOT_RRTYPE_NSEC3PARAM ||
346 type == KNOT_RRTYPE_CDNSKEY ||
347 type == KNOT_RRTYPE_CDS;
348 }
349
350 _public_
knot_rrtype_additional_needed(const uint16_t type)351 int knot_rrtype_additional_needed(const uint16_t type)
352 {
353 return type == KNOT_RRTYPE_NS ||
354 type == KNOT_RRTYPE_MX ||
355 type == KNOT_RRTYPE_SRV;
356 }
357
358 _public_
knot_rrtype_should_be_lowercased(const uint16_t type)359 bool knot_rrtype_should_be_lowercased(const uint16_t type)
360 {
361 return type == KNOT_RRTYPE_NS ||
362 type == KNOT_RRTYPE_MD ||
363 type == KNOT_RRTYPE_MF ||
364 type == KNOT_RRTYPE_CNAME ||
365 type == KNOT_RRTYPE_SOA ||
366 type == KNOT_RRTYPE_MB ||
367 type == KNOT_RRTYPE_MG ||
368 type == KNOT_RRTYPE_MR ||
369 type == KNOT_RRTYPE_PTR ||
370 type == KNOT_RRTYPE_MINFO ||
371 type == KNOT_RRTYPE_MX ||
372 type == KNOT_RRTYPE_RP ||
373 type == KNOT_RRTYPE_AFSDB ||
374 type == KNOT_RRTYPE_RT ||
375 type == KNOT_RRTYPE_SIG ||
376 type == KNOT_RRTYPE_PX ||
377 type == KNOT_RRTYPE_NXT ||
378 type == KNOT_RRTYPE_NAPTR ||
379 type == KNOT_RRTYPE_KX ||
380 type == KNOT_RRTYPE_SRV ||
381 type == KNOT_RRTYPE_DNAME ||
382 type == KNOT_RRTYPE_RRSIG;
383 }
384
385 _public_
knot_opt_code_to_string(const uint16_t code,char * out,const size_t out_len)386 int knot_opt_code_to_string(const uint16_t code, char *out, const size_t out_len)
387 {
388 if (out == NULL) {
389 return -1;
390 }
391
392 const char *name = NULL;
393
394 switch (code) {
395 case 1: name = "LLQ"; break;
396 case 2: name = "UL"; break;
397 case 3: name = "NSID"; break;
398 case 5: name = "DAU"; break;
399 case 6: name = "DHU"; break;
400 case 7: name = "N3U"; break;
401 case 8: name = "EDNS-CLIENT-SUBNET"; break;
402 case 9: name = "EDNS-EXPIRE"; break;
403 case 10: name = "COOKIE"; break;
404 case 11: name = "EDNS-TCP-KEEPALIVE"; break;
405 case 12: name = "PADDING"; break;
406 case 13: name = "CHAIN"; break;
407 case 14: name = "EDNS-KEY-TAG"; break;
408 }
409
410 int ret;
411
412 if (name != NULL) {
413 ret = snprintf(out, out_len, "%s", name);
414 } else {
415 ret = snprintf(out, out_len, "CODE%u", code);
416 }
417
418 if (ret <= 0 || (size_t)ret >= out_len) {
419 return -1;
420 } else {
421 return ret;
422 }
423 }
424