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