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.  */
28lookup_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.  */
48lookup_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
69const char *svcparamkey_strs[] = {
70		"mandatory", "alpn", "no-default-alpn", "port",
71		"ipv4hint", "ech", "ipv6hint", "dohpath"
72	};
73
74typedef int (*rdata_to_string_type)(buffer_type *output,
75				    rdata_atom_type rdata,
76				    rr_type *rr);
77
78static int
79rdata_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
89static int
90rdata_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
126static int
127rdata_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
150static int
151rdata_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
178static int
179rdata_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
202static int
203rdata_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
218static int
219rdata_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
227static int
228rdata_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
236static int
237rdata_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
245static int
246rdata_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
258static int
259rdata_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
271static int
272rdata_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
285static int
286rdata_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
302static int
303rdata_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
321static int
322rdata_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
330static int
331rdata_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
339static int
340rdata_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
354static int
355rdata_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
363static int
364rdata_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
378static int
379rdata_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
398static int
399rdata_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
418static void
419hex_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
435static int
436rdata_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
448static int
449rdata_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
461static int
462rdata_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
470static int
471rdata_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
510static int
511rdata_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
548static int
549rdata_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
581static int
582rdata_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
600static int
601rdata_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
638static int
639rdata_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
650static void
651buffer_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
659static int
660rdata_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
669static int
670rdata_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
696static int
697rdata_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
723static int
724rdata_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
744static int
745rdata_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
764static int
765rdata_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
801static int
802rdata_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
870static int
871rdata_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
880static 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
915int
916rdata_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
922ssize_t
923rdata_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
1098size_t
1099rdata_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
1115int
1116rdata_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
1139int
1140print_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