xref: /openbsd/usr.sbin/nsd/rdata.c (revision de04d855)
1 /*
2  * rdata.c -- RDATA conversion functions.
3  *
4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #include "config.h"
11 
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include <ctype.h>
17 #include <netdb.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #ifdef HAVE_STRINGS_H
21 #include <strings.h>
22 #endif
23 
24 #include "rdata.h"
25 #include "zonec.h"
26 
27 /* Taken from RFC 4398, section 2.1.  */
28 lookup_table_type dns_certificate_types[] = {
29 /*	0		Reserved */
30 	{ 1, "PKIX" },	/* X.509 as per PKIX */
31 	{ 2, "SPKI" },	/* SPKI cert */
32 	{ 3, "PGP" },	/* OpenPGP packet */
33 	{ 4, "IPKIX" },	/* The URL of an X.509 data object */
34 	{ 5, "ISPKI" },	/* The URL of an SPKI certificate */
35 	{ 6, "IPGP" },	/* The fingerprint and URL of an OpenPGP packet */
36 	{ 7, "ACPKIX" },	/* Attribute Certificate */
37 	{ 8, "IACPKIX" },	/* The URL of an Attribute Certificate */
38 	{ 253, "URI" },	/* URI private */
39 	{ 254, "OID" },	/* OID private */
40 /*	255 		Reserved */
41 /* 	256-65279	Available for IANA assignment */
42 /*	65280-65534	Experimental */
43 /*	65535		Reserved */
44 	{ 0, NULL }
45 };
46 
47 /* Taken from RFC 2535, section 7.  */
48 lookup_table_type dns_algorithms[] = {
49 	{ 1, "RSAMD5" },	/* RFC 2537 */
50 	{ 2, "DH" },		/* RFC 2539 */
51 	{ 3, "DSA" },		/* RFC 2536 */
52 	{ 4, "ECC" },
53 	{ 5, "RSASHA1" },	/* RFC 3110 */
54 	{ 6, "DSA-NSEC3-SHA1" },	/* RFC 5155 */
55 	{ 7, "RSASHA1-NSEC3-SHA1" },	/* RFC 5155 */
56 	{ 8, "RSASHA256" },		/* RFC 5702 */
57 	{ 10, "RSASHA512" },		/* RFC 5702 */
58 	{ 12, "ECC-GOST" },		/* RFC 5933 */
59 	{ 13, "ECDSAP256SHA256" },	/* RFC 6605 */
60 	{ 14, "ECDSAP384SHA384" },	/* RFC 6605 */
61 	{ 15, "ED25519" },		/* RFC 8080 */
62 	{ 16, "ED448" },		/* RFC 8080 */
63 	{ 252, "INDIRECT" },
64 	{ 253, "PRIVATEDNS" },
65 	{ 254, "PRIVATEOID" },
66 	{ 0, NULL }
67 };
68 
69 const char *svcparamkey_strs[] = {
70 		"mandatory", "alpn", "no-default-alpn", "port",
71 		"ipv4hint", "ech", "ipv6hint", "dohpath"
72 	};
73 
74 typedef int (*rdata_to_string_type)(buffer_type *output,
75 				    rdata_atom_type rdata,
76 				    rr_type *rr);
77 
78 static int
rdata_dname_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))79 rdata_dname_to_string(buffer_type *output, rdata_atom_type rdata,
80 	rr_type* ATTR_UNUSED(rr))
81 {
82 	buffer_printf(output,
83 		      "%s",
84 		      dname_to_string(domain_dname(rdata_atom_domain(rdata)),
85 				      NULL));
86 	return 1;
87 }
88 
89 static int
rdata_dns_name_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))90 rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata,
91 	rr_type* ATTR_UNUSED(rr))
92 {
93 	const uint8_t *data = rdata_atom_data(rdata);
94 	size_t offset = 0;
95 	uint8_t length = data[offset];
96 	size_t i;
97 
98 	while (length > 0)
99 	{
100 		if (offset) /* concat label */
101 			buffer_printf(output, ".");
102 
103 		for (i = 1; i <= length; ++i) {
104 			uint8_t ch = data[i+offset];
105 
106 			if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') {
107 				buffer_printf(output, "\\%c", (char) ch);
108 			} else if (!isgraph((unsigned char) ch)) {
109 				buffer_printf(output, "\\%03u", (unsigned int) ch);
110 			} else if (isprint((unsigned char) ch)) {
111 				buffer_printf(output, "%c", (char) ch);
112 			} else {
113 				buffer_printf(output, "\\%03u", (unsigned int) ch);
114 			}
115 		}
116 		/* next label */
117 		offset = offset+length+1;
118 		length = data[offset];
119 	}
120 
121 	/* root label */
122 	buffer_printf(output, ".");
123 	return 1;
124 }
125 
126 static int
rdata_text_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))127 rdata_text_to_string(buffer_type *output, rdata_atom_type rdata,
128 	rr_type* ATTR_UNUSED(rr))
129 {
130 	const uint8_t *data = rdata_atom_data(rdata);
131 	uint8_t length = data[0];
132 	size_t i;
133 
134 	buffer_printf(output, "\"");
135 	for (i = 1; i <= length; ++i) {
136 		char ch = (char) data[i];
137 		if (isprint((unsigned char)ch)) {
138 			if (ch == '"' || ch == '\\') {
139 				buffer_printf(output, "\\");
140 			}
141 			buffer_printf(output, "%c", ch);
142 		} else {
143 			buffer_printf(output, "\\%03u", (unsigned) data[i]);
144 		}
145 	}
146 	buffer_printf(output, "\"");
147 	return 1;
148 }
149 
150 static int
rdata_texts_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))151 rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata,
152 	rr_type* ATTR_UNUSED(rr))
153 {
154 	uint16_t pos = 0;
155 	const uint8_t *data = rdata_atom_data(rdata);
156 	uint16_t length = rdata_atom_size(rdata);
157 	size_t i;
158 
159 	while (pos < length && pos + data[pos] < length) {
160 		buffer_printf(output, "\"");
161 		for (i = 1; i <= data[pos]; ++i) {
162 			char ch = (char) data[pos + i];
163 			if (isprint((unsigned char)ch)) {
164 				if (ch == '"' || ch == '\\') {
165 					buffer_printf(output, "\\");
166 				}
167 				buffer_printf(output, "%c", ch);
168 			} else {
169 				buffer_printf(output, "\\%03u", (unsigned) data[pos+i]);
170 			}
171 		}
172 		pos += data[pos]+1;
173 		buffer_printf(output, pos < length?"\" ":"\"");
174 	}
175 	return 1;
176 }
177 
178 static int
rdata_long_text_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))179 rdata_long_text_to_string(buffer_type *output, rdata_atom_type rdata,
180 	rr_type* ATTR_UNUSED(rr))
181 {
182 	const uint8_t *data = rdata_atom_data(rdata);
183 	uint16_t length = rdata_atom_size(rdata);
184 	size_t i;
185 
186 	buffer_printf(output, "\"");
187 	for (i = 0; i < length; ++i) {
188 		char ch = (char) data[i];
189 		if (isprint((unsigned char)ch)) {
190 			if (ch == '"' || ch == '\\') {
191 				buffer_printf(output, "\\");
192 			}
193 			buffer_printf(output, "%c", ch);
194 		} else {
195 			buffer_printf(output, "\\%03u", (unsigned) data[i]);
196 		}
197 	}
198 	buffer_printf(output, "\"");
199 	return 1;
200 }
201 
202 static int
rdata_tag_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))203 rdata_tag_to_string(buffer_type *output, rdata_atom_type rdata,
204 	rr_type* ATTR_UNUSED(rr))
205 {
206 	const uint8_t *data = rdata_atom_data(rdata);
207 	uint8_t length = data[0];
208 	size_t i;
209 	for (i = 1; i <= length; ++i) {
210 		char ch = (char) data[i];
211 		if (isdigit((unsigned char)ch) || islower((unsigned char)ch))
212 			buffer_printf(output, "%c", ch);
213 		else	return 0;
214 	}
215 	return 1;
216 }
217 
218 static int
rdata_byte_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))219 rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata,
220 	rr_type* ATTR_UNUSED(rr))
221 {
222 	uint8_t data = *rdata_atom_data(rdata);
223 	buffer_printf(output, "%lu", (unsigned long) data);
224 	return 1;
225 }
226 
227 static int
rdata_short_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))228 rdata_short_to_string(buffer_type *output, rdata_atom_type rdata,
229 	rr_type* ATTR_UNUSED(rr))
230 {
231 	uint16_t data = read_uint16(rdata_atom_data(rdata));
232 	buffer_printf(output, "%lu", (unsigned long) data);
233 	return 1;
234 }
235 
236 static int
rdata_long_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))237 rdata_long_to_string(buffer_type *output, rdata_atom_type rdata,
238 	rr_type* ATTR_UNUSED(rr))
239 {
240 	uint32_t data = read_uint32(rdata_atom_data(rdata));
241 	buffer_printf(output, "%lu", (unsigned long) data);
242 	return 1;
243 }
244 
245 static int
rdata_a_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))246 rdata_a_to_string(buffer_type *output, rdata_atom_type rdata,
247 	rr_type* ATTR_UNUSED(rr))
248 {
249 	int result = 0;
250 	char str[200];
251 	if (inet_ntop(AF_INET, rdata_atom_data(rdata), str, sizeof(str))) {
252 		buffer_printf(output, "%s", str);
253 		result = 1;
254 	}
255 	return result;
256 }
257 
258 static int
rdata_aaaa_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))259 rdata_aaaa_to_string(buffer_type *output, rdata_atom_type rdata,
260 	rr_type* ATTR_UNUSED(rr))
261 {
262 	int result = 0;
263 	char str[200];
264 	if (inet_ntop(AF_INET6, rdata_atom_data(rdata), str, sizeof(str))) {
265 		buffer_printf(output, "%s", str);
266 		result = 1;
267 	}
268 	return result;
269 }
270 
271 static int
rdata_ilnp64_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))272 rdata_ilnp64_to_string(buffer_type *output, rdata_atom_type rdata,
273 	rr_type* ATTR_UNUSED(rr))
274 {
275 	uint8_t* data = rdata_atom_data(rdata);
276 	uint16_t a1 = read_uint16(data);
277 	uint16_t a2 = read_uint16(data+2);
278 	uint16_t a3 = read_uint16(data+4);
279 	uint16_t a4 = read_uint16(data+6);
280 
281 	buffer_printf(output, "%.4x:%.4x:%.4x:%.4x", a1, a2, a3, a4);
282 	return 1;
283 }
284 
285 static int
rdata_eui48_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))286 rdata_eui48_to_string(buffer_type *output, rdata_atom_type rdata,
287 	rr_type* ATTR_UNUSED(rr))
288 {
289 	uint8_t* data = rdata_atom_data(rdata);
290 	uint8_t a1 = data[0];
291 	uint8_t a2 = data[1];
292 	uint8_t a3 = data[2];
293 	uint8_t a4 = data[3];
294 	uint8_t a5 = data[4];
295 	uint8_t a6 = data[5];
296 
297 	buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
298 		a1, a2, a3, a4, a5, a6);
299 	return 1;
300 }
301 
302 static int
rdata_eui64_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))303 rdata_eui64_to_string(buffer_type *output, rdata_atom_type rdata,
304 	rr_type* ATTR_UNUSED(rr))
305 {
306 	uint8_t* data = rdata_atom_data(rdata);
307 	uint8_t a1 = data[0];
308 	uint8_t a2 = data[1];
309 	uint8_t a3 = data[2];
310 	uint8_t a4 = data[3];
311 	uint8_t a5 = data[4];
312 	uint8_t a6 = data[5];
313 	uint8_t a7 = data[6];
314 	uint8_t a8 = data[7];
315 
316 	buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
317 		a1, a2, a3, a4, a5, a6, a7, a8);
318 	return 1;
319 }
320 
321 static int
rdata_rrtype_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))322 rdata_rrtype_to_string(buffer_type *output, rdata_atom_type rdata,
323 	rr_type* ATTR_UNUSED(rr))
324 {
325 	uint16_t type = read_uint16(rdata_atom_data(rdata));
326 	buffer_printf(output, "%s", rrtype_to_string(type));
327 	return 1;
328 }
329 
330 static int
rdata_algorithm_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))331 rdata_algorithm_to_string(buffer_type *output, rdata_atom_type rdata,
332 	rr_type* ATTR_UNUSED(rr))
333 {
334 	uint8_t id = *rdata_atom_data(rdata);
335 	buffer_printf(output, "%u", (unsigned) id);
336 	return 1;
337 }
338 
339 static int
rdata_certificate_type_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))340 rdata_certificate_type_to_string(buffer_type *output, rdata_atom_type rdata,
341 	rr_type* ATTR_UNUSED(rr))
342 {
343 	uint16_t id = read_uint16(rdata_atom_data(rdata));
344 	lookup_table_type *type
345 		= lookup_by_id(dns_certificate_types, id);
346 	if (type) {
347 		buffer_printf(output, "%s", type->name);
348 	} else {
349 		buffer_printf(output, "%u", (unsigned) id);
350 	}
351 	return 1;
352 }
353 
354 static int
rdata_period_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))355 rdata_period_to_string(buffer_type *output, rdata_atom_type rdata,
356 	rr_type* ATTR_UNUSED(rr))
357 {
358 	uint32_t period = read_uint32(rdata_atom_data(rdata));
359 	buffer_printf(output, "%lu", (unsigned long) period);
360 	return 1;
361 }
362 
363 static int
rdata_time_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))364 rdata_time_to_string(buffer_type *output, rdata_atom_type rdata,
365 	rr_type* ATTR_UNUSED(rr))
366 {
367 	int result = 0;
368 	time_t time = (time_t) read_uint32(rdata_atom_data(rdata));
369 	struct tm *tm = gmtime(&time);
370 	char buf[15];
371 	if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tm)) {
372 		buffer_printf(output, "%s", buf);
373 		result = 1;
374 	}
375 	return result;
376 }
377 
378 static int
rdata_base32_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))379 rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata,
380 	rr_type* ATTR_UNUSED(rr))
381 {
382 	int length;
383 	size_t size = rdata_atom_size(rdata);
384 	if(size == 0) {
385 		buffer_write(output, "-", 1);
386 		return 1;
387 	}
388 	size -= 1; /* remove length byte from count */
389 	buffer_reserve(output, size * 2 + 1);
390 	length = b32_ntop(rdata_atom_data(rdata)+1, size,
391 			  (char *) buffer_current(output), size * 2);
392 	if (length > 0) {
393 		buffer_skip(output, length);
394 	}
395 	return length != -1;
396 }
397 
398 static int
rdata_base64_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))399 rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata,
400 	rr_type* ATTR_UNUSED(rr))
401 {
402 	int length;
403 	size_t size = rdata_atom_size(rdata);
404 	if(size == 0) {
405 		/* single zero represents empty buffer */
406 		buffer_write(output, "0", 1);
407 		return 1;
408 	}
409 	buffer_reserve(output, size * 2 + 1);
410 	length = __b64_ntop(rdata_atom_data(rdata), size,
411 			  (char *) buffer_current(output), size * 2);
412 	if (length > 0) {
413 		buffer_skip(output, length);
414 	}
415 	return length != -1;
416 }
417 
418 static void
hex_to_string(buffer_type * output,const uint8_t * data,size_t size)419 hex_to_string(buffer_type *output, const uint8_t *data, size_t size)
420 {
421 	static const char hexdigits[] = {
422 		'0', '1', '2', '3', '4', '5', '6', '7',
423 		'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
424 	};
425 	size_t i;
426 
427 	buffer_reserve(output, size * 2);
428 	for (i = 0; i < size; ++i) {
429 		uint8_t octet = *data++;
430 		buffer_write_u8(output, hexdigits[octet >> 4]);
431 		buffer_write_u8(output, hexdigits[octet & 0x0f]);
432 	}
433 }
434 
435 static int
rdata_hex_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))436 rdata_hex_to_string(buffer_type *output, rdata_atom_type rdata,
437 	rr_type* ATTR_UNUSED(rr))
438 {
439 	if(rdata_atom_size(rdata) == 0) {
440 		/* single zero represents empty buffer, such as CDS deletes */
441 		buffer_printf(output, "0");
442 	} else {
443 		hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
444 	}
445 	return 1;
446 }
447 
448 static int
rdata_hexlen_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))449 rdata_hexlen_to_string(buffer_type *output, rdata_atom_type rdata,
450 	rr_type* ATTR_UNUSED(rr))
451 {
452 	if(rdata_atom_size(rdata) <= 1) {
453 		/* NSEC3 salt hex can be empty */
454 		buffer_printf(output, "-");
455 		return 1;
456 	}
457 	hex_to_string(output, rdata_atom_data(rdata)+1, rdata_atom_size(rdata)-1);
458 	return 1;
459 }
460 
461 static int
rdata_nsap_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))462 rdata_nsap_to_string(buffer_type *output, rdata_atom_type rdata,
463 	rr_type* ATTR_UNUSED(rr))
464 {
465 	buffer_printf(output, "0x");
466 	hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
467 	return 1;
468 }
469 
470 static int
rdata_apl_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))471 rdata_apl_to_string(buffer_type *output, rdata_atom_type rdata,
472 	rr_type* ATTR_UNUSED(rr))
473 {
474 	int result = 0;
475 	buffer_type packet;
476 
477 	buffer_create_from(
478 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
479 
480 	if (buffer_available(&packet, 4)) {
481 		uint16_t address_family = buffer_read_u16(&packet);
482 		uint8_t prefix = buffer_read_u8(&packet);
483 		uint8_t length = buffer_read_u8(&packet);
484 		int negated = length & APL_NEGATION_MASK;
485 		int af = -1;
486 
487 		length &= APL_LENGTH_MASK;
488 		switch (address_family) {
489 		case 1: af = AF_INET; break;
490 		case 2: af = AF_INET6; break;
491 		}
492 		if (af != -1 && buffer_available(&packet, length)) {
493 			char text_address[1000];
494 			uint8_t address[128];
495 			memset(address, 0, sizeof(address));
496 			buffer_read(&packet, address, length);
497 			if (inet_ntop(af, address, text_address, sizeof(text_address))) {
498 				buffer_printf(output, "%s%d:%s/%d",
499 					      negated ? "!" : "",
500 					      (int) address_family,
501 					      text_address,
502 					      (int) prefix);
503 				result = 1;
504 			}
505 		}
506 	}
507 	return result;
508 }
509 
510 static int
rdata_services_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))511 rdata_services_to_string(buffer_type *output, rdata_atom_type rdata,
512 	rr_type* ATTR_UNUSED(rr))
513 {
514 	int result = 0;
515 	buffer_type packet;
516 
517 	buffer_create_from(
518 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
519 
520 	if (buffer_available(&packet, 1)) {
521 		uint8_t protocol_number = buffer_read_u8(&packet);
522 		ssize_t bitmap_size = buffer_remaining(&packet);
523 		uint8_t *bitmap = buffer_current(&packet);
524 		struct protoent *proto = getprotobynumber(protocol_number);
525 
526 		if (proto) {
527 			int i;
528 
529 			buffer_printf(output, "%s", proto->p_name);
530 
531 			for (i = 0; i < bitmap_size * 8; ++i) {
532 				if (get_bit(bitmap, i)) {
533 					struct servent *service = getservbyport((int)htons(i), proto->p_name);
534 					if (service) {
535 						buffer_printf(output, " %s", service->s_name);
536 					} else {
537 						buffer_printf(output, " %d", i);
538 					}
539 				}
540 			}
541 			buffer_skip(&packet, bitmap_size);
542 			result = 1;
543 		}
544 	}
545 	return result;
546 }
547 
548 static int
rdata_ipsecgateway_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * rr)549 rdata_ipsecgateway_to_string(buffer_type *output, rdata_atom_type rdata, rr_type* rr)
550 {
551 	int gateway_type = rdata_atom_data(rr->rdatas[1])[0];
552 	switch(gateway_type) {
553 	case IPSECKEY_NOGATEWAY:
554 		buffer_printf(output, ".");
555 		break;
556 	case IPSECKEY_IP4:
557 		rdata_a_to_string(output, rdata, rr);
558 		break;
559 	case IPSECKEY_IP6:
560 		rdata_aaaa_to_string(output, rdata, rr);
561 		break;
562 	case IPSECKEY_DNAME:
563 		{
564 			region_type* temp = region_create(xalloc, free);
565 			const dname_type* d = dname_make(temp,
566 				rdata_atom_data(rdata), 0);
567 			if(!d) {
568 				region_destroy(temp);
569 				return 0;
570 			}
571 			buffer_printf(output, "%s", dname_to_string(d, NULL));
572 			region_destroy(temp);
573 		}
574 		break;
575 	default:
576 		return 0;
577 	}
578 	return 1;
579 }
580 
581 static int
rdata_nxt_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))582 rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata,
583 	rr_type* ATTR_UNUSED(rr))
584 {
585 	size_t i;
586 	uint8_t *bitmap = rdata_atom_data(rdata);
587 	size_t bitmap_size = rdata_atom_size(rdata);
588 
589 	for (i = 0; i < bitmap_size * 8; ++i) {
590 		if (get_bit(bitmap, i)) {
591 			buffer_printf(output, "%s ", rrtype_to_string(i));
592 		}
593 	}
594 
595 	buffer_skip(output, -1);
596 
597 	return 1;
598 }
599 
600 static int
rdata_nsec_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))601 rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata,
602 	rr_type* ATTR_UNUSED(rr))
603 {
604 	size_t saved_position = buffer_position(output);
605 	buffer_type packet;
606 	int insert_space = 0;
607 
608 	buffer_create_from(
609 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
610 
611 	while (buffer_available(&packet, 2)) {
612 		uint8_t window = buffer_read_u8(&packet);
613 		uint8_t bitmap_size = buffer_read_u8(&packet);
614 		uint8_t *bitmap = buffer_current(&packet);
615 		int i;
616 
617 		if (!buffer_available(&packet, bitmap_size)) {
618 			buffer_set_position(output, saved_position);
619 			return 0;
620 		}
621 
622 		for (i = 0; i < bitmap_size * 8; ++i) {
623 			if (get_bit(bitmap, i)) {
624 				buffer_printf(output,
625 					      "%s%s",
626 					      insert_space ? " " : "",
627 					      rrtype_to_string(
628 						      window * 256 + i));
629 				insert_space = 1;
630 			}
631 		}
632 		buffer_skip(&packet, bitmap_size);
633 	}
634 
635 	return 1;
636 }
637 
638 static int
rdata_loc_to_string(buffer_type * ATTR_UNUSED (output),rdata_atom_type ATTR_UNUSED (rdata),rr_type * ATTR_UNUSED (rr))639 rdata_loc_to_string(buffer_type *ATTR_UNUSED(output),
640 		    rdata_atom_type ATTR_UNUSED(rdata),
641 		    rr_type* ATTR_UNUSED(rr))
642 {
643 	/*
644 	 * Returning 0 forces the record to be printed in unknown
645 	 * format.
646 	 */
647 	return 0;
648 }
649 
650 static void
buffer_print_svcparamkey(buffer_type * output,uint16_t svcparamkey)651 buffer_print_svcparamkey(buffer_type *output, uint16_t svcparamkey)
652 {
653 	if (svcparamkey < SVCPARAMKEY_COUNT)
654 		buffer_printf(output, "%s", svcparamkey_strs[svcparamkey]);
655 	else
656 		buffer_printf(output, "key%d", (int)svcparamkey);
657 }
658 
659 static int
rdata_svcparam_port_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)660 rdata_svcparam_port_to_string(buffer_type *output, uint16_t val_len,
661 	uint16_t *data)
662 {
663 	if (val_len != 2)
664 		return 0; /* wireformat error, a short is 2 bytes */
665 	buffer_printf(output, "=%d", (int)ntohs(data[0]));
666 	return 1;
667 }
668 
669 static int
rdata_svcparam_ipv4hint_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)670 rdata_svcparam_ipv4hint_to_string(buffer_type *output, uint16_t val_len,
671 	uint16_t *data)
672 {
673 	char ip_str[INET_ADDRSTRLEN + 1];
674 
675 	assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
676 
677 	if ((val_len % IP4ADDRLEN) == 0) {
678 		if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
679 			return 0; /* wireformat error, incorrect size or inet family */
680 
681 		buffer_printf(output, "=%s", ip_str);
682 		data += IP4ADDRLEN / sizeof(uint16_t);
683 
684 		while ((val_len -= IP4ADDRLEN) > 0) {
685 			if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
686 				return 0; /* wireformat error, incorrect size or inet family */
687 
688 			buffer_printf(output, ",%s", ip_str);
689 			data += IP4ADDRLEN / sizeof(uint16_t);
690 		}
691 		return 1;
692 	} else
693 		return 0;
694 }
695 
696 static int
rdata_svcparam_ipv6hint_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)697 rdata_svcparam_ipv6hint_to_string(buffer_type *output, uint16_t val_len,
698 	uint16_t *data)
699 {
700 	char ip_str[INET6_ADDRSTRLEN + 1];
701 
702 	assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
703 
704 	if ((val_len % IP6ADDRLEN) == 0) {
705 		if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
706 			return 0; /* wireformat error, incorrect size or inet family */
707 
708 		buffer_printf(output, "=%s", ip_str);
709 		data += IP6ADDRLEN / sizeof(uint16_t);
710 
711 		while ((val_len -= IP6ADDRLEN) > 0) {
712 			if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
713 				return 0; /* wireformat error, incorrect size or inet family */
714 
715 			buffer_printf(output, ",%s", ip_str);
716 			data += IP6ADDRLEN / sizeof(uint16_t);
717 		}
718 		return 1;
719 	} else
720 		return 0;
721 }
722 
723 static int
rdata_svcparam_mandatory_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)724 rdata_svcparam_mandatory_to_string(buffer_type *output, uint16_t val_len,
725 	uint16_t *data)
726 {
727 	assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
728 
729 	if (val_len % sizeof(uint16_t))
730 		return 0; /* wireformat error, val_len must be multiple of shorts */
731 	buffer_write_u8(output, '=');
732 	buffer_print_svcparamkey(output, ntohs(*data));
733 	data += 1;
734 
735 	while ((val_len -= sizeof(uint16_t))) {
736 		buffer_write_u8(output, ',');
737 		buffer_print_svcparamkey(output, ntohs(*data));
738 		data += 1;
739 	}
740 
741 	return 1;
742 }
743 
744 static int
rdata_svcparam_ech_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)745 rdata_svcparam_ech_to_string(buffer_type *output, uint16_t val_len,
746 	uint16_t *data)
747 {
748 	int length;
749 
750 	assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
751 
752 	buffer_write_u8(output, '=');
753 
754 	buffer_reserve(output, val_len * 2 + 1);
755 	length = __b64_ntop((uint8_t*) data, val_len,
756 			  (char *) buffer_current(output), val_len * 2);
757 	if (length > 0) {
758 		buffer_skip(output, length);
759 	}
760 
761 	return length != -1;
762 }
763 
764 static int
rdata_svcparam_alpn_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)765 rdata_svcparam_alpn_to_string(buffer_type *output, uint16_t val_len,
766 	uint16_t *data)
767 {
768 	uint8_t *dp = (void *)data;
769 
770 	assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
771 
772 	buffer_write_u8(output, '=');
773 	buffer_write_u8(output, '"');
774 	while (val_len) {
775 		uint8_t i, str_len = *dp++;
776 
777 		if (str_len > --val_len)
778 			return 0;
779 
780 		for (i = 0; i < str_len; i++) {
781 			if (dp[i] == '"' || dp[i] == '\\')
782 				buffer_printf(output, "\\\\\\%c", dp[i]);
783 
784 			else if (dp[i] == ',')
785 				buffer_printf(output, "\\\\%c", dp[i]);
786 
787 			else if (!isprint(dp[i]))
788 				buffer_printf(output, "\\%03u", (unsigned) dp[i]);
789 
790 			else
791 				buffer_write_u8(output, dp[i]);
792 		}
793 		dp += str_len;
794 		if ((val_len -= str_len))
795 			buffer_write_u8(output, ',');
796 	}
797 	buffer_write_u8(output, '"');
798 	return 1;
799 }
800 
801 static int
rdata_svcparam_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))802 rdata_svcparam_to_string(buffer_type *output, rdata_atom_type rdata,
803 	rr_type* ATTR_UNUSED(rr))
804 {
805 	uint16_t  size = rdata_atom_size(rdata);
806 	uint16_t* data = (uint16_t *)rdata_atom_data(rdata);
807 	uint16_t  svcparamkey, val_len;
808 	uint8_t*  dp;
809 	size_t i;
810 
811 	if (size < 4)
812 		return 0;
813 	svcparamkey = ntohs(data[0]);
814 
815 	buffer_print_svcparamkey(output, svcparamkey);
816 	val_len = ntohs(data[1]);
817 	if (size != val_len + 4)
818 		return 0; /* wireformat error */
819 	if (!val_len) {
820 		/* Some SvcParams MUST have values */
821 		switch (svcparamkey) {
822 		case SVCB_KEY_ALPN:
823 		case SVCB_KEY_PORT:
824 		case SVCB_KEY_IPV4HINT:
825 		case SVCB_KEY_IPV6HINT:
826 		case SVCB_KEY_MANDATORY:
827 		case SVCB_KEY_DOHPATH:
828 			return 0;
829 		default:
830 			return 1;
831 		}
832 	}
833 	switch (svcparamkey) {
834 	case SVCB_KEY_PORT:
835 		return rdata_svcparam_port_to_string(output, val_len, data+2);
836 	case SVCB_KEY_IPV4HINT:
837 		return rdata_svcparam_ipv4hint_to_string(output, val_len, data+2);
838 	case SVCB_KEY_IPV6HINT:
839 		return rdata_svcparam_ipv6hint_to_string(output, val_len, data+2);
840 	case SVCB_KEY_MANDATORY:
841 		return rdata_svcparam_mandatory_to_string(output, val_len, data+2);
842 	case SVCB_KEY_NO_DEFAULT_ALPN:
843 		return 0; /* wireformat error, should not have a value */
844 	case SVCB_KEY_ALPN:
845 		return rdata_svcparam_alpn_to_string(output, val_len, data+2);
846 	case SVCB_KEY_ECH:
847 		return rdata_svcparam_ech_to_string(output, val_len, data+2);
848 	case SVCB_KEY_DOHPATH:
849 		/* fallthrough */
850 	default:
851 		buffer_write(output, "=\"", 2);
852 		dp = (void*) (data + 2);
853 
854 		for (i = 0; i < val_len; i++) {
855 			if (dp[i] == '"' || dp[i] == '\\')
856 				buffer_printf(output, "\\%c", dp[i]);
857 
858 			else if (!isprint(dp[i]))
859 				buffer_printf(output, "\\%03u", (unsigned) dp[i]);
860 
861 			else
862 				buffer_write_u8(output, dp[i]);
863 		}
864 		buffer_write_u8(output, '"');
865 		break;
866 	}
867 	return 1;
868 }
869 
870 static int
rdata_unknown_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))871 rdata_unknown_to_string(buffer_type *output, rdata_atom_type rdata,
872 	rr_type* ATTR_UNUSED(rr))
873 {
874  	uint16_t size = rdata_atom_size(rdata);
875  	buffer_printf(output, "\\# %lu ", (unsigned long) size);
876 	hex_to_string(output, rdata_atom_data(rdata), size);
877 	return 1;
878 }
879 
880 static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = {
881 	rdata_dname_to_string,
882 	rdata_dns_name_to_string,
883 	rdata_text_to_string,
884 	rdata_texts_to_string,
885 	rdata_byte_to_string,
886 	rdata_short_to_string,
887 	rdata_long_to_string,
888 	rdata_a_to_string,
889 	rdata_aaaa_to_string,
890 	rdata_rrtype_to_string,
891 	rdata_algorithm_to_string,
892 	rdata_certificate_type_to_string,
893 	rdata_period_to_string,
894 	rdata_time_to_string,
895 	rdata_base64_to_string,
896 	rdata_base32_to_string,
897 	rdata_hex_to_string,
898 	rdata_hexlen_to_string,
899 	rdata_nsap_to_string,
900 	rdata_apl_to_string,
901 	rdata_ipsecgateway_to_string,
902 	rdata_services_to_string,
903 	rdata_nxt_to_string,
904 	rdata_nsec_to_string,
905 	rdata_loc_to_string,
906 	rdata_ilnp64_to_string,
907 	rdata_eui48_to_string,
908 	rdata_eui64_to_string,
909 	rdata_long_text_to_string,
910 	rdata_tag_to_string,
911 	rdata_svcparam_to_string,
912 	rdata_unknown_to_string
913 };
914 
915 int
rdata_atom_to_string(buffer_type * output,rdata_zoneformat_type type,rdata_atom_type rdata,rr_type * record)916 rdata_atom_to_string(buffer_type *output, rdata_zoneformat_type type,
917 		     rdata_atom_type rdata, rr_type* record)
918 {
919 	return rdata_to_string_table[type](output, rdata, record);
920 }
921 
922 ssize_t
rdata_wireformat_to_rdata_atoms(region_type * region,domain_table_type * owners,uint16_t rrtype,uint16_t data_size,buffer_type * packet,rdata_atom_type ** rdatas)923 rdata_wireformat_to_rdata_atoms(region_type *region,
924 				domain_table_type *owners,
925 				uint16_t rrtype,
926 				uint16_t data_size,
927 				buffer_type *packet,
928 				rdata_atom_type **rdatas)
929 {
930 	size_t end = buffer_position(packet) + data_size;
931 	size_t i;
932 	rdata_atom_type temp_rdatas[MAXRDATALEN];
933 	rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype);
934 	region_type *temp_region;
935 
936 	assert(descriptor->maximum <= MAXRDATALEN);
937 
938 	if (!buffer_available(packet, data_size)) {
939 		return -1;
940 	}
941 
942 	temp_region = region_create(xalloc, free);
943 
944 	for (i = 0; i < descriptor->maximum; ++i) {
945 		int is_domain = 0;
946 		int is_normalized = 0;
947 		int is_wirestore = 0;
948 		size_t length = 0;
949 		int required = i < descriptor->minimum;
950 
951 		switch (rdata_atom_wireformat_type(rrtype, i)) {
952 		case RDATA_WF_COMPRESSED_DNAME:
953 		case RDATA_WF_UNCOMPRESSED_DNAME:
954 			is_domain = 1;
955 			is_normalized = 1;
956 			break;
957 		case RDATA_WF_LITERAL_DNAME:
958 			is_domain = 1;
959 			is_wirestore = 1;
960 			break;
961 		case RDATA_WF_BYTE:
962 			length = sizeof(uint8_t);
963 			break;
964 		case RDATA_WF_SHORT:
965 			length = sizeof(uint16_t);
966 			break;
967 		case RDATA_WF_LONG:
968 			length = sizeof(uint32_t);
969 			break;
970 		case RDATA_WF_TEXTS:
971 		case RDATA_WF_LONG_TEXT:
972 			length = end - buffer_position(packet);
973 			break;
974 		case RDATA_WF_TEXT:
975 		case RDATA_WF_BINARYWITHLENGTH:
976 			/* Length is stored in the first byte.  */
977 			length = 1;
978 			if (buffer_position(packet) + length <= end) {
979 				length += buffer_current(packet)[length - 1];
980 			}
981 			break;
982 		case RDATA_WF_A:
983 			length = sizeof(in_addr_t);
984 			break;
985 		case RDATA_WF_AAAA:
986 			length = IP6ADDRLEN;
987 			break;
988 		case RDATA_WF_ILNP64:
989 			length = IP6ADDRLEN/2;
990 			break;
991 		case RDATA_WF_EUI48:
992 			length = EUI48ADDRLEN;
993 			break;
994 		case RDATA_WF_EUI64:
995 			length = EUI64ADDRLEN;
996 			break;
997 		case RDATA_WF_BINARY:
998 			/* Remaining RDATA is binary.  */
999 			length = end - buffer_position(packet);
1000 			break;
1001 		case RDATA_WF_APL:
1002 			length = (sizeof(uint16_t)    /* address family */
1003 				  + sizeof(uint8_t)   /* prefix */
1004 				  + sizeof(uint8_t)); /* length */
1005 			if (buffer_position(packet) + length <= end) {
1006 				/* Mask out negation bit.  */
1007 				length += (buffer_current(packet)[length - 1]
1008 					   & APL_LENGTH_MASK);
1009 			}
1010 			break;
1011 		case RDATA_WF_IPSECGATEWAY:
1012 			assert(i>1); /* we are past the gateway type */
1013 			switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ {
1014 			default:
1015 			case IPSECKEY_NOGATEWAY:
1016 				length = 0;
1017 				break;
1018 			case IPSECKEY_IP4:
1019 				length = IP4ADDRLEN;
1020 				break;
1021 			case IPSECKEY_IP6:
1022 				length = IP6ADDRLEN;
1023 				break;
1024 			case IPSECKEY_DNAME:
1025 				is_domain = 1;
1026 				is_normalized = 1;
1027 				is_wirestore = 1;
1028 				break;
1029 			}
1030 			break;
1031 		case RDATA_WF_SVCPARAM:
1032 			length = 4;
1033 			if (buffer_position(packet) + 4 <= end) {
1034 				length +=
1035 				    read_uint16(buffer_current(packet) + 2);
1036 			}
1037 			break;
1038 		}
1039 
1040 		if (is_domain) {
1041 			const dname_type *dname;
1042 
1043 			if (!required && buffer_position(packet) == end) {
1044 				break;
1045 			}
1046 
1047 			dname = dname_make_from_packet(
1048 				temp_region, packet, 1, is_normalized);
1049 			if (!dname || buffer_position(packet) > end) {
1050 				/* Error in domain name.  */
1051 				region_destroy(temp_region);
1052 				return -1;
1053 			}
1054 			if(is_wirestore) {
1055 				temp_rdatas[i].data = (uint16_t *) region_alloc(
1056                                 	region, sizeof(uint16_t) + ((size_t)dname->name_size));
1057 				temp_rdatas[i].data[0] = dname->name_size;
1058 				memcpy(temp_rdatas[i].data+1, dname_name(dname),
1059 					dname->name_size);
1060 			} else {
1061 				temp_rdatas[i].domain
1062 					= domain_table_insert(owners, dname);
1063 				temp_rdatas[i].domain->usage ++;
1064 			}
1065 		} else {
1066 			if (buffer_position(packet) + length > end) {
1067 				if (required) {
1068 					/* Truncated RDATA.  */
1069 					region_destroy(temp_region);
1070 					return -1;
1071 				} else {
1072 					break;
1073 				}
1074 			}
1075 			if (!required && buffer_position(packet) == end) {
1076 				break;
1077 			}
1078 
1079 			temp_rdatas[i].data = (uint16_t *) region_alloc(
1080 				region, sizeof(uint16_t) + length);
1081 			temp_rdatas[i].data[0] = length;
1082 			buffer_read(packet, temp_rdatas[i].data + 1, length);
1083 		}
1084 	}
1085 
1086 	if (buffer_position(packet) < end) {
1087 		/* Trailing garbage.  */
1088 		region_destroy(temp_region);
1089 		return -1;
1090 	}
1091 
1092 	*rdatas = (rdata_atom_type *) region_alloc_array_init(
1093 		region, temp_rdatas, i, sizeof(rdata_atom_type));
1094 	region_destroy(temp_region);
1095 	return (ssize_t)i;
1096 }
1097 
1098 size_t
rdata_maximum_wireformat_size(rrtype_descriptor_type * descriptor,size_t rdata_count,rdata_atom_type * rdatas)1099 rdata_maximum_wireformat_size(rrtype_descriptor_type *descriptor,
1100 			      size_t rdata_count,
1101 			      rdata_atom_type *rdatas)
1102 {
1103 	size_t result = 0;
1104 	size_t i;
1105 	for (i = 0; i < rdata_count; ++i) {
1106 		if (rdata_atom_is_domain(descriptor->type, i)) {
1107 			result += domain_dname(rdata_atom_domain(rdatas[i]))->name_size;
1108 		} else {
1109 			result += rdata_atom_size(rdatas[i]);
1110 		}
1111 	}
1112 	return result;
1113 }
1114 
1115 int
rdata_atoms_to_unknown_string(buffer_type * output,rrtype_descriptor_type * descriptor,size_t rdata_count,rdata_atom_type * rdatas)1116 rdata_atoms_to_unknown_string(buffer_type *output,
1117 			      rrtype_descriptor_type *descriptor,
1118 			      size_t rdata_count,
1119 			      rdata_atom_type *rdatas)
1120 {
1121 	size_t i;
1122 	size_t size =
1123 		rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas);
1124 	buffer_printf(output, " \\# %lu ", (unsigned long) size);
1125 	for (i = 0; i < rdata_count; ++i) {
1126 		if (rdata_atom_is_domain(descriptor->type, i)) {
1127 			const dname_type *dname =
1128 				domain_dname(rdata_atom_domain(rdatas[i]));
1129 			hex_to_string(
1130 				output, dname_name(dname), dname->name_size);
1131 		} else {
1132 			hex_to_string(output, rdata_atom_data(rdatas[i]),
1133 				rdata_atom_size(rdatas[i]));
1134 		}
1135 	}
1136 	return 1;
1137 }
1138 
1139 int
print_rdata(buffer_type * output,rrtype_descriptor_type * descriptor,rr_type * record)1140 print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor,
1141 	    rr_type *record)
1142 {
1143 	size_t i;
1144 	size_t saved_position = buffer_position(output);
1145 
1146 	for (i = 0; i < record->rdata_count; ++i) {
1147 		if (i == 0) {
1148 			buffer_printf(output, "\t");
1149 		} else if (descriptor->type == TYPE_SOA && i == 2) {
1150 			buffer_printf(output, " (\n\t\t");
1151 		} else {
1152 			buffer_printf(output, " ");
1153 		}
1154 		if (!rdata_atom_to_string(
1155 			    output,
1156 			    (rdata_zoneformat_type) descriptor->zoneformat[i],
1157 			    record->rdatas[i], record))
1158 		{
1159 			buffer_set_position(output, saved_position);
1160 			return 0;
1161 		}
1162 	}
1163 	if (descriptor->type == TYPE_SOA) {
1164 		buffer_printf(output, " )");
1165 	}
1166 
1167 	return 1;
1168 }
1169 
1170